all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: martin rudalics <rudalics@gmx.at>
To: emacs-devel <emacs-devel@gnu.org>
Subject: Side Windows
Date: Thu, 22 Sep 2016 11:07:24 +0200	[thread overview]
Message-ID: <57E39F4C.7010208@gmx.at> (raw)

[-- Attachment #1: Type: text/plain, Size: 148 bytes --]

The attached patch fixes some longstanding bugs/issues with side windows
and provides the lacking documentation.  Comments welcome.

Thanks, martin

[-- Attachment #2: side-windows.diff --]
[-- Type: text/plain, Size: 55668 bytes --]

--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -1038,6 +1038,7 @@ Top
                               a specific window.
 * Quitting Windows::        How to restore the state prior to displaying a
                               buffer.
+* Side Windows::            Special windows on a frame's sides.
 * Window Point::            Each window has its own location of point.
 * Window Start and End::    Buffer positions indicating which text is
                               on-screen in a window.
@@ -1051,6 +1052,14 @@ Top
                               redisplay going past a certain point,
                               or window configuration changes.

+Side Windows
+
+* Displaying Buffers in Side Windows:: An action function for displaying
+                              buffers in side windows.
+* Side Window Options and Functions:: Further tuning of side windows.
+* Frame Layouts with Side Windows:: Setting up frame layouts with side
+                              windows.
+
 Frames

 * Creating Frames::         Creating additional frames.
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 3c9df0b..c326b7c 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -33,6 +33,7 @@ Windows
                               a specific window.
 * Quitting Windows::        How to restore the state prior to displaying a
                               buffer.
+* Side Windows::            Special windows on a frame's sides.
 * Window Point::            Each window has its own location of point.
 * Window Start and End::    Buffer positions indicating which text is
                               on-screen in a window.
@@ -1275,9 +1276,12 @@ Deleting Windows
 @deffn Command delete-window &optional window
 This function removes @var{window} from display and returns
 @code{nil}.  If @var{window} is omitted or @code{nil}, it defaults to
-the selected window.  If deleting the window would leave no more
-windows in the window tree (e.g., if it is the only live window in the
-frame), an error is signaled.
+the selected window.
+
+If deleting the window would leave no more windows in the window tree
+(e.g., if it is the only live window in the frame) or all remaining
+windows on @var{window}'s frame are side windows (@pxref{Side Windows}),
+an error is signaled.

 By default, the space taken up by @var{window} is given to one of its
 adjacent sibling windows, if any.  However, if the variable
@@ -1285,33 +1289,34 @@ Deleting Windows
 proportionally distributed among any remaining windows in the same
 window combination.  @xref{Recombining Windows}.

-The behavior of this function may be altered by the window parameters
-of @var{window}, so long as the variable
-@code{ignore-window-parameters} is @code{nil}.  If the value of
-the @code{delete-window} window parameter is @code{t}, this function
-ignores all other window parameters.  Otherwise, if the value of the
-@code{delete-window} window parameter is a function, that function is
-called with the argument @var{window}, in lieu of the usual action of
-@code{delete-window}.  Otherwise, this function obeys the
-@code{window-atom} or @code{window-side} window parameter, if any.
-@xref{Window Parameters}.
+The behavior of this function may be altered by the window parameters of
+@var{window}, so long as the variable @code{ignore-window-parameters} is
+@code{nil}.  If the value of the @code{delete-window} window parameter
+is @code{t}, this function ignores all other window parameters.
+Otherwise, if the value of the @code{delete-window} window parameter is
+a function, that function is called with the argument @var{window}, in
+lieu of the usual action of @code{delete-window}.  @xref{Window
+Parameters}.
 @end deffn

 @deffn Command delete-other-windows &optional window
-This function makes @var{window} fill its frame, by deleting other
-windows as necessary.  If @var{window} is omitted or @code{nil}, it
-defaults to the selected window.  The return value is @code{nil}.
-
-The behavior of this function may be altered by the window parameters
-of @var{window}, so long as the variable
-@code{ignore-window-parameters} is @code{nil}.  If the value of
-the @code{delete-other-windows} window parameter is @code{t}, this
-function ignores all other window parameters.  Otherwise, if the value
-of the @code{delete-other-windows} window parameter is a function,
-that function is called with the argument @var{window}, in lieu of the
-usual action of @code{delete-other-windows}.  Otherwise, this function
-obeys the @code{window-atom} or @code{window-side} window parameter,
-if any.  @xref{Window Parameters}.
+This function makes @var{window} fill its frame, deleting other windows
+as necessary.  If @var{window} is omitted or @code{nil}, it defaults to
+the selected window.  An error is signaled if @var{window} is a side
+window (@pxref{Side Windows}).  The return value is @code{nil}.
+
+The behavior of this function may be altered by the window parameters of
+@var{window}, so long as the variable @code{ignore-window-parameters} is
+@code{nil}.  If the value of the @code{delete-other-windows} window
+parameter is @code{t}, this function ignores all other window
+parameters.  Otherwise, if the value of the @code{delete-other-windows}
+window parameter is a function, that function is called with the
+argument @var{window}, in lieu of the usual action of
+@code{delete-other-windows}.  @xref{Window Parameters}.
+
+Also, if @code{ignore-window-parameters} is @code{nil}, this function
+does not delete any window whose @code{no-delete-other-window} parameter
+is non-@code{nil}.
 @end deffn

 @deffn Command delete-windows-on &optional buffer-or-name frame
@@ -2574,7 +2579,12 @@ Display Action Functions
 from @code{display-buffer} in this case.
 @end defun

-To illustrate the use of action functions, consider the following
+If the @var{alist} argument of any of these functions contains a
+@code{window-parameters} entry, @code{display-buffer} assigns the
+elements of the associated value as window parameters of the chosen
+window.
+
+   To illustrate the use of action functions, consider the following
 example.

 @example
@@ -3068,6 +3078,278 @@ Quitting Windows
 @end defopt


+@node Side Windows
+@section Side Windows
+@cindex side windows
+@cindex main window
+@cindex main window of a frame
+
+Side windows are special windows positioned at any of the four sides of
+a frame's root window (@pxref{Windows and Frames}).  In practice, this
+means that the area of the frame's root window is subdivided into a main
+window and a number of side windows surrounding that main window.  The
+main window is either a ``normal'' live window or specifies the area
+containing all the normal windows.
+
+   In their most simple form of use, side windows allow to display
+specific buffers always in the same area of a frame.  Hence they can be
+regarded as a generalization of the concept provided by
+@code{display-buffer-at-bottom} (@pxref{Display Action Functions}) to
+the remaining sides of a frame.  With suitable customizations, however,
+side windows can be also used to provide frame layouts similar to those
+found in so-called integrated development environments (IDEs).
+
+@menu
+* Displaying Buffers in Side Windows:: An action function for displaying
+                              buffers in side windows.
+* Side Window Options and Functions:: Further tuning of side windows.
+* Frame Layouts with Side Windows:: Setting up frame layouts with side
+                              windows.
+@end menu
+
+
+@node Displaying Buffers in Side Windows
+@subsection Displaying Buffers in Side Windows
+
+The following action function for @code{display-buffer} (@pxref{Display
+Action Functions}) creates or reuses a side window for displaying the
+specified buffer.
+
+@defun display-buffer-in-side-window buffer alist
+This function displays @var{buffer} in a side window of the selected
+frame.  @var{alist} is an association list of symbols and values as for
+@code{display-buffer}.  The following symbols in @var{alist} are special
+for this function:
+
+@table @code
+@item side
+Denotes the side of the frame where the window shall be located.  Valid
+values are @code{left}, @code{top}, @code{right} and @code{bottom}.  If
+unspecified, the window is located at the bottom of the frame.
+
+@item slot
+Denotes a slot at the specified side where to locate the window.  A
+value of zero means to preferably position the window in the middle of
+the specified side.  A negative value means to use a slot preceding
+(that is, above or on the left of) the middle slot.  A positive value
+means to use a slot following (that is, below or on the right of) the
+middle slot.  Hence, all windows on a specific side are ordered by their
+@code{slot} value.  If unspecified, the window is located in the middle
+of the specified side.
+@end table
+
+If you specify the same slot on the same side for two or more different
+buffers, the buffer displayed last is shown in the corresponding window.
+Hence, slots can be used for sharing the same side window between
+buffers.
+
+This function installs the @code{window-side} and @code{window-slot}
+parameters (@pxref{Window Parameters}) and makes them persistent.  It
+does not install any other window parameters unless they have been
+explicitly provided via a @code{window-parameters} entry in @var{alist}.
+@end defun
+
+By default, side windows cannot be split via @code{split-window}
+(@pxref{Splitting Windows}).  Also, a side window is not reused or split
+by any buffer display action (@pxref{Display Action Functions}) unless
+it is explicitly specified as target of that action.  Note also that
+@code{delete-other-windows} cannot make a side window the only window on
+its frame (@pxref{Deleting Windows}).
+
+   Once set up, side windows also change the behavior of the commands
+@code{switch-to-prev-buffer} and @code{switch-to-next-buffer}
+(@pxref{Window History}).  In particular, these commands will refrain
+from showing, in a side window, buffers that have not been displayed in
+that window before.  And, they will refrain from having a normal,
+non-side window show a buffer that has been already displayed in a side
+window.  A notable exception to the latter rule occurs when an
+application, after displaying a buffer, resets that buffer's local
+variables.
+
+
+@node Side Window Options and Functions
+@subsection Side Window Options and Functions
+
+The following two options provide additional control over the
+placement of side windows.
+
+@defopt window-sides-vertical
+If non-@code{nil}, this means that the side windows on the left and
+right of a frame occupy the frame's full height.  Otherwise, the side
+windows on the top and bottom of the frame occupy the frame's full
+width.  Note that changing the value of this variable does not affect
+the layout of frames already displaying side windows on at least two
+orthogonal sides.
+@end defopt
+
+@defopt window-sides-slots
+This option specifies the maximum number of side windows on each side of
+a frame.  The value is a list of four elements specifying the number of
+side window slots on (in this order) the left, top, right and bottom of
+each frame.  If an element is a number, this means to display at most
+that many windows on the corresponding side.  If an element is
+@code{nil}, this means there's no bound on the number of slots on that
+side.
+
+If any of the specified values is zero, no window can be created on the
+corresponding side.  @code{display-buffer-in-side-window} will not
+signal an error in that case but return @code{nil}.  If a specified
+value just forbids the creation of an additional side window, the most
+suitable window on that side is reused and may have its
+@code{window-slot} parameter changed accordingly.
+@end defopt
+
+When a frame has side windows, the following function returns the main
+window of that frame.
+
+@defun window-main-window &optional frame
+This function returns the main window of the specified @var{frame}.  The
+optional argument @var{frame} must be a live frame and defaults to the
+selected one.
+
+If @var{frame} has no side windows, it returns @var{frame}'s root
+window.  Otherwise, it returns either an internal non-side window such
+that all other non-side windows on @var{frame} descend from it, or the
+single live non-side window of @var{frame}.  Note that the main window
+of a frame cannot be deleted via @code{delete-window}.
+@end defun
+
+The following command is handy to toggle the appearance of all side
+windows on a specified frame.
+
+@deffn Command window-toggle-side-windows &optional frame
+This command toggles side windows on the specified @var{frame}.  The
+optional argument @var{frame} must be a live frame and defaults to the
+selected one.
+
+If @var{frame} has at least one side window, this command saves the
+state of @var{frame}'s root window in the @var{frame}'s
+@code{window-state} frame parameter and deletes all side windows on
+@var{frame} afterwards.
+
+If @var{frame} has no side window but a @code{window-state} parameter,
+it uses that parameter's value to restore the side windows on
+@var{frame} leaving @var{frame}'s main window alone.
+
+An error is signaled if @var{frame} has no side window and no saved
+state is found.
+@end deffn
+
+
+@node Frame Layouts with Side Windows
+@subsection Frame Layouts with Side Windows
+
+Side windows can be used to create more complex frame layouts like those
+provided by integrated development environments (IDEs).  In such
+layouts, the area of the main window is where the normal editing
+activities take place.  Side windows are not conceived for editing in
+the usual sense.  Rather, they are supposed to display information
+complementary to the current editing activity, like lists of files, tags
+or buffers, help information, search or grep results or shell output.
+
+   The layout of such a frame might appear as follows:
+
+@smallexample
+@group
+     ___________________________________
+    |          *Buffer List*            | 
+    |___________________________________|
+    |     |                       |     |
+    |  *  |                       |  *  |
+    |  d  |                       |  T  |
+    |  i  |                       |  a  |
+    |  r  |   Main Window Area    |  g  |
+    |  e  |                       |  s  |
+    |  d  |                       |  *  |
+    |  *  |                       |     |
+    |_____|_______________________|_____|
+    | *help*/*grep*/  |  *shell*/       |
+    | *Completions*   |  *compilation*  |
+    |_________________|_________________|
+    |             Echo Area             |
+    |___________________________________|
+
+
+@end group
+@end smallexample
+
+The following example illustrates how window parameters (@pxref{Window
+Parameters}) can be used with @code{display-buffer-in-side-window}
+(@pxref{Displaying Buffers in Side Windows}) to set up code for
+producing the frame sketched above.
+
+@example
+@group
+(defvar parameters
+  '(window-parameters . ((no-other-window . t) (no-delete-other-window . t))))
+
+(setq fit-window-to-buffer-horizontally t)
+(setq window-resize-pixelwise t)
+
+(setq
+ display-buffer-alist
+ `(("\\*Buffer List\\*" display-buffer-in-side-window
+    (side . top) (slot . 0) (window-height . fit-window-to-buffer)
+    (preserve-size . (nil . t)) ,parameters)
+   ("\\*Tags List\\*" display-buffer-in-side-window
+    (side . right) (slot . 0) (window-width . fit-window-to-buffer)
+    (preserve-size . (t . nil)) ,parameters)
+   ("\\*\\(?:help\\|grep\\|Completions\\)\\*" display-buffer-in-side-window
+    (side . bottom) (slot . -1) (preserve-size . (nil . t)) ,parameters)
+   ("\\*\\(?:shell\\|compilation\\)\\*" display-buffer-in-side-window
+    (side . bottom) (slot . 1) (preserve-size . (nil . t)) ,parameters)))
+@end group
+@end example
+
+This specifies @code{display-buffer-alist} entries (@pxref{Choosing
+Window}) for buffers with fixed names.  In particular, it asks for
+showing @file{*Buffer List*} with adjustable height at the top of the
+frame and @file{*Tags List*} with adjustable width on the frame's right.
+It also asks for having the @file{*help*}, @file{*grep*} and
+@file{*Completions*} buffers share a window on the bottom left side of
+the frame and the @file{*shell*} and @file{*compilation*} buffers appear
+in a window on the bottom right side of the frame.
+
+   Note that the option @code{fit-window-to-buffer-horizontally} must
+have a non-@code{nil} value in order to allow horizontal adjustment of
+windows.  We also added entries that ask for preserving the height of
+side windows at the top and bottom of the frame and the width of side
+windows at the left or right of the frame.  To assure that side windows
+retain their respective sizes when maximizing the associated frame, we
+have also set the variable @code{window-resize-pixelwise}.
+@xref{Resizing Windows}.
+
+   The last form also makes sure that none of the side windows it
+creates are accessible via @kbd{C-x o} by installing a
+@code{no-other-window} parameter for each of these windows.  In addition
+it also makes sure that side windows are not deleted via @kbd{C-x 1} by
+installing a @code{no-delete-other-window} parameter on each of these
+windows.
+
+   Since @code{dired} buffers have no fixed names, we use a special
+function @code{dired-default-directory-on-left} in order to display a
+lean directory buffer on the left side of the frame.
+
+@example
+@group
+(defun dired-default-directory-on-left ()
+  "Display `default-directory' in side window on left, hiding details."
+  (interactive)
+  (let ((buffer (dired-noselect default-directory)))
+    (with-current-buffer buffer (dired-hide-details-mode t))
+    (display-buffer-in-side-window
+     buffer `((side . left) (slot . 0)
+              (window-width . fit-window-to-buffer)
+              (preserve-size . (t . nil)) ,parameters))))
+@end group
+@end example
+
+Evaluating the preceding forms and typing, in any order, @kbd{M-x
+list-buffers}, @kbd{C-h f}, @kbd{M-x shell}, @kbd{M-x list-tags} and
+@kbd{M-x dired-default-directory-on-left} should now reproduce the frame
+layout sketched above.
+
+
 @node Window Point
 @section Windows and Point
 @cindex window position
@@ -4279,6 +4561,7 @@ Window Parameters
 parameters reset to @code{nil}.  The following variable allows you to
 override the standard behavior:

+@cindex persistent window parameters
 @defvar window-persistent-parameters
 This variable is an alist specifying which parameters get saved by
 @code{current-window-configuration} and @code{window-state-get}, and
@@ -4308,10 +4591,10 @@ Window Parameters
 @end defvar

 Some functions (notably @code{delete-window},
-@code{delete-other-windows} and @code{split-window}), may behave specially
-when their @var{window} argument has a parameter set.  You can override
-such special behavior by binding the following variable to a
-non-@code{nil} value:
+@code{delete-other-windows} and @code{split-window}), may behave
+specially when the window specified by their @var{window} argument has
+the homonymous parameter set.  You can override such special behavior by
+binding the following variable to a non-@code{nil} value:

 @defvar ignore-window-parameters
 If this variable is non-@code{nil}, some standard functions do not
@@ -4337,6 +4620,10 @@ Window Parameters
 This parameter affects the execution of @code{delete-other-windows}
 (@pxref{Deleting Windows}).

+@item @code{no-delete-other-window}
+This parameter marks the window as not deletable by
+@code{delete-other-windows} (@pxref{Deleting Windows}).
+
 @item @code{split-window}
 This parameter affects the execution of @code{split-window}
 (@pxref{Splitting Windows}).
@@ -4387,6 +4674,10 @@ Window Parameters
 this parameter.  @code{quit-restore-window} deletes the specified window
 only if it still shows that buffer.

+@item @code{window-side} @code{window-slot}
+These parameters are used for implementing side windows (@pxref{Side
+Windows}).
+
 @item @code{min-margins}
 The value of this parameter is a cons cell whose @sc{car} and @sc{cdr},
 if non-@code{nil}, specify the minimum values (in columns) for the left
@@ -4409,8 +4700,7 @@ Window Parameters
 versions of Emacs.
 @end table

-There are additional parameters @code{window-atom} and @code{window-side};
-these are reserved and should not be used by applications.
+The @code{window-atom} parameter is used for implemeting atomic windows.


 @node Window Hooks
diff --git a/lisp/window.el b/lisp/window.el
index 6728ea3..73c48be 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -714,19 +714,23 @@ window-sides

 (defcustom window-sides-vertical nil
   "If non-nil, left and right side windows are full height.
-Otherwise, top and bottom side windows are full width."
+Otherwise, top and bottom side windows are full width.  
+
+Setting this variable does not affect the layout of frames
+already displaying side windows on at least two orthogonal
+sides."
   :type 'boolean
   :group 'windows
   :version "24.1")

 (defcustom window-sides-slots '(nil nil nil nil)
   "Maximum number of side window slots.
-The value is a list of four elements specifying the number of
-side window slots on (in this order) the left, top, right and
-bottom side of each frame.  If an element is a number, this means
-to display at most that many side windows on the corresponding
-side.  If an element is nil, this means there's no bound on the
-number of slots on that side."
+The value is a list of four elements specifying the maximum
+number of side windows on the left, top, right and bottom side of
+any frame.  If an element is a number, this means to display at
+most that many side windows on the corresponding side.  If an
+element is nil, this means there's no bound on the number of
+slots on that side."
   :version "24.1"
   :risky t
   :type
@@ -734,34 +738,44 @@ window-sides-slots
     :value (nil nil nil nil)
     (choice
      :tag "Left"
-     :help-echo "Maximum slots of left side window."
+     :help-echo "Maximum number of left side windows."
      :value nil
      :format "%[Left%] %v\n"
      (const :tag "Unlimited" :format "%t" nil)
      (integer :tag "Number" :value 2 :size 5))
     (choice
      :tag "Top"
-     :help-echo "Maximum slots of top side window."
+     :help-echo "Maximum number of top side windows."
      :value nil
      :format "%[Top%] %v\n"
      (const :tag "Unlimited" :format "%t" nil)
      (integer :tag "Number" :value 3 :size 5))
     (choice
      :tag "Right"
-     :help-echo "Maximum slots of right side window."
+     :help-echo "Maximum number of right side windows."
      :value nil
      :format "%[Right%] %v\n"
      (const :tag "Unlimited" :format "%t" nil)
      (integer :tag "Number" :value 2 :size 5))
     (choice
      :tag "Bottom"
-     :help-echo "Maximum slots of bottom side window."
+     :help-echo "Maximum number of bottom side windows."
      :value nil
      :format "%[Bottom%] %v\n"
      (const :tag "Unlimited" :format "%t" nil)
      (integer :tag "Number" :value 3 :size 5)))
   :group 'windows)

+(defvar-local window-sides-shown nil
+  "Non-nil if this buffer was shown in a side window once.
+If this variable is non-nil in a buffer, the
+`switch-to-prev-buffer' and `switch-to-next-buffer' functions
+will refrain to show this buffer within the main window area.
+`display-buffer-in-side-window' sets this variable automatically.
+
+Killing buffer local variables after showing the buffer in a side
+window annihilates the effect provided by setting this.")
+
 (defun window--side-window-p (window)
   "Return non-nil if WINDOW is a side window or the parent of one."
   (or (window-parameter window 'window-side)
@@ -771,19 +785,18 @@ window--side-window-p
 	       (window-parameter
 		(window-last-child window) 'window-side)))))

-(defun window--major-non-side-window (&optional frame)
-  "Return the major non-side window of frame FRAME.
+(defun window-main-window (&optional frame)
+  "Return the main window of specified FRAME.
 The optional argument FRAME must be a live frame and defaults to
 the selected one.

-If FRAME has at least one side window, the major non-side window
-is either an internal non-side window such that all other
-non-side windows on FRAME descend from it, or the single live
-non-side window of FRAME.  If FRAME has no side windows, return
-its root window."
+If FRAME has no side windows, return FRAME's root window.
+Otherwise, return either an internal non-side window such that
+all other non-side windows on FRAME descend from it, or the
+single live non-side window of FRAME."
   (let ((frame (window-normalize-frame frame))
-	major sibling)
-    ;; Set major to the _last_ window found by `walk-window-tree' that
+	main sibling)
+    ;; Set main to the _last_ window found by `walk-window-tree' that
     ;; is not a side window but has a side window as its sibling.
     (walk-window-tree
      (lambda (window)
@@ -792,14 +805,17 @@ window--major-non-side-window
 		     (window-parameter sibling 'window-side))
 		(and (setq sibling (window-next-sibling window))
 		     (window-parameter sibling 'window-side)))
-	    (setq major window)))
+	    (setq main window)))
      frame t 'nomini)
-    (or major (frame-root-window frame))))
+    (or main (frame-root-window frame))))

-(defun window--major-side-window (side)
-  "Return major side window on SIDE.
+(defun window--make-major-side-window-next-to (side)
+  "Return window to split for making a major side window.
 SIDE must be one of the symbols `left', `top', `right' or
-`bottom'.  Return nil if no such window exists."
+`bottom'.
+
+This is an auxiliary function of `window--make-major-side-window'
+and must not be called when a window on SIDE exists already."
   (let ((root (frame-root-window))
 	window)
     ;; (1) If a window on the opposite side exists, return that window's
@@ -839,35 +855,36 @@ window--major-side-window
 	(window-prev-sibling window))
        (t root))))))

