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

From: "Drew Adams" <[email-masked]>
Date: Sun, 15 Jul 2012 08:06:47 -0700

Hi Martin,

>  >> OK.  What happens if in in `yes-or-no-p' you use
>  >>                      (when minibuffer-auto-raise
>  >>                        (select-frame-set-input-focus
>  >> 		       (window-frame (minibuffer-window))))
>  >> instead of `raise-frame'?
>  >
>  > Sorry, I don't understand.  `yes-or-no-p' is coded in C.  
>  > Where should I change a call to raise-frame to instead use the above code?
> 
> Sorry.  Do (defalias 'yes-or-no-p 'y-or-n-p) and then try.

Are you sure you mean that?  AFAIK, `y-or-n-p' is not at all representative - it
does not even use the minibuffer, I think: it just reads events directly.  I
will try to do as you instruct, if you confirm, but I do not understand how
using `y-or-n-p' here can possibly help.

> ... what command is C-] bound to?  I can't type it on my keyboard ...

`abort-recursive-edit'.  `C-]' is the (only) default global binding (emacs -Q)
for `abort-recursive-edit'.

>  > OK, I tried that: still using my setup, I set 
>  > `special-display-regexps' to nil then tried C-x C-c etc.
>  >
>  > That changed nothing (except that the popped up buffer 
>  > appeared in a regular frame, not a special-display frame).
>  > The symptoms were identical AFAICT: input
>  > did not go to minibuffer, and quitting (C-]) left the 
>  > frame but put the originally current buffer in it, replacing the 
>  > processes-list buffer there.
> 
> But it does work with emacs -Q on your system, I suppose?

I'm not sure just what the test was to be here.  But I tried with emacs -Q (plus
loading cygwin-mount.el & setup-cygwin.el, so that I have a bash shell on
Windows).

I tried first with nil `pop-up-frames' - that behaved normally, i.e., as it
should.  I tried then with non-nil `pop-up-frames' - and that manifested the
same problem that I reported!  Good news!

So even *without* a standalone minibuffer and the rest of my setup, this bug is
reproducible.  Thanks for helping find that.  (Perhaps there are additional
problems, but we need not worry about those now, if any in fact exist.)

So that's great news.  A simple recipe:

