]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix drag-and-drop bugs on Lucid build
authorPo Lu <luangruo@yahoo.com>
Tue, 25 Oct 2022 11:50:57 +0000 (19:50 +0800)
committerPo Lu <luangruo@yahoo.com>
Tue, 25 Oct 2022 11:51:08 +0000 (19:51 +0800)
Also, optimize Fx_translate_coordinates to avoid excessive calls
to _XReply.

* lisp/x-dnd.el (x-dnd-get-drop-rectangle): Return empty drop
rectangle if posn-area.
* src/xfns.c (Fx_translate_coordinates): Accept arg
`require_child'.  If not set, allow optimizations based on
cached position data.
* src/xselect.c (x_handle_dnd_message): Use
x_translate_coordinates.
* src/xterm.c (x_translate_coordinates): Export function.
(x_handle_translate_coordinates): New function.
(handle_one_xevent): Fix coding style.
* src/xterm.h: Update prototypes.

lisp/x-dnd.el
src/xfns.c
src/xselect.c
src/xterm.c
src/xterm.h

index ee80e41a22ee4f0ef20146a35756439cfdc85322..058ab99f5cb31ec8f40ff6d719ab6b1262bf7a55 100644 (file)
@@ -675,7 +675,15 @@ with coordinates relative to the root window."
 (defun x-dnd-get-drop-rectangle (window posn)
   "Return the drag-and-drop rectangle at POSN on WINDOW."
   (if (or dnd-scroll-margin
-          (not (windowp window)))
+          (not (windowp window))
+          ;; Drops on the scroll bar aren't allowed, but the mouse
+          ;; rectangle can be set while still on the scroll bar,
+          ;; causing the drag initiator to never send an XdndPosition
+          ;; event that will an XdndStatus message with the accept
+          ;; flag set to be set, even after the mouse enters the
+          ;; window text area.  To prevent that, simply don't generate
+          ;; a mouse rectangle when an area is set.
+          (posn-area posn))
       '(0 0 0 0)
     (let ((window-rectangle (x-dnd-get-window-rectangle window))
           object-rectangle)
index e8732986eb9f5a35b1fe84285dd1bb40403301e3..3ff7a8c28652d36a622547c4d20adbd736e50e42 100644 (file)
@@ -7913,7 +7913,7 @@ Otherwise, the return value is a vector with the following fields:
 
 DEFUN ("x-translate-coordinates", Fx_translate_coordinates,
        Sx_translate_coordinates,
-       1, 5, 0, doc: /* Translate coordinates from FRAME.
+       1, 6, 0, doc: /* Translate coordinates from FRAME.
 Translate the given coordinates SOURCE-X and SOURCE-Y from
 SOURCE-WINDOW's coordinate space to that of DEST-WINDOW, on FRAME.
 
@@ -7929,16 +7929,21 @@ Return a list of (X Y CHILD) if the given coordinates are on the same
 screen, or nil otherwise, where X and Y are the coordinates in
 DEST-WINDOW's coordinate space, and CHILD is the window ID of any
 mapped child in DEST-WINDOW at those coordinates, or nil if there is
-no such window.  */)
+no such window.  If REQUIRE-CHILD is nil, avoid fetching CHILD if it
+would result in an avoidable request to the X server, thereby
+improving performance when the X connection is over a slow network.
+Otherwise, always obtain the mapped child window from the X
+server.  */)
   (Lisp_Object frame, Lisp_Object source_window,
    Lisp_Object dest_window, Lisp_Object source_x,
-   Lisp_Object source_y)
+   Lisp_Object source_y, Lisp_Object require_child)
 {
   struct x_display_info *dpyinfo;
   struct frame *source_frame;
   int dest_x, dest_y;
   Window child_return, src, dest;
   Bool rc;
+  Lisp_Object temp_result;
 
   dpyinfo = check_x_display_info (frame);
   dest_x = 0;
@@ -7956,6 +7961,8 @@ no such window.  */)
       dest_y = XFIXNUM (source_y);
     }
 
+  source_frame = NULL;
+
   if (!NILP (source_window))
     CONS_TO_INTEGER (source_window, Window, src);
   else
@@ -7964,6 +7971,17 @@ no such window.  */)
       src = FRAME_X_WINDOW (source_frame);
     }
 
+  /* If require_child is nil, try to avoid an avoidable roundtrip to
+     the X server.  */
+  if (NILP (require_child) && source_frame)
+    {
+      temp_result
+       = x_handle_translate_coordinates (source_frame, dest_window, dest_x,
+                                         dest_y);
+      if (!NILP (temp_result))
+       return temp_result;
+    }
+
   if (!src)
     src = dpyinfo->root_window;
 
index 498c28af5364deeeaa6776d65e14beade6412fe5..db5c7853e7f43f2abad4c6c7491a2ab8c795e10c 100644 (file)
@@ -2787,7 +2787,6 @@ 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;
@@ -2822,11 +2821,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event,
   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);
+    x_translate_coordinates (f, root_x, root_y, &x, &y);
 
   bufp->kind = DRAG_N_DROP_EVENT;
   bufp->frame_or_window = frame;
index 205c948c4617f2a0cf2aabc5f1bf12114fe1802c..b061383a2ea338e573b2964bb20874ea8c71e53f 100644 (file)
@@ -1143,7 +1143,6 @@ static Window x_get_window_below (Display *, Window, int, int, int *, int *);
 #ifndef USE_TOOLKIT_SCROLL_BARS
 static void x_scroll_bar_redraw (struct scroll_bar *);
 #endif
-static void x_translate_coordinates (struct frame *, int, int, int *, int *);
 
 /* Global state maintained during a drag-and-drop operation.  */
 
@@ -13658,7 +13657,7 @@ x_compute_root_window_offset (struct frame *f, int root_x, int root_y,
    many cases while handling events, which would otherwise result in
    slowdowns over slow network connections.  */
 
-static void
+void
 x_translate_coordinates (struct frame *f, int root_x, int root_y,
                         int *x_out, int *y_out)
 {
@@ -13731,6 +13730,31 @@ x_translate_coordinates_to_root (struct frame *f, int x, int y,
     }
 }
 
+/* Do x-translate-coordinates, but try to avoid a roundtrip to the X
+   server at the cost of not returning `child', which most callers
+   have no reason to use.  */
+
+Lisp_Object
+x_handle_translate_coordinates (struct frame *f, Lisp_Object dest_window,
+                               int source_x, int source_y)
+{
+  if (NILP (dest_window))
+    {
+      /* We are translating coordinates from a frame to the root
+        window.  Avoid a roundtrip if possible by using cached
+        coordinates.  */
+
+      if (!FRAME_X_OUTPUT (f)->window_offset_certain_p)
+       return Qnil;
+
+      return list3 (make_fixnum (source_x + FRAME_X_OUTPUT (f)->root_x),
+                   make_fixnum (source_y + FRAME_X_OUTPUT (f)->root_y),
+                   Qnil);
+    }
+
+  return Qnil;
+}
+
 /* The same, but for an XIDeviceEvent.  */
 
 #ifdef HAVE_XINPUT2
@@ -20826,7 +20850,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                                              event->xbutton.time);
                      }
                    else if (x_dnd_last_seen_window != None
-                       && x_dnd_last_protocol_version != -1)
+                            && x_dnd_last_protocol_version != -1)
                      {
                        x_dnd_pending_finish_target = x_dnd_last_seen_toplevel;
                        x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version;
index 2967d105ea2659e1c53a796f74db6c40b83f79de..537cabc9577cc4dbba8c7e61bf7ce3c934d30e5f 100644 (file)
@@ -1695,8 +1695,12 @@ extern void x_xr_apply_ext_clip (struct frame *, GC);
 extern void x_xr_reset_ext_clip (struct frame *);
 #endif
 
+extern void x_translate_coordinates (struct frame *, int, int, int *, int *);
 extern void x_translate_coordinates_to_root (struct frame *, int, int,
                                             int *, int *);
+extern Lisp_Object x_handle_translate_coordinates (struct frame *, Lisp_Object,
+                                                  int, int);
+
 extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *,
                             int *, int *, int *, unsigned int *);