Subject: Re: bug#11939: 24.1; `save-buffers-kill-emacs' loses minibuffer focus when itcalls `list-processes'

From: martin rudalics <[email-masked]>
Date: Tue, 17 Jul 2012 11:50:16 +0200

> In my code I put command `1on1-fit-minibuffer-frame' on `post-command-hook'.
 > That function fits the standalone minibuffer frame to its "buffer contents"
 > (taking Icomplete overlays into account etc.).
 >
 > The function assumes that it is called from the minibuffer, i.e., that the
 > selected frame is the standalone frame.  Which it is...

Why does that function _assume_ that?  It should check it.

 > But something apparently changed the focus in this case - I'm guessing, as I
 > said before, that it was the popping up of the new frame.  And some second
 > command is involved at that point - apparently `handle-switch-frame'.

So `1on1-fit-minibuffer-frame' assumes that the selected frame is the
standalone minibuffer frame and that that frame has focus.  Why don't
you verify all that in the function's body?

 > So because of `post-command-hook', `1on1-fit-minibuffer-frame' got called a
 > second time, and this time with the previously selected frame being selected
 > (i.e., the frame that was selected prior to entering the minibuffer).  The
 > minibuffer was still active,

... you mean `active-minibuffer-window' returned the window of the
minibuffer-only frame ...

 > but the selected frame was another one (e.g.
 > *Process List*).
 >
 > I came up with three alternative fixes that work - I chose the second one:
 >
 > 1. The first fix is to call `select-frame-set-input-focus' at the end of
 > `1on1-fit-minibuffer-frame'.
 >
 > I can tell by debugging using `message' that the frame switch happens outside
 > `1on1-fit-minibuffer-frame': the selected frame is the minibuffer frame the
 > first time `1on1-fit-minibuffer-frame' is called, right up till the end.  But it
 > is another frame the next time `1on1-fit-minibuffer-frame' is called, which
 > appears to be immediately afterward.
 >
 > So why does this fix work?  Dunno.  Even though without adding the call to
 > `select-frame-set-input-focus' the frame is correct when the first call to
 > `1on1-fit-minibuffer-frame' ends, if I do not add that call then it is incorrect
 > for the second `1on1-fit-minibuffer-frame' call.  Well that's understandable
 > from a `switch-frame' event.
 >
 > But what's not clear to me is why calling `select-frame-set-input-focus' at the
 > end of the first call to `1on1-fit-minibuffer-frame' fixes things.  As I said,
 > the frame switch seems to happen between the two calls, yet selecting the
 > minibuffer frame before the end of the first call solves the problem.  Maybe
 > this has something to do with the redisplay code?  No idea.

You have two calls from `post-command-hook': The first seems due to
`save-buffers-kill-emacs' preliminary terminating with a `yes-or-no-p'
question which does not affect frame or focus.  The second should come
from `handle-switch-frame' as a consequence of emacs being called back
by the window manager.  IIUC `handle-switch-frame' calls do_switch_frame
with TRACK equal 0, so focus is not affected by `handle-switch-frame'.
But focus has been redirected to the new frame by the window manager and
emacs should probably adapt to that situation because that is the frame
that gets the keystrokes.

Now if whatever you want to do after `handle-switch-frame' has
terminated happens in the new frame, there's no problem.  We have a
problem if we want to make things happen in another frame and for that
purpose we have to redirect focus to that other frame.  That's what you
apparently do via the `select-frame-set-input-focus' call at the end of
the first `post-command-hook' execution since `handle-switch-frame'
won't change focus afterwards.  Looks like a very fragile hack.

 > 2. The second fix is to have `1on1-fit-minibuffer-frame' do nothing unless:
 >
 > (eq last-event-frame
 >     (save-selected-window
 >      (select-window (minibuffer-window)) (selected-frame)))

Is that (eq last-event-frame (window-frame (minibuffer-window)))?

This means that you don't do anything in this case so apparently some
side-effect gets suppressed.  Which side-effect?

 > 3. The third fix is to have `1on1-fit-minibuffer-frame' do nothing unless:
 > `this-command' is not eq to `handle-switch-frame.

Same as before.  What is the side-effect of `1on1-fit-minibuffer-frame'?

 > In sum, this is my guess: The creation of the new frame provoked a
 > `switch-frame' event, which, because of `post-command-hook' caused
 > `1on1-fit-minibuffer-frame' to be called a second time, this time with the new
 > frame selected because the last command was `handle-frame-switch'.

I think you should make sure two things: (1) `1on1-fit-minibuffer-frame'
should do something iff the frame in question is a minibuffer frame.
(2) `1on1-fit-minibuffer-frame' should avoid having any side-effects wrt
window selection or focus unless you explictly want that.

martin