unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
@ 2011-09-01 17:46 Eli Zaretskii
  2011-09-03 11:01 ` martin rudalics
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2011-09-01 17:46 UTC (permalink / raw)
  To: 9419

This bug report will be sent to the Bug-GNU-Emacs mailing list
and the GNU bug tracker at debbugs.gnu.org.  Please check that
the From: line contains a valid email address.  After a delay of up
to one day, you should receive an acknowledgement at that address.

Please write in English if possible, as the Emacs maintainers
usually do not have translators for other languages.

Please describe exactly what actions triggered the bug, and
the precise symptoms of the bug.  If you can, give a recipe
starting from `emacs -Q':

 emacs -Q
 M-x list-colors-display RET
 C-x 1
 C-x 5 b *Colors* RET
 C-x b foo RET
 C-x b *Colors* RET
 C-x k

Boom! the frame is deleted, although there's at least one more buffer
(`foo') in that frame's nuffer list.

This happens because window-deletable-p returns `frame' for the window
of the *Colors* buffer.  It does so because that buffer's window's
quit-restore parameter has `new-frame' as its car.  Why is that so, I
don't know; quit-restore doesn't seem to be documented anywhere, only
mentioned in a few doc strings without any explanation.  Perhaps the
reason is that *Colors* was the first buffer on that frame?

If Emacs crashed, and you have the Emacs process in the gdb debugger,
please include the output from the following gdb commands:
    `bt full' and `xbacktrace'.
For information about debugging Emacs, please read the file
d:/gnu/bzr/emacs/trunk/etc/DEBUG.


In GNU Emacs 24.0.50.1 (i386-mingw-nt5.1.2600)
 of 2011-09-01 on HOME-C4E4A596F7
Windowing system distributor `Microsoft Corp.', version 5.1.2600
configured using `configure --with-gcc (3.4) --no-opt'

Important settings:
  value of $LC_ALL: nil
  value of $LC_COLLATE: nil
  value of $LC_CTYPE: nil
  value of $LC_MESSAGES: nil
  value of $LC_MONETARY: nil
  value of $LC_NUMERIC: nil
  value of $LC_TIME: nil
  value of $LANG: ENU
  value of $XMODIFIERS: nil
  locale-coding-system: cp1255
  default enable-multibyte-characters: t

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Recent input:
M-x r e p o r t C-g M-x l i s t - c o l o <tab> <return> 
C-x 1 C-x 5 b * C o l <tab> <return> C-x b f o o <return> 
x C-x b b a r <return> C-x b <up> <up> <up> <return> 
C-x k <return> M-x r e p o r t - e m <tab> <return
>

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
Quit

Load-path shadows:
None found.

Features:
(shadow sort gnus-util mail-extr message format-spec rfc822 mml mml-sec
mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045
ietf-drums mm-util mail-prsvr mailabbrev mail-utils gmm-utils mailheader
emacsbug color help-mode easymenu view time-date tooltip ediff-hook
vc-hooks lisp-float-type mwheel dos-w32 disp-table ls-lisp w32-win
w32-vars tool-bar dnd fontset image fringe lisp-mode register page
menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock
syntax facemenu font-core frame cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer button
faces cus-face files text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget hashtable-print-readable backquote
make-network-process multi-tty emacs)





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-01 17:46 bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer Eli Zaretskii
@ 2011-09-03 11:01 ` martin rudalics
  2011-09-03 11:53   ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: martin rudalics @ 2011-09-03 11:01 UTC (permalink / raw)
  To: 9419-done

 >  emacs -Q
 >  M-x list-colors-display RET
 >  C-x 1
 >  C-x 5 b *Colors* RET
 >  C-x b foo RET
 >  C-x b *Colors* RET
 >  C-x k
 >
 > Boom! the frame is deleted, although there's at least one more buffer
 > (`foo') in that frame's nuffer list.
 >
 > This happens because window-deletable-p returns `frame' for the window
 > of the *Colors* buffer.  It does so because that buffer's window's
 > quit-restore parameter has `new-frame' as its car.  Why is that so, I
 > don't know; quit-restore doesn't seem to be documented anywhere, only
 > mentioned in a few doc strings without any explanation.  Perhaps the
 > reason is that *Colors* was the first buffer on that frame?

*Colors* was the buffer recorded in the quit-restore parameter.  I
installed a fix in revision 105644 and closed the bug.  Please check.

Thanks, martin





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 11:01 ` martin rudalics
@ 2011-09-03 11:53   ` Eli Zaretskii
  2011-09-03 13:54     ` martin rudalics
  2011-09-08  7:02     ` martin rudalics
  0 siblings, 2 replies; 16+ messages in thread
From: Eli Zaretskii @ 2011-09-03 11:53 UTC (permalink / raw)
  To: martin rudalics; +Cc: 9419

> Date: Sat, 03 Sep 2011 13:01:14 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: Eli Zaretskii <eliz@gnu.org>
> 
> *Colors* was the buffer recorded in the quit-restore parameter.  I
> installed a fix in revision 105644 and closed the bug.  Please check.

Thanks.

The original use case seems to work now, i.e. the frame is not
deleted.  The following also works, IIUC the intent:

  emacs -Q
  C-x 5 b foo RET
  C-x k RET

This kills buffer foo and deletes the second frame.  Is this the
intended behavior?

However, this use case looks inconsistent, or maybe I don't understand
the intended behavior:

  emacs -Q
  C-x 5 b foo RET

then in the new frame:

  C-x b bar RET
  C-x b foo RET
  C-x k RET      (kills the foo buffer and shows bar)
  C-x k RET      (kills the bar buffer and shows *scratch*)

My understanding of the intended behavior is that since foo and bar
are the only 2 buffers in that frame's buffer list, the frame should
be deleted after the last one of them is deleted.  But in fact the
frame stays alive and shows *scratch*.

If I kill the buffers in the reverse order, i.e. bar first and then
foo, the frame does get deleted when foo is killed.





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 11:53   ` Eli Zaretskii
@ 2011-09-03 13:54     ` martin rudalics
  2011-09-03 14:20       ` Eli Zaretskii
  2011-09-08  7:02     ` martin rudalics
  1 sibling, 1 reply; 16+ messages in thread
From: martin rudalics @ 2011-09-03 13:54 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 9419

 >   emacs -Q
 >   C-x 5 b foo RET
 >   C-x k RET
 >
 > This kills buffer foo and deletes the second frame.  Is this the
 > intended behavior?

Yes.

 > However, this use case looks inconsistent, or maybe I don't understand
 > the intended behavior:
 >
 >   emacs -Q
 >   C-x 5 b foo RET
 >
 > then in the new frame:
 >
 >   C-x b bar RET
 >   C-x b foo RET
 >   C-x k RET      (kills the foo buffer and shows bar)
 >   C-x k RET      (kills the bar buffer and shows *scratch*)
 >
 > My understanding of the intended behavior is that since foo and bar
 > are the only 2 buffers in that frame's buffer list, the frame should
 > be deleted after the last one of them is deleted.  But in fact the
 > frame stays alive and shows *scratch*.
 >
 > If I kill the buffers in the reverse order, i.e. bar first and then
 > foo, the frame does get deleted when foo is killed.

The problem I originally wanted to solve is the following idiom

(save-window-excursion
   (display-buffer "foo"))

which doesn't DTRT when foo is displayed on a different frame.  My
intention was to solve this with the help of the quit-restore window
parameter (similar to the quit mechanism of help windows in Emacs 23).
For that purpose the buffer shown in the corresponding window must be
the same as when the window was created in order to rule out cases where
the user long time after doing the original display quits the window
showing some different buffer in some way and gets surprised by the
deletion of the window.

I can remove this restriction and kill the buffer in the "kill foo first
and bar afterwards" scenario too, but then I will delete a window always
when all buffers I've ever shown in it have gone.  What do you mean?

martin





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 13:54     ` martin rudalics
@ 2011-09-03 14:20       ` Eli Zaretskii
  2011-09-03 17:29         ` martin rudalics
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2011-09-03 14:20 UTC (permalink / raw)
  To: martin rudalics; +Cc: 9419

> Date: Sat, 03 Sep 2011 15:54:35 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: 9419@debbugs.gnu.org
> 
> The problem I originally wanted to solve is the following idiom
> 
> (save-window-excursion
>    (display-buffer "foo"))
> 
> which doesn't DTRT when foo is displayed on a different frame.

You mean, if display-buffer creates a new frame?  Or that frame
already exists, and display-buffer just raises it and makes it the
selected frame?

And what do you mean by "doesn't DTRT"?  What is TRT in that case?

> My intention was to solve this with the help of the quit-restore
> window parameter (similar to the quit mechanism of help windows in
> Emacs 23).  For that purpose the buffer shown in the corresponding
> window must be the same as when the window was created in order to
> rule out cases where the user long time after doing the original
> display quits the window showing some different buffer in some way
> and gets surprised by the deletion of the window.

Perhaps I'm missing something, but if we are talking about "long time
after", then which buffer causes frame deletion is immaterial: they
both will cause the same amount of surprise.

This is actually how I bumped into this problem in the first place.  I
have a frame where I switch between different *info*<n> buffers
showing various manuals, using the info-display-manual command.
Whenever the Emacs or ELisp manuals are rebuilt (because they are
updated on the trunk), I kill the corresponding buffer and re-read
that manual anew.  When I started using Emacs 24, I was surprised to
find out that this sometimes, but not always, deleted the entire
frame.  I now understand that this depends on which buffer I was
killing and in what order, but believe me: the surprise was complete,
and the apparently inconsistent behavior only added to it.

> I can remove this restriction and kill the buffer in the "kill foo first
> and bar afterwards" scenario too, but then I will delete a window always
> when all buffers I've ever shown in it have gone.  What do you mean?

I can see 3 possible ways to have a consistent behavior:

 . Never delete a frame except by an explicit call to delete-frame.  I
   think this is what Emacs 23 did, so it is also backward-compatible.

 . A minor variation on the above: never delete a frame, except when
   it was created by display-buffer, and never had more than one
   buffer in its buffer list.  IIUC the use case you were trying to
   fix, this will fix it.

 . Always delete a frame whenever the last buffer in its buffer list
   is killed.  This is a change in behavior wrt Emacs 23, so it should
   probably be conditional on some option.

Anything else is inconsistent, IMO, and inconsistency is always worse
than any consistent alternative, in my experience.

Thanks.





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 14:20       ` Eli Zaretskii
@ 2011-09-03 17:29         ` martin rudalics
  2011-09-03 17:44           ` Eli Zaretskii
  2011-09-06 13:06           ` Stefan Monnier
  0 siblings, 2 replies; 16+ messages in thread
From: martin rudalics @ 2011-09-03 17:29 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 9419

 >> The problem I originally wanted to solve is the following idiom
 >>
 >> (save-window-excursion
 >>    (display-buffer "foo"))
 >>
 >> which doesn't DTRT when foo is displayed on a different frame.
 >
 > You mean, if display-buffer creates a new frame?  Or that frame
 > already exists, and display-buffer just raises it and makes it the
 > selected frame?
 >
 > And what do you mean by "doesn't DTRT"?  What is TRT in that case?

In the idiom above, when a user has `pop-up-frames' nil, a new window
showing the buffer gets created on the selected frame and gets deleted
when the window excursion terminates.  When a user has `pop-up-frames'
non-nil and a new frame gets created that frame is not deleted.  This
fact has already caused some vivid discussions here.  IMO TRT is to
treat windows and frames the same.

 > Perhaps I'm missing something, but if we are talking about "long time
 > after", then which buffer causes frame deletion is immaterial: they
 > both will cause the same amount of surprise.

Precisely this mechanism is inherent to help frames you quit with "q" in
Emacs 23.  Quitting any other buffer in such a frame would not cause its
deletion.

 > This is actually how I bumped into this problem in the first place.  I
 > have a frame where I switch between different *info*<n> buffers
 > showing various manuals, using the info-display-manual command.
 > Whenever the Emacs or ELisp manuals are rebuilt (because they are
 > updated on the trunk), I kill the corresponding buffer and re-read
 > that manual anew.  When I started using Emacs 24, I was surprised to
 > find out that this sometimes, but not always, deleted the entire
 > frame.  I now understand that this depends on which buffer I was
 > killing and in what order, but believe me: the surprise was complete,
 > and the apparently inconsistent behavior only added to it.

You should have protested immediately.

 >> I can remove this restriction and kill the buffer in the "kill foo first
 >> and bar afterwards" scenario too, but then I will delete a window always
 >> when all buffers I've ever shown in it have gone.  What do you mean?
 >
 > I can see 3 possible ways to have a consistent behavior:
 >
 >  . Never delete a frame except by an explicit call to delete-frame.  I
 >    think this is what Emacs 23 did, so it is also backward-compatible.

There are two exceptions in Emacs 23 to this rule - help frames and
dedicated frames.

 >  . A minor variation on the above: never delete a frame, except when
 >    it was created by display-buffer, and never had more than one
 >    buffer in its buffer list.  IIUC the use case you were trying to
 >    fix, this will fix it.

Tracking the "never had more than one buffer" is tedious but could be
done.

 >  . Always delete a frame whenever the last buffer in its buffer list
 >    is killed.  This is a change in behavior wrt Emacs 23, so it should
 >    probably be conditional on some option.

It is: Setting `frame-auto-delete' to nil should inhibit implicit
deletion of frames.  But it won't inhibit implicit deletion of windows,
something hardly anyone has noticed (Juanma is the only one who suffers
from it so far).

 > Anything else is inconsistent, IMO, and inconsistency is always worse
 > than any consistent alternative, in my experience.

I can do whatever people want.  But consistency should also cover the
window/frame dichotomy.

martin





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 17:29         ` martin rudalics
@ 2011-09-03 17:44           ` Eli Zaretskii
  2011-09-03 19:27             ` Eli Zaretskii
  2011-09-06 13:06           ` Stefan Monnier
  1 sibling, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2011-09-03 17:44 UTC (permalink / raw)
  To: martin rudalics; +Cc: 9419

> Date: Sat, 03 Sep 2011 19:29:29 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: 9419@debbugs.gnu.org
> 
>  >> (save-window-excursion
>  >>    (display-buffer "foo"))
>  >>
>  >> which doesn't DTRT when foo is displayed on a different frame.
>  >
>  > You mean, if display-buffer creates a new frame?  Or that frame
>  > already exists, and display-buffer just raises it and makes it the
>  > selected frame?
>  >
>  > And what do you mean by "doesn't DTRT"?  What is TRT in that case?
> 
> In the idiom above, when a user has `pop-up-frames' nil, a new window
> showing the buffer gets created on the selected frame and gets deleted
> when the window excursion terminates.  When a user has `pop-up-frames'
> non-nil and a new frame gets created that frame is not deleted.  This
> fact has already caused some vivid discussions here.  IMO TRT is to
> treat windows and frames the same.

Agreed.

>  > Perhaps I'm missing something, but if we are talking about "long time
>  > after", then which buffer causes frame deletion is immaterial: they
>  > both will cause the same amount of surprise.
> 
> Precisely this mechanism is inherent to help frames you quit with "q" in
> Emacs 23.  Quitting any other buffer in such a frame would not cause its
> deletion.

That sucks, IMO.

>  > This is actually how I bumped into this problem in the first place.  I
>  > have a frame where I switch between different *info*<n> buffers
>  > showing various manuals, using the info-display-manual command.
>  > Whenever the Emacs or ELisp manuals are rebuilt (because they are
>  > updated on the trunk), I kill the corresponding buffer and re-read
>  > that manual anew.  When I started using Emacs 24, I was surprised to
>  > find out that this sometimes, but not always, deleted the entire
>  > frame.  I now understand that this depends on which buffer I was
>  > killing and in what order, but believe me: the surprise was complete,
>  > and the apparently inconsistent behavior only added to it.
> 
> You should have protested immediately.

Believe it or not, this bug report is my "immediate" protest ;-)  It
took time for me to realize that the frame deletion was not due to
some cockpit error on my part, and then some more time to create a
simple recipe suitable for submission.

