bug 1272194 use WidgetStyleCache for menus r=stransky draft
authorKarl Tomlinson <karlt+@karlt.net>
Tue, 17 May 2016 18:24:55 +1200
changeset 368608 6f19b911e455c619b7360156ee966eb3701624b6
parent 368607 8a1a98a46cc80dd6e20b5a1fe0b8ff910c3ee07f
child 368609 57a01f75931c565d193dcc40c2f5025f121b287b
child 369014 c00471a623f740ca028caee76dcfcbdb1d620735
push id18602
push userktomlinson@mozilla.com
push dateThu, 19 May 2016 05:18:04 +0000
reviewersstransky
bugs1272194
milestone49.0a1
bug 1272194 use WidgetStyleCache for menus r=stransky Unnecessary widget realization is also removed. MozReview-Commit-ID: A5HuE5bqf4x
widget/gtk/WidgetStyleCache.cpp
widget/gtk/gtk3drawing.cpp
--- a/widget/gtk/WidgetStyleCache.cpp
+++ b/widget/gtk/WidgetStyleCache.cpp
@@ -68,16 +68,41 @@ static GtkWidget*
 CreateRadiobuttonWidget()
 {
   GtkWidget* widget = gtk_radio_button_new_with_label(NULL, "M");
   AddToWindowContainer(widget);
   return widget;
 }
 
 static GtkWidget*
+CreateMenuBarWidget()
+{
+  GtkWidget* widget = gtk_menu_bar_new();
+  AddToWindowContainer(widget);
+  return widget;
+}
+
+static GtkWidget*
+CreateMenuPopupWidget()
+{
+  GtkWidget* widget = gtk_menu_new();
+  gtk_menu_attach_to_widget(GTK_MENU(widget), GetWidget(MOZ_GTK_WINDOW),
+                            nullptr);
+  return widget;
+}
+
+static GtkWidget*
+CreateMenuItemWidget(WidgetNodeType aShellType)
+{
+  GtkWidget* widget = gtk_menu_item_new();
+  gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(aShellType)), widget);
+  return widget;
+}
+
+static GtkWidget*
 CreateWidget(WidgetNodeType aWidgetType)
 {
   switch (aWidgetType) {
     case MOZ_GTK_WINDOW:
       return CreateWindowWidget();
     case MOZ_GTK_WINDOW_CONTAINER:
       return CreateWindowContainerWidget();
     case MOZ_GTK_SCROLLBAR_HORIZONTAL:
@@ -85,16 +110,24 @@ CreateWidget(WidgetNodeType aWidgetType)
                                    GTK_ORIENTATION_HORIZONTAL);
     case MOZ_GTK_SCROLLBAR_VERTICAL:
       return CreateScrollbarWidget(aWidgetType,
                                    GTK_ORIENTATION_VERTICAL);
     case MOZ_GTK_CHECKBUTTON_CONTAINER:
       return CreateCheckboxWidget();
     case MOZ_GTK_RADIOBUTTON_CONTAINER:
       return CreateRadiobuttonWidget();
+    case MOZ_GTK_MENUBAR:
+      return CreateMenuBarWidget();
+    case MOZ_GTK_MENUPOPUP:
+      return CreateMenuPopupWidget();
+    case MOZ_GTK_MENUBARITEM:
+      return CreateMenuItemWidget(MOZ_GTK_MENUBAR);
+    case MOZ_GTK_MENUITEM:
+      return CreateMenuItemWidget(MOZ_GTK_MENUPOPUP);
     default:
       /* Not implemented */
       return nullptr;
   }
 }
 
 GtkWidget*
 GetWidget(WidgetNodeType aWidgetType)
--- a/widget/gtk/gtk3drawing.cpp
+++ b/widget/gtk/gtk3drawing.cpp
@@ -37,20 +37,16 @@ static GtkWidget* gComboBoxEntryButtonWi
 static GtkWidget* gComboBoxEntryArrowWidget;
 static GtkWidget* gHandleBoxWidget;
 static GtkWidget* gToolbarWidget;
 static GtkWidget* gFrameWidget;
 static GtkWidget* gProgressWidget;
 static GtkWidget* gTabWidget;
 static GtkWidget* gTextViewWidget;
 static GtkWidget* gTooltipWidget;
-static GtkWidget* gMenuBarWidget;
-static GtkWidget* gMenuBarItemWidget;
-static GtkWidget* gMenuPopupWidget;
-static GtkWidget* gMenuItemWidget;
 static GtkWidget* gImageMenuItemWidget;
 static GtkWidget* gCheckMenuItemWidget;
 static GtkWidget* gTreeViewWidget;
 static GtkTreeViewColumn* gMiddleTreeViewColumn;
 static GtkWidget* gTreeHeaderCellWidget;
 static GtkWidget* gTreeHeaderSortArrowWidget;
 static GtkWidget* gExpanderWidget;
 static GtkWidget* gToolbarSeparatorWidget;
