aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-04-04 20:32:46 +0800
committerPo Lu2022-04-04 20:32:46 +0800
commit84cf3be6f77f61dd361acdb3683ab9d71e76c995 (patch)
treeccf6ea1ff0d6ac533f3665991f311750af99f738 /src
parent3d2531c12c54f9ab923603655016077450c23ab2 (diff)
downloademacs-84cf3be6f77f61dd361acdb3683ab9d71e76c995.tar.gz
emacs-84cf3be6f77f61dd361acdb3683ab9d71e76c995.zip
Handle mouse movement correctly during DND from one of our own frames
* lisp/dnd.el (dnd-handle-movement): Select the window specified in posn. * lisp/term/x-win.el (x-dnd-movement): New function. (x-dnd-movement-function): Set it as the default. * src/frame.c (delete_frame): Prevent deleting the drop source frame. * src/xterm.c (x_dnd_send_position): Set new mouse movement flags if the target window is one of our own frames. (x_dnd_begin_drag_and_drop): Call DND movement function whenever appropriate. (x_free_frame_resources): Remove useless code. (syms_of_xterm): New defvar `x-dnd-movement-function'. * src/xterm.h: Update prototypes.
Diffstat (limited to 'src')
-rw-r--r--src/frame.c4
-rw-r--r--src/xterm.c106
-rw-r--r--src/xterm.h3
3 files changed, 66 insertions, 47 deletions
diff --git a/src/frame.c b/src/frame.c
index 7a9ed3302e4..05b22ac72ba 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1987,6 +1987,10 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1987 else 1987 else
1988 error ("Attempt to delete the only frame"); 1988 error ("Attempt to delete the only frame");
1989 } 1989 }
1990#ifdef HAVE_X_WINDOWS
1991 else if (x_dnd_in_progress && f == x_dnd_frame)
1992 error ("Attempt to delete the drop source frame");
1993#endif
1990 1994
1991 XSETFRAME (frame, f); 1995 XSETFRAME (frame, f);
1992 1996
diff --git a/src/xterm.c b/src/xterm.c
index 2e4df67c76e..d29a7a122aa 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -846,7 +846,10 @@ static int x_filter_event (struct x_display_info *, XEvent *);
846/* Global state maintained during a drag-and-drop operation. */ 846/* Global state maintained during a drag-and-drop operation. */
847 847
848/* Flag that indicates if a drag-and-drop operation is in progress. */ 848/* Flag that indicates if a drag-and-drop operation is in progress. */
849static bool x_dnd_in_progress; 849bool x_dnd_in_progress;
850
851/* The frame where the drag-and-drop operation originated. */
852struct frame *x_dnd_frame;
850 853
851/* Flag that indicates if a drag-and-drop operation is no longer in 854/* Flag that indicates if a drag-and-drop operation is no longer in
852 progress, but the nested event loop should continue to run, because 855 progress, but the nested event loop should continue to run, because
@@ -946,9 +949,6 @@ static Atom *x_dnd_targets = NULL;
946/* The number of elements in that array. */ 949/* The number of elements in that array. */
947static int x_dnd_n_targets; 950static int x_dnd_n_targets;
948 951
949/* The frame where the drag-and-drop operation originated. */
950static struct frame *x_dnd_frame;
951
952/* The old window attributes of the root window before the 952/* The old window attributes of the root window before the
953 drag-and-drop operation started. It is used to keep the old event 953 drag-and-drop operation started. It is used to keep the old event
954 mask around, since that should be restored after the operation 954 mask around, since that should be restored after the operation
@@ -959,6 +959,13 @@ static XWindowAttributes x_dnd_old_window_attrs;
959 up the drag and drop operation. */ 959 up the drag and drop operation. */
960static bool x_dnd_unwind_flag; 960static bool x_dnd_unwind_flag;
961 961
962/* The frame for which `x-dnd-movement-function' should be called. */
963static struct frame *x_dnd_movement_frame;
964
965/* The coordinates which the movement function should be called
966 with. */
967static int x_dnd_movement_x, x_dnd_movement_y;
968
962struct x_client_list_window 969struct x_client_list_window
963{ 970{
964 Window window; 971 Window window;
@@ -3137,6 +3144,23 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
3137{ 3144{
3138 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); 3145 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3139 XEvent msg; 3146 XEvent msg;
3147 struct frame *target_frame;
3148 int dest_x, dest_y;
3149 Window child_return;
3150
3151 target_frame = x_top_window_to_frame (dpyinfo, target);
3152
3153 if (target_frame && XTranslateCoordinates (dpyinfo->display,
3154 dpyinfo->root_window,
3155 FRAME_X_WINDOW (target_frame),
3156 root_x, root_y, &dest_x,
3157 &dest_y, &child_return))
3158 {
3159 x_dnd_movement_frame = target_frame;
3160 x_dnd_movement_x = dest_x;
3161 x_dnd_movement_y = dest_y;
3162 return;
3163 }
3140 3164
3141 if (target == x_dnd_mouse_rect_target 3165 if (target == x_dnd_mouse_rect_target
3142 && x_dnd_mouse_rect.width 3166 && x_dnd_mouse_rect.width
@@ -3151,9 +3175,6 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
3151 return; 3175 return;
3152 } 3176 }
3153 3177
3154 if (x_top_window_to_frame (dpyinfo, target))
3155 return;
3156
3157 msg.xclient.type = ClientMessage; 3178 msg.xclient.type = ClientMessage;
3158 msg.xclient.message_type = dpyinfo->Xatom_XdndPosition; 3179 msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
3159 msg.xclient.format = 32; 3180 msg.xclient.format = 32;
@@ -9143,6 +9164,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
9143 ptrdiff_t i, end, fill; 9164 ptrdiff_t i, end, fill;
9144 XTextProperty prop; 9165 XTextProperty prop;
9145 xm_drop_start_message dmsg; 9166 xm_drop_start_message dmsg;
9167 Lisp_Object frame_object, x, y;
9146 9168
9147 if (!FRAME_VISIBLE_P (f)) 9169 if (!FRAME_VISIBLE_P (f))
9148 error ("Frame is invisible"); 9170 error ("Frame is invisible");
@@ -9229,6 +9251,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
9229 = x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking); 9251 = x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking);
9230 x_dnd_toplevels = NULL; 9252 x_dnd_toplevels = NULL;
9231 x_dnd_allow_current_frame = allow_current_frame; 9253 x_dnd_allow_current_frame = allow_current_frame;
9254 x_dnd_movement_frame = NULL;
9232 9255
9233 if (x_dnd_use_toplevels) 9256 if (x_dnd_use_toplevels)
9234 { 9257 {
@@ -9307,6 +9330,28 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
9307#endif 9330#endif
9308#endif 9331#endif
9309 9332
9333 if (x_dnd_movement_frame)
9334 {
9335 XSETFRAME (frame_object, x_dnd_movement_frame);
9336 XSETINT (x, x_dnd_movement_x);
9337 XSETINT (y, x_dnd_movement_y);
9338 x_dnd_movement_frame = NULL;
9339
9340 if (!NILP (Vx_dnd_movement_function)
9341 && !FRAME_TOOLTIP_P (XFRAME (frame_object)))
9342 {
9343 x_dnd_old_window_attrs = root_window_attrs;
9344 x_dnd_unwind_flag = true;
9345
9346 ref = SPECPDL_INDEX ();
9347 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
9348 call2 (Vx_dnd_movement_function, frame_object,
9349 Fposn_at_x_y (x, y, frame_object, Qnil));
9350 x_dnd_unwind_flag = false;
9351 unbind_to (ref, Qnil);
9352 }
9353 }
9354
9310 if (hold_quit.kind != NO_EVENT) 9355 if (hold_quit.kind != NO_EVENT)
9311 { 9356 {
9312 if (hold_quit.kind == SELECTION_REQUEST_EVENT) 9357 if (hold_quit.kind == SELECTION_REQUEST_EVENT)
@@ -20746,46 +20791,6 @@ x_free_frame_resources (struct frame *f)
20746 Lisp_Object bar; 20791 Lisp_Object bar;
20747 struct scroll_bar *b; 20792 struct scroll_bar *b;
20748#endif 20793#endif
20749 xm_drop_start_message dmsg;
20750
20751 if (x_dnd_in_progress && f == x_dnd_frame)
20752 {
20753 block_input ();
20754 if (x_dnd_last_seen_window != None
20755 && x_dnd_last_protocol_version != -1)
20756 x_dnd_send_leave (f, x_dnd_last_seen_window);
20757 else if (x_dnd_last_seen_window != None
20758 && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
20759 && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
20760 && x_dnd_motif_setup_p)
20761 {
20762 dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
20763 XM_DRAG_REASON_DROP_START);
20764 dmsg.byte_order = XM_TARGETS_TABLE_CUR;
20765 dmsg.timestamp = 0;
20766 dmsg.side_effects
20767 = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (dpyinfo,
20768 x_dnd_wanted_action),
20769 XM_DROP_SITE_VALID,
20770 xm_side_effect_from_action (dpyinfo,
20771 x_dnd_wanted_action),
20772 XM_DROP_ACTION_DROP_CANCEL);
20773 dmsg.x = 0;
20774 dmsg.y = 0;
20775 dmsg.index_atom = dpyinfo->Xatom_XdndSelection;
20776 dmsg.source_window = FRAME_X_WINDOW (f);
20777
20778 xm_send_drop_message (dpyinfo, FRAME_X_WINDOW (f),
20779 x_dnd_last_seen_window, &dmsg);
20780 }
20781 unblock_input ();
20782
20783 x_dnd_end_window = None;
20784 x_dnd_last_seen_window = None;
20785 x_dnd_in_progress = false;
20786 x_dnd_waiting_for_finish = false;
20787 x_dnd_frame = NULL;
20788 }
20789 20794
20790 block_input (); 20795 block_input ();
20791 20796
@@ -23054,4 +23059,11 @@ coordinates to a Motif drop receiver when the mouse moves outside it
23054during a drag-and-drop session, to work around broken implementations 23059during a drag-and-drop session, to work around broken implementations
23055of Motif. */); 23060of Motif. */);
23056 x_dnd_fix_motif_leave = true; 23061 x_dnd_fix_motif_leave = true;
23062
23063 DEFVAR_LISP ("x-dnd-movement-function", Vx_dnd_movement_function,
23064 doc: /* Function called upon mouse movement on a frame during drag-and-drop.
23065It should either be nil, or accept two arguments FRAME and POSITION,
23066where FRAME is the frame the mouse is on top of, and POSITION is a
23067mouse position list. */);
23068 Vx_dnd_movement_function = Qnil;
23057} 23069}
diff --git a/src/xterm.h b/src/xterm.h
index 57036af2bb5..5627fd23c57 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1548,6 +1548,9 @@ extern void x_session_close (void);
1548extern struct input_event xg_pending_quit_event; 1548extern struct input_event xg_pending_quit_event;
1549#endif 1549#endif
1550 1550
1551extern bool x_dnd_in_progress;
1552extern struct frame *x_dnd_frame;
1553
1551#ifdef HAVE_XINPUT2 1554#ifdef HAVE_XINPUT2
1552struct xi_device_t *xi_device_from_id (struct x_display_info *, int); 1555struct xi_device_t *xi_device_from_id (struct x_display_info *, int);
1553#endif 1556#endif