Bug 1434646 - Titlebar rendering - Place titlebar buttons in GtkBox, r?jhorak draft
authorMartin Stransky <stransky@redhat.com>
Fri, 23 Feb 2018 21:28:37 +0100
changeset 761058 d9f522437ea59e5d9cc797e28b6a1e6edbda0e15
parent 760648 5297541590781af40ff09e067646f3115960af75
push id100839
push userstransky@redhat.com
push dateWed, 28 Feb 2018 16:33:00 +0000
reviewersjhorak
bugs1434646
milestone60.0a1
Bug 1434646 - Titlebar rendering - Place titlebar buttons in GtkBox, r?jhorak Some themes (Ambiance for instance) uses first-child/last-child css selectors to style titlebar buttons. Ubuntu Ambiance theme places titlebar buttons closer by negative margin applied to them. We put titlebar buttons to GtkBox as well as Gtk+ does and also keep the button order here to match first-child/last-child selectors. It also means we must have maximize/restore as one button to keep the correct order. MozReview-Commit-ID: 9mqljOa4Vu7
widget/gtk/WidgetStyleCache.cpp
widget/gtk/gtk3drawing.cpp
widget/gtk/gtkdrawing.h
widget/gtk/nsLookAndFeel.cpp
widget/gtk/nsNativeThemeGTK.cpp
--- a/widget/gtk/WidgetStyleCache.cpp
+++ b/widget/gtk/WidgetStyleCache.cpp
@@ -628,67 +628,125 @@ GetWidgetIconSurface(GtkWidget* aWidgetI
     aScale = ICON_SCALE_VARIANTS;
 
   nsAutoCString surfaceName;
   surfaceName = nsPrintfCString("MozillaIconSurface%d", aScale);
   return (cairo_surface_t*)
     g_object_get_data(G_OBJECT(aWidgetIcon), surfaceName.get());
 }
 
-// TODO - Also return style for buttons located at Maximized toolbar.
 static GtkWidget*
 CreateHeaderBarButton(WidgetNodeType aWidgetType)
 {
-  MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
-             "GtkHeaderBar is only available on GTK 3.10+.");
+  GtkWidget* widget = gtk_button_new();
 
-  GtkWidget* widget = gtk_button_new();
-  gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_HEADER_BAR)), widget);
+  // We bypass GetWidget() here because we create all titlebar
+  // buttons at once when a first one is requested.
+  NS_ASSERTION(sWidgetStorage[aWidgetType] == nullptr,
+               "Titlebar button is already created!");
+  sWidgetStorage[aWidgetType] = widget;
+
+  // We need to show the button widget now as GtkBox does not
+  // place invisible widgets and we'll miss first-child/last-child
+  // css selectors at the buttons otherwise.
+  gtk_widget_show(widget);
 
   GtkStyleContext* style = gtk_widget_get_style_context(widget);
   gtk_style_context_add_class(style, "titlebutton");
 
   GtkWidget *image = nullptr;
   switch (aWidgetType) {
-    case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
-      gtk_style_context_add_class(style, "close");
-      image = gtk_image_new_from_icon_name("window-close-symbolic",
-                                          GTK_ICON_SIZE_MENU);
-      break;
-    case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
-      gtk_style_context_add_class(style, "minimize");
-      image = gtk_image_new_from_icon_name("window-minimize-symbolic",
-                                           GTK_ICON_SIZE_MENU);
-      break;
-    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
-      gtk_style_context_add_class(style, "maximize");
-      image = gtk_image_new_from_icon_name("window-maximize-symbolic",
+     case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
+       gtk_style_context_add_class(style, "close");
+       image = gtk_image_new_from_icon_name("window-close-symbolic",
                                            GTK_ICON_SIZE_MENU);
-      break;
-    case MOZ_GTK_HEADER_BAR_BUTTON_RESTORE:
-      gtk_style_context_add_class(style, "maximize");
-      image = gtk_image_new_from_icon_name("window-restore-symbolic",
-                                           GTK_ICON_SIZE_MENU);
-      break;
-    default:
-      break;
-  }
+       break;
+     case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
+       gtk_style_context_add_class(style, "minimize");
+       image = gtk_image_new_from_icon_name("window-minimize-symbolic",
+                                            GTK_ICON_SIZE_MENU);
+       break;
+
+     case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
+       gtk_style_context_add_class(style, "maximize");
+       image = gtk_image_new_from_icon_name("window-maximize-symbolic",
+                                            GTK_ICON_SIZE_MENU);
+       break;
+
+     case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE:
+       gtk_style_context_add_class(style, "maximize");
+       image = gtk_image_new_from_icon_name("window-restore-symbolic",
+                                            GTK_ICON_SIZE_MENU);
+       break;
+     default:
+       break;
+   }
+
+   gtk_widget_set_valign(widget, GTK_ALIGN_CENTER);
+   g_object_set(image, "use-fallback", TRUE, NULL);
+   gtk_container_add(GTK_CONTAINER (widget), image);
+
+   // We bypass GetWidget() here by explicit sWidgetStorage[] update so
+   // invalidate the style as well as GetWidget() does.
+   style = gtk_widget_get_style_context(image);
+   gtk_style_context_invalidate(style);
+
+   LoadWidgetIconPixbuf(image);
+
+   return widget;
+}
 
