From: Chong Yidong Date: Sat, 1 Jan 2011 06:02:36 +0000 (-0500) Subject: Reduce GTK tool-bar switching delay by avoiding selective show/hide of widgets. X-Git-Tag: emacs-pretest-24.0.90~104^2~618^2~1322^2~278^2~38 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=3afff00e6f188170ef5eca34d435e7a0730df3fc;p=emacs.git Reduce GTK tool-bar switching delay by avoiding selective show/hide of widgets. * src/gtkutil.c (xg_get_tool_bar_widgets): Use NULL for a missing image or label in the container. (xg_make_tool_item): Replace VERT_ONLY arg with HORIZ, TEXT_IMAGE. (xg_show_toolbar_item): Function deleted. (xg_tool_item_stale_p): New function. (update_frame_tool_bar): Calculate tool-bar style once per call. Instead of hiding text labels, omit them. Don't use xg_show_toolbar_item; create new GtkToolItems from scratch if necessary, instead of trying to re-use them. This avoids an annoying animation when changing tool-bars. --- diff --git a/src/ChangeLog b/src/ChangeLog index e0201b2ab1a..d03b16a7092 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2011-01-01 Chong Yidong + + * gtkutil.c (xg_get_tool_bar_widgets): Use NULL for a missing + image or label in the container. + (xg_make_tool_item): Replace VERT_ONLY arg with HORIZ, TEXT_IMAGE. + (xg_show_toolbar_item): Function deleted. + (xg_tool_item_stale_p): New function. + (update_frame_tool_bar): Calculate tool-bar style once per call. + Instead of hiding text labels, omit them. Don't use + xg_show_toolbar_item; create new GtkToolItems from scratch if + necessary, instead of trying to re-use them. This avoids an + annoying animation when changing tool-bars. + 2010-12-31 Jan Djärv * nsfns.m (ns_set_name_as_filename): Always use buffer name for diff --git a/src/gtkutil.c b/src/gtkutil.c index a6cfbf002b3..fb003749493 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -3664,7 +3664,8 @@ xg_get_tool_bar_widgets (GtkWidget *vb, GtkWidget **wimage) { GList *clist = gtk_container_get_children (GTK_CONTAINER (vb)); GtkWidget *c1 = (GtkWidget *) clist->data; - GtkWidget *c2 = (GtkWidget *) clist->next->data; + GtkWidget *c2 = clist->next ? (GtkWidget *) clist->next->data : NULL; + *wimage = GTK_IS_IMAGE (c1) ? c1 : c2; g_list_free (clist); return GTK_IS_LABEL (c1) ? c1 : c2; @@ -4039,28 +4040,17 @@ xg_make_tool_item (FRAME_PTR f, GtkWidget *wimage, GtkWidget **wbutton, const char *label, - int i, - int vert_only) + int i, int horiz, int text_image) { GtkToolItem *ti = gtk_tool_item_new (); - Lisp_Object style = Ftool_bar_get_system_style (); - int both_horiz = EQ (style, Qboth_horiz); - int text_image = EQ (style, Qtext_image_horiz); - - GtkWidget *vb = both_horiz || text_image - ? gtk_hbox_new (FALSE, 0) : gtk_vbox_new (FALSE, 0); + GtkWidget *vb = horiz ? gtk_hbox_new (FALSE, 0) : gtk_vbox_new (FALSE, 0); GtkWidget *wb = gtk_button_new (); GtkWidget *weventbox = gtk_event_box_new (); - /* We are not letting Gtk+ alter display on this, we only keep it here - so we can get it later in xg_show_toolbar_item. */ - gtk_tool_item_set_is_important (ti, !vert_only); - - if (wimage && ! text_image) + if (wimage && !text_image) gtk_box_pack_start (GTK_BOX (vb), wimage, TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (vb), gtk_label_new (label), TRUE, TRUE, 0); - + if (label) + gtk_box_pack_start (GTK_BOX (vb), gtk_label_new (label), TRUE, TRUE, 0); if (wimage && text_image) gtk_box_pack_start (GTK_BOX (vb), wimage, TRUE, TRUE, 0); @@ -4121,58 +4111,49 @@ xg_make_tool_item (FRAME_PTR f, return ti; } -static void -xg_show_toolbar_item (GtkToolItem *ti) +static int +xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name, + const char *icon_name, const struct image *img, + const char *label, int horiz) { - Lisp_Object style = Ftool_bar_get_system_style (); - int both_horiz = EQ (style, Qboth_horiz); - int text_image = EQ (style, Qtext_image_horiz); - - int horiz = both_horiz || text_image; - int vert_only = ! gtk_tool_item_get_is_important (ti); - int show_label = ! EQ (style, Qimage) && ! (vert_only && horiz); - int show_image = ! EQ (style, Qtext); - - GtkWidget *weventbox = XG_BIN_CHILD (ti); - GtkWidget *wbutton = XG_BIN_CHILD (weventbox); - GtkWidget *vb = XG_BIN_CHILD (wbutton); + gpointer old; GtkWidget *wimage; + GtkWidget *vb = XG_BIN_CHILD (wbutton); GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage); - GtkWidget *new_box = NULL; - - if (GTK_IS_VBOX (vb) && horiz) - new_box = gtk_hbox_new (FALSE, 0); - else if (GTK_IS_HBOX (vb) && !horiz && show_label && show_image) - new_box = gtk_vbox_new (FALSE, 0); - if (!new_box && horiz) - gtk_box_reorder_child (GTK_BOX (vb), wlbl, text_image ? 0 : 1); - else if (new_box) + /* Check if the tool icon matches. */ + if (stock_name) { - g_object_ref (G_OBJECT (wimage)); - g_object_ref (G_OBJECT (wlbl)); - gtk_container_remove (GTK_CONTAINER (vb), wimage); - gtk_container_remove (GTK_CONTAINER (vb), wlbl); - gtk_widget_destroy (GTK_WIDGET (vb)); - if (! text_image) - gtk_box_pack_start (GTK_BOX (new_box), wimage, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (new_box), wlbl, TRUE, TRUE, 0); - if (text_image) - gtk_box_pack_start (GTK_BOX (new_box), wimage, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (wbutton), new_box); - g_object_unref (G_OBJECT (wimage)); - g_object_unref (G_OBJECT (wlbl)); - vb = new_box; + old = g_object_get_data (G_OBJECT (wimage), + XG_TOOL_BAR_STOCK_NAME); + if (!old || strcmp (old, stock_name)) + return 1; } + else if (icon_name) + { + old = g_object_get_data (G_OBJECT (wimage), + XG_TOOL_BAR_ICON_NAME); + if (!old || strcmp (old, icon_name)) + return 1; + } + else + { + Pixmap old_img + = (Pixmap) g_object_get_data (G_OBJECT (wimage), + XG_TOOL_BAR_IMAGE_DATA); + if (old_img != img->pixmap) + return 1; + } + + /* Check button configuration and label. */ + if ((horiz ? GTK_IS_VBOX (vb) : GTK_IS_HBOX (vb)) + || (label ? (wlbl == NULL) : (wlbl != NULL))) + return 1; - if (show_label) gtk_widget_show (wlbl); - else gtk_widget_hide (wlbl); - if (show_image) gtk_widget_show (wimage); - else gtk_widget_hide (wimage); - gtk_widget_show (GTK_WIDGET (weventbox)); - gtk_widget_show (GTK_WIDGET (vb)); - gtk_widget_show (GTK_WIDGET (wbutton)); - gtk_widget_show (GTK_WIDGET (ti)); + /* Ensure label is correct. */ + if (label) + gtk_label_set_text (GTK_LABEL (wlbl), label); + return 0; } static int @@ -4225,7 +4206,7 @@ xg_update_tool_bar_sizes (FRAME_PTR f) void update_frame_tool_bar (FRAME_PTR f) { - int i; + int i, j; struct x_output *x = f->output_data.x; int hmargin = 0, vmargin = 0; GtkToolbar *wtoolbar; @@ -4233,6 +4214,9 @@ update_frame_tool_bar (FRAME_PTR f) GtkTextDirection dir; int pack_tool_bar = x->handlebox_widget == NULL; + Lisp_Object style; + int text_image, horiz; + if (! FRAME_GTK_WIDGET (f)) return; @@ -4268,7 +4252,11 @@ update_frame_tool_bar (FRAME_PTR f) wtoolbar = GTK_TOOLBAR (x->toolbar_widget); dir = gtk_widget_get_direction (GTK_WIDGET (wtoolbar)); - for (i = 0; i < f->n_tool_bar_items; ++i) + style = Ftool_bar_get_system_style (); + text_image = EQ (style, Qtext_image_horiz); + horiz = EQ (style, Qboth_horiz) || text_image; + + for (i = j = 0; i < f->n_tool_bar_items; ++i) { int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); @@ -4284,11 +4272,14 @@ update_frame_tool_bar (FRAME_PTR f) Lisp_Object rtl; GtkWidget *wbutton = NULL; Lisp_Object specified_file; - const char *label = (STRINGP (PROP (TOOL_BAR_ITEM_LABEL)) - ? SSDATA (PROP (TOOL_BAR_ITEM_LABEL)) : ""); int vert_only = ! NILP (PROP (TOOL_BAR_ITEM_VERT_ONLY)); + const char *label + = (EQ (style, Qimage) || (vert_only && horiz)) ? NULL + : STRINGP (PROP (TOOL_BAR_ITEM_LABEL)) + ? SSDATA (PROP (TOOL_BAR_ITEM_LABEL)) + : ""; - ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), i); + ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), j); /* If this is a separator, use a gtk separator item. */ if (EQ (PROP (TOOL_BAR_ITEM_TYPE), Qt)) @@ -4299,9 +4290,9 @@ update_frame_tool_bar (FRAME_PTR f) gtk_container_remove (GTK_CONTAINER (wtoolbar), GTK_WIDGET (ti)); ti = gtk_separator_tool_item_new (); - gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, i); + gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j); } - gtk_widget_show (GTK_WIDGET (ti)); + j++; continue; } @@ -4313,14 +4304,15 @@ update_frame_tool_bar (FRAME_PTR f) ti = NULL; } - if (ti) - wbutton = XG_BIN_CHILD (XG_BIN_CHILD (ti)); + if (ti) wbutton = XG_BIN_CHILD (XG_BIN_CHILD (ti)); /* Ignore invalid image specifications. */ image = PROP (TOOL_BAR_ITEM_IMAGES); if (!valid_image_p (image)) { - if (wbutton) gtk_widget_hide (wbutton); + if (ti) + gtk_container_remove (GTK_CONTAINER (wtoolbar), + GTK_WIDGET (ti)); continue; } @@ -4356,16 +4348,13 @@ update_frame_tool_bar (FRAME_PTR f) if (stock_name == NULL && icon_name == NULL) { - /* No stock image, or stock item not known. Try regular image. */ - - /* If image is a vector, choose the image according to the + /* No stock image, or stock item not known. Try regular + image. If image is a vector, choose it according to the button state. */ if (dir == GTK_TEXT_DIR_RTL && !NILP (rtl = PROP (TOOL_BAR_ITEM_RTL_IMAGE)) && STRINGP (rtl)) - { - image = find_rtl_image (f, image, rtl); - } + image = find_rtl_image (f, image, rtl); if (VECTORP (image)) { @@ -4391,21 +4380,31 @@ update_frame_tool_bar (FRAME_PTR f) if (img->load_failed_p || img->pixmap == None) { if (ti) - gtk_widget_hide_all (GTK_WIDGET (ti)); - else - { - /* Insert an empty (non-image) button */ - ti = xg_make_tool_item (f, NULL, NULL, "", i, 0); - gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, i); - } + gtk_container_remove (GTK_CONTAINER (wtoolbar), + GTK_WIDGET (ti)); continue; } } + /* If there is an existing widget, check if it's stale; if so, + remove it and make a new tool item from scratch. */ + if (ti && xg_tool_item_stale_p (wbutton, stock_name, icon_name, + img, label, horiz)) + { + gtk_container_remove (GTK_CONTAINER (wtoolbar), + GTK_WIDGET (ti)); + ti = NULL; + } + if (ti == NULL) { GtkWidget *w; - if (stock_name) + + /* Save the image so we can see if an update is needed the + next time we call xg_tool_item_match_p. */ + if (EQ (style, Qtext)) + w = NULL; + else if (stock_name) { w = gtk_image_new_from_stock (stock_name, icon_size); g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_STOCK_NAME, @@ -4422,93 +4421,34 @@ update_frame_tool_bar (FRAME_PTR f) else { w = xg_get_image_for_pixmap (f, img, x->widget, NULL); - /* Save the image so we can see if an update is needed when - this function is called again. */ g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA, (gpointer)img->pixmap); } - gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin); - ti = xg_make_tool_item (f, w, &wbutton, label, i, vert_only); - gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, i); - gtk_widget_set_sensitive (wbutton, enabled_p); - } - else - { - GtkWidget *vb = XG_BIN_CHILD (wbutton); - GtkWidget *wimage; - GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage); - - Pixmap old_img = (Pixmap) g_object_get_data (G_OBJECT (wimage), - XG_TOOL_BAR_IMAGE_DATA); - gpointer old_stock_name = g_object_get_data (G_OBJECT (wimage), - XG_TOOL_BAR_STOCK_NAME); - gpointer old_icon_name = g_object_get_data (G_OBJECT (wimage), - XG_TOOL_BAR_ICON_NAME); - gtk_label_set_text (GTK_LABEL (wlbl), label); - gtk_tool_item_set_is_important (ti, !vert_only); - if (stock_name && - (! old_stock_name || strcmp (old_stock_name, stock_name) != 0)) - { - gtk_image_set_from_stock (GTK_IMAGE (wimage), - stock_name, icon_size); - g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME, - (gpointer) xstrdup (stock_name), - (GDestroyNotify) xfree); - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, - NULL); - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME, - NULL); - } - else if (icon_name && - (! old_icon_name || strcmp (old_icon_name, icon_name) != 0)) - { - gtk_image_set_from_icon_name (GTK_IMAGE (wimage), - icon_name, icon_size); - g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME, - (gpointer) xstrdup (icon_name), - (GDestroyNotify) xfree); - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, - NULL); - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME, - NULL); - } - else if (img && old_img != img->pixmap) - { - (void) xg_get_image_for_pixmap (f, img, x->widget, - GTK_IMAGE (wimage)); - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, - (gpointer)img->pixmap); - - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME, - NULL); - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_ICON_NAME, - NULL); - } - - gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin); - - gtk_widget_set_sensitive (wbutton, enabled_p); + if (w) gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin); + ti = xg_make_tool_item (f, w, &wbutton, label, i, horiz, text_image); + gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, j); } - xg_show_toolbar_item (ti); #undef PROP + + gtk_widget_set_sensitive (wbutton, enabled_p); + j++; } - /* Remove buttons not longer needed. We just hide them so they - can be reused later on. */ + /* Remove buttons not longer needed. */ do { - ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), i++); - if (ti) gtk_widget_hide_all (GTK_WIDGET (ti)); + ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), j++); + if (ti) + gtk_container_remove (GTK_CONTAINER (wtoolbar), GTK_WIDGET (ti)); } while (ti != NULL); if (f->n_tool_bar_items != 0) { if (pack_tool_bar) xg_pack_tool_bar (f, f->tool_bar_position); - gtk_widget_show (x->toolbar_widget); - gtk_widget_show (x->handlebox_widget); + gtk_widget_show_all (GTK_WIDGET (x->handlebox_widget)); if (xg_update_tool_bar_sizes (f)) xg_height_or_width_changed (f); }