Commit 3afff00e authored by Chong Yidong's avatar Chong Yidong
Browse files

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.
parent 8d68c659
2011-01-01 Chong Yidong <cyd@stupidchicken.com>
* 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 <jan.h.d@swipnet.se>
 
* nsfns.m (ns_set_name_as_filename): Always use buffer name for
......
......@@ -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);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment