Subject: Re: bug#69915: 30.0.50; mouse-autoselect-window has no effect in terminal

From: Olaf Rogalsky <[email-masked]>
Date: Sun, 24 Mar 2024 20:27:55 +0100

Hi Jared,

thanks for your feedback (answering this from my gmail account and
hope this doesn't mess up the debbugs history).

> A few other pieces of feedback (you may find it easier to generate the
> events in xterm-mouse-translate-1 to address):
Yes, I think you are right. I refactored my code accordingly, see the new patch
below.

> Are you certain you need the change to window.el as well? I'd be very
> surprised if it is necessary to change
...
> Is your setup is different somehow?
No, but I forgot to mention, that the "nil <select-window> is undefined" error
only occurred, iff mouse-autoselect-window had a numeric value.
With my new patch, the error disappeared. I don't know why, but a
change to window.el
isn't necessary anymore. I still think, that the proposed change would
be correct.

> <select-window> events shouldn't be generated while the mouse is being
> dragged. This probably is reflected in fully by track-mouse, but I'd
> suggest looking at the native code that generates the event to confirm.
Truly understanding xterm.c unfortunately is beyond my expertise. Nevertheless I
tested, the behavior. Dragging the mouse from one window to the next
(while passing over
the modeline) gives the following sequence of events:

 ESC [ < 3 5 ; 5 5 ; 4 1 M ESC [ < 0 ; 5 5 ; 4 1 M ;; mouse-drag-region
 ESC [ < 3 2 ; 5 5 ; 4 2 M             ;; anonymous-command
 ESC [ < 3 2 ; 5 5 ; 4 3 M             ;; anonymous-command
 <help-echo> ESC [ < 3 2 ; 5 5 ; 4 4 M ;; ignore
 ESC [ < 3 2 ; 5 6 ; 4 4 M             ;; anonymous-command
 ESC [ < 0 ; 5 6 ; 4 4 m               ;; anonymous-command
 <drag-mouse-1>                        ;; mouse-set-region

So indeed, no select-window event is generated. As a result, dragging
the mouse over the
borders of the window results in a scrolling of the window. This
matches the behavior of the
X11 backend.

> If there is a case where two events should be generated (not sure if
> this case exists depending on above), we'd want to return both, but you
> can only return a single key sequence from the translate function. I
> think this case deserves a FIXME note.
Can't follow you here. At which occasion two events might be generated
and which ones?

> Did you try out switching frames? I'm not certain if <select-window> is
> supposed to be generated when the frame is switched.
Switching frames is not handled in xt-mouse.el. However, if you change
the focus from another
X11 window to the title bar of the terminal or wise-versa, no
switch-frame event is generated. Instead,
xterm-translate-focus-in/xterm-translate-focus-out are called via a
binding in xterm-rxvt-function-map.
These functions toggle the terminal parameter tty-focus-state between
focused and defocused and then
call after-focus-change-function, which also does not generate a
switch-frame event.
As far as I could find out, the X11 backend of emacs doesn't generate
switch-frame events, either.

> Please name the new internal state variable with prefix "xt-mouse--".
I changed it to the terminal parameter xterm-mouse-last-window.

Regards, Olaf

New patch:
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
index 081b8f32456..8b405262168 100644
--- a/lisp/xt-mouse.el
+++ b/lisp/xt-mouse.el
@@ -60,7 +60,9 @@ xterm-mouse-translate-1
     (let* ((event (xterm-mouse-event extension))
           (ev-command (nth 0 event))
           (ev-data    (nth 1 event))
+          (ev-window  (nth 0 ev-data))
           (ev-where   (nth 1 ev-data))
+          (last-window (terminal-parameter nil 'xterm-mouse-last-window))
           (vec (vector event))
           (is-move (eq 'mouse-movement ev-command))
           (is-down (string-match "down-" (symbol-name ev-command))))
@@ -73,6 +75,9 @@ xterm-mouse-translate-1
                                 'mouse-movement
                               'mouse-click)))

+      ;; remember window of current mouse position
+      (set-terminal-parameter nil 'xterm-mouse-last-window ev-window)
+
       (cond
        ((null event) nil)              ;Unknown/bogus byte sequence!
        (is-down
@@ -84,10 +89,19 @@ xterm-mouse-translate-1
        vec)
        (is-move
         (xterm-mouse--handle-mouse-movement)
-        (if track-mouse vec
-          ;; Mouse movement events are currently supposed to be
-          ;; suppressed.  Return no event.
-          []))
+       (if (and mouse-autoselect-window ; after mouse movement
autoselect the mouse window, but ...
+                (windowp ev-window) ; ignore modeline, tab-bar,
menu-bar and so forth ...
+                ;;(not (posn-area (event-start event))) ; also
ignore, if not inside of text area of window ...
+                (not (eq ev-window last-window)) ; but only, if mouse
is over new window ...
+                (not (eq ev-window (selected-window)))) ; which is
different from the selected window
+           (progn
+             (put 'select-window 'event-kind 'switch-frame)
+             (setf (car event) 'select-window)
+             vec)
+          (if track-mouse vec
+            ;; Mouse movement events are currently supposed to be
+            ;; suppressed.  Return no event.
+            [])))
        (t
        (let* ((down (terminal-parameter nil 'xterm-mouse-last-down))
               (down-data (nth 1 down))