]> git.eshelyaron.com Git - emacs.git/commitdiff
Lower the roundtrip overhead of x-get-atom-name by 50% for common atoms
authorPo Lu <luangruo@yahoo.com>
Wed, 25 May 2022 12:29:38 +0000 (20:29 +0800)
committerPo Lu <luangruo@yahoo.com>
Wed, 25 May 2022 12:29:47 +0000 (20:29 +0800)
* src/xselect.c (Fx_get_atom_name):
* src/xterm.c (x_dnd_begin_drag_and_drop): Use that instead.  Don't
sync to handle errors if using `x_get_atom_name' resulted in no
protocol request being made.
(x_get_atom_name): New function.
* src/xterm.h: Update prototypes.

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

index 3acfcbe94b03f3883ea456629506076bc1b751b3..6cb279f9e8da011aada6e82e6e1a2cc6d41a94d9 100644 (file)
@@ -2458,21 +2458,25 @@ If the value is 0 or the atom is not known, return the empty string.  */)
   char empty[] = "";
   Lisp_Object ret = Qnil;
   Display *dpy = FRAME_X_DISPLAY (f);
+  struct x_display_info *dpyinfo;
   Atom atom;
-  bool had_errors_p;
+  bool had_errors_p, need_sync;
+
+  dpyinfo = FRAME_DISPLAY_INFO (f);
 
   CONS_TO_INTEGER (value, Atom, atom);
 
   block_input ();
   x_catch_errors (dpy);
-  name = atom ? XGetAtomName (dpy, atom) : empty;
-  had_errors_p = x_had_errors_p (dpy);
+  name = (atom ? x_get_atom_name (dpyinfo, atom,
+                                 &need_sync) : empty);
+  had_errors_p = need_sync && x_had_errors_p (dpy);
   x_uncatch_errors_after_check ();
 
   if (!had_errors_p)
     ret = build_string (name);
 
-  if (atom && name) XFree (name);
+  if (atom && name) xfree (name);
   if (NILP (ret)) ret = empty_unibyte_string;
 
   unblock_input ();
index 3ca0c15897364a8b7ccb0ddeed170c0263743052..1997cc77dc1038ade5203e360f79d45611f20997 100644 (file)
@@ -10238,7 +10238,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
   XTextProperty prop;
   xm_drop_start_message dmsg;
   Lisp_Object frame_object, x, y, frame, local_value;
-  bool signals_were_pending;
+  bool signals_were_pending, need_sync;
 #ifdef HAVE_XKB
   XkbStateRec keyboard_state;
 #endif
@@ -10800,14 +10800,20 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
     {
       block_input ();
       x_catch_errors (FRAME_X_DISPLAY (f));
-      atom_name = XGetAtomName (FRAME_X_DISPLAY (f),
-                               x_dnd_action);
-      x_uncatch_errors ();
+      atom_name = x_get_atom_name (FRAME_DISPLAY_INFO (f),
+                                  x_dnd_action, &need_sync);
+
+      if (need_sync)
+       x_uncatch_errors ();
+      else
+       /* No protocol request actually happened, so avoid the extra
+          sync by calling x_uncatch_errors_after_check instead.  */
+       x_uncatch_errors_after_check ();
 
       if (atom_name)
        {
          action = intern (atom_name);
-         XFree (atom_name);
+         xfree (atom_name);
        }
       else
        action = Qnil;
@@ -23599,8 +23605,10 @@ x_destroy_window (struct frame *f)
 }
 
 /* Intern NAME in DPYINFO, but check to see if the atom was already
-   interned, and use that instead.  If PREDEFINED_ONLY, return None if
-   the atom was not already interned at connection setup.  */
+   interned when the X connection was opened, and use that instead.
+
+   If PREDEFINED_ONLY, return None if the atom was not interned during
+   connection setup or is predefined.  */
 Atom
 x_intern_cached_atom (struct x_display_info *dpyinfo,
                      const char *name, bool predefined_only)
@@ -23666,6 +23674,65 @@ x_intern_cached_atom (struct x_display_info *dpyinfo,
   return XInternAtom (dpyinfo->display, name, False);
 }
 
+/* Whether or not a request to the X server happened is placed in
+   NEED_SYNC.  */
+char *
+x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
+                bool *need_sync)
+{
+  char *dpyinfo_pointer, *name, *value;
+  int i;
+  Atom ref_atom;
+
+  dpyinfo_pointer = (char *) dpyinfo;
+  value = NULL;
+  *need_sync = false;
+
+  switch (atom)
+    {
+    case XA_PRIMARY:
+      return xstrdup ("PRIMARY");
+
+    case XA_SECONDARY:
+      return xstrdup ("SECONDARY");
+
+    case XA_INTEGER:
+      return xstrdup ("INTEGER");
+
+    case XA_ATOM:
+      return xstrdup ("ATOM");
+
+    case XA_CARDINAL:
+      return xstrdup ("CARDINAL");
+
+    case XA_WINDOW:
+      return xstrdup ("WINDOW");
+
+    default:
+      for (i = 0; i < ARRAYELTS (x_atom_refs); ++i)
+       {
+         ref_atom = *(Atom *) (dpyinfo_pointer
+                               + x_atom_refs[i].offset);
+
+         if (atom == ref_atom)
+           return xstrdup (x_atom_refs[i].name);
+       }
+
+      name = XGetAtomName (dpyinfo->display, atom);
+      *need_sync = true;
+
+      if (name)
+       {
+         value = xstrdup (name);
+         XFree (name);
+       }
+
+      break;
+    }
+
+  return value;
+}
+
 \f
 /* Setting window manager hints.  */
 
index fba775d96b6c06a03ab6d05358097a557ffe4920..daeb1a4575f6933cdefd775c8d3bfec66b16cde7 100644 (file)
@@ -1538,6 +1538,7 @@ extern void x_set_pending_dnd_time (Time);
 extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object);
 extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
                                  bool);
+extern char *x_get_atom_name (struct x_display_info *, Atom, bool *);
 
 #ifdef USE_GTK
 extern bool xg_set_icon (struct frame *, Lisp_Object);