Subject: bug#10037: 24.0.91; `isearch-mouse-2' no good with standalone minibuffer frame

From: "Drew Adams" <[email-masked]>
Date: Mon, 14 Nov 2011 14:54:29 -0800

> The selected text should be inserted into the search string.  Instead,
> Isearch is exited.  A guess would be that this is because of a
> switch-frame event.

A little debugging showed that this is indeed the case.
The `isearch-mouse-2' code does this:

(defun isearch-mouse-2 (click)
  "..."
  (interactive "e")
  (let* ((w (posn-window (event-start click)))
         (overriding-terminal-local-map nil)
         (binding (key-binding (this-command-keys-vector) t)))
    (if (and (window-minibuffer-p w)
             (not (minibuffer-window-active-p w)))
      (isearch-yank-x-selection)
      (when (functionp binding)
        (call-interactively binding)))))

When you click mouse-2 in a standalone minibuffer, `this-command-keys-vector'
corresponds to a switch-frame event.  `switch-frame' is bound to nil in
`isearch-mode-map', so `key-binding' returns nil.

What I do not understand is why handling the `switch-frame' event in the normal
way would exit Isearch.  But that is what I see on Windows, even with `emacs
-Q': Isearch exits.

These comments in the isearch.el code suggest that `switch-frame'
(intentionally) does NOT exit Isearch:

;; Pass frame events transparently so they won't exit the search.
;; In particular, if we have more than one display open, then a
;; switch-frame might be generated by someone typing at another keyboard.

But Isearch does exit - at least that is what I see on Windows.  Is this a bug,
perhaps a Windows-specific bug?  Do `switch-frame' events on Linux also cause
Isearch to exit, in contradiction to the Isearch code comment above?

In my case, I bind `down-mouse-2' globally to a command,
`mouse-flash-position-or-M-x'.  During Isearch I do not want this command to be
invoked when I click `mouse-2' in the minibuffer.  So I bind `down-mouse-2' in
Isearch to `ignore' instead of nil, to prevent such invocation.  That works,
when there is no standalone minibuffer frame (so no `switch-frame' event).

But because I usually have a standalone minibuffer frame, that is not a complete
solution.  The `switch-frame' event occurs (just) before the `down-mouse-2', so
Isearch mode has already been exited when `down-mouse-2' is clicked in the
standalone minibuffer frame.  Neither the `down-mouse-2' Isearch binding nor the
`mouse-2' Isearch binding is invoked, because Isearch is finished.  The
`down-mouse-2' event invokes the globally bound command instead,
`mouse-flash-position-or-M-x'.

So to fix that I now do the same thing for `switch-frame' as for `down-mouse-2':
bind it to `ignore' instead of nil.  That works OK.  Clicking `mouse-2' in any
frame then does not exit Isearch.  (And yet, the frame seems to be switched to.)

This seems like a workaround, however.  According to the nil binding and the
Isearch code comments for it, it seems like a `switch-frame' event should NOT
exit Isearch.  Please let me know whether you think this is a bug and could be
fixed.  (In that case I would bind `switch-frame' to `ignore' only for older
Emacs releases.)

The Isearch code currently has several `isearch-mode-map' bindings of nil:

(define-key map [switch-frame] nil)
(define-key map [delete-frame] nil)
(define-key map [iconify-frame] nil)
(define-key map [make-frame-visible] nil)
(define-key map [mouse-movement] nil)
(define-key map [language-change] nil)
(define-key map [down-mouse-2] nil)

Dunno what a better default binding might be for some of them, but AFAICT for my
setup of a standalone minibuffer, binding `switch-frame' and `down-mouse-2' to
`ignore' takes care of the problems I encountered.