diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c index dd0be62f33..9c3d1ba36f 100644 --- a/gtk/gtkapplicationwindow.c +++ b/gtk/gtkapplicationwindow.c @@ -297,12 +297,10 @@ gtk_application_window_update_shell_shows_app_menu (GtkApplicationWindow *window { gboolean shown_by_shell; gboolean shown_by_titlebar; - GtkWidget *titlebar; g_object_get (settings, "gtk-shell-shows-app-menu", &shown_by_shell, NULL); - titlebar = _gtk_window_get_titlebar (GTK_WINDOW (window)); - shown_by_titlebar = GTK_IS_HEADER_BAR (titlebar) && gtk_header_bar_get_show_fallback_app_menu (GTK_HEADER_BAR (titlebar)); + shown_by_titlebar = _gtk_window_titlebar_shows_app_menu (GTK_WINDOW (window)); if (shown_by_shell || shown_by_titlebar) { @@ -632,13 +630,12 @@ gtk_application_window_real_realize (GtkWidget *widget) g_signal_connect (settings, "notify::gtk-shell-shows-menubar", G_CALLBACK (gtk_application_window_shell_shows_menubar_changed), window); + GTK_WIDGET_CLASS (gtk_application_window_parent_class)->realize (widget); + gtk_application_window_update_shell_shows_app_menu (window, settings); gtk_application_window_update_shell_shows_menubar (window, settings); gtk_application_window_update_menubar (window); - GTK_WIDGET_CLASS (gtk_application_window_parent_class) - ->realize (widget); - #ifdef GDK_WINDOWING_X11 { GdkWindow *gdkwindow; @@ -679,8 +676,7 @@ gtk_application_window_real_unrealize (GtkWidget *widget) g_signal_handlers_disconnect_by_func (settings, gtk_application_window_shell_shows_app_menu_changed, widget); g_signal_handlers_disconnect_by_func (settings, gtk_application_window_shell_shows_menubar_changed, widget); - GTK_WIDGET_CLASS (gtk_application_window_parent_class) - ->unrealize (widget); + GTK_WIDGET_CLASS (gtk_application_window_parent_class)->unrealize (widget); } gboolean diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 8101b094bd..7206fd8296 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -157,6 +157,7 @@ struct _GtkWindowPrivate GtkWidget *title_box; GtkWidget *titlebar; GtkWidget *titlebar_icon; + GtkWidget *titlebar_menu_button; GtkWidget *titlebar_min_button; GtkWidget *titlebar_max_button; GtkWidget *titlebar_close_button; @@ -1068,7 +1069,7 @@ gtk_window_class_init (GtkWindowClass *klass) g_param_spec_string ("decoration-button-layout", P_("Decorated button layout"), P_("Decorated button layout"), - ":close", + "menu:close", GTK_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, @@ -3473,6 +3474,7 @@ unset_titlebar (GtkWindow *window) priv->title_box = NULL; priv->titlebar = NULL; priv->titlebar_icon = NULL; + priv->titlebar_menu_button = NULL; priv->titlebar_min_button = NULL; priv->titlebar_max_button = NULL; priv->titlebar_close_button = NULL; @@ -3579,10 +3581,18 @@ gtk_window_set_titlebar (GtkWindow *window, gtk_widget_queue_resize (widget); } -GtkWidget * -_gtk_window_get_titlebar (GtkWindow *window) +gboolean +_gtk_window_titlebar_shows_app_menu (GtkWindow *window) { - return window->priv->title_box; + GtkWindowPrivate *priv = window->priv; + + if (priv->titlebar_menu_button) + return TRUE; + + if (GTK_IS_HEADER_BAR (priv->title_box)) + return gtk_header_bar_get_show_fallback_app_menu (GTK_HEADER_BAR (priv->title_box)); + + return FALSE; } /** @@ -3811,12 +3821,18 @@ set_titlebar_icon (GtkWindow *window, GList *list) { GdkPixbuf *pixbuf, *best; GList *l; + gint size; + + if (GTK_IS_BUTTON (gtk_widget_get_parent (priv->titlebar_icon))) + size = 16; + else + size = 20; best = NULL; for (l = list; l; l = l->next) { pixbuf = list->data; - if (gdk_pixbuf_get_width (pixbuf) <= 20) + if (gdk_pixbuf_get_width (pixbuf) <= size) { best = g_object_ref (pixbuf); break; @@ -3824,7 +3840,7 @@ set_titlebar_icon (GtkWindow *window, GList *list) } if (best == NULL) - best = gdk_pixbuf_scale_simple (GDK_PIXBUF (list->data), 20, 20, GDK_INTERP_BILINEAR); + best = gdk_pixbuf_scale_simple (GDK_PIXBUF (list->data), size, size, GDK_INTERP_BILINEAR); gtk_image_set_from_pixbuf (GTK_IMAGE (priv->titlebar_icon), best); g_object_unref (best); @@ -5127,6 +5143,8 @@ update_window_buttons (GtkWindow *window) gchar **tokens, **t; gint i, j; GdkPixbuf *icon = NULL; + GMenuModel *menu; + gboolean shown_by_shell; if (priv->title_box == NULL) return; @@ -5155,6 +5173,11 @@ update_window_buttons (GtkWindow *window) gtk_widget_destroy (priv->titlebar_icon); priv->titlebar_icon = NULL; } + if (priv->titlebar_menu_button) + { + gtk_widget_destroy (priv->titlebar_menu_button); + priv->titlebar_menu_button = NULL; + } if (priv->titlebar_min_button) { gtk_widget_destroy (priv->titlebar_min_button); @@ -5175,6 +5198,14 @@ update_window_buttons (GtkWindow *window) "decoration-button-layout", &layout_desc, NULL); + g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)), + "gtk-shell-shows-app-menu", &shown_by_shell, NULL); + + if (!shown_by_shell && priv->application) + menu = gtk_application_get_app_menu (priv->application); + else + menu = NULL; + tokens = g_strsplit (layout_desc, ":", 2); if (tokens) { @@ -5211,15 +5242,30 @@ update_window_buttons (GtkWindow *window) 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); - } + gtk_image_set_from_pixbuf (GTK_IMAGE (button), icon); else gtk_widget_hide (button); priv->titlebar_icon = button; } + else if (strcmp (t[j], "menu") == 0 && menu != NULL) + { + button = gtk_menu_button_new (); + gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (button), menu); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "titlebutton"); + if (icon != NULL) + image = gtk_image_new_from_pixbuf (icon); + else + image = gtk_image_new_from_icon_name ("process-stop-symbolic", GTK_ICON_SIZE_MENU); + gtk_container_add (GTK_CONTAINER (button), image); + gtk_widget_set_can_focus (button, FALSE); + gtk_widget_show_all (button); + accessible = gtk_widget_get_accessible (button); + if (GTK_IS_ACCESSIBLE (accessible)) + atk_object_set_name (accessible, _("Application menu")); + priv->titlebar_icon = image; + priv->titlebar_menu_button = button; + } else if (strcmp (t[j], "minimize") == 0 && priv->gdk_type_hint == GDK_WINDOW_TYPE_HINT_NORMAL) { @@ -5285,6 +5331,8 @@ update_window_buttons (GtkWindow *window) g_strfreev (tokens); } g_free (layout_desc); + if (icon) + g_object_unref (icon); } static GtkWidget * @@ -5297,7 +5345,9 @@ create_titlebar (GtkWindow *window) gchar *title; titlebar = gtk_header_bar_new (); - g_object_set (titlebar, "spacing", 0, NULL); + g_object_set (titlebar, + "spacing", 0, + NULL); context = gtk_widget_get_style_context (titlebar); gtk_style_context_add_class (context, GTK_STYLE_CLASS_TITLEBAR); gtk_style_context_add_class (context, "default-decoration"); @@ -11687,3 +11737,10 @@ _gtk_window_handle_button_press_for_widget (GtkWidget *widget, return FALSE; } + +void +_gtk_window_get_decoration_size (GtkWindow *window, + GtkBorder *border) +{ + get_decoration_size (window, border); +} diff --git a/gtk/gtkwindowprivate.h b/gtk/gtkwindowprivate.h index 19bed99373..a9f431d432 100644 --- a/gtk/gtkwindowprivate.h +++ b/gtk/gtkwindowprivate.h @@ -87,7 +87,10 @@ void _gtk_window_schedule_mnemonics_visible (GtkWindow *window); void _gtk_window_notify_keys_changed (GtkWindow *window); -GtkWidget *_gtk_window_get_titlebar (GtkWindow *window); +gboolean _gtk_window_titlebar_shows_app_menu (GtkWindow *window); + +void _gtk_window_get_decoration_size (GtkWindow *window, + GtkBorder *border); G_END_DECLS