diff options
| author | Po Lu | 2022-06-13 15:01:06 +0800 |
|---|---|---|
| committer | Po Lu | 2022-06-13 15:02:41 +0800 |
| commit | a1a435b3f6c7afa910da2256334471ba49010974 (patch) | |
| tree | add823f06b7f05d4dd4a57d54854e8af2ccae67f /src | |
| parent | 7cd1f432c62d5677fb2d44ed05ed9546c3c292dc (diff) | |
| download | emacs-a1a435b3f6c7afa910da2256334471ba49010974.tar.gz emacs-a1a435b3f6c7afa910da2256334471ba49010974.zip | |
Respect test function when performing local drag-and-drop
* lisp/x-dnd.el (x-dnd-test-function): Fix doc string to
describe what is actually accepted.
(x-dnd-known-types, x-dnd-targets-list): Fix coding style.
(x-dnd-handle-native-drop): New function.
* src/xselect.c (x_atom_to_symbol): Export.
* src/xterm.c (x_dnd_note_self_drop): Call new variable to
determine what action to return.
(x_clear_dnd_action): New function.
(x_dnd_begin_drag_and_drop): Respect new variable.
(syms_of_xterm): New defvar `x-dnd-native-test-function'.
* src/xterm.h: Update prototypes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xselect.c | 4 | ||||
| -rw-r--r-- | src/xterm.c | 54 | ||||
| -rw-r--r-- | src/xterm.h | 1 |
3 files changed, 52 insertions, 7 deletions
diff --git a/src/xselect.c b/src/xselect.c index bb5a1447df7..490a008dfcb 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -112,7 +112,7 @@ selection_quantum (Display *display) | |||
| 112 | : MAX_SELECTION_QUANTUM); | 112 | : MAX_SELECTION_QUANTUM); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | #define LOCAL_SELECTION(selection_symbol,dpyinfo) \ | 115 | #define LOCAL_SELECTION(selection_symbol, dpyinfo) \ |
| 116 | assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) | 116 | assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) |
| 117 | 117 | ||
| 118 | 118 | ||
| @@ -179,7 +179,7 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) | |||
| 179 | /* This converts a server Atom to a Lisp symbol, avoiding server roundtrips | 179 | /* This converts a server Atom to a Lisp symbol, avoiding server roundtrips |
| 180 | and calls to intern whenever possible. */ | 180 | and calls to intern whenever possible. */ |
| 181 | 181 | ||
| 182 | static Lisp_Object | 182 | Lisp_Object |
| 183 | x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) | 183 | x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) |
| 184 | { | 184 | { |
| 185 | char *str; | 185 | char *str; |
diff --git a/src/xterm.c b/src/xterm.c index 81b3b5cbeff..d9dd29ca128 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -1228,6 +1228,10 @@ static XRectangle x_dnd_mouse_rect; | |||
| 1228 | protocol, this is set to the atom XdndActionPrivate. */ | 1228 | protocol, this is set to the atom XdndActionPrivate. */ |
| 1229 | static Atom x_dnd_action; | 1229 | static Atom x_dnd_action; |
| 1230 | 1230 | ||
| 1231 | /* The symbol to return from `x-begin-drag' if non-nil. Takes | ||
| 1232 | precedence over `x_dnd_action`. */ | ||
| 1233 | static Lisp_Object x_dnd_action_symbol; | ||
| 1234 | |||
| 1231 | /* The action we want the drop target to perform. The drop target may | 1235 | /* The action we want the drop target to perform. The drop target may |
| 1232 | elect to perform some different action, which is guaranteed to be | 1236 | elect to perform some different action, which is guaranteed to be |
| 1233 | in `x_dnd_action' upon completion of a drop. */ | 1237 | in `x_dnd_action' upon completion of a drop. */ |
| @@ -1242,7 +1246,7 @@ static uint8_t x_dnd_motif_operations; | |||
| 1242 | static uint8_t x_dnd_first_motif_operation; | 1246 | static uint8_t x_dnd_first_motif_operation; |
| 1243 | 1247 | ||
| 1244 | /* Array of selection targets available to the drop target. */ | 1248 | /* Array of selection targets available to the drop target. */ |
| 1245 | static Atom *x_dnd_targets = NULL; | 1249 | static Atom *x_dnd_targets; |
| 1246 | 1250 | ||
| 1247 | /* The number of elements in that array. */ | 1251 | /* The number of elements in that array. */ |
| 1248 | static int x_dnd_n_targets; | 1252 | static int x_dnd_n_targets; |
| @@ -4298,15 +4302,30 @@ x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target, | |||
| 4298 | if (!f) | 4302 | if (!f) |
| 4299 | return; | 4303 | return; |
| 4300 | 4304 | ||
| 4305 | if (NILP (Vx_dnd_native_test_function)) | ||
| 4306 | return; | ||
| 4307 | |||
| 4301 | if (!XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, | 4308 | if (!XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, |
| 4302 | FRAME_X_WINDOW (f), root_x, root_y, | 4309 | FRAME_X_WINDOW (f), root_x, root_y, |
| 4303 | &win_x, &win_y, &dummy)) | 4310 | &win_x, &win_y, &dummy)) |
| 4304 | return; | 4311 | return; |
| 4305 | 4312 | ||
| 4306 | /* Emacs can't respond to DND events inside the nested event | 4313 | /* Emacs can't respond to DND events inside the nested event loop, |
| 4307 | loop, so when dragging items to itself, always return | 4314 | so when dragging items to itself, call the test function |
| 4308 | XdndActionPrivate. */ | 4315 | manually. */ |
| 4309 | x_dnd_action = dpyinfo->Xatom_XdndActionPrivate; | 4316 | |
| 4317 | XSETFRAME (lval, f); | ||
| 4318 | x_dnd_action = None; | ||
| 4319 | x_dnd_action_symbol | ||
| 4320 | = safe_call2 (Vx_dnd_native_test_function, | ||
| 4321 | Fposn_at_x_y (make_fixnum (win_x), | ||
| 4322 | make_fixnum (win_y), | ||
| 4323 | lval, Qnil), | ||
| 4324 | x_atom_to_symbol (dpyinfo, | ||
| 4325 | x_dnd_wanted_action)); | ||
| 4326 | |||
| 4327 | if (!SYMBOLP (x_dnd_action_symbol)) | ||
| 4328 | return; | ||
| 4310 | 4329 | ||
| 4311 | EVENT_INIT (ie); | 4330 | EVENT_INIT (ie); |
| 4312 | 4331 | ||
| @@ -10779,6 +10798,12 @@ x_detect_pending_selection_requests (void) | |||
| 10779 | return pending_selection_requests; | 10798 | return pending_selection_requests; |
| 10780 | } | 10799 | } |
| 10781 | 10800 | ||
| 10801 | static void | ||
| 10802 | x_clear_dnd_action (void) | ||
| 10803 | { | ||
| 10804 | x_dnd_action_symbol = Qnil; | ||
| 10805 | } | ||
| 10806 | |||
| 10782 | /* This function is defined far away from the rest of the XDND code so | 10807 | /* This function is defined far away from the rest of the XDND code so |
| 10783 | it can utilize `x_any_window_to_frame'. */ | 10808 | it can utilize `x_any_window_to_frame'. */ |
| 10784 | 10809 | ||
| @@ -10922,6 +10947,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 10922 | 10947 | ||
| 10923 | x_set_dnd_targets (target_atoms, ntargets); | 10948 | x_set_dnd_targets (target_atoms, ntargets); |
| 10924 | record_unwind_protect_void (x_free_dnd_targets); | 10949 | record_unwind_protect_void (x_free_dnd_targets); |
| 10950 | record_unwind_protect_void (x_clear_dnd_action); | ||
| 10925 | 10951 | ||
| 10926 | ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), | 10952 | ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), |
| 10927 | QXdndSelection); | 10953 | QXdndSelection); |
| @@ -11042,6 +11068,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 11042 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; | 11068 | x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; |
| 11043 | x_dnd_mouse_rect_target = None; | 11069 | x_dnd_mouse_rect_target = None; |
| 11044 | x_dnd_action = None; | 11070 | x_dnd_action = None; |
| 11071 | x_dnd_action_symbol = Qnil; | ||
| 11045 | x_dnd_wanted_action = xaction; | 11072 | x_dnd_wanted_action = xaction; |
| 11046 | x_dnd_return_frame = 0; | 11073 | x_dnd_return_frame = 0; |
| 11047 | x_dnd_waiting_for_finish = false; | 11074 | x_dnd_waiting_for_finish = false; |
| @@ -11435,6 +11462,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 11435 | x_dnd_return_frame_object = NULL; | 11462 | x_dnd_return_frame_object = NULL; |
| 11436 | FRAME_DISPLAY_INFO (f)->grabbed = 0; | 11463 | FRAME_DISPLAY_INFO (f)->grabbed = 0; |
| 11437 | 11464 | ||
| 11465 | if (!NILP (x_dnd_action_symbol)) | ||
| 11466 | return unbind_to (base, x_dnd_action_symbol); | ||
| 11467 | |||
| 11438 | if (x_dnd_action != None) | 11468 | if (x_dnd_action != None) |
| 11439 | { | 11469 | { |
| 11440 | block_input (); | 11470 | block_input (); |
| @@ -26942,6 +26972,9 @@ syms_of_xterm (void) | |||
| 26942 | x_dnd_monitors = Qnil; | 26972 | x_dnd_monitors = Qnil; |
| 26943 | staticpro (&x_dnd_monitors); | 26973 | staticpro (&x_dnd_monitors); |
| 26944 | 26974 | ||
| 26975 | x_dnd_action_symbol = Qnil; | ||
| 26976 | staticpro (&x_dnd_action_symbol); | ||
| 26977 | |||
| 26945 | DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); | 26978 | DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); |
| 26946 | DEFSYM (Qlatin_1, "latin-1"); | 26979 | DEFSYM (Qlatin_1, "latin-1"); |
| 26947 | DEFSYM (Qnow, "now"); | 26980 | DEFSYM (Qnow, "now"); |
| @@ -27189,4 +27222,15 @@ This variable contains the list of drag-and-drop selection targets | |||
| 27189 | during a drag-and-drop operation, in the same format as the TARGET | 27222 | during a drag-and-drop operation, in the same format as the TARGET |
| 27190 | argument to `x-begin-drag'. */); | 27223 | argument to `x-begin-drag'. */); |
| 27191 | Vx_dnd_targets_list = Qnil; | 27224 | Vx_dnd_targets_list = Qnil; |
| 27225 | |||
| 27226 | DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function, | ||
| 27227 | doc: /* Function called to determine return when dropping on Emacs itself. | ||
| 27228 | It should accept two arguments POS and ACTION, and return a symbol | ||
| 27229 | describing what to return from `x-begin-drag'. POS is a mouse | ||
| 27230 | position list detailing the location of the drop, and ACTION is the | ||
| 27231 | action specified by the caller of `x-begin-drag'. | ||
| 27232 | |||
| 27233 | If nil or a non-symbol value is returned, the drop will be | ||
| 27234 | cancelled. */); | ||
| 27235 | Vx_dnd_native_test_function = Qnil; | ||
| 27192 | } | 27236 | } |
diff --git a/src/xterm.h b/src/xterm.h index 25d145c6c0a..25c2453ee78 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1535,6 +1535,7 @@ extern void x_handle_property_notify (const XPropertyEvent *); | |||
| 1535 | extern void x_handle_selection_notify (const XSelectionEvent *); | 1535 | extern void x_handle_selection_notify (const XSelectionEvent *); |
| 1536 | extern void x_handle_selection_event (struct selection_input_event *); | 1536 | extern void x_handle_selection_event (struct selection_input_event *); |
| 1537 | extern void x_clear_frame_selections (struct frame *); | 1537 | extern void x_clear_frame_selections (struct frame *); |
| 1538 | extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom); | ||
| 1538 | 1539 | ||
| 1539 | extern bool x_handle_dnd_message (struct frame *, | 1540 | extern bool x_handle_dnd_message (struct frame *, |
| 1540 | const XClientMessageEvent *, | 1541 | const XClientMessageEvent *, |