aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2021-05-31 10:33:10 +0000
committerAlan Mackenzie2021-05-31 10:33:10 +0000
commit6e2d3bce087d30a535b1f01715d7820576ffe390 (patch)
tree66cadf98c10587225c1e0a68076dac378337c109
parent0b1dfb5de601c945e88e98c8fc40611d015a8b77 (diff)
downloademacs-6e2d3bce087d30a535b1f01715d7820576ffe390.tar.gz
emacs-6e2d3bce087d30a535b1f01715d7820576ffe390.zip
Correct mouse handling when window origin changes between down and up events
Do this by using frame relative positions rather than window relative ones, which gave rise to spurious drag events when the origin of the window changed between the mouse down and up events. This fixes bug #48409. * keyboard.c (frame_relative_event_pos): New static variable. (make_lispy_event): Record frame relative position of down event. When the up event is in the same position, "move" this event into the window of the down event when this window (typically a mini-window) is no longer under the mouse. Call make_lispy_position a second time to generate this changed event. (syms_of_keyboard): Declare Qwindow_edges. static_pro frame_relative_event_pos.
-rw-r--r--src/keyboard.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index c855d45afab..4433cfa4193 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5018,6 +5018,10 @@ static short const internal_border_parts[] = {
5018 5018
5019static Lisp_Object button_down_location; 5019static Lisp_Object button_down_location;
5020 5020
5021/* A cons recording the original frame-relative x and y coordinates of
5022 the down mouse event. */
5023static Lisp_Object frame_relative_event_pos;
5024
5021/* Information about the most recent up-going button event: Which 5025/* Information about the most recent up-going button event: Which
5022 button, what location, and what time. */ 5026 button, what location, and what time. */
5023 5027
@@ -5669,6 +5673,7 @@ make_lispy_event (struct input_event *event)
5669 double_click_count = 1; 5673 double_click_count = 1;
5670 button_down_time = event->timestamp; 5674 button_down_time = event->timestamp;
5671 *start_pos_ptr = Fcopy_alist (position); 5675 *start_pos_ptr = Fcopy_alist (position);
5676 frame_relative_event_pos = Fcons (event->x, event->y);
5672 ignore_mouse_drag_p = false; 5677 ignore_mouse_drag_p = false;
5673 } 5678 }
5674 5679
@@ -5691,20 +5696,12 @@ make_lispy_event (struct input_event *event)
5691 ignore_mouse_drag_p = false; 5696 ignore_mouse_drag_p = false;
5692 else 5697 else
5693 { 5698 {
5694 Lisp_Object new_down, down;
5695 intmax_t xdiff = double_click_fuzz, ydiff = double_click_fuzz; 5699 intmax_t xdiff = double_click_fuzz, ydiff = double_click_fuzz;
5696 5700
5697 /* The third element of every position 5701 xdiff = XFIXNUM (event->x)
5698 should be the (x,y) pair. */ 5702 - XFIXNUM (XCAR (frame_relative_event_pos));
5699 down = Fcar (Fcdr (Fcdr (start_pos))); 5703 ydiff = XFIXNUM (event->y)
5700 new_down = Fcar (Fcdr (Fcdr (position))); 5704 - XFIXNUM (XCDR (frame_relative_event_pos));
5701
5702 if (CONSP (down)
5703 && FIXNUMP (XCAR (down)) && FIXNUMP (XCDR (down)))
5704 {
5705 xdiff = XFIXNUM (XCAR (new_down)) - XFIXNUM (XCAR (down));
5706 ydiff = XFIXNUM (XCDR (new_down)) - XFIXNUM (XCDR (down));
5707 }
5708 5705
5709 if (! (0 < double_click_fuzz 5706 if (! (0 < double_click_fuzz
5710 && - double_click_fuzz < xdiff 5707 && - double_click_fuzz < xdiff
@@ -5721,12 +5718,51 @@ make_lispy_event (struct input_event *event)
5721 a click. But mouse-drag-region completely ignores 5718 a click. But mouse-drag-region completely ignores
5722 this case and it hasn't caused any real problem, so 5719 this case and it hasn't caused any real problem, so
5723 it's probably OK to ignore it as well. */ 5720 it's probably OK to ignore it as well. */
5724 && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position))))) 5721 && (EQ (Fcar (Fcdr (start_pos)),
5722 Fcar (Fcdr (position))) /* Same buffer pos */
5723 || !EQ (Fcar (start_pos),
5724 Fcar (position))))) /* Different window */
5725 { 5725 {
5726 /* Mouse has moved enough. */ 5726 /* Mouse has moved enough. */
5727 button_down_time = 0; 5727 button_down_time = 0;
5728 click_or_drag_modifier = drag_modifier; 5728 click_or_drag_modifier = drag_modifier;
5729 } 5729 }
5730 else if (((!EQ (Fcar (start_pos), Fcar (position)))
5731 || (!EQ (Fcar (Fcdr (start_pos)),
5732 Fcar (Fcdr (position)))))
5733 /* Was the down event in a window body? */
5734 && FIXNUMP (Fcar (Fcdr (start_pos)))
5735 && WINDOW_LIVE_P (Fcar (start_pos))
5736 && Ffboundp (Qwindow_edges))
5737 /* If the window (etc.) at the mouse position has
5738 changed between the down event and the up event,
5739 we assume there's been a redisplay between the
5740 two events, and we pretend the mouse is still in
5741 the old window to prevent a spurious drag event
5742 being generated. */
5743 {
5744 Lisp_Object edges
5745 = call4 (Qwindow_edges, Fcar (start_pos), Qt, Qnil, Qt);
5746 int new_x = XFIXNUM (Fcar (frame_relative_event_pos));
5747 int new_y = XFIXNUM (Fcdr (frame_relative_event_pos));
5748
5749 /* If the up-event is outside the down-event's
5750 window, use coordinates that are within it. */
5751 if (new_x < XFIXNUM (Fcar (edges)))
5752 new_x = XFIXNUM (Fcar (edges));
5753 else if (new_x >= XFIXNUM (Fcar (Fcdr (Fcdr (edges)))))
5754 new_x = XFIXNUM (Fcar (Fcdr (Fcdr (edges)))) - 1;
5755 if (new_y < XFIXNUM (Fcar (Fcdr (edges))))
5756 new_y = XFIXNUM (Fcar (Fcdr (edges)));
5757 else if (new_y
5758 >= XFIXNUM (Fcar (Fcdr (Fcdr (Fcdr (edges))))))
5759 new_y = XFIXNUM (Fcar (Fcdr (Fcdr (Fcdr (edges))))) - 1;
5760
5761 position = make_lispy_position
5762 (XFRAME (event->frame_or_window),
5763 make_fixnum (new_x), make_fixnum (new_y),
5764 event->timestamp);
5765 }
5730 } 5766 }
5731 5767
5732 /* Don't check is_double; treat this as multiple if the 5768 /* Don't check is_double; treat this as multiple if the
@@ -11645,6 +11681,7 @@ syms_of_keyboard (void)
11645 DEFSYM (Qmake_frame_visible, "make-frame-visible"); 11681 DEFSYM (Qmake_frame_visible, "make-frame-visible");
11646 DEFSYM (Qselect_window, "select-window"); 11682 DEFSYM (Qselect_window, "select-window");
11647 DEFSYM (Qselection_request, "selection-request"); 11683 DEFSYM (Qselection_request, "selection-request");
11684 DEFSYM (Qwindow_edges, "window-edges");
11648 { 11685 {
11649 int i; 11686 int i;
11650 11687
@@ -11661,6 +11698,7 @@ syms_of_keyboard (void)
11661 11698
11662 button_down_location = make_nil_vector (5); 11699 button_down_location = make_nil_vector (5);
11663 staticpro (&button_down_location); 11700 staticpro (&button_down_location);
11701 staticpro (&frame_relative_event_pos);
11664 mouse_syms = make_nil_vector (5); 11702 mouse_syms = make_nil_vector (5);
11665 staticpro (&mouse_syms); 11703 staticpro (&mouse_syms);
11666 wheel_syms = make_nil_vector (ARRAYELTS (lispy_wheel_names)); 11704 wheel_syms = make_nil_vector (ARRAYELTS (lispy_wheel_names));