]> git.eshelyaron.com Git - emacs.git/commitdiff
Handle XDND mouse rects synchronously
authorPo Lu <luangruo@yahoo.com>
Sat, 16 Jul 2022 03:53:42 +0000 (11:53 +0800)
committerPo Lu <luangruo@yahoo.com>
Sat, 16 Jul 2022 03:53:42 +0000 (11:53 +0800)
* 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.

src/xterm.c

index c0a01d0d73205269577783e128bd8a52dc130533..94cfe6f010e8dd83ba02df34bdb22b2de59e37f1 100644 (file)
@@ -1285,6 +1285,15 @@ static Window x_dnd_waiting_for_status_window;
    upon receiving an XdndStatus event from said window.  */
 static XEvent x_dnd_pending_send_position;
 
+/* Whether or not that event corresponds to a button press.  */
+static bool x_dnd_pending_send_position_button;
+
+/* The root-window position of that event.  */
+static int x_dnd_pending_send_position_root_x;
+
+/* Likewise.  */
+static int x_dnd_pending_send_position_root_y;
+
 /* If true, send a drop from `x_dnd_finish_frame' to the pending
    status window after receiving all pending XdndStatus events.  */
 static bool x_dnd_need_send_drop;
@@ -4453,22 +4462,6 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   XEvent msg;
 
-  if (target == x_dnd_mouse_rect_target
-      && x_dnd_mouse_rect.width
-      && x_dnd_mouse_rect.height
-      /* Ignore the mouse rectangle if we're supposed to be sending a
-        button press instead.  */
-      && (supported < 5 || !button))
-    {
-      if (root_x >= x_dnd_mouse_rect.x
-         && root_x < (x_dnd_mouse_rect.x
-                      + x_dnd_mouse_rect.width)
-         && root_y >= x_dnd_mouse_rect.y
-         && root_y < (x_dnd_mouse_rect.y
-                      + x_dnd_mouse_rect.height))
-       return;
-    }
-
   msg.xclient.type = ClientMessage;
   msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
   msg.xclient.format = 32;
@@ -4502,9 +4495,30 @@ x_dnd_send_position (struct frame *f, Window target, int supported,
     msg.xclient.data.l[4] = action;
 
   if (x_dnd_waiting_for_status_window == target)
-    x_dnd_pending_send_position = msg;
+    {
+      x_dnd_pending_send_position = msg;
+      x_dnd_pending_send_position_button = button;
+      x_dnd_pending_send_position_root_x = root_x;
+      x_dnd_pending_send_position_root_y = root_y;
+    }
   else
     {
+      if (target == x_dnd_mouse_rect_target
+         && x_dnd_mouse_rect.width
+         && x_dnd_mouse_rect.height
+         /* Ignore the mouse rectangle if we're supposed to be sending a
+            button press instead.  */
+         && (supported < 5 || !button))
+       {
+         if (root_x >= x_dnd_mouse_rect.x
+             && root_x < (x_dnd_mouse_rect.x
+                          + x_dnd_mouse_rect.width)
+             && root_y >= x_dnd_mouse_rect.y
+             && root_y < (x_dnd_mouse_rect.y
+                          + x_dnd_mouse_rect.height))
+           return;
+       }
+
       x_ignore_errors_for_next_request (dpyinfo);
       XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
       x_stop_ignoring_errors (dpyinfo);
@@ -4530,6 +4544,7 @@ x_dnd_send_leave (struct frame *f, Window target)
   msg.xclient.data.l[4] = 0;
 
   x_dnd_waiting_for_status_window = None;
+  x_dnd_pending_send_position.type = 0;
 
   x_ignore_errors_for_next_request (dpyinfo);
   XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
@@ -16372,6 +16387,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
          {
            Window target;
            unsigned long r1, r2;
+           int root_x, root_y;
+           bool button;
 
            target = event->xclient.data.l[0];
 
@@ -16417,17 +16434,43 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              {
                if (x_dnd_pending_send_position.type != 0)
                  {
-                   x_ignore_errors_for_next_request (dpyinfo);
-                   XSendEvent (dpyinfo->display, target,
-                               False, NoEventMask,
-                               &x_dnd_pending_send_position);
-                   x_stop_ignoring_errors (dpyinfo);
-                   x_dnd_pending_send_position.type = 0;
-
-                   /* Since we sent another XdndPosition message, we
-                      have to wait for another one in reply, so don't
-                      reset `x_dnd_waiting_for_status_window'
-                      here.  */
+                   /* If the last XdndStatus specified a mouse
+                      rectangle and this event falls inside, don't
+                      send the event, but clear
+                      x_dnd_waiting_for_status_window instead.  */
+
+                   root_x = x_dnd_pending_send_position_root_x;
+                   root_y = x_dnd_pending_send_position_root_y;
+                   button = x_dnd_pending_send_position_button;
+
+                   if (target == x_dnd_mouse_rect_target
+                       && x_dnd_mouse_rect.width
+                       && x_dnd_mouse_rect.height
+                       /* Ignore the mouse rectangle if we're
+                          supposed to be sending a button press
+                          instead.  */
+                       && (x_dnd_last_protocol_version < 5 || !button)
+                       && (root_x >= x_dnd_mouse_rect.x
+                           && root_x < (x_dnd_mouse_rect.x
+                                        + x_dnd_mouse_rect.width)
+                           && root_y >= x_dnd_mouse_rect.y
+                           && root_y < (x_dnd_mouse_rect.y
+                                        + x_dnd_mouse_rect.height)))
+                     x_dnd_waiting_for_status_window = None;
+                   else
+                     {
+                       x_ignore_errors_for_next_request (dpyinfo);
+                       XSendEvent (dpyinfo->display, target,
+                                   False, NoEventMask,
+                                   &x_dnd_pending_send_position);
+                       x_stop_ignoring_errors (dpyinfo);
+                       x_dnd_pending_send_position.type = 0;
+
+                       /* Since we sent another XdndPosition message, we
+                          have to wait for another one in reply, so don't
+                          reset `x_dnd_waiting_for_status_window'
+                          here.  */
+                     }
                  }
                else
                  x_dnd_waiting_for_status_window = None;