>  > I can see 3 possible ways to have a consistent behavior:
>  >
>  >  . Never delete a frame except by an explicit call to delete-frame.  I
>  >    think this is what Emacs 23 did, so it is also backward-compatible.
> 
> There are two exceptions in Emacs 23 to this rule - help frames and
> dedicated frames.
> 
>  >  . A minor variation on the above: never delete a frame, except when
>  >    it was created by display-buffer, and never had more than one
>  >    buffer in its buffer list.  IIUC the use case you were trying to
>  >    fix, this will fix it.
> 
> Tracking the "never had more than one buffer" is tedious but could be
> done.
> 
>  >  . Always delete a frame whenever the last buffer in its buffer list
>  >    is killed.  This is a change in behavior wrt Emacs 23, so it should
>  >    probably be conditional on some option.
> 
> It is: Setting `frame-auto-delete' to nil should inhibit implicit
> deletion of frames.

So I think the second alternative is the best, if it is doable.

> But it won't inhibit implicit deletion of windows, something hardly
> anyone has noticed (Juanma is the only one who suffers from it so
> far).

I did notice that.  I just didn't yet make up my mind whether I like
it or not.

> I can do whatever people want.  But consistency should also cover the
> window/frame dichotomy.

Agreed.

So how about this plan:

  . Never delete a frame, except when it was created by
    display-buffer, and never had more than one buffer in its buffer
    list.

  . Do the same with windows created by display-buffer: if the user
    switched buffers in that window, don't delete the window when the
    excursion ends.

  . Introduce a window-auto-delete option, by default set the same as
    frame-auto-delete, to control window deletion like
    frame-auto-delete controls that of frames.  Alternatively,
    deprecate frame-auto-delete and introduce a new
    frame-and-window-auto-delete with the old one its alias.  Then
    make this new option control both window and frame auto-deletion
    alike.






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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 17:44           ` Eli Zaretskii
@ 2011-09-03 19:27             ` Eli Zaretskii
  2011-09-04 10:34               ` martin rudalics
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2011-09-03 19:27 UTC (permalink / raw)
  To: rudalics; +Cc: 9419

