emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 4ef1e4daf5: Speed up receiving drops over slow connections


From: Po Lu
Subject: master 4ef1e4daf5: Speed up receiving drops over slow connections
Date: Sat, 2 Jul 2022 21:43:34 -0400 (EDT)

branch: master
commit 4ef1e4daf5e3569fed748f4487058d68a4c20ae6
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Speed up receiving drops over slow connections
    
    * lisp/x-dnd.el (x-dnd-debug-errors): New variable.
    (x-dnd-handle-drag-n-drop-event): Bind
    `x-fast-protocol-requests' to t if that is off.
    
    * src/xfns.c (Fx_change_window_property):
    (Fx_delete_window_property):
    * src/xselect.c (Fx_send_client_message, x_send_client_event):
    Don't sync to check for errors if fast protocol requests are
    enabled.
    
    * src/xterm.c (x_catch_errors_for_lisp, x_check_errors_for_lisp)
    (x_uncatch_errors_for_lisp): New functions.
    (syms_of_xterm): New variable `x-fast-protocol-requests'.
    * src/xterm.h: Update prototypes.
---
 lisp/x-dnd.el |  9 ++++++++
 src/xfns.c    | 71 ++++++++++++++++++++++++++++++++++++-----------------------
 src/xselect.c | 11 ++++++---
 src/xterm.c   | 39 ++++++++++++++++++++++++++++++++
 src/xterm.h   |  5 +++++
 5 files changed, 104 insertions(+), 31 deletions(-)

diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index 8bea333012..f9e6b3198e 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -151,6 +151,12 @@ data types in this list."
 
 ;; Internal variables
 
+(defvar x-dnd-debug-errors nil
+  "Whether or not to signal protocol errors during drag-and-drop.
+This is useful for debugging errors in the DND code, but makes
+drag-and-drop much slower over network connections with high
+latency.")
+
 (defvar x-dnd-current-state nil
   "The current state for a drop.
 This is an alist with one entry for each display.  The value for each display
@@ -425,11 +431,14 @@ nil if not."
          (select-frame frame)
          (funcall handler window action data))))))
 
