diff options
Diffstat (limited to 'widget-rebase.patch')
-rw-r--r-- | widget-rebase.patch | 1747 |
1 files changed, 725 insertions, 1022 deletions
diff --git a/widget-rebase.patch b/widget-rebase.patch index 45a3b91..59cc4a1 100644 --- a/widget-rebase.patch +++ b/widget-rebase.patch @@ -1,454 +1,297 @@ -diff -up firefox-52.0/widget/gtk/gtk3drawing.cpp.widget-rebase firefox-52.0/widget/gtk/gtk3drawing.cpp ---- firefox-52.0/widget/gtk/gtk3drawing.cpp.widget-rebase 2017-02-27 17:11:05.000000000 +0100 -+++ firefox-52.0/widget/gtk/gtk3drawing.cpp 2017-03-10 12:20:30.232205991 +0100 -@@ -36,6 +36,10 @@ static gboolean is_initialized; - static gint - moz_gtk_get_tab_thickness(GtkStyleContext *style); +diff -up firefox-53.0/widget/gtk/gtk3drawing.cpp.widget-rebase firefox-53.0/widget/gtk/gtk3drawing.cpp +--- firefox-53.0/widget/gtk/gtk3drawing.cpp.widget-rebase 2017-04-11 06:15:20.000000000 +0200 ++++ firefox-53.0/widget/gtk/gtk3drawing.cpp 2017-04-18 10:22:45.332920938 +0200 +@@ -18,11 +18,10 @@ + + #include <math.h> + +-static style_prop_t style_prop_func; +-static gboolean have_arrow_scaling; + static gboolean checkbox_check_state; + static gboolean notebook_has_tab_gap; +-static gboolean is_initialized; ++ ++static ScrollbarGTKMetrics sScrollbarMetrics[2]; + + #define ARROW_UP 0 + #define ARROW_DOWN G_PI +@@ -40,6 +39,9 @@ static gint + moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect, + GtkWidgetState* state, GtkTextDirection direction); -+static gint -+moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect, -+ GtkWidgetState* state, GtkTextDirection direction); ++static GtkBorder ++GetMarginBorderPadding(GtkStyleContext* aStyle); + // GetStateFlagsFromGtkWidgetState() can be safely used for the specific // GtkWidgets that set both prelight and active flags. For other widgets, // either the GtkStateFlags or Gecko's GtkWidgetState need to be carefully -@@ -167,7 +171,7 @@ moz_gtk_menuitem_get_horizontal_padding( - gint - moz_gtk_checkmenuitem_get_horizontal_padding(gint* horizontal_padding) - { -- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_CHECKMENUITEM_CONTAINER); -+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_CHECKMENUITEM); - gtk_style_context_get_style(style, - "horizontal-padding", horizontal_padding, - nullptr); -@@ -463,7 +467,7 @@ moz_gtk_get_widget_min_size(WidgetNodeTy +@@ -78,27 +80,22 @@ GetStateFlagsFromGtkTabFlags(GtkTabFlags } - static void --moz_gtk_rectangle_inset(GdkRectangle* rect, GtkBorder& aBorder) -+Inset(GdkRectangle* rect, GtkBorder& aBorder) - { - MOZ_ASSERT(rect); - rect->x += aBorder.left; -@@ -472,17 +476,29 @@ moz_gtk_rectangle_inset(GdkRectangle* re - rect->height -= aBorder.top + aBorder.bottom; - } - --/* Subtracting margin is used to inset drawing of element which can have margins, -- * like scrollbar, scrollbar's trough, thumb and scrollbar's button */ -+// Inset a rectangle by the margins specified in a style context. - static void --moz_gtk_subtract_margin(GtkStyleContext* style, GdkRectangle* rect) -+InsetByMargin(GdkRectangle* rect, GtkStyleContext* style) + gint +-moz_gtk_enable_style_props(style_prop_t styleGetProp) +-{ +- style_prop_func = styleGetProp; +- return MOZ_GTK_SUCCESS; +-} +- +-gint + moz_gtk_init() { - MOZ_ASSERT(rect); - GtkBorder margin; - - gtk_style_context_get_margin(style, gtk_style_context_get_state(style), - &margin); -- moz_gtk_rectangle_inset(rect, margin); -+ Inset(rect, margin); +- if (is_initialized) +- return MOZ_GTK_SUCCESS; +- +- is_initialized = TRUE; +- have_arrow_scaling = (gtk_major_version > 2 || +- (gtk_major_version == 2 && gtk_minor_version >= 12)); + if (gtk_major_version > 3 || + (gtk_major_version == 3 && gtk_minor_version >= 14)) + checkbox_check_state = GTK_STATE_FLAG_CHECKED; + else + checkbox_check_state = GTK_STATE_FLAG_ACTIVE; + ++ moz_gtk_refresh(); ++ ++ return MOZ_GTK_SUCCESS; +} + -+// Inset a rectangle by the border and padding specified in a style context. -+static void -+InsetByBorderPadding(GdkRectangle* rect, GtkStyleContext* style) ++void ++moz_gtk_refresh() +{ -+ GtkStateFlags state = gtk_style_context_get_state(style); -+ GtkBorder padding, border; -+ -+ gtk_style_context_get_padding(style, state, &padding); -+ Inset(rect, padding); -+ gtk_style_context_get_border(style, state, &border); -+ Inset(rect, border); - } - - static gint -@@ -528,7 +544,7 @@ moz_gtk_scrollbar_button_paint(cairo_t * - if (gtk_check_version(3,20,0) == nullptr) { - // The "trough-border" is not used since GTK 3.20. The stepper margin - // box occupies the full width of the "contents" gadget content box. -- moz_gtk_subtract_margin(style, &rect); -+ InsetByMargin(&rect, style); - } else { - // Scrollbar button has to be inset by trough_border because its DOM - // element is filling width of vertical scrollbar's track (or height -@@ -601,7 +617,7 @@ moz_gtk_draw_styled_frame(GtkStyleContex - { - GdkRectangle rect = *aRect; - if (gtk_check_version(3, 6, 0) == nullptr) { -- moz_gtk_subtract_margin(style, &rect); -+ InsetByMargin(&rect, style); + if (gtk_check_version(3, 12, 0) == nullptr && + gtk_check_version(3, 20, 0) != nullptr) + { +@@ -112,7 +109,8 @@ moz_gtk_init() + notebook_has_tab_gap = true; } - 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); -@@ -664,7 +680,7 @@ moz_gtk_scrollbar_thumb_paint(WidgetNode - - GdkRectangle rect = *aRect; - GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags); -- moz_gtk_subtract_margin(style, &rect); -+ InsetByMargin(&rect, style); - gtk_render_slider(style, cr, - rect.x, -@@ -865,7 +881,7 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect +- return MOZ_GTK_SUCCESS; ++ sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; ++ sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; } - static gint --moz_gtk_text_view_paint(cairo_t *cr, GdkRectangle* rect, -+moz_gtk_text_view_paint(cairo_t *cr, GdkRectangle* aRect, - GtkWidgetState* state, - GtkTextDirection direction) - { -@@ -882,24 +898,24 @@ moz_gtk_text_view_paint(cairo_t *cr, Gdk - - 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); -+ gtk_render_frame(style_frame, cr, -+ aRect->x, aRect->y, aRect->width, aRect->height); -+ -+ GdkRectangle rect = *aRect; -+ InsetByBorderPadding(&rect, style_frame); - -- 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); -- -+ gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); -+ ReleaseStyleContext(style); -+ // There is a separate "text" window, which usually provides the -+ // background behind the text. However, this is transparent in Ambiance -+ // for GTK 3.20, in which case the MOZ_GTK_TEXT_VIEW background is -+ // visible. -+ style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW_TEXT, direction, state_flags); -+ gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); - ReleaseStyleContext(style); - - return MOZ_GTK_SUCCESS; -@@ -1291,6 +1307,7 @@ moz_gtk_tooltip_paint(cairo_t *cr, const - GdkRectangle rect = *aRect; - 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); - - // Horizontal Box drawing - // -@@ -1300,33 +1317,26 @@ moz_gtk_tooltip_paint(cairo_t *cr, const - // 6px margin. - // For drawing Horizontal Box we have to inset drawing area by that 6px - // plus its CSS margin. -- GtkStyleContext* boxStyle = -- CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), style); -+ GtkStyleContext* boxStyle = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX, direction); - - rect.x += 6; - rect.y += 6; - rect.width -= 12; - rect.height -= 12; - -- moz_gtk_subtract_margin(boxStyle, &rect); -+ InsetByMargin(&rect, boxStyle); - gtk_render_background(boxStyle, cr, rect.x, rect.y, rect.width, rect.height); - gtk_render_frame(boxStyle, cr, rect.x, rect.y, rect.width, rect.height); - - // Label drawing -- GtkBorder padding, border; -- gtk_style_context_get_padding(boxStyle, GTK_STATE_FLAG_NORMAL, &padding); -- moz_gtk_rectangle_inset(&rect, padding); -- gtk_style_context_get_border(boxStyle, GTK_STATE_FLAG_NORMAL, &border); -- moz_gtk_rectangle_inset(&rect, border); -+ InsetByBorderPadding(&rect, boxStyle); -+ ReleaseStyleContext(boxStyle); - - GtkStyleContext* labelStyle = -- CreateStyleForWidget(gtk_label_new(nullptr), boxStyle); -+ ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL, direction); - moz_gtk_draw_styled_frame(labelStyle, cr, &rect, false); -- g_object_unref(labelStyle); -+ ReleaseStyleContext(labelStyle); - -- g_object_unref(boxStyle); -- -- ReleaseStyleContext(style); + gint +@@ -420,9 +418,8 @@ calculate_arrow_rect(GtkWidget* arrow, G + gfloat mxalign, myalign; + GtkMisc* misc = GTK_MISC(arrow); + +- if (have_arrow_scaling) +- gtk_style_context_get_style(gtk_widget_get_style_context(arrow), +- "arrow_scaling", &arrow_scaling, NULL); ++ gtk_style_context_get_style(gtk_widget_get_style_context(arrow), ++ "arrow_scaling", &arrow_scaling, NULL); + + gtk_misc_get_padding(misc, &mxpad, &mypad); + extent = MIN((rect->width - mxpad * 2), +@@ -443,7 +440,23 @@ calculate_arrow_rect(GtkWidget* arrow, G return MOZ_GTK_SUCCESS; } -@@ -1335,17 +1345,9 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRe - GtkWidgetState* state, - GtkTextDirection direction) - { -- GtkStyleContext* style; -- -- // gtk_render_handle() draws a background, so use GtkTextView and its -- // 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. -- 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); -+ GtkStyleContext* style = -+ ClaimStyleContext(MOZ_GTK_RESIZER, GTK_TEXT_DIR_LTR, -+ GetStateFlagsFromGtkWidgetState(state)); - - // Workaround unico not respecting the text direction for resizers. - // See bug 1174248. -@@ -1392,17 +1394,8 @@ moz_gtk_progress_chunk_paint(cairo_t *cr - GtkTextDirection direction, - WidgetNodeType widget) - { -- GtkStyleContext* style; -- -- 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); -- } -+ GtkStyleContext* style = -+ ClaimStyleContext(MOZ_GTK_PROGRESS_CHUNK, direction); - - if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE || - widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) { -@@ -1786,6 +1779,13 @@ static gint - moz_gtk_menu_separator_paint(cairo_t *cr, GdkRectangle* rect, - GtkTextDirection direction) - { -+ GtkWidgetState defaultState = { 0 }; -+ moz_gtk_menu_item_paint(MOZ_GTK_MENUSEPARATOR, cr, rect, -+ &defaultState, direction); -+ -+ if (gtk_get_minor_version() >= 20) -+ return MOZ_GTK_SUCCESS; +-void ++static MozGtkSize ++GetMinContentBox(GtkStyleContext* style) ++{ ++ GtkStateFlags state_flags = gtk_style_context_get_state(style); ++ gint width, height; ++ gtk_style_context_get(style, state_flags, ++ "min-width", &width, ++ "min-height", &height, ++ nullptr); ++ return {width, height}; ++} + - GtkStyleContext* style; - gboolean wide_separators; - gint separator_height; -@@ -1833,36 +1833,39 @@ moz_gtk_menu_item_paint(WidgetNodeType w - GtkWidgetState* state, GtkTextDirection direction) ++/** ++ * Get minimum widget size as sum of margin, padding, border and ++ * min-width/min-height. ++ */ ++static void + moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, + int* height) { - gint x, y, w, h; -+ guint minorVersion = gtk_get_minor_version(); -+ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); +@@ -466,6 +479,14 @@ moz_gtk_get_widget_min_size(WidgetNodeTy + padding.top + padding.bottom; + } -- if (state->inHover && !state->disabled) { -- 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 versions prior to 3.8 render the background and frame only when not -+ // a separator and in hover prelight. -+ if (minorVersion < 8 && (widget == MOZ_GTK_MENUSEPARATOR || -+ !(state_flags & GTK_STATE_FLAG_PRELIGHT))) -+ return MOZ_GTK_SUCCESS; -+ -+ GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags); ++static MozGtkSize ++GetMinMarginBox(WidgetNodeType aNodeType) ++{ ++ gint width, height; ++ moz_gtk_get_widget_min_size(aNodeType, &width, &height); ++ return {width, height}; ++} + -+ if (minorVersion < 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); - } -+ } - -- x = rect->x; -- y = rect->y; -- w = rect->width; -- h = rect->height; -+ x = rect->x; -+ y = rect->y; -+ w = rect->width; -+ h = rect->height; - -- gtk_render_background(style, cr, x, y, w, h); -- gtk_render_frame(style, cr, x, y, w, h); -+ 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); -- } -- ReleaseStyleContext(style); -+ if (minorVersion < 6) { -+ gtk_style_context_restore(style); + static void + Inset(GdkRectangle* rect, GtkBorder& aBorder) + { +@@ -546,18 +567,22 @@ moz_gtk_scrollbar_button_paint(cairo_t * + // box occupies the full width of the "contents" gadget content box. + InsetByMargin(&rect, style); + } else { +- // Scrollbar button has to be inset by trough_border because its DOM +- // element is filling width of vertical scrollbar's track (or height +- // in case of horizontal scrollbars). +- MozGtkScrollbarMetrics metrics; +- moz_gtk_get_scrollbar_metrics(&metrics); +- if (flags & MOZ_GTK_STEPPER_VERTICAL) { +- rect.x += metrics.trough_border; +- rect.width = metrics.slider_width; +- } else { +- rect.y += metrics.trough_border; +- rect.height = metrics.slider_width; +- } ++ // Scrollbar button has to be inset by trough_border because its DOM ++ // element is filling width of vertical scrollbar's track (or height ++ // in case of horizontal scrollbars). ++ GtkOrientation orientation = flags & MOZ_GTK_STEPPER_VERTICAL ? ++ GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL; ++ const auto& metrics = sScrollbarMetrics[orientation]; ++ if (!metrics.initialized) { ++ NS_WARNING("Didn't measure before drawing?"); ++ } ++ if (flags & MOZ_GTK_STEPPER_VERTICAL) { ++ rect.x += metrics.border.track.left; ++ rect.width = metrics.size.thumb.width; ++ } else { ++ rect.y += metrics.border.track.top; ++ rect.height = metrics.size.thumb.height; ++ } } -+ ReleaseStyleContext(style); - return MOZ_GTK_SUCCESS; - } -@@ -1882,16 +1885,16 @@ moz_gtk_menu_arrow_paint(cairo_t *cr, Gd - return MOZ_GTK_SUCCESS; - } + gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); +@@ -629,12 +654,37 @@ moz_gtk_draw_styled_frame(GtkStyleContex --// See gtk_real_check_menu_item_draw_indicator() for reference. -+// For reference, see gtk_check_menu_item_size_allocate() in GTK versions after -+// 3.20 and gtk_real_check_menu_item_draw_indicator() in earlier versions. static gint --moz_gtk_check_menu_item_paint(cairo_t *cr, GdkRectangle* rect, -+moz_gtk_check_menu_item_paint(WidgetNodeType widgetType, -+ cairo_t *cr, GdkRectangle* rect, - GtkWidgetState* state, -- gboolean checked, gboolean isradio, -- GtkTextDirection direction) -+ gboolean checked, GtkTextDirection direction) + moz_gtk_scrollbar_trough_paint(WidgetNodeType widget, +- cairo_t *cr, const GdkRectangle* rect, ++ cairo_t *cr, const GdkRectangle* aRect, + GtkWidgetState* state, + GtkTextDirection direction) { - GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); - GtkStyleContext* style; -- GtkBorder padding; - gint indicator_size, horizontal_padding; - gint x, y; - -@@ -1901,35 +1904,44 @@ moz_gtk_check_menu_item_paint(cairo_t *c - state_flags = static_cast<GtkStateFlags>(state_flags|checkbox_check_state); - } - -- style = ClaimStyleContext(isradio ? MOZ_GTK_RADIOMENUITEM_CONTAINER : -- MOZ_GTK_CHECKMENUITEM_CONTAINER, -- direction); -+ bool pre_3_20 = gtk_get_minor_version() < 20; -+ gint offset; -+ style = ClaimStyleContext(widgetType, direction); - gtk_style_context_get_style(style, - "indicator-size", &indicator_size, - "horizontal-padding", &horizontal_padding, - NULL); -+ if (pre_3_20) { -+ GtkBorder padding; -+ gtk_style_context_get_padding(style, state_flags, &padding); -+ offset = horizontal_padding + padding.left + 2; +- GtkStyleContext* style = ClaimStyleContext(widget, direction); +- moz_gtk_draw_styled_frame(style, cr, rect, state->focused); ++ GdkRectangle rect = *aRect; ++ GtkStyleContext* style; ++ ++ if (gtk_get_minor_version() >= 20) { ++ WidgetNodeType thumb = widget == MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL ? ++ MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : ++ MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; ++ MozGtkSize thumbSize = GetMinMarginBox(thumb); ++ style = ClaimStyleContext(widget, direction); ++ MozGtkSize trackSize = GetMinContentBox(style); ++ trackSize.Include(thumbSize); ++ trackSize += GetMarginBorderPadding(style); ++ // Gecko's trough |aRect| fills available breadth, but GTK's trough is ++ // centered in the contents_gadget. The centering here round left ++ // and up, like gtk_box_gadget_allocate_child(). ++ if (widget == MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL) { ++ rect.x += (rect.width - trackSize.width)/2; ++ rect.width = trackSize.width; ++ } else { ++ rect.y += (rect.height - trackSize.height)/2; ++ rect.height = trackSize.height; ++ } + } else { -+ GdkRectangle r = { 0 }; -+ InsetByMargin(&r, style); -+ InsetByBorderPadding(&r, style); -+ offset = r.x; ++ style = ClaimStyleContext(widget, direction); + } ++ ++ moz_gtk_draw_styled_frame(style, cr, &rect, state->focused); ReleaseStyleContext(style); -- style = ClaimStyleContext(isradio ? MOZ_GTK_RADIOMENUITEM : -- MOZ_GTK_CHECKMENUITEM, -- direction, state_flags); -- gtk_style_context_get_padding(style, state_flags, &padding); -- gint offset = padding.left + 2; -+ bool isRadio = (widgetType == MOZ_GTK_RADIOMENUITEM); -+ WidgetNodeType indicatorType = isRadio ? MOZ_GTK_RADIOMENUITEM_INDICATOR -+ : MOZ_GTK_CHECKMENUITEM_INDICATOR; -+ style = ClaimStyleContext(indicatorType, direction, state_flags); - - if (direction == GTK_TEXT_DIR_RTL) { -- x = rect->width - indicator_size - offset - horizontal_padding; -+ x = rect->width - indicator_size - offset; - } - else { -- x = rect->x + offset + horizontal_padding; -+ x = rect->x + offset; - } - y = rect->y + (rect->height - indicator_size) / 2; - -- if (gtk_check_version(3, 20, 0) == nullptr) { -+ if (!pre_3_20) { - gtk_render_background(style, cr, x, y, indicator_size, indicator_size); - gtk_render_frame(style, cr, x, y, indicator_size, indicator_size); - } - -- if (isradio) { -+ if (isRadio) { - gtk_render_option(style, cr, x, y, indicator_size, indicator_size); - } else { - gtk_render_check(style, cr, x, y, indicator_size, indicator_size); -@@ -2033,9 +2045,6 @@ moz_gtk_get_widget_border(WidgetNodeType - if (widget == MOZ_GTK_TOOLBAR_BUTTON) - gtk_style_context_restore(style); - -- // XXX: Subtract 1 pixel from the border to account for the added -- // -moz-focus-inner border (Bug 1228281). -- *left -= 1; *top -= 1; *right -= 1; *bottom -= 1; - moz_gtk_add_style_border(style, left, top, right, bottom); + return MOZ_GTK_SUCCESS; +@@ -2009,6 +2059,20 @@ static void moz_gtk_add_margin_border_pa + moz_gtk_add_style_padding(style, left, top, right, bottom); + } - ReleaseStyleContext(style); -@@ -2174,12 +2183,15 @@ moz_gtk_get_widget_border(WidgetNodeType - { - // Bug 1274143 for MOZ_GTK_MENUBARITEM - WidgetNodeType type = -- widget == MOZ_GTK_MENUBARITEM || widget == MOZ_GTK_MENUITEM ? -- MOZ_GTK_MENUITEM : MOZ_GTK_CHECKMENUITEM_CONTAINER; -+ widget == MOZ_GTK_MENUBARITEM ? MOZ_GTK_MENUITEM : widget; - style = ClaimStyleContext(type); ++static GtkBorder ++GetMarginBorderPadding(GtkStyleContext* aStyle) ++{ ++ gint left = 0, top = 0, right = 0, bottom = 0; ++ moz_gtk_add_margin_border_padding(aStyle, &left, &top, &right, &bottom); ++ // narrowing conversions to gint16: ++ GtkBorder result; ++ result.left = left; ++ result.right = right; ++ result.top = top; ++ result.bottom = bottom; ++ return result; ++} ++ + gint + moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + gint* right, gint* bottom, GtkTextDirection direction, +@@ -2212,61 +2276,7 @@ moz_gtk_get_widget_border(WidgetNodeType -- moz_gtk_add_style_padding(style, left, top, right, bottom); -- -+ if (gtk_get_minor_version() < 20) { -+ moz_gtk_add_style_padding(style, left, top, right, bottom); -+ } else { -+ moz_gtk_add_margin_border_padding(style, -+ left, top, right, bottom); -+ } - ReleaseStyleContext(style); return MOZ_GTK_SUCCESS; } -@@ -2188,7 +2200,6 @@ moz_gtk_get_widget_border(WidgetNodeType - break; - case MOZ_GTK_TOOLTIP: - { -- style = ClaimStyleContext(MOZ_GTK_TOOLTIP); - // In GTK 3 there are 6 pixels of additional margin around the box. - // See details there: - // https://github.com/GNOME/gtk/blob/5ea69a136bd7e4970b3a800390e20314665aaed2/gtk/ui/gtktooltipwindow.ui#L11 -@@ -2197,21 +2208,16 @@ moz_gtk_get_widget_border(WidgetNodeType - // We also need to add margin/padding/borders from Tooltip content. - // Tooltip contains horizontal box, where icon and label is put. - // We ignore icon as long as we don't have support for it. -- GtkStyleContext* boxStyle = -- CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), -- style); -+ GtkStyleContext* boxStyle = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX); - moz_gtk_add_margin_border_padding(boxStyle, - left, top, right, bottom); -+ ReleaseStyleContext(boxStyle); - -- GtkStyleContext* labelStyle = -- CreateStyleForWidget(gtk_label_new(nullptr), boxStyle); -+ GtkStyleContext* labelStyle = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL); - moz_gtk_add_margin_border_padding(labelStyle, - left, top, right, bottom); -+ ReleaseStyleContext(labelStyle); - -- g_object_unref(labelStyle); -- g_object_unref(boxStyle); +- case MOZ_GTK_SCROLLBAR_VERTICAL: +- case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL: +- { +- if (gtk_check_version(3,20,0) == nullptr) { +- style = ClaimStyleContext(widget); +- moz_gtk_add_margin_border_padding(style, left, top, right, bottom); +- ReleaseStyleContext(style); +- if (widget == MOZ_GTK_SCROLLBAR_VERTICAL) { +- style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL); +- moz_gtk_add_margin_border_padding(style, left, top, right, bottom); +- ReleaseStyleContext(style); +- } +- } else { +- MozGtkScrollbarMetrics metrics; +- moz_gtk_get_scrollbar_metrics(&metrics); +- /* Top and bottom border for whole vertical scrollbar, top and bottom +- * border for horizontal track - to correctly position thumb element */ +- *top = *bottom = metrics.trough_border; +- } +- return MOZ_GTK_SUCCESS; +- } +- break; + +- case MOZ_GTK_SCROLLBAR_HORIZONTAL: +- case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL: +- { +- if (gtk_check_version(3,20,0) == nullptr) { +- style = ClaimStyleContext(widget); +- moz_gtk_add_margin_border_padding(style, left, top, right, bottom); +- ReleaseStyleContext(style); +- if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) { +- style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL); +- moz_gtk_add_margin_border_padding(style, left, top, right, bottom); +- ReleaseStyleContext(style); +- } +- } else { +- MozGtkScrollbarMetrics metrics; +- moz_gtk_get_scrollbar_metrics(&metrics); +- *left = *right = metrics.trough_border; +- } +- return MOZ_GTK_SUCCESS; +- } +- break; - +- case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: +- case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL: +- { +- if (gtk_check_version(3,20,0) == nullptr) { +- style = ClaimStyleContext(widget); +- moz_gtk_add_margin_border_padding(style, left, top, right, bottom); - ReleaseStyleContext(style); - return MOZ_GTK_SUCCESS; - } - case MOZ_GTK_SCROLLBAR_VERTICAL: -@@ -2500,11 +2506,11 @@ void +- } +- return MOZ_GTK_SUCCESS; +- } +- break; + /* These widgets have no borders, since they are not containers. */ + case MOZ_GTK_CHECKBUTTON_LABEL: + case MOZ_GTK_RADIOBUTTON_LABEL: +@@ -2275,6 +2285,8 @@ moz_gtk_get_widget_border(WidgetNodeType + case MOZ_GTK_CHECKBUTTON: + case MOZ_GTK_RADIOBUTTON: + case MOZ_GTK_SCROLLBAR_BUTTON: ++ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: ++ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL: + case MOZ_GTK_SCALE_THUMB_HORIZONTAL: + case MOZ_GTK_SCALE_THUMB_VERTICAL: + case MOZ_GTK_GRIPPER: +@@ -2498,11 +2510,11 @@ void moz_gtk_get_scale_metrics(GtkOrientation orient, gint* scale_width, gint* scale_height) { @@ -464,7 +307,7 @@ diff -up firefox-52.0/widget/gtk/gtk3drawing.cpp.widget-rebase firefox-52.0/widg gint thumb_length, thumb_height, trough_border; moz_gtk_get_scalethumb_metrics(orient, &thumb_length, &thumb_height); -@@ -2520,12 +2526,10 @@ moz_gtk_get_scale_metrics(GtkOrientation +@@ -2518,12 +2530,10 @@ moz_gtk_get_scale_metrics(GtkOrientation } ReleaseStyleContext(style); } else { @@ -481,7 +324,7 @@ diff -up firefox-52.0/widget/gtk/gtk3drawing.cpp.widget-rebase firefox-52.0/widg } } -@@ -2548,10 +2552,28 @@ moz_gtk_get_scalethumb_metrics(GtkOrient +@@ -2546,33 +2556,176 @@ moz_gtk_get_scalethumb_metrics(GtkOrient MOZ_GTK_SCALE_THUMB_HORIZONTAL: MOZ_GTK_SCALE_THUMB_VERTICAL; GtkStyleContext* style = ClaimStyleContext(widget); @@ -513,647 +356,507 @@ diff -up firefox-52.0/widget/gtk/gtk3drawing.cpp.widget-rebase firefox-52.0/widg ReleaseStyleContext(style); } -@@ -2791,10 +2813,8 @@ moz_gtk_widget_paint(WidgetNodeType widg - break; - case MOZ_GTK_CHECKMENUITEM: - case MOZ_GTK_RADIOMENUITEM: -- return moz_gtk_check_menu_item_paint(cr, rect, state, -- (gboolean) flags, -- (widget == MOZ_GTK_RADIOMENUITEM), -- direction); -+ return moz_gtk_check_menu_item_paint(widget, cr, rect, state, -+ (gboolean) flags, direction); - break; - case MOZ_GTK_SPLITTER_HORIZONTAL: - return moz_gtk_vpaned_paint(cr, rect, state); -diff -up firefox-52.0/widget/gtk/gtkdrawing.h.widget-rebase firefox-52.0/widget/gtk/gtkdrawing.h ---- firefox-52.0/widget/gtk/gtkdrawing.h.widget-rebase 2017-02-27 17:11:05.000000000 +0100 -+++ firefox-52.0/widget/gtk/gtkdrawing.h 2017-03-10 12:20:30.233205986 +0100 -@@ -145,8 +145,11 @@ typedef enum { - MOZ_GTK_ENTRY, - /* Paints a GtkExpander. */ - MOZ_GTK_EXPANDER, -- /* Paints a GtkTextView. */ -+ /* Paints a GtkTextView or gets the style context corresponding to the -+ root node of a GtkTextView. */ - MOZ_GTK_TEXT_VIEW, -+ /* The "text" window or node of a GtkTextView */ -+ MOZ_GTK_TEXT_VIEW_TEXT, - /* Paints a GtkOptionMenu. */ - MOZ_GTK_DROPDOWN, - /* Paints a dropdown arrow (a GtkButton containing a down GtkArrow). */ -@@ -160,11 +163,15 @@ typedef enum { - MOZ_GTK_TOOLBAR_SEPARATOR, - /* Paints a GtkToolTip */ - MOZ_GTK_TOOLTIP, -+ /* Paints a GtkBox from GtkToolTip */ -+ MOZ_GTK_TOOLTIP_BOX, -+ /* Paints a GtkLabel of GtkToolTip */ -+ MOZ_GTK_TOOLTIP_BOX_LABEL, - /* Paints a GtkFrame (e.g. a status bar panel). */ - MOZ_GTK_FRAME, - /* Paints the border of a GtkFrame */ - MOZ_GTK_FRAME_BORDER, -- /* Paints a resize grip for a GtkWindow */ -+ /* Paints a resize grip for a GtkTextView */ - MOZ_GTK_RESIZER, - /* Paints a GtkProgressBar. */ - MOZ_GTK_PROGRESSBAR, -@@ -210,11 +217,13 @@ typedef enum { - MOZ_GTK_MENUBARITEM, - /* Paints items of popup menus. */ - MOZ_GTK_MENUITEM, -- MOZ_GTK_IMAGEMENUITEM, -- MOZ_GTK_CHECKMENUITEM_CONTAINER, -- MOZ_GTK_RADIOMENUITEM_CONTAINER, -+ /* Paints a menuitem with check indicator, or the gets the style context for -+ a menuitem that contains a checkbox. */ - MOZ_GTK_CHECKMENUITEM, -+ /* Gets the style context for a checkbox in a check menuitem. */ -+ MOZ_GTK_CHECKMENUITEM_INDICATOR, - MOZ_GTK_RADIOMENUITEM, -+ MOZ_GTK_RADIOMENUITEM_INDICATOR, - MOZ_GTK_MENUSEPARATOR, - /* GtkVPaned base class */ - MOZ_GTK_SPLITTER_HORIZONTAL, -diff -up firefox-52.0/widget/gtk/mozgtk/mozgtk.c.widget-rebase firefox-52.0/widget/gtk/mozgtk/mozgtk.c ---- firefox-52.0/widget/gtk/mozgtk/mozgtk.c.widget-rebase 2017-02-27 17:11:05.000000000 +0100 -+++ firefox-52.0/widget/gtk/mozgtk/mozgtk.c 2017-03-10 12:20:30.233205986 +0100 -@@ -245,7 +245,6 @@ STUB(gtk_icon_theme_get_icon_sizes) - STUB(gtk_icon_theme_lookup_by_gicon) - STUB(gtk_icon_theme_lookup_icon) - STUB(gtk_image_get_type) --STUB(gtk_image_menu_item_new) - STUB(gtk_image_new) - STUB(gtk_image_new_from_stock) - STUB(gtk_image_set_from_pixbuf) -diff -up firefox-52.0/widget/gtk/nsLookAndFeel.cpp.widget-rebase firefox-52.0/widget/gtk/nsLookAndFeel.cpp ---- firefox-52.0/widget/gtk/nsLookAndFeel.cpp.widget-rebase 2017-02-27 17:11:05.000000000 +0100 -+++ firefox-52.0/widget/gtk/nsLookAndFeel.cpp 2017-03-10 13:54:36.918205357 +0100 -@@ -24,6 +24,7 @@ - #include "nsStyleConsts.h" - #include "gfxFontConstants.h" - #include "WidgetUtils.h" -+#include "nsIXULRuntime.h" - - #include <dlfcn.h> - -@@ -47,9 +48,6 @@ nsLookAndFeel::nsLookAndFeel() - : nsXPLookAndFeel(), - #if (MOZ_WIDGET_GTK == 2) - mStyle(nullptr), --#else -- mBackgroundStyle(nullptr), -- mButtonStyle(nullptr), - #endif - mDefaultFontCached(false), mButtonFontCached(false), - mFieldFontCached(false), mMenuFontCached(false) -@@ -61,13 +59,27 @@ nsLookAndFeel::~nsLookAndFeel() - { - #if (MOZ_WIDGET_GTK == 2) - g_object_unref(mStyle); --#else -- g_object_unref(mBackgroundStyle); -- g_object_unref(mButtonStyle); - #endif + return MOZ_GTK_SUCCESS; } - #if MOZ_WIDGET_GTK != 2 -+// Modifies color |*aDest| as if a pattern of color |aSource| was painted with -+// CAIRO_OPERATOR_OVER to a surface with color |*aDest|. -+static void -+ApplyColorOver(const GdkRGBA& aSource, GdkRGBA* aDest) { -+ gdouble sourceCoef = aSource.alpha; -+ gdouble destCoef = aDest->alpha * (1.0 - sourceCoef); -+ gdouble resultAlpha = sourceCoef + destCoef; -+ if (resultAlpha != 0.0) { // don't divide by zero -+ destCoef /= resultAlpha; -+ sourceCoef /= resultAlpha; -+ aDest->red = sourceCoef * aSource.red + destCoef * aDest->red; -+ aDest->green = sourceCoef * aSource.green + destCoef * aDest->green; -+ aDest->blue = sourceCoef * aSource.blue + destCoef * aDest->blue; -+ aDest->alpha = resultAlpha; -+ } +-gint +-moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics) ++static MozGtkSize ++SizeFromLengthAndBreadth(GtkOrientation aOrientation, ++ gint aLength, gint aBreadth) + { +- // For Gtk >= 3.20 scrollbar metrics are ignored +- MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr); ++ return aOrientation == GTK_ORIENTATION_HORIZONTAL ? ++ MozGtkSize({aLength, aBreadth}) : MozGtkSize({aBreadth, aLength}); +} + - static void - GetLightAndDarkness(const GdkRGBA& aColor, - double* aLightness, double* aDarkness) -@@ -377,30 +389,39 @@ nsLookAndFeel::NativeGetColor(ColorID aI - break; - #else - // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors -- case eColorID_activeborder: -+ case eColorID_activeborder: { - // active window border -- gtk_style_context_get_border_color(mBackgroundStyle, -+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_WINDOW); -+ gtk_style_context_get_border_color(style, - GTK_STATE_FLAG_NORMAL, &gdk_color); - aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); -+ ReleaseStyleContext(style); - break; -- case eColorID_inactiveborder: -+ } -+ case eColorID_inactiveborder: { - // inactive window border -- gtk_style_context_get_border_color(mBackgroundStyle, -- GTK_STATE_FLAG_INSENSITIVE, -+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_WINDOW); -+ gtk_style_context_get_border_color(style, -+ GTK_STATE_FLAG_INSENSITIVE, - &gdk_color); - aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); ++const ScrollbarGTKMetrics* ++GetScrollbarMetrics(GtkOrientation aOrientation) ++{ ++ auto metrics = &sScrollbarMetrics[aOrientation]; ++ if (metrics->initialized) ++ return metrics; ++ ++ metrics->initialized = true; + +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_VERTICAL); ++ WidgetNodeType scrollbar = aOrientation == GTK_ORIENTATION_HORIZONTAL ? ++ MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; ++ ++ gboolean backward, forward, secondary_backward, secondary_forward; ++ GtkStyleContext* style = ClaimStyleContext(scrollbar); + gtk_style_context_get_style(style, +- "slider_width", &metrics->slider_width, +- "trough_border", &metrics->trough_border, +- "stepper_size", &metrics->stepper_size, +- "stepper_spacing", &metrics->stepper_spacing, +- "min-slider-length", &metrics->min_slider_size, +- nullptr); ++ "has-backward-stepper", &backward, ++ "has-forward-stepper", &forward, ++ "has-secondary-backward-stepper", ++ &secondary_backward, ++ "has-secondary-forward-stepper", ++ &secondary_forward, nullptr); ++ bool hasButtons = ++ backward || forward || secondary_backward || secondary_forward; ++ ++ if (gtk_get_minor_version() < 20) { ++ gint slider_width, trough_border, stepper_size, min_slider_size; ++ ++ gtk_style_context_get_style(style, ++ "slider-width", &slider_width, ++ "trough-border", &trough_border, ++ "stepper-size", &stepper_size, ++ "min-slider-length", &min_slider_size, ++ nullptr); + ReleaseStyleContext(style); - break; ++ ++ metrics->size.thumb = ++ SizeFromLengthAndBreadth(aOrientation, min_slider_size, slider_width); ++ metrics->size.button = ++ SizeFromLengthAndBreadth(aOrientation, stepper_size, slider_width); ++ // overall scrollbar ++ gint breadth = slider_width + 2 * trough_border; ++ // Require room for the slider in the track if we don't have buttons. ++ gint length = hasButtons ? 0 : min_slider_size + 2 * trough_border; ++ metrics->size.scrollbar = ++ SizeFromLengthAndBreadth(aOrientation, length, breadth); ++ ++ // Borders on the major axis are set on the outermost scrollbar ++ // element to correctly position the buttons when ++ // trough-under-steppers is true. ++ // Borders on the minor axis are set on the track element so that it ++ // receives mouse events, as in GTK. ++ // Other borders have been zero-initialized. ++ if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { ++ metrics->border.scrollbar.left = ++ metrics->border.scrollbar.right = ++ metrics->border.track.top = ++ metrics->border.track.bottom = trough_border; ++ } else { ++ metrics->border.scrollbar.top = ++ metrics->border.scrollbar.bottom = ++ metrics->border.track.left = ++ metrics->border.track.right = trough_border; ++ } ++ ++ return metrics; + } - case eColorID_graytext: // disabled text in windows, menus, etc. - case eColorID_inactivecaptiontext: // text in inactive window caption - aColor = sMenuTextInactive; - break; -- case eColorID_inactivecaption: -+ case eColorID_inactivecaption: { - // inactive window caption -- gtk_style_context_get_background_color(mBackgroundStyle, -+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_WINDOW); -+ gtk_style_context_get_background_color(style, - GTK_STATE_FLAG_INSENSITIVE, - &gdk_color); - aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); -+ ReleaseStyleContext(style); - break; ++ ++ // GTK version > 3.20 ++ // scrollbar ++ metrics->border.scrollbar = GetMarginBorderPadding(style); + ReleaseStyleContext(style); + +- return MOZ_GTK_SUCCESS; ++ WidgetNodeType contents, track, thumb; ++ if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { ++ contents = MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL; ++ track = MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL; ++ thumb = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; ++ } else { ++ contents = MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL; ++ track = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL; ++ thumb = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL; + } - #endif - case eColorID_infobackground: - // tooltip background color -@@ -521,18 +542,24 @@ nsLookAndFeel::NativeGetColor(ColorID aI - case eColorID__moz_fieldtext: - aColor = sMozFieldText; - break; -- case eColorID__moz_buttondefault: -- // default button border color -- gtk_style_context_get_border_color(mButtonStyle, -+ case eColorID__moz_buttondefault: { -+ // default button border color -+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); -+ gtk_style_context_get_border_color(style, - GTK_STATE_FLAG_NORMAL, &gdk_color); - aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); -+ ReleaseStyleContext(style); - break; -- case eColorID__moz_buttonhoverface: -- gtk_style_context_get_background_color(mButtonStyle, ++ // thumb ++ metrics->size.thumb = GetMinMarginBox(thumb); ++ // track ++ style = ClaimStyleContext(track); ++ metrics->border.track = GetMarginBorderPadding(style); ++ MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track; ++ ReleaseStyleContext(style); ++ MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; ++ // button ++ if (hasButtons) { ++ metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON); ++ } else { ++ metrics->size.button = {0, 0}; + } -+ case eColorID__moz_buttonhoverface: { -+ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); -+ gtk_style_context_get_background_color(style, - GTK_STATE_FLAG_PRELIGHT, - &gdk_color); - aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); -+ ReleaseStyleContext(style); - break; ++ if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { ++ metrics->size.button.Rotate(); ++ // If the track is wider than necessary for the thumb, including when ++ // the buttons will cause Gecko to expand the track to fill ++ // available breadth, then add to the track border to prevent Gecko ++ // from expanding the thumb to fill available breadth. ++ gint extra = ++ std::max(trackMinSize.height, ++ metrics->size.button.height) - trackSizeForThumb.height; ++ if (extra > 0) { ++ // If extra is odd, then the thumb is 0.5 pixels above ++ // center as in gtk_range_compute_slider_position(). ++ metrics->border.track.top += extra / 2; ++ metrics->border.track.bottom += extra - extra / 2; ++ // Update size for change in border. ++ trackSizeForThumb.height += extra; ++ } ++ } else { ++ gint extra = ++ std::max(trackMinSize.width, ++ metrics->size.button.width) - trackSizeForThumb.width; ++ if (extra > 0) { ++ // If extra is odd, then the thumb is 0.5 pixels to the left ++ // of center as in gtk_range_compute_slider_position(). ++ metrics->border.track.left += extra / 2; ++ metrics->border.track.right += extra - extra / 2; ++ trackSizeForThumb.width += extra; ++ } + } - case eColorID__moz_buttonhovertext: - aColor = sButtonHoverText; - break; -@@ -1029,16 +1056,6 @@ nsLookAndFeel::GetFontImpl(FontID aID, n - return true; ++ ++ style = ClaimStyleContext(contents); ++ GtkBorder contentsBorder = GetMarginBorderPadding(style); ++ ReleaseStyleContext(style); ++ ++ metrics->size.scrollbar = ++ trackSizeForThumb + contentsBorder + metrics->border.scrollbar; ++ ++ return metrics; + } + + /* cairo_t *cr argument has to be a system-cairo. */ +@@ -2814,34 +2967,11 @@ moz_gtk_widget_paint(WidgetNodeType widg + return MOZ_GTK_UNKNOWN_WIDGET; } --#if (MOZ_WIDGET_GTK == 3) --static GtkStyleContext* --create_context(GtkWidgetPath *path) +-GtkWidget* moz_gtk_get_scrollbar_widget(void) -{ -- GtkStyleContext *style = gtk_style_context_new(); -- gtk_style_context_set_path(style, path); -- return(style); +- return GetWidget(MOZ_GTK_SCROLLBAR_HORIZONTAL); -} --#endif - - void - nsLookAndFeel::Init() +-gboolean moz_gtk_has_scrollbar_buttons(void) +-{ +- gboolean backward, forward, secondary_backward, secondary_forward; +- MOZ_ASSERT(is_initialized, "Forgot to call moz_gtk_init()"); +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_VERTICAL); +- gtk_style_context_get_style(style, +- "has-backward-stepper", &backward, +- "has-forward-stepper", &forward, +- "has-secondary-backward-stepper", &secondary_backward, +- "has-secondary-forward-stepper", &secondary_forward, +- NULL); +- ReleaseStyleContext(style); +- +- return backward | forward | secondary_forward | secondary_forward; +-} +- + gint + moz_gtk_shutdown() { -@@ -1129,78 +1146,54 @@ nsLookAndFeel::Init() - g_object_set(settings, dark_setting, FALSE, nullptr); - } + /* This will destroy all of our widgets */ + ResetWidgetCache(); -- GtkWidgetPath *path = gtk_widget_path_new(); -- gtk_widget_path_append_type(path, GTK_TYPE_WINDOW); +- is_initialized = FALSE; - -- mBackgroundStyle = create_context(path); -- gtk_style_context_add_class(mBackgroundStyle, GTK_STYLE_CLASS_BACKGROUND); + return MOZ_GTK_SUCCESS; + } +diff -up firefox-53.0/widget/gtk/gtkdrawing.h.widget-rebase firefox-53.0/widget/gtk/gtkdrawing.h +--- firefox-53.0/widget/gtk/gtkdrawing.h.widget-rebase 2017-04-18 10:24:37.950508591 +0200 ++++ firefox-53.0/widget/gtk/gtkdrawing.h 2017-04-18 10:22:45.412920645 +0200 +@@ -39,13 +39,49 @@ typedef struct { + gint32 maxpos; + } GtkWidgetState; + ++/** ++ * A size in the same GTK pixel units as GtkBorder and GdkRectangle. ++ */ ++struct MozGtkSize { ++ gint width; ++ gint height; ++ ++ MozGtkSize& operator+=(const GtkBorder& aBorder) ++ { ++ width += aBorder.left + aBorder.right; ++ height += aBorder.top + aBorder.bottom; ++ return *this; ++ } ++ MozGtkSize operator+(const GtkBorder& aBorder) const ++ { ++ MozGtkSize result = *this; ++ return result += aBorder; ++ } ++ void Include(MozGtkSize aOther) ++ { ++ width = std::max(width, aOther.width); ++ height = std::max(height, aOther.height); ++ } ++ void Rotate() ++ { ++ gint tmp = width; ++ width = height; ++ height = tmp; ++ } ++}; ++ + typedef struct { +- gint slider_width; +- gint trough_border; +- gint stepper_size; +- gint stepper_spacing; +- gint min_slider_size; +-} MozGtkScrollbarMetrics; ++ bool initialized; ++ struct { ++ MozGtkSize scrollbar; ++ MozGtkSize thumb; ++ MozGtkSize button; ++ } size; ++ struct { ++ GtkBorder scrollbar; ++ GtkBorder track; ++ } border; ++} ScrollbarGTKMetrics; + + typedef enum { + MOZ_GTK_STEPPER_DOWN = 1 << 0, +@@ -67,9 +103,6 @@ typedef enum { + MOZ_GTK_TAB_SELECTED = 1 << 10 + } GtkTabFlags; + +-/* function type for moz_gtk_enable_style_props */ +-typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint); - -- mButtonStyle = create_context(path); -- gtk_style_context_add_class(mButtonStyle, GTK_STYLE_CLASS_BUTTON); + /*** result/error codes ***/ + #define MOZ_GTK_SUCCESS 0 + #define MOZ_GTK_UNKNOWN_WIDGET -1 +@@ -272,13 +305,9 @@ typedef enum { + gint moz_gtk_init(); + + /** +- * Enable GTK+ 1.2.9+ theme enhancements. You must provide a pointer +- * to the GTK+ 1.2.9+ function "gtk_style_get_prop_experimental". +- * styleGetProp: pointer to gtk_style_get_prop_experimental +- * +- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise ++ * Updates the drawing library when the theme changes. + */ +-gint moz_gtk_enable_style_props(style_prop_t styleGetProp); ++void moz_gtk_refresh(); + + /** + * Perform cleanup of the drawing library. You should call this function +@@ -432,13 +461,10 @@ gint + moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height); + + /** +- * Get the desired metrics for a GtkScrollbar +- * metrics: [IN] struct which will contain the metrics +- * +- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise ++ * Get the metrics in GTK pixels for a scrollbar. + */ +-gint +-moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics* metrics); ++const ScrollbarGTKMetrics* ++GetScrollbarMetrics(GtkOrientation aOrientation); + + /** + * Get the desired size of a dropdown arrow button +@@ -518,30 +544,11 @@ gint moz_gtk_get_menu_separator_height(g + gint moz_gtk_splitter_get_metrics(gint orientation, gint* size); + + /** +- * Retrieve an actual GTK scrollbar widget for style analysis. It will not +- * be modified. +- */ +-GtkWidget* moz_gtk_get_scrollbar_widget(void); - - // Scrollbar colors -- style = create_context(path); -- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SCROLLBAR); -- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH); -+ style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); - sMozScrollbar = GDK_RGBA_TO_NS_RGBA(color); -- g_object_unref(style); -+ ReleaseStyleContext(style); - - // Window colors -- style = create_context(path); -- gtk_style_context_save(style); -- gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND); -+ style = ClaimStyleContext(MOZ_GTK_WINDOW); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); - sMozWindowBackground = GDK_RGBA_TO_NS_RGBA(color); - 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); -+ ReleaseStyleContext(style); - - // tooltip foreground and 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); -- { -- 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); - ReleaseStyleContext(style); +-/** + * Get the YTHICKNESS of a tab (notebook extension). + */ + gint + moz_gtk_get_tab_thickness(WidgetNodeType aNodeType); -- // menu foreground & menu background -- GtkWidget *accel_label = gtk_accel_label_new("M"); -- GtkWidget *menuitem = gtk_menu_item_new(); -- GtkWidget *menu = gtk_menu_new(); -- -- g_object_ref_sink(menu); +-/** +- * Get a boolean which indicates whether the theme draws scrollbar buttons. +- * If TRUE, draw scrollbar buttons. +- */ +-gboolean moz_gtk_has_scrollbar_buttons(void); - -- gtk_container_add(GTK_CONTAINER(menuitem), accel_label); -- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); +-/** +- * Get minimum widget size as sum of margin, padding, border and min-width, +- * min-height. +- */ +-void moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, +- int* height); - -- style = gtk_widget_get_style_context(accel_label); -+ style = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); -- sMenuText = GDK_RGBA_TO_NS_RGBA(color); -- gtk_style_context_get_color(style, GTK_STATE_FLAG_INSENSITIVE, &color); -- sMenuTextInactive = GDK_RGBA_TO_NS_RGBA(color); -+ sInfoText = GDK_RGBA_TO_NS_RGBA(color); -+ ReleaseStyleContext(style); + #if (MOZ_WIDGET_GTK == 2) + #ifdef __cplusplus + } +diff -up firefox-53.0/widget/gtk/mozgtk/mozgtk.c.widget-rebase firefox-53.0/widget/gtk/mozgtk/mozgtk.c +diff -up firefox-53.0/widget/gtk/nsLookAndFeel.cpp.widget-rebase firefox-53.0/widget/gtk/nsLookAndFeel.cpp +--- firefox-53.0/widget/gtk/nsLookAndFeel.cpp.widget-rebase 2017-04-11 06:15:20.000000000 +0200 ++++ firefox-53.0/widget/gtk/nsLookAndFeel.cpp 2017-04-18 10:22:45.333920935 +0200 +@@ -18,7 +18,7 @@ + + #include <fontconfig/fontconfig.h> + #include "gfxPlatformGtk.h" +-#include "nsScreenGtk.h" ++#include "ScreenHelperGTK.h" + + #include "gtkdrawing.h" + #include "nsStyleConsts.h" +@@ -49,9 +49,9 @@ nsLookAndFeel::nsLookAndFeel() + mStyle(nullptr), + #endif + mDefaultFontCached(false), mButtonFontCached(false), +- mFieldFontCached(false), mMenuFontCached(false) ++ mFieldFontCached(false), mMenuFontCached(false), ++ mInitialized(false) + { +- Init(); + } -- style = gtk_widget_get_style_context(menu); -+ style = ClaimStyleContext(MOZ_GTK_MENUITEM); -+ { -+ GtkStyleContext* accelStyle = -+ CreateStyleForWidget(gtk_accel_label_new("M"), style); -+ gtk_style_context_get_color(accelStyle, GTK_STATE_FLAG_NORMAL, &color); -+ sMenuText = GDK_RGBA_TO_NS_RGBA(color); -+ gtk_style_context_get_color(accelStyle, GTK_STATE_FLAG_INSENSITIVE, &color); -+ sMenuTextInactive = GDK_RGBA_TO_NS_RGBA(color); -+ g_object_unref(accelStyle); -+ } -+ ReleaseStyleContext(style); + nsLookAndFeel::~nsLookAndFeel() +@@ -223,6 +223,8 @@ GetBorderColors(GtkStyleContext* aContex + nsresult + nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + { ++ EnsureInit(); + -+ style = ClaimStyleContext(MOZ_GTK_MENUPOPUP); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); - sMenuBackground = GDK_RGBA_TO_NS_RGBA(color); -+ ReleaseStyleContext(style); - -- style = gtk_widget_get_style_context(menuitem); -+ style = ClaimStyleContext(MOZ_GTK_MENUITEM); - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_PRELIGHT, &color); - sMenuHover = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); - sMenuHoverText = GDK_RGBA_TO_NS_RGBA(color); -- -- g_object_unref(menu); -+ ReleaseStyleContext(style); + #if (MOZ_WIDGET_GTK == 3) + GdkRGBA gdk_color; #endif +@@ -674,6 +676,11 @@ nsLookAndFeel::GetIntImpl(IntID aID, int + return res; + res = NS_OK; + ++ // We use delayed initialization by EnsureInit() here ++ // to make sure mozilla::Preferences is available (Bug 115807). ++ // eIntID_UseAccessibilityTheme is requested before user preferences ++ // are read, and so EnsureInit(), which depends on preference values, ++ // is deliberately delayed until required. + switch (aID) { + case eIntID_CaretBlinkTime: + { +@@ -777,11 +784,11 @@ nsLookAndFeel::GetIntImpl(IntID aID, int + aResult = threshold; + } + break; +- case eIntID_ScrollArrowStyle: +- moz_gtk_init(); +- aResult = +- ConvertGTKStepperStyleToMozillaScrollArrowStyle(moz_gtk_get_scrollbar_widget()); ++ case eIntID_ScrollArrowStyle: { ++ GtkWidget* scrollbar = GetWidget(MOZ_GTK_SCROLLBAR_HORIZONTAL); ++ aResult = ConvertGTKStepperStyleToMozillaScrollArrowStyle(scrollbar); + break; ++ } + case eIntID_ScrollSliderStyle: + aResult = eScrollThumbStyle_Proportional; + break; +@@ -836,6 +843,7 @@ nsLookAndFeel::GetIntImpl(IntID aID, int + aResult = NS_STYLE_TEXT_DECORATION_STYLE_WAVY; + break; + case eIntID_MenuBarDrag: ++ EnsureInit(); + aResult = sMenuSupportsDrag; + break; + case eIntID_ScrollbarButtonAutoRepeatBehavior: +@@ -876,6 +884,7 @@ nsLookAndFeel::GetFloatImpl(FloatID aID, + aResult = 1.0f; + break; + case eFloatID_CaretAspectRatio: ++ EnsureInit(); + aResult = sCaretRatio; + break; + default: +@@ -925,7 +934,7 @@ GetSystemFontInfo(GtkWidget *aWidget, + // Scale fonts up on HiDPI displays. + // This would be done automatically with cairo, but we manually manage + // the display scale for platform consistency. +- size *= nsScreenGtk::GetGtkMonitorScaleFactor(); ++ size *= ScreenHelperGTK::GetGTKMonitorScaleFactor(); - // button styles -@@ -1211,9 +1204,6 @@ nsLookAndFeel::Init() - GtkWidget *combobox = gtk_combo_box_new(); - GtkWidget *comboboxLabel = gtk_label_new("M"); - gtk_container_add(GTK_CONTAINER(combobox), comboboxLabel); --#else -- GtkWidget *combobox = gtk_combo_box_new_with_entry(); -- GtkWidget *comboboxLabel = gtk_bin_get_child(GTK_BIN(combobox)); - #endif - GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP); - GtkWidget *treeView = gtk_tree_view_new(); -@@ -1227,7 +1217,9 @@ nsLookAndFeel::Init() - gtk_container_add(GTK_CONTAINER(parent), button); - gtk_container_add(GTK_CONTAINER(parent), treeView); - gtk_container_add(GTK_CONTAINER(parent), linkButton); -+#if (MOZ_WIDGET_GTK == 2) - gtk_container_add(GTK_CONTAINER(parent), combobox); -+#endif - gtk_container_add(GTK_CONTAINER(parent), menuBar); - gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), menuBarItem); - gtk_container_add(GTK_CONTAINER(window), parent); -@@ -1310,11 +1302,19 @@ nsLookAndFeel::Init() - } - #else - // Text colors -- style = gtk_widget_get_style_context(textView); -- gtk_style_context_save(style); -- gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW); -- gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); -- sMozFieldBackground = GDK_RGBA_TO_NS_RGBA(color); -+ GdkRGBA bgColor; -+ // If the text window background is translucent, then the background of -+ // the textview root node is visible. -+ style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW); -+ gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, -+ &bgColor); -+ ReleaseStyleContext(style); -+ -+ style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW_TEXT); -+ gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, -+ &color); -+ ApplyColorOver(color, &bgColor); -+ sMozFieldBackground = GDK_RGBA_TO_NS_RGBA(bgColor); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); - sMozFieldText = GDK_RGBA_TO_NS_RGBA(color); + // |size| is now pixels -@@ -1327,26 +1327,34 @@ nsLookAndFeel::Init() - static_cast<GtkStateFlags>(GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_SELECTED), - &color); - sTextSelectedText = GDK_RGBA_TO_NS_RGBA(color); -- gtk_style_context_restore(style); -+ ReleaseStyleContext(style); +@@ -1056,11 +1065,15 @@ nsLookAndFeel::GetFontImpl(FontID aID, n + } -- // Button text, background, border -- style = gtk_widget_get_style_context(label); -- gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); -- sButtonText = GDK_RGBA_TO_NS_RGBA(color); -- gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); -- sButtonHoverText = GDK_RGBA_TO_NS_RGBA(color); -+ // Button text color -+ style = ClaimStyleContext(MOZ_GTK_BUTTON); -+ { -+ GtkStyleContext* labelStyle = -+ CreateStyleForWidget(gtk_label_new("M"), style); -+ gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_NORMAL, &color); -+ sButtonText = GDK_RGBA_TO_NS_RGBA(color); -+ gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_PRELIGHT, &color); -+ sButtonHoverText = GDK_RGBA_TO_NS_RGBA(color); -+ g_object_unref(labelStyle); -+ } -+ ReleaseStyleContext(style); + void +-nsLookAndFeel::Init() ++nsLookAndFeel::EnsureInit() + { + GdkColor colorValue; + GdkColor *colorValuePtr; - // Combobox text color -- style = gtk_widget_get_style_context(comboboxLabel); -+ style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); - sComboBoxText = GDK_RGBA_TO_NS_RGBA(color); -+ ReleaseStyleContext(style); ++ if (mInitialized) ++ return; ++ mInitialized = true; ++ + #if (MOZ_WIDGET_GTK == 2) + NS_ASSERTION(!mStyle, "already initialized"); + // GtkInvisibles come with a refcount that is not floating +@@ -1133,16 +1146,39 @@ nsLookAndFeel::Init() + // with wrong color theme, see Bug 972382 + GtkSettings *settings = gtk_settings_get_for_screen(gdk_screen_get_default()); + +- // Disable dark theme because it interacts poorly with widget styling in +- // web content (see bug 1216658). ++ // Dark themes interacts poorly with widget styling (see bug 1216658). ++ // We disable dark themes by default for all processes (chrome, web content) ++ // but allow user to overide it by prefs. ++ const gchar* dark_setting = "gtk-application-prefer-dark-theme"; ++ gboolean darkThemeDefault; ++ g_object_get(settings, dark_setting, &darkThemeDefault, nullptr); ++ + // To avoid triggering reload of theme settings unnecessarily, only set the + // setting when necessary. +- const gchar* dark_setting = "gtk-application-prefer-dark-theme"; +- gboolean dark; +- g_object_get(settings, dark_setting, &dark, nullptr); ++ if (darkThemeDefault) { ++ bool allowDarkTheme; ++ if (XRE_IsContentProcess()) { ++ allowDarkTheme = ++ mozilla::Preferences::GetBool("widget.content.allow-gtk-dark-theme", ++ false); ++ } else { ++ allowDarkTheme = (PR_GetEnv("MOZ_ALLOW_GTK_DARK_THEME") != nullptr) || ++ mozilla::Preferences::GetBool("widget.chrome.allow-gtk-dark-theme", ++ false); ++ } ++ if (!allowDarkTheme) { ++ g_object_set(settings, dark_setting, FALSE, nullptr); ++ } ++ } - // Menubar text and hover text colors -- style = gtk_widget_get_style_context(menuBarItem); -+ style = ClaimStyleContext(MOZ_GTK_MENUBARITEM); - gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); - sMenuBarText = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); - sMenuBarHoverText = GDK_RGBA_TO_NS_RGBA(color); -+ ReleaseStyleContext(style); +- if (dark && !PR_GetEnv("MOZ_ALLOW_GTK_DARK_THEME")) { +- g_object_set(settings, dark_setting, FALSE, nullptr); ++ // Allow content Gtk theme override by pref, it's useful when styled Gtk+ ++ // widgets break web content. ++ if (XRE_IsContentProcess()) { ++ auto contentThemeName = ++ mozilla::Preferences::GetCString("widget.content.gtk-theme-override"); ++ if (!contentThemeName.IsEmpty()) { ++ g_object_set(settings, "gtk-theme-name", contentThemeName.get(), nullptr); ++ } + } - // GTK's guide to fancy odd row background colors: - // 1) Check if a theme explicitly defines an odd row color -@@ -1354,7 +1362,7 @@ nsLookAndFeel::Init() - // slightly by a hardcoded value (gtkstyle.c) - // 3) If neither are defined, take the base background color and - // darken that by a hardcoded value -- style = gtk_widget_get_style_context(treeView); -+ style = ClaimStyleContext(MOZ_GTK_TREEVIEW); + // Scrollbar colors +@@ -1438,6 +1474,7 @@ nsLookAndFeel::Init() + char16_t + nsLookAndFeel::GetPasswordCharacterImpl() + { ++ EnsureInit(); + return sInvisibleCharacter; + } - // Get odd row background color - gtk_style_context_save(style); -@@ -1362,8 +1370,7 @@ nsLookAndFeel::Init() - gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); - sOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); - gtk_style_context_restore(style); -- -- gtk_widget_path_free(path); -+ ReleaseStyleContext(style); +@@ -1445,6 +1482,7 @@ void + nsLookAndFeel::RefreshImpl() + { + nsXPLookAndFeel::RefreshImpl(); ++ moz_gtk_refresh(); - // GtkFrame has a "border" subnode on which Adwaita draws the border. - // Some themes do not draw on this node but draw a border on the widget -@@ -1448,12 +1455,6 @@ nsLookAndFeel::RefreshImpl() - #if (MOZ_WIDGET_GTK == 2) - g_object_unref(mStyle); + mDefaultFontCached = false; + mButtonFontCached = false; +@@ -1456,7 +1494,7 @@ nsLookAndFeel::RefreshImpl() mStyle = nullptr; --#else -- g_object_unref(mBackgroundStyle); -- g_object_unref(mButtonStyle); -- -- mBackgroundStyle = nullptr; -- mButtonStyle = nullptr; #endif - Init(); -diff -up firefox-52.0/widget/gtk/WidgetStyleCache.cpp.widget-rebase firefox-52.0/widget/gtk/WidgetStyleCache.cpp ---- firefox-52.0/widget/gtk/WidgetStyleCache.cpp.widget-rebase 2017-02-27 17:11:05.000000000 +0100 -+++ firefox-52.0/widget/gtk/WidgetStyleCache.cpp 2017-03-10 12:20:30.235205976 +0100 -@@ -434,15 +434,6 @@ CreateScrolledWindowWidget() +- Init(); ++ mInitialized = false; } - 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(); -@@ -591,8 +582,6 @@ CreateWidget(WidgetNodeType aWidgetType) - return CreateEntryWidget(); - case MOZ_GTK_SCROLLED_WINDOW: - return CreateScrolledWindowWidget(); -- case MOZ_GTK_TEXT_VIEW: -- return CreateTextViewWidget(); - case MOZ_GTK_TREEVIEW: - return CreateTreeViewWidget(); - case MOZ_GTK_TREE_HEADER_CELL: -@@ -744,16 +733,38 @@ GetWidgetRootStyle(WidgetNodeType aNodeT - case MOZ_GTK_MENUITEM: - style = CreateStyleForWidget(gtk_menu_item_new(), MOZ_GTK_MENUPOPUP); - break; -- case MOZ_GTK_IMAGEMENUITEM: -- style = CreateStyleForWidget(gtk_image_menu_item_new(), MOZ_GTK_MENUPOPUP); -- break; -- case MOZ_GTK_CHECKMENUITEM_CONTAINER: -+ case MOZ_GTK_CHECKMENUITEM: - style = CreateStyleForWidget(gtk_check_menu_item_new(), MOZ_GTK_MENUPOPUP); - break; -- case MOZ_GTK_RADIOMENUITEM_CONTAINER: -+ case MOZ_GTK_RADIOMENUITEM: - style = CreateStyleForWidget(gtk_radio_menu_item_new(nullptr), - MOZ_GTK_MENUPOPUP); - break; -+ case MOZ_GTK_TEXT_VIEW: -+ style = CreateStyleForWidget(gtk_text_view_new(), -+ MOZ_GTK_SCROLLED_WINDOW); -+ break; -+ case MOZ_GTK_TOOLTIP: -+ if (gtk_check_version(3, 20, 0) != nullptr) { -+ // The tooltip style class is added first in CreateTooltipWidget() -+ // and transfered to style in CreateStyleForWidget(). -+ GtkWidget* tooltipWindow = CreateTooltipWidget(); -+ style = CreateStyleForWidget(tooltipWindow, nullptr); -+ gtk_widget_destroy(tooltipWindow); // Release GtkWindow self-reference. -+ } else { -+ // 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_TOOLTIP_BOX: -+ style = CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), -+ MOZ_GTK_TOOLTIP); -+ break; -+ case MOZ_GTK_TOOLTIP_BOX_LABEL: -+ style = CreateStyleForWidget(gtk_label_new(nullptr), -+ MOZ_GTK_TOOLTIP_BOX); -+ break; - default: - GtkWidget* widget = GetWidget(aNodeType); - MOZ_ASSERT(widget); -@@ -827,13 +838,13 @@ GetCssNodeStyleInternal(WidgetNodeType a - style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK, - MOZ_GTK_CHECKBUTTON_CONTAINER); - break; -- case MOZ_GTK_RADIOMENUITEM: -+ case MOZ_GTK_RADIOMENUITEM_INDICATOR: - style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO, -- MOZ_GTK_RADIOMENUITEM_CONTAINER); -+ MOZ_GTK_RADIOMENUITEM); - break; -- case MOZ_GTK_CHECKMENUITEM: -+ case MOZ_GTK_CHECKMENUITEM_INDICATOR: - style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK, -- MOZ_GTK_CHECKMENUITEM_CONTAINER); -+ MOZ_GTK_CHECKMENUITEM); - break; - case MOZ_GTK_PROGRESS_TROUGH: - /* Progress bar background (trough) */ -@@ -844,11 +855,6 @@ GetCssNodeStyleInternal(WidgetNodeType a - 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, -@@ -865,10 +871,28 @@ GetCssNodeStyleInternal(WidgetNodeType a - // 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); -+ case MOZ_GTK_TEXT_VIEW_TEXT: -+ case MOZ_GTK_RESIZER: -+ style = CreateChildCSSNode("text", MOZ_GTK_TEXT_VIEW); -+ if (aNodeType == MOZ_GTK_RESIZER) { -+ // The "grip" class provides the correct builtin icon from -+ // gtk_render_handle(). The icon is drawn with shaded variants of -+ // the background color, and so a transparent background would lead to -+ // a transparent resizer. gtk_render_handle() also uses the -+ // background color to draw a background, and so this style otherwise -+ // matches what is used in GtkTextView to match the background with -+ // textarea elements. -+ GdkRGBA color; -+ gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, -+ &color); -+ if (color.alpha == 0.0) { -+ g_object_unref(style); -+ style = CreateStyleForWidget(gtk_text_view_new(), -+ MOZ_GTK_SCROLLED_WINDOW); -+ } -+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP); -+ } -+ break; - case MOZ_GTK_FRAME_BORDER: - style = CreateChildCSSNode("border", MOZ_GTK_FRAME); - break; -@@ -971,27 +995,20 @@ GetWidgetStyleInternal(WidgetNodeType aN - case MOZ_GTK_CHECKBUTTON: - return GetWidgetStyleWithClass(MOZ_GTK_CHECKBUTTON_CONTAINER, - GTK_STYLE_CLASS_CHECK); -- case MOZ_GTK_RADIOMENUITEM: -- return GetWidgetStyleWithClass(MOZ_GTK_RADIOMENUITEM_CONTAINER, -+ case MOZ_GTK_RADIOMENUITEM_INDICATOR: -+ return GetWidgetStyleWithClass(MOZ_GTK_RADIOMENUITEM, - GTK_STYLE_CLASS_RADIO); -- case MOZ_GTK_CHECKMENUITEM: -- return GetWidgetStyleWithClass(MOZ_GTK_CHECKMENUITEM_CONTAINER, -+ case MOZ_GTK_CHECKMENUITEM_INDICATOR: -+ return GetWidgetStyleWithClass(MOZ_GTK_CHECKMENUITEM, - 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; -+ case MOZ_GTK_PROGRESS_CHUNK: { -+ GtkStyleContext* style = -+ GetWidgetStyleWithClass(MOZ_GTK_PROGRESSBAR, -+ GTK_STYLE_CLASS_PROGRESSBAR); -+ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH); - return style; - } - case MOZ_GTK_GRIPPER: -@@ -1006,9 +1023,25 @@ GetWidgetStyleInternal(WidgetNodeType aN - 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); -+ case MOZ_GTK_TEXT_VIEW_TEXT: -+ case MOZ_GTK_RESIZER: { -+ // GTK versions prior to 3.20 do not have the view class on the root -+ // node, but add this to determine the background for the text window. -+ GtkStyleContext* style = -+ GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW, GTK_STYLE_CLASS_VIEW); -+ if (aNodeType == MOZ_GTK_RESIZER) { -+ // The "grip" class provides the correct builtin icon from -+ // gtk_render_handle(). The icon is drawn with shaded variants of -+ // the background color, and so a transparent background would lead to -+ // a transparent resizer. gtk_render_handle() also uses the -+ // background color to draw a background, and so this style otherwise -+ // matches MOZ_GTK_TEXT_VIEW_TEXT to match the background with -+ // textarea elements. GtkTextView creates a separate text window and -+ // so the background should not be transparent. -+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP); -+ } -+ return style; -+ } - case MOZ_GTK_FRAME_BORDER: - return GetWidgetRootStyle(MOZ_GTK_FRAME); - case MOZ_GTK_TREEVIEW_VIEW: + bool |