unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: Side Windows
@ 2016-10-05 10:25 Angelo Graziosi
  0 siblings, 0 replies; 27+ messages in thread
From: Angelo Graziosi @ 2016-10-05 10:25 UTC (permalink / raw)
  To: rudalics, Emacs developers

Martin Rudalics wrote:
> I now committed my changes.

Leaving aside your commit, where can one find the documentation about 
this? Ho to use and so on. One needs some practical examples, adding 
this and this to the init file you will get this, adding this, instead, 
you will get this etc..

   Angelo



^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: Side Windows
@ 2016-10-05 10:26 Angelo Graziosi
  2016-10-05 10:51 ` Eli Zaretskii
  0 siblings, 1 reply; 27+ messages in thread
From: Angelo Graziosi @ 2016-10-05 10:26 UTC (permalink / raw)
  To: rudalics, Emacs developers

Martin Rudalics wrote:
> I now committed my changes.

Leaving aside your commit, where can one find the documentation about 
this? Ho to use and so on. One needs some practical examples, adding 
this and this to the init file you will get this, adding this, instead, 
you will get this etc..

   Angelo



^ permalink raw reply	[flat|nested] 27+ messages in thread
* Side Windows
@ 2016-09-22  9:07 martin rudalics
  2016-09-22 20:54 ` Juri Linkov
  2016-09-23  8:38 ` Eli Zaretskii
  0 siblings, 2 replies; 27+ messages in thread
From: martin rudalics @ 2016-09-22  9:07 UTC (permalink / raw)
  To: emacs-devel

[-- 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))


^ permalink raw reply related	[flat|nested] 27+ messages in thread
* RE: Gtk tabs in emacs, new branch.
@ 2010-04-13 19:53 grischka
  2010-04-13 23:31 ` Side windows (was: Gtk tabs in emacs, new branch.) Juri Linkov
  0 siblings, 1 reply; 27+ messages in thread
From: grischka @ 2010-04-13 19:53 UTC (permalink / raw)
  To: drew.adams; +Cc: emacs-devel

 > It's not clear to me, for example, what you mean by tabs (necessarily)
 > doing the same thing to different objects.

See, tabs are defined by their shape, more by their placement and
mostly by their action.  Which is to "switch content in the associated
window".  If it does not perform this action then it is not a tabs
control but just a row of buttons.

To give another example:  A scrollbar is defined mostly by its action
to "scroll content in the associated window".  Of course you could use
the scrollbar widget just as well to adjust your speaker volume, but
then it wouldn't be a scrollbar, even if it looked like one.

Aside from that it is completely unnecessary and boring to overload
widgets with alien functionality.  If for example you like to have
a row of buttons to switch color themes in the buffer, then well,
just use a row of (possibly colored) buttons.

--- grischka





^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2016-10-05 14:20 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-05 10:25 Side Windows Angelo Graziosi
  -- 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-09-22  9:07 martin rudalics
2016-09-22 20:54 ` 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
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

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).