aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/NEWS16
-rw-r--r--lisp/mouse.el13
-rw-r--r--lisp/mwheel.el21
-rw-r--r--lisp/xt-mouse.el20
-rw-r--r--src/keyboard.c13
-rw-r--r--src/xterm.c53
6 files changed, 90 insertions, 46 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 2654d9d7995..7ebaeac986a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -68,6 +68,12 @@ more details.
68 68
69* Incompatible Changes in Emacs 30.1 69* Incompatible Changes in Emacs 30.1
70 70
71** Mouse wheel events should now always be 'wheel-up/down/left/right'.
72At those places where the old 'mouse-4/5/6/7' events could still occur
73(i.e. X11 input in the absence of XInput2, and 'xterm-mouse-mode'),
74we remap them to the corresponding 'wheel-up/down/left/right' event,
75according to the new variable 'mouse-wheel-buttons'.
76
71** Tree-Sitter modes are now declared as submodes of the non-TS modes. 77** Tree-Sitter modes are now declared as submodes of the non-TS modes.
72In order to help the use of those Tree-Sitter modes, they are now 78In order to help the use of those Tree-Sitter modes, they are now
73declared to have the corresponding non-Tree-Sitter mode as an 79declared to have the corresponding non-Tree-Sitter mode as an
@@ -520,15 +526,15 @@ In batch mode, tracing now sends the trace to stdout.
520** Mwheel 526** Mwheel
521The 'wheel-up/down/left/right' events are now bound unconditionally, 527The 'wheel-up/down/left/right' events are now bound unconditionally,
522and the 'mouse-wheel-up/down/left/right-event' variables are thus used 528and the 'mouse-wheel-up/down/left/right-event' variables are thus used
523only to specify the 'mouse-4/5/6/7' events generated by older 529only to specify the 'mouse-4/5/6/7' events that might still
524configurations such as X11 when the X server does not support at least 530happen to be generated by some old packages (or if 'mouse-wheel-buttons'
525version 2.1 of the X Input Extension, and 'xterm-mouse-mode'. 531has been set to nil).
526 532
527** 'xterm-mouse-mode' 533** 'xterm-mouse-mode'
528This mode now emits 'wheel-up/down/right/left' events instead of 534This mode now emits 'wheel-up/down/right/left' events instead of
529'mouse-4/5/6/7' events for the mouse wheel. 535'mouse-4/5/6/7' events for the mouse wheel.
530It uses the 'mouse-wheel-up/down/left/right-event' 536It uses the new variable 'mouse-wheel-buttons' to decide which button
531variables to decide which button maps to which wheel event (if any). 537maps to which wheel event (if any).
532 538
533** Info 539** Info
534 540
diff --git a/lisp/mouse.el b/lisp/mouse.el
index cef88dede8a..410e52b2ecb 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -133,6 +133,19 @@ or macOS)."
133 :type 'boolean 133 :type 'boolean
134 :version "29.1") 134 :version "29.1")
135 135
136(defcustom mouse-wheel-buttons
137 '((4 . wheel-up) (5 . wheel-down) (6 . wheel-left) (7 . wheel-right))
138 "How to remap mouse button numbers to wheel events.
139This is an alist of (NUMBER . SYMBOL) used to remap old-style mouse wheel
140events represented as mouse button events. It remaps mouse button
141NUMBER to the event SYMBOL. SYMBOL must be one of `wheel-up', `wheel-down',
142`wheel-left', or `wheel-right'.
143This is used only for events that come from sources known to generate such
144events, such as X11 events when XInput2 is not used, or events coming from
145a text terminal."
146 :type '(alist)
147 :version "30.1")
148
136(defvar mouse--last-down nil) 149(defvar mouse--last-down nil)
137 150
138(defun mouse--down-1-maybe-follows-link (&optional _prompt) 151(defun mouse--down-1-maybe-follows-link (&optional _prompt)
diff --git a/lisp/mwheel.el b/lisp/mwheel.el
index 66a1fa1a706..9fc922eebc9 100644
--- a/lisp/mwheel.el
+++ b/lisp/mwheel.el
@@ -56,20 +56,17 @@
56 (bound-and-true-p mouse-wheel-mode)) 56 (bound-and-true-p mouse-wheel-mode))
57 (mouse-wheel-mode 1))) 57 (mouse-wheel-mode 1)))
58 58
59(defvar mouse-wheel-obey-old-style-wheel-buttons t 59(make-obsolete-variable 'mouse-wheel-up-event 'mouse-wheel-buttons "30.1")
60 "If non-nil, treat mouse-4/5/6/7 events as mouse wheel events. 60(make-obsolete-variable 'mouse-wheel-down-event 'mouse-wheel-buttons "30.1")
61These are the event names used historically in X11 before XInput2. 61(make-obsolete-variable 'mouse-wheel-left-event 'mouse-wheel-buttons "30.1")
62They are sometimes generated by things like text-terminals as well.") 62(make-obsolete-variable 'mouse-wheel-right-event 'mouse-wheel-buttons "30.1")
63 63
64(defcustom mouse-wheel-down-event 64(defcustom mouse-wheel-down-event 'mouse-4
65 (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-4)
66 "Event used for scrolling down, beside `wheel-up', if any." 65 "Event used for scrolling down, beside `wheel-up', if any."
67 :group 'mouse 66 :group 'mouse
68 :type 'symbol 67 :type 'symbol
69 :set #'mouse-wheel-change-button) 68 :set #'mouse-wheel-change-button)
70 69(defcustom mouse-wheel-up-event 'mouse-5
71(defcustom mouse-wheel-up-event
72 (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-5)
73 "Event used for scrolling up, beside `wheel-down', if any." 70 "Event used for scrolling up, beside `wheel-down', if any."
74 :group 'mouse 71 :group 'mouse
75 :type 'symbol 72 :type 'symbol
@@ -223,12 +220,10 @@ Also see `mouse-wheel-tilt-scroll'."
223(defvar mwheel-scroll-right-function 'scroll-right 220(defvar mwheel-scroll-right-function 'scroll-right
224 "Function that does the job of scrolling right.") 221 "Function that does the job of scrolling right.")
225 222
226(defvar mouse-wheel-left-event 223(defvar mouse-wheel-left-event 'mouse-6
227 (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-6)
228 "Event used for scrolling left, beside `wheel-left', if any.") 224 "Event used for scrolling left, beside `wheel-left', if any.")
229 225
230(defvar mouse-wheel-right-event 226(defvar mouse-wheel-right-event 'mouse-7
231 (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-7)
232 "Event used for scrolling right, beside `wheel-right', if any.") 227 "Event used for scrolling right, beside `wheel-right', if any.")
233 228
234(defun mouse-wheel--get-scroll-window (event) 229(defun mouse-wheel--get-scroll-window (event)
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
index 081b8f32456..c27dee7e249 100644
--- a/lisp/xt-mouse.el
+++ b/lisp/xt-mouse.el
@@ -40,8 +40,6 @@
40 40
41;;; Code: 41;;; Code:
42 42
43(require 'mwheel)
44
45(defvar xterm-mouse-debug-buffer nil) 43(defvar xterm-mouse-debug-buffer nil)
46 44
47(defun xterm-mouse-translate (_event) 45(defun xterm-mouse-translate (_event)
@@ -195,12 +193,6 @@ single byte."
195 (cons n c)) 193 (cons n c))
196 (cons (- (setq c (xterm-mouse--read-coordinate)) 32) c)))) 194 (cons (- (setq c (xterm-mouse--read-coordinate)) 32) c))))
197 195
198(defun xterm-mouse--button-p (event btn)
199 (and (symbolp event)
200 (string-prefix-p "mouse-" (symbol-name event))
201 (eq btn (car (read-from-string (symbol-name event)
202 (length "mouse-"))))))
203
204;; XTerm reports mouse events as 196;; XTerm reports mouse events as
205;; <EVENT-CODE> <X> <Y> in default mode, and 197;; <EVENT-CODE> <X> <Y> in default mode, and
206;; <EVENT-CODE> ";" <X> ";" <Y> <"M" or "m"> in extended mode. 198;; <EVENT-CODE> ";" <X> ";" <Y> <"M" or "m"> in extended mode.
@@ -246,14 +238,10 @@ single byte."
246 (if meta "M-" "") 238 (if meta "M-" "")
247 (if shift "S-" "") 239 (if shift "S-" "")
248 (if down "down-" "") 240 (if down "down-" "")
249 (cond 241 (let ((remap (alist-get btn mouse-wheel-buttons)))
250 ;; BEWARE: `mouse-wheel-UP-event' corresponds to 242 (if remap
251 ;; `wheel-DOWN' events and vice versa!! 243 (symbol-name remap)
252 ((xterm-mouse--button-p mouse-wheel-down-event btn) "wheel-up") 244 (format "mouse-%d" btn))))))))
253 ((xterm-mouse--button-p mouse-wheel-up-event btn) "wheel-down")
254 ((xterm-mouse--button-p mouse-wheel-left-event btn) "wheel-left")
255 ((xterm-mouse--button-p mouse-wheel-right-event btn) "wheel-right")
256 (t (format "mouse-%d" btn))))))))
257 (list sym (1- x) (1- y)))) 245 (list sym (1- x) (1- y))))
258 246
259(defun xterm-mouse--set-click-count (event click-count) 247(defun xterm-mouse--set-click-count (event click-count)
diff --git a/src/keyboard.c b/src/keyboard.c
index 91faf4582fa..a06c9116d24 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -6639,8 +6639,17 @@ make_lispy_event (struct input_event *event)
6639 6639
6640 if (CONSP (event->arg)) 6640 if (CONSP (event->arg))
6641 return list5 (head, position, make_fixnum (double_click_count), 6641 return list5 (head, position, make_fixnum (double_click_count),
6642 XCAR (event->arg), Fcons (XCAR (XCDR (event->arg)), 6642 XCAR (event->arg),
6643 XCAR (XCDR (XCDR (event->arg))))); 6643 /* FIXME: When a mouse-click on a tab-bar is
6644 converted into a wheel-event we get here something
6645 of an unexpected shape... */
6646 (CONSP (XCDR (event->arg))
6647 && CONSP (XCDR (XCDR (event->arg))))
6648 ? Fcons (XCAR (XCDR (event->arg)),
6649 XCAR (XCDR (XCDR (event->arg))))
6650 /* ... not knowing what this "unexpected shape" means,
6651 we just use nil. */
6652 : Qnil);
6644 else if (NUMBERP (event->arg)) 6653 else if (NUMBERP (event->arg))
6645 return list4 (head, position, make_fixnum (double_click_count), 6654 return list4 (head, position, make_fixnum (double_click_count),
6646 event->arg); 6655 event->arg);
diff --git a/src/xterm.c b/src/xterm.c
index c0aef65ab66..5e5eb6269e4 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -14551,18 +14551,19 @@ x_query_pointer (Display *dpy, Window w, Window *root_return,
14551 `x', `y', `x_root' and `y_root'. This function should not access 14551 `x', `y', `x_root' and `y_root'. This function should not access
14552 any other fields in EVENT without also initializing the 14552 any other fields in EVENT without also initializing the
14553 corresponding fields in `bv' under the XI_ButtonPress and 14553 corresponding fields in `bv' under the XI_ButtonPress and
14554 XI_ButtonRelease labels inside `handle_one_xevent'. */ 14554 XI_ButtonRelease labels inside `handle_one_xevent'.
14555
14556 XI2 indicates that this click comes from XInput2 rather than core
14557 event. */
14555 14558
14556static Lisp_Object 14559static Lisp_Object
14557x_construct_mouse_click (struct input_event *result, 14560x_construct_mouse_click (struct input_event *result,
14558 const XButtonEvent *event, 14561 const XButtonEvent *event,
14559 struct frame *f) 14562 struct frame *f, bool xi2)
14560{ 14563{
14561 int x = event->x; 14564 int x = event->x;
14562 int y = event->y; 14565 int y = event->y;
14563 14566
14564 /* Make the event type NO_EVENT; we'll change that when we decide
14565 otherwise. */
14566 result->kind = MOUSE_CLICK_EVENT; 14567 result->kind = MOUSE_CLICK_EVENT;
14567 result->code = event->button - Button1; 14568 result->code = event->button - Button1;
14568 result->timestamp = event->time; 14569 result->timestamp = event->time;
@@ -14572,6 +14573,29 @@ x_construct_mouse_click (struct input_event *result,
14572 ? up_modifier 14573 ? up_modifier
14573 : down_modifier)); 14574 : down_modifier));
14574 14575
14576 /* Convert pre-XInput2 wheel events represented as mouse-clicks. */
14577 if (!xi2)
14578 {
14579 Lisp_Object base
14580 = Fcdr_safe (Fassq (make_fixnum (result->code + 1),
14581 Fsymbol_value (Qmouse_wheel_buttons)));
14582 int wheel
14583 = (NILP (base) ? -1
14584 : BASE_EQ (base, Qwheel_down) ? 0
14585 : BASE_EQ (base, Qwheel_up) ? 1
14586 : BASE_EQ (base, Qwheel_left) ? 2
14587 : BASE_EQ (base, Qwheel_right) ? 3
14588 : -1);
14589 if (wheel >= 0)
14590 {
14591 result->kind = (event->type != ButtonRelease ? NO_EVENT
14592 : wheel & 2 ? HORIZ_WHEEL_EVENT : WHEEL_EVENT);
14593 result->code = 0; /* Not used. */
14594 result->modifiers &= ~(up_modifier || down_modifier);
14595 result->modifiers |= wheel & 1 ? up_modifier : down_modifier;
14596 }
14597 }
14598
14575 /* If result->window is not the frame's edit widget (which can 14599 /* If result->window is not the frame's edit widget (which can
14576 happen with GTK+ scroll bars, for example), translate the 14600 happen with GTK+ scroll bars, for example), translate the
14577 coordinates so they appear at the correct position. */ 14601 coordinates so they appear at the correct position. */
@@ -21881,13 +21905,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21881 && event->xbutton.time > ignore_next_mouse_click_timeout) 21905 && event->xbutton.time > ignore_next_mouse_click_timeout)
21882 { 21906 {
21883 ignore_next_mouse_click_timeout = 0; 21907 ignore_next_mouse_click_timeout = 0;
21884 x_construct_mouse_click (&inev.ie, &event->xbutton, f); 21908 x_construct_mouse_click (&inev.ie, &event->xbutton,
21909 f, false);
21885 } 21910 }
21886 if (event->type == ButtonRelease) 21911 if (event->type == ButtonRelease)
21887 ignore_next_mouse_click_timeout = 0; 21912 ignore_next_mouse_click_timeout = 0;
21888 } 21913 }
21889 else 21914 else
21890 x_construct_mouse_click (&inev.ie, &event->xbutton, f); 21915 x_construct_mouse_click (&inev.ie, &event->xbutton, f, false);
21891 21916
21892 *finish = X_EVENT_DROP; 21917 *finish = X_EVENT_DROP;
21893 goto OTHER; 21918 goto OTHER;
@@ -21957,13 +21982,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21957 && event->xbutton.time > ignore_next_mouse_click_timeout) 21982 && event->xbutton.time > ignore_next_mouse_click_timeout)
21958 { 21983 {
21959 ignore_next_mouse_click_timeout = 0; 21984 ignore_next_mouse_click_timeout = 0;
21960 x_construct_mouse_click (&inev.ie, &event->xbutton, f); 21985 x_construct_mouse_click (&inev.ie, &event->xbutton,
21986 f, false);
21961 } 21987 }
21962 if (event->type == ButtonRelease) 21988 if (event->type == ButtonRelease)
21963 ignore_next_mouse_click_timeout = 0; 21989 ignore_next_mouse_click_timeout = 0;
21964 } 21990 }
21965 else 21991 else
21966 x_construct_mouse_click (&inev.ie, &event->xbutton, f); 21992 x_construct_mouse_click (&inev.ie, &event->xbutton,
21993 f, false);
21967 21994
21968 if (!NILP (tab_bar_arg)) 21995 if (!NILP (tab_bar_arg))
21969 inev.ie.arg = tab_bar_arg; 21996 inev.ie.arg = tab_bar_arg;
@@ -23740,13 +23767,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23740 && xev->time > ignore_next_mouse_click_timeout) 23767 && xev->time > ignore_next_mouse_click_timeout)
23741 { 23768 {
23742 ignore_next_mouse_click_timeout = 0; 23769 ignore_next_mouse_click_timeout = 0;
23743 x_construct_mouse_click (&inev.ie, &bv, f); 23770 x_construct_mouse_click (&inev.ie, &bv, f, true);
23744 } 23771 }
23745 if (xev->evtype == XI_ButtonRelease) 23772 if (xev->evtype == XI_ButtonRelease)
23746 ignore_next_mouse_click_timeout = 0; 23773 ignore_next_mouse_click_timeout = 0;
23747 } 23774 }
23748 else 23775 else
23749 x_construct_mouse_click (&inev.ie, &bv, f); 23776 x_construct_mouse_click (&inev.ie, &bv, f, true);
23750 23777
23751 if (!NILP (tab_bar_arg)) 23778 if (!NILP (tab_bar_arg))
23752 inev.ie.arg = tab_bar_arg; 23779 inev.ie.arg = tab_bar_arg;
@@ -32452,6 +32479,12 @@ syms_of_xterm (void)
32452 DEFSYM (Qexpose, "expose"); 32479 DEFSYM (Qexpose, "expose");
32453 DEFSYM (Qdont_save, "dont-save"); 32480 DEFSYM (Qdont_save, "dont-save");
32454 32481
32482 DEFSYM (Qmouse_wheel_buttons, "mouse-wheel-buttons");
32483 DEFSYM (Qwheel_up, "wheel-up");
32484 DEFSYM (Qwheel_down, "wheel-down");
32485 DEFSYM (Qwheel_left, "wheel-left");
32486 DEFSYM (Qwheel_right, "wheel-right");
32487
32455#ifdef USE_GTK 32488#ifdef USE_GTK
32456 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); 32489 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
32457 staticpro (&xg_default_icon_file); 32490 staticpro (&xg_default_icon_file);