gtkwindow: Have a separate "titlebar" pointer for decorations we create ourselves

This cleans up the code a bit.

https://bugzilla.gnome.org/show_bug.cgi?id=706529
This commit is contained in:
Jasper St. Pierre 2013-08-21 14:59:44 -04:00
parent cae2b697ef
commit a95cabd787

View File

@ -148,6 +148,7 @@ struct _GtkWindowPrivate
gint title_height; gint title_height;
GtkWidget *title_box; GtkWidget *title_box;
GtkWidget *titlebar;
GtkWidget *titlebar_icon; GtkWidget *titlebar_icon;
GtkWidget *titlebar_min_button; GtkWidget *titlebar_min_button;
GtkWidget *titlebar_max_button; GtkWidget *titlebar_max_button;
@ -1805,8 +1806,8 @@ gtk_window_set_title (GtkWindow *window,
if (gtk_widget_get_realized (widget)) if (gtk_widget_get_realized (widget))
gdk_window_set_title (gtk_widget_get_window (widget), priv->title); gdk_window_set_title (gtk_widget_get_window (widget), priv->title);
if (GTK_IS_HEADER_BAR (priv->title_box) && !priv->custom_title) if (priv->titlebar != NULL)
gtk_header_bar_set_title (GTK_HEADER_BAR (priv->title_box), priv->title); gtk_header_bar_set_title (GTK_HEADER_BAR (priv->titlebar), priv->title);
g_object_notify (G_OBJECT (window), "title"); g_object_notify (G_OBJECT (window), "title");
} }
@ -3463,6 +3464,7 @@ unset_titlebar (GtkWindow *window)
{ {
gtk_widget_unparent (priv->title_box); gtk_widget_unparent (priv->title_box);
priv->title_box = NULL; priv->title_box = NULL;
priv->titlebar = NULL;
priv->titlebar_icon = NULL; priv->titlebar_icon = NULL;
priv->titlebar_min_button = NULL; priv->titlebar_min_button = NULL;
priv->titlebar_max_button = NULL; priv->titlebar_max_button = NULL;
@ -5050,6 +5052,10 @@ update_window_buttons (GtkWindow *window)
GtkWindowPrivate *priv = window->priv; GtkWindowPrivate *priv = window->priv;
gboolean maximized; gboolean maximized;
GtkTextDirection direction; GtkTextDirection direction;
gchar *layout_desc;
gchar **tokens, **t;
gint i, j;
GdkPixbuf *icon = NULL;
if (priv->title_box == NULL) if (priv->title_box == NULL)
return; return;
@ -5068,147 +5074,171 @@ update_window_buttons (GtkWindow *window)
gtk_widget_show (priv->title_box); gtk_widget_show (priv->title_box);
} }
if (priv->custom_title) if (priv->titlebar == NULL)
return; return;
if (priv->decorated && if (priv->titlebar_icon)
priv->client_decorated)
{ {
gchar *layout_desc; icon = gtk_image_get_pixbuf (GTK_IMAGE (priv->titlebar_icon));
gchar **tokens, **t; if (icon)
gint i, j; g_object_ref (icon);
GdkPixbuf *icon = NULL; gtk_widget_destroy (priv->titlebar_icon);
priv->titlebar_icon = NULL;
if (priv->titlebar_icon)
{
icon = gtk_image_get_pixbuf (GTK_IMAGE (priv->titlebar_icon));
if (icon)
g_object_ref (icon);
gtk_widget_destroy (priv->titlebar_icon);
priv->titlebar_icon = NULL;
}
if (priv->titlebar_min_button)
{
gtk_widget_destroy (priv->titlebar_min_button);
priv->titlebar_min_button = NULL;
}
if (priv->titlebar_max_button)
{
gtk_widget_destroy (priv->titlebar_max_button);
priv->titlebar_max_button = NULL;
}
if (priv->titlebar_close_button)
{
gtk_widget_destroy (priv->titlebar_close_button);
priv->titlebar_close_button = NULL;
}
gtk_widget_style_get (GTK_WIDGET (window),
"decoration-button-layout", &layout_desc,
NULL);
tokens = g_strsplit (layout_desc, ":", 2);
if (tokens)
{
for (i = 0; i < 2; i++)
{
GtkWidget *box;
if (tokens[i] == NULL)
continue;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_show (box);
gtk_widget_set_margin_bottom (box, 6);
if ((direction == GTK_TEXT_DIR_LTR && i == 0) ||
(direction == GTK_TEXT_DIR_RTL && i == 1))
gtk_style_context_add_class (gtk_widget_get_style_context (box), "left");
else
gtk_style_context_add_class (gtk_widget_get_style_context (box), "right");
if (i == 0)
gtk_header_bar_pack_start (GTK_HEADER_BAR (priv->title_box), box);
else
gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), box);
t = g_strsplit (tokens[i], ",", -1);
for (j = 0; t[j]; j++)
{
GtkWidget *button = NULL;
GtkWidget *image = NULL;
if (strcmp (t[j], "icon") == 0)
{
button = gtk_image_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
gtk_widget_set_size_request (button, 20, 20);
gtk_widget_show (button);
if (icon != NULL)
{
gtk_image_set_from_pixbuf (GTK_IMAGE (button), icon);
g_object_unref (icon);
}
else
gtk_widget_hide (button);
priv->titlebar_icon = button;
}
else if (strcmp (t[j], "minimize") == 0 &&
priv->gdk_type_hint == GDK_WINDOW_TYPE_HINT_NORMAL)
{
button = gtk_button_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
image = gtk_image_new_from_icon_name ("window-minimize-symbolic", GTK_ICON_SIZE_MENU);
g_object_set (image, "use-fallback", TRUE, NULL);
gtk_container_add (GTK_CONTAINER (button), image);
gtk_widget_set_can_focus (button, FALSE);
gtk_widget_show_all (button);
g_signal_connect (button, "clicked",
G_CALLBACK (gtk_window_titlebar_min_clicked), window);
priv->titlebar_min_button = button;
}
else if (strcmp (t[j], "maximize") == 0 &&
priv->resizable &&
priv->gdk_type_hint == GDK_WINDOW_TYPE_HINT_NORMAL)
{
const gchar *icon_name;
icon_name = maximized ? "window-restore-symbolic" : "window-maximize-symbolic";
button = gtk_button_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
g_object_set (image, "use-fallback", TRUE, NULL);
gtk_container_add (GTK_CONTAINER (button), image);
gtk_widget_set_can_focus (button, FALSE);
gtk_widget_show_all (button);
g_signal_connect (button, "clicked",
G_CALLBACK (gtk_window_titlebar_max_clicked), window);
priv->titlebar_max_button = button;
}
else if (strcmp (t[j], "close") == 0 &&
priv->deletable &&
priv->gdk_type_hint == GDK_WINDOW_TYPE_HINT_NORMAL)
{
button = gtk_button_new ();
image = gtk_image_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_MENU);
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
g_object_set (image, "use-fallback", TRUE, NULL);
gtk_container_add (GTK_CONTAINER (button), image);
gtk_widget_set_can_focus (button, FALSE);
gtk_widget_show_all (button);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_window_close), window);
priv->titlebar_close_button = button;
}
if (button)
gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
}
g_strfreev (t);
}
g_strfreev (tokens);
}
g_free (layout_desc);
} }
if (priv->titlebar_min_button)
{
gtk_widget_destroy (priv->titlebar_min_button);
priv->titlebar_min_button = NULL;
}
if (priv->titlebar_max_button)
{
gtk_widget_destroy (priv->titlebar_max_button);
priv->titlebar_max_button = NULL;
}
if (priv->titlebar_close_button)
{
gtk_widget_destroy (priv->titlebar_close_button);
priv->titlebar_close_button = NULL;
}
gtk_widget_style_get (GTK_WIDGET (window),
"decoration-button-layout", &layout_desc,
NULL);
tokens = g_strsplit (layout_desc, ":", 2);
if (tokens)
{
for (i = 0; i < 2; i++)
{
GtkWidget *box;
if (tokens[i] == NULL)
continue;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_show (box);
gtk_widget_set_margin_bottom (box, 6);
if ((direction == GTK_TEXT_DIR_LTR && i == 0) ||
(direction == GTK_TEXT_DIR_RTL && i == 1))
gtk_style_context_add_class (gtk_widget_get_style_context (box), "left");
else
gtk_style_context_add_class (gtk_widget_get_style_context (box), "right");
if (i == 0)
gtk_header_bar_pack_start (GTK_HEADER_BAR (priv->title_box), box);
else
gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), box);
t = g_strsplit (tokens[i], ",", -1);
for (j = 0; t[j]; j++)
{
GtkWidget *button = NULL;
GtkWidget *image = NULL;
if (strcmp (t[j], "icon") == 0)
{
button = gtk_image_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
gtk_widget_set_size_request (button, 20, 20);
gtk_widget_show (button);
if (icon != NULL)
{
gtk_image_set_from_pixbuf (GTK_IMAGE (button), icon);
g_object_unref (icon);
}
else
gtk_widget_hide (button);
priv->titlebar_icon = button;
}
else if (strcmp (t[j], "minimize") == 0 &&
priv->gdk_type_hint == GDK_WINDOW_TYPE_HINT_NORMAL)
{
button = gtk_button_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
image = gtk_image_new_from_icon_name ("window-minimize-symbolic", GTK_ICON_SIZE_MENU);
g_object_set (image, "use-fallback", TRUE, NULL);
gtk_container_add (GTK_CONTAINER (button), image);
gtk_widget_set_can_focus (button, FALSE);
gtk_widget_show_all (button);
g_signal_connect (button, "clicked",
G_CALLBACK (gtk_window_titlebar_min_clicked), window);
priv->titlebar_min_button = button;
}
else if (strcmp (t[j], "maximize") == 0 &&
priv->resizable &&
priv->gdk_type_hint == GDK_WINDOW_TYPE_HINT_NORMAL)
{
const gchar *icon_name;
icon_name = maximized ? "window-restore-symbolic" : "window-maximize-symbolic";
button = gtk_button_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
g_object_set (image, "use-fallback", TRUE, NULL);
gtk_container_add (GTK_CONTAINER (button), image);
gtk_widget_set_can_focus (button, FALSE);
gtk_widget_show_all (button);
g_signal_connect (button, "clicked",
G_CALLBACK (gtk_window_titlebar_max_clicked), window);
priv->titlebar_max_button = button;
}
else if (strcmp (t[j], "close") == 0 &&
priv->deletable &&
priv->gdk_type_hint == GDK_WINDOW_TYPE_HINT_NORMAL)
{
button = gtk_button_new ();
image = gtk_image_new_from_icon_name ("window-close-symbolic", GTK_ICON_SIZE_MENU);
gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton");
g_object_set (image, "use-fallback", TRUE, NULL);
gtk_container_add (GTK_CONTAINER (button), image);
gtk_widget_set_can_focus (button, FALSE);
gtk_widget_show_all (button);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gtk_window_close), window);
priv->titlebar_close_button = button;
}
if (button)
gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
}
g_strfreev (t);
}
g_strfreev (tokens);
}
g_free (layout_desc);
}
static GtkWidget *
create_titlebar (GtkWindow *window)
{
GtkWindowPrivate *priv = window->priv;
GtkWidget *label;
GtkWidget *titlebar;
GtkStyleContext *context;
gchar *title;
titlebar = gtk_header_bar_new ();
g_object_set (titlebar,
"spacing", 0,
"hpadding", 0,
"vpadding", 0,
NULL);
context = gtk_widget_get_style_context (titlebar);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TITLEBAR);
title = g_markup_printf_escaped ("<b>%s</b>",
priv->title ? priv->title : get_default_title ());
label = gtk_label_new (title);
g_free (title);
g_object_set (label,
"use-markup", TRUE,
"ellipsize", PANGO_ELLIPSIZE_END,
"margin", 6,
NULL);
gtk_header_bar_set_custom_title (GTK_HEADER_BAR (titlebar), label);
return titlebar;
} }
static void static void
@ -5216,9 +5246,6 @@ create_decoration (GtkWidget *widget)
{ {
GtkWindow *window = GTK_WINDOW (widget); GtkWindow *window = GTK_WINDOW (widget);
GtkWindowPrivate *priv = window->priv; GtkWindowPrivate *priv = window->priv;
GtkStyleContext *context;
gchar *title;
GtkWidget *label;
/* Client decorations already created */ /* Client decorations already created */
if (priv->client_decorated) if (priv->client_decorated)
@ -5254,29 +5281,10 @@ create_decoration (GtkWidget *widget)
if (priv->title_box == NULL) if (priv->title_box == NULL)
{ {
priv->title_box = gtk_header_bar_new (); priv->titlebar = create_titlebar (window);
g_object_set (priv->title_box, gtk_widget_set_parent (priv->titlebar, widget);
"spacing", 0, gtk_widget_show_all (priv->titlebar);
"hpadding", 0, priv->title_box = priv->titlebar;
"vpadding", 0,
NULL);
context = gtk_widget_get_style_context (priv->title_box);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TITLEBAR);
gtk_widget_set_parent (priv->title_box, widget);
title = g_markup_printf_escaped ("<b>%s</b>",
priv->title ? priv->title : get_default_title ());
label = gtk_label_new (title);
g_free (title);
g_object_set (label,
"use-markup", TRUE,
"ellipsize", PANGO_ELLIPSIZE_END,
"margin", 6,
NULL);
gtk_header_bar_set_custom_title (GTK_HEADER_BAR (priv->title_box), label);
gtk_widget_show_all (priv->title_box);
} }
update_window_buttons (window); update_window_buttons (window);
@ -7364,7 +7372,7 @@ gtk_window_forall (GtkContainer *container,
(* callback) (child, callback_data); (* callback) (child, callback_data);
if (priv->title_box != NULL && if (priv->title_box != NULL &&
(priv->custom_title || include_internals)) (priv->titlebar == NULL || include_internals))
(* callback) (priv->title_box, callback_data); (* callback) (priv->title_box, callback_data);
} }