-  gtk_widget_set_valign(widget, GTK_ALIGN_CENTER);
-  g_object_set(image, "use-fallback", TRUE, NULL);
-  gtk_container_add(GTK_CONTAINER (widget), image);
+static bool
+IsToolbarButtonEnabled(WidgetNodeType* aButtonLayout, int aButtonNums,
+                       WidgetNodeType aWidgetType)
+{
+    for (int i = 0; i < aButtonNums; i++) {
+      if (aButtonLayout[i] == aWidgetType) {
+        return true;
+      }
+    }
+    return false;
+}
+
+static void
+CreateHeaderBarButtons()
+{
+  MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
+             "GtkHeaderBar is only available on GTK 3.10+.");
+
+  GtkWidget* headerBar = GetWidget(MOZ_GTK_HEADER_BAR);
+
+  gint buttonSpacing = 6;
+  g_object_get(headerBar, "spacing", &buttonSpacing, nullptr);
 
-  // We bypass GetWidget() here by explicit sWidgetStorage[] update so
-  // invalidate the style as well as GetWidget() does.
-  style = gtk_widget_get_style_context(image);
-  gtk_style_context_invalidate(style);
+  GtkWidget *buttonBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, buttonSpacing);
+  gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_HEADER_BAR)), buttonBox);
+
+  WidgetNodeType buttonLayout[TOOLBAR_BUTTONS];
+  int activeButtons =
+      GetGtkHeaderBarButtonLayout(buttonLayout, TOOLBAR_BUTTONS);
 
-  LoadWidgetIconPixbuf(image);
-
-  return widget;
+  if (IsToolbarButtonEnabled(buttonLayout, activeButtons,
+                             MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE)) {
+    GtkWidget* button = CreateHeaderBarButton(MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE);
+    gtk_box_pack_start(GTK_BOX(buttonBox), button, FALSE, FALSE, 0);
+  }
+  if (IsToolbarButtonEnabled(buttonLayout, activeButtons,
+                             MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE)) {
+    GtkWidget* button = CreateHeaderBarButton(MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE);
+    gtk_box_pack_start(GTK_BOX(buttonBox), button, FALSE, FALSE, 0);
+    // We don't pack "restore" headerbar button as it's an icon
+    // placeholder only.
+    CreateHeaderBarButton(MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE);
+  }
+  if (IsToolbarButtonEnabled(buttonLayout, activeButtons,
+                             MOZ_GTK_HEADER_BAR_BUTTON_CLOSE)) {
+    GtkWidget* button = CreateHeaderBarButton(MOZ_GTK_HEADER_BAR_BUTTON_CLOSE);
+    gtk_box_pack_start(GTK_BOX(buttonBox), button, FALSE, FALSE, 0);
+  }
 }
 
 static GtkWidget*
 CreateWidget(WidgetNodeType aWidgetType)
 {
   switch (aWidgetType) {
     case MOZ_GTK_WINDOW:
       return CreateWindowWidget();
@@ -769,18 +827,19 @@ CreateWidget(WidgetNodeType aWidgetType)
     case MOZ_GTK_COMBOBOX_ENTRY_ARROW:
       return CreateComboBoxEntryArrowWidget();
     case MOZ_GTK_HEADER_BAR:
     case MOZ_GTK_HEADER_BAR_MAXIMIZED:
       return CreateHeaderBar(aWidgetType);
     case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
     case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
     case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
-    case MOZ_GTK_HEADER_BAR_BUTTON_RESTORE:
-      return CreateHeaderBarButton(aWidgetType);
+    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE:
+      CreateHeaderBarButtons();
+      return sWidgetStorage[aWidgetType];
     default:
       /* Not implemented */
       return nullptr;
   }
 }
 
 GtkWidget*
 GetWidget(WidgetNodeType aWidgetType)