1. On MS Windows (I'm using XP SP3).
(I hope someone on Windows will confirm and help.)

2. emacs -Q

3. Load cygwin-mount.el, then setup-cygwin.el (from Emacs Wiki's Elisp Area).

4. M-x set-variable pop-up-frames t

5. M-x shell

6. C-x C-c

The informative buffer *Process List* is popped up in a separate frame, which
apparently gets the focus.  The question about killing active processes appears
in the minibuffer of the original frame (which has only buffer *shell*).

Because the new frame has the focus, _you cannot answer the question_.  You are
forced to select the frame with the question (e.g. clicking mouse-1 on its title
bar), in order to answer it and exit Emacs.

A second bug (I think) is that there is NO feedback/response to your typing the
answer.  With focus in the *Process List* frame, which has a read-only buffer, I
would expect an error message saying that the buffer is read-only.  But you get
NO message - nada.  Not only that, but I see no such message in buffer
*Messages* if I look there.  Dunno why this is.

> So the problem seems that input doesn't get redirected to your 
> minibuffer frame when popping up a new minibuffer-less frame.

Seems to not depend on a standalone minibuffer frame, but yes, that seems to be
the problem.

Well, that's one problem, anyway.  Really, I do not want the new frame popped up
to have a minibuffer and pose the question about killing processes.  I want the
new frame to just be displayed and _not selected_ for input/output (user
interaction).  I do not want it to have a minibuffer.

More precisely, I don't have much of an opinion in the case of a non standalone
minibuffer.

But in the case of a standalone minibuffer, it definitely should continue to
have the input focus.  That's the point, for me.

It would not be a solution for me to give the new frame its own minibuffer or
something and to let it keep the input focus.  The user should be able to always
look to the same, standalone minibuffer - the *only* minibuffer area - for all
prompts and user replies.

>  > Oh, it also changed this: Now when I hit `q' in *Help*, 
>  > instead of the frame being removed I get another buffer in it,
>  > substituted for *Help*.  This in spite of the fact that
>  > `special-display-buffer-names' has this entry, which should
>  > make *Help* be dedicated:
>  >
>  > ("*Help*" 1on1-display-*Help*-frame
>  >   ((background-color . "Thistle")
>  >    (mouse-color . "Blue Violet")
>  >    (cursor-color . "Blue Violet")
>  >    (height . 40)))
>  >
>  > Buffer *Help* is still popped up in a new frame that has 
>  > those colors, but now when I hit `q' in it the frame does not
>  > disappear and its buffer is changed.  That's not what I would
>  > call "dedicated" anymore.
> 
> That's hardly surprising: With `pop-up-frames' t you shouldn't get a
> dedicated window, I suppose.

Uh, if you are saying what I think you are saying then I'm afraid I disagree
strongly about that.  To me, that would be a regression.

If a buffer is declared via `special-display-buffer-names' to be
special-display, then it _must be_ special-display.  That must not be violated
just because `pop-up-frames' might have some particular value.

I *hope* I am just misunderstanding you here - I hope you are not suggesting
that `special-display-buffer-names' is no longer enough to ensure that a buffer
is special-display.

>  >> BTW, has bug#11566 been resolved meanwhile?
>  >
>  > Not at all (not that I know of/can tell).  The last message in
>  > that thread is from me, and its questions were never answered.
> 
> Then why do you suggest at the beginning of the current thread to
> 
>  >> "look to `dired-mark-pop-up' which does something similar 
>  >> but gets it right"
> 
> if it apparently doesn't get it right anyway?

I'm sorry; I was probably confused in saying that.  I must have meant that it
works with the patch I sent, which (I thought) was applied to Emacs (or was
going to be applied).

If I use Dired+ (which does what my patch does) then there is no problem, so in
my daily use this is solved for the Dired but reported, but not in general (viz.
this bug wrt quitting with active processes).

> It would be fine if we were able to sketch the problem as 
> follows: If a user has a
> 
> (1) minibuffer-only frame and all other frames use that minibuffer and
> (2) a `yes-or-no-p' or `read-from-minibuffer' prompt pops up in a
>      separate frame
> 
> then `select-frame-set-input-focus' is needed to redirect 
> input to that minibuffer-only frame inorder to answer the question.

See above.  What you say might well be involved (i.e., be part of a solution),
but the problem (of this bug) is apparently present even without a standalone
minibuffer frame.

> Can't you try to provide a test example on this basis?

I don't know how.  I did suggest in the bug #11566 thread that perhaps
`read-from-minibuffer' could do something like that systematically, and I
thought briefly that I had found a general solution that way, but I soon
discovered that `message' then had no effect!  No messages were ever output if I
did that.

> The Elisp manual doesn't help me at all when I try doing that.
> For example, if I want to know how to use `set-minibuffer-window'
> for setting up the minibuffer-window to use for
> a minibuffer-less frame, I'm completely lost.

I'm sorry I can't help either, here.  I know less about this than you do -
especially wrt Emacs windows, for which you are the expert.

> If with emacs -Q I do
> (let ((frame-1 (make-frame '((minibuffer . only))))
>       (frame-2 (make-frame '((minibuffer . nil)))))
>    (set-minibuffer-window (frame-root-window frame-1)))
> 
> then I still can't delete the initial frame because the
> minibuffer-window for frame-2 is that of the initial frame.

Ah, there I can help, in a minimal way at least, by confirming.  I don't know
why, and I cannot really explain anything here, but yes:

If you want a standalone minibuffer frame to have the _only_ minibuffer then you
must do everything at load time, i.e., in .emacs.  That is why I have provided
bug-repro recipes in the past that used this:

 runemacs.exe -Q -l "hexrgb.el" -l "oneonone.el" -f "1on1-emacs"

Command `1on1-emacs' must be run before the initial frame is created.
Otherwise, there will be a frame that has its own minibuffer, and you will never
be able to get rid of that frame (as you discovered).

IOW, it is too late to create your standalone minibuffer, once Emacs has already
created a frame with a normal minibuffer.  Whether this SHOULD be the case I
cannot answer, but it has always been the case with Gnu Emacs, AFAIK.

That is why I tell users of oneonone.el that they must do this:
  (require 'oneonone)
  (1on1-emacs)
rather than just invoke `1on1-emacs' after Emacs has already created its initial
frame, e.g., `M-x 1on1-emacs'.

With the simple reproducible test case above, we are making real progress.  I
hope we can finally find a solution to this problem.  My guess is that it lies
at the root of a majority of the problems I've had with GNU Emacs and frames -
problems that I have been trying to work around for decades.

FWIW:

Many Moon Ago, I used Epoch, which offered, out of the box, the ability to have
a standalone minibuffer frame (they did not call it that), which stretched
across the bottom of your display (by default).  (No customization necessary -
maybe you used a command switch when invoking the editor, I don't recall.)

I found that to be a wonderful, simple, reasonable way to interact with Emacs
(yes, Epoch was as much Emacs as GNU Emacs is).  And I tried to reproduce that
behavior in GNU Emacs.  I've come close, but this problem, in particular, has
always plagued me to some extent in my attempts.