diff options
| author | Po Lu | 2022-06-29 10:24:14 +0800 |
|---|---|---|
| committer | Po Lu | 2022-06-29 10:24:14 +0800 |
| commit | 0e6516a1f022e18f4e32848331954deb0e850d4e (patch) | |
| tree | aaf82c350a8aee4ea7867587af7a6555ca6804af /src/xselect.c | |
| parent | 9705609c0ef5e426606300da95fed4bec54923fb (diff) | |
| download | emacs-0e6516a1f022e18f4e32848331954deb0e850d4e.tar.gz emacs-0e6516a1f022e18f4e32848331954deb0e850d4e.zip | |
Fix reported problem with drag-and-drop inside VirtualBox
* lisp/x-dnd.el (x-dnd-handle-old-kde, x-dnd-handle-offix)
(x-dnd-handle-motif): Select window before handling drop, like
on Xdnd.
(x-dnd-convert-to-offix, x-dnd-do-offix-drop)
(x-dnd-handle-unsupported-drop): Accept local selection data and
use that instead.
* src/keyboard.c (kbd_buffer_get_event): Call unsupported drop
function with local selection data as 8th arg.
* src/xselect.c (x_get_local_selection): Accept new arg
`local_value'. All callers changed.
(Fx_get_local_selection): New function.
(syms_of_xselect): Update defsubrs.
* src/xterm.c (x_dnd_lose_ownership): New function.
(x_dnd_begin_drag_and_drop): Unless new variable is true, disown
XdndSelection after returning. This supposedly makes
drag-and-drop from guest to host work in VirtualBox without
causing pointer motion to become choppy afterwards.
(syms_of_xterm): New variable `x_dnd_preserve_selection_data'
and update doc string of `x-dnd-unsupported-drop-function'.
* test/lisp/dnd-tests.el (dnd-tests-begin-text-drag)
(dnd-tests-begin-file-drag, dnd-tests-begin-drag-files): Set new
variable to nil during tests.
Diffstat (limited to 'src/xselect.c')
| -rw-r--r-- | src/xselect.c | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/src/xselect.c b/src/xselect.c index d90916c6b63..a1f590632f8 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -307,18 +307,30 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, | |||
| 307 | This function is used both for remote requests (LOCAL_REQUEST is zero) | 307 | This function is used both for remote requests (LOCAL_REQUEST is zero) |
| 308 | and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). | 308 | and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). |
| 309 | 309 | ||
| 310 | If LOCAL_VALUE is non-nil, use it as the local copy. Also allow | ||
| 311 | quitting in that case, and let DPYINFO be NULL. | ||
| 312 | |||
| 310 | This calls random Lisp code, and may signal or gc. */ | 313 | This calls random Lisp code, and may signal or gc. */ |
| 311 | 314 | ||
| 312 | static Lisp_Object | 315 | static Lisp_Object |
| 313 | x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, | 316 | x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, |
| 314 | bool local_request, struct x_display_info *dpyinfo) | 317 | bool local_request, struct x_display_info *dpyinfo, |
| 318 | Lisp_Object local_value) | ||
| 315 | { | 319 | { |
| 316 | Lisp_Object local_value, tem; | 320 | Lisp_Object tem; |
| 317 | Lisp_Object handler_fn, value, check; | 321 | Lisp_Object handler_fn, value, check; |
| 322 | bool may_quit; | ||
| 323 | specpdl_ref count; | ||
| 324 | |||
| 325 | may_quit = false; | ||
| 318 | 326 | ||
| 319 | local_value = LOCAL_SELECTION (selection_symbol, dpyinfo); | 327 | if (NILP (local_value)) |
| 328 | local_value = LOCAL_SELECTION (selection_symbol, dpyinfo); | ||
| 329 | else | ||
| 330 | may_quit = true; | ||
| 320 | 331 | ||
| 321 | if (NILP (local_value)) return Qnil; | 332 | if (NILP (local_value)) |
| 333 | return Qnil; | ||
| 322 | 334 | ||
| 323 | /* TIMESTAMP is a special case. */ | 335 | /* TIMESTAMP is a special case. */ |
| 324 | if (EQ (target_type, QTIMESTAMP)) | 336 | if (EQ (target_type, QTIMESTAMP)) |
| @@ -331,8 +343,10 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, | |||
| 331 | /* Don't allow a quit within the converter. | 343 | /* Don't allow a quit within the converter. |
| 332 | When the user types C-g, he would be surprised | 344 | When the user types C-g, he would be surprised |
| 333 | if by luck it came during a converter. */ | 345 | if by luck it came during a converter. */ |
| 334 | specpdl_ref count = SPECPDL_INDEX (); | 346 | count = SPECPDL_INDEX (); |
| 335 | specbind (Qinhibit_quit, Qt); | 347 | |
| 348 | if (!may_quit) | ||
| 349 | specbind (Qinhibit_quit, Qt); | ||
| 336 | 350 | ||
| 337 | CHECK_SYMBOL (target_type); | 351 | CHECK_SYMBOL (target_type); |
| 338 | handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); | 352 | handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); |
| @@ -804,7 +818,9 @@ x_handle_selection_request (struct selection_input_event *event) | |||
| 804 | target that doesn't support XDND. */ | 818 | target that doesn't support XDND. */ |
| 805 | if (SELECTION_EVENT_TIME (event) == pending_dnd_time + 1 | 819 | if (SELECTION_EVENT_TIME (event) == pending_dnd_time + 1 |
| 806 | || SELECTION_EVENT_TIME (event) == pending_dnd_time + 2) | 820 | || SELECTION_EVENT_TIME (event) == pending_dnd_time + 2) |
| 807 | selection_symbol = QXdndSelection; | 821 | /* Always reply with the contents of PRIMARY, since that's where |
| 822 | the selection data is. */ | ||
| 823 | selection_symbol = QPRIMARY; | ||
| 808 | 824 | ||
| 809 | local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo); | 825 | local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo); |
| 810 | 826 | ||
| @@ -915,7 +931,7 @@ x_convert_selection (Lisp_Object selection_symbol, | |||
| 915 | 931 | ||
| 916 | lisp_selection | 932 | lisp_selection |
| 917 | = x_get_local_selection (selection_symbol, target_symbol, | 933 | = x_get_local_selection (selection_symbol, target_symbol, |
| 918 | false, dpyinfo); | 934 | false, dpyinfo, Qnil); |
| 919 | 935 | ||
| 920 | frame = selection_request_stack; | 936 | frame = selection_request_stack; |
| 921 | 937 | ||
| @@ -2131,7 +2147,7 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */) | |||
| 2131 | } | 2147 | } |
| 2132 | 2148 | ||
| 2133 | val = x_get_local_selection (selection_symbol, target_type, true, | 2149 | val = x_get_local_selection (selection_symbol, target_type, true, |
| 2134 | FRAME_DISPLAY_INFO (f)); | 2150 | FRAME_DISPLAY_INFO (f), Qnil); |
| 2135 | 2151 | ||
| 2136 | if (NILP (val) && FRAME_LIVE_P (f)) | 2152 | if (NILP (val) && FRAME_LIVE_P (f)) |
| 2137 | { | 2153 | { |
| @@ -2273,6 +2289,45 @@ On Nextstep, TERMINAL is unused. */) | |||
| 2273 | return (owner ? Qt : Qnil); | 2289 | return (owner ? Qt : Qnil); |
| 2274 | } | 2290 | } |
| 2275 | 2291 | ||
| 2292 | DEFUN ("x-get-local-selection", Fx_get_local_selection, Sx_get_local_selection, | ||
| 2293 | 0, 2, 0, | ||
| 2294 | doc: /* Run selection converters for VALUE, and return the result. | ||
| 2295 | TARGET is the selection target that is used to find a suitable | ||
| 2296 | converter. VALUE is a list of 4 values NAME, SELECTION-VALUE, | ||
| 2297 | TIMESTAMP and FRAME. NAME is the name of the selection that will be | ||
| 2298 | passed to selection converters, SELECTION-VALUE is the value of the | ||
| 2299 | selection used by the converter, TIMESTAMP is not meaningful (but must | ||
| 2300 | be a number that fits in an X timestamp), and FRAME is the frame | ||
| 2301 | describing the terminal for which the selection converter will be | ||
| 2302 | run. */) | ||
| 2303 | (Lisp_Object value, Lisp_Object target) | ||
| 2304 | { | ||
| 2305 | Time time; | ||
| 2306 | Lisp_Object name, timestamp, frame, result; | ||
| 2307 | |||
| 2308 | CHECK_SYMBOL (target); | ||
| 2309 | name = Fnth (make_fixnum (0), value); | ||
| 2310 | timestamp = Fnth (make_fixnum (2), value); | ||
| 2311 | frame = Fnth (make_fixnum (3), value); | ||
| 2312 | |||
| 2313 | CHECK_SYMBOL (name); | ||
| 2314 | CONS_TO_INTEGER (timestamp, Time, time); | ||
| 2315 | check_window_system (decode_live_frame (frame)); | ||
| 2316 | |||
| 2317 | result = x_get_local_selection (name, target, true, | ||
| 2318 | NULL, value); | ||
| 2319 | |||
| 2320 | if (CONSP (result) && SYMBOLP (XCAR (result))) | ||
| 2321 | { | ||
| 2322 | result = XCDR (result); | ||
| 2323 | |||
| 2324 | if (CONSP (result) && NILP (XCDR (result))) | ||
| 2325 | result = XCAR (result); | ||
| 2326 | } | ||
| 2327 | |||
| 2328 | return clean_local_selection_data (result); | ||
| 2329 | } | ||
| 2330 | |||
| 2276 | 2331 | ||
| 2277 | /* Send clipboard manager a SAVE_TARGETS request with a UTF8_STRING | 2332 | /* Send clipboard manager a SAVE_TARGETS request with a UTF8_STRING |
| 2278 | property (https://www.freedesktop.org/wiki/ClipboardManager/). */ | 2333 | property (https://www.freedesktop.org/wiki/ClipboardManager/). */ |
| @@ -2809,6 +2864,7 @@ syms_of_xselect (void) | |||
| 2809 | defsubr (&Sx_get_atom_name); | 2864 | defsubr (&Sx_get_atom_name); |
| 2810 | defsubr (&Sx_send_client_message); | 2865 | defsubr (&Sx_send_client_message); |
| 2811 | defsubr (&Sx_register_dnd_atom); | 2866 | defsubr (&Sx_register_dnd_atom); |
| 2867 | defsubr (&Sx_get_local_selection); | ||
| 2812 | 2868 | ||
| 2813 | reading_selection_reply = Fcons (Qnil, Qnil); | 2869 | reading_selection_reply = Fcons (Qnil, Qnil); |
| 2814 | staticpro (&reading_selection_reply); | 2870 | staticpro (&reading_selection_reply); |