diff --git a/firefox.spec b/firefox.spec index e54310b..c1aefb4 100644 --- a/firefox.spec +++ b/firefox.spec @@ -150,9 +150,9 @@ Patch229: firefox-nss-version.patch Patch304: mozilla-1253216.patch Patch402: mozilla-1196777.patch Patch406: mozilla-256180.patch -# Rebase Gtk3 widget code to latest trunk to -# fix various rendering problems -Patch407: widget-rebase.patch +Patch407: mozilla-1348576.patch +Patch408: mozilla-1158076-1.patch +Patch409: mozilla-1158076-2.patch # Debian patches Patch500: mozilla-440908.patch @@ -313,9 +313,9 @@ cd %{tarballdir} %patch304 -p1 -b .1253216 %patch402 -p1 -b .1196777 %patch406 -p1 -b .256180 -# Rebase Gtk3 widget code to latest trunk to -# fix various rendering problems -%patch407 -p1 -b .widget-rebase +%patch407 -p1 -b .1348576 +%patch408 -p1 -b .1158076-1 +%patch409 -p1 -b .1158076-2 # Debian extension patch %patch500 -p1 -b .440908 diff --git a/mozilla-1158076-1.patch b/mozilla-1158076-1.patch new file mode 100644 index 0000000..1efa975 --- /dev/null +++ b/mozilla-1158076-1.patch @@ -0,0 +1,74 @@ +diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js +--- a/modules/libpref/init/all.js ++++ b/modules/libpref/init/all.js +@@ -4733,16 +4733,18 @@ pref("gfx.content.always-paint", false); + + #ifdef ANDROID + pref("gfx.apitrace.enabled",false); + #endif + + #ifdef MOZ_X11 + #ifdef MOZ_WIDGET_GTK + pref("gfx.xrender.enabled",false); ++pref("widget.chrome.allow-gtk-dark-theme", false); ++pref("widget.content.allow-gtk-dark-theme", false); + #endif + #endif + + #ifdef XP_WIN + // Whether to disable the automatic detection and use of direct2d. + pref("gfx.direct2d.disabled", false); + + // Whether to attempt to enable Direct2D regardless of automatic detection or +diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp +--- a/widget/gtk/nsLookAndFeel.cpp ++++ b/widget/gtk/nsLookAndFeel.cpp +@@ -1128,26 +1128,39 @@ nsLookAndFeel::Init() + GdkRGBA color; + GtkStyleContext *style; + + // Gtk manages a screen's CSS in the settings object so we + // ask Gtk to create it explicitly. Otherwise we may end up + // 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 (dark && !PR_GetEnv("MOZ_ALLOW_GTK_DARK_THEME")) { +- g_object_set(settings, dark_setting, FALSE, 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); ++ } + } + + // Scrollbar colors + 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); + ReleaseStyleContext(style); + + diff --git a/mozilla-1158076-2.patch b/mozilla-1158076-2.patch new file mode 100644 index 0000000..2999b1f --- /dev/null +++ b/mozilla-1158076-2.patch @@ -0,0 +1,100 @@ +diff -up firefox-53.0/widget/gtk/nsLookAndFeel.cpp.1158076-2 firefox-53.0/widget/gtk/nsLookAndFeel.cpp +--- firefox-53.0/widget/gtk/nsLookAndFeel.cpp.1158076-2 2017-04-18 13:09:01.756315856 +0200 ++++ firefox-53.0/widget/gtk/nsLookAndFeel.cpp 2017-04-18 13:10:10.615069083 +0200 +@@ -49,9 +49,9 @@ nsLookAndFeel::nsLookAndFeel() + mStyle(nullptr), + #endif + mDefaultFontCached(false), mButtonFontCached(false), +- mFieldFontCached(false), mMenuFontCached(false) ++ mFieldFontCached(false), mMenuFontCached(false), ++ mInitialized(false) + { +- Init(); + } + + nsLookAndFeel::~nsLookAndFeel() +@@ -223,6 +223,8 @@ GetBorderColors(GtkStyleContext* aContex + nsresult + nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + { ++ EnsureInit(); ++ + #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: + { +@@ -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: +@@ -1056,11 +1065,15 @@ nsLookAndFeel::GetFontImpl(FontID aID, n + } + + void +-nsLookAndFeel::Init() ++nsLookAndFeel::EnsureInit() + { + GdkColor colorValue; + GdkColor *colorValuePtr; + ++ if (mInitialized) ++ return; ++ mInitialized = true; ++ + #if (MOZ_WIDGET_GTK == 2) + NS_ASSERTION(!mStyle, "already initialized"); + // GtkInvisibles come with a refcount that is not floating +@@ -1451,6 +1464,7 @@ nsLookAndFeel::Init() + char16_t + nsLookAndFeel::GetPasswordCharacterImpl() + { ++ EnsureInit(); + return sInvisibleCharacter; + } + +@@ -1469,7 +1483,7 @@ nsLookAndFeel::RefreshImpl() + mStyle = nullptr; + #endif + +- Init(); ++ mInitialized = false; + } + + bool +diff -up firefox-53.0/widget/gtk/nsLookAndFeel.h.1158076-2 firefox-53.0/widget/gtk/nsLookAndFeel.h +--- firefox-53.0/widget/gtk/nsLookAndFeel.h.1158076-2 2017-04-11 06:15:20.000000000 +0200 ++++ firefox-53.0/widget/gtk/nsLookAndFeel.h 2017-04-18 13:09:01.759315845 +0200 +@@ -81,8 +81,9 @@ protected: + char16_t sInvisibleCharacter; + float sCaretRatio; + bool sMenuSupportsDrag; ++ bool mInitialized; + +- void Init(); ++ void EnsureInit(); + }; + + #endif diff --git a/mozilla-1348576.patch b/mozilla-1348576.patch new file mode 100644 index 0000000..ce6dad2 --- /dev/null +++ b/mozilla-1348576.patch @@ -0,0 +1,47 @@ +diff -up firefox-53.0/browser/extensions/e10srollout/bootstrap.js.1348576 firefox-53.0/browser/extensions/e10srollout/bootstrap.js +--- firefox-53.0/browser/extensions/e10srollout/bootstrap.js.1348576 2017-04-18 13:06:29.660860929 +0200 ++++ firefox-53.0/browser/extensions/e10srollout/bootstrap.js 2017-04-18 13:07:34.804627469 +0200 +@@ -9,6 +9,7 @@ const {classes: Cc, interfaces: Ci, util + Cu.import("resource://gre/modules/Preferences.jsm"); + Cu.import("resource://gre/modules/Services.jsm"); + Cu.import("resource://gre/modules/UpdateUtils.jsm"); ++Cu.import("resource://gre/modules/AppConstants.jsm"); + + // The amount of people to be part of e10s + const TEST_THRESHOLD = { +@@ -23,6 +24,23 @@ const ADDON_ROLLOUT_POLICY = { + "esr" : "esrA", // WebExtensions and Addons with mpc=true + }; + ++if (AppConstants.RELEASE_OR_BETA) { ++ // Bug 1348576 - e10s is never enabled for non-official release builds ++ // This is hacky, but the problem it solves is the following: ++ // the e10s rollout is controlled by the channel name, which ++ // is the only way to distinguish between Beta and Release. ++ // However, non-official release builds (like the ones done by distros ++ // to ship Firefox on their package managers) do not set a value ++ // for the release channel, which gets them to the default value ++ // of.. (drumroll) "default". ++ // But we can't just always configure the same settings for the ++ // "default" channel because that's also the name that a locally ++ // built Firefox gets, and e10s is managed in a different way ++ // there (directly by prefs, on Nightly and Aurora). ++ TEST_THRESHOLD.default = TEST_THRESHOLD.release; ++ ADDON_ROLLOUT_POLICY.default = ADDON_ROLLOUT_POLICY.release; ++} ++ + const PREF_COHORT_SAMPLE = "e10s.rollout.cohortSample"; + const PREF_COHORT_NAME = "e10s.rollout.cohort"; + const PREF_E10S_OPTED_IN = "browser.tabs.remote.autostart"; +diff -up firefox-53.0/browser/extensions/e10srollout/install.rdf.in.1348576 firefox-53.0/browser/extensions/e10srollout/install.rdf.in +--- firefox-53.0/browser/extensions/e10srollout/install.rdf.in.1348576 2017-04-11 06:15:16.000000000 +0200 ++++ firefox-53.0/browser/extensions/e10srollout/install.rdf.in 2017-04-18 13:06:29.660860929 +0200 +@@ -10,7 +10,7 @@ + + + e10srollout@mozilla.org +- 1.14 ++ 1.15 + 2 + true + true diff --git a/widget-rebase.patch b/widget-rebase.patch deleted file mode 100644 index 59cc4a1..0000000 --- a/widget-rebase.patch +++ /dev/null @@ -1,862 +0,0 @@ -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 - --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 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 -@@ -78,27 +80,22 @@ GetStateFlagsFromGtkTabFlags(GtkTabFlags - } - - gint --moz_gtk_enable_style_props(style_prop_t styleGetProp) --{ -- style_prop_func = styleGetProp; -- return MOZ_GTK_SUCCESS; --} -- --gint - moz_gtk_init() - { -- 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; -+} -+ -+void -+moz_gtk_refresh() -+{ - 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; - } - -- return MOZ_GTK_SUCCESS; -+ sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; -+ sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; - } - - 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; - } - --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}; -+} -+ -+/** -+ * 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) - { -@@ -466,6 +479,14 @@ moz_gtk_get_widget_min_size(WidgetNodeTy - padding.top + padding.bottom; - } - -+static MozGtkSize -+GetMinMarginBox(WidgetNodeType aNodeType) -+{ -+ gint width, height; -+ moz_gtk_get_widget_min_size(aNodeType, &width, &height); -+ return {width, height}; -+} -+ - 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; -+ } - } - - gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); -@@ -629,12 +654,37 @@ moz_gtk_draw_styled_frame(GtkStyleContex - - static gint - moz_gtk_scrollbar_trough_paint(WidgetNodeType widget, -- cairo_t *cr, const GdkRectangle* rect, -+ cairo_t *cr, const GdkRectangle* aRect, - GtkWidgetState* state, - GtkTextDirection direction) - { -- 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 { -+ style = ClaimStyleContext(widget, direction); -+ } -+ -+ moz_gtk_draw_styled_frame(style, cr, &rect, state->focused); - ReleaseStyleContext(style); - - 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); - } - -+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 - - return MOZ_GTK_SUCCESS; - } -- 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; -- } -- 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) - { -- WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ? -- MOZ_GTK_SCALE_HORIZONTAL : -- MOZ_GTK_SCALE_VERTICAL; -- - if (gtk_check_version(3, 20, 0) != nullptr) { -+ WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ? -+ MOZ_GTK_SCALE_HORIZONTAL : -+ MOZ_GTK_SCALE_VERTICAL; -+ - gint thumb_length, thumb_height, trough_border; - moz_gtk_get_scalethumb_metrics(orient, &thumb_length, &thumb_height); - -@@ -2518,12 +2530,10 @@ moz_gtk_get_scale_metrics(GtkOrientation - } - ReleaseStyleContext(style); - } else { -- GtkStyleContext* style = ClaimStyleContext(widget); -- gtk_style_context_get(style, gtk_style_context_get_state(style), -- "min-width", scale_width, -- "min-height", scale_height, -- nullptr); -- ReleaseStyleContext(style); -+ WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ? -+ MOZ_GTK_SCALE_TROUGH_HORIZONTAL : -+ MOZ_GTK_SCALE_TROUGH_VERTICAL; -+ moz_gtk_get_widget_min_size(widget, scale_width, scale_height); - } - } - -@@ -2546,33 +2556,176 @@ moz_gtk_get_scalethumb_metrics(GtkOrient - MOZ_GTK_SCALE_THUMB_HORIZONTAL: - MOZ_GTK_SCALE_THUMB_VERTICAL; - GtkStyleContext* style = ClaimStyleContext(widget); -- gtk_style_context_get(style, gtk_style_context_get_state(style), -- "min-width", thumb_length, -- "min-height", thumb_height, -+ -+ gint min_width, min_height; -+ GtkStateFlags state = gtk_style_context_get_state(style); -+ gtk_style_context_get(style, state, -+ "min-width", &min_width, -+ "min-height", &min_height, - nullptr); -+ GtkBorder margin; -+ gtk_style_context_get_margin(style, state, &margin); -+ gint margin_width = margin.left + margin.right; -+ gint margin_height = margin.top + margin.bottom; -+ -+ // Negative margin of slider element also determines its minimal size -+ // so use bigger of those two values. -+ if (min_width < -margin_width) -+ min_width = -margin_width; -+ if (min_height < -margin_height) -+ min_height = -margin_height; -+ -+ *thumb_length = min_width; -+ *thumb_height = min_height; -+ - ReleaseStyleContext(style); - } - - return MOZ_GTK_SUCCESS; - } - --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}); -+} -+ -+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); -+ -+ 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; -+ } -+ -+ // 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; -+ } -+ // 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}; -+ } -+ 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; -+ } -+ } -+ -+ 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; - } - --GtkWidget* moz_gtk_get_scrollbar_widget(void) --{ -- return GetWidget(MOZ_GTK_SCROLLBAR_HORIZONTAL); --} -- --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() - { - /* This will destroy all of our widgets */ - ResetWidgetCache(); - -- is_initialized = FALSE; -- - 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); -- - /*** 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); -- --/** - * Get the YTHICKNESS of a tab (notebook extension). - */ - gint - moz_gtk_get_tab_thickness(WidgetNodeType aNodeType); - --/** -- * Get a boolean which indicates whether the theme draws scrollbar buttons. -- * If TRUE, draw scrollbar buttons. -- */ --gboolean moz_gtk_has_scrollbar_buttons(void); -- --/** -- * 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); -- - #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 - #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(); - } - - nsLookAndFeel::~nsLookAndFeel() -@@ -223,6 +223,8 @@ GetBorderColors(GtkStyleContext* aContex - nsresult - nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) - { -+ EnsureInit(); -+ - #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(); - - // |size| is now pixels - -@@ -1056,11 +1065,15 @@ nsLookAndFeel::GetFontImpl(FontID aID, n - } - - void --nsLookAndFeel::Init() -+nsLookAndFeel::EnsureInit() - { - GdkColor colorValue; - GdkColor *colorValuePtr; - -+ 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); -+ } -+ } - -- 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); -+ } - } - - // Scrollbar colors -@@ -1438,6 +1474,7 @@ nsLookAndFeel::Init() - char16_t - nsLookAndFeel::GetPasswordCharacterImpl() - { -+ EnsureInit(); - return sInvisibleCharacter; - } - -@@ -1445,6 +1482,7 @@ void - nsLookAndFeel::RefreshImpl() - { - nsXPLookAndFeel::RefreshImpl(); -+ moz_gtk_refresh(); - - mDefaultFontCached = false; - mButtonFontCached = false; -@@ -1456,7 +1494,7 @@ nsLookAndFeel::RefreshImpl() - mStyle = nullptr; - #endif - -- Init(); -+ mInitialized = false; - } - - bool