@@ -1210,16 +1269,22 @@ GetCssNodeStyleInternal(WidgetNodeType a
     case MOZ_GTK_NOTEBOOK_HEADER:
     case MOZ_GTK_TABPANELS:
     case MOZ_GTK_TAB_SCROLLARROW:
     {
       // TODO - create from CSS node
       GtkWidget* widget = GetWidget(MOZ_GTK_NOTEBOOK);
       return gtk_widget_get_style_context(widget);
     }
+    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE:
+    {
+      NS_ASSERTION(false,
+          "MOZ_GTK_HEADER_BAR_BUTTON_RESTORE is used as an icon only!");
+      return nullptr;
+    }
     default:
       return GetWidgetRootStyle(aNodeType);
   }
 
   MOZ_ASSERT(style, "missing style context for node type");
   sStyleStorage[aNodeType] = style;
   return style;
 }
--- a/widget/gtk/gtk3drawing.cpp
+++ b/widget/gtk/gtk3drawing.cpp
@@ -382,17 +382,17 @@ CalculateToolbarButtonSpacing(WidgetNode
     aMetrics->iconYPosition += aMetrics->buttonMargin.top;
 
     aMetrics->minSizeWithBorderMargin.width +=
         aMetrics->buttonMargin.right + aMetrics->buttonMargin.left;
     aMetrics->minSizeWithBorderMargin.height +=
         aMetrics->buttonMargin.top + aMetrics->buttonMargin.bottom;
 }
 
-static int
+int
 GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout, int aMaxButtonNums)
 {
   NS_ASSERTION(aMaxButtonNums >= TOOLBAR_BUTTONS,
                "Requested number of buttons is higher than storage capacity!");
 
   static auto sGtkHeaderBarGetDecorationLayoutPtr =
     (const gchar* (*)(GtkWidget*))
     dlsym(RTLD_DEFAULT, "gtk_header_bar_get_decoration_layout");
@@ -478,31 +478,16 @@ GetToolbarButtonMetrics(WidgetNodeType a
 
     int buttonIndex = (aWidgetType - MOZ_GTK_HEADER_BAR_BUTTON_CLOSE);
     NS_ASSERTION(buttonIndex >= 0 &&
                  buttonIndex <= TOOLBAR_BUTTONS,
                  "GetToolbarButtonMetrics(): Wrong titlebar button!");
     return sToolbarMetrics.button + buttonIndex;
 }
 
-bool
-IsToolbarButtonEnabled(WidgetNodeType aWidgetType)
-{
-    WidgetNodeType aButtonLayout[TOOLBAR_BUTTONS];
-    int activeButtonNums =
-        GetGtkHeaderBarButtonLayout(aButtonLayout, TOOLBAR_BUTTONS);
-
-    for (int i = 0; i < activeButtonNums; i++) {
-        if (aButtonLayout[i] == aWidgetType) {
-            return true;
-        }
-    }
-    return false;
-}
-
 static gint
 moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect,
                      GtkTextDirection direction)
 {
     GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW, direction);
 
     gtk_style_context_save(style);
     gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
