Subject: Re: bug#49803: 27.2; Mouse wheel on MacOS is reported as mouse-4 and mouse-5, but Emacs mwheel seems to use wheel-up/wheel-down instead

From: Robert Pluim <[email-masked]>
Date: Wed, 11 Aug 2021 19:10:51 +0200

>>>>> On Wed, 11 Aug 2021 19:41:27 +0300, Eli Zaretskii <[email-masked]> said:

    >> From: Robert Pluim <[email-masked]>
    >> Cc: [email-masked],  [email-masked]
    >> Date: Wed, 11 Aug 2021 16:59:45 +0200
    >> 
    Eli> Does the xterm protocol allow to report wheel events, or does it only
    Eli> allow to report mouse-click events?  If the latter, I don't see how
    Eli> you could map the events in any way different from what we have now,
    Eli> i.e. via a user-controlled setting.
    >> 
    >> It allows reporting wheel events, but as that part of the protocol is
    >> not being used by the iterm2 everything is reported as mouse clicks,
    >> but thatʼs immaterial:
    >> 
    >> - terminal sends "\e[<" to indicate itʼs sending us a mouse event
    >> - xt-mouse.el reads and decodes a bunch of stuff from the terminal
    >> - xt-mouse.el produces a 'mouse-<n>' event from that bunch of stuff, and
    >> pushes it onto 'unread-command-events'

    Eli> But then any mapping of mouse-4 etc. to wheel events is pure
    Eli> heuristics, right?  There are mice out there which have more than 3
    Eli> buttons, and they can legitimately produce mouse-4 for the 4th button,
    Eli> right?

Absolutely

    >> So the only place I can see to add the optional mapping is in xt-mouse.el
    >> itself, or in 'read-char' in keyboard.c
    >> 
    >> Itʼs easier to do in xt-mouse.el, and as far as I can tell thatʼs the
    >> only terminal mouse handling code that does this kind of thing (GPM is
    >> handled in keyboard.c)

    Eli> If I'm right, and this mapping is based on heuristics, we cannot
    Eli> hard-code it, we must allow users to control the mapping in case the
    Eli> heuristics fails.  Or am I missing something?

Something like this. We can discuss if xterm-mouse-map-buttons should
default to t on ns-win or not. I think it should, because then using
the mouse wheel with builtin and external trackpads becomes:

(require 'mwheel)
(require 'mouse)
(xterm-mouse-mode t)
(mouse-wheel-mode t)

with no other configuration required.

diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
index 72faff8101..7906a6a024 100644
--- a/lisp/xt-mouse.el
+++ b/lisp/xt-mouse.el
@@ -42,6 +42,28 @@
 
 (defvar xterm-mouse-debug-buffer nil)
 
+(defcustom xterm-mouse-map-buttons
+  (if (featurep 'ns-win)
+      t
+    nil)
+  "Non-nil if xterm should perfom mouse button mappings.
+Will use `xterm-mouse-map-buttons-alist' for the mapping.
+Defaults to t when using macOS for consistency with 'mwheel'."
+  :type 'boolean
+  :version "28.1"
+  :group 'xterm)
+
+(defcustom xterm-mouse-map-buttons-alist
+  '((mouse-4 . wheel-up)
+    (mouse-5 . wheel-down))
+  "Alist used to map buttons to different buttons.
+Only consulted if `xterm-mouse-map-buttons' is non-nil.  The
+default value maps 'mouse-4' and 'mouse-5 to 'wheel-up' and
+'wheel-down'."
+  :type 'alist
+  :version "28.1"
+  :group 'xterm)
+
 (defun xterm-mouse-translate (_event)
   "Read a click and release event from XTerm."
   (xterm-mouse-translate-1))
@@ -65,8 +87,12 @@ xterm-mouse-translate-1
 
       ;; Mouse events symbols must have an 'event-kind property with
       ;; the value 'mouse-click.
-      (when ev-command (put ev-command 'event-kind 'mouse-click))
-
+      (when ev-command
+        (put ev-command 'event-kind 'mouse-click)
+        (when xterm-mouse-map-buttons
+          (when-let (mapping (alist-get ev-command xterm-mouse-map-buttons-alist))
+            (setq ev-command mapping)
+            (setf (nth 0 event) ev-command))))
       (cond
        ((null event) nil)		;Unknown/bogus byte sequence!
        (is-down

Robert
--