aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-07-19 09:33:09 +0800
committerPo Lu2022-07-19 09:33:09 +0800
commitbcbd06b4bbb57d285988937f82afd70538303536 (patch)
tree9f81f7179b3111117f99d27d1f79cbccd6283ca3 /src
parent7a937167030d44341409b3a2ac7ff1704142a191 (diff)
downloademacs-bcbd06b4bbb57d285988937f82afd70538303536.tar.gz
emacs-bcbd06b4bbb57d285988937f82afd70538303536.zip
Make drag-and-drop wheel movement work locally too on X
This is provided by the XDND protocol, so it isn't fair for it to not work with local drag-and-drop. * lisp/x-dnd.el (x-dnd-note-wheel-movement): New function. Set it as the `x-dnd-wheel-function'. * src/xterm.c (x_dnd_cleanup_drag_and_drop): Clear new flags. (x_dnd_note_self_wheel): New function. Set some flags. (x_dnd_process_quit, x_dnd_begin_drag_and_drop, handle_one_xevent) (x_connection_closed, x_delete_terminal, mark_xterm): Handle and set new wheel movement flags (syms_of_xterm): New variable `x-dnd-wheel-function'.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c155
1 files changed, 138 insertions, 17 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 0436d3c00c0..88028948ba3 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1353,6 +1353,21 @@ static struct frame *x_dnd_movement_frame;
1353 with. */ 1353 with. */
1354static int x_dnd_movement_x, x_dnd_movement_y; 1354static int x_dnd_movement_x, x_dnd_movement_y;
1355 1355
1356/* The frame for which `x-dnd-wheel-function' should be called. */
1357static struct frame *x_dnd_wheel_frame;
1358
1359/* The coordinates which the wheel function should be called with. */
1360static int x_dnd_wheel_x, x_dnd_wheel_y;
1361
1362/* The button that was pressed. */
1363static int x_dnd_wheel_button;
1364
1365/* The modifier state when the button was pressed. */
1366static int x_dnd_wheel_state;
1367
1368/* When the button was pressed. */
1369static Time x_dnd_wheel_time;
1370
1356#ifdef HAVE_XKB 1371#ifdef HAVE_XKB
1357/* The keyboard state during the drag-and-drop operation. */ 1372/* The keyboard state during the drag-and-drop operation. */
1358static unsigned int x_dnd_keyboard_state; 1373static unsigned int x_dnd_keyboard_state;
@@ -4734,6 +4749,7 @@ x_dnd_cleanup_drag_and_drop (void *frame)
4734#endif 4749#endif
4735 x_dnd_return_frame_object = NULL; 4750 x_dnd_return_frame_object = NULL;
4736 x_dnd_movement_frame = NULL; 4751 x_dnd_movement_frame = NULL;
4752 x_dnd_wheel_frame = NULL;
4737 x_dnd_frame = NULL; 4753 x_dnd_frame = NULL;
4738 4754
4739 x_restore_events_after_dnd (f, &x_dnd_old_window_attrs); 4755 x_restore_events_after_dnd (f, &x_dnd_old_window_attrs);
@@ -4764,6 +4780,37 @@ x_dnd_note_self_position (struct x_display_info *dpyinfo, Window target,
4764} 4780}
4765 4781
4766static void 4782static void
4783x_dnd_note_self_wheel (struct x_display_info *dpyinfo, Window target,
4784 unsigned short root_x, unsigned short root_y,
4785 int button, unsigned int state, Time time)
4786{
4787 struct frame *f;
4788 int dest_x, dest_y;
4789 Window child_return;
4790
4791 if (button < 4 || button > 7)
4792 return;
4793
4794 f = x_top_window_to_frame (dpyinfo, target);
4795
4796 if (f && XTranslateCoordinates (dpyinfo->display,
4797 dpyinfo->root_window,
4798 FRAME_X_WINDOW (f),
4799 root_x, root_y, &dest_x,
4800 &dest_y, &child_return))
4801 {
4802 x_dnd_wheel_frame = f;
4803 x_dnd_wheel_x = dest_x;
4804 x_dnd_wheel_y = dest_y;
4805 x_dnd_wheel_button = button;
4806 x_dnd_wheel_state = state;
4807 x_dnd_wheel_time = time;
4808
4809 return;
4810 }
4811}
4812
4813static void
4767x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target, 4814x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target,
4768 unsigned short root_x, unsigned short root_y, 4815 unsigned short root_x, unsigned short root_y,
4769 Time timestamp) 4816 Time timestamp)
@@ -11395,6 +11442,7 @@ x_dnd_process_quit (struct frame *f, Time timestamp)
11395 x_dnd_waiting_for_finish = false; 11442 x_dnd_waiting_for_finish = false;
11396 x_dnd_return_frame_object = NULL; 11443 x_dnd_return_frame_object = NULL;
11397 x_dnd_movement_frame = NULL; 11444 x_dnd_movement_frame = NULL;
11445 x_dnd_wheel_frame = NULL;
11398} 11446}
11399 11447
11400/* This function is defined far away from the rest of the XDND code so 11448/* This function is defined far away from the rest of the XDND code so
@@ -11618,6 +11666,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
11618 x_dnd_toplevels = NULL; 11666 x_dnd_toplevels = NULL;
11619 x_dnd_allow_current_frame = allow_current_frame; 11667 x_dnd_allow_current_frame = allow_current_frame;
11620 x_dnd_movement_frame = NULL; 11668 x_dnd_movement_frame = NULL;
11669 x_dnd_wheel_frame = NULL;
11621 x_dnd_init_type_lists = false; 11670 x_dnd_init_type_lists = false;
11622 x_dnd_need_send_drop = false; 11671 x_dnd_need_send_drop = false;
11623#ifdef HAVE_XKB 11672#ifdef HAVE_XKB
@@ -11787,6 +11836,43 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
11787 } 11836 }
11788 } 11837 }
11789 11838
11839 if (x_dnd_wheel_frame
11840 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
11841 {
11842 XSETFRAME (frame_object, x_dnd_wheel_frame);
11843 XSETINT (x, x_dnd_wheel_x);
11844 XSETINT (y, x_dnd_wheel_y);
11845 x_dnd_wheel_frame = NULL;
11846
11847 if (!NILP (Vx_dnd_wheel_function)
11848 && FRAME_LIVE_P (XFRAME (frame_object))
11849 && !FRAME_TOOLTIP_P (XFRAME (frame_object))
11850 && x_dnd_movement_x >= 0
11851 && x_dnd_movement_y >= 0
11852 && x_dnd_frame
11853 && (XFRAME (frame_object) != x_dnd_frame
11854 || x_dnd_allow_current_frame))
11855 {
11856 x_dnd_old_window_attrs = root_window_attrs;
11857 x_dnd_unwind_flag = true;
11858
11859 ref = SPECPDL_INDEX ();
11860 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
11861 call4 (Vx_dnd_wheel_function,
11862 Fposn_at_x_y (x, y, frame_object, Qnil),
11863 make_fixnum (x_dnd_wheel_button),
11864 make_uint (x_dnd_wheel_state),
11865 make_uint (x_dnd_wheel_time));
11866 x_dnd_unwind_flag = false;
11867 unbind_to (ref, Qnil);
11868
11869 /* Redisplay this way to preserve the echo area.
11870 Otherwise, the contents will abruptly disappear
11871 when the mouse moves over a frame. */
11872 redisplay_preserve_echo_area (33);
11873 }
11874 }
11875
11790 if (hold_quit.kind != NO_EVENT) 11876 if (hold_quit.kind != NO_EVENT)
11791 { 11877 {
11792 x_dnd_process_quit (f, hold_quit.timestamp); 11878 x_dnd_process_quit (f, hold_quit.timestamp);
@@ -11890,6 +11976,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
11890 if (x_dnd_movement_frame) 11976 if (x_dnd_movement_frame)
11891 x_dnd_movement_frame = NULL; 11977 x_dnd_movement_frame = NULL;
11892 11978
11979 if (x_dnd_wheel_frame)
11980 x_dnd_wheel_frame = NULL;
11981
11893 if (hold_quit.kind != NO_EVENT) 11982 if (hold_quit.kind != NO_EVENT)
11894 EVENT_INIT (hold_quit); 11983 EVENT_INIT (hold_quit);
11895 } 11984 }
@@ -11902,6 +11991,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
11902 current_hold_quit = NULL; 11991 current_hold_quit = NULL;
11903#endif 11992#endif
11904 x_dnd_movement_frame = NULL; 11993 x_dnd_movement_frame = NULL;
11994 x_dnd_wheel_frame = NULL;
11905 x_restore_events_after_dnd (f, &root_window_attrs); 11995 x_restore_events_after_dnd (f, &root_window_attrs);
11906 11996
11907 if (x_dnd_return_frame == 3 11997 if (x_dnd_return_frame == 3
@@ -18914,18 +19004,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
18914 dpyinfo->grabbed &= ~(1 << event->xbutton.button); 19004 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
18915 19005
18916 if (event->xbutton.type == ButtonPress 19006 if (event->xbutton.type == ButtonPress
18917 && x_dnd_last_seen_window != None 19007 && x_dnd_last_seen_window != None)
18918 && x_dnd_last_protocol_version != -1)
18919 { 19008 {
18920 x_dnd_send_position (x_dnd_frame, 19009 if (x_dnd_last_window_is_frame)
18921 x_dnd_last_seen_window, 19010 x_dnd_note_self_wheel (dpyinfo,
18922 x_dnd_last_protocol_version, 19011 x_dnd_last_seen_window,
18923 event->xbutton.x_root, 19012 event->xbutton.x_root,
18924 event->xbutton.y_root, 19013 event->xbutton.y_root,
18925 x_dnd_selection_timestamp, 19014 event->xbutton.button,
18926 x_dnd_wanted_action, 19015 event->xbutton.state,
18927 event->xbutton.button, 19016 event->xbutton.time);
18928 event->xbutton.state); 19017 else if (x_dnd_last_protocol_version != -1)
19018 x_dnd_send_position (x_dnd_frame,
19019 x_dnd_last_seen_window,
19020 x_dnd_last_protocol_version,
19021 event->xbutton.x_root,
19022 event->xbutton.y_root,
19023 x_dnd_selection_timestamp,
19024 x_dnd_wanted_action,
19025 event->xbutton.button,
19026 event->xbutton.state);
18929 19027
18930 goto OTHER; 19028 goto OTHER;
18931 } 19029 }
@@ -20315,15 +20413,21 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20315#endif 20413#endif
20316 20414
20317 if (xev->evtype == XI_ButtonPress 20415 if (xev->evtype == XI_ButtonPress
20318 && x_dnd_last_seen_window != None 20416 && x_dnd_last_seen_window != None)
20319 && x_dnd_last_protocol_version != -1)
20320 { 20417 {
20321 dnd_state = xi_convert_event_state (xev); 20418 dnd_state = xi_convert_event_state (xev);
20322 20419
20323 x_dnd_send_position (x_dnd_frame, x_dnd_last_seen_window, 20420 if (x_dnd_last_window_is_frame)
20324 x_dnd_last_protocol_version, xev->root_x, 20421 x_dnd_note_self_wheel (dpyinfo,
20325 xev->root_y, x_dnd_selection_timestamp, 20422 x_dnd_last_seen_window,
20326 x_dnd_wanted_action, xev->detail, dnd_state); 20423 xev->root_x, xev->root_y,
20424 xev->detail, dnd_state,
20425 xev->time);
20426 else
20427 x_dnd_send_position (x_dnd_frame, x_dnd_last_seen_window,
20428 x_dnd_last_protocol_version, xev->root_x,
20429 xev->root_y, x_dnd_selection_timestamp,
20430 x_dnd_wanted_action, xev->detail, dnd_state);
20327 20431
20328 goto XI_OTHER; 20432 goto XI_OTHER;
20329 } 20433 }
@@ -23482,6 +23586,7 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
23482 23586
23483 x_dnd_return_frame_object = NULL; 23587 x_dnd_return_frame_object = NULL;
23484 x_dnd_movement_frame = NULL; 23588 x_dnd_movement_frame = NULL;
23589 x_dnd_wheel_frame = NULL;
23485 x_dnd_frame = NULL; 23590 x_dnd_frame = NULL;
23486 } 23591 }
23487 23592
@@ -27750,6 +27855,7 @@ x_delete_terminal (struct terminal *terminal)
27750 27855
27751 x_dnd_return_frame_object = NULL; 27856 x_dnd_return_frame_object = NULL;
27752 x_dnd_movement_frame = NULL; 27857 x_dnd_movement_frame = NULL;
27858 x_dnd_wheel_frame = NULL;
27753 x_dnd_frame = NULL; 27859 x_dnd_frame = NULL;
27754 } 27860 }
27755 27861
@@ -28008,6 +28114,12 @@ mark_xterm (void)
28008 mark_object (val); 28114 mark_object (val);
28009 } 28115 }
28010 28116
28117 if (x_dnd_wheel_frame)
28118 {
28119 XSETFRAME (val, x_dnd_wheel_frame);
28120 mark_object (val);
28121 }
28122
28011#if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \ 28123#if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
28012 || defined HAVE_XRANDR || defined USE_GTK 28124 || defined HAVE_XRANDR || defined USE_GTK
28013 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) 28125 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
@@ -28454,6 +28566,15 @@ where FRAME is the frame the mouse is on top of, and POSITION is a
28454mouse position list. */); 28566mouse position list. */);
28455 Vx_dnd_movement_function = Qnil; 28567 Vx_dnd_movement_function = Qnil;
28456 28568
28569 DEFVAR_LISP ("x-dnd-wheel-function", Vx_dnd_wheel_function,
28570 doc: /* Function called upon wheel movement on a frame during drag-and-drop.
28571It should either be nil, or accept four arguments POSITION, BUTTON,
28572STATE and TIME, where POSITION is a mouse position list describing
28573where the wheel moved, BUTTON is the wheel button that was pressed,
28574STATE is the X modifier state at the time of the wheel movement, and
28575TIME is the X server time at which the wheel moved. */);
28576 Vx_dnd_wheel_function = Qnil;
28577
28457 DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function, 28578 DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function,
28458 doc: /* Function called when trying to drop on an unsupported window. 28579 doc: /* Function called when trying to drop on an unsupported window.
28459This function is called whenever the user tries to drop something on a 28580This function is called whenever the user tries to drop something on a