From 9661c82920cf2b75300266bbd9da9e45b9471173 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 25 May 2022 20:29:38 +0800 Subject: [PATCH] Lower the roundtrip overhead of x-get-atom-name by 50% for common atoms * 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 | 12 +++++--- src/xterm.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++----- src/xterm.h | 1 + 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/src/xselect.c b/src/xselect.c index 3acfcbe94b0..6cb279f9e8d 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -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 (); diff --git a/src/xterm.c b/src/xterm.c index 3ca0c158973..1997cc77dc1 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -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; +} + /* Setting window manager hints. */ diff --git a/src/xterm.h b/src/xterm.h index fba775d96b6..daeb1a4575f 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -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); -- 2.39.2