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

From: martin rudalics <[email-masked]>
Date: Sat, 21 Jul 2012 13:02:05 +0200

>> But choose_minibuf_frame has this
 >>
 >>        /* I don't think that any frames may validly have a
 >>           null minibuffer window anymore.  */
 >>        if (NILP (sf->minibuffer_window))
 >> 	abort ();
 >
 > Wow, that comment seems weird.  Unless a frame that has nil as the value of its
 > `minibuffer' frame parameter is still expected to have a minibuffer _window_.
 > That's a distinction that is beyond me.  I do not claim to understand things at
 > the Emacs window level.

Usually, each frame must have a minibuffer window.  How else should
`read-minibuffer' work?  But within the C routines this invariant seems
too strong.

 > But certainly there can be frames that have no minibuffer - their `minibuffer'
 > frame parameter value is nil.

That's a different story.  IIUC only the selected frame must have the
minibuffer_window slot always set.

 >> and read_minibuf calls choose_minibuf_frame, so if a new frame doesn't
 >> have a valid minibuffer window, emacs should abort.
 >
 > What does abort mean here - does it mean that Emacs exits?

Ungracefully, yes.

 >> If it does, the latter
 >>    if (!EQ (mini_frame, selected_frame))
 >>      Fredirect_frame_focus (selected_frame, mini_frame);
 >>
 >> in read_minibuf should redirect focus but apparently it doesn't.
 >
 > Again, are you sure it does not?  I've been (stubbornly) guessing that it always
 > does, but then, in the problematic case we've been looking at, the focus is
 > grabbed away and given to the new frame that is popped up.
 >
 > I understand that you don't see it that way, that you instead guess that in this
 > problematic case there is never any redirection of focus to the minibuffer
 > frame.  But I haven't yet understood why you think that.  (I do not say you are
 > wrong.)

As explained many times before I'm just speculating.  Note, however,
that the redirection in the code above works only for the selected
frame.  That's why I ask the `yes-or-no-p' questions with the new frame
selected.

 >> Probably by checking whether the focus of the minibuffer-less
 >> frame A is redirected to the minibuffer-equipped frame B.
 >
 > I don't know how to do that.
 >
 > And in `1on1-fit-minibuffer-frame' I do not know how to find out what the
 > minibuffer-less frame is.  That function is just invoked by `post-command-hook'.
 >
 > It seems that in the problematic case it is command `handle-switch-frame' that
 > is the command current when `post-command-hook' does its thing here.  But I
 > don't know how to determine what frame was switched to.  I can check
 > `selected-frame', which is what I do, but I'm not sure what you are suggesting I
 > do.

Why don't you try what I suggested earlier: Put something on
`mouse-leave-buffer-hook' and in a `pre-' or `post-command-hook' check
whether that something got executed.  Then you can be sure that
somewhere in between a `handle-switch-frame' interfered.

 > OK, but did the minibuffer frame ever receive the focus, after
 > `read-from-minibuffer' was invoked?  That's the question that I think we are
 > assuming different answers to.  I'm guessing yes, and I think you are saying no.
 > I'm guessing yes, but then the window mgr gave the focus instead to the new
 > frame it created.

So you mean the following happens:

(1) Emacs ask a `yes-or-no-p' with input focus directed to frame A.

(2) The window manager redirects focus to the new frame B and the
     `handle-switch-frame' which should redirect focus from B to A gets
     delayed as long as Emacs waits for minibuffer input.

 > OK.  What's needed I guess is to make sure somehow that every frame redirects
 > input to the minibuffer frame when the minibuffer becomes active.

Which won't help in (2) above.

 > Perhaps it would help to imagine the new frame scenario a bit like the
 > switch-to-*Completions*-frame scenario (dunno).
 >
 > As I mentioned in my other reply today, you can, when the minibuffer is active,
 > explicitly switch the focus to the *Completions* frame, to do something there
 > (e.g. move to some completion candidate).

Which function precisely does that?

 > So a possible (hack) solution, if we could detect that unprogrammed (in Emacs)
 > focus switch, might be to automatically switch focus back to the minibuffer
 > frame (IF the minibuffer is active).

Or assume that the focus switch happened and react accordingly.

martin