bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#11939: 24.1; `save-buffers-kill-emacs' loses minibuffer focuswhenit


From: Drew Adams
Subject: bug#11939: 24.1; `save-buffers-kill-emacs' loses minibuffer focuswhenit calls `list-processes'
Date: Fri, 3 Aug 2012 09:46:53 -0700

> The problem happens in the following scenario:
> 
> (1) The application requests (implicitly) to make a new frame.
> 
> (2) The application ask to read from the minibuffer with some 
>     old frame selected.  In this case the statement above does not 
>     redirect focus because either the old frame is the minibuffer
>     frame or the old frame's focus is already redirected to the
>     minibuffer frame.
> 
> (3) Emacs eventually selects the new frame in `handle-switch-frame'.
> 
> After that, the new frame gets the keystrokes for reading from the
> minibuffer but Emacs won't find a redirection in kbd_buffer_get_event.

Agreed; that is what we have been discussing.

> the idea of doing
> (when (eq (selected-frame)
>           (window-frame (minibuffer-window)))
> 
> means that when you pop up a new frame when a non-minibuffer frame is
> selected you never redirect, while you always redirect when the
> minibuffer frame is selected.  This conditioning cannot always work
> correctly IMHO.

Which is what I said in my last message.  It must not be done systematically.  I
gave the counter-example of a *Backtrace* frame.

It is only the code that is calling for such a user dialog that knows that that
is what is being called for.  By "such a user dialog", again, I mean (a) the
display of a buffer for information only, i.e., one that does not need the input
focus, and (b) request of user input with the previous buffer remaining current
and the minibuffer having the input focus.

That is the use case that is problematic.  It is the case where the above
systematic "fix" is inappropriate.  There might be other such use cases, but it
is the only one I have encountered.  And I have encountered it in several
different places (e.g., Dired *Marked Files* popup, *Process List* popup).

My suggestion is, again, that we try to come up with a construct that covers
this use case, and then use it in the appropriate places: places where we do (a)
+ (b).

On the other hand, if you know of a way to _detect_ such an intention on the
part of the developer, i.e., somehow _detect_ whether the displayed buffer
should have input focus, then I'm all ears.

I don't expect that to be possible, which is why I propose that the developer
make the intention explicit by using a new construct (e.g. a macro) that takes
care of this.

The construct would display the informational buffer and redirect its input
focus to a standalone minibuffer, if there is one.  If there is no standalone
minibuffer frame, then that part could be a no-op, AFAICT.  Something like this:

(with-unfocused-buffer-displayed BUFFER &body BODY)

where BUFFER is displayed for information only, and where BODY would include the
call(s) that read from the minibuffer.

The current buffer would remain what it was beforehand, and _if_ BUFFER gets
displayed in its own frame and _if_ there is a standalone minibuffer frame,
_then_ the focus for BUFFER's frame gets automatically redirected to the
minibuffer frame.  If those conditions do not hold then there is no special
handling needed - the construct can essentially be a no-op in that case
(AFAICT).

How something like this would be implemented I'm not sure.  When the redirection
would need to take place, to DTRT, I'm not sure.  Perhaps it would need to be
done more than once.

But an important further requirement is that nothing should prevent Emacs code
in BODY or called from within BODY from switching the input focus to BUFFER's
frame.  Likewise, nothing should prevent the user from explicitly switching the
focus to BUFFER's frame.

The only switching of focus to BUFFER's frame that this construct would be
trying to prevent would be something that comes from neither a user action nor
the Emacs code - in particular, MS Windows auto-focussing a newly created frame.

Again, I don't know the "how".  But (so far) I'm convinced that this has to be
an explicit Emacs construct: there needs to be some way for a Lisp programmer to
communicate the intention that BUFFER is not intended to have the input focus
during BODY (unless that is done by the user or by code within BODY).

I do not expect that the problematic use case we've been discussing can be
detected and dealt with correctly in an automatic way.  If the programmer
intention cannot be made explicit then there is no way to know what TRT is.

It's problematic enough even with the intention communicated, in the sense that
we need to allow users and Emacs code to give focus to BUFFER's frame if they
want to.  IOW, even if we _know_ that initially BUFFER's frame should not be
focused, it is hard enough to prevent or undo focusing by MS Windows while still
allowing users and Emacs to focus BUFFER.

>  >>  > That's the best thing I've come up with, but perhaps you
>  >>  > have a suggestion.  `after-make-frame-functions' seems
>  >>  > like the right place to do the deed, because it knows
>  >>  > about the new frame, which is the one whose focus needs
>  >>  > to be redirected.
>  >
>  > I want to say "ONLY IT knows..." (among existing hooks), but I am not
>  > sure of that.  IOW, of the hooks I am aware of, this one seems the 
>  > most pertinent here.
> 
> It knows that a new frame will be constructed.  But it does not know
> whether focus shall be redirected.

That's the point of providing programmers with a construct to express that
intention explicitly: "This buffer's frame, if it is displayed in its own frame,
should not receive the focus."

>  >>  > Again, this all seems to underline the need for a
>  >>  > notion/mechanism of defining or detecting a user dialog
>  >
>  > I think you are probably right that "detecting" might be a 
>  > pipe dream.  What I really have had in mind is mentioned above:
>  > the code would encapsulate a minibuffer reading that might
>  > pop up an informational window,

By "might pop up" I meant that _if_ informational BUFFER is popped up in its own
frame, _then_ the intention is that that frame not receive the input focus.

>  > redirecting focus for any new frames to the minibuffer.
> 
> And what you have in mind here should be distinguishable from other
> things that pop up frames but do not want the redirection.

Not sure I follow you.  Are you referring to the equivalent of possibly nested
`with-unfocused-buffer-displayed' calls?

Here's the thing.  I don't know whether we can come up with something that is
100% reliable.  But the important thing, I think, is to have _some_ programmatic
translation of the programmer intention that this BUFFER be shown without giving
it the input focus.

Today there is no way for a programmer to indicate that.  S?he might not
_expect_ that the focus would be grabbed away from a minibuffer frame and given
to a new frame, but that lack of expectation today is mainly based on
inexperience with a standalone minibuffer and MS Windows.

What's needed is some way to reinforce the programmer's natural expectation that
the user can in fact type input into the minibuffer even when the informational
buffer gets displayed.

No one would naturally expect that not to be the case, but it can be the case,
unfortunately.  So the idea is to somehow support the natural expectation and
take away the possibility (or reduce the probability) of MS Windows interfering
with what should be a simple user dialog.

>  >>  > that uses the minibuffer while popping up an informational
>  >>  > frame only for the duration of the minibuffer interaction
>  >>  > (input).
>  >
>  > The important point here is "informational...only".
>  >
>  > And this is where I need to mention an example of why it 
>  > is not a solution to do this redirection systematically, testing only
>  > (when (eq (selected-frame) (window-frame (minibuffer-window))).
>  >
>  > A case in point is the debugger.  In my setup *Backtrace* 
>  > pops up in a special-display frame.  It is not the case that this 
>  > buffer is for information only.  It is truly necessary that
>  > *Backtrace* receive the focus.
> 
> Is it?  I never gave it a thought.

Yes, it seems to be necessary.  The proof being that when I applied my partly
misguided "fix" systematically the *Backtrace* frame lost the focus to the
minibuffer frame and I could not use it.  I had to click the *Backtrace* frame
to give it back the focus.

> But I perfectly understand that when *Backtrace* pops up you
> don't want to redirect focus to the minibuffer frame.

Correct.  *Backtrace* is not popped up for info only.  It is popped up for
interacting with the user.  It is supposed to have the input focus, even if it
is popped during a minibuffer interaction.

Note that this is not really an example of what I meant above by Emacs code
within BODY being able to switch focus to BUFFER, because *Backtrace* would not
be invoked using `with-unfocused-buffer-displayed'.  It is not the intention
that it be displayed for info only.

But it is an example of why systematically redirecting the focus to the
minibuffer frame from any new frame that pops up when the minibuffer is active
is not TRT.

>  > So this is a good case where my redirection "fix" does not do
>  > the right thing.
> 
> If you hardwire redirection in `after-make-frame-functions', 
> you get bad results in the case where the redirection is not wanted.

Correct.  That is what I was saying too.  Systematic or hard-wire is not
appropriate.

The first lesson (for me) was learning that it can only be appropriate when the
minibuffer is active.  The second lesson was that even when the minibuffer is
active it might not be appropriate.

In the end, it is only the programmer who knows whether some buffer that is
popped up should be denied the input focus.

> What you want is some clairvoyance in step (1) of my description
> above whether step (2) will be performed.

No, I don't think so.  I don't believe in such clairvoyance (but I'm open to
being convinced).  Instead, I believe in the programmer stating that the buffer
is not intended to have the focus.  (But that nothing should prevent Emacs or
the user from giving it the focus at some point.)

> `with-temp-buffer-window' avoids that by asking the `yes-or-no-p'
> question in the new frame.

The issue at stake is the case of a standalone minibuffer.  I don't see any
problem if there is no standalone minibuffer frame.

With a standalone minibuffer frame, the proper behavior is for the minibuffer
frame to be used for all minibuffer activity.  Anything else is less than
desirable, even if it might be acceptable if no better solution could be found
in some case.

A user of a standalone minibuffer looks there for all echo-area output and all
minibuffer input.  That is one of the reasons for using a standalone minibuffer:
a single place where all Q & A with the user takes place.

Well, nearly all.  Yes, there are some times where things like `read-event' are
used instead of the minibuffer.  But let's not get pedantic; this is about use
of the minibuffer and echo area.  A standalone minibuffer offers the advantage
of always looking to the same place on the screen for user I/O.

> Older application don't and that's our trouble.

That's one problem.  Admittedly, that can be looked at as a nice-to-have, and I
might be the only person who cares much about that.

The other potential trouble is the need to show an informational buffer that
does not necessarily correspond to what you have defined for
`with-temp-buffer-window'.

