]> git.eshelyaron.com Git - emacs.git/commitdiff
Use coordinates provided by DND messages if available
authorPo Lu <luangruo@yahoo.com>
Tue, 14 Jun 2022 01:41:59 +0000 (09:41 +0800)
committerPo Lu <luangruo@yahoo.com>
Tue, 14 Jun 2022 01:41:59 +0000 (09:41 +0800)
This avoids an extra sync, which matters when dropping onto
Emacs running over a slow connection.

* src/xselect.c (x_handle_dnd_message): New args
`root_window_coords', `root_x' and `root_y'.
* src/xterm.c (x_coords_from_dnd_message): New function.
(handle_one_xevent): Pass root window coordinates to
x_handle_dnd_message.
* src/xterm.h: Update prototypes.

src/xselect.c
src/xterm.c
src/xterm.h

index 490a008dfcbc44fc008f1d2dff322133d7322686..96c1e9830fbbcf1eb181f7977c1683c368dac48e 100644 (file)
@@ -2522,7 +2522,8 @@ FRAME is on.  If FRAME is nil, the selected frame is used.  */)
 
 bool
 x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
-                      struct x_display_info *dpyinfo, struct input_event *bufp)
+                      struct x_display_info *dpyinfo, struct input_event *bufp,
+                     bool root_window_coords, int root_x, int root_y)
 {
   Lisp_Object vec;
   Lisp_Object frame;
@@ -2532,6 +2533,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
   unsigned char *data = (unsigned char *) event->data.b;
   int idata[5];
   ptrdiff_t i;
+  Window child_return;
 
   for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i)
     if (dpyinfo->x_dnd_atoms[i] == event->message_type) break;
@@ -2563,7 +2565,15 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
                                         event->format,
                                         size));
 
-  x_relative_mouse_position (f, &x, &y);
+  if (!root_window_coords)
+    x_relative_mouse_position (f, &x, &y);
+  else
+    XTranslateCoordinates (dpyinfo->display,
+                          dpyinfo->root_window,
+                          FRAME_X_WINDOW (f),
+                          root_x, root_y,
+                          &x, &y, &child_return);
+
   bufp->kind = DRAG_N_DROP_EVENT;
   bufp->frame_or_window = frame;
   bufp->timestamp = CurrentTime;
index d9dd29ca128eef01e07a834f165d2e17f5c566a8..d79871e0210b019fe938ceb44a221a318e79235c 100644 (file)
@@ -15762,6 +15762,31 @@ x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data)
 }
 #endif
 
+/* Extract the root window coordinates from the client message EVENT
+   if it is a message that we already understand.  Return false if the
+   event was not understood.  */
+static bool
+x_coords_from_dnd_message (struct x_display_info *dpyinfo,
+                          XEvent *event, int *x_out, int *y_out)
+{
+  if (event->type != ClientMessage)
+    return false;
+
+  if (event->xclient.message_type == dpyinfo->Xatom_XdndPosition)
+    {
+      if (event->xclient.format != 32)
+       return false;
+
+      *x_out = (((unsigned long) event->xclient.data.l[2]) >> 16
+               & 0xffff);
+      *y_out = (event->xclient.data.l[2] & 0xffff);
+
+      return true;
+    }
+
+  return false;
+}
+
 /* Handles the XEvent EVENT on display DPYINFO.
 
    *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
@@ -15804,6 +15829,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
   GdkEvent *copy = NULL;
   GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
 #endif
+  int dx, dy;
   USE_SAFE_ALLOCA;
 
   *finish = X_EVENT_NORMAL;
@@ -15835,6 +15861,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
     {
     case ClientMessage:
       {
+       int rc;
+
        if (x_dnd_in_progress
            && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo
            && event->xclient.message_type == dpyinfo->Xatom_XdndStatus)
@@ -16211,7 +16239,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
        f = any;
        if (!f)
          goto OTHER;
-       if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie))
+
+       /* These values are always used initialized, but GCC doesn't
+          know that.  */
+       dx = 0;
+       dy = 0;
+
+       rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event,
+                                       &dx, &dy);
+
+       if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie,
+                                 rc, dx, dy))
          *finish = X_EVENT_DROP;
       }
       break;
index 25c2453ee7852c5f417d302a92fba9d33bf69b9a..82b4308041a05661ad12cff628b40e5fef4043f0 100644 (file)
@@ -1540,7 +1540,8 @@ extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom);
 extern bool x_handle_dnd_message (struct frame *,
                                  const XClientMessageEvent *,
                                  struct x_display_info *,
-                                 struct input_event *);
+                                 struct input_event *,
+                                 bool, int, int);
 extern int x_check_property_data (Lisp_Object);
 extern void x_fill_property_data (Display *,
                                   Lisp_Object,