> Date: Sat, 03 Sep 2011 20:44:09 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: 9419@debbugs.gnu.org
> 
> So how about this plan:
> 
>   . Never delete a frame, except when it was created by
>     display-buffer, and never had more than one buffer in its buffer
>     list.
> 
>   . Do the same with windows created by display-buffer: if the user
>     switched buffers in that window, don't delete the window when the
>     excursion ends.
> 
>   . Introduce a window-auto-delete option, by default set the same as
>     frame-auto-delete, to control window deletion like
>     frame-auto-delete controls that of frames.  Alternatively,
>     deprecate frame-auto-delete and introduce a new
>     frame-and-window-auto-delete with the old one its alias.  Then
>     make this new option control both window and frame auto-deletion
>     alike.

On second though, if we are trying to fix the specific use case of
save-window-excursion, why not solve it on the level of
save-window-excursion?  That is, let save-window-excursion keep track
of the window/frame created by display-buffer, and then delete that
window/frame when the excursion ends.

If this will solve the original problem, we can leave the behavior of
kill-buffer etc. as it was in Emacs 23.

WDYT?





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 19:27             ` Eli Zaretskii
@ 2011-09-04 10:34               ` martin rudalics
  2011-09-04 16:28                 ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: martin rudalics @ 2011-09-04 10:34 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 9419

 >> Precisely this mechanism is inherent to help frames you quit with "q" in
 >> Emacs 23.  Quitting any other buffer in such a frame would not cause its
 >> deletion.
 >
 > That sucks, IMO.

