From 8e17c9ba1443c2f21c5801f0c4660ac08dccc837 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Sat, 22 Sep 2012 14:56:08 +0200 Subject: [PATCH] Make Temp Buffer Resize Mode less intrusive (Bug#1806). * window.c (Fsplit_window_internal): Handle only Qt value of Vwindow_combination_limit separately. (Qtemp_buffer_resize): New symbol. (Vwindow_combination_limit): New default value. Rewrite doc-string. * cus-start.el (window-combination-limit): Add new optional values. * window.el (temp-buffer-window-show) (window--try-to-split-window): Obey new values of window-combination-limit. (split-window): Test window-combination-limit for t instead of non-nil. (display-buffer-at-bottom): New buffer display action function. * help.el (temp-buffer-resize-regexps): New option. (temp-buffer-resize-mode): Rewrite doc-string. (resize-temp-buffer-window): Obey temp-buffer-resize-regexps. Don't resize reused window. Suggested by Glen Morris. --- etc/NEWS | 14 +++++++--- lisp/ChangeLog | 15 +++++++++++ lisp/cus-start.el | 12 ++++++++- lisp/help.el | 63 ++++++++++++++++++++++++++++++--------------- lisp/window.el | 65 ++++++++++++++++++++++++++++++++++++++--------- src/ChangeLog | 8 ++++++ src/window.c | 63 +++++++++++++++++++++++++++------------------ 7 files changed, 178 insertions(+), 62 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index ccd8a6fe35b..30648a5961a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -719,15 +719,21 @@ recursive invocations. *** The functions get-lru-window, get-mru-window and get-largest-window now accept a third argument to avoid choosing the selected window. +*** Additional values recognized for option `window-combination-limit'. + *** New macro `with-temp-buffer-window'. -*** New option `temp-buffer-resize-frames'. +*** New options `temp-buffer-resize-frames' and +`temp-buffer-resize-regexps'. + +*** `temp-buffer-resize-mode' no longer resizes windows that have been +reused. *** New function `fit-frame-to-buffer' and new option - `fit-frame-to-buffer-bottom-margin'. +`fit-frame-to-buffer-bottom-margin'. -*** New display action functions `display-buffer-below-selected' and -`display-buffer-in-previous-window'. +*** New display action functions `display-buffer-below-selected', +`display-buffer-at-bottom' and `display-buffer-in-previous-window'. *** New display action alist entry `inhibit-switch-frame', if non-nil, tells display action functions to avoid changing which frame is diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7f9044e4f36..f18bfd73611 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,18 @@ +2012-09-22 Martin Rudalics + + * cus-start.el (window-combination-limit): Add new optional + values. + * window.el (temp-buffer-window-show) + (window--try-to-split-window): Handle new values of + window-combination-limit (Bug#1806). + (split-window): Test window-combination-limit for t instead of + non-nil. + (display-buffer-at-bottom): New buffer display action function. + * help.el (temp-buffer-resize-regexps): New option. + (temp-buffer-resize-mode): Rewrite doc-string. + (resize-temp-buffer-window): Obey temp-buffer-resize-regexps. + Don't resize reused window. Suggested by Glen Morris. + 2012-09-22 Stefan Merten * rst.el: Revamp section title faces. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 0eb8b2d63c3..a91a479b054 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -422,7 +422,17 @@ since it could result in memory overflow and make Emacs crash." (const :tag "Only on ttys" :value tty) (other :tag "Always" t)) "23.1") (window-combination-resize windows boolean "24.1") - (window-combination-limit windows boolean "24.1") + (window-combination-limit + windows (choice + (const :tag "Never (nil)" :value nil) + (const :tag "For Temp Buffer Resize mode (temp-buffer-resize)" + :value temp-buffer-resize) + (const :tag "For temporary buffers (temp-buffer)" + :value temp-buffer) + (const :tag "For buffer display (display-buffer)" + :value display-buffer) + (other :tag "Always (t)" :value t)) + "24.3") ;; xdisp.c (show-trailing-whitespace whitespace-faces boolean nil :safe booleanp) diff --git a/lisp/help.el b/lisp/help.el index da11389d87c..707c8e3c84f 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -990,6 +990,17 @@ window. The height of the root window is subject to the values of :version "24.2" :group 'help) +(defcustom temp-buffer-resize-regexps nil + "List of regexps that inhibit Temp Buffer Resize mode. +Any window of a buffer whose name matches one of these regular +expressions is left alone by Temp Buffer Resize mode." + :type '(repeat + :tag "Buffer" + :value "" + (regexp :format "%v")) + :version "24.3" + :group 'help) + (define-minor-mode temp-buffer-resize-mode "Toggle auto-resizing temporary buffer windows (Temp Buffer Resize Mode). With a prefix argument ARG, enable Temp Buffer Resize mode if ARG @@ -1001,6 +1012,12 @@ show a temporary buffer are automatically resized in height to fit the buffer's contents, but never more than `temp-buffer-max-height' nor less than `window-min-height'. +A window is resized only if it has been specially created for the +buffer. Windows that have shown another buffer before are not +resized. A window showing a buffer whose name matches any of the +expressions in `temp-buffer-resize-regexps' is not resized. A +frame is resized only if `temp-buffer-resize-frames' is non-nil. + This mode is used by `help', `apropos' and `completion' buffers, and some others." :global t :group 'help @@ -1017,27 +1034,33 @@ WINDOW can be any live window and defaults to the selected one. Do not make WINDOW higher than `temp-buffer-max-height' nor smaller than `window-min-height'. Do nothing if WINDOW is not vertically combined or some of its contents are scrolled out of -view." +view. Do nothing if the name of WINDOW's buffer matches an +expression in `temp-buffer-resize-regexps'." (setq window (window-normalize-window window t)) - (let ((height (if (functionp temp-buffer-max-height) - (with-selected-window window - (funcall temp-buffer-max-height (window-buffer))) - temp-buffer-max-height))) - (cond - ((and (pos-visible-in-window-p (point-min) window) - (window-combined-p window)) - (fit-window-to-buffer window height)) - ((and temp-buffer-resize-frames - (eq window (frame-root-window window)) - (memq (car (window-parameter window 'quit-restore)) - ;; If 'same is too strong, we might additionally check - ;; whether the second element is 'frame. - '(same frame))) - (let ((frame (window-frame window))) - (fit-frame-to-buffer - frame (+ (frame-height frame) - (- (window-total-size window)) - height))))))) + (let ((buffer-name (buffer-name (window-buffer window)))) + (unless (catch 'found + (dolist (regexp temp-buffer-resize-regexps) + (when (string-match regexp buffer-name) + (throw 'found t)))) + (let ((height (if (functionp temp-buffer-max-height) + (with-selected-window window + (funcall temp-buffer-max-height (window-buffer))) + temp-buffer-max-height)) + (quit-cadr (cadr (window-parameter window 'quit-restore)))) + (cond + ;; Don't resize WINDOW if it showed another buffer before. + ((and (eq quit-cadr 'window) + (pos-visible-in-window-p (point-min) window) + (window-combined-p window)) + (fit-window-to-buffer window height)) + ((and temp-buffer-resize-frames + (eq quit-cadr 'frame) + (eq window (frame-root-window window))) + (let ((frame (window-frame window))) + (fit-frame-to-buffer + frame (+ (frame-height frame) + (- (window-total-size window)) + height))))))))) ;;; Help windows. (defcustom help-window-select 'other diff --git a/lisp/window.el b/lisp/window.el index fccb68bd94a..87817fb8773 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -111,7 +111,19 @@ to `display-buffer'." (set-buffer-modified-p nil) (setq buffer-read-only t) (goto-char (point-min)) - (when (setq window (display-buffer buffer action)) + (when (let ((window-combination-limit + ;; When `window-combination-limit' equals + ;; `temp-buffer' or `temp-buffer-resize' and + ;; `temp-buffer-resize-mode' is enabled in this + ;; buffer bind it to t so resizing steals space + ;; preferably from the window that was split. + (if (or (eq window-combination-limit 'temp-buffer) + (and (eq window-combination-limit + 'temp-buffer-resize) + temp-buffer-resize-mode)) + t + window-combination-limit))) + (setq window (display-buffer buffer action))) (setq frame (window-frame window)) (unless (eq frame (selected-frame)) (raise-frame frame)) @@ -3678,9 +3690,8 @@ frame. The selected window is not changed by this function." (parent (window-parent window)) (function (window-parameter window 'split-window)) (window-side (window-parameter window 'window-side)) - ;; Rebind `window-combination-limit' and - ;; `window-combination-resize' since in some cases we may have - ;; to override their value. + ;; Rebind the following two variables since in some cases we + ;; have to override their value. (window-combination-limit window-combination-limit) (window-combination-resize window-combination-resize) atom-root) @@ -3738,7 +3749,7 @@ frame. The selected window is not changed by this function." (and window-combination-resize (or (window-parameter window 'window-side) (not (eq window-combination-resize 'side))) - (not window-combination-limit) + (not (eq window-combination-limit t)) ;; Resize makes sense in iso-combinations only. (window-combined-p window horizontal))) ;; `old-size' is the current size of WINDOW. @@ -3818,7 +3829,7 @@ frame. The selected window is not changed by this function." ;; Make new-parent non-nil if we need a new parent window; ;; either because we want to nest or because WINDOW is not ;; iso-combined. - (or window-combination-limit + (or (eq window-combination-limit t) (not (window-combined-p window horizontal)))) (setq new-normal ;; Make new-normal the normal size of the new window. @@ -5066,12 +5077,19 @@ Return value returned by `split-window-preferred-function' if it represents a live window, nil otherwise." (and (window-live-p window) (not (frame-parameter (window-frame window) 'unsplittable)) - (let ((new-window - ;; Since `split-window-preferred-function' might - ;; throw an error use `condition-case'. - (condition-case nil - (funcall split-window-preferred-function window) - (error nil)))) + (let* ((window-combination-limit + ;; When `window-combination-limit' equals + ;; `display-buffer' bind it to t so resizing steals + ;; space preferably from the window that was split. + (if (eq window-combination-limit 'display-buffer) + t + window-combination-limit)) + (new-window + ;; Since `split-window-preferred-function' might + ;; throw an error use `condition-case'. + (condition-case nil + (funcall split-window-preferred-function window) + (error nil)))) (and (window-live-p new-window) new-window)))) (defun window--frame-usable-p (frame) @@ -5524,6 +5542,29 @@ the selected one." (window--display-buffer buffer window 'reuse display-buffer-mark-dedicated))))) +(defun display-buffer-at-bottom (buffer _alist) + "Try displaying BUFFER in a window at the botom of the selected frame. +This either splits the window at the bottom of the frame or the +frame's root window, or reuses an existing window at the bottom +of the selected frame." + (let (bottom-window window) + (walk-window-tree (lambda (window) (setq bottom-window window))) + (or (and (not (frame-parameter nil 'unsplittable)) + (setq window (window--try-to-split-window bottom-window)) + (window--display-buffer + buffer window 'window display-buffer-mark-dedicated)) + (and (not (frame-parameter nil 'unsplittable)) + (setq window + (condition-case nil + (split-window (frame-root-window)) + (error nil))) + (window--display-buffer + buffer window 'window display-buffer-mark-dedicated)) + (and (setq window bottom-window) + (not (window-dedicated-p window)) + (window--display-buffer + buffer window 'reuse display-buffer-mark-dedicated))))) + (defun display-buffer-in-previous-window (buffer alist) "Display BUFFER in a window previously showing it. If ALIST has a non-nil `inhibit-same-window' entry, the selected diff --git a/src/ChangeLog b/src/ChangeLog index 4033f51ca1a..6ea40b3f122 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2012-09-22 Martin Rudalics + + * window.c (Fsplit_window_internal): Handle only Qt value of + Vwindow_combination_limit separately. + (Qtemp_buffer_resize): New symbol. + (Vwindow_combination_limit): New default value. Rewrite + doc-string. + 2012-09-22 Eli Zaretskii * xdisp.c (next_overlay_string): Initialize it->end_charpos for diff --git a/src/window.c b/src/window.c index a6f1104587e..6798be8231c 100644 --- a/src/window.c +++ b/src/window.c @@ -60,8 +60,7 @@ static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer; static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window; static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically; static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command; -static Lisp_Object Qsafe, Qabove, Qbelow; -static Lisp_Object Qclone_of; +static Lisp_Object Qsafe, Qabove, Qbelow, Qtemp_buffer_resize, Qclone_of; static int displayed_window_lines (struct window *); static int count_windows (struct window *); @@ -613,10 +612,10 @@ WINDOW are never \(re-)combined with WINDOW's siblings. */) DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0, doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT. WINDOW must be a valid window and defaults to the selected one. -If LIMIT is nil, child windows of WINDOW can be recombined with -WINDOW's siblings. LIMIT t means that child windows of WINDOW are -never \(re-)combined with WINDOW's siblings. Other values are reserved -for future use. */) +If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's +siblings. LIMIT t means that child windows of WINDOW are never +\(re-)combined with WINDOW's siblings. Other values are reserved for +future use. */) (Lisp_Object window, Lisp_Object limit) { wset_combination_limit (decode_valid_window (window), limit); @@ -3466,7 +3465,7 @@ make_window (void) allocate_window. */ wset_prev_buffers (w, Qnil); wset_next_buffers (w, Qnil); - + /* Initialize non-Lisp data. Note that allocate_window zeroes out all non-Lisp data, so do it only for slots which should not be zero. */ w->nrows_scale_factor = w->ncols_scale_factor = 1; @@ -3848,7 +3847,7 @@ set correctly. See the code of `split-window' for how this is done. */) We do that if either `window-combination-limit' is t, or OLD has no parent, or OLD is ortho-combined. */ combination_limit = - !NILP (Vwindow_combination_limit) + EQ (Vwindow_combination_limit, Qt) || NILP (o->parent) || NILP (horflag ? (XWINDOW (o->parent)->hchild) @@ -3903,9 +3902,9 @@ set correctly. See the code of `split-window' for how this is done. */) make_parent_window (old, horflag); p = XWINDOW (o->parent); - /* Store value of `window-combination-limit' in new parent's - combination_limit slot. */ - wset_combination_limit (p, Vwindow_combination_limit); + /* Store t in the new parent's combination_limit slot to avoid + that its children get merged into another window. */ + wset_combination_limit (p, Qt); /* These get applied below. */ wset_new_total (p, horflag ? o->total_cols : o->total_lines); wset_new_normal (p, new_normal); @@ -6705,6 +6704,7 @@ syms_of_window (void) DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows"); DEFSYM (Qrecord_window_buffer, "record-window-buffer"); DEFSYM (Qget_mru_window, "get-mru-window"); + DEFSYM (Qtemp_buffer_resize, "temp-buffer-resize"); DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook"); DEFSYM (Qabove, "above"); DEFSYM (Qbelow, "below"); @@ -6800,23 +6800,36 @@ This variable takes no effect if `window-combination-limit' is non-nil. */); Vwindow_combination_resize = Qnil; DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit, - doc: /* If t, splitting a window makes a new parent window. -If this variable is nil, splitting a window will create a new parent -window only if the window has no parent window or the window shall -become a combination orthogonal to the one it is part of. + doc: /* If non-nil, splitting a window makes a new parent window. +The following values are recognized: -If this variable is t, splitting a window always creates a new parent -window. If all splits behave this way, each frame's window tree is a -binary tree and every window but the frame's root window has exactly one -sibling. +nil means splitting a window will create a new parent window only if the + window has no parent window or the window shall become a combination + orthogonal to the one it is part of. -Other values are reserved for future use. +`temp-buffer-resize' means that splitting a window for displaying a + temporary buffer makes a new parent window provided + `temp-buffer-resize-mode' is enabled. Otherwise, this value is + handled like nil. + +`temp-buffer' means that splitting a window for displaying a temporary + buffer always makes a new parent window. Otherwise, this value is + handled like nil. + + +`display-buffer' means that splitting a window for displaying a buffer + always makes a new parent window. Since temporary buffers are + displayed by the function `display-buffer', this value is stronger + than `temp-buffer'. Splitting a window for other purpose makes a + new parent window only if needed. + +t means that splitting a window always creates a new parent window. If + all splits behave this way, each frame's window tree is a binary + tree and every window but the frame's root window has exactly one + sibling. -The value of this variable is also assigned to the combination limit of -the new parent window. The combination limit of a window can be -retrieved via the function `window-combination-limit' and altered by the -function `set-window-combination-limit'. */); - Vwindow_combination_limit = Qnil; +Other values are reserved for future use. */); + Vwindow_combination_limit = Qtemp_buffer_resize; DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters, doc: /* Alist of persistent window parameters. -- 2.39.2