diff options
Diffstat (limited to 'libre-testing/iceweasel/iceweasel-gtk3-20.patch')
-rw-r--r-- | libre-testing/iceweasel/iceweasel-gtk3-20.patch | 2333 |
1 files changed, 2333 insertions, 0 deletions
diff --git a/libre-testing/iceweasel/iceweasel-gtk3-20.patch b/libre-testing/iceweasel/iceweasel-gtk3-20.patch new file mode 100644 index 000000000..eccbc5e8d --- /dev/null +++ b/libre-testing/iceweasel/iceweasel-gtk3-20.patch @@ -0,0 +1,2333 @@ +diff -up firefox-48.0/widget/gtk/gtk3drawing.cpp.gtk3-20 firefox-48.0/widget/gtk/gtk3drawing.cpp +--- firefox-48.0/widget/gtk/gtk3drawing.cpp.gtk3-20 2016-07-25 22:22:07.000000000 +0200 ++++ firefox-48.0/widget/gtk/gtk3drawing.cpp 2016-07-29 09:15:11.822285857 +0200 +@@ -18,15 +18,9 @@ + + #include <math.h> + +-static GtkWidget* gProtoWindow; + static GtkWidget* gProtoLayout; +-static GtkWidget* gButtonWidget; +-static GtkWidget* gToggleButtonWidget; +-static GtkWidget* gButtonArrowWidget; +-static GtkWidget* gSpinWidget; + static GtkWidget* gHScaleWidget; + static GtkWidget* gVScaleWidget; +-static GtkWidget* gEntryWidget; + static GtkWidget* gComboBoxWidget; + static GtkWidget* gComboBoxButtonWidget; + static GtkWidget* gComboBoxArrowWidget; +@@ -35,30 +29,15 @@ static GtkWidget* gComboBoxEntryWidget; + static GtkWidget* gComboBoxEntryTextareaWidget; + static GtkWidget* gComboBoxEntryButtonWidget; + 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; +-static GtkWidget* gMenuSeparatorWidget; + static GtkWidget* gHPanedWidget; + static GtkWidget* gVPanedWidget; +-static GtkWidget* gScrolledWindowWidget; +-static GtkWidget* gInfoBar; + + static style_prop_t style_prop_func; + static gboolean have_arrow_scaling; +@@ -94,15 +73,6 @@ GetStateFlagsFromGtkWidgetState(GtkWidge + return stateFlags; + } + +-/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine +- that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific +- things they may want to do. */ +-static void +-moz_gtk_set_widget_name(GtkWidget* widget) +-{ +- gtk_widget_set_name(widget, "MozillaGtkWidget"); +-} +- + gint + moz_gtk_enable_style_props(style_prop_t styleGetProp) + { +@@ -111,15 +81,6 @@ moz_gtk_enable_style_props(style_prop_t + } + + static gint +-ensure_window_widget() +-{ +- if (!gProtoWindow) { +- gProtoWindow = GetWidget(MOZ_GTK_WINDOW); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint + setup_widget_prototype(GtkWidget* widget) + { + if (!gProtoLayout) { +@@ -130,16 +91,6 @@ setup_widget_prototype(GtkWidget* widget + } + + static gint +-ensure_button_widget() +-{ +- if (!gButtonWidget) { +- gButtonWidget = gtk_button_new_with_label("M"); +- setup_widget_prototype(gButtonWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint + ensure_hpaned_widget() + { + if (!gHPanedWidget) { +@@ -160,40 +111,6 @@ ensure_vpaned_widget() + } + + static gint +-ensure_toggle_button_widget() +-{ +- if (!gToggleButtonWidget) { +- gToggleButtonWidget = gtk_toggle_button_new(); +- setup_widget_prototype(gToggleButtonWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint +-ensure_button_arrow_widget() +-{ +- if (!gButtonArrowWidget) { +- ensure_toggle_button_widget(); +- +- gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); +- gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget); +- gtk_widget_realize(gButtonArrowWidget); +- gtk_widget_show(gButtonArrowWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint +-ensure_spin_widget() +-{ +- if (!gSpinWidget) { +- gSpinWidget = gtk_spin_button_new(NULL, 1, 0); +- setup_widget_prototype(gSpinWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint + ensure_scale_widget() + { + if (!gHScaleWidget) { +@@ -207,16 +124,6 @@ ensure_scale_widget() + return MOZ_GTK_SUCCESS; + } + +-static gint +-ensure_entry_widget() +-{ +- if (!gEntryWidget) { +- gEntryWidget = gtk_entry_new(); +- setup_widget_prototype(gEntryWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- + /* We need to have pointers to the inner widgets (button, separator, arrow) + * of the ComboBox to get the correct rendering from theme engines which + * special cases their look. Since the inner layout can change, we ask GTK +@@ -225,7 +132,7 @@ ensure_entry_widget() + * g_object_add_weak_pointer(). + * Note that if we don't find the inner widgets (which shouldn't happen), we + * fallback to use generic "non-inner" widgets, and they don't need that kind +- * of weak pointer since they are explicit children of gProtoWindow and as ++ * of weak pointer since they are explicit children of gProtoLayout and as + * such GTK holds a strong reference to them. */ + static void + moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data) +@@ -297,16 +204,14 @@ ensure_combo_box_widgets() + /* Shouldn't be reached with current internal gtk implementation; we + * use a generic toggle button as last resort fallback to avoid + * crashing. */ +- ensure_toggle_button_widget(); +- gComboBoxButtonWidget = gToggleButtonWidget; ++ gComboBoxButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON); + } + + if (!gComboBoxArrowWidget) { + /* Shouldn't be reached with current internal gtk implementation; + * we gButtonArrowWidget as last resort fallback to avoid + * crashing. */ +- ensure_button_arrow_widget(); +- gComboBoxArrowWidget = gButtonArrowWidget; ++ gComboBoxArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW); + } + + /* We don't test the validity of gComboBoxSeparatorWidget since there +@@ -316,15 +221,6 @@ ensure_combo_box_widgets() + return MOZ_GTK_SUCCESS; + } + +-static void +-ensure_info_bar() +-{ +- if (!gInfoBar) { +- gInfoBar = gtk_info_bar_new(); +- setup_widget_prototype(gInfoBar); +- } +-} +- + /* We need to have pointers to the inner widgets (entry, button, arrow) of + * the ComboBoxEntry to get the correct rendering from theme engines which + * special cases their look. Since the inner layout can change, we ask GTK +@@ -333,7 +229,7 @@ ensure_info_bar() + * g_object_add_weak_pointer(). + * Note that if we don't find the inner widgets (which shouldn't happen), we + * fallback to use generic "non-inner" widgets, and they don't need that kind +- * of weak pointer since they are explicit children of gProtoWindow and as ++ * of weak pointer since they are explicit children of gProtoLayout and as + * such GTK holds a strong reference to them. */ + static void + moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget, +@@ -385,8 +281,7 @@ ensure_combo_box_entry_widgets() + NULL); + + if (!gComboBoxEntryTextareaWidget) { +- ensure_entry_widget(); +- gComboBoxEntryTextareaWidget = gEntryWidget; ++ gComboBoxEntryTextareaWidget = GetWidget(MOZ_GTK_ENTRY); + } + + if (gComboBoxEntryButtonWidget) { +@@ -412,68 +307,19 @@ ensure_combo_box_entry_widgets() + /* Shouldn't be reached with current internal gtk implementation; + * we use a generic toggle button as last resort fallback to avoid + * crashing. */ +- ensure_toggle_button_widget(); +- gComboBoxEntryButtonWidget = gToggleButtonWidget; ++ gComboBoxEntryButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON); + } + + if (!gComboBoxEntryArrowWidget) { + /* Shouldn't be reached with current internal gtk implementation; + * we gButtonArrowWidget as last resort fallback to avoid + * crashing. */ +- ensure_button_arrow_widget(); +- gComboBoxEntryArrowWidget = gButtonArrowWidget; ++ gComboBoxEntryArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW); + } + + return MOZ_GTK_SUCCESS; + } + +- +-static gint +-ensure_handlebox_widget() +-{ +- if (!gHandleBoxWidget) { +- gHandleBoxWidget = gtk_handle_box_new(); +- setup_widget_prototype(gHandleBoxWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint +-ensure_toolbar_widget() +-{ +- if (!gToolbarWidget) { +- ensure_handlebox_widget(); +- gToolbarWidget = gtk_toolbar_new(); +- gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget); +- gtk_widget_realize(gToolbarWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint +-ensure_toolbar_separator_widget() +-{ +- if (!gToolbarSeparatorWidget) { +- ensure_toolbar_widget(); +- gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new()); +- setup_widget_prototype(gToolbarSeparatorWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint +-ensure_tooltip_widget() +-{ +- if (!gTooltipWidget) { +- gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP); +- GtkStyleContext* style = gtk_widget_get_style_context(gTooltipWidget); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP); +- gtk_widget_realize(gTooltipWidget); +- moz_gtk_set_widget_name(gTooltipWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- + static gint + ensure_tab_widget() + { +@@ -485,81 +331,11 @@ ensure_tab_widget() + } + + static gint +-ensure_progress_widget() +-{ +- if (!gProgressWidget) { +- gProgressWidget = gtk_progress_bar_new(); +- setup_widget_prototype(gProgressWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint +-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_with_label("M"); +- 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); + } +@@ -567,25 +343,11 @@ ensure_image_menu_item_widget() + } + + 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), +- 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_with_label("M"); +- gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget), ++ gCheckMenuItemWidget = gtk_check_menu_item_new(); ++ gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)), + gCheckMenuItemWidget); + gtk_widget_realize(gCheckMenuItemWidget); + } +@@ -646,37 +408,6 @@ ensure_tree_header_cell_widget() + return MOZ_GTK_SUCCESS; + } + +-static gint +-ensure_expander_widget() +-{ +- if (!gExpanderWidget) { +- gExpanderWidget = gtk_expander_new("M"); +- setup_widget_prototype(gExpanderWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static gint +-ensure_scrolled_window_widget() +-{ +- if (!gScrolledWindowWidget) { +- gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL); +- setup_widget_prototype(gScrolledWindowWidget); +- } +- return MOZ_GTK_SUCCESS; +-} +- +-static void +-ensure_text_view_widget() +-{ +- if (gTextViewWidget) +- return; +- +- gTextViewWidget = gtk_text_view_new(); +- ensure_scrolled_window_widget(); +- gtk_container_add(GTK_CONTAINER(gScrolledWindowWidget), gTextViewWidget); +-} +- + gint + moz_gtk_init() + { +@@ -729,26 +460,21 @@ moz_gtk_get_focus_outline_size(gint* foc + { + GtkBorder border; + GtkBorder padding; +- GtkStyleContext *style; +- +- ensure_entry_widget(); +- style = gtk_widget_get_style_context(gEntryWidget); +- ++ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_ENTRY); + gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); + gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); + *focus_h_width = border.left + padding.left; + *focus_v_width = border.top + padding.top; ++ ReleaseStyleContext(style); + 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; + } +@@ -771,10 +497,11 @@ moz_gtk_button_get_default_overflow(gint + { + GtkBorder* default_outside_border; + +- ensure_button_widget(); +- gtk_style_context_get_style(gtk_widget_get_style_context(gButtonWidget), ++ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ gtk_style_context_get_style(style, + "default-outside-border", &default_outside_border, + NULL); ++ ReleaseStyleContext(style); + + if (default_outside_border) { + *border_top = default_outside_border->top; +@@ -794,10 +521,11 @@ moz_gtk_button_get_default_border(gint* + { + GtkBorder* default_border; + +- ensure_button_widget(); +- gtk_style_context_get_style(gtk_widget_get_style_context(gButtonWidget), ++ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ gtk_style_context_get_style(style, + "default-border", &default_border, + NULL); ++ ReleaseStyleContext(style); + + if (default_border) { + *border_top = default_border->top; +@@ -831,17 +559,15 @@ static gint + moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style; +- +- ensure_window_widget(); +- gtk_widget_set_direction(gProtoWindow, direction); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_WINDOW, direction); + +- style = gtk_widget_get_style_context(gProtoWindow); + gtk_style_context_save(style); + gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND); + gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_style_context_restore(style); + ++ ReleaseStyleContext(style); ++ + return MOZ_GTK_SUCCESS; + } + +@@ -1118,6 +844,36 @@ moz_gtk_scrollbar_button_paint(cairo_t * + return MOZ_GTK_SUCCESS; + } + ++static void ++moz_gtk_update_scrollbar_style(GtkStyleContext* style, ++ WidgetNodeType widget, ++ GtkTextDirection direction) ++{ ++ if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) { ++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_BOTTOM); ++ } else { ++ if (direction == GTK_TEXT_DIR_LTR) { ++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_RIGHT); ++ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_LEFT); ++ } else { ++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_LEFT); ++ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_RIGHT); ++ } ++ } ++} ++ ++static void ++moz_gtk_draw_styled_frame(GtkStyleContext* style, cairo_t *cr, ++ GdkRectangle* rect, bool drawFocus) ++{ ++ 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); ++ if (drawFocus) { ++ gtk_render_focus(style, cr, ++ rect->x, rect->y, rect->width, rect->height); ++ } ++} ++ + static gint + moz_gtk_scrollbar_trough_paint(WidgetNodeType widget, + cairo_t *cr, GdkRectangle* rect, +@@ -1126,26 +882,34 @@ moz_gtk_scrollbar_trough_paint(WidgetNod + GtkTextDirection direction) + { + if (flags & MOZ_GTK_TRACK_OPAQUE) { +- GtkStyleContext* style = +- gtk_widget_get_style_context(GTK_WIDGET(gProtoWindow)); +- gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_WINDOW, direction); ++ gtk_render_background(style, cr, ++ rect->x, rect->y, rect->width, rect->height); ++ ReleaseStyleContext(style); + } + +- GtkStyleContext* style = +- ClaimStyleContext(widget == MOZ_GTK_SCROLLBAR_HORIZONTAL ? +- MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL : +- MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL, +- direction); +- // TODO - integate with ClaimStyleContext()? +- gtk_style_context_set_direction(style, direction); ++ bool isHorizontal = (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL); ++ GtkStyleContext* style; + +- 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); ++ // Draw all child CSS Nodes for Gtk >= 3.20 ++ if (gtk_check_version(3, 20, 0) == nullptr) { ++ style = ClaimStyleContext(widget, direction); ++ moz_gtk_update_scrollbar_style(style, widget, direction); ++ moz_gtk_draw_styled_frame(style, cr, rect, state->focused); ++ ReleaseStyleContext(style); + +- if (state->focused) { +- gtk_render_focus(style, cr, +- rect->x, rect->y, rect->width, rect->height); ++ style = ClaimStyleContext(isHorizontal ? ++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL : ++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL, ++ direction); ++ moz_gtk_draw_styled_frame(style, cr, rect, state->focused); ++ ReleaseStyleContext(style); + } ++ style = ClaimStyleContext(isHorizontal ? ++ MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL : ++ MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL, ++ direction); ++ moz_gtk_draw_styled_frame(style, cr, rect, state->focused); + ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; +@@ -1160,12 +924,7 @@ moz_gtk_scrollbar_thumb_paint(WidgetNode + GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); + GtkBorder margin; + +- GtkStyleContext* style = ClaimStyleContext(widget, direction); +- +- // TODO - integate those with ClaimStyleContext()? +- gtk_style_context_set_state(style, state_flags); +- gtk_style_context_set_direction(style, direction); +- ++ GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags); + gtk_style_context_get_margin (style, state_flags, &margin); + + gtk_render_slider(style, cr, +@@ -1185,17 +944,10 @@ static gint + moz_gtk_spin_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style; +- +- ensure_spin_widget(); +- gtk_widget_set_direction(gSpinWidget, direction); +- style = gtk_widget_get_style_context(gSpinWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON, direction); + 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); +- ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1204,21 +956,14 @@ moz_gtk_spin_updown_paint(cairo_t *cr, G + gboolean isDown, GtkWidgetState* state, + GtkTextDirection direction) + { +- GdkRectangle arrow_rect; +- GtkStyleContext* style; +- +- ensure_spin_widget(); +- style = gtk_widget_get_style_context(gSpinWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON); +- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state)); +- gtk_widget_set_direction(gSpinWidget, direction); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + + 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); + +- + /* hard code these values */ ++ GdkRectangle arrow_rect; + arrow_rect.width = 6; + arrow_rect.height = 6; + arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2; +@@ -1229,7 +974,8 @@ moz_gtk_spin_updown_paint(cairo_t *cr, G + isDown ? ARROW_DOWN : ARROW_UP, + arrow_rect.x, arrow_rect.y, + arrow_rect.width); +- gtk_style_context_restore(style); ++ ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1295,8 +1041,8 @@ moz_gtk_scale_thumb_paint(cairo_t *cr, G + gtk_widget_set_direction(widget, direction); + + style = gtk_widget_get_style_context(widget); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER); + gtk_style_context_save(style); ++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER); + gtk_style_context_set_state(style, state_flags); + /* determine the thumb size, and position the thumb in the center in the opposite axis + */ +@@ -1321,20 +1067,12 @@ moz_gtk_gripper_paint(cairo_t *cr, GdkRe + GtkWidgetState* state, + GtkTextDirection direction) + { +- GtkStyleContext* style; +- +- ensure_handlebox_widget(); +- gtk_widget_set_direction(gHandleBoxWidget, direction); +- +- style = gtk_widget_get_style_context(gHandleBoxWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP); +- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state)); +- ++ GtkStyleContext* style = ++ ClaimStyleContext(MOZ_GTK_GRIPPER, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + 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); +- ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1435,6 +1173,38 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect + return MOZ_GTK_SUCCESS; + } + ++static gint ++moz_gtk_text_view_paint(cairo_t *cr, GdkRectangle* rect, ++ GtkWidgetState* state, ++ GtkTextDirection direction) ++{ ++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); ++ ++ GtkStyleContext* style_frame = ++ ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction, state_flags); ++ gtk_render_frame(style_frame, cr, rect->x, rect->y, rect->width, rect->height); ++ ++ GtkBorder border, padding; ++ gtk_style_context_get_border(style_frame, state_flags, &border); ++ gtk_style_context_get_padding(style_frame, state_flags, &padding); ++ ReleaseStyleContext(style_frame); ++ ++ GtkStyleContext* style = ++ ClaimStyleContext(MOZ_GTK_TEXT_VIEW, direction, state_flags); ++ ++ gint xthickness = border.left + padding.left; ++ gint ythickness = border.top + padding.top; ++ ++ gtk_render_background(style, cr, ++ rect->x + xthickness, rect->y + ythickness, ++ rect->width - 2 * xthickness, ++ rect->height - 2 * ythickness); ++ ++ ReleaseStyleContext(style); ++ ++ return MOZ_GTK_SUCCESS; ++} ++ + static gint + moz_gtk_treeview_paint(cairo_t *cr, GdkRectangle* rect, + GtkWidgetState* state, +@@ -1447,18 +1217,13 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR + GtkBorder border; + + ensure_tree_view_widget(); +- ensure_scrolled_window_widget(); +- + gtk_widget_set_direction(gTreeViewWidget, direction); +- gtk_widget_set_direction(gScrolledWindowWidget, direction); + + /* only handle disabled and normal states, otherwise the whole background + * area will be painted differently with other states */ + state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL; + +- style = gtk_widget_get_style_context(gScrolledWindowWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME); ++ style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction); + gtk_style_context_get_border(style, state_flags, &border); + xthickness = border.left; + ythickness = border.top; +@@ -1473,7 +1238,7 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR + rect->height - 2 * ythickness); + gtk_render_frame(style, cr, + rect->x, rect->y, rect->width, rect->height); +- gtk_style_context_restore(style); ++ ReleaseStyleContext(style); + gtk_style_context_restore(style_tree); + return MOZ_GTK_SUCCESS; + } +@@ -1648,20 +1413,9 @@ moz_gtk_arrow_paint(cairo_t *cr, GdkRect + GtkWidgetState* state, + GtkArrowType arrow_type, GtkTextDirection direction) + { +- GtkStyleContext* style; +- GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); + GdkRectangle arrow_rect; + gdouble arrow_angle; + +- ensure_button_arrow_widget(); +- style = gtk_widget_get_style_context(gButtonArrowWidget); +- gtk_style_context_save(style); +- gtk_style_context_set_state(style, state_flags); +- gtk_widget_set_direction(gButtonArrowWidget, direction); +- +- calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect, +- direction); +- + if (direction == GTK_TEXT_DIR_RTL) { + arrow_type = (arrow_type == GTK_ARROW_LEFT) ? + GTK_ARROW_RIGHT : GTK_ARROW_LEFT; +@@ -1680,10 +1434,17 @@ moz_gtk_arrow_paint(cairo_t *cr, GdkRect + arrow_angle = ARROW_UP; + break; + } +- if (arrow_type != GTK_ARROW_NONE) +- gtk_render_arrow(style, cr, arrow_angle, +- arrow_rect.x, arrow_rect.y, arrow_rect.width); +- gtk_style_context_restore(style); ++ if (arrow_type == GTK_ARROW_NONE) ++ return MOZ_GTK_SUCCESS; ++ ++ calculate_arrow_rect(GetWidget(MOZ_GTK_BUTTON_ARROW), rect, &arrow_rect, ++ direction); ++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_BUTTON_ARROW, ++ direction, state_flags); ++ gtk_render_arrow(style, cr, arrow_angle, ++ arrow_rect.x, arrow_rect.y, arrow_rect.width); ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1776,19 +1537,10 @@ static gint + moz_gtk_toolbar_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style; +- +- ensure_toolbar_widget(); +- gtk_widget_set_direction(gToolbarWidget, direction); +- +- style = gtk_widget_get_style_context(gToolbarWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLBAR); +- ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR, direction); + 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); +- ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1798,7 +1550,6 @@ static gint + moz_gtk_toolbar_separator_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style; + gint separator_width; + gint paint_width; + gboolean wide_separators; +@@ -1807,16 +1558,14 @@ moz_gtk_toolbar_separator_paint(cairo_t + const double start_fraction = 0.2; + const double end_fraction = 0.8; + +- ensure_toolbar_separator_widget(); +- gtk_widget_set_direction(gToolbarSeparatorWidget, direction); +- +- style = gtk_widget_get_style_context(gToolbarSeparatorWidget); +- +- gtk_style_context_get_style(gtk_widget_get_style_context(gToolbarWidget), ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR); ++ gtk_style_context_get_style(style, + "wide-separators", &wide_separators, + "separator-width", &separator_width, + NULL); ++ ReleaseStyleContext(style); + ++ style = ClaimStyleContext(MOZ_GTK_TOOLBAR_SEPARATOR, direction); + if (wide_separators) { + if (separator_width > rect->width) + separator_width = rect->width; +@@ -1840,7 +1589,7 @@ moz_gtk_toolbar_separator_paint(cairo_t + rect->x + (rect->width - paint_width) / 2, + rect->y + rect->height * end_fraction); + } +- ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1848,14 +1597,10 @@ static gint + moz_gtk_tooltip_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style; +- +- ensure_tooltip_widget(); +- gtk_widget_set_direction(gTooltipWidget, direction); +- +- style = gtk_widget_get_style_context(gTooltipWidget); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLTIP, direction); + 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); ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1870,14 +1615,11 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRe + // GTK_STYLE_CLASS_VIEW to match the background with textarea elements. + // The resizer is drawn with shaded variants of the background color, and + // so a transparent background would lead to a transparent resizer. +- ensure_text_view_widget(); +- gtk_widget_set_direction(gTextViewWidget, GTK_TEXT_DIR_LTR); +- +- style = gtk_widget_get_style_context(gTextViewWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW); ++ style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW, GTK_TEXT_DIR_LTR, ++ GetStateFlagsFromGtkWidgetState(state)); ++ // TODO - we need to save/restore style when gtk 3.20 CSS node path ++ // is used + gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP); +- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state)); + + // Workaround unico not respecting the text direction for resizers. + // See bug 1174248. +@@ -1891,7 +1633,7 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRe + + gtk_render_handle(style, cr, rect->x, rect->y, rect->width, rect->height); + cairo_restore(cr); +- gtk_style_context_restore(style); ++ ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1900,16 +1642,9 @@ static gint + moz_gtk_frame_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style; +- +- ensure_frame_widget(); +- gtk_widget_set_direction(gFrameWidget, direction); +- style = gtk_widget_get_style_context(gFrameWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME); +- ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_FRAME, direction); + gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); +- gtk_style_context_restore(style); ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1917,18 +1652,11 @@ static gint + moz_gtk_progressbar_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style; +- +- ensure_progress_widget(); +- gtk_widget_set_direction(gProgressWidget, direction); +- +- style = gtk_widget_get_style_context(gProgressWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH); +- ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_PROGRESS_TROUGH, ++ direction); + 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); ++ ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1940,13 +1668,15 @@ moz_gtk_progress_chunk_paint(cairo_t *cr + { + GtkStyleContext* style; + +- ensure_progress_widget(); +- gtk_widget_set_direction(gProgressWidget, direction); +- +- style = gtk_widget_get_style_context(gProgressWidget); +- gtk_style_context_save(style); +- gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_PROGRESSBAR); ++ if (gtk_check_version(3, 20, 0) != nullptr) { ++ /* Ask for MOZ_GTK_PROGRESS_TROUGH instead of MOZ_GTK_PROGRESSBAR ++ * because ClaimStyleContext() saves/restores that style */ ++ style = ClaimStyleContext(MOZ_GTK_PROGRESS_TROUGH, direction); ++ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH); ++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_PROGRESSBAR); ++ } else { ++ style = ClaimStyleContext(MOZ_GTK_PROGRESS_CHUNK, direction); ++ } + + if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE || + widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) { +@@ -1990,7 +1720,7 @@ moz_gtk_progress_chunk_paint(cairo_t *cr + } else { + gtk_render_activity(style, cr, rect->x, rect->y, rect->width, rect->height); + } +- gtk_style_context_restore(style); ++ ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -2324,10 +2054,10 @@ moz_gtk_menu_bar_paint(cairo_t *cr, GdkR + { + GtkStyleContext* style; + +- ensure_menu_bar_widget(); +- gtk_widget_set_direction(gMenuBarWidget, direction); ++ GtkWidget* widget = GetWidget(MOZ_GTK_MENUBAR); ++ gtk_widget_set_direction(widget, direction); + +- style = gtk_widget_get_style_context(gMenuBarWidget); ++ 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); +@@ -2343,14 +2073,14 @@ moz_gtk_menu_popup_paint(cairo_t *cr, Gd + { + 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); + +@@ -2373,12 +2103,10 @@ moz_gtk_menu_separator_paint(cairo_t *cr + gint x, y, w; + GtkBorder padding; + +- ensure_menu_separator_widget(); +- gtk_widget_set_direction(gMenuSeparatorWidget, direction); +- +- border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget)); +- +- style = gtk_widget_get_style_context(gMenuSeparatorWidget); ++ border_width = ++ gtk_container_get_border_width(GTK_CONTAINER( ++ GetWidget(MOZ_GTK_MENUSEPARATOR))); ++ style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR, direction); + gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); + + x = rect->x + border_width; +@@ -2408,42 +2136,36 @@ moz_gtk_menu_separator_paint(cairo_t *cr + } + + gtk_style_context_restore(style); ++ ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } + + // See gtk_menu_item_draw() for reference. + static gint +-moz_gtk_menu_item_paint(cairo_t *cr, GdkRectangle* rect, +- GtkWidgetState* state, +- gint flags, GtkTextDirection direction) ++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 (flags & MOZ_TOPLEVEL_MENU_ITEM) { +- ensure_menu_bar_item_widget(); +- item_widget = gMenuBarItemWidget; +- } else { +- ensure_menu_item_widget(); +- item_widget = gMenuItemWidget; +- } +- style = gtk_widget_get_style_context(item_widget); +- gtk_style_context_save(style); ++ guint border_width = ++ gtk_container_get_border_width(GTK_CONTAINER(GetWidget(widget))); ++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); ++ GtkStyleContext* style = ++ ClaimStyleContext(widget, direction, state_flags); + +- if (flags & MOZ_TOPLEVEL_MENU_ITEM) { +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR); ++ 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_add_class(style, GTK_STYLE_CLASS_MENUITEM); +- 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; +@@ -2451,7 +2173,11 @@ moz_gtk_menu_item_paint(cairo_t *cr, Gdk + + gtk_render_background(style, cr, x, y, w, h); + gtk_render_frame(style, cr, x, y, w, h); +- gtk_style_context_restore(style); ++ ++ if (pre_3_6) { ++ gtk_style_context_restore(style); ++ } ++ ReleaseStyleContext(style); + } + + return MOZ_GTK_SUCCESS; +@@ -2462,21 +2188,13 @@ moz_gtk_menu_arrow_paint(cairo_t *cr, Gd + 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); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUITEM); +- gtk_style_context_set_state(style, state_flags); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_MENUITEM, ++ direction, 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); +- ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -2494,7 +2212,7 @@ moz_gtk_check_menu_item_paint(cairo_t *c + gint indicator_size, horizontal_padding; + gint x, y; + +- moz_gtk_menu_item_paint(cr, rect, state, FALSE, direction); ++ moz_gtk_menu_item_paint(MOZ_GTK_MENUITEM, cr, rect, state, direction); + + ensure_check_menu_item_widget(); + gtk_widget_set_direction(gCheckMenuItemWidget, direction); +@@ -2545,21 +2263,13 @@ static gint + moz_gtk_info_bar_paint(cairo_t *cr, GdkRectangle* rect, + GtkWidgetState* state) + { +- GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); +- GtkStyleContext *style; +- ensure_info_bar(); +- +- style = gtk_widget_get_style_context(gInfoBar); +- gtk_style_context_save(style); +- +- gtk_style_context_set_state(style, state_flags); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_INFO); +- ++ GtkStyleContext *style = ++ ClaimStyleContext(MOZ_GTK_INFO_BAR, GTK_TEXT_DIR_LTR, ++ GetStateFlagsFromGtkWidgetState(state)); + 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); ++ ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -2605,18 +2315,18 @@ moz_gtk_get_widget_border(WidgetNodeType + case MOZ_GTK_BUTTON: + case MOZ_GTK_TOOLBAR_BUTTON: + { +- ensure_button_widget(); +- style = gtk_widget_get_style_context(gButtonWidget); ++ style = ClaimStyleContext(MOZ_GTK_BUTTON); + +- *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gButtonWidget)); ++ *left = *top = *right = *bottom = ++ gtk_container_get_border_width(GTK_CONTAINER(GetWidget(MOZ_GTK_BUTTON))); + + if (widget == MOZ_GTK_TOOLBAR_BUTTON) { + gtk_style_context_save(style); + gtk_style_context_add_class(style, "image-button"); + } +- ++ + moz_gtk_add_style_padding(style, left, top, right, bottom); +- ++ + if (widget == MOZ_GTK_TOOLBAR_BUTTON) + gtk_style_context_restore(style); + +@@ -2624,12 +2334,13 @@ moz_gtk_get_widget_border(WidgetNodeType + // -moz-focus-inner border (Bug 1228281). + *left -= 1; *top -= 1; *right -= 1; *bottom -= 1; + moz_gtk_add_style_border(style, left, top, right, bottom); ++ ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_ENTRY: + { +- ensure_entry_widget(); +- style = gtk_widget_get_style_context(gEntryWidget); ++ style = ClaimStyleContext(MOZ_GTK_ENTRY); + + // XXX: Subtract 1 pixel from the padding to account for the default + // padding in forms.css. See bug 1187385. +@@ -2637,16 +2348,15 @@ moz_gtk_get_widget_border(WidgetNodeType + moz_gtk_add_style_padding(style, left, top, right, bottom); + moz_gtk_add_style_border(style, left, top, right, bottom); + ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } ++ case MOZ_GTK_TEXT_VIEW: + case MOZ_GTK_TREEVIEW: + { +- ensure_scrolled_window_widget(); +- style = gtk_widget_get_style_context(gScrolledWindowWidget); +- gtk_style_context_save(style); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME); ++ style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW); + moz_gtk_add_style_border(style, left, top, right, bottom); +- gtk_style_context_restore(style); ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_TREE_HEADER_CELL: +@@ -2726,14 +2436,12 @@ moz_gtk_get_widget_border(WidgetNodeType + w = gTabWidget; + break; + case MOZ_GTK_PROGRESSBAR: +- ensure_progress_widget(); +- w = gProgressWidget; ++ w = GetWidget(MOZ_GTK_PROGRESSBAR); + break; + case MOZ_GTK_SPINBUTTON_ENTRY: + case MOZ_GTK_SPINBUTTON_UP: + case MOZ_GTK_SPINBUTTON_DOWN: +- ensure_spin_widget(); +- w = gSpinWidget; ++ w = GetWidget(MOZ_GTK_SPINBUTTON); + break; + case MOZ_GTK_SCALE_HORIZONTAL: + ensure_scale_widget(); +@@ -2744,8 +2452,7 @@ moz_gtk_get_widget_border(WidgetNodeType + w = gVScaleWidget; + break; + case MOZ_GTK_FRAME: +- ensure_frame_widget(); +- w = gFrameWidget; ++ w = GetWidget(MOZ_GTK_FRAME); + break; + case MOZ_GTK_CHECKBUTTON_CONTAINER: + case MOZ_GTK_RADIOBUTTON_CONTAINER: +@@ -2761,19 +2468,17 @@ moz_gtk_get_widget_border(WidgetNodeType + 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_MENUITEM) { +- ensure_menu_item_widget(); +- ensure_menu_bar_item_widget(); +- w = gMenuItemWidget; +- } +- else { ++ if (widget == MOZ_GTK_MENUBARITEM || widget == MOZ_GTK_MENUITEM) { ++ // Bug 1274143 for MOZ_GTK_MENUBARITEM ++ w = GetWidget(MOZ_GTK_MENUITEM); ++ } else { + ensure_check_menu_item_widget(); + w = gCheckMenuItemWidget; + } +@@ -2784,9 +2489,16 @@ moz_gtk_get_widget_border(WidgetNodeType + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_INFO_BAR: +- ensure_info_bar(); +- w = gInfoBar; ++ w = GetWidget(MOZ_GTK_INFO_BAR); + break; ++ case MOZ_GTK_TOOLTIP: ++ { ++ style = ClaimStyleContext(MOZ_GTK_TOOLTIP); ++ moz_gtk_add_style_border(style, left, top, right, bottom); ++ moz_gtk_add_style_padding(style, left, top, right, bottom); ++ ReleaseStyleContext(style); ++ return MOZ_GTK_SUCCESS; ++ } + /* These widgets have no borders, since they are not containers. */ + case MOZ_GTK_CHECKBUTTON_LABEL: + case MOZ_GTK_RADIOBUTTON_LABEL: +@@ -2810,7 +2522,6 @@ moz_gtk_get_widget_border(WidgetNodeType + case MOZ_GTK_MENUSEPARATOR: + /* These widgets have no borders.*/ + case MOZ_GTK_SPINBUTTON: +- case MOZ_GTK_TOOLTIP: + case MOZ_GTK_WINDOW: + case MOZ_GTK_RESIZER: + case MOZ_GTK_MENUARROW: +@@ -2908,8 +2619,7 @@ moz_gtk_get_arrow_size(WidgetNodeType wi + widget = gComboBoxArrowWidget; + break; + default: +- ensure_button_arrow_widget(); +- widget = gButtonArrowWidget; ++ widget = GetWidget(MOZ_GTK_BUTTON_ARROW); + break; + } + +@@ -2924,11 +2634,9 @@ moz_gtk_get_toolbar_separator_width(gint + { + gboolean wide_separators; + gint separator_width; +- GtkStyleContext* style; + GtkBorder border; + +- ensure_toolbar_widget(); +- style = gtk_widget_get_style_context(gToolbarWidget); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR); + gtk_style_context_get_style(style, + "space-size", size, + "wide-separators", &wide_separators, +@@ -2937,17 +2645,18 @@ moz_gtk_get_toolbar_separator_width(gint + /* Just in case... */ + gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); + *size = MAX(*size, (wide_separators ? separator_width : border.left)); ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + + gint + moz_gtk_get_expander_size(gint* size) + { +- ensure_expander_widget(); +- gtk_style_context_get_style(gtk_widget_get_style_context(gExpanderWidget), ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_EXPANDER); ++ gtk_style_context_get_style(style, + "expander-size", size, + NULL); +- ++ ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -2972,11 +2681,11 @@ moz_gtk_get_menu_separator_height(gint * + GtkStyleContext* style; + guint border_width; + +- ensure_menu_separator_widget(); +- +- border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget)); ++ border_width = ++ gtk_container_get_border_width(GTK_CONTAINER( ++ GetWidget(MOZ_GTK_MENUSEPARATOR))); + +- style = gtk_widget_get_style_context(gMenuSeparatorWidget); ++ style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR); + gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); + + gtk_style_context_save(style); +@@ -2988,6 +2697,7 @@ moz_gtk_get_menu_separator_height(gint * + NULL); + + gtk_style_context_restore(style); ++ ReleaseStyleContext(style); + + *size = padding.top + padding.bottom + border_width*2; + *size += (wide_separators) ? separator_height : 1; +@@ -2998,8 +2708,7 @@ moz_gtk_get_menu_separator_height(gint * + void + moz_gtk_get_entry_min_height(gint* height) + { +- ensure_entry_widget(); +- GtkStyleContext* style = gtk_widget_get_style_context(gEntryWidget); ++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_ENTRY); + if (!gtk_check_version(3, 20, 0)) { + gtk_style_context_get(style, gtk_style_context_get_state(style), + "min-height", height, +@@ -3014,6 +2723,7 @@ moz_gtk_get_entry_min_height(gint* heigh + gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); + + *height += (border.top + border.bottom + padding.top + padding.bottom); ++ ReleaseStyleContext(style); + } + + void +@@ -3094,8 +2804,7 @@ moz_gtk_images_in_buttons() + gboolean result; + GtkSettings* settings; + +- ensure_button_widget(); +- settings = gtk_widget_get_settings(gButtonWidget); ++ settings = gtk_widget_get_settings(GetWidget(MOZ_GTK_BUTTON)); + + g_object_get(settings, "gtk-button-images", &result, NULL); + return result; +@@ -3116,14 +2825,14 @@ moz_gtk_widget_paint(WidgetNodeType widg + case MOZ_GTK_BUTTON: + case MOZ_GTK_TOOLBAR_BUTTON: + if (state->depressed) { +- ensure_toggle_button_widget(); + return moz_gtk_button_paint(cr, rect, state, + (GtkReliefStyle) flags, +- gToggleButtonWidget, direction); ++ GetWidget(MOZ_GTK_TOGGLE_BUTTON), ++ direction); + } +- ensure_button_widget(); + return moz_gtk_button_paint(cr, rect, state, +- (GtkReliefStyle) flags, gButtonWidget, ++ (GtkReliefStyle) flags, ++ GetWidget(MOZ_GTK_BUTTON), + direction); + break; + case MOZ_GTK_CHECKBUTTON: +@@ -3171,9 +2880,9 @@ moz_gtk_widget_paint(WidgetNodeType widg + state, direction); + break; + case MOZ_GTK_SPINBUTTON_ENTRY: +- ensure_spin_widget(); ++ // TODO - use MOZ_GTK_SPINBUTTON_ENTRY style directly + return moz_gtk_entry_paint(cr, rect, state, +- gSpinWidget, direction); ++ GetWidget(MOZ_GTK_SPINBUTTON), direction); + break; + case MOZ_GTK_GRIPPER: + return moz_gtk_gripper_paint(cr, rect, state, +@@ -3198,9 +2907,11 @@ moz_gtk_widget_paint(WidgetNodeType widg + (GtkExpanderStyle) flags, direction); + break; + case MOZ_GTK_ENTRY: +- ensure_entry_widget(); +- return moz_gtk_entry_paint(cr, rect, state, +- gEntryWidget, direction); ++ return moz_gtk_entry_paint(cr, rect, state, GetWidget(MOZ_GTK_ENTRY), ++ direction); ++ break; ++ case MOZ_GTK_TEXT_VIEW: ++ return moz_gtk_text_view_paint(cr, rect, state, direction); + break; + case MOZ_GTK_DROPDOWN: + return moz_gtk_combo_box_paint(cr, rect, state, direction); +@@ -3271,9 +2982,9 @@ moz_gtk_widget_paint(WidgetNodeType widg + return moz_gtk_menu_separator_paint(cr, rect, + direction); + break; ++ case MOZ_GTK_MENUBARITEM: + case MOZ_GTK_MENUITEM: +- return moz_gtk_menu_item_paint(cr, rect, state, flags, +- direction); ++ return moz_gtk_menu_item_paint(widget, cr, rect, state, direction); + break; + case MOZ_GTK_MENUARROW: + return moz_gtk_menu_arrow_paint(cr, rect, state, +@@ -3333,25 +3044,16 @@ gboolean moz_gtk_has_scrollbar_buttons(v + gint + moz_gtk_shutdown() + { +- if (gTooltipWidget) +- gtk_widget_destroy(gTooltipWidget); + /* This will destroy all of our widgets */ +- + ResetWidgetCache(); + + /* TODO - replace it with appropriate widget */ + if (gTreeHeaderSortArrowWidget) + gtk_widget_destroy(gTreeHeaderSortArrowWidget); + +- gProtoWindow = NULL; + gProtoLayout = NULL; +- gButtonWidget = NULL; +- gToggleButtonWidget = NULL; +- gButtonArrowWidget = NULL; +- gSpinWidget = NULL; + gHScaleWidget = NULL; + gVScaleWidget = NULL; +- gEntryWidget = NULL; + gComboBoxWidget = NULL; + gComboBoxButtonWidget = NULL; + gComboBoxSeparatorWidget = NULL; +@@ -3360,29 +3062,15 @@ moz_gtk_shutdown() + gComboBoxEntryButtonWidget = NULL; + gComboBoxEntryArrowWidget = NULL; + 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; +- gMenuSeparatorWidget = NULL; + gHPanedWidget = NULL; + gVPanedWidget = NULL; +- gScrolledWindowWidget = NULL; + + is_initialized = FALSE; + +diff -up firefox-48.0/widget/gtk/gtkdrawing.h.gtk3-20 firefox-48.0/widget/gtk/gtkdrawing.h +--- firefox-48.0/widget/gtk/gtkdrawing.h.gtk3-20 2016-07-25 22:22:07.000000000 +0200 ++++ firefox-48.0/widget/gtk/gtkdrawing.h 2016-07-29 09:15:11.822285857 +0200 +@@ -69,12 +69,6 @@ typedef enum { + MOZ_GTK_TAB_SELECTED = 1 << 10 + } GtkTabFlags; + +-/** flags for menuitems **/ +-typedef enum { +- /* menuitem is part of the menubar */ +- MOZ_TOPLEVEL_MENU_ITEM = 1 << 0 +-} GtkMenuItemFlags; +- + /* function type for moz_gtk_enable_style_props */ + typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint); + +@@ -93,6 +87,10 @@ typedef enum { + MOZ_GTK_BUTTON, + /* Paints a button with image and no text */ + MOZ_GTK_TOOLBAR_BUTTON, ++ /* Paints a toggle button */ ++ MOZ_GTK_TOGGLE_BUTTON, ++ /* Paints a button arrow */ ++ MOZ_GTK_BUTTON_ARROW, + + /* Paints the container part of a GtkCheckButton. */ + MOZ_GTK_CHECKBUTTON_CONTAINER, +@@ -115,6 +113,7 @@ typedef enum { + + /* Horizontal GtkScrollbar counterparts */ + MOZ_GTK_SCROLLBAR_HORIZONTAL, ++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL, + /* Paints the trough (track) of a GtkScrollbar. */ + MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL, + /* Paints the slider (thumb) of a GtkScrollbar. */ +@@ -122,6 +121,7 @@ typedef enum { + + /* Vertical GtkScrollbar counterparts */ + MOZ_GTK_SCROLLBAR_VERTICAL, ++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL, + MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL, + MOZ_GTK_SCROLLBAR_THUMB_VERTICAL, + +@@ -140,6 +140,10 @@ typedef enum { + MOZ_GTK_GRIPPER, + /* Paints a GtkEntry. */ + MOZ_GTK_ENTRY, ++ /* Paints a GtkExpander. */ ++ MOZ_GTK_EXPANDER, ++ /* Paints a GtkTextView. */ ++ MOZ_GTK_TEXT_VIEW, + /* Paints a GtkOptionMenu. */ + MOZ_GTK_DROPDOWN, + /* Paints a dropdown arrow (a GtkButton containing a down GtkArrow). */ +@@ -159,6 +163,8 @@ typedef enum { + MOZ_GTK_RESIZER, + /* Paints a GtkProgressBar. */ + MOZ_GTK_PROGRESSBAR, ++ /* Paints a trough (track) of a GtkProgressBar */ ++ MOZ_GTK_PROGRESS_TROUGH, + /* Paints a progress chunk of a GtkProgressBar. */ + MOZ_GTK_PROGRESS_CHUNK, + /* Paints a progress chunk of an indeterminated GtkProgressBar. */ +@@ -187,7 +193,9 @@ typedef enum { + MOZ_GTK_MENUARROW, + /* Paints an arrow in a toolbar button. flags is a GtkArrowType. */ + MOZ_GTK_TOOLBARBUTTON_ARROW, +- /* Paints items of menubar and popups. */ ++ /* Paints items of menubar. */ ++ MOZ_GTK_MENUBARITEM, ++ /* Paints items of popup menus. */ + MOZ_GTK_MENUITEM, + MOZ_GTK_CHECKMENUITEM, + MOZ_GTK_RADIOMENUITEM, +@@ -202,6 +210,8 @@ typedef enum { + MOZ_GTK_WINDOW_CONTAINER, + /* Paints a GtkInfoBar, for notifications. */ + MOZ_GTK_INFO_BAR, ++ /* Used for scrolled window shell. */ ++ MOZ_GTK_SCROLLED_WINDOW, + + MOZ_GTK_WIDGET_NODE_COUNT + } WidgetNodeType; +diff -up firefox-48.0/widget/gtk/mozgtk/mozgtk.c.gtk3-20 firefox-48.0/widget/gtk/mozgtk/mozgtk.c +--- firefox-48.0/widget/gtk/mozgtk/mozgtk.c.gtk3-20 2016-07-25 22:22:07.000000000 +0200 ++++ firefox-48.0/widget/gtk/mozgtk/mozgtk.c 2016-07-29 09:15:11.823285862 +0200 +@@ -517,6 +517,7 @@ STUB(gdk_event_get_source_device) + STUB(gdk_window_get_type) + STUB(gdk_x11_window_get_xid) + STUB(gdk_x11_display_get_type) ++STUB(gtk_box_new) + STUB(gtk_cairo_should_draw_window) + STUB(gtk_cairo_transform_to_window) + STUB(gtk_combo_box_text_append) +@@ -570,6 +571,7 @@ STUB(gtk_tree_view_column_get_button) + STUB(gtk_widget_get_preferred_size) + STUB(gtk_widget_get_state_flags) + STUB(gtk_widget_get_style_context) ++STUB(gtk_widget_path_append_for_widget) + STUB(gtk_widget_path_append_type) + STUB(gtk_widget_path_copy) + STUB(gtk_widget_path_free) +@@ -587,6 +589,10 @@ STUB(gtk_color_chooser_get_type) + STUB(gtk_color_chooser_set_rgba) + STUB(gtk_color_chooser_get_rgba) + STUB(gtk_color_chooser_set_use_alpha) ++STUB(gtk_check_menu_item_new) ++STUB(gtk_style_context_get_direction) ++STUB(gtk_style_context_invalidate) ++STUB(gtk_tooltip_get_type) + #endif + + #ifdef GTK2_SYMBOLS +diff -up firefox-48.0/widget/gtk/nsLookAndFeel.cpp.gtk3-20 firefox-48.0/widget/gtk/nsLookAndFeel.cpp +--- firefox-48.0/widget/gtk/nsLookAndFeel.cpp.gtk3-20 2016-06-01 06:11:44.000000000 +0200 ++++ firefox-48.0/widget/gtk/nsLookAndFeel.cpp 2016-07-29 09:15:54.943459700 +0200 +@@ -31,6 +31,7 @@ + + #if MOZ_WIDGET_GTK != 2 + #include <cairo-gobject.h> ++#include "WidgetStyleCache.h" + #endif + + using mozilla::LookAndFeel; +@@ -1135,15 +1136,24 @@ nsLookAndFeel::Init() + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMozWindowText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); ++ g_object_unref(style); + + // tooltip foreground and background +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP); +- gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND); ++ style = ClaimStyleContext(MOZ_GTK_TOOLTIP); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + sInfoBackground = GDK_RGBA_TO_NS_RGBA(color); +- gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); ++ { ++ GtkStyleContext* boxStyle = ++ CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), ++ style); ++ GtkStyleContext* labelStyle = ++ CreateStyleForWidget(gtk_label_new(nullptr), boxStyle); ++ gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_NORMAL, &color); ++ g_object_unref(labelStyle); ++ g_object_unref(boxStyle); ++ } + sInfoText = GDK_RGBA_TO_NS_RGBA(color); +- g_object_unref(style); ++ ReleaseStyleContext(style); + + // menu foreground & menu background + GtkWidget *accel_label = gtk_accel_label_new("M"); +diff -up firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20 firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp +--- firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20 2016-07-25 22:22:07.000000000 +0200 ++++ firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp 2016-07-29 09:15:11.824285865 +0200 +@@ -354,10 +354,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + + if (isTopLevel) { + aState->inHover = menuFrame->IsOpen(); +- *aWidgetFlags |= MOZ_TOPLEVEL_MENU_ITEM; + } else { + aState->inHover = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive); +- *aWidgetFlags &= ~MOZ_TOPLEVEL_MENU_ITEM; + } + + aState->active = FALSE; +@@ -510,8 +508,14 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + break; + case NS_THEME_NUMBER_INPUT: + case NS_THEME_TEXTFIELD: ++ aGtkWidgetType = MOZ_GTK_ENTRY; ++ break; + case NS_THEME_TEXTFIELD_MULTILINE: ++#if (MOZ_WIDGET_GTK == 3) ++ aGtkWidgetType = MOZ_GTK_TEXT_VIEW; ++#else + aGtkWidgetType = MOZ_GTK_ENTRY; ++#endif + break; + case NS_THEME_LISTBOX: + case NS_THEME_TREEVIEW: +@@ -673,6 +677,13 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u + aGtkWidgetType = MOZ_GTK_MENUPOPUP; + break; + case NS_THEME_MENUITEM: ++ { ++ nsMenuFrame *menuFrame = do_QueryFrame(aFrame); ++ if (menuFrame && menuFrame->IsOnMenuBar()) { ++ aGtkWidgetType = MOZ_GTK_MENUBARITEM; ++ break; ++ } ++ } + aGtkWidgetType = MOZ_GTK_MENUITEM; + break; + case NS_THEME_MENUSEPARATOR: +diff -up firefox-48.0/widget/gtk/WidgetStyleCache.cpp.gtk3-20 firefox-48.0/widget/gtk/WidgetStyleCache.cpp +--- firefox-48.0/widget/gtk/WidgetStyleCache.cpp.gtk3-20 2016-07-25 22:22:07.000000000 +0200 ++++ firefox-48.0/widget/gtk/WidgetStyleCache.cpp 2016-07-29 09:15:11.825285869 +0200 +@@ -22,7 +22,7 @@ static bool sStyleContextNeedsRestore; + static GtkStyleContext* sCurrentStyleContext; + #endif + static GtkStyleContext* +-GetStyleInternal(WidgetNodeType aNodeType); ++GetCssNodeStyleInternal(WidgetNodeType aNodeType); + + static GtkWidget* + CreateWindowWidget() +@@ -67,12 +67,175 @@ CreateCheckboxWidget() + static GtkWidget* + CreateRadiobuttonWidget() + { +- GtkWidget* widget = gtk_radio_button_new_with_label(NULL, "M"); ++ GtkWidget* widget = gtk_radio_button_new_with_label(nullptr, "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* ++CreateProgressWidget() ++{ ++ GtkWidget* widget = gtk_progress_bar_new(); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateTooltipWidget() ++{ ++ MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr, ++ "CreateTooltipWidget should be used for Gtk < 3.20 only."); ++ GtkWidget* widget = CreateWindowWidget(); ++ GtkStyleContext* style = gtk_widget_get_style_context(widget); ++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP); ++ return widget; ++} ++ ++static GtkWidget* ++CreateExpanderWidget() ++{ ++ GtkWidget* widget = gtk_expander_new("M"); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateFrameWidget() ++{ ++ GtkWidget* widget = gtk_frame_new(nullptr); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateGripperWidget() ++{ ++ GtkWidget* widget = gtk_handle_box_new(); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateToolbarWidget() ++{ ++ GtkWidget* widget = gtk_toolbar_new(); ++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_GRIPPER)), widget); ++ gtk_widget_realize(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateToolbarSeparatorWidget() ++{ ++ GtkWidget* widget = GTK_WIDGET(gtk_separator_tool_item_new()); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateInfoBarWidget() ++{ ++ GtkWidget* widget = gtk_info_bar_new(); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateButtonWidget() ++{ ++ GtkWidget* widget = gtk_button_new_with_label("M"); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateToggleButtonWidget() ++{ ++ GtkWidget* widget = gtk_toggle_button_new(); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateButtonArrowWidget() ++{ ++ GtkWidget* widget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); ++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_TOGGLE_BUTTON)), widget); ++ gtk_widget_realize(widget); ++ gtk_widget_show(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateSpinWidget() ++{ ++ GtkWidget* widget = gtk_spin_button_new(nullptr, 1, 0); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateEntryWidget() ++{ ++ GtkWidget* widget = gtk_entry_new(); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateScrolledWindowWidget() ++{ ++ GtkWidget* widget = gtk_scrolled_window_new(nullptr, nullptr); ++ AddToWindowContainer(widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateTextViewWidget() ++{ ++ GtkWidget* widget = gtk_text_view_new(); ++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_SCROLLED_WINDOW)), ++ widget); ++ return widget; ++} ++ ++static GtkWidget* ++CreateMenuSeparatorWidget() ++{ ++ GtkWidget* widget = gtk_separator_menu_item_new(); ++ gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)), ++ widget); ++ gtk_widget_realize(widget); ++ return widget; ++} ++ ++ ++static GtkWidget* + CreateWidget(WidgetNodeType aWidgetType) + { + switch (aWidgetType) { +@@ -80,16 +243,54 @@ CreateWidget(WidgetNodeType aWidgetType) + return CreateWindowWidget(); + case MOZ_GTK_WINDOW_CONTAINER: + return CreateWindowContainerWidget(); ++ case MOZ_GTK_CHECKBUTTON_CONTAINER: ++ return CreateCheckboxWidget(); ++ case MOZ_GTK_PROGRESSBAR: ++ return CreateProgressWidget(); ++ case MOZ_GTK_RADIOBUTTON_CONTAINER: ++ return CreateRadiobuttonWidget(); + case MOZ_GTK_SCROLLBAR_HORIZONTAL: + return CreateScrollbarWidget(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); ++ case MOZ_GTK_MENUSEPARATOR: ++ return CreateMenuSeparatorWidget(); ++ case MOZ_GTK_EXPANDER: ++ return CreateExpanderWidget(); ++ case MOZ_GTK_FRAME: ++ return CreateFrameWidget(); ++ case MOZ_GTK_GRIPPER: ++ return CreateGripperWidget(); ++ case MOZ_GTK_TOOLBAR: ++ return CreateToolbarWidget(); ++ case MOZ_GTK_TOOLBAR_SEPARATOR: ++ return CreateToolbarSeparatorWidget(); ++ case MOZ_GTK_INFO_BAR: ++ return CreateInfoBarWidget(); ++ case MOZ_GTK_SPINBUTTON: ++ return CreateSpinWidget(); ++ case MOZ_GTK_BUTTON: ++ return CreateButtonWidget(); ++ case MOZ_GTK_TOGGLE_BUTTON: ++ return CreateToggleButtonWidget(); ++ case MOZ_GTK_BUTTON_ARROW: ++ return CreateButtonArrowWidget(); ++ case MOZ_GTK_ENTRY: ++ return CreateEntryWidget(); ++ case MOZ_GTK_SCROLLED_WINDOW: ++ return CreateScrolledWindowWidget(); ++ case MOZ_GTK_TEXT_VIEW: ++ return CreateTextViewWidget(); + default: + /* Not implemented */ + return nullptr; +@@ -107,17 +308,42 @@ GetWidget(WidgetNodeType aWidgetType) + return widget; + } + +-static GtkStyleContext* +-CreateCSSNode(const char* aName, GtkStyleContext *aParentStyle) ++GtkStyleContext* ++CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle) ++{ ++ GtkWidgetPath* path = aParentStyle ? ++ gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) : ++ gtk_widget_path_new(); ++ ++ // Work around https://bugzilla.gnome.org/show_bug.cgi?id=767312 ++ // which exists in GTK+ 3.20. ++ gtk_widget_get_style_context(aWidget); ++ ++ gtk_widget_path_append_for_widget(path, aWidget); ++ // Release any floating reference on aWidget. ++ g_object_ref_sink(aWidget); ++ g_object_unref(aWidget); ++ ++ GtkStyleContext *context = gtk_style_context_new(); ++ gtk_style_context_set_path(context, path); ++ gtk_style_context_set_parent(context, aParentStyle); ++ gtk_widget_path_unref(path); ++ ++ return context; ++} ++ ++GtkStyleContext* ++CreateCSSNode(const char* aName, GtkStyleContext* aParentStyle, GType aType) + { + static auto sGtkWidgetPathIterSetObjectName = + reinterpret_cast<void (*)(GtkWidgetPath *, gint, const char *)> + (dlsym(RTLD_DEFAULT, "gtk_widget_path_iter_set_object_name")); + +- GtkWidgetPath* path = +- gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)); ++ GtkWidgetPath* path = aParentStyle ? ++ gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) : ++ gtk_widget_path_new(); + +- gtk_widget_path_append_type(path, G_TYPE_NONE); ++ gtk_widget_path_append_type(path, aType); + + (*sGtkWidgetPathIterSetObjectName)(path, -1, aName); + +@@ -130,95 +356,168 @@ CreateCSSNode(const char* aName, GtkStyl + } + + static GtkStyleContext* +-GetChildNodeStyle(WidgetNodeType aStyleType, +- WidgetNodeType aWidgetType, +- const gchar* aStyleClass, +- WidgetNodeType aParentNodeType) ++CreateChildCSSNode(const char* aName, WidgetNodeType aParentNodeType) + { +- GtkStyleContext* style; +- +- if (gtk_check_version(3, 20, 0) != nullptr) { +- style = gtk_widget_get_style_context(sWidgetStorage[aWidgetType]); +- +- gtk_style_context_save(style); +- MOZ_ASSERT(!sStyleContextNeedsRestore); +- sStyleContextNeedsRestore = true; +- +- gtk_style_context_add_class(style, aStyleClass); +- } +- else { +- style = sStyleStorage[aStyleType]; +- if (!style) { +- style = CreateCSSNode(aStyleClass, GetStyleInternal(aParentNodeType)); +- MOZ_ASSERT(!sStyleContextNeedsRestore); +- sStyleStorage[aStyleType] = style; +- } +- } ++ return CreateCSSNode(aName, GetCssNodeStyleInternal(aParentNodeType)); ++} + ++static GtkStyleContext* ++GetWidgetStyleWithClass(WidgetNodeType aWidgetType, const gchar* aStyleClass) ++{ ++ GtkStyleContext* style = gtk_widget_get_style_context(GetWidget(aWidgetType)); ++ gtk_style_context_save(style); ++ MOZ_ASSERT(!sStyleContextNeedsRestore); ++ sStyleContextNeedsRestore = true; ++ gtk_style_context_add_class(style, aStyleClass); + return style; + } + ++/* GetCssNodeStyleInternal is used by Gtk >= 3.20 */ + static GtkStyleContext* +-GetStyleInternal(WidgetNodeType aNodeType) ++GetCssNodeStyleInternal(WidgetNodeType aNodeType) + { ++ GtkStyleContext* style = sStyleStorage[aNodeType]; ++ if (style) ++ return style; ++ + switch (aNodeType) { +- case MOZ_GTK_SCROLLBAR_HORIZONTAL: +- /* Root CSS node / widget for scrollbars */ ++ case MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL: ++ style = CreateChildCSSNode("contents", ++ MOZ_GTK_SCROLLBAR_HORIZONTAL); + break; + case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL: +- return GetChildNodeStyle(aNodeType, +- MOZ_GTK_SCROLLBAR_HORIZONTAL, +- GTK_STYLE_CLASS_TROUGH, +- MOZ_GTK_SCROLLBAR_HORIZONTAL); +- ++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH, ++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL); ++ break; + case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: +- return GetChildNodeStyle(aNodeType, +- MOZ_GTK_SCROLLBAR_HORIZONTAL, +- GTK_STYLE_CLASS_SLIDER, +- MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL); +- +- case MOZ_GTK_SCROLLBAR_VERTICAL: +- /* Root CSS node / widget for scrollbars */ ++ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER, ++ MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL); ++ break; ++ case MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL: ++ style = CreateChildCSSNode("contents", ++ MOZ_GTK_SCROLLBAR_VERTICAL); + break; + case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL: +- return GetChildNodeStyle(aNodeType, +- MOZ_GTK_SCROLLBAR_VERTICAL, +- GTK_STYLE_CLASS_TROUGH, +- MOZ_GTK_SCROLLBAR_VERTICAL); +- ++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH, ++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL); ++ break; + case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL: +- return GetChildNodeStyle(aNodeType, +- MOZ_GTK_SCROLLBAR_VERTICAL, +- GTK_STYLE_CLASS_SLIDER, +- MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL); +- +- case MOZ_GTK_RADIOBUTTON_CONTAINER: +- /* Root CSS node / widget for checkboxes */ ++ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER, ++ MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL); + break; + case MOZ_GTK_RADIOBUTTON: +- return GetChildNodeStyle(aNodeType, +- MOZ_GTK_RADIOBUTTON_CONTAINER, +- GTK_STYLE_CLASS_RADIO, +- MOZ_GTK_RADIOBUTTON_CONTAINER); +- case MOZ_GTK_CHECKBUTTON_CONTAINER: +- /* Root CSS node / widget for radiobuttons */ ++ style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO, ++ MOZ_GTK_RADIOBUTTON_CONTAINER); + break; + case MOZ_GTK_CHECKBUTTON: +- return GetChildNodeStyle(aNodeType, +- MOZ_GTK_CHECKBUTTON_CONTAINER, +- GTK_STYLE_CLASS_CHECK, +- MOZ_GTK_CHECKBUTTON_CONTAINER); +- default: ++ style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK, ++ MOZ_GTK_CHECKBUTTON_CONTAINER); ++ break; ++ case MOZ_GTK_PROGRESS_TROUGH: ++ /* Progress bar background (trough) */ ++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH, ++ MOZ_GTK_PROGRESSBAR); ++ break; ++ case MOZ_GTK_PROGRESS_CHUNK: ++ style = CreateChildCSSNode("progress", ++ MOZ_GTK_PROGRESS_TROUGH); + break; ++ case MOZ_GTK_TOOLTIP: ++ // We create this from the path because GtkTooltipWindow is not public. ++ style = CreateCSSNode("tooltip", nullptr, GTK_TYPE_TOOLTIP); ++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND); ++ break; ++ case MOZ_GTK_GRIPPER: ++ // TODO - create from CSS node ++ return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER, ++ GTK_STYLE_CLASS_GRIP); ++ case MOZ_GTK_INFO_BAR: ++ // TODO - create from CSS node ++ return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR, ++ GTK_STYLE_CLASS_INFO); ++ case MOZ_GTK_SPINBUTTON_ENTRY: ++ // TODO - create from CSS node ++ return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON, ++ GTK_STYLE_CLASS_ENTRY); ++ case MOZ_GTK_SCROLLED_WINDOW: ++ // TODO - create from CSS node ++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW, ++ GTK_STYLE_CLASS_FRAME); ++ case MOZ_GTK_TEXT_VIEW: ++ // TODO - create from CSS node ++ return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW, ++ GTK_STYLE_CLASS_VIEW); ++ default: ++ // TODO - create style from style path ++ GtkWidget* widget = GetWidget(aNodeType); ++ return gtk_widget_get_style_context(widget); + } + +- GtkWidget* widget = GetWidget(aNodeType); +- if (widget) { +- return gtk_widget_get_style_context(widget); +- } ++ MOZ_ASSERT(style, "missing style context for node type"); ++ sStyleStorage[aNodeType] = style; ++ return style; ++} + +- MOZ_ASSERT_UNREACHABLE("missing style context for node type"); +- return nullptr; ++/* GetWidgetStyleInternal is used by Gtk < 3.20 */ ++static GtkStyleContext* ++GetWidgetStyleInternal(WidgetNodeType aNodeType) ++{ ++ switch (aNodeType) { ++ case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL: ++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL, ++ GTK_STYLE_CLASS_TROUGH); ++ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: ++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL, ++ GTK_STYLE_CLASS_SLIDER); ++ case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL: ++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL, ++ GTK_STYLE_CLASS_TROUGH); ++ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL: ++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL, ++ GTK_STYLE_CLASS_SLIDER); ++ case MOZ_GTK_RADIOBUTTON: ++ return GetWidgetStyleWithClass(MOZ_GTK_RADIOBUTTON_CONTAINER, ++ GTK_STYLE_CLASS_RADIO); ++ case MOZ_GTK_CHECKBUTTON: ++ return GetWidgetStyleWithClass(MOZ_GTK_CHECKBUTTON_CONTAINER, ++ GTK_STYLE_CLASS_CHECK); ++ case MOZ_GTK_PROGRESS_TROUGH: ++ return GetWidgetStyleWithClass(MOZ_GTK_PROGRESSBAR, ++ GTK_STYLE_CLASS_TROUGH); ++ case MOZ_GTK_TOOLTIP: { ++ GtkStyleContext* style = sStyleStorage[aNodeType]; ++ if (style) ++ return style; ++ ++ // The tooltip style class is added first in CreateTooltipWidget() so ++ // that gtk_widget_path_append_for_widget() in CreateStyleForWidget() ++ // will find it. ++ GtkWidget* tooltipWindow = CreateTooltipWidget(); ++ style = CreateStyleForWidget(tooltipWindow, nullptr); ++ gtk_widget_destroy(tooltipWindow); // Release GtkWindow self-reference. ++ sStyleStorage[aNodeType] = style; ++ return style; ++ } ++ case MOZ_GTK_GRIPPER: ++ return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER, ++ GTK_STYLE_CLASS_GRIP); ++ case MOZ_GTK_INFO_BAR: ++ return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR, ++ GTK_STYLE_CLASS_INFO); ++ case MOZ_GTK_SPINBUTTON_ENTRY: ++ return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON, ++ GTK_STYLE_CLASS_ENTRY); ++ case MOZ_GTK_SCROLLED_WINDOW: ++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW, ++ GTK_STYLE_CLASS_FRAME); ++ case MOZ_GTK_TEXT_VIEW: ++ return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW, ++ GTK_STYLE_CLASS_VIEW); ++ default: ++ GtkWidget* widget = GetWidget(aNodeType); ++ MOZ_ASSERT(widget); ++ return gtk_widget_get_style_context(widget); ++ } + } + + void +@@ -245,13 +544,39 @@ ResetWidgetCache(void) + + GtkStyleContext* + ClaimStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection, +- StyleFlags aFlags) ++ GtkStateFlags aStateFlags, StyleFlags aFlags) + { +- GtkStyleContext* style = GetStyleInternal(aNodeType); ++ MOZ_ASSERT(!sStyleContextNeedsRestore); ++ GtkStyleContext* style; ++ if (gtk_check_version(3, 20, 0) != nullptr) { ++ style = GetWidgetStyleInternal(aNodeType); ++ } else { ++ style = GetCssNodeStyleInternal(aNodeType); ++ } + #ifdef DEBUG + MOZ_ASSERT(!sCurrentStyleContext); + sCurrentStyleContext = style; + #endif ++ GtkStateFlags oldState = gtk_style_context_get_state(style); ++ GtkTextDirection oldDirection = gtk_style_context_get_direction(style); ++ if (oldState != aStateFlags || oldDirection != aDirection) { ++ // From GTK 3.8, set_state() will overwrite the direction, so set ++ // direction after state. ++ gtk_style_context_set_state(style, aStateFlags); ++ gtk_style_context_set_direction(style, aDirection); ++ ++ // This invalidate is necessary for unsaved style contexts from GtkWidgets ++ // in pre-3.18 GTK, because automatic invalidation of such contexts ++ // was delayed until a resize event runs. ++ // ++ // https://bugzilla.mozilla.org/show_bug.cgi?id=1272194#c7 ++ // ++ // Avoid calling invalidate on saved contexts to avoid performing ++ // build_properties() (in 3.16 stylecontext.c) unnecessarily early. ++ if (!sStyleContextNeedsRestore) { ++ gtk_style_context_invalidate(style); ++ } ++ } + return style; + } + +diff -up firefox-48.0/widget/gtk/WidgetStyleCache.h.gtk3-20 firefox-48.0/widget/gtk/WidgetStyleCache.h +--- firefox-48.0/widget/gtk/WidgetStyleCache.h.gtk3-20 2016-07-25 22:22:07.000000000 +0200 ++++ firefox-48.0/widget/gtk/WidgetStyleCache.h 2016-07-29 09:15:11.825285869 +0200 +@@ -21,10 +21,24 @@ enum : StyleFlags { + GtkWidget* + GetWidget(WidgetNodeType aNodeType); + ++/* ++ * Return a new style context based on aWidget, as a child of aParentStyle. ++ * If aWidget still has a floating reference, then it is sunk and released. ++ */ ++GtkStyleContext* ++CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle); ++ ++// CreateCSSNode is implemented for gtk >= 3.20 only. ++GtkStyleContext* ++CreateCSSNode(const char* aName, ++ GtkStyleContext* aParentStyle, ++ GType aType = G_TYPE_NONE); ++ + // Callers must call ReleaseStyleContext() on the returned context. + GtkStyleContext* + ClaimStyleContext(WidgetNodeType aNodeType, + GtkTextDirection aDirection = GTK_TEXT_DIR_LTR, ++ GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL, + StyleFlags aFlags = NO_STYLE_FLAGS); + void + ReleaseStyleContext(GtkStyleContext* style); |