To be clear, I do not know whether such a need exists much in practice.  But it
looks to me like your macro and the related code you sent make additional
assumptions about the buffer that is popped up that constrain it more than what
I was describing abstractly for the hypothetical
`with-unfocused-buffer-displayed'.

The buffer in the case of `with-temp-buffer-window' starts out from scratch (it
must be empty), etc.  In a nutshell, your construct assumes that the buffer
itself is temporary, whereas the only real need for our problematic use case is
that the buffer's _display_, in a separate frame, be temporary.

IOW, I think your solution is more constraining/limited and doesn't really
address the general problem, which is that of displaying _any_ buffer for only
informational use (at least initially, allowing for user/code to intentionally
switch focus to it).  And AFAIK the problem we are trying to solve occurs only
when such a buffer appears in its own frame.

Your solution certainly helps for things like *Process List* and *Marked Files*.
But the characterization of the problem is, logically, in terms of a buffer that
is displayed temporarily during a minibuffer dialog, in its own frame, and whose
frame should not have the input focus in that context.

Am I wrong about that?

Don't get me wrong.  I think your code (the little that I've tried using it) is
a definite improvement for the problem cases we've actually encountered, which
are in fact not only temporary displays of a buffer but also displays of a
temporary buffer.

I'm just saying that I think the problem of MS Windows giving the focus to a new
frame that gets popped during a minibuffer interaction, where that new frame
should not have the focus, i.e., where its buffer is shown only for information,
is more general than the show-a-temporary-buffer case you have treated.

At least that's what I think so far.  You'll tell me if I'm wrong.

>  > It is only the code that invokes reading from the minibuffer
>  > and pops up the other window/frame that can know whether the
>  > focus should be in that window/frame or in the minibuffer.
> 
> It's not that simple. The invoking code doesn't care about focus

It does care.  Maybe what you mean is that it does not expect the focus to be
messed with by MS Windows.

Typically, such code simply does not expect (take into account) a scenario where
the user (a) has a standalone minibuffer frame, (b) has the buffer in question
be popped up in its own frame, and (c) is on MS Windows, which steals the input
focus and gives it to the new frame.

But the code does expect the minibuffer to have the focus, and it knows that the
buffer is shown only for informational purposes, i.e., the buffer does not need
(and should not have) the input focus.

The code does not, today, explicitly express that intention/care, because
outside of the problematic case of (a), (b), and (c), which today is not that
common, there is no need to express and handle that intention.  IOW it cares,
but its cares are already taken care of automatically in most cases.

> and in particular not about some frame whose eventually popping
> up will cause problems.  It expects the reading from the minibuffer
> mechanism DTRT.

Precisely.  And except for the problematic case, there has never been any need
for the programmer to make clear the fact (intention) that the buffer is
informational only.

You have encapsulated precisely that intention in your code.  But you have gone
beyond that and expressed the additional intention that the buffer be temporary.

That's fine, but it is less general: there are (at least logically) problematic
cases that it does not solve, namely, popping up an existing, non-temporary
buffer temporarily during a minibuffer query of the user.

>  > But here's the thing: in the case of windows instead of 
>  > frames, Emacs DTRT, no?  Emacs distinguishes the case of
>  > window *Process List* from window *Backtrace*,
>  > giving the focus to the latter and not to the former.  Why 
>  > can't we make Emacs DTRT for frames, just as it does for windows?

And your code in fact does make the distinction between *Process List* and
*Backtrace*, which proves my point here.  But your code makes the distinction
based on *Process List* being a temporary buffer (which it is), and not on it
being a buffer that is displayed temporarily in its own frame.

The latter distinction is I think the right one, and which would be good to
handle.  That is where MS Windows's automatic focusing leads to a problem.

The problematic case is (a) standalone minibuffer (b) popped-up buffer in its
own frame, (c) that frame being new, and (d) the OS giving the new frame the
input focus.

> For windows on the same frame we can differ between 
> `display-buffer' and `pop-to-buffer'.  For windows on different
> frames we have the complication that the `handle-switch-frame'
> event triggered by the OS causes Emacs to select that frame,
> that is, implicitly replace `display-buffer' by `pop-to-buffer'.

Yes, that is one way to put it.

>  > I know that MS Windows altering the focus throws a monkey 
>  > wrench into the mix, but surely we can find some way to KEEP
>  > the focus (i.e. re-focus if necessary) where Emacs put it
>  > (correctly).
> 
> As far as old code is concerned you probably are overly optimistic.

OK, let's say that that is a nice-to-have, and move on.

The first step is your code, which handles a subset of the problematic cases for
new Emacs releases.  Very good.

The second step, I think, would be something similar, but not limited to
temporary buffers.  Some way for a programmer to express the intention of
displaying a buffer (temporary or not) only for informational purposes during a
minibuffer interaction.

And I think that for that more general case, there is a problem to be handled
only when (a) there is a standalone minibuffer frame, (b) the buffer is popped
up in its own frame.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]