Subject: bug#11566: 24.0.97; `read-from-minibuffer': focus to standalone minibuffer frame?

From: "Drew Adams" <[email-masked]>
Date: Sat, 26 May 2012 17:07:46 -0700

Not a recipe from emacs -Q - sorry.  Please bear with my description.  I
don't claim to understand things 100%, but this is what I think is going
on.  I really hope that someone who understands better can help.
 
Normally, if you have a standalone minibuffer frame, then when
`read-from-minibuffer' is called the input focus switches to that frame
- which it should, so that your typed input goes into the minibuffer.
 
However, it can happen that the focus sometimes does not go to the
minibuffer frame (or perhaps it leaves that frame? dunno).  And that's
the problem I'm looking for a solution to.
 
On MS Windows at least, when a new frame is created it grabs the input
focus.  The problem where the minibuffer frame does not get the focus it
needs seems to arise in a situation where a new frame is popped up and
then `read-from-minibuffer' is called immediately afterward.  Maybe
there is some kind of contention or delay/race problem here (?) - I have
no idea.
 
For example, `dired-mark-read-string' calls `dired-mark-pop-up' to read
a string using `read-from-minibuffer' (`r-f-m' is the FUNCTION arg
passed to `d-m-p-u' in this case).
 
Inside a `save-window-excursion', `dired-mark-pop-up' then calls
`dired-pop-to-buffer', which pops up a new buffer, which (let's say,
because of `special-display-regexp' or whatever) is shown in a new
frame.  MS Windows gives this frame the input focus.
 
Then, still inside the `save-window-excursion', `dired-mark-pop-up'
immediately calls the FUNCTION arg, which in this case is
`read-from-minibuffer'.  (It does this using (apply FUNCTION args), but
that should not make any difference.)
 
[I don't think it matters for correctness whether the (apply FUNCTION
args) is inside the `save-window-excursion'.  I've tried moving it
outside, but that did not change anything.  I would think that it should
be outside logically (why perform the action from that buffer?), but I'm
not knowledgeable about all use cases of `dired-mark-pop-up'.]
 
OK, so what happens is this: When `read-from-minibuffer' does its thing,
the standalone minibuffer does not receive the user input.  Instead, the
input goes to the popped-up frame (which has a list of *Marked Files*).
 
That seems to be an exception to the general rule that
`read-from-minibuffer' correctly moves the focus to the minibuffer - and
to its frame.  I don't know why there is a difference in this case, but
that seems to be what happens.  The problem is not specific to this
example - it can occur at other times.  But I think that this is a good
case to follow what's happening.
 
I've tried various workarounds, with more or less success.  But I'm
thinking now that the problem is not in any such functions that pop up a
frame etc. but rather with `read-from-minibuffer' itself.  Shouldn't it
have the responsibility here to give the minibuffer frame the focus?
 
Here is a workaround I've come up with when trying to "fix" `r-f-m'
itself:
 
(defadvice read-from-minibuffer (around focus-standalone-minibuf activate)
  "..."
  (let ((selframe  (selected-frame))
        result)
    (unwind-protect
         (progn (when (and (boundp '1on1-minibuffer-frame)
                           (frame-live-p 1on1-minibuffer-frame))
                  (select-frame-set-input-focus 1on1-minibuffer-frame))
                (setq result  ad-do-it))
      (ignore-errors (select-frame-set-input-focus selframe))
      result)))
 
(In my case I know that the standalone minibuffer, if it exists, is the
value of `1on1-minibuffer-frame'.  Not sure how the use of a standalone
minibuffer would be detected in general - presumably by checking for a
frame that has a `minibuffer' parameter with value `only'...)
 
But that defadvice does not always make `r-f-m' DTRT, in any case.  For
example, if the originally selected frame is deleted during `ad-do-it',
then it punts and leaves the input focus in the minibuffer frame.  What
I would probably expect (want) in that case is for the previously
selected frame to get the focus.
 
For example, if I tweak `dired-mark-pop-up' so that it deletes the
popped up frame at the end, then - since that frame was selected (by the
window manager) when `read-from-minibuffer' was called - the minibuffer
frame ends up with the focus.
 
(And I do tweak `d-m-p-u' that way, because of another problem with such
a popped up frame - see bug #7533.)
 
Any help is appreciated.  Hope I've made the problem clear enough,
though you would probably have to be on Windows to see it manifested.
I really hope that someone with better understanding than I can help.
(Stefan? Martin? ...)

In GNU Emacs 24.0.97.1 (i386-mingw-nt5.1.2600)
 of 2012-05-16 on MARVIN
Windowing system distributor `Microsoft Corp.', version 5.1.2600
Configured using:
 `configure --with-gcc (4.6) --no-opt --enable-checking --cflags
 -ID:/devel/emacs/libs/libXpm-3.5.8/include
 -ID:/devel/emacs/libs/libXpm-3.5.8/src
 -ID:/devel/emacs/libs/libpng-dev_1.4.3-1/include
 -ID:/devel/emacs/libs/zlib-dev_1.2.5-2/include
 -ID:/devel/emacs/libs/giflib-4.1.4-1/include
 -ID:/devel/emacs/libs/jpeg-6b-4/include
 -ID:/devel/emacs/libs/tiff-3.8.2-1/include
 -ID:/devel/emacs/libs/gnutls-3.0.9/include'