summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-05-25 20:29:38 +0800
committerPo Lu <luangruo@yahoo.com>2022-05-25 20:29:47 +0800
commit9661c82920cf2b75300266bbd9da9e45b9471173 (patch)
treeb11cd1caa073e5ff886170c41b85b1072642e17e
parentce79fe451d845c09e5502071f9af9845eb930885 (diff)
downloademacs-9661c82920cf2b75300266bbd9da9e45b9471173.tar.gz
emacs-9661c82920cf2b75300266bbd9da9e45b9471173.tar.bz2
emacs-9661c82920cf2b75300266bbd9da9e45b9471173.zip
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.
-rw-r--r--src/xselect.c12
-rw-r--r--src/xterm.c81
-rw-r--r--src/xterm.h1
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);