diff options
| author | Po Lu | 2022-03-16 12:33:15 +0800 |
|---|---|---|
| committer | Po Lu | 2022-03-16 12:33:15 +0800 |
| commit | f62a6acd00fa5045fbc537bcaa87756416e246a4 (patch) | |
| tree | ff29580e4f687a5d5ec7841486cd1d62f002f27f /src | |
| parent | 5ff13718a53c161c3a0d3e8795544a740c10064b (diff) | |
| download | emacs-f62a6acd00fa5045fbc537bcaa87756416e246a4.tar.gz emacs-f62a6acd00fa5045fbc537bcaa87756416e246a4.zip | |
Better handle drag-and-drop from one Emacs frame to another
* doc/lispref/frames.texi (Drag and Drop): Document new
parameter `return-frame' to `x-begin-drag'.
* lisp/mouse.el (mouse-drag-and-drop-region): Utilize new
feature.
* src/xfns.c (Fx_begin_drag): New parameter `return-frame'.
* src/xterm.c (x_dnd_begin_drag_and_drop): New parameter
return_frame_p.
(handle_one_xevent): Set new flags and return frame whenever
appropriate.
* src/xterm.h: Update prototypes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfns.c | 11 | ||||
| -rw-r--r-- | src/xterm.c | 50 | ||||
| -rw-r--r-- | src/xterm.h | 3 |
3 files changed, 59 insertions, 5 deletions
diff --git a/src/xfns.c b/src/xfns.c index 0d197c1dd7d..b5d0b2c54e8 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -6582,7 +6582,7 @@ The coordinates X and Y are interpreted in pixels relative to a position | |||
| 6582 | return Qnil; | 6582 | return Qnil; |
| 6583 | } | 6583 | } |
| 6584 | 6584 | ||
| 6585 | DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 3, 0, | 6585 | DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 4, 0, |
| 6586 | doc: /* Begin dragging contents on FRAME, with targets TARGETS. | 6586 | doc: /* Begin dragging contents on FRAME, with targets TARGETS. |
| 6587 | TARGETS is a list of strings, which defines the X selection targets | 6587 | TARGETS is a list of strings, which defines the X selection targets |
| 6588 | that will be available to the drop target. Block until the mouse | 6588 | that will be available to the drop target. Block until the mouse |
| @@ -6607,9 +6607,14 @@ Emacs. For that reason, they are not mentioned here. Consult | |||
| 6607 | "Drag-and-Drop Protocol for the X Window System" for more details: | 6607 | "Drag-and-Drop Protocol for the X Window System" for more details: |
| 6608 | https://freedesktop.org/wiki/Specifications/XDND/. | 6608 | https://freedesktop.org/wiki/Specifications/XDND/. |
| 6609 | 6609 | ||
| 6610 | If RETURN-FRAME is non-nil, this function will return the frame if the | ||
| 6611 | mouse pointer moves onto an Emacs frame, after first moving out of | ||
| 6612 | FRAME. | ||
| 6613 | |||
| 6610 | If ACTION is not specified or nil, `XdndActionCopy' is used | 6614 | If ACTION is not specified or nil, `XdndActionCopy' is used |
| 6611 | instead. */) | 6615 | instead. */) |
| 6612 | (Lisp_Object targets, Lisp_Object action, Lisp_Object frame) | 6616 | (Lisp_Object targets, Lisp_Object action, Lisp_Object frame, |
| 6617 | Lisp_Object return_frame) | ||
| 6613 | { | 6618 | { |
| 6614 | struct frame *f = decode_window_system_frame (frame); | 6619 | struct frame *f = decode_window_system_frame (frame); |
| 6615 | int ntargets = 0; | 6620 | int ntargets = 0; |
| @@ -6655,7 +6660,7 @@ instead. */) | |||
| 6655 | 6660 | ||
| 6656 | x_set_dnd_targets (target_atoms, ntargets); | 6661 | x_set_dnd_targets (target_atoms, ntargets); |
| 6657 | lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time, | 6662 | lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time, |
| 6658 | xaction); | 6663 | xaction, !NILP (return_frame)); |
| 6659 | 6664 | ||
| 6660 | return lval; | 6665 | return lval; |
| 6661 | } | 6666 | } |
diff --git a/src/xterm.c b/src/xterm.c index 8a4344f2a4f..a3d20a9d226 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -771,6 +771,15 @@ static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar | |||
| 771 | #endif | 771 | #endif |
| 772 | 772 | ||
| 773 | static bool x_dnd_in_progress; | 773 | static bool x_dnd_in_progress; |
| 774 | |||
| 775 | /* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'. | ||
| 776 | |||
| 777 | 0 means to do nothing. 1 means to wait for the mouse to first exit | ||
| 778 | `x_dnd_frame'. 2 means to wait for the mouse to move onto a frame, | ||
| 779 | and 3 means to `x_dnd_return_frame_object'. */ | ||
| 780 | static int x_dnd_return_frame; | ||
| 781 | static struct frame *x_dnd_return_frame_object; | ||
| 782 | |||
| 774 | static Window x_dnd_last_seen_window; | 783 | static Window x_dnd_last_seen_window; |
| 775 | static int x_dnd_last_protocol_version; | 784 | static int x_dnd_last_protocol_version; |
| 776 | static Time x_dnd_selection_timestamp; | 785 | static Time x_dnd_selection_timestamp; |
| @@ -1025,7 +1034,8 @@ x_set_dnd_targets (Atom *targets, int ntargets) | |||
| 1025 | } | 1034 | } |
| 1026 | 1035 | ||
| 1027 | Lisp_Object | 1036 | Lisp_Object |
| 1028 | x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction) | 1037 | x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, |
| 1038 | bool return_frame_p) | ||
| 1029 | { | 1039 | { |
| 1030 | XEvent next_event; | 1040 | XEvent next_event; |
| 1031 | struct input_event hold_quit; | 1041 | struct input_event hold_quit; |
| @@ -1054,6 +1064,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction) | |||
| 1054 | x_dnd_mouse_rect_target = None; | 1064 | x_dnd_mouse_rect_target = None; |
| 1055 | x_dnd_action = None; | 1065 | x_dnd_action = None; |
| 1056 | x_dnd_wanted_action = xaction; | 1066 | x_dnd_wanted_action = xaction; |
| 1067 | x_dnd_return_frame = 0; | ||
| 1068 | |||
| 1069 | if (return_frame_p) | ||
| 1070 | x_dnd_return_frame = 1; | ||
| 1057 | 1071 | ||
| 1058 | while (x_dnd_in_progress) | 1072 | while (x_dnd_in_progress) |
| 1059 | { | 1073 | { |
| @@ -1085,6 +1099,14 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction) | |||
| 1085 | } | 1099 | } |
| 1086 | } | 1100 | } |
| 1087 | 1101 | ||
| 1102 | if (x_dnd_return_frame == 3) | ||
| 1103 | { | ||
| 1104 | x_dnd_return_frame_object->mouse_moved = true; | ||
| 1105 | |||
| 1106 | XSETFRAME (action, x_dnd_return_frame_object); | ||
| 1107 | return action; | ||
| 1108 | } | ||
| 1109 | |||
| 1088 | FRAME_DISPLAY_INFO (f)->grabbed = 0; | 1110 | FRAME_DISPLAY_INFO (f)->grabbed = 0; |
| 1089 | 1111 | ||
| 1090 | if (x_dnd_wanted_action != None) | 1112 | if (x_dnd_wanted_action != None) |
| @@ -11606,6 +11628,19 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 11606 | && x_dnd_last_seen_window != FRAME_X_WINDOW (x_dnd_frame)) | 11628 | && x_dnd_last_seen_window != FRAME_X_WINDOW (x_dnd_frame)) |
| 11607 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 11629 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 11608 | 11630 | ||
| 11631 | if (x_dnd_last_seen_window == FRAME_X_WINDOW (x_dnd_frame) | ||
| 11632 | && x_dnd_return_frame == 1) | ||
| 11633 | x_dnd_return_frame = 2; | ||
| 11634 | |||
| 11635 | if (x_dnd_return_frame == 2 | ||
| 11636 | && x_window_to_frame (dpyinfo, target)) | ||
| 11637 | { | ||
| 11638 | x_dnd_in_progress = false; | ||
| 11639 | x_dnd_return_frame_object | ||
| 11640 | = x_window_to_frame (dpyinfo, target); | ||
| 11641 | x_dnd_return_frame = 3; | ||
| 11642 | } | ||
| 11643 | |||
| 11609 | x_dnd_wanted_action = None; | 11644 | x_dnd_wanted_action = None; |
| 11610 | x_dnd_last_seen_window = target; | 11645 | x_dnd_last_seen_window = target; |
| 11611 | x_dnd_last_protocol_version | 11646 | x_dnd_last_protocol_version |
| @@ -12825,6 +12860,19 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 12825 | && x_dnd_last_seen_window != FRAME_X_WINDOW (x_dnd_frame)) | 12860 | && x_dnd_last_seen_window != FRAME_X_WINDOW (x_dnd_frame)) |
| 12826 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); | 12861 | x_dnd_send_leave (x_dnd_frame, x_dnd_last_seen_window); |
| 12827 | 12862 | ||
| 12863 | if (x_dnd_last_seen_window == FRAME_X_WINDOW (x_dnd_frame) | ||
| 12864 | && x_dnd_return_frame == 1) | ||
| 12865 | x_dnd_return_frame = 2; | ||
| 12866 | |||
| 12867 | if (x_dnd_return_frame == 2 | ||
| 12868 | && x_window_to_frame (dpyinfo, target)) | ||
| 12869 | { | ||
| 12870 | x_dnd_in_progress = false; | ||
| 12871 | x_dnd_return_frame_object | ||
| 12872 | = x_window_to_frame (dpyinfo, target); | ||
| 12873 | x_dnd_return_frame = 3; | ||
| 12874 | } | ||
| 12875 | |||
| 12828 | x_dnd_last_seen_window = target; | 12876 | x_dnd_last_seen_window = target; |
| 12829 | x_dnd_last_protocol_version | 12877 | x_dnd_last_protocol_version |
| 12830 | = x_dnd_get_window_proto (dpyinfo, target); | 12878 | = x_dnd_get_window_proto (dpyinfo, target); |
diff --git a/src/xterm.h b/src/xterm.h index 225aaf4cad5..9665e92a9fb 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1367,7 +1367,8 @@ extern void x_scroll_bar_configure (GdkEvent *); | |||
| 1367 | 1367 | ||
| 1368 | extern void x_display_set_last_user_time (struct x_display_info *, Time); | 1368 | extern void x_display_set_last_user_time (struct x_display_info *, Time); |
| 1369 | 1369 | ||
| 1370 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom); | 1370 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, |
| 1371 | bool); | ||
| 1371 | extern void x_set_dnd_targets (Atom *, int); | 1372 | extern void x_set_dnd_targets (Atom *, int); |
| 1372 | 1373 | ||
| 1373 | INLINE int | 1374 | INLINE int |