+(defvar x-fast-protocol-requests)
+
 (defun x-dnd-handle-drag-n-drop-event (event)
   "Receive drag and drop events (X client messages).
 Currently XDND, Motif and old KDE 1.x protocols are recognized."
   (interactive "e")
   (let* ((client-message (car (cdr (cdr event))))
+         (x-fast-protocol-requests (not x-dnd-debug-errors))
         (window (posn-window (event-start event))))
     (if (eq (and (consp client-message)
                  (car client-message))
diff --git a/src/xfns.c b/src/xfns.c
index adb4fb58bc..ea2b1c0b3d 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -7339,18 +7339,23 @@ If VALUE is a string and FORMAT is 32, then the format 
of VALUE is
 system-specific.  VALUE must contain unsigned integer data in native
 endian-ness in multiples of the size of the C type 'long': the low 32
 bits of each such number are used as the value of each element of the
-property.  */)
+property.
+
+Wait for the request to complete and signal any error, unless
+`x-fast-protocol-requests' is non-nil, in which case errors will be
+silently ignored.  */)
   (Lisp_Object prop, Lisp_Object value, Lisp_Object frame,
    Lisp_Object type, Lisp_Object format, Lisp_Object outer_p,
    Lisp_Object window_id)
 {
-  struct frame *f = decode_window_system_frame (frame);
+  struct frame *f;
   Atom prop_atom;
   Atom target_type = XA_STRING;
   int element_format = 8;
   unsigned char *data;
   int nelements;
   Window target_window;
+  struct x_display_info *dpyinfo;
 #ifdef USE_XCB
   bool intern_prop;
   bool intern_target;
@@ -7361,6 +7366,9 @@ property.  */)
   bool rc;
 #endif
 
+  f = decode_window_system_frame (frame);
+  dpyinfo = FRAME_DISPLAY_INFO (f);
+
   CHECK_STRING (prop);
 
   if (! NILP (format))
@@ -7412,7 +7420,7 @@ property.  */)
     {
       CONS_TO_INTEGER (window_id, Window, target_window);
       if (! target_window)
-        target_window = FRAME_DISPLAY_INFO (f)->root_window;
+        target_window = dpyinfo->root_window;
     }
   else
     {
@@ -7424,47 +7432,47 @@ property.  */)
 
   block_input ();
 #ifndef USE_XCB
-  prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
-                                   SSDATA (prop), false);
+  prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop),
+                                   false);
   if (! NILP (type))
     {
       CHECK_STRING (type);
-      target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
-                                         SSDATA (type), false);
+      target_type = x_intern_cached_atom (dpyinfo, SSDATA (type),
+                                         false);
     }
 #else
   rc = true;
   intern_target = true;
   intern_prop = true;
 
-  prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
-                                   SSDATA (prop), true);
+  prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop),
+                                   true);
 
   if (prop_atom != None)
     intern_prop = false;
   else
     prop_atom_cookie
-      = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection,
+      = xcb_intern_atom (dpyinfo->xcb_connection,
                         0, SBYTES (prop), SSDATA (prop));
 
   if (!NILP (type))
     {
       CHECK_STRING (type);
 
-      target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
-                                         SSDATA (type), true);
+      target_type = x_intern_cached_atom (dpyinfo, SSDATA (type),
+                                         true);
 
       if (target_type)
        intern_target = false;
       else
        target_type_cookie
-         = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection,
+         = xcb_intern_atom (dpyinfo->xcb_connection,
                             0, SBYTES (type), SSDATA (type));
     }
 
   if (intern_prop)
     {
-      reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection,
+      reply = xcb_intern_atom_reply (dpyinfo->xcb_connection,
                                     prop_atom_cookie, &generic_error);
 
       if (reply)
@@ -7481,7 +7489,7 @@ property.  */)
 
   if (!NILP (type) && intern_target)
     {
-      reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection,
+      reply = xcb_intern_atom_reply (dpyinfo->xcb_connection,
                                     target_type_cookie, &generic_error);
 
       if (reply)
@@ -7500,15 +7508,18 @@ property.  */)
     error ("Failed to intern type or property atom");
 #endif
 
-  x_catch_errors (FRAME_X_DISPLAY (f));
-  XChangeProperty (FRAME_X_DISPLAY (f), target_window,
-                  prop_atom, target_type, element_format, PropModeReplace,
-                  data, nelements);
+  x_catch_errors_for_lisp (dpyinfo);
 
-  if (CONSP (value)) xfree (data);
-  x_check_errors (FRAME_X_DISPLAY (f),
-                 "Couldn't change window property: %s");
-  x_uncatch_errors_after_check ();
+  XChangeProperty (dpyinfo->display, target_window,
+                  prop_atom, target_type, element_format,
+                  PropModeReplace, data, nelements);
+
+  if (CONSP (value))
+    xfree (data);
+
+  x_check_errors_for_lisp (dpyinfo,
+                          "Couldn't change window property: %s");
+  x_uncatch_errors_for_lisp (dpyinfo);
 
   unblock_input ();
   return value;
@@ -7525,7 +7536,11 @@ If WINDOW-ID is non-nil, remove property from that 
window instead
  across X displays or screens on the same display, so FRAME provides
  context for the window ID.
 
-Value is PROP.  */)
+Value is PROP.
+
+Wait for the request to complete and signal any error, unless
+`x-fast-protocol-requests' is non-nil, in which case errors will be
+silently ignored.  */)
   (Lisp_Object prop, Lisp_Object frame, Lisp_Object window_id)
 {
   struct frame *f = decode_window_system_frame (frame);
@@ -7545,11 +7560,11 @@ Value is PROP.  */)
   prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f),
                                    SSDATA (prop), false);
 
-  x_catch_errors (FRAME_X_DISPLAY (f));
+  x_catch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
   XDeleteProperty (FRAME_X_DISPLAY (f), target_window, prop_atom);
-  x_check_errors (FRAME_X_DISPLAY (f),
-                 "Couldn't delete window property: %s");
-  x_uncatch_errors_after_check ();
+  x_check_errors_for_lisp (FRAME_DISPLAY_INFO (f),
+                          "Couldn't delete window property: %s");
+  x_uncatch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
 
   unblock_input ();
   return prop;
