From 9817e1919d7fc19194c63e87ddafe1e3e04cb538 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Mon, 29 Apr 2024 11:03:33 +0100 Subject: [PATCH] dot/emacs, el/dot-emacs.el: Another `display-window' hack: fallback. Allow a window in each frame to be declared as the `victim' for random pop-up buffers, overriding the usual policy. --- dot/emacs | 1 + el/dot-emacs.el | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/dot/emacs b/dot/emacs index 5588a43..8749882 100644 --- a/dot/emacs +++ b/dot/emacs @@ -779,6 +779,7 @@ (global-set-key [?\C-c ?w ?b] 'w3m-bookmark-view) (global-set-key [?\C-c ?w ?c] 'mdw-set-frame-colour) (global-set-key [?\C-c ?w ?d] 'mdw-divvy-window) + (global-set-key [?\C-c ?w ?f] 'mdw-set-fallback-window) (global-set-key [?\C-c ?w ?h] 'windmove-left) (global-set-key [?\C-c ?w ?j] 'windmove-down) (global-set-key [?\C-c ?w ?k] 'windmove-up) diff --git a/el/dot-emacs.el b/el/dot-emacs.el index 6cad98c..01d3ac5 100644 --- a/el/dot-emacs.el +++ b/el/dot-emacs.el @@ -772,6 +772,45 @@ Pretend they don't exist. They might be on other display devices." even-window-heights nil display-buffer-reuse-frames nil) +(defvar mdw-fallback-window-alist nil + "Alist mapping frames to fallback windows.") + +(defun mdw-cleanup-fallback-window-alist () + "Remove entries for dead frames and windows from the fallback alist." + (let ((prev nil) + (cursor mdw-fallback-window-alist)) + (while cursor + (let* ((assoc (car cursor)) + (tail (cdr cursor))) + (cond ((and (frame-live-p (car assoc)) + (window-live-p (cdr assoc))) + (setq prev cursor)) + ((null prev) + (setq mdw-fallback-window-alist tail)) + (t + (setcdr prev tail))) + (setq cursor tail))))) + +(defun mdw-set-fallback-window (cancel) + "Prefer the selected window for pop-up buffers in this frame. +With a prefix argument, clear the fallback window." + (interactive "P") + (let* ((frame (selected-frame)) (window (selected-window)) + (assoc (assq (selected-frame) mdw-fallback-window-alist))) + (cond (cancel + (cond (assoc + (setcdr assoc nil) + (message "Fallback window cleared.")) + (t + (message "No fallback window active in this frame.")))) + ((window-dedicated-p window) + (error "Window is dedicated to its buffer.")) + (t + (if assoc (setcdr assoc window) + (push (cons frame window) mdw-fallback-window-alist)) + (message "Fallback window set."))) + (mdw-cleanup-fallback-window-alist))) + (defun mdw-last-window-in-frame-p (window) "Return whether WINDOW is the last in its frame." (catch 'done @@ -790,10 +829,17 @@ Begone, foul DWIMmerlaik! This is all totally subject to arbitrary change in the future, but the emphasis is on predictability rather than crazy DWIMmery." (let* ((selected (selected-window)) chosen + (fallback (assq (selected-frame) mdw-fallback-window-alist)) (full-height-p (window-full-height-p selected)) (full-width-p (window-full-width-p selected))) (cond + ((and fallback (window-live-p (cdr fallback))) + ;; There's a fallback window set for this frame. Use it. + + (setq chosen (cdr fallback)) + (display-buffer-record-window 'window chosen buffer)) + ((and full-height-p full-width-p) ;; We're basically the only window in the frame. If we want to get ;; anywhere, we'll have to split the window. -- 2.11.0