diff --git a/src/xdisp.c b/src/xdisp.c index 466bb1534ae..b7333dc1ee6 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -26312,13 +26312,17 @@ display_menu_bar (struct window *w) it.first_visible_x = 0; it.last_visible_x = FRAME_PIXEL_WIDTH (f); #elif defined (HAVE_X_WINDOWS) /* X without toolkit. */ - struct window *menu_w; + struct window *menu_window; + + menu_window = NULL; + if (FRAME_WINDOW_P (f)) { /* Menu bar lines are displayed in the desired matrix of the dummy window menu_bar_window. */ - menu_w = XWINDOW (f->menu_bar_window); - init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows, + menu_window = XWINDOW (f->menu_bar_window); + init_iterator (&it, menu_window, -1, -1, + menu_window->desired_matrix->rows, MENU_FACE_ID); it.first_visible_x = 0; it.last_visible_x = FRAME_PIXEL_WIDTH (f); @@ -26379,11 +26383,16 @@ display_menu_bar (struct window *w) #if defined (HAVE_X_WINDOWS) && !defined (USE_X_TOOLKIT) && !defined (USE_GTK) /* With the non-toolkit version, modify the menu bar window height accordingly. */ - if (FRAME_WINDOW_P (it.f)) + if (FRAME_WINDOW_P (it.f) && menu_window) { - struct glyph_row *row = it.glyph_row; - int delta_height = ((row->y + row->height) - - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_w)); + struct glyph_row *row; + int delta_height; + + row = it.glyph_row; + delta_height + = ((row->y + row->height) + - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window)); + if (delta_height != 0) { FRAME_MENU_BAR_HEIGHT (it.f) += delta_height; diff --git a/src/xfns.c b/src/xfns.c index 36b51a30112..df805d66db9 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7079,8 +7079,8 @@ that mouse buttons are being held down, such as immediately after a /* Catch errors since interning lots of targets can potentially generate a BadAlloc error. */ x_catch_errors (FRAME_X_DISPLAY (f)); - XInternAtoms (FRAME_X_DISPLAY (f), target_names, - ntargets, False, target_atoms); + x_intern_atoms (FRAME_DISPLAY_INFO (f), target_names, + ntargets, target_atoms); x_check_errors (FRAME_X_DISPLAY (f), "Failed to intern target atoms: %s"); x_uncatch_errors_after_check (); @@ -7484,7 +7484,7 @@ silently ignored. */) elsize = element_format == 32 ? sizeof (long) : element_format >> 3; data = xnmalloc (nelements, elsize); - x_fill_property_data (FRAME_X_DISPLAY (f), value, data, nelements, + x_fill_property_data (FRAME_DISPLAY_INFO (f), value, data, nelements, element_format); } else diff --git a/src/xselect.c b/src/xselect.c index c47093dfad0..120a5a163e2 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -2216,7 +2216,12 @@ static void lisp_data_to_selection_data (struct x_display_info *dpyinfo, Lisp_Object obj, struct selection_data *cs) { - Lisp_Object type = Qnil; + Lisp_Object type; + char **name_buffer; + + USE_SAFE_ALLOCA; + + type = Qnil; eassert (cs != NULL); @@ -2321,8 +2326,19 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo, x_atoms = data; cs->format = 32; cs->size = size; - for (i = 0; i < size; i++) - x_atoms[i] = symbol_to_x_atom (dpyinfo, AREF (obj, i)); + + if (size == 1) + x_atoms[0] = symbol_to_x_atom (dpyinfo, AREF (obj, i)); + else + { + SAFE_NALLOCA (name_buffer, sizeof *x_atoms, size); + + for (i = 0; i < size; i++) + name_buffer[i] = SSDATA (SYMBOL_NAME (AREF (obj, i))); + + x_intern_atoms (dpyinfo, name_buffer, size, + x_atoms); + } } else /* This vector is an INTEGER set, or something like it */ @@ -2364,6 +2380,8 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo, signal_error (/* Qselection_error */ "Unrecognized selection data", obj); cs->type = symbol_to_x_atom (dpyinfo, type); + + SAFE_FREE (); } static Lisp_Object @@ -2891,8 +2909,8 @@ x_check_property_data (Lisp_Object data) XClientMessageEvent). */ void -x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, - int nelements_max, int format) +x_fill_property_data (struct x_display_info *dpyinfo, Lisp_Object data, + void *ret, int nelements_max, int format) { unsigned long val; unsigned long *d32 = (unsigned long *) ret; @@ -2927,7 +2945,7 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, else if (STRINGP (o)) { block_input (); - val = XInternAtom (dpy, SSDATA (o), False); + val = x_intern_cached_atom (dpyinfo, SSDATA (o), false); unblock_input (); } else @@ -3215,7 +3233,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, memset (event.xclient.data.l, 0, sizeof (event.xclient.data.l)); /* event.xclient.data can hold 20 chars, 10 shorts, or 5 longs. */ - x_fill_property_data (dpyinfo->display, values, event.xclient.data.b, + x_fill_property_data (dpyinfo, values, event.xclient.data.b, 5 * 32 / event.xclient.format, event.xclient.format); diff --git a/src/xterm.c b/src/xterm.c index 43dc7c18b9d..c775f199857 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -28875,6 +28875,53 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom, return value; } +/* Intern an array of atoms, and do so quickly, avoiding extraneous + roundtrips to the X server. + + Avoid sending atoms that have already been found to the X server. + This cannot do anything that will end up triggering garbage + collection. */ + +void +x_intern_atoms (struct x_display_info *dpyinfo, char **names, int count, + Atom *atoms_return) +{ + int i, j, indices[256]; + char *new_names[256]; + Atom results[256], candidate; + + if (count > 256) + /* Atoms array too big to inspect reasonably, just send it to the + server and back. */ + XInternAtoms (dpyinfo->display, new_names, count, False, atoms_return); + else + { + for (i = 0, j = 0; i < count; ++i) + { + candidate = x_intern_cached_atom (dpyinfo, names[i], + true); + + if (candidate) + atoms_return[i] = candidate; + else + { + indices[j++] = i; + new_names[j - 1] = names[i]; + } + } + + if (!j) + return; + + /* Now, get the results back from the X server. */ + XInternAtoms (dpyinfo->display, new_names, j, False, + results); + + for (i = 0; i < j; ++i) + atoms_return[indices[i]] = results[i]; + } +} + #ifndef USE_GTK /* Set up XEmbed for F, and change its save set to handle the parent diff --git a/src/xterm.h b/src/xterm.h index 86763dc6e04..0b227cbdc09 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1723,6 +1723,11 @@ extern Lisp_Object x_handle_translate_coordinates (struct frame *, Lisp_Object, extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *, int *, int *, int *, unsigned int *); +extern Atom x_intern_cached_atom (struct x_display_info *, const char *, + bool); +extern void x_intern_atoms (struct x_display_info *, char **, int, Atom *); +extern char *x_get_atom_name (struct x_display_info *, Atom, bool *) + ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE; #ifdef HAVE_GTK3 extern void x_scroll_bar_configure (GdkEvent *); @@ -1815,11 +1820,8 @@ extern bool x_handle_dnd_message (struct frame *, struct input_event *, bool, int, int); extern int x_check_property_data (Lisp_Object); -extern void x_fill_property_data (Display *, - Lisp_Object, - void *, - int, - int); +extern void x_fill_property_data (struct x_display_info *, Lisp_Object, + void *, int, int); extern Lisp_Object x_property_data_to_lisp (struct frame *, const unsigned char *, Atom, @@ -1832,10 +1834,6 @@ extern Lisp_Object x_timestamp_for_selection (struct x_display_info *, Lisp_Object); extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Time); -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 *) - ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE; extern void mark_xselect (void);