diff --git a/src/xselect.c b/src/xselect.c
index 41fa837c5a..2521dc171c 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -2749,7 +2749,11 @@ to send.  If a value is a string, it is converted to an 
Atom and the value of
 the Atom is sent.  If a value is a cons, it is converted to a 32 bit number
 with the high 16 bits from the car and the lower 16 bit from the cdr.
 If more values than fits into the event is given, the excessive values
-are ignored.  */)
+are ignored.
+
+Wait for the event to be sent and signal any error, unless
+`x-fast-protocol-requests' is non-nil, in which case errors will be
+silently ignored.  */)
   (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
    Lisp_Object message_type, Lisp_Object format, Lisp_Object values)
 {
@@ -2830,7 +2834,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object 
dest, Lisp_Object from,
      the destination window.  But if we are sending to the root window,
      there is no such client.  Then we set the event mask to 0xffffff.  The
      event then goes to clients selecting for events on the root window.  */
-  x_catch_errors (dpyinfo->display);
+  x_catch_errors_for_lisp (dpyinfo);
   {
     bool propagate = !to_root;
     long mask = to_root ? 0xffffff : 0;
@@ -2838,7 +2842,8 @@ x_send_client_event (Lisp_Object display, Lisp_Object 
dest, Lisp_Object from,
     XSendEvent (dpyinfo->display, wdest, propagate, mask, &event);
     XFlush (dpyinfo->display);
   }
-  x_uncatch_errors ();
+  x_check_errors_for_lisp (dpyinfo, "Failed to send client event: %s");
+  x_uncatch_errors_for_lisp (dpyinfo);
   unblock_input ();
 }
 
diff --git a/src/xterm.c b/src/xterm.c
index 7ab22f256f..4353b173ca 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -27836,6 +27836,36 @@ mark_xterm (void)
 #endif
 }
 
+/* Error handling functions for Lisp functions that expose X protocol
+   requests.  They are mostly like `x_catch_errors' and friends, but
+   respect `x-fast-protocol-requests'.  */
+
+void
+x_catch_errors_for_lisp (struct x_display_info *dpyinfo)
+{
+  if (!x_fast_protocol_requests)
+    x_catch_errors (dpyinfo->display);
+  else
+    x_ignore_errors_for_next_request (dpyinfo);
+}
+
+void
+x_check_errors_for_lisp (struct x_display_info *dpyinfo,
+                        const char *format)
+{
+  if (!x_fast_protocol_requests)
+    x_check_errors (dpyinfo->display, format);
+}
+
+void
+x_uncatch_errors_for_lisp (struct x_display_info *dpyinfo)
+{
+  if (!x_fast_protocol_requests)
+    x_uncatch_errors ();
+  else
+    x_stop_ignoring_errors (dpyinfo);
+}
+
 void
 syms_of_xterm (void)
 {
@@ -28141,4 +28171,13 @@ When nil, do not use the primary selection and 
synthetic mouse clicks
 to emulate the drag-and-drop of `STRING', `UTF8_STRING',
 `COMPOUND_TEXT' or `TEXT'.  */);
   x_dnd_use_unsupported_drop = true;
+
+  DEFVAR_BOOL ("x-fast-protocol-requests", x_fast_protocol_requests,
+    doc: /* Whether or not X protocol-related functions should wait for errors.
+When this is nil, functions such as `x-delete-window-property',
+`x-change-window-property' and `x-send-client-message' will wait for a
+reply from the X server, and signal any errors that occurred while
+executing the protocol request.  Otherwise, errors will be silently
+ignored without waiting, which is generally faster.  */);
+  x_fast_protocol_requests = false;
 }
diff --git a/src/xterm.h b/src/xterm.h
index 7c09073d76..26d6e4b3d0 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1445,6 +1445,11 @@ extern bool x_text_icon (struct frame *, const char *);
 extern void x_catch_errors (Display *);
 extern void x_catch_errors_with_handler (Display *, x_special_error_handler,
                                         void *);
+extern void x_catch_errors_for_lisp (struct x_display_info *);
+extern void x_uncatch_errors_for_lisp (struct x_display_info *);
+extern void x_check_errors_for_lisp (struct x_display_info *,
+                                    const char *)
+  ATTRIBUTE_FORMAT_PRINTF (2, 0);
 extern void x_check_errors (Display *, const char *)
   ATTRIBUTE_FORMAT_PRINTF (2, 0);
 extern bool x_had_errors_p (Display *);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]