X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/c4142a830206e97d2d793c2ad73c5d51d9bf1bf0..2bfa3d3e1fb347ba76bddf77f3e288049635821d:/src/gtkutil.c diff --git a/src/gtkutil.c b/src/gtkutil.c index 8f007dad86..fcb4224b14 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1,6 +1,6 @@ /* Functions for creating and updating GTK widgets. -Copyright (C) 2003-2013 Free Software Foundation, Inc. +Copyright (C) 2003-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -78,6 +78,7 @@ along with GNU Emacs. If not, see . */ #define remove_submenu(w) gtk_menu_item_remove_submenu ((w)) #endif +#ifdef HAVE_FREETYPE #if GTK_CHECK_VERSION (3, 2, 0) #define USE_NEW_GTK_FONT_CHOOSER 1 #else @@ -89,6 +90,7 @@ along with GNU Emacs. If not, see . */ #define gtk_font_chooser_set_font(x, y) \ gtk_font_selection_dialog_set_font_name (x, y) #endif +#endif /* HAVE_FREETYPE */ #ifndef HAVE_GTK3 #ifdef USE_GTK_TOOLTIP @@ -219,57 +221,6 @@ xg_display_close (Display *dpy) /*********************************************************************** Utility functions ***********************************************************************/ -/* The next two variables and functions are taken from lwlib. */ -static widget_value *widget_value_free_list; -static int malloc_cpt; - -/* Allocate a widget_value structure, either by taking one from the - widget_value_free_list or by malloc:ing a new one. - - Return a pointer to the allocated structure. */ - -widget_value * -malloc_widget_value (void) -{ - widget_value *wv; - if (widget_value_free_list) - { - wv = widget_value_free_list; - widget_value_free_list = wv->free_list; - wv->free_list = 0; - } - else - { - wv = xmalloc (sizeof *wv); - malloc_cpt++; - } - memset (wv, 0, sizeof (widget_value)); - return wv; -} - -/* This is analogous to free. It frees only what was allocated - by malloc_widget_value, and no substructures. */ - -void -free_widget_value (widget_value *wv) -{ - if (wv->free_list) - emacs_abort (); - - if (malloc_cpt > 25) - { - /* When the number of already allocated cells is too big, - We free it. */ - xfree (wv); - malloc_cpt--; - } - else - { - wv->free_list = widget_value_free_list; - widget_value_free_list = wv; - } -} - /* Create and return the cursor to be used for popup menus and scroll bars on display DPY. */ @@ -547,7 +498,7 @@ get_utf8_string (const char *str) len = strlen (str); if ((min (PTRDIFF_MAX, SIZE_MAX) - len - 1) / 4 < nr_bad) memory_full (SIZE_MAX); - up = utf8_str = xmalloc (len + nr_bad * 4 + 1); + up = utf8_str = xmalloc_atomic (len + nr_bad * 4 + 1); p = (unsigned char *)str; while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read, @@ -1352,8 +1303,8 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) hint_flags = f->output_data.x->hint_flags; hint_flags |= GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE; - size_hints.width_inc = FRAME_COLUMN_WIDTH (f); - size_hints.height_inc = FRAME_LINE_HEIGHT (f); + size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f); + size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f); hint_flags |= GDK_HINT_BASE_SIZE; /* Use one row/col here so base_height/width does not become zero. @@ -1368,8 +1319,8 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) size_hints.base_width = base_width; size_hints.base_height = base_height; - size_hints.min_width = base_width + min_cols * size_hints.width_inc; - size_hints.min_height = base_height + min_rows * size_hints.height_inc; + size_hints.min_width = base_width + min_cols * FRAME_COLUMN_WIDTH (f);; + size_hints.min_height = base_height + min_rows * FRAME_LINE_HEIGHT (f); /* These currently have a one to one mapping with the X values, but I don't think we should rely on that. */ @@ -1686,7 +1637,7 @@ xg_maybe_add_timer (gpointer data) static int xg_dialog_run (struct frame *f, GtkWidget *w) { - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct xg_dialog_data dd; xg_set_screen (w, f); @@ -1714,7 +1665,7 @@ xg_dialog_run (struct frame *f, GtkWidget *w) g_main_loop_run (dd.loop); dd.w = 0; - unbind_to (count, Qnil); + dynwind_end (); return dd.response; } @@ -1744,7 +1695,13 @@ typedef char * (*xg_get_file_func) (GtkWidget *); static char * xg_get_file_name_from_chooser (GtkWidget *w) { - return gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w)); + char *s1, *s2; + s1 = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w)); + if (! s1) + return NULL; + s2 = xstrdup (s1); + g_free (s1); + return s2; } /* Callback called when the "Show hidden files" toggle is pressed. @@ -2104,8 +2061,7 @@ xg_get_font (struct frame *f, const char *default_name) font = Ffont_spec (8, args); pango_font_description_free (desc); - xfree (x_last_font_name); - x_last_font_name = xstrdup (name); + dupstring (&x_last_font_name, name); } #else /* Use old font selector, which just returns the font name. */ @@ -2163,7 +2119,7 @@ make_cl_data (xg_menu_cb_data *cl_data, struct frame *f, GCallback highlight_cb) { if (! cl_data) { - cl_data = xmalloc (sizeof *cl_data); + cl_data = xmalloc_uncollectable (sizeof *cl_data); cl_data->f = f; cl_data->menu_bar_vector = f->menu_bar_vector; cl_data->menu_bar_items_used = f->menu_bar_items_used; @@ -2220,44 +2176,6 @@ unref_cl_data (xg_menu_cb_data *cl_data) } } -/* Function that marks all lisp data during GC. */ - -void -xg_mark_data (void) -{ - xg_list_node *iter; - Lisp_Object rest, frame; - - for (iter = xg_menu_cb_list.next; iter; iter = iter->next) - mark_object (((xg_menu_cb_data *) iter)->menu_bar_vector); - - for (iter = xg_menu_item_cb_list.next; iter; iter = iter->next) - { - xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data *) iter; - - if (! NILP (cb_data->help)) - mark_object (cb_data->help); - } - - FOR_EACH_FRAME (rest, frame) - { - struct frame *f = XFRAME (frame); - - if (FRAME_X_P (f) && FRAME_GTK_OUTER_WIDGET (f)) - { - struct xg_frame_tb_info *tbinfo - = g_object_get_data (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), - TB_INFO_KEY); - if (tbinfo) - { - mark_object (tbinfo->last_tool_bar); - mark_object (tbinfo->style); - } - } - } -} - - /* Callback called when a menu item is destroyed. Used to free data. W is the widget that is being destroyed (not used). CLIENT_DATA points to the xg_menu_item_cb_data associated with the W. */ @@ -2412,9 +2330,12 @@ static int xg_detached_menus; /* Return true if there are detached menus. */ bool -xg_have_tear_offs (void) +xg_have_tear_offs (struct frame *f) { - return xg_detached_menus > 0; + /* If the frame's menubar height is zero, the menu bar is probably + being redirected outside the window to some kind of global menu; + this situation is the moral equivalent of a tear-off. */ + return FRAME_MENUBAR_HEIGHT (f) == 0 || xg_detached_menus > 0; } /* Callback invoked when a detached menu window is removed. Here we @@ -2447,9 +2368,9 @@ tearoff_activate (GtkWidget *widget, gpointer client_data) } #else /* ! HAVE_GTK_TEAROFF_MENU_ITEM_NEW */ bool -xg_have_tear_offs (void) +xg_have_tear_offs (struct frame *f) { - return false; + return FRAME_MENUBAR_HEIGHT (f) == 0; } #endif /* ! HAVE_GTK_TEAROFF_MENU_ITEM_NEW */ @@ -2895,7 +2816,13 @@ xg_update_menubar (GtkWidget *menubar, char *utf8_label = get_utf8_string (val->name); GtkWidget *submenu = gtk_menu_item_get_submenu (witem); + /* GTK menu items don't notice when their labels have been + changed from underneath them, so we have to explicitly + use g_object_notify to tell listeners (e.g., a GMenuModel + bridge that might be loaded) that the item's label has + changed. */ gtk_label_set_text (wlabel, utf8_label); + g_object_notify (G_OBJECT (witem), "label"); #ifdef HAVE_GTK_TEAROFF_MENU_ITEM_NEW /* If this item has a submenu that has been detached, change @@ -2932,6 +2859,7 @@ xg_update_menubar (GtkWidget *menubar, select_cb, deactivate_cb, highlight_cb, 0, 0, 0, 0, cl_data, 0); + gtk_widget_set_name (w, MENU_ITEM_NAME); gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), w, pos); gtk_menu_item_set_submenu (GTK_MENU_ITEM (w), submenu); @@ -2991,6 +2919,7 @@ xg_update_menu_item (widget_value *val, const char *old_label = 0; const char *old_key = 0; xg_menu_item_cb_data *cb_data; + bool label_changed = false; wchild = XG_BIN_CHILD (w); utf8_label = get_utf8_string (val->name); @@ -3035,15 +2964,20 @@ xg_update_menu_item (widget_value *val, } } - if (wkey) old_key = gtk_label_get_label (wkey); if (wlbl) old_label = gtk_label_get_label (wlbl); if (wkey && utf8_key && (! old_key || strcmp (utf8_key, old_key) != 0)) - gtk_label_set_text (wkey, utf8_key); + { + label_changed = true; + gtk_label_set_text (wkey, utf8_key); + } if (! old_label || strcmp (utf8_label, old_label) != 0) - gtk_label_set_text (wlbl, utf8_label); + { + label_changed = true; + gtk_label_set_text (wlbl, utf8_label); + } if (utf8_key) g_free (utf8_key); if (utf8_label) g_free (utf8_label); @@ -3075,6 +3009,9 @@ xg_update_menu_item (widget_value *val, cb_data->select_id = 0; } } + + if (label_changed) /* See comment in xg_update_menubar. */ + g_object_notify (G_OBJECT (w), "label"); } /* Update the toggle menu item W so it corresponds to VAL. */ @@ -3357,11 +3294,6 @@ xg_update_frame_menubar (struct frame *f) gtk_widget_show_all (x->menubar_widget); gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req); - /* If menu bar doesn't know its height yet, cheat a little so the frame - doesn't jump so much when resized later in menubar_map_cb. */ - if (req.height == 0) - req.height = 23; - if (FRAME_MENUBAR_HEIGHT (f) != req.height) { FRAME_MENUBAR_HEIGHT (f) = req.height; @@ -4861,15 +4793,15 @@ update_frame_tool_bar (struct frame *f) { w = gtk_image_new_from_stock (stock_name, icon_size); g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_STOCK_NAME, - (gpointer) xstrdup (stock_name), - (GDestroyNotify) xfree); + (gpointer) g_strdup (stock_name), + (GDestroyNotify) g_free); } else if (icon_name) { w = gtk_image_new_from_icon_name (icon_name, icon_size); g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_ICON_NAME, - (gpointer) xstrdup (icon_name), - (GDestroyNotify) xfree); + (gpointer) g_strdup (icon_name), + (GDestroyNotify) g_free); } else {