Subject: Re: dired-pop-to-buffer in wrong place

From: martin rudalics <[email-masked]>
Date: Fri, 28 Sep 2012 15:14:08 +0200

>>> The problem is that it steals space when the upper window is large
 >> ... I suppose you mean "when the upper window is small" here ...
 >
 > When a window has 30 lines in height, I call it "large" :-)

So splitting a 30 lines window is not enough for getting you enough
space for the Marked Files buffer.  How many lines would you need?

 >> IIUC `fit-window-to-buffer' always tried to display as much as possible
 >> within limits imposed, for example, by `temp-buffer-max-height'.  Can
 >> you tell me when and where it restricted itself to just some area of the
 >> frame?
 >
 > I'll try to provide the exact details:
 >
 > 1. When the Dired window is small (less than 7 lines in height),
 >    there is no problem because it reuses the lower window.

Because `window--try-to-split-window' fails immediately, I presume.

 > 2. When the Dired window is large (more than 7 lines in height)
 >    and a list of marked files is small:
 >
 > 2.1. When `window-combination-limit' is nil,
 >      the result of `dired-mark-pop-up' is horribly ugly
 >      (when `temp-buffer-resize-mode' is enabled).  But thank you
 >      `window-combination-limit' is not nil anymore,
 >      so there is no problem now.

What you probably intend to say between these lines is that users should
not have to enable `temp-buffer-resize-mode' to avoid that horribly ugly
result.

 > 2.2. When `window-combination-limit' is non-nil, the result is still
 >      bad looking because `fit-window-to-buffer' is missing like in the
 >      original version of `dired-pop-to-buffer'.  This is a regression.

This is the part I don't understand.  Suppose with Emacs -Q I do

C-x 2
(setq window-combination-limit t)
(temp-buffer-resize-mode 1)
C-x d

for some directory, mark some files and type D, the space for the
*Deletions* window is taken from the upper window only.

 > 2.3. When a list of files is too large to fit into split windows, it
 >      resizes the lower window.  What I misremembered is that actually it
 >      never tried to avoid resizing the lower window.  Sorry for my amnesia.
 >      This is not a regression.  Its result looks like when
 >      `window-combination-limit' is nil, but since a large list of files
 >      is rarely displayed in Dired, this is a minor problem.

We agree here.

 > So the main problem that remains is the need to use `fit-window-to-buffer'.

I suppose you intend "the need to enable `temp-buffer-resize-mode'"
here.  `fit-window-to-buffer' has been used all the time.

 > I see three possible variants to fix this:
 >
 > 1. Call `fit-window-to-buffer' directly in `dired-mark-pop-up'.

This solves the problem at hand but is no general fix.  In addition we'd
have to maintain things like `dired-shrink-to-fit' forever.

 > 2. Call `fit-window-to-buffer' in `display-buffer-below-selected'
 >    using a new action specifier.

This is still not a complete solution since `fit-window-to-buffer'
should apply whenever we create a new window.

 > 3. Enable `temp-buffer-resize-mode'.

 From your and Chong less than enthusiastic comments this is no good.

I think your idea to pass an appropriate alist entry to `display-buffer'
was best.  I attach a patch which should do that, in principle (actually
I just revived the respective part from my old specifiers approach).

Anyone who wants the nil behavior for `dired-shrink-to-fit' can add a
corresponding entry to `display-buffer-alist' as you proposed earlier.
(Someone would have to formulate that for users nicely and in the
appropriate context.)

The resizing request by `temp-buffer-resize-mode' is still done
explicitly in the corresponding hook but this can be moved to
`display-buffer' in a similar fashion.  Unless we decide that
`temp-buffer-resize-mode' should be removed, that is, moved to
`display-buffer-alist'.

martin
=== modified file 'etc/NEWS'
--- etc/NEWS	2012-09-25 04:13:02 +0000
+++ etc/NEWS	2012-09-28 09:42:19 +0000
@@ -723,14 +723,11 @@
 
 *** New macro `with-temp-buffer-window'.
 
-*** 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'.
+*** New function `fit-frame-to-buffer' and new options
+`fit-frame-to-buffer' and `fit-frame-to-buffer-bottom-margin'.
 
 *** New display action functions `display-buffer-below-selected',
 `display-buffer-at-bottom' and `display-buffer-in-previous-window'.
@@ -745,6 +742,9 @@
 *** New display action alist entry `previous-window', if non-nil,
 specifies window to reuse in `display-buffer-in-previous-window'.
 
+*** New display action alist entries `window-height' and `window-width'
+to specify size of new window created by `display-buffer'.
+
 *** The following variables are obsolete, as they can be replaced by
 appropriate entries in the `display-buffer-alist' function introduced
 in Emacs 24.1:

=== modified file 'lisp/ChangeLog'
--- lisp/ChangeLog	2012-09-25 08:20:05 +0000
+++ lisp/ChangeLog	2012-09-28 09:32:16 +0000
@@ -1,3 +1,32 @@
+2012-09-28  Martin Rudalics  <[email-masked]>
+
+	* window.el (window--display-buffer): New argument ALIST.  Obey
+	window-height and window-width alist entries.
+	(window--try-to-split-window): New argument ALIST.  Bind
+	window-combination-limit to t when the window's size shall be
+	changed and window-combination-limit equals `window-size'.
+	(display-buffer-in-atom-window)
+	(display-buffer-in-major-side-window)
+	(display-buffer-in-side-window, display-buffer-same-window)
+	(display-buffer-reuse-window, display-buffer-pop-up-frame)
+	(display-buffer-pop-up-window, display-buffer-below-selected)
+	(display-buffer-at-bottom, display-buffer-in-previous-window)
+	(display-buffer-use-some-window): Adjust all callers of
+	window--display-buffer and window--try-to-split-window.
+	(fit-frame-to-buffer): New option.
+	(fit-window-to-buffer): Can resize frames if fit-frame-to-buffer
+	is non-nil.
+
+	* help.el (temp-buffer-resize-frames)
+	(temp-buffer-resize-regexps): Remove options.
+	(temp-buffer-resize-mode): Adjust doc-string.
+	(resize-temp-buffer-window): Don't consult
+	temp-buffer-resize-regexps.  Use fit-frame-to-buffer instead of
+	temp-buffer-resize-frames.
+
+	* dired.el (dired-mark-pop-up): Call display-buffer-below-selected
+	with a fit-window-to-buffer alist entry.
+
 2012-09-25  Martin Rudalics  <[email-masked]>
 
 	* window.el (window--resize-child-windows): When resizing child

=== modified file 'lisp/dired.el'
--- lisp/dired.el	2012-09-25 04:13:02 +0000
+++ lisp/dired.el	2012-09-28 09:03:53 +0000
@@ -2997,7 +2997,8 @@
 	(let ((split-height-threshold 0))
 	  (with-temp-buffer-window
 	   buffer
-	   (cons 'display-buffer-below-selected nil)
+	   (cons 'display-buffer-below-selected
+		 '((window-height . fit-window-to-buffer)))
 	   #'(lambda (window _value)
 	       (with-selected-window window
 		 (unwind-protect

=== modified file 'lisp/help.el'
--- lisp/help.el	2012-09-22 12:56:08 +0000
+++ lisp/help.el	2012-09-28 09:03:00 +0000
@@ -981,26 +981,6 @@
   :group 'help
   :version "24.2")
 
-(defcustom temp-buffer-resize-frames nil
-  "Non-nil means `temp-buffer-resize-mode' can resize frames.
-A frame can be resized if and only if its root window is a live
-window.  The height of the root window is subject to the values of
-`temp-buffer-max-height' and `window-min-height'."
-  :type 'boolean
-  :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
@@ -1014,9 +994,8 @@
 
 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.
+resized.  A frame is resized only if `fit-frame-to-buffer' is
+non-nil.
 
 This mode is used by `help', `apropos' and `completion' buffers,
 and some others."
@@ -1034,33 +1013,28 @@
 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.  Do nothing if the name of WINDOW's buffer matches an
-expression in `temp-buffer-resize-regexps'."
+view."
   (setq window (window-normalize-window window t))
   (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)))))))))
