From unknown Tue Jul 15 19:29:05 2025 X-Loop: help-debbugs@gnu.org Subject: bug#43379: [PATCH] Double-click events can occur without preceding single-click events Resent-From: Daniel Koning Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 13 Sep 2020 17:01:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 43379 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: 43379@debbugs.gnu.org X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.160001644214942 (code B ref -1); Sun, 13 Sep 2020 17:01:02 +0000 Received: (at submit) by debbugs.gnu.org; 13 Sep 2020 17:00:42 +0000 Received: from localhost ([127.0.0.1]:51552 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kHVMm-0003su-NV for submit@debbugs.gnu.org; Sun, 13 Sep 2020 13:00:41 -0400 Received: from lists.gnu.org ([209.51.188.17]:35384) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kHVMj-0003sk-GO for submit@debbugs.gnu.org; Sun, 13 Sep 2020 13:00:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:36002) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHVMh-0007wy-RP for bug-gnu-emacs@gnu.org; Sun, 13 Sep 2020 13:00:37 -0400 Received: from sender4-of-o56.zoho.com ([136.143.188.56]:21636) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kHVMb-00080l-Dk for bug-gnu-emacs@gnu.org; Sun, 13 Sep 2020 13:00:35 -0400 ARC-Seal: i=1; a=rsa-sha256; t=1600016423; cv=none; d=zohomail.com; s=zohoarc; b=iDLc8yt/9F8u444HZiGLtsdP3aCFqZhyyybqRaWNNDLLcGcaqJ8YE7JQAs2jfi0mHOTV8+p2ng27z6adr8Qd7RLKI0rHIG7Q21gr8Xgxu+aaJGXBhzC7WSLi26cEv9Q9+QuIW/o0EfvhhRLlu/eGBlWIDSEwkNpaKNUBHbgjUE0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1600016423; h=Content-Type:Date:From:MIME-Version:Message-ID:Subject:To; bh=cLkKtiUAWzKEgwK69xofN5eU0pex71zj2EIn0Y2wN98=; b=mHiHQ7Jiw/TwSs5x6uiC8lfiSd3KPhS4Lmr0qrt+4LCIDKG0UI6wpZS8ZZ29FXh8Q5ieJGzmVY4Ysr9HZDh1AAnlNAW1Jf8LJAQ2jwnJt1rsxYgM1HcICyb8t6XnuKOsSHLGDAEaStAmvpACmgNQ8JnXDh2zDe/SCQNF/NBHBPA= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass smtp.mailfrom=dk@danielkoning.com; dmarc=pass header.from= header.from= Received: from cornelius (112.157.239.35.bc.googleusercontent.com [35.239.157.112]) by mx.zohomail.com with SMTPS id 160001642181849.76418151456926; Sun, 13 Sep 2020 10:00:21 -0700 (PDT) From: Daniel Koning Date: Sun, 13 Sep 2020 12:00:10 -0500 Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Zoho-Virus-Status: 1 X-ZohoMailClient: External Received-SPF: pass client-ip=136.143.188.56; envelope-from=dk@danielkoning.com; helo=sender4-of-o56.zoho.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/13 13:00:25 X-ACL-Warn: Detected OS = Linux 3.11 and newer [fuzzy] X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.3 (-) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) --=-=-= Content-Type: text/plain According to the documentation (21.7.7 of the Lisp ref, "Repeat Events"), a double-click binding should "assume that the single-click command has already run," since Emacs only produces a double-click event after an equivalent single-click event. But (so long as 'double-click-time' is set generously enough) it's easy to trigger a double-click event without a corresponding single-click event, because the event handling primitives aren't quite particular enough about what they count as a repeat. For one thing, the code ignores whether the modifier keys of one input action differ from the next. So the sequence "M-mouse-1 mouse-1" produces . This is no good: is likely bound to something different from , so the command will run under false premises. It also uses just one repeat click counter, despite the fact that down/up click event pairs can be interleaved. The counter increments when a button-down matches the last button-up, and it carries over to whatever button-up comes in next. Therefore, the mouse sequence down on mouse-1 down on mouse-3 up on mouse-1 down on mouse-1 up on mouse-3 produces a event with no preceding . The function 'make_lispy_event', which translates raw events to Lisp objects, is responsible for tagging a mouse event (button-down, click, drag, or wheel) as a double. This patch against master revises that function to avoid creating "bare" double mouse events. It does so by consolidating the scattered repeat-tracking logic into its own function, where more relevant state can be maintained without any extra global cruft. (With less cruft, in fact: 'button_down_time' is no longer punned as an interrupt flag, wheel event codes need not be coerced to negative to stuff them into the same variable as clicks, etc.) Just as before, a repeat mouse event has to use the same button, happen in roughly the same place, happen at roughly the same time, and so on. Aside from the specific deliberate narrowing I've described, I believe this code duplicates the logic of the old code exactly. That includes nuances that strike me as strange. For instance, down on mouse-1 up on mouse-1 down on mouse-1 keystroke up on mouse-1 down on mouse-1 finishes with , even though it would make more sense to me if the keystroke reset the count right away. But that's how it was before. There is still at least one fringy situation in which a command could run without the command running first: when the first and second click land in different windows. I would have liked to add a test for this, but I don't fully understand the type constraint on the 'frame_or_window' member of struct input_event (specifically when it's a mouse event). 'make_lispy_event' seems to assume it's a frame: it does an XFRAME without a check. But then the comparison against 'double-click-fuzz', which I folded into the new function, tries both possibilities. I left the more cautious code in place, and I haven't added any more logic related to windows. This also has no effect on xterm-mouse-mode, which doesn't interact with the C event translator at all. It just takes key sequences which have already passed through 'make_lispy_event' and translates them to mouse-event lists. xterm-mouse-mode has some major inconsistencies with the GUI repeat-handling behavior, but it doesn't seem to exhibit the bug this report describes. This patch rewords the docs slightly to say explicitly that modifier keys make a difference. It also makes a small tweak to the criteria for drag events, and another tweak to the Cocoa-specific trackpad code to fix a conspicuous bug caused by a similar oversight. Namely, newly pressed modifier keys can attach to invisible so-called "momentum" events generated by a swipe on the trackpad that has already ended. One result is that if a Cocoa user scrolls up to the top of the buffer and immediately presses (say) C-e, Emacs gets barraged with events and scales the buffer text up to a ridiculous size. Daniel --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=repeat-events.patch >From 8acd0adbaffc20cda484031723a625b361472293 Mon Sep 17 00:00:00 2001 From: Daniel Koning Date: Tue, 1 Sep 2020 18:56:12 -0500 Subject: [PATCH 1/6] Detect repeat mouse events more stringently If two closely spaced mouse events come in with different modifier keys, never treat the second as a double. Also, be stricter about the sequencing of overlapping clicks, where one button goes down before the other comes up. * src/keyboard.c (mouse_repeat_count): New function. (interrupt_next_repeat_click): New global variable. (make_lispy_event): Delegate to 'mouse_repeat_count'. * doc/emacs/custom.texi (Mouse Buttons): Clarify the behavior for users. * doc/lispref/commands.texi (Repeat Events): Clarify the behavior for Lisp programmers. * etc/NEWS: Describe the change. --- doc/emacs/custom.texi | 8 +- doc/lispref/commands.texi | 9 +- etc/NEWS | 10 ++ src/keyboard.c | 283 ++++++++++++++++++++++---------------- 4 files changed, 186 insertions(+), 124 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index a512fd14c8..a3ffd90c5b 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -2145,8 +2145,12 @@ Mouse Buttons The symbols for mouse events also indicate the status of the modifier keys, with the usual prefixes @samp{C-}, @samp{M-}, @samp{H-}, -@samp{s-}, @samp{A-}, and @samp{S-}. These always precede @samp{double-} -or @samp{triple-}, which always precede @samp{drag-} or @samp{down-}. +@samp{s-}, @samp{A-}, and @samp{S-}. These always precede +@samp{double-} or @samp{triple-}, which always precede @samp{drag-} or +@samp{down-}. (Two clicks with different modifier keys can never +produce a double event, no matter how close together the clicks are. +Otherwise, Emacs could get a @code{double-mouse-1} event without getting +a @code{mouse-1} event first.) A frame includes areas that don't show text from the buffer, such as the mode line and the scroll bar. You can tell whether a mouse button diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 25f657404f..93350927f2 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -1548,9 +1548,12 @@ Repeat Events @cindex triple-click events @cindex mouse events, repeated -If you press the same mouse button more than once in quick succession -without moving the mouse, Emacs generates special @dfn{repeat} mouse -events for the second and subsequent presses. +Emacs generates special @dfn{repeat} mouse events to represent actions +like double and triple clicks. If you press a button twice in quick +succession without moving the mouse in between, Emacs will designate the +second event as a repeat. (However, if you hold down any modifier keys +during one press and not the other, Emacs will treat the two events as +unconnected, and the second event will not be a repeat.) The most common repeat events are @dfn{double-click} events. Emacs generates a double-click event when you click a button twice; the event diff --git a/etc/NEWS b/etc/NEWS index ddc2fb9d60..5a45295f33 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -127,6 +127,16 @@ the mouse cursor is on the scroll bars, fringes, margins, header line, and mode line. ('mwheel-mode' is enabled by default on most graphical displays.) ++++ +** Repeat events are now produced only when the modifier keys are the same. +Before, when the user pressed the same mouse button repeatedly within +the bounds specified by 'double-click-fuzz' and 'double-click-time', +it always produced a 'double-' or 'triple-' event, even if the user +was holding down modifier keys on one click and not another. This +meant that it was possible for Emacs to read a double-click event +without reading the same kind of single-click event first. Emacs now +looks at modifier keys to determine if a mouse event is a repeat. + * Editing Changes in Emacs 28.1 diff --git a/src/keyboard.c b/src/keyboard.c index 590d183c4c..1214e62820 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -347,6 +347,7 @@ #define READABLE_EVENTS_IGNORE_SQUEEZABLES (1 << 2) static Lisp_Object read_char_x_menu_prompt (Lisp_Object, Lisp_Object, bool *); static Lisp_Object read_char_minibuf_menu_prompt (int, Lisp_Object); +static intmax_t mouse_repeat_count (const struct input_event *); static Lisp_Object make_lispy_event (struct input_event *); static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object, enum scroll_bar_part, @@ -5024,18 +5025,6 @@ #define ISO_FUNCTION_KEY_OFFSET 0xfe00 static Lisp_Object button_down_location; -/* Information about the most recent up-going button event: Which - button, what location, and what time. */ - -static int last_mouse_button; -static int last_mouse_x; -static int last_mouse_y; -static Time button_down_time; - -/* The number of clicks in this multiple-click. */ - -static int double_click_count; - /* X and Y are frame-relative coordinates for a click or wheel event. Return a Lisp-style event list. */ @@ -5306,6 +5295,139 @@ make_scroll_bar_position (struct input_event *ev, Lisp_Object type) builtin_lisp_symbol (scroll_bar_parts[ev->part])); } +/* Whether the next click (or wheel event) should be treated as a + single no matter what, even if a matching prior event would make it + a repeat. This gets flipped on when a keystroke or drag event + comes in: double clicks can't extend across one of those. */ + +static bool interrupt_next_repeat_click; + +/* If EVENT is a repeat, return the number of consecutive mouse events + so far. Return 1 otherwise. In the background, keep a record of + where we are in the current sequence of repeats. + + This should only receive a pointer to an event of an applicable + kind -- namely, a button-down, button-up, or wheel event. */ + +static intmax_t +mouse_repeat_count (const struct input_event *event) +{ + /* Keep persistent information about any chain of repeat events we + might be in the middle of. */ + + static ENUM_BF (event_kind) kind; + static unsigned code; + static unsigned keys; + static unsigned wheel_dir; + + static Time timeout_start; + static EMACS_INT x, y; + + static intmax_t count; + + /* Analyze the new event that came in. */ + + unsigned new_keys = event->modifiers & CHAR_MODIFIER_MASK; + unsigned new_wheel_dir; + + Time interval; + EMACS_INT new_x, new_y, offset; + + bool is_wheel = (event->kind == WHEEL_EVENT + || event->kind == HORIZ_WHEEL_EVENT); + bool is_button = !is_wheel; + bool is_button_up = (is_button && (event->modifiers & up_modifier)); + + if (is_wheel) + new_wheel_dir = (event->modifiers & (down_modifier | up_modifier)); + else + new_wheel_dir = 0; + + /* We need to update timestamp and position after both repeat and + non-repeat events. Make the relevant comparisons in advance, + then do the update immediately. */ + + interval = event->timestamp - timeout_start; + if (!is_button_up) + timeout_start = event->timestamp; + + new_x = XFIXNUM (event->x); + new_y = XFIXNUM (event->y); + offset = max (eabs (new_x - x), eabs (new_y - y)); + x = new_x; + y = new_y; + + /* Is this a repeat? Start checking for conditions that imply + otherwise. */ + + if (interrupt_next_repeat_click && !is_button_up) + { + interrupt_next_repeat_click = false; + goto not_a_repeat; + } + + if (event->kind != kind || event->code != code || new_keys != keys + || new_wheel_dir != wheel_dir) + goto not_a_repeat; + + if (is_button_up) + /* That's it for button-up events. At this point, we declare that + it's a repeat that should inherit the count of the preceding + button-down. */ + return count; + + if (FIXNATP (Vdouble_click_time)) + { + if (interval >= XFIXNAT (Vdouble_click_time)) + goto not_a_repeat; + } + else if (!EQ (Vdouble_click_time, Qt)) + goto not_a_repeat; + + { + /* On window-system frames, use the value of 'double-click-fuzz' + as is. On other frames, interpret it as a multiple of 1/8 + characters. */ + struct frame *f; + intmax_t fuzz; + + if (WINDOWP (event->frame_or_window)) + f = XFRAME (XWINDOW (event->frame_or_window)->frame); + else if (FRAMEP (event->frame_or_window)) + f = XFRAME (event->frame_or_window); + else + emacs_abort (); + + if (FRAME_WINDOW_P (f)) + fuzz = double_click_fuzz; + else + fuzz = double_click_fuzz / 8; + + if (offset > fuzz) + goto not_a_repeat; + } + + /* We've ruled out everything that could disqualify it as a repeat, + so treat it as one. */ + count++; + return count; + + not_a_repeat: + /* Base a new repeat chain off of this event. */ + count = 1; + kind = event->kind; + code = event->code; + keys = new_keys; + wheel_dir = new_wheel_dir; + + if (is_button_up) + /* A button-up event should cut off a chain when it doesn't match + the last event, but it shouldn't start its own chain. */ + interrupt_next_repeat_click = true; + + return count; +} + /* Given a struct input_event, build the lisp event which represents it. If EVENT is 0, build a mouse movement event from the mouse movement buffer, which should have a movement event in it. @@ -5438,7 +5560,7 @@ make_lispy_event (struct input_event *event) if ((event->code) == 040 && event->modifiers & shift_modifier) c |= shift_modifier; - button_down_time = 0; + interrupt_next_repeat_click = true; XSETFASTINT (lispy_c, c); return lispy_c; } @@ -5457,7 +5579,7 @@ make_lispy_event (struct input_event *event) /* A function key. The symbol may need to have modifier prefixes tacked onto it. */ case NON_ASCII_KEYSTROKE_EVENT: - button_down_time = 0; + interrupt_next_repeat_click = true; for (i = 0; i < ARRAYELTS (lispy_accent_codes); i++) if (event->code == lispy_accent_codes[i]) @@ -5546,10 +5668,10 @@ make_lispy_event (struct input_event *event) #endif { int button = event->code; - bool is_double; Lisp_Object position; Lisp_Object *start_pos_ptr; Lisp_Object start_pos; + int repeat_count; position = Qnil; @@ -5637,57 +5759,20 @@ make_lispy_event (struct input_event *event) mouse_syms = larger_vector (mouse_syms, incr, -1); } + repeat_count = mouse_repeat_count (event); + if (repeat_count == 2) + event->modifiers |= double_modifier; + else if (repeat_count >= 3) + event->modifiers |= triple_modifier; + start_pos_ptr = aref_addr (button_down_location, button); start_pos = *start_pos_ptr; *start_pos_ptr = Qnil; - { - /* On window-system frames, use the value of - double-click-fuzz as is. On other frames, interpret it - as a multiple of 1/8 characters. */ - struct frame *f; - intmax_t fuzz; - - if (WINDOWP (event->frame_or_window)) - f = XFRAME (XWINDOW (event->frame_or_window)->frame); - else if (FRAMEP (event->frame_or_window)) - f = XFRAME (event->frame_or_window); - else - emacs_abort (); - - if (FRAME_WINDOW_P (f)) - fuzz = double_click_fuzz; - else - fuzz = double_click_fuzz / 8; - - is_double = (button == last_mouse_button - && (eabs (XFIXNUM (event->x) - last_mouse_x) <= fuzz) - && (eabs (XFIXNUM (event->y) - last_mouse_y) <= fuzz) - && button_down_time != 0 - && (EQ (Vdouble_click_time, Qt) - || (FIXNATP (Vdouble_click_time) - && (event->timestamp - button_down_time - < XFIXNAT (Vdouble_click_time))))); - } - - last_mouse_button = button; - last_mouse_x = XFIXNUM (event->x); - last_mouse_y = XFIXNUM (event->y); - /* If this is a button press, squirrel away the location, so we can decide later whether it was a click or a drag. */ if (event->modifiers & down_modifier) { - if (is_double) - { - double_click_count++; - event->modifiers |= ((double_click_count > 2) - ? triple_modifier - : double_modifier); - } - else - double_click_count = 1; - button_down_time = event->timestamp; *start_pos_ptr = Fcopy_alist (position); ignore_mouse_drag_p = false; } @@ -5744,19 +5829,13 @@ make_lispy_event (struct input_event *event) && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position))))) { /* Mouse has moved enough. */ - button_down_time = 0; + interrupt_next_repeat_click = true; click_or_drag_modifier = drag_modifier; } } - /* Don't check is_double; treat this as multiple if the - down-event was multiple. */ - event->modifiers - = ((event->modifiers & ~up_modifier) - | click_or_drag_modifier - | (double_click_count < 2 ? 0 - : double_click_count == 2 ? double_modifier - : triple_modifier)); + event->modifiers = ((event->modifiers & ~up_modifier) + | click_or_drag_modifier); } else /* Every mouse event should either have the down_modifier or @@ -5776,7 +5855,7 @@ make_lispy_event (struct input_event *event) if (event->modifiers & drag_modifier) return list3 (head, start_pos, position); else if (event->modifiers & (double_modifier | triple_modifier)) - return list3 (head, position, make_fixnum (double_click_count)); + return list3 (head, position, make_fixnum (repeat_count)); else return list2 (head, position); } @@ -5787,6 +5866,7 @@ make_lispy_event (struct input_event *event) { Lisp_Object position; Lisp_Object head; + int repeat_count; /* Build the position as appropriate for this mouse click. */ struct frame *f = XFRAME (event->frame_or_window); @@ -5799,38 +5879,15 @@ make_lispy_event (struct input_event *event) position = make_lispy_position (f, event->x, event->y, event->timestamp); - /* Set double or triple modifiers to indicate the wheel speed. */ { - /* On window-system frames, use the value of - double-click-fuzz as is. On other frames, interpret it - as a multiple of 1/8 characters. */ - struct frame *fr; - intmax_t fuzz; int symbol_num; - bool is_double; - - if (WINDOWP (event->frame_or_window)) - fr = XFRAME (XWINDOW (event->frame_or_window)->frame); - else if (FRAMEP (event->frame_or_window)) - fr = XFRAME (event->frame_or_window); - else - emacs_abort (); - - fuzz = FRAME_WINDOW_P (fr) - ? double_click_fuzz : double_click_fuzz / 8; if (event->modifiers & up_modifier) - { /* Emit a wheel-up event. */ - event->modifiers &= ~up_modifier; - symbol_num = 0; - } + symbol_num = 0; else if (event->modifiers & down_modifier) - { /* Emit a wheel-down event. */ - event->modifiers &= ~down_modifier; - symbol_num = 1; - } + symbol_num = 1; else /* Every wheel event should either have the down_modifier or the up_modifier set. */ @@ -5839,32 +5896,20 @@ make_lispy_event (struct input_event *event) if (event->kind == HORIZ_WHEEL_EVENT) symbol_num += 2; - is_double = (last_mouse_button == - (1 + symbol_num) - && (eabs (XFIXNUM (event->x) - last_mouse_x) <= fuzz) - && (eabs (XFIXNUM (event->y) - last_mouse_y) <= fuzz) - && button_down_time != 0 - && (EQ (Vdouble_click_time, Qt) - || (FIXNATP (Vdouble_click_time) - && (event->timestamp - button_down_time - < XFIXNAT (Vdouble_click_time))))); - if (is_double) - { - double_click_count++; - event->modifiers |= ((double_click_count > 2) - ? triple_modifier - : double_modifier); - } + /* Set double or triple modifiers to indicate the wheel + speed. */ + repeat_count = mouse_repeat_count (event); + if (repeat_count == 2) + event->modifiers |= double_modifier; + else if (repeat_count >= 3) + event->modifiers |= triple_modifier; else - { - double_click_count = 1; - event->modifiers |= click_modifier; - } + /* Non-repeat wheel events are tagged as clicks. */ + event->modifiers |= click_modifier; - button_down_time = event->timestamp; - /* Use a negative value to distinguish wheel from mouse button. */ - last_mouse_button = - (1 + symbol_num); - last_mouse_x = XFIXNUM (event->x); - last_mouse_y = XFIXNUM (event->y); + /* The Lisp side expects to see direction information in + 'symbol_num', but not in the modifier bits. */ + event->modifiers &= ~(down_modifier | up_modifier); /* Get the symbol we should use for the wheel event. */ head = modify_event_symbol (symbol_num, @@ -5877,10 +5922,10 @@ make_lispy_event (struct input_event *event) } if (NUMBERP (event->arg)) - return list4 (head, position, make_fixnum (double_click_count), + return list4 (head, position, make_fixnum (repeat_count), event->arg); else if (event->modifiers & (double_modifier | triple_modifier)) - return list3 (head, position, make_fixnum (double_click_count)); + return list3 (head, position, make_fixnum (repeat_count)); else return list2 (head, position); } -- 2.20.1 >From 3e484dbae4bac122ec7093688906484e13a81156 Mon Sep 17 00:00:00 2001 From: Daniel Koning Date: Thu, 3 Sep 2020 16:15:16 -0500 Subject: [PATCH 2/6] Clarify a quirk of how 'double-click-fuzz' works * doc/lispref/commands.texi (Repeat Events): Mention that if the mouse changes screen positions with a button held down, it's always a drag. --- doc/lispref/commands.texi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 93350927f2..0adc6fc17d 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -1627,7 +1627,9 @@ Repeat Events clicks to make a double-click. This variable is also the threshold for motion of the mouse to count -as a drag. +as a drag. (But if the mouse moves from one screen position to +another while the button is held down, it always counts as a drag, no +matter the value of @code{double-click-fuzz}.) @end defopt @defopt double-click-time -- 2.20.1 >From f8f6fcf3cd329ded23586838249fd372ece969d6 Mon Sep 17 00:00:00 2001 From: Daniel Koning Date: Thu, 3 Sep 2020 16:26:28 -0500 Subject: [PATCH 3/6] Use event macros with meaningful names * src/keyboard.c (make_lispy_event): Use 'POSN_POSN' and 'POSN_WINDOW_POSN' to extract fields from a mouse event list; don't just cadr and caddr things out. --- doc/lispref/commands.texi | 2 +- src/keyboard.c | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 0adc6fc17d..c28e87619e 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -1627,7 +1627,7 @@ Repeat Events clicks to make a double-click. This variable is also the threshold for motion of the mouse to count -as a drag. (But if the mouse moves from one screen position to +as a drag. (But if the mouse moves from one buffer position to another while the button is held down, it always counts as a drag, no matter the value of @code{double-click-fuzz}.) @end defopt diff --git a/src/keyboard.c b/src/keyboard.c index 1214e62820..66d9b816a5 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -5796,13 +5796,10 @@ make_lispy_event (struct input_event *event) ignore_mouse_drag_p = false; else { - Lisp_Object new_down, down; - intmax_t xdiff = double_click_fuzz, ydiff = double_click_fuzz; + Lisp_Object down = POSN_WINDOW_POSN (start_pos); + Lisp_Object new_down = POSN_WINDOW_POSN (position); - /* The third element of every position - should be the (x,y) pair. */ - down = Fcar (Fcdr (Fcdr (start_pos))); - new_down = Fcar (Fcdr (Fcdr (position))); + intmax_t xdiff = double_click_fuzz, ydiff = double_click_fuzz; if (CONSP (down) && FIXNUMP (XCAR (down)) && FIXNUMP (XCDR (down))) @@ -5826,7 +5823,7 @@ make_lispy_event (struct input_event *event) a click. But mouse-drag-region completely ignores this case and it hasn't caused any real problem, so it's probably OK to ignore it as well. */ - && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position))))) + && EQ (POSN_POSN (start_pos), POSN_POSN (position)))) { /* Mouse has moved enough. */ interrupt_next_repeat_click = true; -- 2.20.1 >From 76b195d2402b097d6c04bc809c95ec947f9f73c4 Mon Sep 17 00:00:00 2001 From: Daniel Koning Date: Thu, 3 Sep 2020 16:55:45 -0500 Subject: [PATCH 4/6] Take windows into account when detecting drags * src/keyboard.c (make_lispy_event): Whenever a button-up event lands in a different window than its corresponding button-down event, always treat it as a drag, not a click. This worked most of the time before, but not always: if you happened to land in the same position in the other window's buffer, it wasn't detected. * doc/lispref/commands.texi (Repeat Events): Be explicit about this. --- doc/lispref/commands.texi | 7 ++++--- src/keyboard.c | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index c28e87619e..e0137b976d 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -1627,9 +1627,10 @@ Repeat Events clicks to make a double-click. This variable is also the threshold for motion of the mouse to count -as a drag. (But if the mouse moves from one buffer position to -another while the button is held down, it always counts as a drag, no -matter the value of @code{double-click-fuzz}.) +as a drag. (But if the mouse moves from one window to another while +the button is held down, or from one screen position to another, it +always counts as a drag, no matter the value of +@code{double-click-fuzz}.) @end defopt @defopt double-click-time diff --git a/src/keyboard.c b/src/keyboard.c index 66d9b816a5..cc38cd5ce0 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -5813,6 +5813,8 @@ make_lispy_event (struct input_event *event) && xdiff < double_click_fuzz && - double_click_fuzz < ydiff && ydiff < double_click_fuzz + /* If we jumped windows, it has to be a drag. */ + && EQ (POSN_WINDOW (start_pos), POSN_WINDOW (position)) /* Maybe the mouse has moved a lot, caused scrolling, and eventually ended up at the same screen position (but not buffer position) in which case it is a drag, not -- 2.20.1 >From e760b108efc51f17b23298d3271697bd278e25ee Mon Sep 17 00:00:00 2001 From: Daniel Koning Date: Fri, 21 Aug 2020 19:39:25 -0500 Subject: [PATCH 5/6] Ignore changes in modifier keys during momentum * src/nsterm.m ([EmacsView mouseDown:]): Treat a momentum-phase mouse wheel event as having the same modifier keys as the non-momentum event that triggered it. --- src/nsterm.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/nsterm.m b/src/nsterm.m index 26059ab67c..9dd5249b97 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -313,6 +313,7 @@ - (NSColor *)colorUsingDefaultColorSpace static NSAutoreleasePool *outerpool; static struct input_event *emacs_event = NULL; static struct input_event *q_event_ptr = NULL; +static int last_real_wheel_modifier_keys = 0; static int n_emacs_events_pending = 0; static NSMutableArray *ns_pending_files, *ns_pending_service_names, *ns_pending_service_args; @@ -6984,6 +6985,21 @@ - (void)mouseDown: (NSEvent *)theEvent emacs_event->code = 0; emacs_event->modifiers = EV_MODIFIERS (theEvent) | (scrollUp ? up_modifier : down_modifier); + + /* If this is a momentum-phase event, ignore the modifier + * keys it arrived with. Inherit the modifier keys from the + * last non-momentum event in the sequence. The user may be + * pressing or releasing modifier keys, intending to use + * them in the next event, while the wheel events are still + * firing. */ + if ([theEvent momentumPhase] != NSEventPhaseNone) + { + emacs_event->modifiers &= ~CHAR_MODIFIER_MASK; + emacs_event->modifiers |= last_real_wheel_modifier_keys; + } + else + last_real_wheel_modifier_keys = + emacs_event->modifiers & CHAR_MODIFIER_MASK; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 } else -- 2.20.1 >From a66ff506f3c7dcd05a95863d724b207f02ed6329 Mon Sep 17 00:00:00 2001 From: Daniel Koning Date: Fri, 21 Aug 2020 19:11:36 -0500 Subject: [PATCH 6/6] Give context to a FIXME comment * src/nsterm.m ([EmacsView mouseDown:]): Provide more detail to explain why it's difficult to adjust scrolling behavior based on wheel momentum phase. --- src/nsterm.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/nsterm.m b/src/nsterm.m index 9dd5249b97..2ddb378d75 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -6899,8 +6899,13 @@ - (void)mouseDown: (NSEvent *)theEvent int lines = 0; int scrollUp = NO; - /* FIXME: At the top or bottom of the buffer we should - * ignore momentum-phase events. */ + /* FIXME: At the top or bottom of the buffer, we should + * ignore momentum-phase events that are bound to scrolling + * the buffer down or up respectively. But since this code + * doesn't know about bindings and the keymap code doesn't + * know about wheel momentum, that doesn't seem to be + * possible yet. */ + if (! ns_use_mwheel_momentum && [theEvent momentumPhase] != NSEventPhaseNone) return; -- 2.20.1 --=-=-=-- From unknown Tue Jul 15 19:29:05 2025 X-Loop: help-debbugs@gnu.org Subject: bug#43379: [PATCH] Double-click events can occur without preceding single-click events Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 13 Sep 2020 17:31:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 43379 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Daniel Koning Cc: 43379@debbugs.gnu.org Received: via spool by 43379-submit@debbugs.gnu.org id=B43379.160001824926183 (code B ref 43379); Sun, 13 Sep 2020 17:31:02 +0000 Received: (at 43379) by debbugs.gnu.org; 13 Sep 2020 17:30:49 +0000 Received: from localhost ([127.0.0.1]:51631 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kHVpx-0006oF-3J for submit@debbugs.gnu.org; Sun, 13 Sep 2020 13:30:49 -0400 Received: from eggs.gnu.org ([209.51.188.92]:34386) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kHVpu-0006o2-TJ for 43379@debbugs.gnu.org; Sun, 13 Sep 2020 13:30:47 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]:33520) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kHVpp-00038x-2j; Sun, 13 Sep 2020 13:30:41 -0400 Received: from [176.228.60.248] (port=3046 helo=home-c4e4a596f7) by fencepost.gnu.org with esmtpsa (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1kHVpb-0000kT-Lb; Sun, 13 Sep 2020 13:30:35 -0400 Date: Sun, 13 Sep 2020 20:30:26 +0300 Message-Id: <83imchbn4d.fsf@gnu.org> From: Eli Zaretskii In-Reply-To: (message from Daniel Koning on Sun, 13 Sep 2020 12:00:10 -0500) References: X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Daniel Koning > Date: Sun, 13 Sep 2020 12:00:10 -0500 > > ++++ > +** Repeat events are now produced only when the modifier keys are the same. What will this do if the modifier key is "simulated" using "C-x @"? More generally, for a change this deep and wide, I'd like to understand better what exactly are the problems being solved, and also how can we be sure (by testing or otherwise) we are not getting regressions in some use cases. Could you please clarify that? > +Before, when the user pressed the same mouse button repeatedly within > +the bounds specified by 'double-click-fuzz' and 'double-click-time', > +it always produced a 'double-' or 'triple-' event, even if the user > +was holding down modifier keys on one click and not another. This > +meant that it was possible for Emacs to read a double-click event > +without reading the same kind of single-click event first. Emacs now > +looks at modifier keys to determine if a mouse event is a repeat. Beyond theoretical (un)cleanliness, what other practical problems did you find with the current code and fix in these patches? > This variable is also the threshold for motion of the mouse to count > -as a drag. > +as a drag. (But if the mouse moves from one screen position to > +another while the button is held down, it always counts as a drag, no > +matter the value of @code{double-click-fuzz}.) Isn't this an incompatible change? Thanks. From unknown Tue Jul 15 19:29:05 2025 X-Loop: help-debbugs@gnu.org Subject: bug#43379: [PATCH] Double-click events can occur without preceding single-click events Resent-From: Daniel Koning Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 13 Sep 2020 20:21:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 43379 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Eli Zaretskii Cc: 43379@debbugs.gnu.org Received: via spool by 43379-submit@debbugs.gnu.org id=B43379.16000284489080 (code B ref 43379); Sun, 13 Sep 2020 20:21:01 +0000 Received: (at 43379) by debbugs.gnu.org; 13 Sep 2020 20:20:48 +0000 Received: from localhost ([127.0.0.1]:51854 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kHYUR-0002MM-CJ for submit@debbugs.gnu.org; Sun, 13 Sep 2020 16:20:47 -0400 Received: from sender4-of-o56.zoho.com ([136.143.188.56]:21689) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kHYUO-0002MD-Py for 43379@debbugs.gnu.org; Sun, 13 Sep 2020 16:20:46 -0400 ARC-Seal: i=1; a=rsa-sha256; t=1600028438; cv=none; d=zohomail.com; s=zohoarc; b=LlBbvKDRNjrDmBrLya/AK+lgFcNGV8VEuVGMacydvV02z3Rpjc++Dd/FREFP0yVtI5nyzYtJjmgan2MKsvL5J8ve5on2VVzudxTsbCtHT4E8AKjI3zhgp0Rkgyn2AbZ9HEBDpE9tddy4dU+dC7Ki+f0GSOf8gWIp9DUt0fFUqsM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1600028438; h=Content-Type:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:To; bh=OoZl5PHNXo7yjSpYbPh14n1k2xkfuQdz20u7LHRpWgg=; b=igoqomznYn4+gY/FgswycGGogRIrpagI6JcK52P2rRuHBWV0mF9/NsL61OFFJcmo3WTSZ+QdhgIrYpIjP1+YCUE7N8kjhszVhE8aDXG5lHR1YnCNeYF1ngi8I3J9XuSaUxczEuWP3siLXcZnfHSzaFhRVworkW86flPV1TfSHf0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass smtp.mailfrom=dk@danielkoning.com; dmarc=pass header.from= header.from= Received: from cornelius (112.157.239.35.bc.googleusercontent.com [35.239.157.112]) by mx.zohomail.com with SMTPS id 1600028436642294.1058114231678; Sun, 13 Sep 2020 13:20:36 -0700 (PDT) From: Daniel Koning References: <83imchbn4d.fsf@gnu.org> Date: Sun, 13 Sep 2020 15:20:35 -0500 In-Reply-To: <83imchbn4d.fsf@gnu.org> (Eli Zaretskii's message of "Sun, 13 Sep 2020 20:30:26 +0300") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1.50 (darwin) MIME-Version: 1.0 Content-Type: text/plain X-ZohoMailClient: External X-Spam-Score: -0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Eli Zaretskii writes: >> From: Daniel Koning >> Date: Sun, 13 Sep 2020 12:00:10 -0500 >> >> ++++ >> +** Repeat events are now produced only when the modifier keys are the same. > > What will this do if the modifier key is "simulated" using "C-x @"? As before, you can't get a repeat tag on an event with a simulated modifier key, because the raw keyboard events representing "C-x @" break the chain, and double and triple modifiers get set before a keymap can see events and reinterpret them. Kind of a shame, but better than getting spurious tags. I guess you could change simple.el to do something akin to what xterm-mouse-mode does, but it doesn't strike me as necessary. "C-x @ m mouse-1 mouse-1" *will* call the commands for and . As with the case of clicks in different windows, even though my patch doesn't concern itself with this, I do think it's a flaw worth fixing at some point. > More generally, for a change this deep and wide, I'd like to > understand better what exactly are the problems being solved, That the program's actual behavior doesn't match the documentation, which describes behavior that reflects how double clicks work on every other GUI I've ever used. The docs could just be rewritten to match the program, but imagine what they'd look like: "Design the command binding of the double click event to assume that the single-click command has already run, or at least *some* single-click command using the same mouse button but potentially different modifier keys, or if not that, then a single-click command for a different mouse button which is now being held down but hasn't been held down for as long as this button has. But one of those for sure!" > and also how can we be sure (by testing or otherwise) we are not > getting regressions in some use cases. Could you please clarify that? Unfortunately, I don't think it's possible to add automated regression tests for this stuff, at least not with ERT. You'd need to have some programmatic way of generating events from Lisp that get fed into the src/keyboard.c functions. Without serious additions to the underlying C layer (or maybe a module?), I don't see how that could happen. And in general, I think that's a sensible limitation; what if event X got mapped to a Lisp command which generated a fake event X, which generated another etc. etc.? Here's how I've been testing it manually: feed Emacs (patched and unpatched) as many combinations of mouse actions as I can think up, then check the lossage file to see if it's interpreting them right. Or better yet, visit *scratch* in a split frame with another buffer called *Events*, and eval this form: (cl-loop (let ((event (read-event))) (with-current-buffer "*Events*" (insert (prin1-to-string event) "\n\n") (goto-char (point-min)))))) You'll see the full (pre-keymap, pre-input-method) event representation appear immediately for everything you do. Bind 'double-click-time' and 'double-click-fuzz' around it as you please for more test cases. (If you click around in the continually updating *Events* window, you'll get a lot of drags, because the text is moving under the cursor between down and release. This is not new, and a preexisting comment says it's by design.) There's no way around the fact that it needs line-by-line scrutiny. But I went to great lengths to make it lucid and direct so that it won't be onerous to give it that scrutiny. > Beyond theoretical (un)cleanliness, what other practical problems did > you find with the current code and fix in these patches? I didn't change the code in order to make it cleaner; if I'd needed to make it dirtier in order to fix the bug, that's what I would have done. It just happened that the most straightforward approach to fixing it meant making it cleaner, which I think is nice. (Modifying the code in place is not straightforward, since the pertinent sections of the switch/case labyrinth -- which are almost but not quite identical -- inevitably end up having to interact with each other when the more stringent criteria come into play. File-level static variables start multiplying out of control at that point.) As for patch #1, the big one, I explained what it addresses above: Emacs was doing the wrong thing both according to its documentation and according to my intuition. Now it does the right thing for modifier keys and interleaved clicks, and (I contend) it does everything else the same as before. Here's what the other five patches address, in order: 2/6 mentions an existing limitation on 'double-click-fuzz' in that variable's manual entry. 3/6 changes some expressions to use the POSN_WINDOW and POSN_POSN macros that are defined to expand to the same things. (Not very important, but it makes the expressions readable instead of opaque.) 4/6 closes a weird loophole in the detection of drag events, surely unintended. See discussion below. 5/6 fixes the Cocoa bug where trackpad swipes got retroactively modified by keys that weren't pressed yet when the user swiped. 6/6 is a small elaboration on an existing FIXME comment to explain why the issue is hard to fix. (Also not too important.) All the patches are self-contained. They can be applied in any combination. > >> This variable is also the threshold for motion of the mouse to count >> -as a drag. >> +as a drag. (But if the mouse moves from one screen position to >> +another while the button is held down, it always counts as a drag, no >> +matter the value of @code{double-click-fuzz}.) > > Isn't this an incompatible change? It's not a change; it already worked that way. And it makes sense that it works that way -- otherwise, if you had 'double-click-fuzz' set too high, you couldn't drag to select a region of two adjacent characters. But the exception to the rule isn't obvious without looking at the code. My related change (4/6) was to look at windows per se as well as window positions. Before, a drag starting at position 1 of one window, and ending at position 1 of another window, wasn't tagged as a drag because the position values were the same. I think this one should be uncontroversial (as should the trackpad thing in src/nsterm.m, 5/6). Daniel From unknown Tue Jul 15 19:29:05 2025 X-Loop: help-debbugs@gnu.org Subject: bug#43379: [PATCH] Double-click events can occur without preceding single-click events Resent-From: Lars Ingebrigtsen Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 21 Jul 2021 12:46:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 43379 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Daniel Koning Cc: 43379@debbugs.gnu.org Received: via spool by 43379-submit@debbugs.gnu.org id=B43379.162687153629978 (code B ref 43379); Wed, 21 Jul 2021 12:46:01 +0000 Received: (at 43379) by debbugs.gnu.org; 21 Jul 2021 12:45:36 +0000 Received: from localhost ([127.0.0.1]:36410 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1m6BbU-0007nS-3X for submit@debbugs.gnu.org; Wed, 21 Jul 2021 08:45:36 -0400 Received: from quimby.gnus.org ([95.216.78.240]:42354) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1m6BbS-0007nC-Ay for 43379@debbugs.gnu.org; Wed, 21 Jul 2021 08:45:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=s9OWQmAerhOwpJKxnCp2fjhca3TVWvrGIzgboysIKxY=; b=WTwfXrqCB74LIfKkN2nuxExM8u ONlHTDA7Pz/ptIpMo84JEZqjpVeIxalyLoongRqPb/i1fKWt2IDZpTfSFUP6+CiAlvL/Ik5zkoKe9 qQXgxvZvTY2iq8k6D8HaAn+mDeyBi3mrH/nog428gTd62DvN0OnOkxuOch5UOwXRbLxU=; Received: from cm-84.212.220.105.getinternet.no ([84.212.220.105] helo=elva) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1m6BbJ-0006gA-05; Wed, 21 Jul 2021 14:45:27 +0200 From: Lars Ingebrigtsen References: X-Now-Playing: Skream's _#savefabric (8)_: "Munk" Date: Wed, 21 Jul 2021 14:45:24 +0200 In-Reply-To: (Daniel Koning's message of "Sun, 13 Sep 2020 12:00:10 -0500") Message-ID: <87zgufj0nv.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: I've just read this thread and skimmed the patches, and they seem to make sense to me. However, when I tried to apply them to test, they don't apply cleanly any more (since this was almost a year ago, [...] Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) I've just read this thread and skimmed the patches, and they seem to make sense to me. However, when I tried to apply them to test, they don't apply cleanly any more (since this was almost a year ago, unfortunately). Do you have updated versions of the patch sets? If so, I can test and get them pushed to Emacs 28. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no From unknown Tue Jul 15 19:29:05 2025 X-Loop: help-debbugs@gnu.org Subject: bug#43379: [PATCH] Double-click events can occur without preceding single-click events Resent-From: Lars Ingebrigtsen Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 12 Nov 2021 08:24:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 43379 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Daniel Koning Cc: 43379@debbugs.gnu.org Received: via spool by 43379-submit@debbugs.gnu.org id=B43379.163670538632075 (code B ref 43379); Fri, 12 Nov 2021 08:24:02 +0000 Received: (at 43379) by debbugs.gnu.org; 12 Nov 2021 08:23:06 +0000 Received: from localhost ([127.0.0.1]:43375 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mlRpx-0008LF-PN for submit@debbugs.gnu.org; Fri, 12 Nov 2021 03:23:06 -0500 Received: from quimby.gnus.org ([95.216.78.240]:34786) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mlRpu-0008KK-R9 for 43379@debbugs.gnu.org; Fri, 12 Nov 2021 03:23:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=uUKJSXt+Ak0fmmcYrbSMXsWPoLEelq/NvcBez/KGZH0=; b=cCYax+EirbgPz69nCQK1AnACa5 4G2/FP2jp1mn483ZFuMKsXdn20Nj1LU4lRPcLmeO/xWyBbeyUukl0+SLJdMm4Ltnuy4IuOaJuLqxM U6Cl5zlJHJ4Uy+lGVFA6+6naUATqrUGD+IfRtludTRjw0KiILn4/W4rvnS9gfusG9Ccs=; Received: from [84.212.220.105] (helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mlRpk-0005g5-CU; Fri, 12 Nov 2021 09:22:55 +0100 From: Lars Ingebrigtsen References: <87zgufj0nv.fsf@gnus.org> X-Now-Playing: Sonic Youth's _NYC Ghosts & Flowers_: "StreamXSonik Subway" Date: Fri, 12 Nov 2021 09:22:50 +0100 In-Reply-To: <87zgufj0nv.fsf@gnus.org> (Lars Ingebrigtsen's message of "Wed, 21 Jul 2021 14:45:24 +0200") Message-ID: <871r3lvl45.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: Lars Ingebrigtsen writes: > I've just read this thread and skimmed the patches, and they seem to > make sense to me. However, when I tried to apply them to test, they > don't apply cleanly any more (since this was almost a yea [...] Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Lars Ingebrigtsen writes: > I've just read this thread and skimmed the patches, and they seem to > make sense to me. However, when I tried to apply them to test, they > don't apply cleanly any more (since this was almost a year ago, > unfortunately). > > Do you have updated versions of the patch sets? If so, I can test and > get them pushed to Emacs 28. I've respun the patches below -- some of the code has changed considerably, so it may not be 100% correct any more. However, I can't reproduce the original bug report (in either emacs-28 or the current trunk). Here's the test case: (let ((double-click-time 500)) (require 'cl-lib) (pop-to-buffer "*Events*") (cl-loop (let ((event (read-event))) (with-current-buffer "*Events*" (insert (replace-regexp-in-string " .*" "" (prin1-to-string event)) "\n") (goto-char (point-min)))))) I can't get a single instance of a double-mouse-x without a mouse-x happening before, even with long double-click-times. Can anybody else reproduce this problem? diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index d9d6a68005..92044309ea 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -2186,8 +2186,12 @@ Mouse Buttons The symbols for mouse events also indicate the status of the modifier keys, with the usual prefixes @samp{C-}, @samp{M-}, @samp{H-}, -@samp{s-}, @samp{A-}, and @samp{S-}. These always precede @samp{double-} -or @samp{triple-}, which always precede @samp{drag-} or @samp{down-}. +@samp{s-}, @samp{A-}, and @samp{S-}. These always precede +@samp{double-} or @samp{triple-}, which always precede @samp{drag-} or +@samp{down-}. (Two clicks with different modifier keys can never +produce a double event, no matter how close together the clicks are. +Otherwise, Emacs could get a @code{double-mouse-1} event without getting +a @code{mouse-1} event first.) A frame includes areas that don't show text from the buffer, such as the mode line and the scroll bar. You can tell whether a mouse button diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 6ed46fa6a2..d1471e9221 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -1717,9 +1717,12 @@ Repeat Events @cindex triple-click events @cindex mouse events, repeated -If you press the same mouse button more than once in quick succession -without moving the mouse, Emacs generates special @dfn{repeat} mouse -events for the second and subsequent presses. +Emacs generates special @dfn{repeat} mouse events to represent actions +like double and triple clicks. If you press a button twice in quick +succession without moving the mouse in between, Emacs will designate the +second event as a repeat. (However, if you hold down any modifier keys +during one press and not the other, Emacs will treat the two events as +unconnected, and the second event will not be a repeat.) The most common repeat events are @dfn{double-click} events. Emacs generates a double-click event when you click a button twice; the event @@ -1793,7 +1796,10 @@ Repeat Events clicks to make a double-click. This variable is also the threshold for motion of the mouse to count -as a drag. +as a drag. (But if the mouse moves from one window to another while +the button is held down, or from one screen position to another, it +always counts as a drag, no matter the value of +@code{double-click-fuzz}.) @end defopt @defopt double-click-time diff --git a/etc/NEWS b/etc/NEWS index 0057fbdcbf..234059a781 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -138,6 +138,16 @@ LRI). The new command 'highlight-confusing-reorderings' finds and highlights segments of buffer text whose reordering for display is suspicious and could be malicious. ++++ +** Repeat events are now produced only when the modifier keys are the same. +Before, when the user pressed the same mouse button repeatedly within +the bounds specified by 'double-click-fuzz' and 'double-click-time', +it always produced a 'double-' or 'triple-' event, even if the user +was holding down modifier keys on one click and not another. This +meant that it was possible for Emacs to read a double-click event +without reading the same kind of single-click event first. Emacs now +looks at modifier keys to determine if a mouse event is a repeat. + ** Emacs server and client changes. diff --git a/src/keyboard.c b/src/keyboard.c index de9805df32..c30b980ba2 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -351,6 +351,7 @@ #define READABLE_EVENTS_IGNORE_SQUEEZABLES (1 << 2) static Lisp_Object read_char_x_menu_prompt (Lisp_Object, Lisp_Object, bool *); static Lisp_Object read_char_minibuf_menu_prompt (int, Lisp_Object); +static intmax_t mouse_repeat_count (const struct input_event *); static Lisp_Object make_lispy_event (struct input_event *); static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object, enum scroll_bar_part, @@ -5062,18 +5063,6 @@ #define ISO_FUNCTION_KEY_OFFSET 0xfe00 the down mouse event. */ static Lisp_Object frame_relative_event_pos; -/* Information about the most recent up-going button event: Which - button, what location, and what time. */ - -static int last_mouse_button; -static int last_mouse_x; -static int last_mouse_y; -static Time button_down_time; - -/* The number of clicks in this multiple-click. */ - -static int double_click_count; - /* X and Y are frame-relative coordinates for a click or wheel event. Return a Lisp-style event list. */ @@ -5388,6 +5377,139 @@ make_scroll_bar_position (struct input_event *ev, Lisp_Object type) builtin_lisp_symbol (scroll_bar_parts[ev->part])); } +/* Whether the next click (or wheel event) should be treated as a + single no matter what, even if a matching prior event would make it + a repeat. This gets flipped on when a keystroke or drag event + comes in: double clicks can't extend across one of those. */ + +static bool interrupt_next_repeat_click; + +/* If EVENT is a repeat, return the number of consecutive mouse events + so far. Return 1 otherwise. In the background, keep a record of + where we are in the current sequence of repeats. + + This should only receive a pointer to an event of an applicable + kind -- namely, a button-down, button-up, or wheel event. */ + +static intmax_t +mouse_repeat_count (const struct input_event *event) +{ + /* Keep persistent information about any chain of repeat events we + might be in the middle of. */ + + static ENUM_BF (event_kind) kind; + static unsigned code; + static unsigned keys; + static unsigned wheel_dir; + + static Time timeout_start; + static EMACS_INT x, y; + + static intmax_t count; + + /* Analyze the new event that came in. */ + + unsigned new_keys = event->modifiers & CHAR_MODIFIER_MASK; + unsigned new_wheel_dir; + + Time interval; + EMACS_INT new_x, new_y, offset; + + bool is_wheel = (event->kind == WHEEL_EVENT + || event->kind == HORIZ_WHEEL_EVENT); + bool is_button = !is_wheel; + bool is_button_up = (is_button && (event->modifiers & up_modifier)); + + if (is_wheel) + new_wheel_dir = (event->modifiers & (down_modifier | up_modifier)); + else + new_wheel_dir = 0; + + /* We need to update timestamp and position after both repeat and + non-repeat events. Make the relevant comparisons in advance, + then do the update immediately. */ + + interval = event->timestamp - timeout_start; + if (!is_button_up) + timeout_start = event->timestamp; + + new_x = XFIXNUM (event->x); + new_y = XFIXNUM (event->y); + offset = max (eabs (new_x - x), eabs (new_y - y)); + x = new_x; + y = new_y; + + /* Is this a repeat? Start checking for conditions that imply + otherwise. */ + + if (interrupt_next_repeat_click && !is_button_up) + { + interrupt_next_repeat_click = false; + goto not_a_repeat; + } + + if (event->kind != kind || event->code != code || new_keys != keys + || new_wheel_dir != wheel_dir) + goto not_a_repeat; + + if (is_button_up) + /* That's it for button-up events. At this point, we declare that + it's a repeat that should inherit the count of the preceding + button-down. */ + return count; + + if (FIXNATP (Vdouble_click_time)) + { + if (interval >= XFIXNAT (Vdouble_click_time)) + goto not_a_repeat; + } + else if (!EQ (Vdouble_click_time, Qt)) + goto not_a_repeat; + + { + /* On window-system frames, use the value of 'double-click-fuzz' + as is. On other frames, interpret it as a multiple of 1/8 + characters. */ + struct frame *f; + intmax_t fuzz; + + if (WINDOWP (event->frame_or_window)) + f = XFRAME (XWINDOW (event->frame_or_window)->frame); + else if (FRAMEP (event->frame_or_window)) + f = XFRAME (event->frame_or_window); + else + emacs_abort (); + + if (FRAME_WINDOW_P (f)) + fuzz = double_click_fuzz; + else + fuzz = double_click_fuzz / 8; + + if (offset > fuzz) + goto not_a_repeat; + } + + /* We've ruled out everything that could disqualify it as a repeat, + so treat it as one. */ + count++; + return count; + + not_a_repeat: + /* Base a new repeat chain off of this event. */ + count = 1; + kind = event->kind; + code = event->code; + keys = new_keys; + wheel_dir = new_wheel_dir; + + if (is_button_up) + /* A button-up event should cut off a chain when it doesn't match + the last event, but it shouldn't start its own chain. */ + interrupt_next_repeat_click = true; + + return count; +} + /* Given a struct input_event, build the lisp event which represents it. If EVENT is 0, build a mouse movement event from the mouse movement buffer, which should have a movement event in it. @@ -5512,7 +5634,7 @@ make_lispy_event (struct input_event *event) if ((event->code) == 040 && event->modifiers & shift_modifier) c |= shift_modifier; - button_down_time = 0; + interrupt_next_repeat_click = true; XSETFASTINT (lispy_c, c); return lispy_c; } @@ -5531,7 +5653,7 @@ make_lispy_event (struct input_event *event) /* A function key. The symbol may need to have modifier prefixes tacked onto it. */ case NON_ASCII_KEYSTROKE_EVENT: - button_down_time = 0; + interrupt_next_repeat_click = true; for (i = 0; i < ARRAYELTS (lispy_accent_codes); i++) if (event->code == lispy_accent_codes[i]) @@ -5617,10 +5739,10 @@ make_lispy_event (struct input_event *event) #endif { int button = event->code; - bool is_double; Lisp_Object position; Lisp_Object *start_pos_ptr; Lisp_Object start_pos; + int repeat_count; position = Qnil; @@ -5709,57 +5831,20 @@ make_lispy_event (struct input_event *event) mouse_syms = larger_vector (mouse_syms, incr, -1); } + repeat_count = mouse_repeat_count (event); + if (repeat_count == 2) + event->modifiers |= double_modifier; + else if (repeat_count >= 3) + event->modifiers |= triple_modifier; + start_pos_ptr = aref_addr (button_down_location, button); start_pos = *start_pos_ptr; *start_pos_ptr = Qnil; - { - /* On window-system frames, use the value of - double-click-fuzz as is. On other frames, interpret it - as a multiple of 1/8 characters. */ - struct frame *f; - intmax_t fuzz; - - if (WINDOWP (event->frame_or_window)) - f = XFRAME (XWINDOW (event->frame_or_window)->frame); - else if (FRAMEP (event->frame_or_window)) - f = XFRAME (event->frame_or_window); - else - emacs_abort (); - - if (FRAME_WINDOW_P (f)) - fuzz = double_click_fuzz; - else - fuzz = double_click_fuzz / 8; - - is_double = (button == last_mouse_button - && (eabs (XFIXNUM (event->x) - last_mouse_x) <= fuzz) - && (eabs (XFIXNUM (event->y) - last_mouse_y) <= fuzz) - && button_down_time != 0 - && (EQ (Vdouble_click_time, Qt) - || (FIXNATP (Vdouble_click_time) - && (event->timestamp - button_down_time - < XFIXNAT (Vdouble_click_time))))); - } - - last_mouse_button = button; - last_mouse_x = XFIXNUM (event->x); - last_mouse_y = XFIXNUM (event->y); - /* If this is a button press, squirrel away the location, so we can decide later whether it was a click or a drag. */ if (event->modifiers & down_modifier) { - if (is_double) - { - double_click_count++; - event->modifiers |= ((double_click_count > 2) - ? triple_modifier - : double_modifier); - } - else - double_click_count = 1; - button_down_time = event->timestamp; *start_pos_ptr = Fcopy_alist (position); frame_relative_event_pos = Fcons (event->x, event->y); ignore_mouse_drag_p = false; @@ -5796,6 +5881,8 @@ make_lispy_event (struct input_event *event) && xdiff < double_click_fuzz && - double_click_fuzz < ydiff && ydiff < double_click_fuzz + /* If we jumped windows, it has to be a drag. */ + && EQ (POSN_WINDOW (start_pos), POSN_WINDOW (position)) /* Maybe the mouse has moved a lot, caused scrolling, and eventually ended up at the same screen position (but not buffer position) in which case it is a drag, not @@ -5812,7 +5899,7 @@ make_lispy_event (struct input_event *event) Fcar (position))))) /* Different window */ { /* Mouse has moved enough. */ - button_down_time = 0; + interrupt_next_repeat_click = true; click_or_drag_modifier = drag_modifier; } else if (((!EQ (Fcar (start_pos), Fcar (position))) @@ -5853,14 +5940,8 @@ make_lispy_event (struct input_event *event) } } - /* Don't check is_double; treat this as multiple if the - down-event was multiple. */ - event->modifiers - = ((event->modifiers & ~up_modifier) - | click_or_drag_modifier - | (double_click_count < 2 ? 0 - : double_click_count == 2 ? double_modifier - : triple_modifier)); + event->modifiers = ((event->modifiers & ~up_modifier) + | click_or_drag_modifier); } else /* Every mouse event should either have the down_modifier or @@ -5880,7 +5961,7 @@ make_lispy_event (struct input_event *event) if (event->modifiers & drag_modifier) return list3 (head, start_pos, position); else if (event->modifiers & (double_modifier | triple_modifier)) - return list3 (head, position, make_fixnum (double_click_count)); + return list3 (head, position, make_fixnum (repeat_count)); else return list2 (head, position); } @@ -5891,6 +5972,7 @@ make_lispy_event (struct input_event *event) { Lisp_Object position; Lisp_Object head; + int repeat_count; /* Build the position as appropriate for this mouse click. */ struct frame *f = XFRAME (event->frame_or_window); @@ -5903,38 +5985,15 @@ make_lispy_event (struct input_event *event) position = make_lispy_position (f, event->x, event->y, event->timestamp); - /* Set double or triple modifiers to indicate the wheel speed. */ { - /* On window-system frames, use the value of - double-click-fuzz as is. On other frames, interpret it - as a multiple of 1/8 characters. */ - struct frame *fr; - intmax_t fuzz; int symbol_num; - bool is_double; - - if (WINDOWP (event->frame_or_window)) - fr = XFRAME (XWINDOW (event->frame_or_window)->frame); - else if (FRAMEP (event->frame_or_window)) - fr = XFRAME (event->frame_or_window); - else - emacs_abort (); - - fuzz = FRAME_WINDOW_P (fr) - ? double_click_fuzz : double_click_fuzz / 8; if (event->modifiers & up_modifier) - { /* Emit a wheel-up event. */ - event->modifiers &= ~up_modifier; - symbol_num = 0; - } + symbol_num = 0; else if (event->modifiers & down_modifier) - { /* Emit a wheel-down event. */ - event->modifiers &= ~down_modifier; - symbol_num = 1; - } + symbol_num = 1; else /* Every wheel event should either have the down_modifier or the up_modifier set. */ @@ -5943,32 +6002,20 @@ make_lispy_event (struct input_event *event) if (event->kind == HORIZ_WHEEL_EVENT) symbol_num += 2; - is_double = (last_mouse_button == - (1 + symbol_num) - && (eabs (XFIXNUM (event->x) - last_mouse_x) <= fuzz) - && (eabs (XFIXNUM (event->y) - last_mouse_y) <= fuzz) - && button_down_time != 0 - && (EQ (Vdouble_click_time, Qt) - || (FIXNATP (Vdouble_click_time) - && (event->timestamp - button_down_time - < XFIXNAT (Vdouble_click_time))))); - if (is_double) - { - double_click_count++; - event->modifiers |= ((double_click_count > 2) - ? triple_modifier - : double_modifier); - } + /* Set double or triple modifiers to indicate the wheel + speed. */ + repeat_count = mouse_repeat_count (event); + if (repeat_count == 2) + event->modifiers |= double_modifier; + else if (repeat_count >= 3) + event->modifiers |= triple_modifier; else - { - double_click_count = 1; - event->modifiers |= click_modifier; - } + /* Non-repeat wheel events are tagged as clicks. */ + event->modifiers |= click_modifier; - button_down_time = event->timestamp; - /* Use a negative value to distinguish wheel from mouse button. */ - last_mouse_button = - (1 + symbol_num); - last_mouse_x = XFIXNUM (event->x); - last_mouse_y = XFIXNUM (event->y); + /* The Lisp side expects to see direction information in + 'symbol_num', but not in the modifier bits. */ + event->modifiers &= ~(down_modifier | up_modifier); /* Get the symbol we should use for the wheel event. */ head = modify_event_symbol (symbol_num, @@ -5981,10 +6028,10 @@ make_lispy_event (struct input_event *event) } if (NUMBERP (event->arg)) - return list4 (head, position, make_fixnum (double_click_count), + return list4 (head, position, make_fixnum (repeat_count), event->arg); else if (event->modifiers & (double_modifier | triple_modifier)) - return list3 (head, position, make_fixnum (double_click_count)); + return list3 (head, position, make_fixnum (repeat_count)); else return list2 (head, position); } diff --git a/src/nsterm.m b/src/nsterm.m index 1f17a30272..b11fcb5ed5 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -291,6 +291,7 @@ - (NSColor *)colorUsingDefaultColorSpace static NSAutoreleasePool *outerpool; static struct input_event *emacs_event = NULL; static struct input_event *q_event_ptr = NULL; +static int last_real_wheel_modifier_keys = 0; static int n_emacs_events_pending = 0; static NSMutableArray *ns_pending_files, *ns_pending_service_names, *ns_pending_service_args; @@ -6559,8 +6560,13 @@ - (void)mouseDown: (NSEvent *)theEvent int lines = 0; int scrollUp = NO; - /* FIXME: At the top or bottom of the buffer we should - * ignore momentum-phase events. */ + /* FIXME: At the top or bottom of the buffer, we should + * ignore momentum-phase events that are bound to scrolling + * the buffer down or up respectively. But since this code + * doesn't know about bindings and the keymap code doesn't + * know about wheel momentum, that doesn't seem to be + * possible yet. */ + if (! ns_use_mwheel_momentum && [theEvent momentumPhase] != NSEventPhaseNone) return; @@ -6645,6 +6651,21 @@ - (void)mouseDown: (NSEvent *)theEvent emacs_event->code = 0; emacs_event->modifiers = EV_MODIFIERS (theEvent) | (scrollUp ? up_modifier : down_modifier); + + /* If this is a momentum-phase event, ignore the modifier + * keys it arrived with. Inherit the modifier keys from the + * last non-momentum event in the sequence. The user may be + * pressing or releasing modifier keys, intending to use + * them in the next event, while the wheel events are still + * firing. */ + if ([theEvent momentumPhase] != NSEventPhaseNone) + { + emacs_event->modifiers &= ~CHAR_MODIFIER_MASK; + emacs_event->modifiers |= last_real_wheel_modifier_keys; + } + else + last_real_wheel_modifier_keys = + emacs_event->modifiers & CHAR_MODIFIER_MASK; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 } else -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no From debbugs-submit-bounces@debbugs.gnu.org Fri Nov 12 03:23:14 2021 Received: (at control) by debbugs.gnu.org; 12 Nov 2021 08:23:14 +0000 Received: from localhost ([127.0.0.1]:43378 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mlRq5-0008Lb-Om for submit@debbugs.gnu.org; Fri, 12 Nov 2021 03:23:13 -0500 Received: from quimby.gnus.org ([95.216.78.240]:34802) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mlRq0-0008L5-Gd for control@debbugs.gnu.org; Fri, 12 Nov 2021 03:23:12 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Subject:From:To:Message-Id:Date:Sender:Reply-To:Cc: MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=8Wwq8FnSMysnCirp9M2HvsFB0k6rv8hEnqb/7+XlRho=; b=NMjwhOK2jH+rwa4WuvPRasip0h baw9orAtDopYviA4DjRXarwdAlFYGhOjDKJv3B5cEMFzqvh/i7F5mYk7M4k4RJf7CPbi3StA3dim5 FTgD4ArDS5oETAnFGGZX4e3Iw/9E8TPik+Vf3meuLqmTmJAOeJGob1q+IDt64UnueBjk=; Received: from [84.212.220.105] (helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mlRps-0005gI-JH for control@debbugs.gnu.org; Fri, 12 Nov 2021 09:23:03 +0100 Date: Fri, 12 Nov 2021 09:23:00 +0100 Message-Id: <87zgq9u6jf.fsf@gnus.org> To: control@debbugs.gnu.org From: Lars Ingebrigtsen Subject: control message for bug #43379 X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: tags 43379 + moreinfo quit Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) tags 43379 + moreinfo quit From unknown Tue Jul 15 19:29:05 2025 X-Loop: help-debbugs@gnu.org Subject: bug#43379: [PATCH] Double-click events can occur without preceding single-click events Resent-From: Lars Ingebrigtsen Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 23 Dec 2021 10:33:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 43379 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch moreinfo To: Daniel Koning Cc: 43379@debbugs.gnu.org Received: via spool by 43379-submit@debbugs.gnu.org id=B43379.164025556624870 (code B ref 43379); Thu, 23 Dec 2021 10:33:01 +0000 Received: (at 43379) by debbugs.gnu.org; 23 Dec 2021 10:32:46 +0000 Received: from localhost ([127.0.0.1]:60468 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n0LOv-0006St-Vh for submit@debbugs.gnu.org; Thu, 23 Dec 2021 05:32:46 -0500 Received: from quimby.gnus.org ([95.216.78.240]:58442) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n0LOt-0006Nw-FY for 43379@debbugs.gnu.org; Thu, 23 Dec 2021 05:32:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=9ZHKMSqjP+qla+uavCuDlnOiLXT4Oddq/6ab63cKIcU=; b=krtlADAm3KeY9G+l1TxeH+QQhR CwT+BDBJAV5dJcaZTWy8cUVbVbLYlAfmuFvTrRo8x8IziH+gitNuwtqVlBEmLRHehPq+aoMUVH+nI Tip5ifIWzHtFHWo6DAZhAsBS6IlJ1hliPCnHr0YXbDfw/XhAydBPqw/tRudmYHv5sTEQ=; Received: from [84.212.220.105] (helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1n0LOk-0000qT-7x; Thu, 23 Dec 2021 11:32:36 +0100 From: Lars Ingebrigtsen References: <87zgufj0nv.fsf@gnus.org> <871r3lvl45.fsf@gnus.org> X-Now-Playing: Yves Tumor's _The Asymptotical World (EP)_: "Secrecy Is Incredibly Important To The Both of Them" Date: Thu, 23 Dec 2021 11:32:33 +0100 In-Reply-To: <871r3lvl45.fsf@gnus.org> (Lars Ingebrigtsen's message of "Fri, 12 Nov 2021 09:22:50 +0100") Message-ID: <87mtkr627y.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: Lars Ingebrigtsen writes: > I can't get a single instance of a double-mouse-x without a mouse-x > happening before, even with long double-click-times. > > Can anybody else reproduce this problem? Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Lars Ingebrigtsen writes: > I can't get a single instance of a double-mouse-x without a mouse-x > happening before, even with long double-click-times. > > Can anybody else reproduce this problem? There was no response within a month, so I'm guessing not, and I'm closing this bug report. If this is still an issue, please respond to the debbugs address and we'll reopen. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no From debbugs-submit-bounces@debbugs.gnu.org Thu Dec 23 05:32:54 2021 Received: (at control) by debbugs.gnu.org; 23 Dec 2021 10:32:54 +0000 Received: from localhost ([127.0.0.1]:60471 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n0LP4-0006Xy-9z for submit@debbugs.gnu.org; Thu, 23 Dec 2021 05:32:54 -0500 Received: from quimby.gnus.org ([95.216.78.240]:58456) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n0LP2-0006To-L8 for control@debbugs.gnu.org; Thu, 23 Dec 2021 05:32:52 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Subject:From:To:Message-Id:Date:Sender:Reply-To:Cc: MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=l9atD1qPB0yqyzuKSrfsKx7D6CPP2UANnqo3JvbR0NU=; b=j2xTGzzsFy3xnS2L9iKhH6JNvj 89nXoY6gmKvU63VnNMtu/HfSwMAkd/In33JI8c45fRW8usCtnfUjVt8SQnx3VWBxj9zd4aF2Q0+/B vresWiAfWEXCMppXzyvoC6AqFhrUOdgFxy66Bq056+0OQR9HLn83nGhW0EdFN0MzSplQ=; Received: from [84.212.220.105] (helo=xo) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1n0LOu-0000qb-QB for control@debbugs.gnu.org; Thu, 23 Dec 2021 11:32:46 +0100 Date: Thu, 23 Dec 2021 11:32:43 +0100 Message-Id: <87lf0b627o.fsf@gnus.org> To: control@debbugs.gnu.org From: Lars Ingebrigtsen Subject: control message for bug #43379 X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: close 43379 quit Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) close 43379 quit