[gtk+] GtkWindow: better app menu fallback for CSD



commit 73b02933d0790dc7478d8eda3eaee0c7f0a7fef5
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Nov 16 14:46:10 2013 -0500

    GtkWindow: better app menu fallback for CSD
    
    Do the menubutton for app menu fallback ourselves in GtkWindow
    for the csd, non-custom titlebar case. This fits better with
    the way we handle other title buttons. Themes have control
    over the placement of this button by placing menu in the
    decoration-button-layout style property.

 gtk/gtkapplicationwindow.c |   12 ++----
 gtk/gtkwindow.c            |   79 +++++++++++++++++++++++++++++++++++++------
 gtk/gtkwindowprivate.h     |    5 ++-
 3 files changed, 76 insertions(+), 20 deletions(-)
---
diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c
index dd0be62..9c3d1ba 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 8101b09..7206fd8 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 19bed99..a9f431d 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
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]