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

From: "Drew Adams" <[email-masked]>
Date: Mon, 6 Aug 2012 14:05:38 -0700

>  >>  > 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?
>  >
>  > Sorry, I don't know what that means.  Perhaps give an 
>  > example of what you mean by temporarily selected and current?
> 
> Temporarily selected means selected via `with-selected-window' and
> temporarily current means `with-current-buffer'.

OK, but I still don't see what you are trying to say, or why.

You seem to be saying that if BUFFER is selected/current, and if input is read
somewhere (where?) - then what?  The focus gets automatically redirected to the
minibuffer frame?

This is not about reading input with BUFFER selected/current.  The idea is to
have the _previously_ selected buffer be selected/current, while input is read
from the minibuffer.  The idea is not to make BUFFER selected/current, but just
to display it.

Beyond that, that sentence of mine was shorthand.  It (apparently) is not enough
that the focus be redirected once, at some point, to the minibuffer frame.  It
needs to either remain there (somehow preventing MS Windows from moving it away)
or be put back there (after MS Windows moves it to BUFFER's frame).  IOW, even
if redirection is happening now as it should, it is not sufficient if, after
that redirection to the minibuffer, the OS changes the focus again (to the new
frame).

>  >>  > 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?
>  >
>  > No, not as I was conceiving it.  I suppose that would be a 
>  > possibility, but I expect it is better to keep buffer display out of it.  
>  > That's why I said things like "_if_ BUFFER gets displayed in its own
frame".
>  >
>  > What I had in mind was that the macro would be responsible 
>  > only for making sure that minibuffer input gets (re-)directed to the
>  > minibuffer frame.  And that goes for any code in BODY, including code
>  > that might pop up BUFFER.
>  >
>  > IOW, display of BUFFER would come (if it came) from BODY.
>  >
>  > But again, I'm just thinking out loud.  And it's probable 
>  > that you see things that I do not.
> 
> No.  Just that I don't have the slightest idea how to write a 
> macro that modifies the behavior of a `yes-or-no-p' dialog it calls.  
> read_minibuf and the code for handling keyboard events do the redirecting.
> 
>  >>  > 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.
>  >
>  > Can you elaborate?  I don't follow.
> 
> IIUC you want to modify the behavior of `yes-or-no-p' to 
> redirect frame focus in your sense.

I don't know why you mention `yes-or-no-p'.  This is about reading from the
minibuffer, in general.

I don't want or not want to modify `yes-or-no-p' or `read-from-minibuffer'.  I'm
just saying that if the problem is that we want to display BUFFER, and it gets
displayed in a new frame, and we want to read from the minibuffer, then we do
not want, for that minibuffer reading, the input focus to be in BUFFER's frame.

I spoke of redirecting, but it might take more than that or doing that more than
once, if the OS switches focus after redirection to the minibuffer.

>  > No.  Again, during reading from the minibuffer it is quite 
>  > possible for a user to interact with other buffers and their frames.
>  > I gave the example of *Completions*.  The user can hit a key or use
>  > the mouse to change the input focus temporarily to another frame -
>  > any frame.
>  >
>  > When the user does that s?he is executing code within 
>  > BODY.  It is code that reads from the minibuffer, but also code
>  > that implements any commands bound to keys or mouse actions that
>  > the user uses during that minibuffer dialog.  That's
>  > all I meant.
> 
> I'm afraid this gets too complicated for me.  You have to find someone
> who understands such scenarios better than me.

The scenario is as simple as your clicking a special-display (hence dedicated,
separate frame) *Completions* frame during minibuffer input.  That changes the
focus to *Completions*.  But that doesn't mean that you cannot switch back to
the minibuffer frame again.

The only point here is that whatever is done to fix the problem should not in
any way prevent a user from clicking *Completions* and thus switching the focus
there.

Or any other frame, besides *Completions*.  You should be able to click another
frame, type some text there, then click the minibuffer frame and finish entering
the input text it wants to read.  IOW, minibuffer interaction is not modal; it
does not (should not) prevent you from interacting with other parts of Emacs,
including typing into other frames.

This was in response to your statement that we wanted to _always_ have the focus
on the minibuffer frame.  Yes, when reading from the minibuffer is initiated,
the minibuffer frame should get the focus.  But the user (or Emacs) should not
be prevented from switching the focus to another frame.

All that we are trying to prevent or remedy is the focus switching to another
(new) frame by the OS.  We should not be preventing either Emacs or the user
from switching focus to another frame, just because the minibuffer is active.

That is the only point I was trying to make here.

>  >>  > 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?
>  >
>  > The person who writes the code that reads from the minibuffer,
>  > code that might or might not be wrapped in the new macro, i.e.,
>  > that might or might not want to stipulate that BUFFER is not to
>  > receive the input focus.
> 
> The person who writes that code expects `yes-or-no-p' DTRT.

Agreed.

>  >> I refer to the case where a minibuffer-equipped frame is 
>  >> popped up.
>  >
>  > I'd rather you didn't.  Let's not bring in new things.
> 
> Users with non-nil `pop-up-frames' who don't use minibuffer-only
> frames do get a minibuffer-equipped frame popped up.

Of course they do.  But is there a problem for them?  Has any problem similar to
the one reported for this bug been identified for those different use cases?

This bug is about a problem that arises (with MS Windows) when you do have a
standalone minibuffer frame.  That's all.

> You can ignore them, I can't.

No one is asking you to ignore them.  If you see a related problem for other use
cases, by all means, try to address that problem at the same time.  I have not
heard of such a problem, so to me bringing up that use case seems irrelevant.

I care about _this_ bug being fixed.  But that does not mean that I want to
prevent you from fixing other bugs.  I haven't heard of any such problem without
a standalone minibuffer, however.

> And a user who excludes BUFFER from the list of specially
> displayed buffers does a perfectly valid thing and can expect Emacs to
> handle it as it currently does.

OK by me.  I have no argument against that.  I don't see how it's related, but
it's fine by me.

>  > I don't know.  The only problems I am aware of for 
>  > `w-t-b-w.el' are these:
>  >
>  > 1. Loss of special-displayness (a separate problem, but 
>  > important if we're talking about `w-t-b-w.el' as it stands now).
>  >
>  > 2. The fact that it limits itself to display of temporary 
>  > buffers, whereas the actual problem has to do with the temporary
>  > display of buffers.
> 
> Because I can safely kill a temporary buffer and remove its frame when
> I'm done with the dialog.

OK.  I've already agreed that that is a good thing.  I'm in favor of your
proposed fix.

I was just pointing out that there can be cases of MS Windows messing things up
that your fix won't solve, namely, temporary display of a non-temporary buffer,
a buffer that you do not want input to be focused to.

>  > And as far as you know, is the fact that the minibuffer 
>  > frame is still used (as it should be) due only to the fact that
>  > `yes-or-no-p' is used, or can I expect
>  > that the minibuffer frame will be used in general?
> 
> Due to the fact that `yes-or-no-p' is called in a special way 
> - with the new window selected.
> 
>  >>  >> `with-temp-buffer-window' avoids that by asking the
>  >>  >> `yes-or-no-p' question in the new frame.
>  >
>  > Dunno why I (or was it you?) said that.  I see the 
>  > question in the minibuffer frame, not the new frame.
>  > Which is TRT.
> 
> To "see the question in the minibuffer frame" I ask it in the 
> new frame.

OK.  That was worth clarifying.  I wasn't understanding that.  I see the
question in the minibuffer frame, and I type the answer there.  My impression
was that the minibuffer frame had the focus.

I did not know where you were asking the question.  By that, I assume you mean
that the new frame is selected (and has the focus?) when you invoke
`yes-or-no-p'.  Is that right?

Just for my info, why does it matter where `yes-or-no-p' is invoked?  _Should_
it matter, or is it just a fact that we must live with that it does matter?

>  > Yes, it is more restrictive than the actual problem encountered.
>  > As I said, it might suffice in practice, but there is nothing in the 
>  > problem description that requires that the buffer itself be temporary.
> 
> I have to kill the buffer to remove the frame.

I don't understand why, but probably I don't need to understand everything.  Why
doesn't `delete-frame' do what you need?

> And I have to remove the frame because you complained that
> `save-window-excursion' cannot remove a popped up frame.

Hm.  I don't recall that at all, but I believe you that I did.  Was that in some
other thread?

> And I can't kill a non-temporary buffer.

>  > The informational frame?  I'd vote for `delete-frame', at 
>  > least for my own use.  We might want to provide ways for the
>  > caller and/or the user to control both what to do with the
>  > frame/window and what to do with the buffer.  But maybe
>  > `frame-auto-hide-function' would make sense here?
> 
> If we use `frame-auto-hide-function', the caller does not have to kill
> the buffer and there's no need to make this construct work 
> for temporary buffers only.

That sounds good to me.  Perhaps I'm missing something.  I don't want to steer
you down the wrong path, but what you say here sounds good to me.

If the more general case can be handled, then the more restrictive case
(temporary buffer, not just temporary display) could presumably be handled also,
as a subcase, no?  Or even if not as a subcase, as a separate case.

IOW, if possible it would be good to have both possibilities, so a programmer
could get the right behavior for a given context: If s?he wants that buffer to
be temporary, then call a construct that treats it as such (killing it).  If
s?he wants that buffer not to be temporary and only its display to be temporary
then call a construct that does that instead.

>  > Anyway, let's talk about this later.
> 
> It's your choice.

Can we have both possibilities?

If not, let's get the temporary-buffer one first.  IOW, I think you have that
case almost nailed - there is just the special-display/dedicatedness that does
not work yet.