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

From: martin rudalics <[email-masked]>
Date: Sat, 04 Aug 2012 15:44:53 +0200

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

Users who want to pop up a frame with a minibuffer almost certainly want
to supply their input right in the frame where the informational buffer
is displayed.  So there is a use case where the informational buffer
must be made current.  Also, when the new frame is popped up and
`handle-switch-frame' switches to it, the informational buffer is made
current anyway.  So we'll have a hard time preserving the "with the
previous buffer remaining current" requirement throughout the dialog.

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

You know that buffers don't have input focus - only frames do, so please
keep this distinction alive here.  I think we agree that developers
leave it to us users to decide whether the buffer is shown in a new or
an existing frame.  For a use case where the frame of the displayed
buffer should have input focus see the `pop-up-frames' non-nil case.

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

We would at least have to make this optional.  Users might want to
prefer standalone buffers for most of their input but prefer answering
the dialogs we talk about here in a minibuffer frame with the list of
files being displayed in the same frame.  The new option, let's call it
`always-redirect-input-to-standalone-minibuffer-frame', if non-nil,
could be used by your construct.

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

In my experience, this requirement is met if the construct requests
input with BUFFER's window temporarily selected and BUFFER temporarily
current.  Or am I missing something?

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

I don't understand what BODY should contain.  Would this macro be
responsible for displaying BUFFER?

 > Likewise, nothing should prevent the user from explicitly switching the
 > focus to BUFFER's frame.

This is part of the `yes-or-no-p' dialog, nothing within the scope of
the construct you propose.

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

And the only way of "trying to prevent" I can think of is to redirect
focus by requesting input from BUFFER's 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

... BUFFER's frame ...

 > during BODY (unless that is done by the user or by code within BODY).

... during the subsequent reading from the minibuffer.  BODY has
terminated long ago at that time I suppose.

 > 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

Who is the programmer here?

 > cannot be made explicit then there is no way to know what TRT is.

First we have to separate application from user in a clear way.

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

Yes.

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

Let's be realistic, programmers won't care.  We can only provide a
construct that's convenient enough and has been tested in a few model
cases like the ones we know of.

 > By "might pop up" I meant that _if_ informational BUFFER is popped up in its own

minibuffer-less

 > 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?

I refer to the case where a minibuffer-equipped frame is popped up.

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

OK.  If you think that the way with-temp-buffer-window.el handles it is
not enough, tell me what you would do instead.

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

Why don't you code the macro you have in mind so we can discuss it?

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

So let's use an option like
`always-redirect-input-to-standalone-minibuffer-frame' and you propose a
macro that does what you mean based on that option (I'm afraid I do not
understand well what you think that macro's BODY should do).

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

So you think it's too restrictive?

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

It's a substitute for `with-output-to-temp-buffer' with an additional
function that can be used to replace the return value of the former.

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

The buffer need not be temporary.  But in order for quitting to get rid
of the frame, the buffer must be killed.

 > 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?

If you came up with a macro that (approximately) does what you
want/need, I probably could answer that question.

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

You might be right.

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

The invoking code does not care.  It expects `display-buffer' and
`yes-or-no-p' to take care of this.

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

Once more - the code expects the underlying mechanism to handle that.

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

So write a `with-buffer-window' doing things in a non-temporary fashion.
The problem is that removing the frame without killing the buffer will
be impossible unless we provide yet another option.

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

You still have to tell me how to remove that frame when you're done.

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

Write the macro and we'll see further.

martin