It's around for almost four years by now and apparently nobody noticed
the problem so far.

 >>  >  . A minor variation on the above: never delete a frame, except when
 >>  >    it was created by display-buffer, and never had more than one
 >>  >    buffer in its buffer list.  IIUC the use case you were trying to
 >>  >    fix, this will fix it.
 >>
 >> Tracking the "never had more than one buffer" is tedious but could be
 >> done.
 >>
 >>  >  . Always delete a frame whenever the last buffer in its buffer list
 >>  >    is killed.  This is a change in behavior wrt Emacs 23, so it should
 >>  >    probably be conditional on some option.
 >>
 >> It is: Setting `frame-auto-delete' to nil should inhibit implicit
 >> deletion of frames.
 >
 > So I think the second alternative is the best, if it is doable.

You mean the "never had more than one buffer" one?

 >   . Never delete a frame, except when it was created by
 >     display-buffer, and never had more than one buffer in its buffer
 >     list.
 >
 >   . Do the same with windows created by display-buffer: if the user
 >     switched buffers in that window, don't delete the window when the
 >     excursion ends.

Detecting whether "the user switched buffers in that window" appears not
entirely trivial.  Earlier, I planned to divide functions into two
groups: The `switch-to-buffer' group would have been entirely left to
the user, while the `pop-to-buffer' group would have been left to the
applications.  In that case we could have made the `switch-to-buffer'
functions reset the quit-restore parameter.  Maybe we could achieve
something similar by testing `called-interactively-p' now.

 >   . Introduce a window-auto-delete option, by default set the same as
 >     frame-auto-delete, to control window deletion like
 >     frame-auto-delete controls that of frames.  Alternatively,
 >     deprecate frame-auto-delete and introduce a new
 >     frame-and-window-auto-delete with the old one its alias.  Then
 >     make this new option control both window and frame auto-deletion
 >     alike.

`frame-auto-delete' is just a more general version of
`view-remove-frame-by-deleting'.  I'd use an option say
`window-auto-delete' with the values nil (for not deleting anything),
window (for deleting only a window and leaving a frame alone), frame
(for deleting only a frame and leaving a window alone), and t (for
deleting window and/or frame, whichever is applicable).

 > On second though, if we are trying to fix the specific use case of
 > save-window-excursion, why not solve it on the level of
 > save-window-excursion?  That is, let save-window-excursion keep track
 > of the window/frame created by display-buffer, and then delete that
 > window/frame when the excursion ends.
 >
 > If this will solve the original problem, we can leave the behavior of
 > kill-buffer etc. as it was in Emacs 23.