@@ -565,40 +550,45 @@ moz_gtk_button_paint(cairo_t *cr, GdkRec
     gtk_style_context_restore(style);
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_header_bar_button_paint(cairo_t *cr, GdkRectangle* rect,
                                 GtkWidgetState* state,
                                 GtkReliefStyle relief,
-                                WidgetNodeType aWidgetType,
+                                WidgetNodeType aIconWidgetType,
                                 GtkTextDirection direction)
 {
+    WidgetNodeType buttonWidgetType =
+      (aIconWidgetType == MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE) ?
+      MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE : aIconWidgetType;
+
     // We need to inset our calculated margin because it also
     // contains titlebar button spacing.
     const ToolbarButtonGTKMetrics* metrics =
-        GetToolbarButtonMetrics(aWidgetType);
+        GetToolbarButtonMetrics(buttonWidgetType);
     Inset(rect, metrics->buttonMargin);
 
-    GtkWidget *widget = GetWidget(aWidgetType);
-    moz_gtk_button_paint(cr, rect, state, relief, widget, direction);
-
-    GtkWidget* iconWidget = gtk_bin_get_child(GTK_BIN(widget));
+    GtkWidget *buttonWidget = GetWidget(buttonWidgetType);
+    moz_gtk_button_paint(cr, rect, state, relief, buttonWidget, direction);
+
+    GtkWidget* iconWidget =
+        gtk_bin_get_child(GTK_BIN(GetWidget(aIconWidgetType)));
     cairo_surface_t *surface = GetWidgetIconSurface(iconWidget, state->scale);
 
     if (surface) {
-        GtkStyleContext* style = gtk_widget_get_style_context(iconWidget);
+        GtkStyleContext* style = gtk_widget_get_style_context(buttonWidget);
         GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
 
         gtk_style_context_save(style);
         gtk_style_context_set_state(style, state_flags);
 
         const ToolbarButtonGTKMetrics *metrics =
-            GetToolbarButtonMetrics(aWidgetType);
+            GetToolbarButtonMetrics(buttonWidgetType);
 
         /* This is available since Gtk+ 3.10 as well as GtkHeaderBar */
         static auto sGtkRenderIconSurfacePtr =
           (void (*)(GtkStyleContext *, cairo_t *, cairo_surface_t *, gdouble, gdouble))
         dlsym(RTLD_DEFAULT, "gtk_render_icon_surface");
 
         sGtkRenderIconSurfacePtr(style, cr, surface,
                                  metrics->iconXPosition, metrics->iconYPosition);
@@ -2534,17 +2524,17 @@ moz_gtk_get_widget_border(WidgetNodeType
     case MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE:
     case MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE:
     case MOZ_GTK_TREEVIEW_EXPANDER:
     case MOZ_GTK_TOOLBAR_SEPARATOR:
     case MOZ_GTK_MENUSEPARATOR:
     case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
     case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
     case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
-    case MOZ_GTK_HEADER_BAR_BUTTON_RESTORE:
+    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE:
     /* These widgets have no borders.*/
     case MOZ_GTK_INNER_SPIN_BUTTON:
     case MOZ_GTK_SPINBUTTON:
     case MOZ_GTK_WINDOW:
     case MOZ_GTK_RESIZER:
     case MOZ_GTK_MENUARROW:
     case MOZ_GTK_TOOLBARBUTTON_ARROW:
     case MOZ_GTK_TOOLBAR:
@@ -3042,17 +3032,17 @@ moz_gtk_widget_paint(WidgetNodeType widg
         return moz_gtk_button_paint(cr, rect, state,
                                     (GtkReliefStyle) flags,
                                     GetWidget(MOZ_GTK_BUTTON),
                                     direction);
         break;
     case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
     case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
     case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
-    case MOZ_GTK_HEADER_BAR_BUTTON_RESTORE:
+    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE:
         return moz_gtk_header_bar_button_paint(cr, rect, state,
                                                (GtkReliefStyle) flags,
                                                widget,
                                                direction);
         break;
     case MOZ_GTK_CHECKBUTTON:
     case MOZ_GTK_RADIOBUTTON:
         return moz_gtk_toggle_paint(cr, rect, state,
--- a/widget/gtk/gtkdrawing.h
+++ b/widget/gtk/gtkdrawing.h
@@ -90,17 +90,17 @@ typedef struct {
   GtkBorder  buttonMargin;
   gint iconXPosition;
   gint iconYPosition;
   bool visible;
   bool firstButton;
   bool lastButton;
 } ToolbarButtonGTKMetrics;
 
-#define TOOLBAR_BUTTONS 4
+#define TOOLBAR_BUTTONS 3
 typedef struct {
   bool initialized;
   ToolbarButtonGTKMetrics button[TOOLBAR_BUTTONS];
 } ToolbarGTKMetrics;
 
 typedef enum {
   MOZ_GTK_STEPPER_DOWN        = 1 << 0,
   MOZ_GTK_STEPPER_BOTTOM      = 1 << 1,
@@ -317,17 +317,22 @@ typedef enum {
   MOZ_GTK_HEADER_BAR_MAXIMIZED,
   /* Paints GtkHeaderBar title buttons.
    * Keep the order here as MOZ_GTK_HEADER_BAR_BUTTON_* are processed
    * as an array from MOZ_GTK_HEADER_BAR_BUTTON_CLOSE to the last one.
    */
   MOZ_GTK_HEADER_BAR_BUTTON_CLOSE,
   MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE,
   MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE,
-  MOZ_GTK_HEADER_BAR_BUTTON_RESTORE,
+
+  /* MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE is a state of
+   * MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE button and it's used as
+   * an icon placeholder only.
+   */
+  MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE,
 
   MOZ_GTK_WIDGET_NODE_COUNT
 } WidgetNodeType;
 
 /*** General library functions ***/
 /**
  * Initializes the drawing library.  You must call this function
  * prior to using any other functionality.
@@ -575,14 +580,22 @@ moz_gtk_get_tab_thickness(WidgetNodeType
 
 
 /**
  * Get ToolbarButtonGTKMetrics for recent theme.
  */
 const ToolbarButtonGTKMetrics*
 GetToolbarButtonMetrics(WidgetNodeType aWidgetType);
 
-/* Get toolbar button state.
-*/
-bool
-IsToolbarButtonEnabled(WidgetNodeType aWidgetType);
+/**
+ * Get toolbar button layout.
+ * aButtonLayout:  [IN][OUT] An array which will be filled by WidgetNodeType
+ *                           references to visible titlebar buttons.
+                             Must contains at least TOOLBAR_BUTTONS entries.
+ * aMaxButtonNums: [IN] Allocated aButtonLayout entries. Must be at least
+                        TOOLBAR_BUTTONS wide.
+ *
+ * returns:    Number of returned entries at aButtonLayout.
+ */
+int
+GetGtkHeaderBarButtonLayout(WidgetNodeType* aButtonLayout, int aMaxButtonNums);
 
 #endif
--- a/widget/gtk/nsLookAndFeel.cpp
+++ b/widget/gtk/nsLookAndFeel.cpp
@@ -1080,24 +1080,41 @@ nsLookAndFeel::EnsureInit()
 
     gtk_widget_destroy(window);
     g_object_unref(labelWidget);
 
     // Require GTK 3.10 for GtkHeaderBar support and compatible window manager.
     mCSDAvailable = (gtk_check_version(3, 10, 0) == nullptr &&
         nsWindow::GetCSDSupportLevel() != nsWindow::CSD_SUPPORT_NONE);
 
+    mCSDCloseButton = false;
+    mCSDMinimizeButton = false;
+    mCSDMaximizeButton = false;
+
     // We need to initialize whole CSD config explicitly because it's queried
     // as -moz-gtk* media features.
-    mCSDCloseButton =
-        IsToolbarButtonEnabled(MOZ_GTK_HEADER_BAR_BUTTON_CLOSE);
-    mCSDMinimizeButton =
-        IsToolbarButtonEnabled(MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE);
-    mCSDMaximizeButton =
-        IsToolbarButtonEnabled(MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE);
+    WidgetNodeType buttonLayout[TOOLBAR_BUTTONS];
+
+    int activeButtons =
+        GetGtkHeaderBarButtonLayout(buttonLayout, TOOLBAR_BUTTONS);
+    for (int i = 0; i < activeButtons; i++) {
+        switch(buttonLayout[i]) {
+        case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
+            mCSDMinimizeButton = true;
+            break;
+        case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
+            mCSDMaximizeButton = true;
+            break;
+        case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
+            mCSDCloseButton = true;
+            break;
+        default:
+            break;
+        }
+    }
 }
 
 // virtual
 char16_t
 nsLookAndFeel::GetPasswordCharacterImpl()
 {
     EnsureInit();
     return mInvisibleCharacter;
--- a/widget/gtk/nsNativeThemeGTK.cpp
+++ b/widget/gtk/nsNativeThemeGTK.cpp
@@ -750,17 +750,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
     break;
   case NS_THEME_WINDOW_BUTTON_MINIMIZE:
     aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE;
     break;
   case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
     aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
     break;
   case NS_THEME_WINDOW_BUTTON_RESTORE:
-    aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_RESTORE;
+    aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE_RESTORE;
     break;
   default:
     return false;
   }
 
   return true;
 }
 
@@ -1621,31 +1621,24 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
     {
       const ToolbarButtonGTKMetrics* metrics =
           GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE);
       aResult->width = metrics->minSizeWithBorderMargin.width;
       aResult->height = metrics->minSizeWithBorderMargin.height;
       break;
     }
   case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
+  case NS_THEME_WINDOW_BUTTON_RESTORE:
     {
       const ToolbarButtonGTKMetrics* metrics =
           GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE);
       aResult->width = metrics->minSizeWithBorderMargin.width;
       aResult->height = metrics->minSizeWithBorderMargin.height;
       break;
     }
-  case NS_THEME_WINDOW_BUTTON_RESTORE:
-    {
-      const ToolbarButtonGTKMetrics* metrics =
-          GetToolbarButtonMetrics(MOZ_GTK_HEADER_BAR_BUTTON_RESTORE);
-      aResult->width = metrics->minSizeWithBorderMargin.width;
-      aResult->height = metrics->minSizeWithBorderMargin.height;
-      break;
-    }
   case NS_THEME_CHECKBOX_CONTAINER:
   case NS_THEME_RADIO_CONTAINER:
   case NS_THEME_CHECKBOX_LABEL:
   case NS_THEME_RADIO_LABEL:
   case NS_THEME_BUTTON:
   case NS_THEME_MENULIST:
   case NS_THEME_TOOLBARBUTTON:
   case NS_THEME_TREEHEADERCELL: