diff options
| author | Po Lu | 2022-07-04 13:41:20 +0800 |
|---|---|---|
| committer | Po Lu | 2022-07-04 13:41:20 +0800 |
| commit | 1da6a6d3271be003b545e41ae21c3071faf22f86 (patch) | |
| tree | 233371a59e930ccebcf3766d77aeb10deee2dfca /src | |
| parent | bd034b342ccf15a1887614f19de1caa9ff2f2d22 (diff) | |
| download | emacs-1da6a6d3271be003b545e41ae21c3071faf22f86.tar.gz emacs-1da6a6d3271be003b545e41ae21c3071faf22f86.zip | |
Always wait for XdndStatus before sending XdndDrop
* src/xterm.c (x_dnd_do_drop): New function.
(x_dnd_begin_drag_and_drop): Clear new flag.
(handle_one_xevent): Use that function; send drops upon receipt
of pending XdndStatus, to avoid race conditions where we don't
yet know the selected action.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 64 |
1 files changed, 55 insertions, 9 deletions
diff --git a/src/xterm.c b/src/xterm.c index 6a357b473d6..de8e973173f 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -1268,6 +1268,13 @@ static Window x_dnd_waiting_for_status_window; | |||
| 1268 | upon receiving an XdndStatus event from said window. */ | 1268 | upon receiving an XdndStatus event from said window. */ |
| 1269 | static XEvent x_dnd_pending_send_position; | 1269 | static XEvent x_dnd_pending_send_position; |
| 1270 | 1270 | ||
| 1271 | /* If true, send a drop from `x_dnd_finish_frame' to the pending | ||
| 1272 | status window after receiving all pending XdndStatus events. */ | ||
| 1273 | static bool x_dnd_need_send_drop; | ||
| 1274 | |||
| 1275 | /* The protocol version of any such drop. */ | ||
| 1276 | static int x_dnd_send_drop_proto; | ||
| 1277 | |||
| 1271 | /* The action the drop target actually chose to perform. | 1278 | /* The action the drop target actually chose to perform. |
| 1272 | 1279 | ||
| 1273 | Under XDND, this is set upon receiving the XdndFinished or | 1280 | Under XDND, this is set upon receiving the XdndFinished or |
| @@ -4529,6 +4536,19 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp, | |||
| 4529 | return true; | 4536 | return true; |
| 4530 | } | 4537 | } |
| 4531 | 4538 | ||
| 4539 | static bool | ||
| 4540 | x_dnd_do_drop (Window target, int supported) | ||
| 4541 | { | ||
| 4542 | if (x_dnd_waiting_for_status_window != target) | ||
| 4543 | return x_dnd_send_drop (x_dnd_frame, target, | ||
| 4544 | x_dnd_selection_timestamp, supported); | ||
| 4545 | |||
| 4546 | x_dnd_need_send_drop = true; | ||
| 4547 | x_dnd_send_drop_proto = supported; | ||
| 4548 | |||
| 4549 | return true; | ||
| 4550 | } | ||
| 4551 | |||
| 4532 | static void | 4552 | static void |
| 4533 | x_set_dnd_targets (Atom *targets, int ntargets) | 4553 | x_set_dnd_targets (Atom *targets, int ntargets) |
| 4534 | { | 4554 | { |
| @@ -11398,6 +11418,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 11398 | ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), | 11418 | ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), |
| 11399 | QXdndSelection); | 11419 | QXdndSelection); |
| 11400 | 11420 | ||
| 11421 | if (NILP (ltimestamp)) | ||
| 11422 | error ("No local value for XdndSelection"); | ||
| 11423 | |||
| 11401 | if (BIGNUMP (ltimestamp)) | 11424 | if (BIGNUMP (ltimestamp)) |
| 11402 | x_dnd_selection_timestamp = bignum_to_intmax (ltimestamp); | 11425 | x_dnd_selection_timestamp = bignum_to_intmax (ltimestamp); |
| 11403 | else | 11426 | else |
| @@ -11538,6 +11561,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | |||
| 11538 | x_dnd_allow_current_frame = allow_current_frame; | 11561 | x_dnd_allow_current_frame = allow_current_frame; |
| 11539 | x_dnd_movement_frame = NULL; | 11562 | x_dnd_movement_frame = NULL; |
| 11540 | x_dnd_init_type_lists = false; | 11563 | x_dnd_init_type_lists = false; |
| 11564 | x_dnd_need_send_drop = false; | ||
| 11541 | #ifdef HAVE_XKB | 11565 | #ifdef HAVE_XKB |
| 11542 | x_dnd_keyboard_state = 0; | 11566 | x_dnd_keyboard_state = 0; |
| 11543 | 11567 | ||
| @@ -16426,8 +16450,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16426 | { | 16450 | { |
| 16427 | int rc; | 16451 | int rc; |
| 16428 | 16452 | ||
| 16429 | if (x_dnd_in_progress | 16453 | if (((x_dnd_in_progress |
| 16430 | && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo | 16454 | && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo) |
| 16455 | || (x_dnd_waiting_for_finish | ||
| 16456 | && FRAME_DISPLAY_INFO (x_dnd_finish_frame) == dpyinfo)) | ||
| 16431 | && event->xclient.message_type == dpyinfo->Xatom_XdndStatus) | 16457 | && event->xclient.message_type == dpyinfo->Xatom_XdndStatus) |
| 16432 | { | 16458 | { |
| 16433 | Window target; | 16459 | Window target; |
| @@ -16436,6 +16462,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16436 | target = event->xclient.data.l[0]; | 16462 | target = event->xclient.data.l[0]; |
| 16437 | 16463 | ||
| 16438 | if (x_dnd_last_protocol_version != -1 | 16464 | if (x_dnd_last_protocol_version != -1 |
| 16465 | && x_dnd_in_progress | ||
| 16439 | && target == x_dnd_last_seen_window | 16466 | && target == x_dnd_last_seen_window |
| 16440 | && event->xclient.data.l[1] & 2) | 16467 | && event->xclient.data.l[1] & 2) |
| 16441 | { | 16468 | { |
| @@ -16452,7 +16479,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16452 | x_dnd_mouse_rect_target = None; | 16479 | x_dnd_mouse_rect_target = None; |
| 16453 | 16480 | ||
| 16454 | if (x_dnd_last_protocol_version != -1 | 16481 | if (x_dnd_last_protocol_version != -1 |
| 16455 | && target == x_dnd_last_seen_window) | 16482 | && (x_dnd_in_progress |
| 16483 | && target == x_dnd_last_seen_window)) | ||
| 16456 | { | 16484 | { |
| 16457 | if (event->xclient.data.l[1] & 1) | 16485 | if (event->xclient.data.l[1] & 1) |
| 16458 | { | 16486 | { |
| @@ -16484,6 +16512,26 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 16484 | } | 16512 | } |
| 16485 | else | 16513 | else |
| 16486 | x_dnd_waiting_for_status_window = None; | 16514 | x_dnd_waiting_for_status_window = None; |
| 16515 | |||
| 16516 | /* Send any pending drop if warranted. */ | ||
| 16517 | if (x_dnd_waiting_for_finish && x_dnd_need_send_drop | ||
| 16518 | && x_dnd_waiting_for_status_window == None) | ||
| 16519 | { | ||
| 16520 | if (event->xclient.data.l[1] & 1) | ||
| 16521 | { | ||
| 16522 | if (x_dnd_send_drop_proto >= 2) | ||
| 16523 | x_dnd_action = event->xclient.data.l[4]; | ||
| 16524 | else | ||
| 16525 | x_dnd_action = dpyinfo->Xatom_XdndActionCopy; | ||
| 16526 | } | ||
| 16527 | else | ||
| 16528 | x_dnd_action = None; | ||
| 16529 | |||
| 16530 | x_dnd_waiting_for_finish | ||
| 16531 | = x_dnd_send_drop (x_dnd_finish_frame, | ||
| 16532 | target, x_dnd_selection_timestamp, | ||
| 16533 | x_dnd_send_drop_proto); | ||
| 16534 | } | ||
| 16487 | } | 16535 | } |
| 16488 | 16536 | ||
| 16489 | goto done; | 16537 | goto done; |
| @@ -18948,9 +18996,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 18948 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; | 18996 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; |
| 18949 | 18997 | ||
| 18950 | x_dnd_waiting_for_finish | 18998 | x_dnd_waiting_for_finish |
| 18951 | = x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window, | 18999 | = x_dnd_do_drop (x_dnd_last_seen_window, |
| 18952 | x_dnd_selection_timestamp, | 19000 | x_dnd_last_protocol_version); |
| 18953 | x_dnd_last_protocol_version); | ||
| 18954 | x_dnd_finish_display = dpyinfo->display; | 19001 | x_dnd_finish_display = dpyinfo->display; |
| 18955 | } | 19002 | } |
| 18956 | else if (x_dnd_last_seen_window != None) | 19003 | else if (x_dnd_last_seen_window != None) |
| @@ -20354,9 +20401,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 20354 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; | 20401 | x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; |
| 20355 | 20402 | ||
| 20356 | x_dnd_waiting_for_finish | 20403 | x_dnd_waiting_for_finish |
| 20357 | = x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window, | 20404 | = x_dnd_do_drop (x_dnd_last_seen_window, |
| 20358 | x_dnd_selection_timestamp, | 20405 | x_dnd_last_protocol_version); |
| 20359 | x_dnd_last_protocol_version); | ||
| 20360 | x_dnd_finish_display = dpyinfo->display; | 20406 | x_dnd_finish_display = dpyinfo->display; |
| 20361 | } | 20407 | } |
| 20362 | else if (x_dnd_last_seen_window != None) | 20408 | else if (x_dnd_last_seen_window != None) |