What I tried was not to fix the use case of `save-window-excursion'
alone but handle that case just as if it were a special case of a help
window.  Trying to handle the `save-window-excursion' case separately
won't remove the "That sucks, IMO" case you bemoaned above.

Anyway - let me shortly try to summarize the problem: Initially there
was a problem with help windows and view mode and the fact that it
wasn't possible to "exit" help windows cleanly.  I tried to solve that
back in 2007 using the `with-help-window' macro and the problems
disappeared.

Then two things happened: Stefan wanted me to rewrite the macro because
it contained ugly code.  And there were protests about `display-buffer'
not DTRT within `save-window-excursion'.  I tried to meet both issues by
installing the quit-restore window parameter (I didn't clean up any of
the window excursions yet though).

Now there are at quite a number of ways to get rid of a buffer in a
window: `bury-buffer', `kill-buffer' (which calls
`replace-buffer-in-windows'), `quit-window', and `delete-windows-on'
(the latter is interesting only in the special case where one of these
windows is the only window on its frame).  I tried to make them behave
in a consistent way which, however, might have been a bad idea in the
first place.

Note also that Stefan always favored a solution based on dedicated
windows: Such windows get automatically deleted and/or the frame
iconified.  But dedicated windows cannot handle the case where a window
got reused for showing the buffer and present difficulties when a window
shall be reused for showing another buffer.

Some of these problems might stem from the fact that `display-buffer' is
now used for creating fairly permanent windows (like when you call it
via `find-file' or `switch-to-buffer') and for fairly temporary windows
(like when you call it via `with-output-to-temp-buffer').  The expected
exit behavior of such windows seems different.

martin





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-04 10:34               ` martin rudalics
@ 2011-09-04 16:28                 ` Eli Zaretskii
  2011-09-06 13:17                   ` Stefan Monnier
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2011-09-04 16:28 UTC (permalink / raw)
  To: martin rudalics; +Cc: 9419

> Date: Sun, 04 Sep 2011 12:34:59 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: 9419@debbugs.gnu.org
> 
>  >> Precisely this mechanism is inherent to help frames you quit with "q" in
>  >> Emacs 23.  Quitting any other buffer in such a frame would not cause its
>  >> deletion.
>  >
>  > That sucks, IMO.
> 
> It's around for almost four years by now and apparently nobody noticed
> the problem so far.

Then maybe we can live with it a bit longer.

>  > So I think the second alternative is the best, if it is doable.
> 
> You mean the "never had more than one buffer" one?

Yes.  But see below.

>  > On second though, if we are trying to fix the specific use case of
>  > save-window-excursion, why not solve it on the level of
>  > save-window-excursion?  That is, let save-window-excursion keep track
>  > of the window/frame created by display-buffer, and then delete that
>  > window/frame when the excursion ends.
>  >
>  > If this will solve the original problem, we can leave the behavior of
>  > kill-buffer etc. as it was in Emacs 23.
> 
> What I tried was not to fix the use case of `save-window-excursion'
> alone but handle that case just as if it were a special case of a help
> window.  Trying to handle the `save-window-excursion' case separately
> won't remove the "That sucks, IMO" case you bemoaned above.

You have convinced me now that a solution to the more general case is
orders of magnitude more complex for which TRT is not at all clear,
what with all the possible ways to create and get rid of windows,
whereas save-window-excursion is a very simple use case where the
correct behavior is both very clear and is probably simple to
implement.

So I'd say let's solve that, and leave the rest for a future version.

Stefan and Chong, would you please chime in and tell if you agree?





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 17:29         ` martin rudalics
  2011-09-03 17:44           ` Eli Zaretskii
@ 2011-09-06 13:06           ` Stefan Monnier
  2011-09-08  7:02             ` martin rudalics
  1 sibling, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2011-09-06 13:06 UTC (permalink / raw)
  To: martin rudalics; +Cc: 9419

>> I can see 3 possible ways to have a consistent behavior:
>> . Never delete a frame except by an explicit call to delete-frame.  I
>> think this is what Emacs 23 did, so it is also backward-compatible.
> There are two exceptions in Emacs 23 to this rule - help frames and
> dedicated frames.
>> . A minor variation on the above: never delete a frame, except when
>> it was created by display-buffer, and never had more than one
>> buffer in its buffer list.  IIUC the use case you were trying to
>> fix, this will fix it.
> Tracking the "never had more than one buffer" is tedious but could be
> done.

Actually, soft-dedicated windows do just that.  Tho they also have one
side-effect, which is to prevent display-buffer from reusing that window.

So what we're trying to do here can be seen as a yet-weaker form of
dedication which does not prevent the reuse of a buffer by
display-buffer.


        Stefan





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-04 16:28                 ` Eli Zaretskii
@ 2011-09-06 13:17                   ` Stefan Monnier
  2011-09-08  7:02                     ` martin rudalics
  0 siblings, 1 reply; 16+ messages in thread
From: Stefan Monnier @ 2011-09-06 13:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 9419

>> > On second though, if we are trying to fix the specific use case of
>> > save-window-excursion, why not solve it on the level of
>> > save-window-excursion?

I think we first need to decide what use case we want to fix:
- the use of save-window-excursion is normally for "I want to run this
  code which fiddles with the windows, but I don't want it to fiddle
  with the windows".  I.e. unless the code really only fiddles with
  windows and never with frames it is actually a bug since you can't
  fully undo frame operations (they're visible to the user before we
  get to try and undo them).
- the use of "get current-window-configuration, store it in a global var,
  give the hand back to the user, at some later time, call
  set-window-configuration".  This is not a good solution since it
  assumes that the user works in a strict nesting way, whereas in
  practice (and with frames even more so), the user may interleave two
  or more activities, so the set-window-configuration may end up
  deleting/resetting windows in undesired ways.

So the problem is really not in how those primitives are implemented,
but in the functionality offered by those primitives.


        Stefan





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-03 11:53   ` Eli Zaretskii
  2011-09-03 13:54     ` martin rudalics
@ 2011-09-08  7:02     ` martin rudalics
  2011-09-09  9:16       ` Eli Zaretskii
  1 sibling, 1 reply; 16+ messages in thread
From: martin rudalics @ 2011-09-08  7:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 9419

 > However, this use case looks inconsistent, or maybe I don't understand
 > the intended behavior:
 >
 >   emacs -Q
 >   C-x 5 b foo RET
 >
 > then in the new frame:
 >
 >   C-x b bar RET
 >   C-x b foo RET
 >   C-x k RET      (kills the foo buffer and shows bar)
 >   C-x k RET      (kills the bar buffer and shows *scratch*)
 >
 > My understanding of the intended behavior is that since foo and bar
 > are the only 2 buffers in that frame's buffer list, the frame should
 > be deleted after the last one of them is deleted.  But in fact the
 > frame stays alive and shows *scratch*.
 >
 > If I kill the buffers in the reverse order, i.e. bar first and then
 > foo, the frame does get deleted when foo is killed.

I hopefully made these cases consistent now.  In addition, the option
`window-auto-delete' can be used to tune down auto-deletion if wanted.

martin





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-06 13:17                   ` Stefan Monnier
@ 2011-09-08  7:02                     ` martin rudalics
  0 siblings, 0 replies; 16+ messages in thread
From: martin rudalics @ 2011-09-08  7:02 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 9419

 > - the use of save-window-excursion is normally for "I want to run this
 >   code which fiddles with the windows, but I don't want it to fiddle
 >   with the windows".  I.e. unless the code really only fiddles with
 >   windows and never with frames it is actually a bug since you can't
 >   fully undo frame operations (they're visible to the user before we
 >   get to try and undo them).

My principal problem with `save-window-excursion' is that it undoes my
changes to the configuration too.  Hence, unless it remains restricted
to modal windows, I find `save-window-excursion' distracting.

 > - the use of "get current-window-configuration, store it in a global var,
 >   give the hand back to the user, at some later time, call
 >   set-window-configuration".  This is not a good solution since it
 >   assumes that the user works in a strict nesting way, whereas in
 >   practice (and with frames even more so), the user may interleave two
 >   or more activities, so the set-window-configuration may end up
 >   deleting/resetting windows in undesired ways.

This is even worse than `save-window-excursion'.  In particular when
buffers got killed in between.

martin





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-06 13:06           ` Stefan Monnier
@ 2011-09-08  7:02             ` martin rudalics
  0 siblings, 0 replies; 16+ messages in thread
From: martin rudalics @ 2011-09-08  7:02 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 9419

 > So what we're trying to do here can be seen as a yet-weaker form of
 > dedication which does not prevent the reuse of a buffer by
 > display-buffer.

That would be a solution.  Just that it does not handle the case when a
window gets reused for displaying the buffer.  In particular, we would
have to also save/restore the dedicated status of such windows.

martin





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

* bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer
  2011-09-08  7:02     ` martin rudalics
@ 2011-09-09  9:16       ` Eli Zaretskii
  0 siblings, 0 replies; 16+ messages in thread
From: Eli Zaretskii @ 2011-09-09  9:16 UTC (permalink / raw)
  To: martin rudalics; +Cc: 9419

> Date: Thu, 08 Sep 2011 09:02:00 +0200
> From: martin rudalics <rudalics@gmx.at>
> CC: 9419@debbugs.gnu.org
> 
>  >   emacs -Q
>  >   C-x 5 b foo RET
>  >
>  > then in the new frame:
>  >
>  >   C-x b bar RET
>  >   C-x b foo RET
>  >   C-x k RET      (kills the foo buffer and shows bar)
>  >   C-x k RET      (kills the bar buffer and shows *scratch*)
>  >
>  > My understanding of the intended behavior is that since foo and bar
>  > are the only 2 buffers in that frame's buffer list, the frame should
>  > be deleted after the last one of them is deleted.  But in fact the
>  > frame stays alive and shows *scratch*.
>  >
>  > If I kill the buffers in the reverse order, i.e. bar first and then
>  > foo, the frame does get deleted when foo is killed.
> 
> I hopefully made these cases consistent now.

Yes, thanks.





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

end of thread, other threads:[~2011-09-09  9:16 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-01 17:46 bug#9419: 24.0.50; C-x k deletes the entire frame instead of switching to another buffer Eli Zaretskii
2011-09-03 11:01 ` martin rudalics
2011-09-03 11:53   ` Eli Zaretskii
2011-09-03 13:54     ` martin rudalics
2011-09-03 14:20       ` Eli Zaretskii
2011-09-03 17:29         ` martin rudalics
2011-09-03 17:44           ` Eli Zaretskii
2011-09-03 19:27             ` Eli Zaretskii
2011-09-04 10:34               ` martin rudalics
2011-09-04 16:28                 ` Eli Zaretskii
2011-09-06 13:17                   ` Stefan Monnier
2011-09-08  7:02                     ` martin rudalics
2011-09-06 13:06           ` Stefan Monnier
2011-09-08  7:02             ` martin rudalics
2011-09-08  7:02     ` martin rudalics
2011-09-09  9:16       ` Eli Zaretskii

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