unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Help with windows and 'quit-restore
@ 2017-02-28  1:01 Eric Abrahamsen
  2017-03-01  0:57 ` Michael Heerdegen
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Abrahamsen @ 2017-02-28  1:01 UTC (permalink / raw)
  To: help-gnu-emacs

I'm having a heck of a time understanding how the 'quit-restore window
parameter actually works.

I've got a pop-up window that goes into special-mode, and I'm trying to
get the right level of control over both the window splitting, and the
behavior of "q" (quit-window).

First it was the "manual way":

#+BEGIN_SRC elisp
(let* ((buf (get-buffer-I-want-to-pop-up))
       (window (get-window-I-want-to-split))
       (buffer-window (split-window window 0.5
				    'right)))
  (set-window-buffer buffer-window buf)
  (display-buffer-record-window 'window buffer-window buf))
#+END_SRC

The SIZE and SIDE args to `split-window' are calculated elsewhere, just
hard-coded in my cut-down example. This allows me to split windows
exactly as I want.

This call to `display-buffer-record-window', however, does *not* set up
the `quit-restore parameter correctly: when I hit "q" in the buffer, the
buffer quits but the popped-up window remains, displaying some other
buffer, usually a copy of a buffer that's already visible.

I can get a perfect 'quit-restore with the "automatic way":