+    (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 fit-frame-to-buffer
+	     (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

=== modified file 'lisp/window.el'
--- lisp/window.el	2012-09-25 08:20:05 +0000
+++ lisp/window.el	2012-09-28 09:24:46 +0000
@@ -508,7 +508,7 @@
       (window-make-atom (window-parent window))
       ;; Display BUFFER in NEW and return NEW.
       (window--display-buffer
-       buffer new 'window display-buffer-mark-dedicated))))
+       buffer new 'window alist display-buffer-mark-dedicated))))
 
 (defun window--atom-check-1 (window)
   "Subroutine of `window--atom-check'."
@@ -706,7 +706,7 @@
       ;; does not get resized.
       (set-window-parameter new 'delete-window 'delete-side-window)
       ;; Install BUFFER in new window and return NEW.
-      (window--display-buffer buffer new 'window 'side))))
+      (window--display-buffer buffer new 'window alist 'side))))
 
 (defun delete-side-window (window)
   "Delete side window WINDOW."
@@ -814,7 +814,7 @@
 	;; ALIST (or, better, avoided in the "other" functions).
 	(or (and this-window
 		 ;; Reuse `this-window'.
-		 (window--display-buffer buffer this-window 'reuse 'side))
+		 (window--display-buffer buffer this-window 'reuse alist 'side))
 	    (and (or (not max-slots) (< slots max-slots))
 		 (or (and next-window
 			  ;; Make new window before `next-window'.
@@ -839,13 +839,14 @@
 			     window 'delete-window 'delete-side-window)
 			    window)))
 		   (set-window-parameter window 'window-slot slot)
-		   (window--display-buffer buffer window 'window 'side))
+		   (window--display-buffer buffer window 'window alist 'side))
 	    (and best-window
 		 ;; Reuse `best-window'.
 		 (progn
 		   ;; Give best-window the new slot value.
 		   (set-window-parameter best-window 'window-slot slot)
-		   (window--display-buffer buffer best-window 'reuse 'side)))))))))
+		   (window--display-buffer
+		    buffer best-window 'reuse alist 'side)))))))))
 
 (defun window--side-check (&optional frame)
   "Check the side window configuration of FRAME.
@@ -5077,7 +5078,7 @@
 		 (with-selected-window window
 		   (split-window-below))))))))
 
-(defun window--try-to-split-window (window)
+(defun window--try-to-split-window (window &optional alist)
   "Try to split WINDOW.
 Return value returned by `split-window-preferred-function' if it
 represents a live window, nil otherwise."
@@ -5085,9 +5086,14 @@
 	   (not (frame-parameter (window-frame window) 'unsplittable))
 	   (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)
+		   ;; `display-buffer' or equals `resize-window' and a
+		   ;; `window-height' or `window-width' alist entry are
+		   ;; present, bind it to t so resizing steals space
+		   ;; preferably from the window that was split.
+		   (if (or (eq window-combination-limit 'display-buffer)
+			   (and (eq window-combination-limit 'window-size)
+				(or (cdr (assq 'window-height alist))
+				    (cdr (assq 'window-width alist)))))
 		       t
 		     window-combination-limit))
 		  (new-window
@@ -5144,7 +5150,7 @@
 	 (/ (- (window-total-height window) (window-total-height)) 2))
       (error nil))))
 
-(defun window--display-buffer (buffer window type &optional dedicated)
+(defun window--display-buffer (buffer window type &optional alist dedicated)
   "Display BUFFER in WINDOW and make its frame visible.
 TYPE must be one of the symbols `reuse', `window' or `frame' and
 is passed unaltered to `display-buffer-record-window'. Set
@@ -5159,6 +5165,58 @@
 	(set-window-dedicated-p window dedicated))
       (when (memq type '(window frame))
 	(set-window-prev-buffers window nil)))
+    (let ((parameter (window-parameter window 'quit-restore))
+	  (height (cdr (assq 'window-height alist)))
+	  (width (cdr (assq 'window-width alist))))
+      (when (or (memq type '(window frame))
+		(and (eq (car parameter) 'same)
+		     (memq (nth 1 parameter) '(window frame))))
+	;; Adjust height of new window or frame.
+	(cond
+	 ((not height))
+	 ((numberp height)
+	  (let* ((new-height
+		  (if (integerp height)
+		      height
+		    (round
+		     (* (window-total-size (frame-root-window window))
+			height))))
+		 (delta (- new-height (window-total-size window))))
+	    (cond
+	     ((and (window-resizable-p window delta nil 'safe)
+		   (window-combined-p window))
+	      (window-resize window delta nil 'safe))
+	     ((or (eq type 'frame)
+		  (and (eq (car parameter) 'same)
+		       (eq (nth 1 parameter) 'frame)))
+	      (set-frame-height
+	       (window-frame window)
+	       (+ (frame-height (window-frame window)) delta))))))
+	 ((functionp height)
+	  (ignore-errors (funcall height window))))
+	;; Adjust width of a window or frame.
+	(cond
+	 ((not width))
+	 ((numberp width)
+	  (let* ((new-width
+		  (if (integerp width)
+		      width
+		    (round
+		     (* (window-total-size (frame-root-window window) t)
+			width))))
+		 (delta (- new-width (window-total-size window t))))
+	    (cond
+	     ((and (window-resizable-p window delta t 'safe)
+		   (window-combined-p window t))
+	      (window-resize window delta t 'safe))
+	     ((or (eq type 'frame)
+		  (and (eq (car parameter) 'same)
+		       (eq (nth 1 parameter) 'frame)))
+	      (set-frame-width
+	       (window-frame window)
+	       (+ (frame-width (window-frame window)) delta))))))
+	 ((functionp width)
+	  (ignore-errors (funcall width window))))))
     window))
 
 (defun window--maybe-raise-frame (frame)
@@ -5400,7 +5458,7 @@
   (unless (or (cdr (assq 'inhibit-same-window alist))
 	      (window-minibuffer-p)
 	      (window-dedicated-p))
-    (window--display-buffer buffer (selected-window) 'reuse)))
+    (window--display-buffer buffer (selected-window) 'reuse alist)))
 
 (defun display-buffer--maybe-same-window (buffer alist)
   "Conditionally display BUFFER in the selected window.
@@ -5448,7 +5506,7 @@
 			      (get-buffer-window-list buffer 'nomini
 						      frames))))))
     (when (window-live-p window)
-      (prog1 (window--display-buffer buffer window 'reuse)
+      (prog1 (window--display-buffer buffer window 'reuse alist)
 	(unless (cdr (assq 'inhibit-switch-frame alist))
 	  (window--maybe-raise-frame (window-frame window)))))))
 
@@ -5485,8 +5543,8 @@
     (when (and fun
 	       (setq frame (funcall fun))
 	       (setq window (frame-selected-window frame)))
-      (prog1 (window--display-buffer buffer window
-				     'frame display-buffer-mark-dedicated)
+      (prog1 (window--display-buffer
+	      buffer window 'frame alist display-buffer-mark-dedicated)
 	(unless (cdr (assq 'inhibit-switch-frame alist))
 	  (window--maybe-raise-frame frame))))))
 
@@ -5511,11 +5569,11 @@
 			(not (frame-parameter frame 'unsplittable))))
 	       ;; Attempt to split largest or least recently used window.
 	       (setq window (or (window--try-to-split-window
-				 (get-largest-window frame t))
+				 (get-largest-window frame t) alist)
 				(window--try-to-split-window
-				 (get-lru-window frame t)))))
-      (prog1 (window--display-buffer buffer window
-				     'window display-buffer-mark-dedicated)
+				 (get-lru-window frame t) alist))))
+      (prog1 (window--display-buffer
+	      buffer window 'window alist display-buffer-mark-dedicated)
 	(unless (cdr (assq 'inhibit-switch-frame alist))
 	  (window--maybe-raise-frame (window-frame window)))))))
 
@@ -5534,21 +5592,21 @@
       (and pop-up-windows
 	   (display-buffer-pop-up-window buffer alist))))
 
-(defun display-buffer-below-selected (buffer _alist)
+(defun display-buffer-below-selected (buffer alist)
   "Try displaying BUFFER in a window below the selected window.
 This either splits the selected window or reuses the window below
 the selected one."
   (let (window)
     (or (and (not (frame-parameter nil 'unsplittable))
-	     (setq window (window--try-to-split-window (selected-window)))
+	     (setq window (window--try-to-split-window (selected-window) alist))
 	     (window--display-buffer
-	      buffer window 'window display-buffer-mark-dedicated))
+	      buffer window 'window alist display-buffer-mark-dedicated))
 	(and (setq window (window-in-direction 'below))
 	     (not (window-dedicated-p window))
 	     (window--display-buffer
-	      buffer window 'reuse display-buffer-mark-dedicated)))))
+	      buffer window 'reuse alist display-buffer-mark-dedicated)))))
 
-(defun display-buffer-at-bottom (buffer _alist)
+(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
@@ -5556,20 +5614,20 @@
   (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))
+	     (setq window (window--try-to-split-window bottom-window alist))
 	     (window--display-buffer
-	      buffer window 'window display-buffer-mark-dedicated))
+	      buffer window 'window alist 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))
+	      buffer window 'window alist display-buffer-mark-dedicated))
 	(and (setq window bottom-window)
 	     (not (window-dedicated-p window))
 	     (window--display-buffer
-	      buffer window 'reuse display-buffer-mark-dedicated)))))
+	      buffer window 'reuse alist display-buffer-mark-dedicated)))))
 
 (defun display-buffer-in-previous-window (buffer alist)
   "Display BUFFER in a window previously showing it.
@@ -5625,7 +5683,7 @@
 	(setq best-window window)))
     ;; Return best or second best window found.
     (when (setq window (or best-window second-best-window))
-      (window--display-buffer buffer window 'reuse))))
+      (window--display-buffer buffer window 'reuse alist))))
 
 (defun display-buffer-use-some-window (buffer alist)
   "Display BUFFER in an existing window.
@@ -5653,7 +5711,7 @@
 	      (get-largest-window 0 not-this-window))))
     (when (window-live-p window)
       (prog1
-	  (window--display-buffer buffer window 'reuse)
+	  (window--display-buffer buffer window 'reuse alist)
 	(window--even-window-heights window)
 	(unless (cdr (assq 'inhibit-switch-frame alist))
 	  (window--maybe-raise-frame (window-frame window)))))))
@@ -5923,6 +5981,97 @@
 			     window))))
 
 ;;; Resizing buffers to fit their contents exactly.
+(defcustom fit-frame-to-buffer nil
+  "Non-nil means `fit-window-to-buffer' can resize frames.
+A frame can be resized if and only if its root window is a live
+window.  The height of the root window is subject to the values
+of `fit-frame-to-buffer-max-height' and `window-min-height'."
+  :type 'boolean
+  :version "24.2"
+  :group 'help)
+
+(defcustom fit-frame-to-buffer-bottom-margin 4
+  "Bottom margin for `fit-frame-to-buffer'.
+This is the number of lines `fit-frame-to-buffer' leaves free at the
+bottom of the display in order to not obscure the system task bar."
+  :type 'integer
+  :version "24.2"
+  :group 'windows)
+
+(defun fit-frame-to-buffer (&optional frame max-height min-height)
+  "Adjust height of FRAME to display its buffer's contents exactly.
+FRAME can be any live frame and defaults to the selected one.
+
+Optional argument MAX-HEIGHT specifies the maximum height of
+FRAME and defaults to the height of the display below the current
+top line of FRAME minus FIT-FRAME-TO-BUFFER-BOTTOM-MARGIN.
+Optional argument MIN-HEIGHT specifies the minimum height of
+FRAME."
+  (interactive)
+  (setq frame (window-normalize-frame frame))
+  (let* ((root (frame-root-window frame))
+	 (frame-min-height
+	  (+ (- (frame-height frame) (window-total-size root))
+	     window-min-height))
+	 (frame-top (frame-parameter frame 'top))
+	 (top (if (consp frame-top)
+		  (funcall (car frame-top) (cadr frame-top))
+		frame-top))
+	 (frame-max-height
+	  (- (/ (- (x-display-pixel-height frame) top)
+		(frame-char-height frame))
+	     fit-frame-to-buffer-bottom-margin))
+	 (compensate 0)
+	 delta)
+    (when (and (window-live-p root) (not (window-size-fixed-p root)))
+      (with-selected-window root
+	(cond
+	 ((not max-height)
+	  (setq max-height frame-max-height))
+	 ((numberp max-height)
+	  (setq max-height (min max-height frame-max-height)))
+	 (t
+	  (error "%s is an invalid maximum height" max-height)))
+	(cond
+	 ((not min-height)
+	  (setq min-height frame-min-height))
+	 ((numberp min-height)
+	  (setq min-height (min min-height frame-min-height)))
+	 (t
+	  (error "%s is an invalid minimum height" min-height)))
+	;; When tool-bar-mode is enabled and we have just created a new
+	;; frame, reserve lines for toolbar resizing.  This is needed
+	;; because for reasons unknown to me Emacs (1) reserves one line
+	;; for the toolbar when making the initial frame and toolbars
+	;; are enabled, and (2) later adds the remaining lines needed.
+	;; Our code runs IN BETWEEN (1) and (2).  YMMV when you're on a
+	;; system that behaves differently.
+	(let ((quit-restore (window-parameter root 'quit-restore))
+	      (lines (tool-bar-lines-needed frame)))
+	  (when (and quit-restore (eq (car quit-restore) 'frame)
+		     (not (zerop lines)))
+	    (setq compensate (1- lines))))
+	(message "%s" compensate)
+	(setq delta
+	      ;; Always count a final newline - we don't do any
+	      ;; post-processing, so let's play safe.
+	      (+ (count-screen-lines nil nil t)
+		 (- (window-body-size))
+		 compensate)))
+      ;; Move away from final newline.
+      (when (and (eobp) (bolp) (not (bobp)))
+	(set-window-point root (line-beginning-position 0)))
+      (set-window-start root (point-min))
+      (set-window-vscroll root 0)
+      (condition-case nil
+	  (set-frame-height
+	   frame
+	   (min (max (+ (frame-height frame) delta)
+		     min-height)
+		max-height))
+	(error (setq delta nil))))
+    delta))
+
 (defun fit-window-to-buffer (&optional window max-height min-height)
   "Adjust height of WINDOW to display its buffer's contents exactly.
 WINDOW must be a live window and defaults to the selected one.
@@ -5943,9 +6092,12 @@
 WINDOW was scrolled."
   (interactive)
   (setq window (window-normalize-window window t))
-  ;; Can't resize a full height or fixed-size window.
-  (unless (or (window-size-fixed-p window)
-	      (window-full-height-p window))
+  (cond
+   ((window-size-fixed-p window))
+   ((window-full-height-p window)
+    (when fit-frame-to-buffer
+      (fit-frame-to-buffer (window-frame window))))
+   (t
     (with-selected-window window
       (let* ((height (window-total-size))
 	     (min-height
@@ -5961,7 +6113,7 @@
 		  ;; Can't get larger than height of frame.
 		  (min max-height
 		       (window-total-size (frame-root-window window)))
-		;, Don't delete other windows.
+		;; Don't delete other windows.
 		(+ height (window-max-delta nil nil window))))
 	     ;; Make `desired-height' the height necessary to show
 	     ;; all of WINDOW's buffer, constrained by MIN-HEIGHT
@@ -6024,89 +6176,7 @@
 		  (window-resize window 1 nil window)
 		  (setq desired-height (1+ desired-height)))))
 	  (error (setq delta nil)))
-	delta))))
-
-(defcustom fit-frame-to-buffer-bottom-margin 4
-  "Bottom margin for `fit-frame-to-buffer'.
-This is the number of lines `fit-frame-to-buffer' leaves free at the
-bottom of the display in order to not obscure the system task bar."
-  :type 'integer
-  :version "24.2"
-  :group 'windows)
-
-(defun fit-frame-to-buffer (&optional frame max-height min-height)
-  "Adjust height of FRAME to display its buffer's contents exactly.
-FRAME can be any live frame and defaults to the selected one.
-
-Optional argument MAX-HEIGHT specifies the maximum height of
-FRAME and defaults to the height of the display below the current
-top line of FRAME minus FIT-FRAME-TO-BUFFER-BOTTOM-MARGIN.
-Optional argument MIN-HEIGHT specifies the minimum height of
-FRAME."
-  (interactive)
-  (setq frame (window-normalize-frame frame))
-  (let* ((root (frame-root-window frame))
-	 (frame-min-height
-	  (+ (- (frame-height frame) (window-total-size root))
-	     window-min-height))
-	 (frame-top (frame-parameter frame 'top))
-	 (top (if (consp frame-top)
-		  (funcall (car frame-top) (cadr frame-top))
-		frame-top))
-	 (frame-max-height
-	  (- (/ (- (x-display-pixel-height frame) top)
-		(frame-char-height frame))
-	     fit-frame-to-buffer-bottom-margin))
-	 (compensate 0)
-	 delta)
-    (when (and (window-live-p root) (not (window-size-fixed-p root)))
-      (with-selected-window root
-	(cond
-	 ((not max-height)
-	  (setq max-height frame-max-height))
-	 ((numberp max-height)
-	  (setq max-height (min max-height frame-max-height)))
-	 (t
-	  (error "%s is an invalid maximum height" max-height)))
-	(cond
-	 ((not min-height)
-	  (setq min-height frame-min-height))
-	 ((numberp min-height)
-	  (setq min-height (min min-height frame-min-height)))
-	 (t
-	  (error "%s is an invalid minimum height" min-height)))
-	;; When tool-bar-mode is enabled and we have just created a new
-	;; frame, reserve lines for toolbar resizing.  This is needed
-	;; because for reasons unknown to me Emacs (1) reserves one line
-	;; for the toolbar when making the initial frame and toolbars
-	;; are enabled, and (2) later adds the remaining lines needed.
-	;; Our code runs IN BETWEEN (1) and (2).  YMMV when you're on a
-	;; system that behaves differently.
-	(let ((quit-restore (window-parameter root 'quit-restore))
-	      (lines (tool-bar-lines-needed frame)))
-	  (when (and quit-restore (eq (car quit-restore) 'frame)
-		     (not (zerop lines)))
-	    (setq compensate (1- lines))))
-	(message "%s" compensate)
-	(setq delta
-	      ;; Always count a final newline - we don't do any
-	      ;; post-processing, so let's play safe.
-	      (+ (count-screen-lines nil nil t)
-		 (- (window-body-size))
-		 compensate)))
-      ;; Move away from final newline.
-      (when (and (eobp) (bolp) (not (bobp)))
-	(set-window-point root (line-beginning-position 0)))
-      (set-window-start root (point-min))
-      (set-window-vscroll root 0)
-      (condition-case nil
-	  (set-frame-height
-	   frame
-	   (min (max (+ (frame-height frame) delta)
-		     min-height)
-		max-height))
-	(error (setq delta nil))))
-    delta))
+	delta)))))
 
 (defun window-safely-shrinkable-p (&optional window)
   "Return t if WINDOW can be shrunk without shrinking other windows.

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2012-09-25 07:01:52 +0000
+++ src/ChangeLog	2012-09-28 09:10:58 +0000
@@ -1,3 +1,8 @@
+2012-09-28  Martin Rudalics  <[email-masked]>
+
+	* window.c (Vwindow_combination_limit): New default value.
+	(Qwindow_size): New symbol replacing Qtemp_buffer_resize.
+
 2012-09-25  Eli Zaretskii  <[email-masked]>
 
 	* character.c (char_string, string_char): Remove calls to

=== modified file 'src/window.c'
--- src/window.c	2012-09-23 08:44:20 +0000
+++ src/window.c	2012-09-28 08:57:02 +0000
@@ -60,7 +60,7 @@
 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, Qtemp_buffer_resize, Qclone_of;
+static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
 
 static int displayed_window_lines (struct window *);
 static int count_windows (struct window *);
@@ -6704,7 +6704,7 @@
   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 (Qwindow_size, "window-size");
   DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
   DEFSYM (Qabove, "above");
   DEFSYM (Qbelow, "below");
@@ -6807,16 +6807,16 @@
     window has no parent window or the window shall become a combination
     orthogonal to the one it is part of.
 
-`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.
+`window-size' means that splitting a window for displaying a buffer
+    makes a new parent window provided `display-buffer' is supposed to
+    explicitly the window's size due to the presence of a
+    `window-height' or `window-width' entry in the alist used by
+    `display-buffer'.  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
@@ -6829,7 +6829,7 @@
     sibling.
 
 Other values are reserved for future use.  */);
-  Vwindow_combination_limit = Qtemp_buffer_resize;
+  Vwindow_combination_limit = Qwindow_size;
 
   DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
 	       doc: /* Alist of persistent window parameters.