-(defun display-buffer-in-major-side-window (buffer side slot &optional alist)
-  "Display BUFFER in a new window on SIDE of the selected frame.
+(defun window--make-major-side-window (buffer side slot &optional alist)
+  "Display BUFFER in a new major side window on the selected frame.
 SIDE must be one of `left', `top', `right' or `bottom'.  SLOT
 specifies the slot to use.  ALIST is an association list of
 symbols and values as passed to `display-buffer-in-side-window'.
-This function may be called only if no window on SIDE exists yet.
-The new window automatically becomes the \"major\" side window on
-SIDE.  Return the new window, nil if its creation window failed."
+Return the new window, nil if its creation failed.
+
+This is an auxiliary function of `display-buffer-in-side-window'
+and may be called only if no window on SIDE exists yet."
   (let* ((left-or-right (memq side '(left right)))
-	 (major (window--major-side-window side))
+	 (next-to (window--make-major-side-window-next-to side))
 	 (on-side (cond
 		   ((eq side 'top) 'above)
 		   ((eq side 'bottom) 'below)
 		   (t side)))
 	 ;; The following two bindings will tell `split-window' to take
-	 ;; the space for the new window from `major' and not make a new
-	 ;; parent window unless needed.
+	 ;; the space for the new window from the selected frame's main
+	 ;; window and not make a new parent window unless needed.
 	 (window-combination-resize 'side)
 	 (window-combination-limit nil)
-	 (new (split-window major nil on-side)))
-    (when new
-      ;; Initialize `window-side' parameter of new window to SIDE.
-      (set-window-parameter new 'window-side side)
-      ;; Install `window-slot' parameter of new window.
-      (set-window-parameter new 'window-slot slot)
-      ;; Install `delete-window' parameter thus making sure that when
-      ;; the new window is deleted, a side window on the opposite side
-      ;; does not get resized.
-      (set-window-parameter new 'delete-window 'delete-side-window)
+	 (window (split-window next-to nil on-side)))
+    (when window
+      ;; Initialize `window-side' parameter of new window to SIDE and
+      ;; make that parameter persistent.
+      (set-window-parameter window 'window-side side)
+      (add-to-list 'window-persistent-parameters '(window-side . writable))
+      ;; Install `window-slot' parameter of new window and make that
+      ;; parameter persistent.
+      (set-window-parameter window 'window-slot slot)
+      (add-to-list 'window-persistent-parameters '(window-slot . writable))
       ;; Auto-adjust height/width of new window unless a size has been
       ;; explicitly requested.
       (unless (if left-or-right
@@ -882,15 +899,10 @@ display-buffer-in-major-side-window
 		   ;; root window.
 		   4))
 	       alist)))
-      ;; Install BUFFER in new window and return NEW.
-      (window--display-buffer buffer new 'window alist 'side))))
-
-(defun delete-side-window (window)
-  "Delete side window WINDOW."
-  (let ((window-combination-resize
-	 (window-parameter (window-parent window) 'window-side))
-	(ignore-window-parameters t))
-    (delete-window window)))
+      (with-current-buffer buffer
+        (setq window-sides-shown t))
+      ;; Install BUFFER in new window and return WINDOW.
+      (window--display-buffer buffer window 'window alist 'side))))

 (defun display-buffer-in-side-window (buffer alist)
   "Display BUFFER in a side window of the selected frame.
@@ -906,9 +918,27 @@ display-buffer-in-side-window
   the specified side.  A negative value means use a slot
   preceding (that is, above or on the left of) the middle slot.
   A positive value means use a slot following (that is, below or
-  on the right of) the middle slot.  The default is zero."
-  (let ((side (or (cdr (assq 'side alist)) 'bottom))
-	(slot (or (cdr (assq 'slot alist)) 0)))
+  on the right of) the middle slot.  The default is zero.
+
+If the current frame size or the settings of `window-sides-slots'
+do not permit making a new window, a suitable existing window may
+be reused and have its `window-slot' parameter value accordingly
+modified.
+
+Unless `display-buffer-mark-dedicated' is non-nil, softly
+dedicate the side window used to BUFFER.  Return nil if no
+suitable window is found.
+
+This function installs the `window-side' and `window-slot'
+parameters and makes them persistent.  It neither modifies ALIST
+nor installs any other window parameters unless they have been
+explicitly provided via a `window-parameter' entry in ALIST."
+  (let* ((side (or (cdr (assq 'side alist)) 'bottom))
+         (slot (or (cdr (assq 'slot alist)) 0))
+         (left-or-right (memq side '(left right)))
+         ;; Softly dedicate window to BUFFER unless
+         ;; `display-buffer-mark-dedicated' already asks for it.
+         (dedicated (or display-buffer-mark-dedicated 'side)))
     (cond
      ((not (memq side '(top bottom left right)))
       (error "Invalid side %s specified" side))
@@ -940,12 +970,12 @@ display-buffer-in-side-window

       (cond
        ((and (numberp max-slots) (<= max-slots 0))
-	;; No side-slots available on this side.  Don't create an error,
+	;; No side-slots available on this side.  Don't raise an error,
 	;; just return nil.
 	nil)
        ((not windows)
-	;; No major window exists on this side, make one.
-	(display-buffer-in-major-side-window buffer side slot alist))
+	;; No major side window exists on this side, make one.
+	(window--make-major-side-window buffer side slot alist))
        (t
 	;; Scan windows on SIDE.
 	(catch 'found
@@ -983,46 +1013,69 @@ display-buffer-in-side-window
 	;; window will be created before it.
 	;; `best-window' is the window with the smallest absolute difference
 	;; of its slot and SLOT.
-
-	;; Note: We dedicate the window used softly to its buffer to
-	;; avoid that "other" (non-side) buffer display functions steal
-	;; it from us.  This must eventually become customizable via
-	;; ALIST (or, better, avoided in the "other" functions).
 	(or (and this-window
 		 ;; Reuse `this-window'.
-		 (window--display-buffer buffer this-window 'reuse alist 'side))
+                 (with-current-buffer buffer
+                   (setq window-sides-shown t))
+		 (window--display-buffer
+                  buffer this-window 'reuse alist dedicated))
 	    (and (or (not max-slots) (< slots max-slots))
 		 (or (and next-window
 			  ;; Make new window before `next-window'.
-			  (let ((next-side
-				 (if (memq side '(left right)) 'above 'left))
+			  (let ((next-side (if left-or-right 'above 'left))
 				(window-combination-resize 'side))
-			    (setq window (split-window next-window nil next-side))
-			    ;; When the new window is deleted, its space
-			    ;; is returned to other side windows.
-			    (set-window-parameter
-			     window 'delete-window 'delete-side-window)
-			    window))
+			    (setq window
+                                  (split-window next-window nil next-side))))
 		     (and prev-window
 			  ;; Make new window after `prev-window'.
-			  (let ((prev-side
-				 (if (memq side '(left right)) 'below 'right))
+			  (let ((prev-side (if left-or-right 'below 'right))
 				(window-combination-resize 'side))
-			    (setq window (split-window prev-window nil prev-side))
-			    ;; When the new window is deleted, its space
-			    ;; is returned to other side windows.
-			    (set-window-parameter
-			     window 'delete-window 'delete-side-window)
-			    window)))
+			    (setq window
+                                  (split-window prev-window nil prev-side)))))
 		   (set-window-parameter window 'window-slot slot)
-		   (window--display-buffer buffer window 'window alist 'side))
+                   (with-current-buffer buffer
+                     (setq window-sides-shown t))
+		   (window--display-buffer
+                    buffer window 'window alist dedicated))
 	    (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 alist 'side)))))))))
+                   (with-current-buffer buffer
+                     (setq window-sides-shown t))
+                   (window--display-buffer
+		    buffer best-window 'reuse alist dedicated)))))))))
+
+(defun window-toggle-side-windows (&optional frame)
+  "Toggle side windows on specified FRAME.
+FRAME must be a live frame and defaults to the selected one.
+
+If FRAME has at least one side window, save FRAME's state in the
+FRAME's `window-state' frame parameter and delete all side
+windows on FRAME afterwards.  Otherwise, if FRAME has a
+`window-state' parameter, use that to restore any side windows on
+FRAME leaving FRAME's main window alone.  Signal an error if
+FRAME has no side window and no saved state is found."
+  (interactive)
+  (let* ((frame (window-normalize-frame frame))
+         state)
+    (cond
+     ((window-with-parameter 'window-side nil frame)
+      ;; At least one side window exists.  Remove all side windows after
+      ;; saving FRAME's state in its `window-state' parameter.
+      (set-frame-parameter
+       frame 'window-state (window-state-get (frame-root-window frame)))
+      (let ((ignore-window-parameters t))
+        (delete-other-windows (window-main-window frame))))
+     ((setq state (frame-parameter frame 'window-state))
+      ;; A window state was saved for FRAME.  Restore it and put the
+      ;; current root window into its main window.
+      (let ((main-state (window-state-get (frame-root-window frame))))
+        (window-state-put state (frame-root-window frame) t)
+        (window-state-put main-state (window-main-window frame))))
+     (t
+      (error "No side windows state found")))))

 (defun window--side-check (&optional frame)
   "Check the side window configuration of FRAME.
@@ -3224,8 +3277,10 @@ adjust-window-trailing-edge
 	(setq left first-left)
 	(while (and left
 		    (or (window-size-fixed-p left horizontal 'preserved)
-			(<= (window-size left horizontal t)
-			    (window-min-size left horizontal 'preserved t))))
+			(and (< delta 0)
+                             (<= (window-size left horizontal t)
+                                 (window-min-size
+                                  left horizontal 'preserved t)))))
 	  (setq left
 		(or (window-left left)
 		    (progn
@@ -3245,7 +3300,8 @@ adjust-window-trailing-edge
 		  (or (window-size-fixed-p right horizontal)
 		      (and (> delta 0)
 			   (<= (window-size right horizontal t)
-			       (window-min-size right horizontal 'preserved t)))))
+			       (window-min-size
+                                right horizontal 'preserved t)))))
 	(setq right
 	      (or (window-right right)
 		  (progn
@@ -3259,8 +3315,10 @@ adjust-window-trailing-edge
 	(setq right first-right)
 	(while (and right
 		    (or (window-size-fixed-p right horizontal 'preserved)
-                        (<= (window-size right horizontal t)
-                            (window-min-size right horizontal 'preserved t))))
+                        (and (> delta 0)
+                             (<= (window-size right horizontal t)
+                                 (window-min-size
+                                  right horizontal 'preserved t)))))
 	  (setq right
 		(or (window-right right)
 		    (progn
@@ -3289,8 +3347,9 @@ adjust-window-trailing-edge
 	  ;; Start resizing.
 	  (window--resize-reset frame horizontal)
 	  ;; Try to enlarge LEFT first.
-	  (setq this-delta (window--resizable
-			    left delta horizontal ignore 'after nil nil pixelwise))
+	  (setq this-delta
+                (window--resizable
+                 left delta horizontal ignore 'after nil nil pixelwise))
 	  (unless (zerop this-delta)
 	    (window--resize-this-window
 	     left this-delta horizontal ignore t 'before
@@ -3740,7 +3799,9 @@ one-window-p
 (defun window-deletable-p (&optional window)
   "Return t if WINDOW can be safely deleted from its frame.
 WINDOW must be a valid window and defaults to the selected one.
-Return `frame' if deleting WINDOW should also delete its frame."
+
+Return `frame' if WINDOW is the root window of its frame and that
+frame can be safely deleted."
   (setq window (window-normalize-window window))

   (unless (or ignore-window-parameters
@@ -3767,10 +3828,14 @@ window-deletable-p
 		  (let ((minibuf (active-minibuffer-window)))
 		    (and minibuf (eq frame (window-frame minibuf)))))
 	'frame))
+     ((window-minibuffer-p window)
+      ;; If WINDOW is the minibuffer window of a non-minibuffer-only
+      ;; frame, it cannot be deleted separately.
+      nil)
      ((or ignore-window-parameters
-	  (not (eq window (window--major-non-side-window frame))))
-      ;; WINDOW can be deleted unless it is the major non-side window of
-      ;; its frame.
+	  (not (eq window (window-main-window frame))))
+      ;; Otherwise, WINDOW can be deleted unless it is the main window
+      ;; of its frame.
       t))))

 (defun window--in-subtree-p (window root)
@@ -3826,11 +3891,14 @@ delete-window
 	  (throw 'done (delete-window atom-root))))
        ((not parent)
 	(error "Attempt to delete minibuffer or sole ordinary window"))
-       ((eq window (window--major-non-side-window frame))
-	(error "Attempt to delete last non-side window")))
+       ((eq window (window-main-window frame))
+	(error "Attempt to delete main window of frame %s" frame)))

       (let* ((horizontal (window-left-child parent))
 	     (size (window-size window horizontal t))
+             (window-combination-resize
+              (or window-combination-resize
+                  (window-parameter parent 'window-side)))
 	     (frame-selected
 	      (window--in-subtree-p (frame-selected-window frame) window))
 	     ;; Emacs 23 preferably gives WINDOW's space to its left
@@ -3886,8 +3954,7 @@ delete-other-windows
   (setq window (window-normalize-window window))
   (let* ((frame (window-frame window))
 	 (function (window-parameter window 'delete-other-windows))
-	 (window-side (window-parameter window 'window-side))
-	 atom-root side-main)
+	 atom-root main)
     (window--check frame)
     (catch 'done
       (cond
@@ -3905,18 +3972,48 @@ delete-other-windows
 	(if (eq atom-root (frame-root-window frame))
 	    (error "Root of atomic window is root window of its frame")
 	  (throw 'done (delete-other-windows atom-root))))
-       ((memq window-side window-sides)
+       ((window-parameter window 'window-side)
 	(error "Cannot make side window the only window"))
        ((and (window-minibuffer-p window)
 	     (not (eq window (frame-root-window window))))
 	(error "Can't expand minibuffer to full frame")))

-      ;; If WINDOW is the major non-side window, do nothing.
-      (if (window-with-parameter 'window-side)
-	  (setq side-main (window--major-non-side-window frame))
-	(setq side-main (frame-root-window frame)))
-      (unless (eq window side-main)
-	(delete-other-windows-internal window side-main)
+      (cond
+       ((or ignore-window-parameters
+            (not (window-with-parameter 'no-delete-other-window nil frame)))
+        (setq main (frame-root-window frame)))
+       ((catch 'tag
+          (walk-window-tree
+           (lambda (other)
+             (when (or (and (window-parameter other 'window-side)
+                            (not (window-parameter
+                                  other 'no-delete-other-window)))
+                       (and (not (window-parameter other 'window-side))
+                            (window-parameter
+                             other 'no-delete-other-window)))
+               (throw 'tag nil))))
+          t)
+        (setq main (window-main-window frame)))
+       (t
+        ;; Delete other windows via `delete-window' because either a
+        ;; side window is or a non-side-window is not deletable.
+        (dolist (other (window-list frame))
+          (when (and (window-live-p other)
+                     (not (eq other window))
+                     (not (window-parameter
+                           other 'no-delete-other-window))
+                     ;; When WINDOW and the other window are part of the
+                     ;; same atomic window, don't delete the other.
+                     (or (not atom-root)
+                         (not (eq (window-atom-root other) atom-root))))
+            (condition-case nil
+                (delete-window other)
+              (error nil))))
+        (throw 'done nil)))
+
+      ;; If WINDOW is the main window of its frame do nothing.
+      (unless (eq window main)
+	(delete-other-windows-internal window main)
 	(run-window-configuration-change-hook frame)
 	(window--check frame))
       ;; Always return nil.
@@ -4066,6 +4163,7 @@ switch-to-prev-buffer
   (interactive)
   (let* ((window (window-normalize-window window t))
 	 (frame (window-frame window))
+         (window-side (window-parameter window 'window-side))
 	 (old-buffer (window-buffer window))
 	 ;; Save this since it's destroyed by `set-window-buffer'.
 	 (next-buffers (window-next-buffers window))
@@ -4076,7 +4174,7 @@ switch-to-prev-buffer
       (unless (setq window (minibuffer-selected-window))
 	(error "Window %s is a minibuffer window" window)))

-    (when (window-dedicated-p window)
+    (unless (memq (window-dedicated-p window) '(nil side))
       ;; Don't switch in dedicated window.
       (error "Window %s is dedicated to buffer %s" window old-buffer))

@@ -4106,23 +4204,27 @@ switch-to-prev-buffer
       ;; buffer we don't reverse the global buffer list to avoid showing
       ;; a buried buffer instead.  Otherwise, we must reverse the global
       ;; buffer list in order to make sure that switching to the
-      ;; previous/next buffer traverse it in opposite directions.
-      (dolist (buffer (if bury-or-kill
-			  (buffer-list frame)
-			(nreverse (buffer-list frame))))
-	(when (and (buffer-live-p buffer)
-		   (not (eq buffer old-buffer))
-                   (or (null pred) (funcall pred buffer))
-		   (not (eq (aref (buffer-name buffer) 0) ?\s))
-		   (or bury-or-kill (not (memq buffer next-buffers))))
-	  (if (and (not switch-to-visible-buffer)
-		   (get-buffer-window buffer frame))
-	      ;; Try to avoid showing a buffer visible in some other window.
-	      (unless visible
-		(setq visible buffer))
-	    (setq new-buffer buffer)
-	    (set-window-buffer-start-and-point window new-buffer)
-	    (throw 'found t))))
+      ;; previous/next buffer traverse it in opposite directions.  Skip
+      ;; this step for side windows.
+      (unless window-side
+        (dolist (buffer (if bury-or-kill
+                            (buffer-list frame)
+                          (nreverse (buffer-list frame))))
+          (when (and (buffer-live-p buffer)
+                     (not (eq buffer old-buffer))
+                     (or (null pred) (funcall pred buffer))
+                     (not (eq (aref (buffer-name buffer) 0) ?\s))
+                     ;; Don't show a buffer shown in a side window before.
+                     (not (buffer-local-value 'window-sides-shown buffer))
+                     (or bury-or-kill (not (memq buffer next-buffers))))
+            (if (and (not switch-to-visible-buffer)
+                     (get-buffer-window buffer frame))
+                ;; Try to avoid showing a buffer visible in some other window.
+                (unless visible
+                  (setq visible buffer))
+              (setq new-buffer buffer)
+              (set-window-buffer-start-and-point window new-buffer)
+              (throw 'found t)))))
       (unless bury-or-kill
 	;; Scan reverted next buffers last (must not use nreverse
 	;; here!).
@@ -4184,6 +4286,7 @@ switch-to-next-buffer
   (interactive)
   (let* ((window (window-normalize-window window t))
 	 (frame (window-frame window))
+         (window-side (window-parameter window 'window-side))
 	 (old-buffer (window-buffer window))
 	 (next-buffers (window-next-buffers window))
          (pred (frame-parameter frame 'buffer-predicate))
@@ -4193,7 +4296,7 @@ switch-to-next-buffer
       (unless (setq window (minibuffer-selected-window))
 	(error "Window %s is a minibuffer window" window)))

-    (when (window-dedicated-p window)
+    (unless (memq (window-dedicated-p window) '(nil side))
       ;; Don't switch in dedicated window.
       (error "Window %s is dedicated to buffer %s" window old-buffer))

@@ -4211,20 +4314,23 @@ switch-to-next-buffer
 	   window new-buffer (nth 1 entry) (nth 2 entry))
 	  (throw 'found t)))
       ;; Scan the buffer list of WINDOW's frame next, skipping previous
-      ;; buffers entries.
-      (dolist (buffer (buffer-list frame))
-	(when (and (buffer-live-p buffer)
-		   (not (eq buffer old-buffer))
-                   (or (null pred) (funcall pred buffer))
-		   (not (eq (aref (buffer-name buffer) 0) ?\s))
-		   (not (assq buffer (window-prev-buffers window))))
-	  (if (and (not switch-to-visible-buffer)
-		   (get-buffer-window buffer frame))
-	      ;; Try to avoid showing a buffer visible in some other window.
-	      (setq visible buffer)
-	    (setq new-buffer buffer)
-	    (set-window-buffer-start-and-point window new-buffer)
-	    (throw 'found t))))
+      ;; buffers entries.  Skip this step for side windows.
+      (unless window-side
+        (dolist (buffer (buffer-list frame))
+          (when (and (buffer-live-p buffer)
+                     (not (eq buffer old-buffer))
+                     (or (null pred) (funcall pred buffer))
+                     (not (eq (aref (buffer-name buffer) 0) ?\s))
+                     ;; Don't show a buffer shown in a side window before.
+                     (not (buffer-local-value 'window-sides-shown buffer))
+                     (not (assq buffer (window-prev-buffers window))))
+            (if (and (not switch-to-visible-buffer)
+                     (get-buffer-window buffer frame))
+                ;; Try to avoid showing a buffer visible in some other window.
+                (setq visible buffer)
+              (setq new-buffer buffer)
+              (set-window-buffer-start-and-point window new-buffer)
+              (throw 'found t)))))
       ;; Scan WINDOW's reverted previous buffers last (must not use
       ;; nreverse here!)
       (dolist (entry (reverse (window-prev-buffers window)))
@@ -5286,12 +5392,17 @@ window--state-get-1
 		     (scroll-bars . ,(window-scroll-bars window))
 		     (vscroll . ,(window-vscroll window))
 		     (dedicated . ,(window-dedicated-p window))
-		     (point . ,(if writable point
-                                 (copy-marker point
-                                              (buffer-local-value
-                                               'window-point-insertion-type
-                                               buffer))))
-		     (start . ,(if writable start (copy-marker start)))))))))
+		     (point . ,(if writable
+                                   point
+                                 (with-current-buffer buffer
+                                   (copy-marker point
+                                                (buffer-local-value
+                                                 'window-point-insertion-type
+                                                 buffer)))))
+		     (start . ,(if writable
+                                   start
+                                 (with-current-buffer buffer
+                                   (copy-marker start))))))))))
 	 (tail
 	  (when (memq type '(vc hc))
 	    (let (list)
@@ -5363,7 +5474,8 @@ window--state-put-1
      ((memq type '(vc hc))
       (let* ((horizontal (eq type 'hc))
 	     (total (window-size window horizontal pixelwise))
-	     (first t)
+             (first t)
+             (window-combination-limit (cdr (assq 'combination-limit state)))
 	     size new)
 	(dolist (item state)
 	  ;; Find the next child window.  WINDOW always points to the
@@ -5406,12 +5518,9 @@ window--state-put-1
 				       (frame-char-height (window-frame window))
 				     1)))))
 	      (if (window-sizable-p window (- size) horizontal 'safe pixelwise)
-		  (let* ((window-combination-limit
-			  (assq 'combination-limit item)))
-		    ;; We must inherit the combination limit, otherwise
-		    ;; we might mess up handling of atomic and side
-		    ;; window.
-		    (setq new (split-window window size horizontal pixelwise)))
+                  (progn
+                    (setq new (split-window window size horizontal pixelwise))
+                    (setq window-combination-limit nil))
 		;; Give up if we can't resize window down to safe sizes.
 		(error "Cannot resize window %s" window))

@@ -5462,7 +5571,8 @@ window--state-put-2
 		   (nth 3 scroll-bars) (nth 5 scroll-bars)))
 		(set-window-vscroll window (cdr (assq 'vscroll state)))
 		;; Adjust vertically.
-		(if (memq window-size-fixed '(t height))
+		(if (or (memq window-size-fixed '(t height))
+                        (window-preserved-size window))
 		    ;; A fixed height window, try to restore the
 		    ;; original size.
 		    (let ((delta
@@ -5484,7 +5594,8 @@ window--state-put-2
 				window delta nil ignore nil nil nil pixelwise))
 		      (window-resize window delta nil ignore pixelwise))))
 		;; Adjust horizontally.
-		(if (memq window-size-fixed '(t width))
+		(if (or (memq window-size-fixed '(t width))
+                        (window-preserved-size window t))
 		    ;; A fixed width window, try to restore the original
 		    ;; size.
 		    (let ((delta
@@ -5494,8 +5605,8 @@ window--state-put-2
 			      (window-size window t pixelwise)))
 			  window-size-fixed)
 		      (when (window--resizable-p
-			     window delta nil nil nil nil nil pixelwise)
-			(window-resize window delta nil nil pixelwise)))
+			     window delta t nil nil nil nil pixelwise)
+			(window-resize window delta t nil pixelwise)))
 		  ;; Else check whether the window is not wide enough.
 		  (let* ((min-size (window-min-size window t ignore pixelwise))
 			 (delta (- min-size (window-size window t pixelwise))))
@@ -5540,16 +5651,14 @@ window-state-put
   ;; When WINDOW is internal, reduce it to a live one to put STATE into,
   ;; see Bug#16793.
   (unless (window-live-p window)
-    (let ((root (frame-root-window window)))
-      (if (eq window root)
-	  (setq window (frame-first-window root))
-	(setq root window)
-	(setq window (catch 'live
-		       (walk-window-subtree
-			(lambda (window)
-			  (when (window-live-p window)
-			    (throw 'live window)))
-			root))))
+    (let ((root window))
+      (setq window (catch 'live
+                     (walk-window-subtree
+                      (lambda (window)
+                        (when (and (window-live-p window)
+                                   (not (window-parameter window 'window-side)))
+                          (throw 'live window)))
+                      root)))
       (delete-other-windows-internal window root)))

   (set-window-dedicated-p window nil)
@@ -6314,15 +6423,15 @@ window--display-buffer
 	(set-window-dedicated-p window dedicated))
       (when (memq type '(window frame))
 	(set-window-prev-buffers window nil)))
-    (let ((parameter (window-parameter window 'quit-restore))
+    (let ((quit-restore (window-parameter window 'quit-restore))
 	  (height (cdr (assq 'window-height alist)))
 	  (width (cdr (assq 'window-width alist)))
 	  (size (cdr (assq 'window-size alist)))
 	  (preserve-size (cdr (assq 'preserve-size alist))))
       (cond
        ((or (eq type 'frame)
-	    (and (eq (car parameter) 'same)
-		 (eq (nth 1 parameter) 'frame)))
+	    (and (eq (car quit-restore) 'same)
+		 (eq (nth 1 quit-restore) 'frame)))
 	;; Adjust size of frame if asked for.
 	(cond
 	 ((not size))
@@ -6340,8 +6449,8 @@ window--display-buffer
 	 ((functionp size)
 	  (ignore-errors (funcall size window)))))
        ((or (eq type 'window)
-	    (and (eq (car parameter) 'same)
-		 (eq (nth 1 parameter) 'window)))
+	    (and (eq (car quit-restore) 'same)
+		 (eq (nth 1 quit-restore) 'window)))
 	;; Adjust height of window if asked for.
 	(cond
 	 ((not height))
@@ -6377,8 +6486,12 @@ window--display-buffer
 	;; Preserve window size if asked for.
 	(when (consp preserve-size)
 	  (window-preserve-size window t (car preserve-size))
-	  (window-preserve-size window nil (cdr preserve-size))))))
-
+	  (window-preserve-size window nil (cdr preserve-size)))))
+      ;; Assign any window parameters specified.
+      (let ((parameters (cdr (assq 'window-parameters alist))))
+        (dolist (parameter parameters)
+          (set-window-parameter
+           window (car parameter) (cdr parameter)))))
     window))

 (defun window--maybe-raise-frame (frame)
@@ -6602,6 +6715,9 @@ display-buffer
     preserve the width of the window, (nil . t) to preserve its
     height or (t . t) to preserve both.

+ `window-parameters' -- Value specifies an alist of window
+                        parameters to give the chosen window.
+
 The ACTION argument to `display-buffer' can also have a non-nil
 and non-list value.  This means to display the buffer in a window
 other than the selected one, even if it is already displayed in
@@ -6954,7 +7070,7 @@ display-buffer-at-bottom
 	(and (not (frame-parameter nil 'unsplittable))
 	     (setq window
 		   (condition-case nil
-		       (split-window (window--major-non-side-window))
+		       (split-window (window-main-window))
 		     (error nil)))
 	     (window--display-buffer
 	      buffer window 'window alist display-buffer-mark-dedicated))


             reply	other threads:[~2016-09-22  9:07 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-22  9:07 martin rudalics [this message]
2016-09-22 20:54 ` Side Windows Juri Linkov
2016-09-24 19:05   ` martin rudalics
2016-09-23  8:38 ` Eli Zaretskii
2016-09-23  9:14   ` Eli Zaretskii
2016-09-24 19:06   ` martin rudalics
2016-09-24 19:27     ` Eli Zaretskii
2016-10-05  8:39       ` martin rudalics
2016-10-05 10:35         ` Eli Zaretskii
2016-10-05 13:13         ` Eli Zaretskii
2016-10-05 14:20           ` martin rudalics
  -- strict thread matches above, loose matches on Subject: below --
2016-10-05 10:26 Angelo Graziosi
2016-10-05 10:51 ` Eli Zaretskii
2016-10-05 11:01   ` Angelo Graziosi
2016-10-05 11:24     ` Kaushal Modi
2016-10-05 13:03     ` Eli Zaretskii
2016-10-05 10:25 Angelo Graziosi
2010-04-13 19:53 Gtk tabs in emacs, new branch grischka
2010-04-13 23:31 ` Side windows (was: Gtk tabs in emacs, new branch.) Juri Linkov
2010-04-14  3:18   ` Eli Zaretskii
2010-04-14 15:24     ` Side windows Jason Rumney
2010-04-14 16:52       ` Juri Linkov
2010-04-14 18:19         ` Eli Zaretskii
2010-04-14 23:54           ` Juri Linkov
2010-04-15  3:18             ` Eli Zaretskii
2010-04-15 23:46               ` Juri Linkov
2010-04-16  6:33                 ` Eli Zaretskii
2010-04-14  5:15   ` Jan Djärv
2010-04-16 14:03   ` grischka
2010-04-16 20:48     ` Juri Linkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57E39F4C.7010208@gmx.at \
    --to=rudalics@gmx.at \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.