#+BEGIN_SRC elisp
(display-buffer
 buf
 `(display-buffer-pop-up-window . ((window-height . 0.5))))
#+END_SRC

Again, cut down to show the final effect. This gives me exactly the
quit-restore behavior I want, but the window splitting is erratic: Emacs
tries to DTRT, but it isn't TRT, and no amount of fiddling with the
`split-*-threshold' variables works. It's forever splitting the wrong
window, or splitting it the wrong way.

So I think what I want is to stick with the former incantation, but learn
how to call `display-buffer-record-window' correctly. I followed
`display-buffer-pop-up-window' as far as I could, but really can't see
how it builds its 'quit-restore.

Can anyone point me to the correct call for that? Or reveal some better
solution to the problem?

Thanks,
Eric




^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: Help with windows and 'quit-restore
@ 2017-03-01  7:10 martin rudalics
  2017-03-01 16:09 ` Eric Abrahamsen
  0 siblings, 1 reply; 9+ messages in thread
From: martin rudalics @ 2017-03-01  7:10 UTC (permalink / raw)
  To: eric; +Cc: help-gnu-emacs

 > I'm having a heck of a time understanding how the 'quit-restore window
 > parameter actually works.
 >
 > I've got a pop-up window that goes into special-mode, and I'm trying to
 > get the right level of control over both the window splitting, and the
 > behavior of "q" (quit-window).
 >
 > First it was the "manual way":
 >
 > #+BEGIN_SRC elisp
 > (let* ((buf (get-buffer-I-want-to-pop-up))
 >        (window (get-window-I-want-to-split))
 >        (buffer-window (split-window window 0.5

Do these 0.5 mean that you have advised ‘split-window’?

 >                                     'right)))
 >   (set-window-buffer buffer-window buf)
 >   (display-buffer-record-window 'window buffer-window buf))
 > #+END_SRC
 >
 > The SIZE and SIDE args to `split-window' are calculated elsewhere, just
 > hard-coded in my cut-down example. This allows me to split windows
 > exactly as I want.
 >
 > This call to `display-buffer-record-window', however, does *not* set up
 > the `quit-restore parameter correctly: when I hit "q" in the buffer, the
 > buffer quits but the popped-up window remains, displaying some other
 > buffer, usually a copy of a buffer that's already visible.

It does set up the ‘quit-restore’ parameter correctly.  The one missing
piece is that you didn't clear the new window's previous buffers by
doing something like

(let* ((buf (get-buffer-I-want-to-pop-up))
        (window (get-window-I-want-to-split))
        (buffer-window (split-window window 0.5
                                     'right)))
   (set-window-buffer buffer-window buf)
   (display-buffer-record-window 'window buffer-window buf)
   (set-window-prev-buffers buffer-window nil))

This is a technical issue I can't solve at a lower level: When Emacs
creates a new window, it first displays the buffer displayed in the
selected window in that new window and that buffer becomes the first
"previous" buffer of the new window.  So the new window ("buffer-window"
in your parlance) already showed a buffer _before_ it did show the
buffer you specify by `get-buffer-I-want-to-pop-up´.  In order to make
‘quit-window’ do what you mean, you have to clear that remembrance
first.

I'll probably add a sentence about this to the doc-string of
‘display-buffer-record-window’ although there will be no warranty that
that function will always work outside the scope of ‘display-buffer’.

martin




^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: Help with windows and 'quit-restore
@ 2017-03-01 20:13 martin rudalics
  2017-03-03 19:27 ` Eric Abrahamsen
  0 siblings, 1 reply; 9+ messages in thread
From: martin rudalics @ 2017-03-01 20:13 UTC (permalink / raw)
  To: eric; +Cc: help-gnu-emacs@gnu.org >> GNU Emacs List

 > Whatever the correct technical solution is, both the docs and the code
 > are pretty confusing. I think the key piece of missing information re
 > quit-restore is that, if there's a history of previously-displayed
 > buffers in this window, quitting the displayed buffer will display the
 > next buffer in the history. If there *isn't* such a history, quitting
 > the buffer will delete the window completely.
 >
 > (Is that always true? Are there any other factors that influence this
 > behavior?)

I think it's true.

 > It's a complicated topic, and probably hard to document. The Window
 > History section of the manual mentions previous buffers, but doesn't
 > mentioned the connection to quit-restore behavior.
 >
 > In Quitting Windows, under the description of `quit-restore-window', it
 > says "If WINDOW was created specially for displaying its buffer, this
 > function deletes WINDOW..." When I was writing my functions I read that,
 > but didn't understand what "created specially" meant. My understanding
 > now is that that means there's no previous buffer history, but this
 > documentation makes it sound like this is something that happens at
 > window creation time, not something you can set later.

‘split-window’ has two connotations: The first one is that a user wants
to see two distinct portions of the same buffer.  The second one is that
the user wants to see two different buffers.  In the second case we
emulate a "pristine" history by pretending that the new window never
showed its initial buffer.  And we do that only for ‘display-buffer’ and
its clients because only in those cases we know for sure that the window
should have shown a different buffer right away.

 > Lastly, the quit-restore description in Window Parameters says what the
 > parameter elements *are*, but (for the first two elements at least) not
 > what they *do*.

Right.  I carefully tried to avoid saying that.  Once created, we change
the contents of the ‘quit-restore’ parameter only when we reuse its
window via ‘display-buffer’.  But we may show another buffer in that
window (and change the history of buffers shown in that window) any
time.  So when ‘quit-restore-window’ gets eventually called, it has to
deal with the situation that the ‘quit-restore’ parameter is out of
date, i.e., presumably no more describes the state of things at the time
it was created.  And in that occasion, the history of buffers previously
shown in that window will prevail.

 > Those are three areas where I'd suggest tweaking the docs. I'd be happy
 > to provide specific suggestions or patches.

Please do that.

 > Lastly, as a shot in the dark, mightn't it make sense to allow
 > `display-buffer-record-window' to set the window history? The docstring
 > says the purpose of the function is to install or update the
 > quit-restore parameter -- wouldn't it make sense to let it set the
 > history part of the parameter, too?

Maybe.  But ‘window--display-buffer’ currently does

     (display-buffer-record-window type window buffer) <---
     (unless (eq buffer (window-buffer window))
       (set-window-dedicated-p window nil)
       (set-window-buffer window buffer) <---
       (when dedicated
	(set-window-dedicated-p window dedicated))
       (when (memq type '(window frame))
	(set-window-prev-buffers window nil))) <---

and I'm not sure whether we anywhere might rely on the
‘set-window-prev-buffers’ call following the ‘set-window-buffer’ call.

martin




^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: Help with windows and 'quit-restore
@ 2017-03-04  9:59 martin rudalics
  2017-03-04 17:37 ` Eric Abrahamsen
  0 siblings, 1 reply; 9+ messages in thread
From: martin rudalics @ 2017-03-04  9:59 UTC (permalink / raw)
  To: eric; +Cc: help-gnu-emacs

 > I found the root of the behavior that was making me think I was crazy.
 > Basically I'm trying to replicate the behavior of this call:
 >
 > (display-buffer "some buffer" '(display-buffer-pop-up-window))

The signature of ‘display-buffer’ is

   (display-buffer BUFFER-OR-NAME &optional ACTION FRAME)

while

 > But in a way that I can reliably select which window gets split to show
 > the pop up. (I'd still rather just be using `display-buffer', but that's
 > a different subject.)
 >
 > This should be the lower-level equivalent:
 >
 > (let ((buf "*scratch*")
 >       (new-window
 >        (split-window (selected-window))))
 >   (set-window-buffer new-window buf)
 >   (display-buffer-record-window 'window new-window buf)
 >   (set-window-prev-buffers new-window nil))

that of ‘display-buffer-record-window’ is

(display-buffer-record-window TYPE WINDOW BUFFER)

So the latter has no optional arguments (which is some sort of reminder
that the function is more strict in the interpretation of its arguments)
and uses BUFFER instead of BUFFER-OR-NAME (which means that it does not
allow a buffer name as argument).  This distinction is valuable when
coding with ‘eldoc-mode’: Whenever you see BUFFER-OR-NAME in the
argument list you know you are at the "user" level where more things are
allowed and more things are checked.  When you see plain BUFFER you know
you are at a "coder" level where less things are allowed and less things
are checked.

 > But it doesn't kill the window after calling `quit-window'. This is
 > apparently because `quit-restore-window' decides whether or not to kill
 > the window by checking (window.el:4766):
 >
 > (eq (nth 3 quit-restore) buffer)
 >
 > There's no call to `get-buffer' anywhere down the line, so (nth 3
 > quit-restore) is a buffer string name, while buffer is a buffer object.
 > Ergo, no kill window. If I'd started with a `get-buffer' in the let form
 > above, all would have been well. `display-buffer' calls `get-buffer'
 > first thing, so you don't see it there.

Right.  ‘display-buffer’ is "user" level while
‘display-buffer-record-window’ is "coder" level.  What you do is
"coding" and you are supposed to know what you do.

 > I don't know if this is a bug -- I'm the one insisting on doing it
 > manually, after all -- but it also wouldn't hurt to put a `get-buffer'
 > in `display-buffer-record-window' and ensure that it's always a buffer
 > object that gets recorded in the quit-restore parameter.

I have tried to use BUFFER-OR-NAME and BUFFER in a consistent manner
throughout the window.el code base.  If you compare the current code
with earlier versions you will notice that this required some work.  See
the ‘window-normalize-buffer’ function which interprets nil as meaning
the current buffer and does not allow a string to name a non-existent
buffer.  All these checks are meant for catching user errors and are
redundant at lower levels.  So I'd rather not change that.

 > Or maybe, because the buffer might get deleted at any time, allow a
 > string and improve the check in `quit-restore-window'?

Why?  When calling ‘quit-restore-window’

(buffer (window-buffer window))

will get me a valid buffer while

(nth 3 quit-restore)

will get me a killed buffer so

(eq (nth 3 quit-restore) buffer)

should be

 > Either way, I vote adding some sort of safety.

safe enough.  Don't you agree?

 > I'm still up for doc suggestions, once I'm confident I actually
 > understand what's happening.

We should move our discussion to emcs-devel, also because I'm not
subscribed to help-gnu-emacs.  There you will also find a patch for
bug#25946 which incorporates your earlier proposal to clear the list of
previous buffers in ‘display-buffer-record-window’.

martin




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

end of thread, other threads:[~2017-03-04 17:37 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-28  1:01 Help with windows and 'quit-restore Eric Abrahamsen
2017-03-01  0:57 ` Michael Heerdegen
2017-03-01 16:23   ` Eric Abrahamsen
  -- strict thread matches above, loose matches on Subject: below --
2017-03-01  7:10 martin rudalics
2017-03-01 16:09 ` Eric Abrahamsen
2017-03-01 20:13 martin rudalics
2017-03-03 19:27 ` Eric Abrahamsen
2017-03-04  9:59 martin rudalics
2017-03-04 17:37 ` Eric Abrahamsen

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