aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-07-04 13:41:20 +0800
committerPo Lu2022-07-04 13:41:20 +0800
commit1da6a6d3271be003b545e41ae21c3071faf22f86 (patch)
tree233371a59e930ccebcf3766d77aeb10deee2dfca /src
parentbd034b342ccf15a1887614f19de1caa9ff2f2d22 (diff)
downloademacs-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.c64
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. */
1269static XEvent x_dnd_pending_send_position; 1269static 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. */
1273static bool x_dnd_need_send_drop;
1274
1275/* The protocol version of any such drop. */
1276static 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
4539static bool
4540x_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
4532static void 4552static void
4533x_set_dnd_targets (Atom *targets, int ntargets) 4553x_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)