@@ -500,97 +496,45 @@ ensure_frame_widget()
     if (!gFrameWidget) {
         gFrameWidget = gtk_frame_new(NULL);
         setup_widget_prototype(gFrameWidget);
     }
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
-ensure_menu_bar_widget()
-{
-    if (!gMenuBarWidget) {
-        gMenuBarWidget = gtk_menu_bar_new();
-        setup_widget_prototype(gMenuBarWidget);
-    }
-    return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_menu_bar_item_widget()
-{
-    if (!gMenuBarItemWidget) {
-        ensure_menu_bar_widget();
-        gMenuBarItemWidget = gtk_menu_item_new();
-        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
-                              gMenuBarItemWidget);
-        gtk_widget_realize(gMenuBarItemWidget);
-    }
-    return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_menu_popup_widget()
-{
-    if (!gMenuPopupWidget) {
-        ensure_window_widget();
-        gMenuPopupWidget = gtk_menu_new();
-        gtk_menu_attach_to_widget(GTK_MENU(gMenuPopupWidget), gProtoWindow,
-                                  NULL);
-        gtk_widget_realize(gMenuPopupWidget);
-    }
-    return MOZ_GTK_SUCCESS;
-}
-
-static gint
-ensure_menu_item_widget()
-{
-    if (!gMenuItemWidget) {
-        ensure_menu_popup_widget();
-        gMenuItemWidget = gtk_menu_item_new();
-        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
-                              gMenuItemWidget);
-        gtk_widget_realize(gMenuItemWidget);
-    }
-    return MOZ_GTK_SUCCESS;
-}
-
-static gint
 ensure_image_menu_item_widget()
 {
     if (!gImageMenuItemWidget) {
-        ensure_menu_popup_widget();
         gImageMenuItemWidget = gtk_image_menu_item_new();
-        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+        gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
                               gImageMenuItemWidget);
         gtk_widget_realize(gImageMenuItemWidget);
     }
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 ensure_menu_separator_widget()
 {
     if (!gMenuSeparatorWidget) {
-        ensure_menu_popup_widget();
         gMenuSeparatorWidget = gtk_separator_menu_item_new();
-        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+        gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
                               gMenuSeparatorWidget);
         gtk_widget_realize(gMenuSeparatorWidget);
     }
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 ensure_check_menu_item_widget()
 {
     if (!gCheckMenuItemWidget) {
-        ensure_menu_popup_widget();
         gCheckMenuItemWidget = gtk_check_menu_item_new();
-        gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+        gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
                               gCheckMenuItemWidget);
         gtk_widget_realize(gCheckMenuItemWidget);
     }
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 ensure_tree_view_widget()
@@ -739,21 +683,19 @@ moz_gtk_get_focus_outline_size(gint* foc
     *focus_h_width = border.left + padding.left;
     *focus_v_width = border.top + padding.top;
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding)
 {
-    ensure_menu_item_widget();
-
-    gtk_style_context_get_style(gtk_widget_get_style_context(gMenuItemWidget),
-                                "horizontal-padding", horizontal_padding,
-                                NULL);
+    gtk_widget_style_get(GetWidget(MOZ_GTK_MENUITEM),
+                         "horizontal-padding", horizontal_padding,
+                         nullptr);
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_checkmenuitem_get_horizontal_padding(gint* horizontal_padding)
 {
     ensure_check_menu_item_widget();
@@ -2360,43 +2302,43 @@ moz_gtk_tab_scroll_arrow_paint(cairo_t *
 }
 
 static gint
 moz_gtk_menu_bar_paint(cairo_t *cr, GdkRectangle* rect,
                        GtkTextDirection direction)
 {
     GtkStyleContext* style;
 
-    ensure_menu_bar_widget();
-    gtk_widget_set_direction(gMenuBarWidget, direction);
-
-    style = gtk_widget_get_style_context(gMenuBarWidget);
+    GtkWidget* widget = GetWidget(MOZ_GTK_MENUBAR);
+    gtk_widget_set_direction(widget, direction);
+
+    style = gtk_widget_get_style_context(widget);
     gtk_style_context_save(style);
     gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
     gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
     gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
     gtk_style_context_restore(style);
     
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_menu_popup_paint(cairo_t *cr, GdkRectangle* rect,
                          GtkTextDirection direction)
 {
     GtkStyleContext* style;
 
-    ensure_menu_popup_widget();
-    gtk_widget_set_direction(gMenuPopupWidget, direction);
+    GtkWidget* widget = GetWidget(MOZ_GTK_MENUPOPUP);
+    gtk_widget_set_direction(widget, direction);
 
     // Draw a backing toplevel. This fixes themes that don't provide a menu
     // background, and depend on the GtkMenu's implementation window to provide it.
     moz_gtk_window_paint(cr, rect, direction);
 
-    style = gtk_widget_get_style_context(gMenuPopupWidget);
+    style = gtk_widget_get_style_context(widget);
     gtk_style_context_save(style);
     gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENU);
 
     gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
     gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
     gtk_style_context_restore(style);
 
     return MOZ_GTK_SUCCESS;
@@ -2453,76 +2395,65 @@ moz_gtk_menu_separator_paint(cairo_t *cr
     return MOZ_GTK_SUCCESS;
 }
 
 // See gtk_menu_item_draw() for reference.
 static gint
 moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
                         GtkWidgetState* state, GtkTextDirection direction)
 {
-    GtkStyleContext* style;
-    GtkWidget* item_widget;
-    guint border_width;
     gint x, y, w, h;
 
     if (state->inHover && !state->disabled) {   
-        if (widget == MOZ_GTK_MENUBARITEM) {
-            ensure_menu_bar_item_widget();
-            item_widget = gMenuBarItemWidget;
-        } else {
-            ensure_menu_item_widget();
-            item_widget = gMenuItemWidget;
-        }
-        style = gtk_widget_get_style_context(item_widget);
+        guint border_width =
+            gtk_container_get_border_width(GTK_CONTAINER(GetWidget(widget)));
+        GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
+        GtkStyleContext* style =
+            ClaimStyleContext(widget, direction, state_flags);
 
         bool pre_3_6 = gtk_check_version(3, 6, 0) != nullptr;
         if (pre_3_6) {
             // GTK+ 3.4 saves the style context and adds the menubar class to
             // menubar children, but does each of these only when drawing, not
             // during layout.
             gtk_style_context_save(style);
             if (widget == MOZ_GTK_MENUBARITEM) {
                 gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
             }
         }
 
-        gtk_widget_set_direction(item_widget, direction);
-        gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
-
-        border_width = gtk_container_get_border_width(GTK_CONTAINER(item_widget));
-
         x = rect->x + border_width;
         y = rect->y + border_width;
         w = rect->width - border_width * 2;
         h = rect->height - border_width * 2;
 
         gtk_render_background(style, cr, x, y, w, h);
         gtk_render_frame(style, cr, x, y, w, h);
 
         if (pre_3_6) {
             gtk_style_context_restore(style);
         }
-        gtk_style_context_set_state(style, GTK_STATE_FLAG_NORMAL);
+        ReleaseStyleContext(style);
     }
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_menu_arrow_paint(cairo_t *cr, GdkRectangle* rect,
                          GtkWidgetState* state,
                          GtkTextDirection direction)
 {
     GtkStyleContext* style;
     GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
 
-    ensure_menu_item_widget();
-    gtk_widget_set_direction(gMenuItemWidget, direction);
-
-    style = gtk_widget_get_style_context(gMenuItemWidget);
+    GtkWidget* widget = GetWidget(MOZ_GTK_MENUITEM);
+    gtk_widget_set_direction(widget, direction);
+
+    style = gtk_widget_get_style_context(widget);
     gtk_style_context_save(style);
     gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUITEM);
     gtk_style_context_set_state(style, state_flags);
     gtk_render_arrow(style, cr,
                     (direction == GTK_TEXT_DIR_LTR) ? ARROW_RIGHT : ARROW_LEFT,
                     rect->x, rect->y, rect->width);
     gtk_style_context_restore(style);
 
@@ -2806,27 +2737,26 @@ moz_gtk_get_widget_border(WidgetNodeType
             *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w));
             moz_gtk_add_style_border(style,
                                      left, top, right, bottom);
             moz_gtk_add_style_padding(style,
                                       left, top, right, bottom);
             return MOZ_GTK_SUCCESS;
         }
     case MOZ_GTK_MENUPOPUP:
-        ensure_menu_popup_widget();
-        w = gMenuPopupWidget;
+        w = GetWidget(MOZ_GTK_MENUPOPUP);
         break;
     case MOZ_GTK_MENUBARITEM:
     case MOZ_GTK_MENUITEM:
     case MOZ_GTK_CHECKMENUITEM:
     case MOZ_GTK_RADIOMENUITEM:
         {
             if (widget == MOZ_GTK_MENUBARITEM || widget == MOZ_GTK_MENUITEM) {
-                ensure_menu_item_widget();
-                w = gMenuItemWidget; // Bug 1274143 for MOZ_GTK_MENUBARITEM
+                // Bug 1274143 for MOZ_GTK_MENUBARITEM
+                w = GetWidget(MOZ_GTK_MENUITEM);
             } else {
                 ensure_check_menu_item_widget();
                 w = gCheckMenuItemWidget;
             }
 
             *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w));
             moz_gtk_add_style_padding(gtk_widget_get_style_context(w),
                                       left, top, right, bottom);
@@ -3414,20 +3344,16 @@ moz_gtk_shutdown()
     gComboBoxEntryTextareaWidget = NULL;
     gHandleBoxWidget = NULL;
     gToolbarWidget = NULL;
     gFrameWidget = NULL;
     gProgressWidget = NULL;
     gTabWidget = NULL;
     gTextViewWidget = nullptr;
     gTooltipWidget = NULL;
-    gMenuBarWidget = NULL;
-    gMenuBarItemWidget = NULL;
-    gMenuPopupWidget = NULL;
-    gMenuItemWidget = NULL;
     gImageMenuItemWidget = NULL;
     gCheckMenuItemWidget = NULL;
     gTreeViewWidget = NULL;
     gMiddleTreeViewColumn = NULL;
     gTreeHeaderCellWidget = NULL;
     gTreeHeaderSortArrowWidget = NULL;
     gExpanderWidget = NULL;
     gToolbarSeparatorWidget = NULL;