Subject: bug#11939: 24.1; `save-buffers-kill-emacs'losesminibufferfocuswhenitcalls`list-processes'

From: "Drew Adams" <[email-masked]>
Date: Mon, 13 Aug 2012 15:20:53 -0700

Coming back to an earlier part of this thread.  I have some news.

I found today that the code you sent does not help in at least one situation.  I
presume that's because it deals only with temporary buffers, but I'm not sure.
The buffer popped up in a separate frame is *Completions*.  By "does not help" I
mean that it makes no difference in this case whether I load your code or not.

Anyway, the scenario involves using my one-on-one stuff with a vanilla Emacs
call to `completing-read' or `completing-read-multiple'.

[I discovered this because the latter (`c-r-m') does not use anything particular
in Icicles, so `customize-face' (via `read-face-name') just calls vanilla
`completing-read-multiple' even in Icicle mode.]

M-x customize-face b TAB

then, trying to type more chars raises an error saying that *Completions* is
read-only (IOW, the *Completions* frame was somehow given the input focus).

I looked into the problem a little more closely.

None of the hacks I had tried previously with `1on1-fit-minibuffer-frame' took
care of this problem: neither guarding the minibuffer frame-fitting, using

(eq last-event-frame (window-frame (minibuffer-window)))

nor adding explicit redirection to the minibuffer frame at the end of
`1on1-fit-minibuffer-frame'.

It turns out that the problem was 3-fold.  That is, there were three places in
the code of `1on1-fit-minibuffer-frame' that caused the problem: each was
_alone_ capable of causing the problem, so all three needed to be fixed.  Here
they are.

1. This was one of the guards of the body of `1on1-fit-minibuffer-frame':

(save-selected-window
  (select-window (minibuffer-window))
  (one-window-p nil 'selected-frame))

The call to `save-selected-window' somehow gave the focus to the *Completions*
frame.  The solution was to change `save-selected-window' to
`save-window-excursion' here.  I don't know why, but I'm hoping you will.

2. This was called near the beginning of the `1on1-fit-minibuffer-frame' body:

(let* ((frame (save-selected-window
                (select-window (minibuffer-window))
                (selected-frame)))

The fix here too was to use `save-window-excursion' instead of
`save-selected-window'.

3. At the end of the `1on1-fit-minibuffer-frame' body there is this call:

(1on1-set-minibuffer-frame-top/bottom)

The code for that function is this:

(defun 1on1-set-minibuffer-frame-top/bottom ()
  (when 1on1-minibuffer-frame
    (condition-case nil
        (if (fboundp 'redisplay)
	    (redisplay t)
	  (force-mode-line-update t))
      (error nil)) ; Ignore errors from, e.g., killed buffers.
    (modify-frame-parameters
     1on1-minibuffer-frame
     `((top ,@ (or 1on1-minibuffer-frame-top/bottom
                   (- (* 2 (frame-char-height
                             1on1-minibuffer-frame)))))))))

Here the problem was the call to `redisplay'.  I changed (foundp 'redisplay) to
just nil to fix things - `force-mode-line-update' works without changing the
focus.

`redisplay' is defined in C code.  I do not know why it causes a problem here
(why would redisplay change the input focus?), and I don't know what the proper
solution might be, except to just use `force-mode-line-update' as I was already
doing in older Emacs versions (which do not have `redisplay').

Do you have an idea about this?  Does any of this make sense to you?

Each of these fixes is needed for `1on1-fit-minibuffer-frame'.  Reverting any of
them brings back the problem (giving *Completions* the focus).  I do not
understand any of these fixes (why they work), and I am certainly not claiming
anything about them or about the problem, which I do not understand.  I am only
saying that together these changes fix the problem I encountered.

But if you can explain things I will be glad to learn.

Thx/HTH - Drew