aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-07-16 11:53:42 +0800
committerPo Lu2022-07-16 11:53:42 +0800
commit00501e82c735d4b0928888fffc2049f8ec2d5ae6 (patch)
tree5bbaad20ede8add15c6cae492330bb8e91888e20
parent97441f742e6b63d583607132f1682d050901d716 (diff)
downloademacs-00501e82c735d4b0928888fffc2049f8ec2d5ae6.tar.gz
emacs-00501e82c735d4b0928888fffc2049f8ec2d5ae6.zip
Handle XDND mouse rects synchronously
* src/xterm.c (x_dnd_send_position): Record event X and Y for consumption by the XdndStatus handler. Ignore mouse rects if waiting for status. (x_dnd_send_leave): Clear pending DND event. (handle_one_xevent): When handling XdndStatus, check if the pending event is contained in the new mouse rect.
-rw-r--r--src/xterm.c99
1 files changed, 71 insertions, 28 deletions
diff --git a/src/xterm.c b/src/xterm.c
index c0a01d0d732..94cfe6f010e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1285,6 +1285,15 @@ static Window x_dnd_waiting_for_status_window;
1285 upon receiving an XdndStatus event from said window. */ 1285 upon receiving an XdndStatus event from said window. */
1286static XEvent x_dnd_pending_send_position; 1286static XEvent x_dnd_pending_send_position;
1287 1287
1288/* Whether or not that event corresponds to a button press. */
1289static bool x_dnd_pending_send_position_button;
1290
1291/* The root-window position of that event. */
1292static int x_dnd_pending_send_position_root_x;
1293
1294/* Likewise. */
1295static int x_dnd_pending_send_position_root_y;
1296
1288/* If true, send a drop from `x_dnd_finish_frame' to the pending 1297/* If true, send a drop from `x_dnd_finish_frame' to the pending
1289 status window after receiving all pending XdndStatus events. */ 1298 status window after receiving all pending XdndStatus events. */
1290static bool x_dnd_need_send_drop; 1299static bool x_dnd_need_send_drop;
@@ -4453,22 +4462,6 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
4453 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); 4462 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4454 XEvent msg; 4463 XEvent msg;
4455 4464
4456 if (target == x_dnd_mouse_rect_target
4457 && x_dnd_mouse_rect.width
4458 && x_dnd_mouse_rect.height
4459 /* Ignore the mouse rectangle if we're supposed to be sending a
4460 button press instead. */
4461 && (supported < 5 || !button))
4462 {
4463 if (root_x >= x_dnd_mouse_rect.x
4464 && root_x < (x_dnd_mouse_rect.x
4465 + x_dnd_mouse_rect.width)
4466 && root_y >= x_dnd_mouse_rect.y
4467 && root_y < (x_dnd_mouse_rect.y
4468 + x_dnd_mouse_rect.height))
4469 return;
4470 }
4471
4472 msg.xclient.type = ClientMessage; 4465 msg.xclient.type = ClientMessage;
4473 msg.xclient.message_type = dpyinfo->Xatom_XdndPosition; 4466 msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
4474 msg.xclient.format = 32; 4467 msg.xclient.format = 32;
@@ -4502,9 +4495,30 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
4502 msg.xclient.data.l[4] = action; 4495 msg.xclient.data.l[4] = action;
4503 4496
4504 if (x_dnd_waiting_for_status_window == target) 4497 if (x_dnd_waiting_for_status_window == target)
4505 x_dnd_pending_send_position = msg; 4498 {
4499 x_dnd_pending_send_position = msg;
4500 x_dnd_pending_send_position_button = button;
4501 x_dnd_pending_send_position_root_x = root_x;
4502 x_dnd_pending_send_position_root_y = root_y;
4503 }
4506 else 4504 else
4507 { 4505 {
4506 if (target == x_dnd_mouse_rect_target
4507 && x_dnd_mouse_rect.width
4508 && x_dnd_mouse_rect.height
4509 /* Ignore the mouse rectangle if we're supposed to be sending a
4510 button press instead. */
4511 && (supported < 5 || !button))
4512 {
4513 if (root_x >= x_dnd_mouse_rect.x
4514 && root_x < (x_dnd_mouse_rect.x
4515 + x_dnd_mouse_rect.width)
4516 && root_y >= x_dnd_mouse_rect.y
4517 && root_y < (x_dnd_mouse_rect.y
4518 + x_dnd_mouse_rect.height))
4519 return;
4520 }
4521
4508 x_ignore_errors_for_next_request (dpyinfo); 4522 x_ignore_errors_for_next_request (dpyinfo);
4509 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4523 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4510 x_stop_ignoring_errors (dpyinfo); 4524 x_stop_ignoring_errors (dpyinfo);
@@ -4530,6 +4544,7 @@ x_dnd_send_leave (struct frame *f, Window target)
4530 msg.xclient.data.l[4] = 0; 4544 msg.xclient.data.l[4] = 0;
4531 4545
4532 x_dnd_waiting_for_status_window = None; 4546 x_dnd_waiting_for_status_window = None;
4547 x_dnd_pending_send_position.type = 0;
4533 4548
4534 x_ignore_errors_for_next_request (dpyinfo); 4549 x_ignore_errors_for_next_request (dpyinfo);
4535 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4550 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
@@ -16372,6 +16387,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
16372 { 16387 {
16373 Window target; 16388 Window target;
16374 unsigned long r1, r2; 16389 unsigned long r1, r2;
16390 int root_x, root_y;
16391 bool button;
16375 16392
16376 target = event->xclient.data.l[0]; 16393 target = event->xclient.data.l[0];
16377 16394
@@ -16417,17 +16434,43 @@ handle_one_xevent (struct x_display_info *dpyinfo,
16417 { 16434 {
16418 if (x_dnd_pending_send_position.type != 0) 16435 if (x_dnd_pending_send_position.type != 0)
16419 { 16436 {
16420 x_ignore_errors_for_next_request (dpyinfo); 16437 /* If the last XdndStatus specified a mouse
16421 XSendEvent (dpyinfo->display, target, 16438 rectangle and this event falls inside, don't
16422 False, NoEventMask, 16439 send the event, but clear
16423 &x_dnd_pending_send_position); 16440 x_dnd_waiting_for_status_window instead. */
16424 x_stop_ignoring_errors (dpyinfo); 16441
16425 x_dnd_pending_send_position.type = 0; 16442 root_x = x_dnd_pending_send_position_root_x;
16426 16443 root_y = x_dnd_pending_send_position_root_y;
16427 /* Since we sent another XdndPosition message, we 16444 button = x_dnd_pending_send_position_button;
16428 have to wait for another one in reply, so don't 16445
16429 reset `x_dnd_waiting_for_status_window' 16446 if (target == x_dnd_mouse_rect_target
16430 here. */ 16447 && x_dnd_mouse_rect.width
16448 && x_dnd_mouse_rect.height
16449 /* Ignore the mouse rectangle if we're
16450 supposed to be sending a button press
16451 instead. */
16452 && (x_dnd_last_protocol_version < 5 || !button)
16453 && (root_x >= x_dnd_mouse_rect.x
16454 && root_x < (x_dnd_mouse_rect.x
16455 + x_dnd_mouse_rect.width)
16456 && root_y >= x_dnd_mouse_rect.y
16457 && root_y < (x_dnd_mouse_rect.y
16458 + x_dnd_mouse_rect.height)))
16459 x_dnd_waiting_for_status_window = None;
16460 else
16461 {
16462 x_ignore_errors_for_next_request (dpyinfo);
16463 XSendEvent (dpyinfo->display, target,
16464 False, NoEventMask,
16465 &x_dnd_pending_send_position);
16466 x_stop_ignoring_errors (dpyinfo);
16467 x_dnd_pending_send_position.type = 0;
16468
16469 /* Since we sent another XdndPosition message, we
16470 have to wait for another one in reply, so don't
16471 reset `x_dnd_waiting_for_status_window'
16472 here. */
16473 }
16431 } 16474 }
16432 else 16475 else
16433 x_dnd_waiting_for_status_window = None; 16476 x_dnd_waiting_for_status_window = None;