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

From: "Drew Adams" <[email-masked]>
Date: Mon, 16 Jul 2012 16:26:27 -0700

> So I do not yet know what else in my setup causes the 
> problem.  I will have to dig to try to find out - can't do that today.

I found the problem in my code and fixed it.  It was kind of interesting, so
I'll describe it a bit in case you are interested.

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

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

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

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

The bug was in my code.  I've wanted to clear this up for a long time, and I
think that's done now (including for older Emacs versions, obviously) - thanks
to your help.  Thank you very much!

----

BTW, in Icicle minor mode I have long used this (which Richard came up with,
IIRC), but it clearly did not help with this particular problem:

(define-key global-map [handle-switch-frame] 'icicle-skip-this-command)
(define-key global-map [switch-frame] 'icicle-handle-switch-frame)

where:

(defun icicle-skip-this-command ()
  "Prevent `handle-switch-frame' from being added to `this-command'."
  (interactive)
  (setq this-command  last-command))

(defun icicle-handle-switch-frame (event)
  "Call `handle-switch-frame', but don't add it to `this-command'."
  (interactive "e")
  (handle-switch-frame event)
  (setq this-command  last-command))