summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Stransky <stransky@redhat.com>2017-10-23 20:35:03 +0200
committerMartin Stransky <stransky@redhat.com>2017-10-23 20:35:03 +0200
commit38da98e3f8ee0ca484405dee28044c54c5495737 (patch)
tree2490776d35520191c0d0f4ad08282dff03ec2ba0
parentMerge branch 'master' into f26 (diff)
parentUpdated to FF57Beta9 (diff)
downloadlibrewolf-fedora-ff-38da98e3f8ee0ca484405dee28044c54c5495737.tar.gz
librewolf-fedora-ff-38da98e3f8ee0ca484405dee28044c54c5495737.tar.bz2
librewolf-fedora-ff-38da98e3f8ee0ca484405dee28044c54c5495737.zip
Merge branch 'master' into f26
-rw-r--r--.gitignore10
-rw-r--r--build-jit-atomic-always-lucky.patch32
-rw-r--r--firefox-build-prbool.patch44
-rw-r--r--firefox-mozconfig2
-rw-r--r--firefox.spec60
-rw-r--r--mozilla-1399611.patch1744
-rw-r--r--mozilla-1405267.patch19
-rw-r--r--rhbz-1497932.patch21
-rw-r--r--sources4
-rw-r--r--xulrunner-24.0-jemalloc-ppc.patch8
10 files changed, 1806 insertions, 138 deletions
diff --git a/.gitignore b/.gitignore
index a40dbb6..eac0742 100644
--- a/.gitignore
+++ b/.gitignore
@@ -249,3 +249,13 @@ firefox-3.6.4.source.tar.bz2
/firefox-56.0.source.tar.xz
/firefox-langpacks-56.0-20170925.tar.xz
/firefox-langpacks-56.0-20170927.tar.xz
+/firefox-57.0b5.source.tar.xz
+/firefox-langpacks-57.0b5-20171005.tar.xz
+/firefox-57.0b6.source.tar.xz
+/firefox-langpacks-57.0b6-20171009.tar.xz
+/firefox-57.0b7.source.tar.xz
+/firefox-langpacks-57.0b7-20171011.tar.xz
+/firefox-57.0b8.source.tar.xz
+/firefox-langpacks-57.0b8-20171016.tar.xz
+/firefox-57.0b9.source.tar.xz
+/firefox-langpacks-57.0b9-20171019.tar.xz
diff --git a/build-jit-atomic-always-lucky.patch b/build-jit-atomic-always-lucky.patch
index d6812b6..31bc5ec 100644
--- a/build-jit-atomic-always-lucky.patch
+++ b/build-jit-atomic-always-lucky.patch
@@ -1,19 +1,19 @@
-diff -up firefox-55.0.2/js/src/jit/AtomicOperations.h.jit-atomic-lucky firefox-55.0.2/js/src/jit/AtomicOperations.h
---- firefox-55.0.2/js/src/jit/AtomicOperations.h.jit-atomic-lucky 2017-07-31 18:20:47.000000000 +0200
-+++ firefox-55.0.2/js/src/jit/AtomicOperations.h 2017-08-29 12:59:52.870926044 +0200
-@@ -348,7 +348,7 @@ AtomicOperations::isLockfree(int32_t siz
- # elif defined(__sh__)
- # include "jit/none/AtomicOperations-feeling-lucky.h"
- # else
--# include "jit/none/AtomicOperations-none.h" // These MOZ_CRASH() always
-+# include "jit/none/AtomicOperations-feeling-lucky.h"
- # endif
- #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
- # include "jit/x86-shared/AtomicOperations-x86-shared.h"
-diff -up firefox-55.0.2/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky firefox-55.0.2/js/src/jit/none/AtomicOperations-feeling-lucky.h
---- firefox-55.0.2/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky 2017-08-29 14:10:52.665031524 +0200
-+++ firefox-55.0.2/js/src/jit/none/AtomicOperations-feeling-lucky.h 2017-08-29 14:09:40.756060235 +0200
-@@ -60,6 +60,14 @@
+diff -up firefox-57.0b5/js/src/jit/AtomicOperations.h.jit-atomic-lucky firefox-57.0b5/js/src/jit/AtomicOperations.h
+--- firefox-57.0b5/js/src/jit/AtomicOperations.h.jit-atomic-lucky 2017-10-06 12:34:02.338973607 +0200
++++ firefox-57.0b5/js/src/jit/AtomicOperations.h 2017-10-06 12:38:24.632622215 +0200
+@@ -415,7 +415,7 @@ AtomicOperations::isLockfreeJS(int32_t s
+ #elif defined(__s390__) || defined(__s390x__)
+ # include "jit/none/AtomicOperations-feeling-lucky.h"
+ #else
+-# error "No AtomicOperations support provided for this platform"
++# include "jit/none/AtomicOperations-feeling-lucky.h"
+ #endif
+
+ #endif // jit_AtomicOperations_h
+diff -up firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h
+--- firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h.jit-atomic-lucky 2017-09-19 06:18:28.000000000 +0200
++++ firefox-57.0b5/js/src/jit/none/AtomicOperations-feeling-lucky.h 2017-10-06 12:34:02.338973607 +0200
+@@ -79,6 +79,14 @@
# define GNUC_COMPATIBLE
#endif
diff --git a/firefox-build-prbool.patch b/firefox-build-prbool.patch
deleted file mode 100644
index 17725af..0000000
--- a/firefox-build-prbool.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-diff -up firefox-53.0/dom/u2f/U2F.cpp.prbool firefox-53.0/dom/u2f/U2F.cpp
---- firefox-53.0/dom/u2f/U2F.cpp.prbool 2017-04-11 06:15:14.000000000 +0200
-+++ firefox-53.0/dom/u2f/U2F.cpp 2017-04-18 09:19:20.524285200 +0200
-@@ -4,6 +4,7 @@
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-+#include "prtypes.h"
- #include "hasht.h"
- #include "mozilla/dom/CallbackFunction.h"
- #include "mozilla/dom/ContentChild.h"
-diff -up firefox-53.0/security/certverifier/CTLogVerifier.cpp.prbool firefox-53.0/security/certverifier/CTLogVerifier.cpp
---- firefox-53.0/security/certverifier/CTLogVerifier.cpp.prbool 2017-04-18 09:19:20.524285200 +0200
-+++ firefox-53.0/security/certverifier/CTLogVerifier.cpp 2017-04-18 09:52:34.189402811 +0200
-@@ -9,6 +9,7 @@
- #include <stdint.h>
-
- #include "CTSerialization.h"
-+#include "prtypes.h"
- #include "hasht.h"
- #include "mozilla/ArrayUtils.h"
- #include "mozilla/Assertions.h"
-diff -up firefox-53.0/security/certverifier/CTObjectsExtractor.cpp.prbool firefox-53.0/security/certverifier/CTObjectsExtractor.cpp
---- firefox-53.0/security/certverifier/CTObjectsExtractor.cpp.prbool 2017-01-16 17:16:51.000000000 +0100
-+++ firefox-53.0/security/certverifier/CTObjectsExtractor.cpp 2017-04-18 09:19:20.525285196 +0200
-@@ -6,6 +6,7 @@
-
- #include "CTObjectsExtractor.h"
-
-+#include "prtypes.h"
- #include "hasht.h"
- #include "mozilla/Assertions.h"
- #include "mozilla/Casting.h"
-diff -up firefox-53.0/security/certverifier/OCSPCache.h.prbool firefox-53.0/security/certverifier/OCSPCache.h
---- firefox-53.0/security/certverifier/OCSPCache.h.prbool 2017-04-11 06:15:19.000000000 +0200
-+++ firefox-53.0/security/certverifier/OCSPCache.h 2017-04-18 09:19:20.525285196 +0200
-@@ -25,6 +25,7 @@
- #ifndef mozilla_psm_OCSPCache_h
- #define mozilla_psm_OCSPCache_h
-
-+#include "prtypes.h"
- #include "hasht.h"
- #include "mozilla/Mutex.h"
- #include "mozilla/Vector.h"
diff --git a/firefox-mozconfig b/firefox-mozconfig
index f3f4d15..6b4cb54 100644
--- a/firefox-mozconfig
+++ b/firefox-mozconfig
@@ -12,9 +12,7 @@ ac_add_options --disable-tests
#ac_add_options --enable-libnotify
ac_add_options --enable-necko-wifi
ac_add_options --enable-startup-notification
-#ac_add_options --disable-cpp-exceptions
ac_add_options --disable-updater
-ac_add_options --enable-url-classifier
ac_add_options --enable-chrome-format=omni
ac_add_options --enable-pulseaudio
ac_add_options --with-system-icu
diff --git a/firefox.spec b/firefox.spec
index fe2c132..f755707 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -2,9 +2,6 @@
ExcludeArch: armv7hl
%endif
-# Use ALSA backend?
-%define alsa_backend 0
-
# Use system nspr/nss?
%define system_nss 1
@@ -68,12 +65,12 @@ ExcludeArch: armv7hl
%endif
%if %{?system_nss}
-%global nspr_version 4.10.10
+%global nspr_version 4.17.0
# NSS/NSPR quite often ends in build override, so as requirement the version
# we're building against could bring us some broken dependencies from time to time.
#%global nspr_build_version %(pkg-config --silence-errors --modversion nspr 2>/dev/null || echo 65536)
%global nspr_build_version %{nspr_version}
-%global nss_version 3.32.1
+%global nss_version 3.33
#%global nss_build_version %(pkg-config --silence-errors --modversion nss 2>/dev/null || echo 65536)
%global nss_build_version %{nss_version}
%endif
@@ -84,9 +81,12 @@ ExcludeArch: armv7hl
%global sqlite_build_version %(pkg-config --silence-errors --modversion sqlite3 2>/dev/null || echo 65536)
%endif
+%define pre_version b9
+
%global mozappdir %{_libdir}/%{name}
%global mozappdirdev %{_libdir}/%{name}-devel-%{version}
%global langpackdir %{mozappdir}/langpacks
+%global tarballdir %{name}-%{version}%{?pre_version}
%define official_branding 1
%define build_langpacks 1
@@ -102,14 +102,14 @@ ExcludeArch: armv7hl
Summary: Mozilla Firefox Web browser
Name: firefox
-Version: 56.0
-Release: 5%{?pre_tag}%{?dist}
+Version: 57.0
+Release: 0.5%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Group: Applications/Internet
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz
%if %{build_langpacks}
-Source1: firefox-langpacks-%{version}%{?pre_version}-20170927.tar.xz
+Source1: firefox-langpacks-%{version}%{?pre_version}-20171019.tar.xz
%endif
Source10: firefox-mozconfig
Source12: firefox-redhat-default-prefs.js
@@ -126,16 +126,13 @@ Patch0: firefox-install-dir.patch
Patch3: mozilla-build-arm.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=814879#c3
Patch18: xulrunner-24.0-jemalloc-ppc.patch
-Patch20: firefox-build-prbool.patch
Patch25: rhbz-1219542-s390-build.patch
Patch26: build-icu-big-endian.patch
Patch27: mozilla-1335250.patch
# Also fixes s390x: https://bugzilla.mozilla.org/show_bug.cgi?id=1376268
Patch29: build-big-endian.patch
-Patch30: fedora-build.patch
Patch31: build-ppc64-s390x-curl.patch
Patch32: build-rust-ppc64le.patch
-Patch34: build-cubeb-pulse-arm.patch
Patch35: build-ppc-jit.patch
Patch36: build-missing-xlocale-h.patch
# Always feel lucky for unsupported platforms:
@@ -153,7 +150,6 @@ Patch225: mozilla-1005640-accept-lang.patch
#ARM run-time patch
Patch226: rhbz-1354671.patch
Patch229: firefox-nss-version.patch
-Patch230: rhbz-1497932.patch
# Upstream patches
Patch402: mozilla-1196777.patch
@@ -163,7 +159,7 @@ Patch410: mozilla-1321521.patch
Patch411: mozilla-1321521-2.patch
Patch412: mozilla-1337988.patch
Patch413: mozilla-1353817.patch
-Patch415: mozilla-1405267.patch
+Patch416: mozilla-1399611.patch
# Debian patches
Patch500: mozilla-440908.patch
@@ -195,9 +191,6 @@ BuildRequires: pkgconfig(xrender)
BuildRequires: pkgconfig(hunspell)
%endif
BuildRequires: pkgconfig(libstartup-notification-1.0)
-%if %{?alsa_backend}
-BuildRequires: pkgconfig(alsa)
-%endif
BuildRequires: pkgconfig(libnotify) >= %{libnotify_version}
BuildRequires: pkgconfig(dri)
BuildRequires: pkgconfig(libcurl)
@@ -302,7 +295,7 @@ This package contains results of tests executed during build.
#---------------------------------------------------------------------
%prep
-%setup -q
+%setup -q -n %{tarballdir}
# Build patches, can't change backup suffix from default because during build
# there is a compare of config and js/config directories and .orig suffix is
@@ -311,15 +304,12 @@ This package contains results of tests executed during build.
%patch18 -p1 -b .jemalloc-ppc
-%patch20 -p1 -b .prbool
%ifarch s390
%patch25 -p1 -b .rhbz-1219542-s390
%endif
%patch29 -p1 -b .big-endian
-%patch30 -p1 -b .fedora-build
%patch31 -p1 -b .ppc64-s390x-curl
%patch32 -p1 -b .rust-ppc64le
-# don't need that %patch34 -p1 -b .cubeb-pulse-arm
%ifarch ppc ppc64 ppc64le
%patch35 -p1 -b .ppc-jit
%endif
@@ -327,8 +317,6 @@ This package contains results of tests executed during build.
%patch3 -p1 -b .arm
-# For branding specific patches.
-
# Fedora patches
%patch215 -p1 -b .addons
%patch219 -p2 -b .rhbz-1173156
@@ -339,7 +327,6 @@ This package contains results of tests executed during build.
%ifarch aarch64
%patch226 -p1 -b .1354671
%endif
-%patch230 -p1 -b .1497932
%patch402 -p1 -b .1196777
%patch406 -p1 -b .256180
@@ -349,8 +336,9 @@ This package contains results of tests executed during build.
%patch412 -p1 -b .1337988
%endif
%endif
+
%patch413 -p1 -b .1353817
-%patch415 -p1 -b .1405267
+%patch416 -p1 -b .1399611
# Debian extension patch
%patch500 -p1 -b .440908
@@ -397,10 +385,6 @@ echo "ac_add_options --enable-system-ffi" >> .mozconfig
echo "ac_add_options --disable-elf-hack" >> .mozconfig
%endif
-%if %{?alsa_backend}
-echo "ac_add_options --enable-alsa" >> .mozconfig
-%endif
-
%if %{?system_hunspell}
echo "ac_add_options --enable-system-hunspell" >> .mozconfig
%else
@@ -471,6 +455,9 @@ echo "ac_add_options --without-system-icu" >> .mozconfig
echo "ac_add_options --disable-ion" >> .mozconfig
%endif
+%ifarch %{ix86}
+echo "ac_add_options --disable-stylo" >> .mozconfig
+%endif
#---------------------------------------------------------------------
@@ -873,8 +860,21 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
-* Fri Oct 6 2017 Martin Stransky <stransky@redhat.com> - 56.0-5
-- Enable Stylo again.
+* Thu Oct 19 2017 Martin Stransky <stransky@redhat.com> - 57.0-0.5
+- Updated to 57.0 Beta 9
+
+* Mon Oct 16 2017 Martin Stransky <stransky@redhat.com> - 57.0-0.4
+- Updated to 57.0 Beta 8
+
+* Wed Oct 11 2017 Martin Stransky <stransky@redhat.com> - 57.0-0.3
+- Updated to 57.0 Beta 7
+
+* Mon Oct 9 2017 Martin Stransky <stransky@redhat.com> - 57.0-0.2
+- Updated to 57.0 Beta 6
+
+* Thu Oct 5 2017 Martin Stransky <stransky@redhat.com> - 57.0-0.1
+- Updated to 57.0 Beta 5
+- Added patch for mozbz#1399611 - CSD emulation
* Wed Oct 4 2017 Martin Stransky <stransky@redhat.com> - 56.0-4
- Fixed rhbz#1497932 - Plug-Ins for example flash fails
diff --git a/mozilla-1399611.patch b/mozilla-1399611.patch
new file mode 100644
index 0000000..8daa2f2
--- /dev/null
+++ b/mozilla-1399611.patch
@@ -0,0 +1,1744 @@
+diff -up firefox-57.0b8/browser/app/profile/firefox.js.1399611 firefox-57.0b8/browser/app/profile/firefox.js
+--- firefox-57.0b8/browser/app/profile/firefox.js.1399611 2017-10-16 12:11:45.364240654 +0200
++++ firefox-57.0b8/browser/app/profile/firefox.js 2017-10-16 12:28:03.860720910 +0200
+@@ -457,11 +457,7 @@ pref("browser.tabs.loadBookmarksInBackgr
+ pref("browser.tabs.loadBookmarksInTabs", false);
+ pref("browser.tabs.tabClipWidth", 140);
+ pref("browser.tabs.tabMinWidth", 76);
+-#ifdef UNIX_BUT_NOT_MAC
+-pref("browser.tabs.drawInTitlebar", false);
+-#else
+ pref("browser.tabs.drawInTitlebar", true);
+-#endif
+
+ // Offer additional drag space to the user. The drag space
+ // will only be shown if browser.tabs.drawInTitlebar is true.
+diff -up firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js.1399611 firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js
+--- firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js.1399611 2017-10-09 22:17:13.000000000 +0200
++++ firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js 2017-10-16 12:11:45.364240654 +0200
+@@ -14,6 +14,11 @@ var TabsInTitlebar = {
+ this._readPref();
+ Services.prefs.addObserver(this._prefName, this);
+
++ // Always disable on unsupported GTK versions.
++ if (AppConstants.MOZ_WIDGET_TOOLKIT == "gtk3") {
++ this.allowedBy("gtk", window.matchMedia("(-moz-gtk-csd-available)"));
++ }
++
+ // We need to update the appearance of the titlebar when the menu changes
+ // from the active to the inactive state. We can't, however, rely on
+ // DOMMenuBarInactive, because the menu fires this event and then removes
+diff -up firefox-57.0b8/browser/base/moz.build.1399611 firefox-57.0b8/browser/base/moz.build
+--- firefox-57.0b8/browser/base/moz.build.1399611 2017-09-29 18:16:45.000000000 +0200
++++ firefox-57.0b8/browser/base/moz.build 2017-10-16 12:11:45.364240654 +0200
+@@ -57,7 +57,7 @@ DEFINES['APP_LICENSE_BLOCK'] = '%s/conte
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
+ DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1
+
+-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
++if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
+ DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
+diff -up firefox-57.0b8/browser/themes/linux/browser.css.1399611 firefox-57.0b8/browser/themes/linux/browser.css
+--- firefox-57.0b8/browser/themes/linux/browser.css.1399611 2017-10-05 06:17:37.000000000 +0200
++++ firefox-57.0b8/browser/themes/linux/browser.css 2017-10-16 12:11:45.365240651 +0200
+@@ -556,7 +556,9 @@ html|span.ac-emphasize-text-url {
+
+ #nav-bar,
+ #toolbar-menubar:not([autohide="true"]):not(:-moz-lwtheme):-moz-system-metric(menubar-drag),
+-#TabsToolbar:not(:-moz-lwtheme):-moz-system-metric(menubar-drag) {
++#TabsToolbar:not(:-moz-lwtheme):-moz-system-metric(menubar-drag),
++#main-window[tabsintitlebar] #toolbar-menubar:not([autohide="true"]),
++#main-window[tabsintitlebar] #TabsToolbar {
+ -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-drag");
+ }
+
+@@ -713,3 +715,85 @@ html|span.ac-emphasize-text-url {
+ .restore-tabs-button:hover:active:not([disabled="true"]) {
+ padding: 3px;
+ }
++
++@media not all and (-moz-gtk-csd-available) {
++ #main-window > #titlebar {
++ /* We need to hide the titlebar explicitly on versions of GTK without CSD. */
++ display: none;
++ }
++}
++
++/* Titlebar/CSD */
++@media (-moz-gtk-csd-available) {
++ #main-window[tabsintitlebar][sizemode="normal"] > #titlebar {
++ min-height: calc(var(--tab-min-height) + 12px);
++ }
++
++ #main-window[tabsintitlebar] #titlebar:-moz-lwtheme {
++ visibility: hidden;
++ }
++ #main-window[tabsintitlebar] #titlebar-content:-moz-lwtheme {
++ visibility: visible;
++ }
++
++ #main-window[tabsintitlebar][sizemode="normal"] > #titlebar {
++ -moz-appearance: -moz-window-titlebar;
++ }
++ #main-window[tabsintitlebar][sizemode="maximized"] > #titlebar {
++ -moz-appearance: -moz-window-titlebar-maximized;
++ }
++
++ /* The button box must appear on top of the navigator-toolbox in order for
++ * click and hover mouse events to work properly for the button in the restored
++ * window state. Otherwise, elements in the navigator-toolbox, like the menubar,
++ * can swallow those events.
++ */
++ #titlebar-buttonbox {
++ z-index: 1;
++ }
++
++ /* titlebar command buttons */
++ /* Use full scale icons here as the Gtk+ does. */
++ @media (-moz-gtk-csd-minimize-button) {
++ #titlebar-min {
++ list-style-image: url("moz-icon://stock/window-minimize-symbolic");
++ -moz-appearance: -moz-window-button-minimize;
++ }
++ }
++ @media not all and (-moz-gtk-csd-minimize-button) {
++ #titlebar-min {
++ display: none;
++ }
++ }
++
++ @media (-moz-gtk-csd-maximize-button) {
++ #titlebar-max {
++ list-style-image: url("moz-icon://stock/window-maximize-symbolic");
++ -moz-appearance: -moz-window-button-maximize;
++ }
++ #main-window[sizemode="maximized"] #titlebar-max {
++ list-style-image: url("moz-icon://stock/window-restore-symbolic");
++ -moz-appearance: -moz-window-button-restore;
++ }
++ }
++ @media not all and (-moz-gtk-csd-maximize-button) {
++ #titlebar-max {
++ display: none;
++ }
++ #main-window[sizemode="maximized"] #titlebar-max {
++ display: none;
++ }
++ }
++
++ @media (-moz-gtk-csd-close-button) {
++ #titlebar-close {
++ list-style-image: url("moz-icon://stock/window-close-symbolic");
++ -moz-appearance: -moz-window-button-close;
++ }
++ }
++ @media not all and (-moz-gtk-csd-close-button) {
++ #titlebar-close {
++ display: none;
++ }
++ }
++}
+diff -up firefox-57.0b8/dom/base/nsGkAtomList.h.1399611 firefox-57.0b8/dom/base/nsGkAtomList.h
+--- firefox-57.0b8/dom/base/nsGkAtomList.h.1399611 2017-09-15 06:15:41.000000000 +0200
++++ firefox-57.0b8/dom/base/nsGkAtomList.h 2017-10-16 12:11:45.365240651 +0200
+@@ -2270,6 +2270,10 @@ GK_ATOM(touch_enabled, "touch-enabled")
+ GK_ATOM(menubar_drag, "menubar-drag")
+ GK_ATOM(swipe_animation_enabled, "swipe-animation-enabled")
+ GK_ATOM(physical_home_button, "physical-home-button")
++GK_ATOM(gtk_csd_available, "gtk-csd-available")
++GK_ATOM(gtk_csd_minimize_button, "gtk-csd-minimize-button")
++GK_ATOM(gtk_csd_maximize_button, "gtk-csd-maximize-button")
++GK_ATOM(gtk_csd_close_button, "gtk-csd-close-button")
+
+ // windows theme selector metrics
+ GK_ATOM(windows_classic, "windows-classic")
+@@ -2306,6 +2310,10 @@ GK_ATOM(_moz_device_orientation, "-moz-d
+ GK_ATOM(_moz_is_resource_document, "-moz-is-resource-document")
+ GK_ATOM(_moz_swipe_animation_enabled, "-moz-swipe-animation-enabled")
+ GK_ATOM(_moz_physical_home_button, "-moz-physical-home-button")
++GK_ATOM(_moz_gtk_csd_available, "-moz-gtk-csd-available")
++GK_ATOM(_moz_gtk_csd_minimize_button, "-moz-gtk-csd-minimize-button")
++GK_ATOM(_moz_gtk_csd_maximize_button, "-moz-gtk-csd-maximize-button")
++GK_ATOM(_moz_gtk_csd_close_button, "-moz-gtk-csd-close-button")
+
+ // application commands
+ GK_ATOM(Back, "Back")
+diff -up firefox-57.0b8/gfx/src/nsThemeConstants.h.1399611 firefox-57.0b8/gfx/src/nsThemeConstants.h
+--- firefox-57.0b8/gfx/src/nsThemeConstants.h.1399611 2017-06-12 18:37:10.000000000 +0200
++++ firefox-57.0b8/gfx/src/nsThemeConstants.h 2017-10-16 12:11:45.365240651 +0200
+@@ -299,6 +299,7 @@ enum ThemeWidgetType : uint8_t {
+ NS_THEME_MAC_SOURCE_LIST,
+ NS_THEME_MAC_SOURCE_LIST_SELECTION,
+ NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION,
++ NS_THEME_GTK_WINDOW_DECORATION,
+
+ ThemeWidgetType_COUNT
+ };
+diff -up firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp.1399611 firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp
+--- firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp.1399611 2017-08-02 14:27:54.000000000 +0200
++++ firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp 2017-10-16 12:11:45.365240651 +0200
+@@ -1180,6 +1180,30 @@ nsCSSRuleProcessor::InitSystemMetrics()
+ sSystemMetrics->AppendElement(nsGkAtoms::physical_home_button);
+ }
+
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_available);
++ }
++
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDMinimizeButton,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_minimize_button);
++ }
++
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDMaximizeButton,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_maximize_button);
++ }
++
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDCloseButton,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_close_button);
++ }
++
+ #ifdef XP_WIN
+ if (NS_SUCCEEDED(
+ LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsThemeIdentifier,
+diff -up firefox-57.0b8/layout/style/nsMediaFeatures.cpp.1399611 firefox-57.0b8/layout/style/nsMediaFeatures.cpp
+--- firefox-57.0b8/layout/style/nsMediaFeatures.cpp.1399611 2017-09-15 06:15:42.000000000 +0200
++++ firefox-57.0b8/layout/style/nsMediaFeatures.cpp 2017-10-16 12:11:45.366240647 +0200
+@@ -788,6 +788,42 @@ nsMediaFeatures::features[] = {
+ GetSystemMetric
+ },
+
++ {
++ &nsGkAtoms::_moz_gtk_csd_available,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_available },
++ GetSystemMetric
++ },
++
++ {
++ &nsGkAtoms::_moz_gtk_csd_minimize_button,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_minimize_button },
++ GetSystemMetric
++ },
++
++ {
++ &nsGkAtoms::_moz_gtk_csd_maximize_button,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_maximize_button },
++ GetSystemMetric
++ },
++
++ {
++ &nsGkAtoms::_moz_gtk_csd_close_button,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_close_button },
++ GetSystemMetric
++ },
++
+ // Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
+ // Internal because it is really only useful in the user agent anyway
+ // and therefore not worth standardizing.
+diff -up firefox-57.0b8/modules/libpref/init/all.js.1399611 firefox-57.0b8/modules/libpref/init/all.js
+--- firefox-57.0b8/modules/libpref/init/all.js.1399611 2017-10-12 18:12:09.000000000 +0200
++++ firefox-57.0b8/modules/libpref/init/all.js 2017-10-16 12:11:45.366240647 +0200
+@@ -4911,6 +4911,7 @@ pref("gfx.apitrace.enabled",false);
+ pref("gfx.xrender.enabled",false);
+ pref("widget.chrome.allow-gtk-dark-theme", false);
+ pref("widget.content.allow-gtk-dark-theme", false);
++pref("widget.allow-client-side-decoration", false);
+ #endif
+ #endif
+
+diff -up firefox-57.0b8/toolkit/modules/moz.build.1399611 firefox-57.0b8/toolkit/modules/moz.build
+--- firefox-57.0b8/toolkit/modules/moz.build.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/toolkit/modules/moz.build 2017-10-16 12:11:45.366240647 +0200
+@@ -259,7 +259,7 @@ EXTRA_JS_MODULES.sessionstore += [
+ ]
+
+ DEFINES['INSTALL_COMPACT_THEMES'] = 1
+-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
++if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
+ DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
+diff -up firefox-57.0b8/widget/gtk/gtk3drawing.cpp.1399611 firefox-57.0b8/widget/gtk/gtk3drawing.cpp
+--- firefox-57.0b8/widget/gtk/gtk3drawing.cpp.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/widget/gtk/gtk3drawing.cpp 2017-10-16 12:11:45.367240644 +0200
+@@ -17,6 +17,7 @@
+ #include "WidgetStyleCache.h"
+
+ #include <math.h>
++#include <dlfcn.h>
+
+ static gboolean checkbox_check_state;
+ static gboolean notebook_has_tab_gap;
+@@ -39,9 +40,25 @@ static gint
+ moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
+ GtkWidgetState* state, GtkTextDirection direction);
+
++static void
++moz_gtk_add_style_margin(GtkStyleContext* style,
++ gint* left, gint* top, gint* right, gint* bottom);
++static void
++moz_gtk_add_style_border(GtkStyleContext* style,
++ gint* left, gint* top, gint* right, gint* bottom);
++static void
++moz_gtk_add_style_padding(GtkStyleContext* style,
++ gint* left, gint* top, gint* right, gint* bottom);
++static void moz_gtk_add_margin_border_padding(GtkStyleContext *style,
++ gint* left, gint* top,
++ gint* right, gint* bottom);
++static void moz_gtk_add_border_padding(GtkStyleContext *style,
++ gint* left, gint* top,
++ gint* right, gint* bottom);
+ 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
+@@ -233,6 +250,43 @@ moz_gtk_splitter_get_metrics(gint orient
+ return MOZ_GTK_SUCCESS;
+ }
+
++void
++moz_gtk_get_window_border(gint* top, gint* right, gint* bottom, gint* left)
++{
++ MOZ_ASSERT(gtk_check_version(3, 20, 0) == nullptr,
++ "Window decorations are only supported on GTK 3.20+.");
++
++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW);
++
++ *top = *right = *bottom = *left = 0;
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
++ GtkBorder windowMargin;
++ gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &windowMargin);
++
++ style = GetStyleContext(MOZ_GTK_WINDOW_DECORATION);
++
++ // Available on GTK 3.20+.
++ static auto sGtkRenderBackgroundGetClip =
++ (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*))
++ dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip");
++
++ GdkRectangle shadowClip;
++ sGtkRenderBackgroundGetClip(style, 0, 0, 0, 0, &shadowClip);
++
++ // Transfer returned inset rectangle to GtkBorder
++ GtkBorder shadowBorder = {
++ static_cast<gint16>(-shadowClip.x), // left
++ static_cast<gint16>(shadowClip.width + shadowClip.x), // right
++ static_cast<gint16>(-shadowClip.y), // top
++ static_cast<gint16>(shadowClip.height + shadowClip.y), // bottom
++ };
++
++ *left += MAX(windowMargin.left, shadowBorder.left);
++ *right += MAX(windowMargin.right, shadowBorder.right);
++ *top += MAX(windowMargin.top, shadowBorder.top);
++ *bottom += MAX(windowMargin.bottom, shadowBorder.bottom);
++}
++
+ static gint
+ moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+@@ -302,6 +356,24 @@ moz_gtk_button_paint(cairo_t *cr, GdkRec
+ }
+
+ static gint
++moz_gtk_header_bar_button_paint(cairo_t *cr, GdkRectangle* rect,
++ GtkWidgetState* state,
++ GtkReliefStyle relief, GtkWidget* widget,
++ GtkTextDirection direction)
++{
++ GtkBorder margin;
++ GtkStyleContext* style = gtk_widget_get_style_context(widget);
++ gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin);
++
++ rect->x += margin.left;
++ rect->y += margin.top;
++ rect->width -= margin.left + margin.right;
++ rect->height -= margin.top + margin.bottom;
++
++ return moz_gtk_button_paint(cr, rect, state, relief, widget, direction);
++}
++
++static gint
+ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkWidgetState* state,
+ gboolean selected, gboolean inconsistent,
+@@ -1948,6 +2020,38 @@ moz_gtk_info_bar_paint(cairo_t *cr, GdkR
+ return MOZ_GTK_SUCCESS;
+ }
+
++static gint
++moz_gtk_header_bar_paint(WidgetNodeType widgetType,
++ cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state)
++{
++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
++ GtkStyleContext *style;
++
++ style = GetStyleContext(widgetType, GTK_TEXT_DIR_LTR,
++ state_flags);
++ InsetByMargin(rect, style);
++ gtk_render_background(style, cr, rect->x, rect->y, rect->width,
++ rect->height);
++ gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
++
++ return MOZ_GTK_SUCCESS;
++}
++
++void
++moz_gtk_header_bar_paint(cairo_t *cr, GdkRectangle* rect)
++{
++ static GtkWidgetState state;
++ moz_gtk_header_bar_paint(MOZ_GTK_HEADER_BAR, cr, rect, &state);
++}
++
++void
++moz_gtk_get_header_bar_border(gint* top, gint* right, gint* bottom, gint* left)
++{
++ *left = *top = *right = *bottom = 0;
++ moz_gtk_add_border_padding(GetStyleContext(MOZ_GTK_HEADER_BAR),
++ left, top, right, bottom);
++}
++
+ static void
+ moz_gtk_add_style_margin(GtkStyleContext* style,
+ gint* left, gint* top, gint* right, gint* bottom)
+@@ -1999,6 +2103,14 @@ static void moz_gtk_add_margin_border_pa
+ moz_gtk_add_style_padding(style, left, top, right, bottom);
+ }
+
++static void moz_gtk_add_border_padding(GtkStyleContext *style,
++ gint* left, gint* top,
++ gint* right, gint* bottom)
++{
++ moz_gtk_add_style_border(style, left, top, right, bottom);
++ moz_gtk_add_style_padding(style, left, top, right, bottom);
++}
++
+ static GtkBorder
+ GetMarginBorderPadding(GtkStyleContext* aStyle)
+ {
+@@ -2054,8 +2166,7 @@ moz_gtk_get_widget_border(WidgetNodeType
+ // XXX: Subtract 1 pixel from the padding to account for the default
+ // padding in forms.css. See bug 1187385.
+ *left = *top = *right = *bottom = -1;
+- moz_gtk_add_style_padding(style, left, top, right, bottom);
+- moz_gtk_add_style_border(style, left, top, right, bottom);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
+
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -2076,10 +2187,8 @@ moz_gtk_get_widget_border(WidgetNodeType
+ *left = *top = *right = *bottom =
+ gtk_container_get_border_width(GTK_CONTAINER(
+ GetWidget(MOZ_GTK_TREE_HEADER_CELL)));
+-
+ style = GetStyleContext(MOZ_GTK_TREE_HEADER_CELL);
+- moz_gtk_add_style_border(style, left, top, right, bottom);
+- moz_gtk_add_style_padding(style, left, top, right, bottom);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_TREE_HEADER_SORTARROW:
+@@ -2105,8 +2214,7 @@ moz_gtk_get_widget_border(WidgetNodeType
+ gtk_container_get_border_width(GTK_CONTAINER(
+ GetWidget(MOZ_GTK_COMBOBOX_BUTTON)));
+ style = GetStyleContext(MOZ_GTK_COMBOBOX_BUTTON);
+- moz_gtk_add_style_padding(style, left, top, right, bottom);
+- moz_gtk_add_style_border(style, left, top, right, bottom);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
+
+ /* If there is no separator, don't try to count its width. */
+ separator_width = 0;
+@@ -2160,10 +2268,8 @@ moz_gtk_get_widget_border(WidgetNodeType
+ style = gtk_widget_get_style_context(w);
+
+ *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w));
+- moz_gtk_add_style_border(style,
+- left, top, right, bottom);
+- moz_gtk_add_style_padding(style,
+- left, top, right, bottom);
++ moz_gtk_add_border_padding(style,
++ left, top, right, bottom);
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_MENUPOPUP:
+@@ -2210,6 +2316,21 @@ moz_gtk_get_widget_border(WidgetNodeType
+
+ return MOZ_GTK_SUCCESS;
+ }
++ case MOZ_GTK_HEADER_BAR:
++ case MOZ_GTK_HEADER_BAR_MAXIMIZED:
++ {
++ style = GetStyleContext(widget);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
++ return MOZ_GTK_SUCCESS;
++ }
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ {
++ style = GetStyleContext(widget);
++ moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
++ return MOZ_GTK_SUCCESS;
++ }
+
+ /* These widgets have no borders, since they are not containers. */
+ case MOZ_GTK_CHECKBUTTON_LABEL:
+@@ -2646,6 +2767,36 @@ GetScrollbarMetrics(GtkOrientation aOrie
+ return metrics;
+ }
+
++void
++moz_gtk_window_decoration_paint(cairo_t *cr, GdkRectangle* rect)
++{
++ gint top, right, bottom, left;
++ moz_gtk_get_window_border(&top, &right, &bottom, &left);
++
++ cairo_save(cr);
++ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
++ cairo_rectangle(cr, rect->x, rect->y, left, rect->height);
++ cairo_fill(cr);
++ cairo_rectangle(cr, rect->x+rect->width-right, rect->y, right, rect->height);
++ cairo_fill(cr);
++ cairo_rectangle(cr, rect->x, rect->y, rect->width, top);
++ cairo_fill(cr);
++ cairo_rectangle(cr, rect->x, rect->height-bottom, rect->width, bottom);
++ cairo_fill(cr);
++ cairo_restore(cr);
++
++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW_DECORATION,
++ GTK_TEXT_DIR_NONE);
++ rect->x += left;
++ rect->y += top;
++ rect->width -= left + right;
++ rect->height -= top + bottom;
++
++ 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);
++}
++
++
+ /* cairo_t *cr argument has to be a system-cairo. */
+ gint
+ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr,
+@@ -2671,6 +2822,14 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ GetWidget(MOZ_GTK_BUTTON),
+ direction);
+ break;
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ return moz_gtk_header_bar_button_paint(cr, rect, state,
++ (GtkReliefStyle) flags,
++ GetWidget(widget),
++ direction);
++ break;
+ case MOZ_GTK_CHECKBUTTON:
+ case MOZ_GTK_RADIOBUTTON:
+ return moz_gtk_toggle_paint(cr, rect, state,
+@@ -2877,6 +3036,10 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ case MOZ_GTK_INFO_BAR:
+ return moz_gtk_info_bar_paint(cr, rect, state);
+ break;
++ case MOZ_GTK_HEADER_BAR:
++ case MOZ_GTK_HEADER_BAR_MAXIMIZED:
++ return moz_gtk_header_bar_paint(widget, cr, rect, state);
++ break;
+ default:
+ g_warning("Unknown widget type: %d", widget);
+ }
+diff -up firefox-57.0b8/widget/gtk/gtkdrawing.h.1399611 firefox-57.0b8/widget/gtk/gtkdrawing.h
+--- firefox-57.0b8/widget/gtk/gtkdrawing.h.1399611 2017-06-12 18:37:20.000000000 +0200
++++ firefox-57.0b8/widget/gtk/gtkdrawing.h 2017-10-16 12:11:45.367240644 +0200
+@@ -268,8 +268,14 @@ typedef enum {
+ MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL,
+ /* Paints the background of a window, dialog or page. */
+ MOZ_GTK_WINDOW,
++ /* Used only as a container for MOZ_GTK_HEADER_BAR_MAXIMIZED. */
++ MOZ_GTK_WINDOW_MAXIMIZED,
+ /* Window container for all widgets */
+ MOZ_GTK_WINDOW_CONTAINER,
++ /* Window with the 'csd' style class. */
++ MOZ_GTK_WINDOW_CSD,
++ /* Client-side window decoration node. Available on GTK 3.20+. */
++ MOZ_GTK_WINDOW_DECORATION,
+ /* Paints a GtkInfoBar, for notifications. */
+ MOZ_GTK_INFO_BAR,
+ /* Used for widget tree construction. */
+@@ -290,6 +296,14 @@ typedef enum {
+ MOZ_GTK_COMBOBOX_ENTRY_ARROW,
+ /* Used for scrolled window shell. */
+ MOZ_GTK_SCROLLED_WINDOW,
++ /* Paints a GtkHeaderBar */
++ MOZ_GTK_HEADER_BAR,
++ /* Paints a GtkHeaderBar in maximized state */
++ MOZ_GTK_HEADER_BAR_MAXIMIZED,
++ /* Paints a GtkHeaderBar title buttons */
++ MOZ_GTK_HEADER_BAR_BUTTON_CLOSE,
++ MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE,
++ MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE,
+
+ MOZ_GTK_WIDGET_NODE_COUNT
+ } WidgetNodeType;
+@@ -542,6 +556,32 @@ gint moz_gtk_get_menu_separator_height(g
+ */
+ gint moz_gtk_splitter_get_metrics(gint orientation, gint* size);
+
++#if (MOZ_WIDGET_GTK == 3)
++/**
++ * Gets the margins to be used for window decorations, typically the extra space
++ * required to draw a drop shadow (obtained from gtk_render_background_get_clip).
++ * Only available on GTK 3.20+.
++ */
++void moz_gtk_get_window_border(gint* top, gint* right, gint* bottom, gint* left);
++
++/**
++ * Draw window decorations, typically a shadow.
++ * Only available on GTK 3.20+.
++ */
++void moz_gtk_window_decoration_paint(cairo_t *cr, GdkRectangle* rect);
++
++/**
++ * Gets the border of window header bar, only available on GTK 3.20+.
++ */
++void moz_gtk_get_header_bar_border(gint* top, gint* right, gint* bottom, gint* left);
++
++/**
++ * Draw window header bar, only available on GTK 3.20+.
++ */
++void moz_gtk_header_bar_paint(cairo_t *cr, GdkRectangle* rect);
++
++#endif
++
+ /**
+ * Get the YTHICKNESS of a tab (notebook extension).
+ */
+diff -up firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c.1399611 firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c
+--- firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c.1399611 2017-10-09 22:17:13.000000000 +0200
++++ firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c 2017-10-16 12:11:45.367240644 +0200
+@@ -580,6 +580,8 @@ STUB(gtk_style_context_set_state)
+ STUB(gtk_style_properties_lookup_property)
+ STUB(gtk_tree_view_column_get_button)
+ STUB(gtk_widget_get_preferred_size)
++STUB(gtk_widget_get_preferred_width)
++STUB(gtk_widget_get_preferred_height)
+ STUB(gtk_widget_get_state_flags)
+ STUB(gtk_widget_get_style_context)
+ STUB(gtk_widget_path_append_type)
+@@ -589,6 +591,10 @@ STUB(gtk_widget_path_iter_add_class)
+ STUB(gtk_widget_path_get_object_type)
+ STUB(gtk_widget_path_new)
+ STUB(gtk_widget_path_unref)
++STUB(gtk_widget_set_margin_left)
++STUB(gtk_widget_set_margin_right)
++STUB(gtk_widget_set_margin_top)
++STUB(gtk_widget_set_margin_bottom)
+ STUB(gtk_widget_set_visual)
+ STUB(gtk_app_chooser_dialog_new_for_content_type)
+ STUB(gtk_app_chooser_get_type)
+@@ -601,6 +607,7 @@ STUB(gtk_color_chooser_get_type)
+ STUB(gtk_color_chooser_set_rgba)
+ STUB(gtk_color_chooser_get_rgba)
+ STUB(gtk_color_chooser_set_use_alpha)
++STUB(gtk_window_get_size)
+ #endif
+
+ #ifdef GTK2_SYMBOLS
+diff -up firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp.1399611 firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp
+--- firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp.1399611 2017-09-21 06:10:10.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp 2017-10-16 12:11:45.367240644 +0200
+@@ -642,6 +642,22 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
+ case eIntID_ContextMenuOffsetHorizontal:
+ aResult = 2;
+ break;
++ case eIntID_GTKCSDAvailable:
++ EnsureInit();
++ aResult = sCSDAvailable;
++ break;
++ case eIntID_GTKCSDMaximizeButton:
++ EnsureInit();
++ aResult = sCSDMaximizeButton;
++ break;
++ case eIntID_GTKCSDMinimizeButton:
++ EnsureInit();
++ aResult = sCSDMinimizeButton;
++ break;
++ case eIntID_GTKCSDCloseButton:
++ EnsureInit();
++ aResult = sCSDCloseButton;
++ break;
+ default:
+ aResult = 0;
+ res = NS_ERROR_FAILURE;
+@@ -1048,6 +1064,40 @@ nsLookAndFeel::EnsureInit()
+
+ gtk_widget_destroy(window);
+ g_object_unref(labelWidget);
++
++ // Require GTK 3.20 for client-side decoration support.
++ // 3.20 exposes gtk_render_background_get_clip, which is required for
++ // calculating shadow metrics for decorated windows.
++ sCSDAvailable = gtk_check_version(3, 20, 0) == nullptr;
++ if (sCSDAvailable) {
++ sCSDAvailable =
++ mozilla::Preferences::GetBool("widget.allow-client-side-decoration",
++ false);
++ }
++
++ const gchar* decorationLayout = nullptr;
++ if (gtk_check_version(3, 12, 0) == nullptr) {
++ static auto sGtkHeaderBarGetDecorationLayoutPtr =
++ (const gchar* (*)(GtkWidget*))
++ dlsym(RTLD_DEFAULT, "gtk_header_bar_get_decoration_layout");
++
++ GtkWidget* headerBar = GetWidget(MOZ_GTK_HEADER_BAR);
++ decorationLayout = sGtkHeaderBarGetDecorationLayoutPtr(headerBar);
++ if (!decorationLayout) {
++ g_object_get(settings, "gtk-decoration-layout", &decorationLayout,
++ nullptr);
++ }
++ }
++
++ if (decorationLayout) {
++ sCSDCloseButton = (strstr(decorationLayout, "close") != nullptr);
++ sCSDMaximizeButton = (strstr(decorationLayout, "maximize") != nullptr);
++ sCSDMinimizeButton = (strstr(decorationLayout, "minimize") != nullptr);
++ } else {
++ sCSDCloseButton = true;
++ sCSDMaximizeButton = true;
++ sCSDMinimizeButton = true;
++ }
+ }
+
+ // virtual
+diff -up firefox-57.0b8/widget/gtk/nsLookAndFeel.h.1399611 firefox-57.0b8/widget/gtk/nsLookAndFeel.h
+--- firefox-57.0b8/widget/gtk/nsLookAndFeel.h.1399611 2017-09-21 06:10:10.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsLookAndFeel.h 2017-10-16 12:11:45.367240644 +0200
+@@ -32,6 +32,8 @@ public:
+ virtual char16_t GetPasswordCharacterImpl();
+ virtual bool GetEchoPasswordImpl();
+
++ bool IsCSDAvailable() const { return sCSDAvailable; }
++
+ protected:
+
+ // Cached fonts
+@@ -82,6 +84,10 @@ protected:
+ char16_t sInvisibleCharacter;
+ float sCaretRatio;
+ bool sMenuSupportsDrag;
++ bool sCSDAvailable;
++ bool sCSDMaximizeButton;
++ bool sCSDMinimizeButton;
++ bool sCSDCloseButton;
+ bool mInitialized;
+
+ void EnsureInit();
+diff -up firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp.1399611 firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp
+--- firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp.1399611 2017-09-19 06:18:28.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp 2017-10-16 12:11:45.368240640 +0200
+@@ -23,6 +23,7 @@
+ #include "nsIDOMHTMLInputElement.h"
+ #include "nsGkAtoms.h"
+ #include "nsAttrValueInlines.h"
++#include "nsWindow.h"
+
+ #include "mozilla/EventStates.h"
+ #include "mozilla/Services.h"
+@@ -703,6 +704,24 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
+ case NS_THEME_GTK_INFO_BAR:
+ aGtkWidgetType = MOZ_GTK_INFO_BAR;
+ break;
++ case NS_THEME_WINDOW_TITLEBAR:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR;
++ break;
++ case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_MAXIMIZED;
++ break;
++ case NS_THEME_WINDOW_BUTTON_CLOSE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE;
++ break;
++ case NS_THEME_WINDOW_BUTTON_MINIMIZE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE;
++ break;
++ case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
++ break;
++ case NS_THEME_WINDOW_BUTTON_RESTORE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
++ break;
+ default:
+ return false;
+ }
+@@ -1627,6 +1646,10 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
+ case NS_THEME_MENULIST:
+ case NS_THEME_TOOLBARBUTTON:
+ case NS_THEME_TREEHEADERCELL:
++ case NS_THEME_WINDOW_BUTTON_CLOSE:
++ case NS_THEME_WINDOW_BUTTON_MINIMIZE:
++ case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
++ case NS_THEME_WINDOW_BUTTON_RESTORE:
+ {
+ if (aWidgetType == NS_THEME_MENULIST) {
+ // Include the arrow size.
+@@ -1892,9 +1915,21 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns
+ case NS_THEME_DIALOG:
+ #if (MOZ_WIDGET_GTK == 3)
+ case NS_THEME_GTK_INFO_BAR:
++ case NS_THEME_GTK_WINDOW_DECORATION:
+ #endif
+ return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
+
++ case NS_THEME_WINDOW_BUTTON_CLOSE:
++ case NS_THEME_WINDOW_BUTTON_MINIMIZE:
++ case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
++ case NS_THEME_WINDOW_BUTTON_RESTORE:
++ case NS_THEME_WINDOW_TITLEBAR:
++ case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
++ // GtkHeaderBar is available on GTK 3.10+, which is used for styling
++ // title bars and title buttons.
++ return gtk_check_version(3, 10, 0) == nullptr &&
++ !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
++
+ case NS_THEME_MENULIST_BUTTON:
+ if (aFrame && aFrame->GetWritingMode().IsVertical()) {
+ return false;
+@@ -1978,6 +2013,13 @@ nsNativeThemeGTK::GetWidgetTransparency(
+ #else
+ return eTransparent;
+ #endif
++ case NS_THEME_GTK_WINDOW_DECORATION:
++ {
++ nsWindow* window = static_cast<nsWindow*>(aFrame->GetNearestWidget());
++ if (window)
++ return window->IsComposited() ? eTransparent : eOpaque;
++ return eOpaque;
++ }
+ }
+
+ return eUnknownTransparency;
+diff -up firefox-57.0b8/widget/gtk/nsWindow.cpp.1399611 firefox-57.0b8/widget/gtk/nsWindow.cpp
+--- firefox-57.0b8/widget/gtk/nsWindow.cpp.1399611 2017-10-16 12:11:45.361240666 +0200
++++ firefox-57.0b8/widget/gtk/nsWindow.cpp 2017-10-16 12:11:45.369240636 +0200
+@@ -85,6 +85,7 @@
+ #include "nsIPropertyBag2.h"
+ #include "GLContext.h"
+ #include "gfx2DGlue.h"
++#include "nsLookAndFeel.h"
+
+ #ifdef ACCESSIBILITY
+ #include "mozilla/a11y/Accessible.h"
+@@ -139,6 +140,8 @@ using namespace mozilla::widget;
+
+ #include "mozilla/layers/APZCTreeManager.h"
+
++#include "gtkdrawing.h"
++
+ using namespace mozilla;
+ using namespace mozilla::gfx;
+ using namespace mozilla::widget;
+@@ -186,6 +189,8 @@ static gboolean expose_event_cb
+ #else
+ static gboolean expose_event_cb (GtkWidget *widget,
+ cairo_t *rect);
++static gboolean expose_event_decoration_draw_cb (GtkWidget *widget,
++ cairo_t *cr);
+ #endif
+ static gboolean configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event);
+@@ -231,7 +236,6 @@ static void screen_composited_change
+ gpointer user_data);
+ static void widget_composited_changed_cb (GtkWidget* widget,
+ gpointer user_data);
+-
+ #if (MOZ_WIDGET_GTK == 3)
+ static void scale_changed_cb (GtkWidget* widget,
+ GParamSpec* aPSpec,
+@@ -440,6 +444,7 @@ nsWindow::nsWindow()
+
+ mContainer = nullptr;
+ mGdkWindow = nullptr;
++ mIsCSDEnabled = false;
+ mShell = nullptr;
+ mCompositorWidgetDelegate = nullptr;
+ mHasMappedToplevel = false;
+@@ -481,6 +486,9 @@ nsWindow::nsWindow()
+ mLastScrollEventTime = GDK_CURRENT_TIME;
+ #endif
+ mPendingConfigures = 0;
++ mDrawWindowDecoration = false;
++ mDecorationSize = {0,0,0,0};
++ mCSDSupportLevel = CSD_SUPPORT_UNKNOWN;
+ }
+
+ nsWindow::~nsWindow()
+@@ -1479,8 +1487,8 @@ LayoutDeviceIntRect
+ nsWindow::GetScreenBounds()
+ {
+ LayoutDeviceIntRect rect;
+- if (mIsTopLevel && mContainer) {
+- // use the point including window decorations
++ if (mIsTopLevel && mContainer && !IsClientDecorated()) {
++ // use the point including default Gtk+ window decorations
+ gint x, y;
+ gdk_window_get_root_origin(gtk_widget_get_window(GTK_WIDGET(mContainer)), &x, &y);
+ rect.MoveTo(GdkPointToDevicePixels({ x, y }));
+@@ -1606,6 +1614,10 @@ nsWindow::SetCursor(nsCursor aCursor)
+ return;
+
+ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), newCursor);
++ if (IsClientDecorated()) {
++ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mShell)),
++ newCursor);
++ }
+ }
+ }
+ }
+@@ -1662,6 +1674,10 @@ nsWindow::SetCursor(imgIContainer* aCurs
+ if (cursor) {
+ if (mContainer) {
+ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), cursor);
++ if (IsClientDecorated()) {
++ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mShell)),
++ cursor);
++ }
+ rv = NS_OK;
+ }
+ #if (MOZ_WIDGET_GTK == 3)
+@@ -2176,6 +2192,12 @@ nsWindow::OnExposeEvent(cairo_t *cr)
+ return TRUE;
+ }
+
++ // Clip upper part of the mContainer to get visible rounded corners
++ // of GtkHeaderBar which is renderd to mShell.
++ if (mIsCSDEnabled) {
++ ApplyCSDClipping();
++ }
++
+ // If this widget uses OMTC...
+ if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT ||
+ GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR) {
+@@ -2586,6 +2608,53 @@ nsWindow::OnMotionNotifyEvent(GdkEventMo
+ }
+ }
+ #endif /* MOZ_X11 */
++ // Client is decorated and we're getting the motion event for mShell
++ // window which draws the CSD decorations around mContainer.
++ if (IsClientDecorated()) {
++ if (aEvent->window == gtk_widget_get_window(mShell)) {
++ GdkWindowEdge edge;
++ LayoutDeviceIntPoint refPoint =
++ GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
++ if (CheckResizerEdge(refPoint, edge)) {
++ nsCursor cursor = eCursor_none;
++ switch (edge) {
++ case GDK_WINDOW_EDGE_NORTH:
++ cursor = eCursor_n_resize;
++ break;
++ case GDK_WINDOW_EDGE_NORTH_WEST:
++ cursor = eCursor_nw_resize;
++ break;
++ case GDK_WINDOW_EDGE_NORTH_EAST:
++ cursor = eCursor_ne_resize;
++ break;
++ case GDK_WINDOW_EDGE_WEST:
++ cursor = eCursor_w_resize;
++ break;
++ case GDK_WINDOW_EDGE_EAST:
++ cursor = eCursor_e_resize;
++ break;
++ case GDK_WINDOW_EDGE_SOUTH:
++ cursor = eCursor_s_resize;
++ break;
++ case GDK_WINDOW_EDGE_SOUTH_WEST:
++ cursor = eCursor_sw_resize;
++ break;
++ case GDK_WINDOW_EDGE_SOUTH_EAST:
++ cursor = eCursor_se_resize;
++ break;
++ }
++ SetCursor(cursor);
++ return;
++ }
++ }
++ // We're not on resize handle - check if we need to reset cursor back.
++ if (mCursor == eCursor_n_resize || mCursor == eCursor_nw_resize ||
++ mCursor == eCursor_ne_resize || mCursor == eCursor_w_resize ||
++ mCursor == eCursor_e_resize || mCursor == eCursor_s_resize ||
++ mCursor == eCursor_sw_resize || mCursor == eCursor_se_resize) {
++ SetCursor(eCursor_standard);
++ }
++ }
+
+ WidgetMouseEvent event(true, eMouseMove, this, WidgetMouseEvent::eReal);
+
+@@ -2756,6 +2825,20 @@ nsWindow::OnButtonPressEvent(GdkEventBut
+ if (CheckForRollup(aEvent->x_root, aEvent->y_root, false, false))
+ return;
+
++ if (IsClientDecorated() && aEvent->window == gtk_widget_get_window(mShell)) {
++ // Check to see if the event is within our window's resize region
++ GdkWindowEdge edge;
++ LayoutDeviceIntPoint refPoint =
++ GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
++ if (CheckResizerEdge(refPoint, edge)) {
++ gdk_window_begin_resize_drag(gtk_widget_get_window(mShell),
++ edge, aEvent->button,
++ aEvent->x_root, aEvent->y_root,
++ aEvent->time);
++ return;
++ }
++ }
++
+ gdouble pressure = 0;
+ gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
+ mLastMotionPressure = pressure;
+@@ -3341,6 +3424,8 @@ nsWindow::OnWindowStateEvent(GtkWidget *
+ #endif //ACCESSIBILITY
+ }
+
++ UpdateClientDecorations();
++
+ if (mWidgetListener) {
+ mWidgetListener->SizeModeChanged(mSizeState);
+ if (aEvent->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+@@ -3405,6 +3490,7 @@ nsWindow::OnCompositedChanged()
+ presShell->ThemeChanged();
+ }
+ }
++ UpdateClientDecorations();
+ }
+
+ void
+@@ -3593,7 +3679,8 @@ nsWindow::Create(nsIWidget* aParent,
+ GtkWindow *topLevelParent = nullptr;
+ nsWindow *parentnsWindow = nullptr;
+ GtkWidget *eventWidget = nullptr;
+- bool shellHasCSD = false;
++ GtkWidget *drawWidget = nullptr;
++ bool drawToContainer = false;
+
+ if (aParent) {
+ parentnsWindow = static_cast<nsWindow*>(aParent);
+@@ -3640,29 +3727,47 @@ nsWindow::Create(nsIWidget* aParent,
+ GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
+ mShell = gtk_window_new(type);
+
+- bool useAlphaVisual = (mWindowType == eWindowType_popup &&
+- aInitData->mSupportTranslucency);
++ bool useAlphaVisual = false;
++#if (MOZ_WIDGET_GTK == 3)
++ // When CSD is available we can emulate it for toplevel windows.
++ // Content is rendered to mContainer and transparent decorations to mShell.
++ if (GetCSDSupportLevel() != CSD_SUPPORT_NONE &&
++ mWindowType == eWindowType_toplevel) {
++ int32_t isCSDAvailable = false;
++ nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
++ &isCSDAvailable);
++ if (NS_SUCCEEDED(rv)) {
++ mIsCSDEnabled = useAlphaVisual = isCSDAvailable;
++ }
++ } else
++#endif
++ if (mWindowType == eWindowType_popup) {
++ useAlphaVisual = aInitData->mSupportTranslucency;
++ }
+
+ // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false
+ // to allow experimentation
+ if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false))
+ useAlphaVisual = true;
+
++ // An ARGB visual is only useful if we are on a compositing
++ // window manager.
++ GdkScreen *screen = gtk_widget_get_screen(mShell);
++ if (useAlphaVisual && !gdk_screen_is_composited(screen)) {
++ useAlphaVisual = false;
++ }
++
+ // We need to select an ARGB visual here instead of in
+ // SetTransparencyMode() because it has to be done before the
+- // widget is realized. An ARGB visual is only useful if we
+- // are on a compositing window manager.
++ // widget is realized.
+ if (useAlphaVisual) {
+- GdkScreen *screen = gtk_widget_get_screen(mShell);
+- if (gdk_screen_is_composited(screen)) {
+ #if (MOZ_WIDGET_GTK == 2)
+- GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
+- gtk_widget_set_colormap(mShell, colormap);
++ GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
++ gtk_widget_set_colormap(mShell, colormap);
+ #else
+- GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
+- gtk_widget_set_visual(mShell, visual);
++ GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
++ gtk_widget_set_visual(mShell, visual);
+ #endif
+- }
+ }
+
+ // We only move a general managed toplevel window if someone has
+@@ -3756,24 +3861,56 @@ nsWindow::Create(nsIWidget* aParent,
+ mContainer = MOZ_CONTAINER(container);
+
+ #if (MOZ_WIDGET_GTK == 3)
+- // "csd" style is set when widget is realized so we need to call
+- // it explicitly now.
+- gtk_widget_realize(mShell);
+-
+- // We can't draw directly to top-level window when client side
+- // decorations are enabled. We use container with GdkWindow instead.
+- GtkStyleContext* style = gtk_widget_get_style_context(mShell);
+- shellHasCSD = gtk_style_context_has_class(style, "csd");
+-#endif
+- if (!shellHasCSD) {
+- // Use mShell's window for drawing and events.
+- gtk_widget_set_has_window(container, FALSE);
+- // Prevent GtkWindow from painting a background to flicker.
+- gtk_widget_set_app_paintable(mShell, TRUE);
+- }
+- // Set up event widget
+- eventWidget = shellHasCSD ? container : mShell;
++ /* There are tree possible situations here:
++ *
++ * 1) We're running on Gtk+ < 3.20 without any decorations. Content
++ * is rendered to mShell window and we listen Gtk+ events on mShell.
++ * 2) We're running on Gtk+ > 3.20 and window decorations are drawn
++ * by default by Gtk+. Content is rendered to mContainer,
++ * we listen events on mContainer. mShell contains default Gtk+
++ * window decorations rendered by Gtk+.
++ * 3) We're running on Gtk+ > 3.20 and both window decorations and
++ * content is rendered by gecko. We emulate Gtk+ decoration rendering
++ * to mShell and we need to listen Gtk events on both mShell
++ * and mContainer.
++ */
++
++ // When client side decorations are enabled (rendered by us or by Gtk+)
++ // the decoration is rendered to mShell (toplevel) window and
++ // we draw our content to mContainer.
++ if (mIsCSDEnabled) {
++ drawToContainer = true;
++ } else {
++ // mIsCSDEnabled can be disabled by preference so look at actual
++ // toplevel window style to to detect active "csd" style.
++ // The "csd" style is set when widget is realized so we need to call
++ // it explicitly now.
++ gtk_widget_realize(mShell);
++
++ GtkStyleContext* style = gtk_widget_get_style_context(mShell);
++ drawToContainer = gtk_style_context_has_class(style, "csd");
++ }
++#endif
++ drawWidget = (drawToContainer) ? container : mShell;
++ // When we draw decorations on our own we need to handle resize events
++ // because Gtk+ does not provide resizers for undecorated windows.
++ // The CSD on mShell borders act as resize handlers
++ // so we need to listen there.
++ eventWidget = (drawToContainer && !mIsCSDEnabled) ? container : mShell;
++
+ gtk_widget_add_events(eventWidget, kEvents);
++ if (eventWidget != drawWidget) {
++ // CSD is rendered by us (not by Gtk+) so we also need to listen
++ // at mShell window for events.
++ gtk_widget_add_events(drawWidget, kEvents);
++ }
++
++ // Prevent GtkWindow from painting a background to flicker.
++ gtk_widget_set_app_paintable(drawWidget, TRUE);
++
++ // gtk_container_add() realizes the child widget so we need to
++ // set it now.
++ gtk_widget_set_has_window(container, drawToContainer);
+
+ gtk_container_add(GTK_CONTAINER(mShell), container);
+ gtk_widget_realize(container);
+@@ -3783,7 +3920,7 @@ nsWindow::Create(nsIWidget* aParent,
+ gtk_widget_grab_focus(container);
+
+ // the drawing window
+- mGdkWindow = gtk_widget_get_window(eventWidget);
++ mGdkWindow = gtk_widget_get_window(drawWidget);
+
+ if (mWindowType == eWindowType_popup) {
+ // gdk does not automatically set the cursor for "temporary"
+@@ -3856,6 +3993,11 @@ nsWindow::Create(nsIWidget* aParent,
+
+ // label the drawing window with this object so we can find our way home
+ g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
++ if (mIsCSDEnabled) {
++ // label the CSD window with this object so we can find our way home
++ g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)),
++ "nsWindow", this);
++ }
+
+ if (mContainer)
+ g_object_set_data(G_OBJECT(mContainer), "nsWindow", this);
+@@ -3893,6 +4035,10 @@ nsWindow::Create(nsIWidget* aParent,
+ g_signal_connect_after(default_settings,
+ "notify::gtk-font-name",
+ G_CALLBACK(theme_changed_cb), this);
++ if (mIsCSDEnabled) {
++ g_signal_connect(G_OBJECT(mShell), "draw",
++ G_CALLBACK(expose_event_decoration_draw_cb), nullptr);
++ }
+ }
+
+ if (mContainer) {
+@@ -3943,7 +4089,7 @@ nsWindow::Create(nsIWidget* aParent,
+ G_CALLBACK(drag_data_received_event_cb), nullptr);
+
+ GtkWidget *widgets[] = { GTK_WIDGET(mContainer),
+- !shellHasCSD ? mShell : nullptr };
++ !drawToContainer ? mShell : nullptr };
+ for (size_t i = 0; i < ArrayLength(widgets) && widgets[i]; ++i) {
+ // Visibility events are sent to the owning widget of the relevant
+ // window but do not propagate to parent widgets so connect on
+@@ -3973,7 +4119,6 @@ nsWindow::Create(nsIWidget* aParent,
+ // Don't let GTK mess with the shapes of our GdkWindows
+ GTK_PRIVATE_SET_FLAG(eventWidget, GTK_HAS_SHAPE_MASK);
+ #endif
+-
+ // These events are sent to the owning widget of the relevant window
+ // and propagate up to the first widget that handles the events, so we
+ // need only connect on mShell, if it exists, to catch events on its
+@@ -4110,6 +4255,12 @@ nsWindow::NativeResize()
+ size.width, size.height));
+
+ if (mIsTopLevel) {
++ // When we draw decorations add extra space to draw shadows
++ // around the main window.
++ if (mDrawWindowDecoration) {
++ size.width += mDecorationSize.left + mDecorationSize.right;
++ size.height += mDecorationSize.top + mDecorationSize.bottom;
++ }
+ gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
+ }
+ else if (mContainer) {
+@@ -4166,6 +4317,11 @@ nsWindow::NativeMoveResize()
+ if (mIsTopLevel) {
+ // x and y give the position of the window manager frame top-left.
+ gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y);
++
++ if (mDrawWindowDecoration) {
++ size.width += mDecorationSize.left + mDecorationSize.right;
++ size.height += mDecorationSize.top + mDecorationSize.bottom;
++ }
+ // This sets the client window size.
+ gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
+ }
+@@ -5524,6 +5680,33 @@ expose_event_cb(GtkWidget *widget, cairo
+
+ return FALSE;
+ }
++
++/* static */
++gboolean
++expose_event_decoration_draw_cb(GtkWidget *widget, cairo_t *cr)
++{
++ GdkWindow* gdkWindow = gtk_widget_get_window(widget);
++ if (gtk_cairo_should_draw_window(cr, gdkWindow)) {
++ RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
++ if (!window) {
++ NS_WARNING("Cannot get nsWindow from GtkWidget");
++ }
++ else if (window->IsClientDecorated()) {
++ cairo_save(cr);
++ gtk_cairo_transform_to_window(cr, widget, gdkWindow);
++
++ GdkRectangle rect = {0,0,0,0};
++ gtk_window_get_size(GTK_WINDOW(widget), &rect.width, &rect.height);
++ moz_gtk_window_decoration_paint(cr, &rect);
++
++ rect.height = 40;
++ moz_gtk_header_bar_paint(cr, &rect);
++ cairo_restore(cr);
++ }
++ }
++ return TRUE;
++}
++
+ #endif //MOZ_WIDGET_GTK == 2
+
+ static gboolean
+@@ -6576,6 +6759,28 @@ nsWindow::ClearCachedResources()
+ }
+ }
+
++NS_IMETHODIMP
++nsWindow::SetNonClientMargins(LayoutDeviceIntMargin &aMargins)
++{
++ SetDrawsInTitlebar(aMargins.top == 0);
++ return NS_OK;
++}
++
++void
++nsWindow::SetDrawsInTitlebar(bool aState)
++{
++ if (!mIsCSDEnabled || aState == mDrawWindowDecoration)
++ return;
++
++ if (mShell) {
++ gtk_window_set_decorated(GTK_WINDOW(mShell), !aState);
++ gtk_widget_set_app_paintable(mShell, aState);
++ }
++
++ mDrawWindowDecoration = aState;
++ UpdateClientDecorations();
++}
++
+ gint
+ nsWindow::GdkScaleFactor()
+ {
+@@ -6846,6 +7051,157 @@ nsWindow::SynthesizeNativeTouchPoint(uin
+ }
+ #endif
+
++bool
++nsWindow::IsClientDecorated() const
++{
++ return mDrawWindowDecoration && mSizeState == nsSizeMode_Normal;
++}
++
++int
++nsWindow::GetClientResizerSize()
++{
++ if (!mShell)
++ return 0;
++
++ // GTK uses a default size of 20px as of 3.20.
++ gint size = 20;
++ gtk_widget_style_get(mShell, "decoration-resize-handle", &size, nullptr);
++
++ return GdkCoordToDevicePixels(size);
++}
++
++nsWindow::CSDSupportLevel
++nsWindow::GetCSDSupportLevel() {
++ if (mCSDSupportLevel != CSD_SUPPORT_UNKNOWN) {
++ return mCSDSupportLevel;
++ }
++ // TODO: MATE
++ const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
++ if (currentDesktop) {
++ if (strcmp(currentDesktop, "GNOME") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FULL;
++ } else if (strcmp(currentDesktop, "XFCE") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FULL;
++ } else if (strcmp(currentDesktop, "X-Cinnamon") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FULL;
++ } else if (strcmp(currentDesktop, "KDE") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FLAT;
++ } else if (strcmp(currentDesktop, "LXDE") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FLAT;
++ } else if (strcmp(currentDesktop, "openbox") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FLAT;
++ } else if (strcmp(currentDesktop, "i3") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_NONE;
++ } else {
++ mCSDSupportLevel = CSD_SUPPORT_NONE;
++ }
++ }
++ return mCSDSupportLevel;
++}
++
++void
++nsWindow::UpdateClientDecorations()
++{
++ // When the CSD is not fully supported by window manager (ie. WM is not
++ // expecting that application is going to draw window shadows) we can't
++ // add shadows widths to the window margin. That would lead to completely
++ // opaque black border of the window.
++ if (!mDrawWindowDecoration || GetCSDSupportLevel() != CSD_SUPPORT_FULL)
++ return;
++
++ gint top = 0, right = 0, bottom = 0, left = 0;
++ if (mSizeState == nsSizeMode_Normal) {
++ moz_gtk_get_window_border(&top, &right, &bottom, &left);
++ }
++
++ static auto sGdkWindowSetShadowWidth =
++ (void (*)(GdkWindow*, gint, gint, gint, gint))
++ dlsym(RTLD_DEFAULT, "gdk_window_set_shadow_width");
++ sGdkWindowSetShadowWidth(gtk_widget_get_window(mShell),
++ left, right, top, bottom);
++
++ mDecorationSize.left = left;
++ mDecorationSize.right = right;
++ mDecorationSize.top = top;
++ mDecorationSize.bottom = bottom;
++
++ // Gtk+ doesn't like when we set mContainer margin bigger than actual
++ // mContainer window size. That happens when we're called early and the
++ // mShell/mContainer is not allocated/resized yet and has default 1x1 size.
++ // Just resize to some minimal value which will be changed
++ // by Gecko soon.
++ GtkAllocation allocation;
++ gtk_widget_get_allocation(GTK_WIDGET(mContainer), &allocation);
++ if (allocation.width < left + right || allocation.height < top + bottom) {
++ gtk_widget_get_preferred_width(GTK_WIDGET(mContainer), nullptr,
++ &allocation.width);
++ gtk_widget_get_preferred_height(GTK_WIDGET(mContainer), nullptr,
++ &allocation.height);
++ allocation.width += left + right + 1;
++ allocation.height += top + bottom + 1;
++ gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
++ }
++
++ gtk_widget_set_margin_left(GTK_WIDGET(mContainer), mDecorationSize.left);
++ gtk_widget_set_margin_right(GTK_WIDGET(mContainer), mDecorationSize.right);
++ gtk_widget_set_margin_top(GTK_WIDGET(mContainer), mDecorationSize.top);
++ gtk_widget_set_margin_bottom(GTK_WIDGET(mContainer), mDecorationSize.bottom);
++}
++
++void
++nsWindow::ApplyCSDClipping()
++{
++ if (IsClientDecorated()) {
++ gint top, right, bottom, left;
++ moz_gtk_get_header_bar_border(&top, &right, &bottom, &left);
++ cairo_rectangle_int_t rect = { 0, top, mBounds.width, mBounds.height};
++ cairo_region_t *region = cairo_region_create_rectangle(&rect);
++ gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
++ cairo_region_destroy(region);
++ } else {
++ gdk_window_shape_combine_region(mGdkWindow, nullptr, 0, 0);
++ }
++}
++
++bool
++nsWindow::CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge)
++{
++ gint scale = GdkScaleFactor();
++ gint left = scale * mDecorationSize.left;
++ gint top = scale * mDecorationSize.top;
++ gint right = scale * mDecorationSize.right;
++ gint bottom = scale * mDecorationSize.bottom;
++
++ int resizerSize = GetClientResizerSize();
++ int topDist = aPoint.y;
++ int leftDist = aPoint.x;
++ int rightDist = mBounds.width - aPoint.x;
++ int bottomDist = mBounds.height - aPoint.y;
++
++ //TODO -> wrong sizes
++
++ if (leftDist <= resizerSize && topDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_NORTH_WEST;
++ } else if (rightDist <= resizerSize && topDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_NORTH_EAST;
++ } else if (leftDist <= resizerSize && bottomDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_SOUTH_WEST;
++ } else if (rightDist <= resizerSize && bottomDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_SOUTH_EAST;
++ } else if (topDist <= top) {
++ aOutEdge = GDK_WINDOW_EDGE_NORTH;
++ } else if (leftDist <= left) {
++ aOutEdge = GDK_WINDOW_EDGE_WEST;
++ } else if (rightDist <= right) {
++ aOutEdge = GDK_WINDOW_EDGE_EAST;
++ } else if (bottomDist <= bottom) {
++ aOutEdge = GDK_WINDOW_EDGE_SOUTH;
++ } else {
++ return false;
++ }
++ return true;
++}
++
+ int32_t
+ nsWindow::RoundsWidgetCoordinatesTo()
+ {
+diff -up firefox-57.0b8/widget/gtk/nsWindow.h.1399611 firefox-57.0b8/widget/gtk/nsWindow.h
+--- firefox-57.0b8/widget/gtk/nsWindow.h.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsWindow.h 2017-10-16 12:11:45.369240636 +0200
+@@ -123,6 +123,7 @@ public:
+ double aHeight,
+ bool aRepaint) override;
+ virtual bool IsEnabled() const override;
++ bool IsComposited() const;
+
+ void SetZIndex(int32_t aZIndex) override;
+ virtual void SetSizeMode(nsSizeMode aMode) override;
+@@ -351,6 +352,9 @@ public:
+ #endif
+ virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
+
++ NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
++ void SetDrawsInTitlebar(bool aState) override;
++
+ // HiDPI scale conversion
+ gint GdkScaleFactor();
+
+@@ -367,6 +371,9 @@ public:
+ LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect);
+
+ virtual bool WidgetTypeSupportsAcceleration() override;
++
++ // Decorations
++ bool IsClientDecorated() const;
+ protected:
+ virtual ~nsWindow();
+
+@@ -384,6 +391,16 @@ protected:
+
+ virtual void RegisterTouchWindow() override;
+
++ int GetClientResizerSize();
++
++ // Informs the window manager about the size of the shadows surrounding
++ // a client-side decorated window.
++ void UpdateClientDecorations();
++
++ // Returns true if the given point (in device pixels) is within a resizer
++ // region of the window. Only used when drawing decorations client side.
++ bool CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge);
++
+ nsCOMPtr<nsIWidget> mParent;
+ // Is this a toplevel window?
+ bool mIsTopLevel;
+@@ -432,12 +449,12 @@ private:
+ gint* aRootX, gint* aRootY);
+ void ClearCachedResources();
+ nsIWidgetListener* GetListener();
+- bool IsComposited() const;
+-
++ void ApplyCSDClipping();
+
+ GtkWidget *mShell;
+ MozContainer *mContainer;
+ GdkWindow *mGdkWindow;
++ bool mIsCSDEnabled;
+ PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
+
+
+@@ -536,6 +553,10 @@ private:
+ // leaving fullscreen
+ nsSizeMode mLastSizeMode;
+
++ // If true, draw our own window decorations (where supported).
++ bool mDrawWindowDecoration;
++ GtkBorder mDecorationSize;
++
+ static bool DragInProgress(void);
+
+ void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent);
+@@ -567,6 +588,17 @@ private:
+ RefPtr<mozilla::widget::IMContextWrapper> mIMContext;
+
+ mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter;
++ typedef enum { CSD_SUPPORT_FULL, // CSD including shadows
++ CSD_SUPPORT_FLAT, // CSD without shadows
++ CSD_SUPPORT_NONE, // WM does not support CSD at all
++ CSD_SUPPORT_UNKNOWN
++ } CSDSupportLevel;
++ /**
++ * Get the support of Client Side Decoration by checking
++ * the XDG_CURRENT_DESKTOP environment variable.
++ */
++ CSDSupportLevel GetCSDSupportLevel();
++ CSDSupportLevel mCSDSupportLevel;
+ };
+
+ #endif /* __nsWindow_h__ */
+diff -up firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp.1399611 firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp
+--- firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp 2017-10-16 12:11:45.369240636 +0200
+@@ -26,10 +26,14 @@ static GtkStyleContext*
+ GetCssNodeStyleInternal(WidgetNodeType aNodeType);
+
+ static GtkWidget*
+-CreateWindowWidget()
++CreateWindowWidget(WidgetNodeType type)
+ {
+ GtkWidget *widget = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_set_name(widget, "MozillaGtkWidget");
++ if (type == MOZ_GTK_WINDOW_CSD) {
++ GtkStyleContext* style = gtk_widget_get_style_context(widget);
++ gtk_style_context_add_class(style, "csd");
++ }
+ return widget;
+ }
+
+@@ -101,7 +105,7 @@ CreateTooltipWidget()
+ {
+ MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr,
+ "CreateTooltipWidget should be used for Gtk < 3.20 only.");
+- GtkWidget* widget = CreateWindowWidget();
++ GtkWidget* widget = CreateWindowWidget(MOZ_GTK_WINDOW);
+ GtkStyleContext* style = gtk_widget_get_style_context(widget);
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
+ return widget;
+@@ -529,11 +533,82 @@ CreateNotebookWidget()
+ }
+
+ static GtkWidget*
++CreateHeaderBar(bool aMaximized)
++{
++ MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
++ "GtkHeaderBar is only available on GTK 3.10+.");
++ if (gtk_check_version(3, 10, 0) != nullptr)
++ return nullptr;
++
++ static auto sGtkHeaderBarNewPtr = (GtkWidget* (*)())
++ dlsym(RTLD_DEFAULT, "gtk_header_bar_new");
++ static const char* MOZ_GTK_STYLE_CLASS_TITLEBAR = "titlebar";
++
++ GtkWidget* headerbar = sGtkHeaderBarNewPtr();
++ if (aMaximized) {
++ GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
++ gtk_widget_set_name(window, "MozillaMaximizedGtkWidget");
++ GtkStyleContext* style = gtk_widget_get_style_context(window);
++ gtk_style_context_add_class(style, "maximized");
++ GtkWidget *fixed = gtk_fixed_new();
++ gtk_container_add(GTK_CONTAINER(window), fixed);
++ gtk_container_add(GTK_CONTAINER(fixed), headerbar);
++ // Save the window container so we don't leak it.
++ sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED] = window;
++ } else {
++ AddToWindowContainer(headerbar);
++ }
++
++ // Emulate what create_titlebar() at gtkwindow.c does.
++ GtkStyleContext* style = gtk_widget_get_style_context(headerbar);
++ gtk_style_context_add_class(style, MOZ_GTK_STYLE_CLASS_TITLEBAR);
++ gtk_style_context_add_class(style, "default-decoration");
++
++ return headerbar;
++}
++
++// TODO - Also return style for buttons located at Maximized toolbar.
++static GtkWidget*
++CreateHeaderBarButton(WidgetNodeType aWidgetType)
++{
++ MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
++ "GtkHeaderBar is only available on GTK 3.10+.");
++
++ if (gtk_check_version(3, 10, 0) != nullptr)
++ return nullptr;
++
++ static const char* MOZ_GTK_STYLE_CLASS_TITLEBUTTON = "titlebutton";
++
++ GtkWidget* widget = gtk_button_new();
++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_HEADER_BAR)), widget);
++
++ GtkStyleContext* style = gtk_widget_get_style_context(widget);
++ gtk_style_context_add_class(style, MOZ_GTK_STYLE_CLASS_TITLEBUTTON);
++
++ switch (aWidgetType) {
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ gtk_style_context_add_class(style, "close");
++ break;
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ gtk_style_context_add_class(style, "minimize");
++ break;
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ gtk_style_context_add_class(style, "maximize");
++ break;
++ default:
++ break;
++ }
++
++ return widget;
++}
++
++static GtkWidget*
+ CreateWidget(WidgetNodeType aWidgetType)
+ {
+ switch (aWidgetType) {
+ case MOZ_GTK_WINDOW:
+- return CreateWindowWidget();
++ case MOZ_GTK_WINDOW_CSD:
++ return CreateWindowWidget(aWidgetType);
+ case MOZ_GTK_WINDOW_CONTAINER:
+ return CreateWindowContainerWidget();
+ case MOZ_GTK_CHECKBUTTON_CONTAINER:
+@@ -610,6 +685,13 @@ CreateWidget(WidgetNodeType aWidgetType)
+ return CreateComboBoxEntryButtonWidget();
+ case MOZ_GTK_COMBOBOX_ENTRY_ARROW:
+ return CreateComboBoxEntryArrowWidget();
++ case MOZ_GTK_HEADER_BAR:
++ case MOZ_GTK_HEADER_BAR_MAXIMIZED:
++ return CreateHeaderBar(aWidgetType == MOZ_GTK_HEADER_BAR_MAXIMIZED);
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ return CreateHeaderBarButton(aWidgetType);
+ default:
+ /* Not implemented */
+ return nullptr;
+@@ -1049,6 +1131,10 @@ GetCssNodeStyleInternal(WidgetNodeType a
+ GtkWidget* widget = GetWidget(MOZ_GTK_NOTEBOOK);
+ return gtk_widget_get_style_context(widget);
+ }
++ case MOZ_GTK_WINDOW_DECORATION:
++ style = CreateChildCSSNode("decoration",
++ MOZ_GTK_WINDOW_CSD);
++ break;
+ default:
+ return GetWidgetRootStyle(aNodeType);
+ }
+@@ -1214,6 +1300,8 @@ ResetWidgetCache(void)
+ /* This will destroy all of our widgets */
+ if (sWidgetStorage[MOZ_GTK_WINDOW])
+ gtk_widget_destroy(sWidgetStorage[MOZ_GTK_WINDOW]);
++ if (sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED])
++ gtk_widget_destroy(sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED]);
+
+ /* Clear already freed arrays */
+ mozilla::PodArrayZero(sWidgetStorage);
+diff -up firefox-57.0b8/widget/LookAndFeel.h.1399611 firefox-57.0b8/widget/LookAndFeel.h
+--- firefox-57.0b8/widget/LookAndFeel.h.1399611 2017-09-16 18:22:54.000000000 +0200
++++ firefox-57.0b8/widget/LookAndFeel.h 2017-10-16 12:11:45.369240636 +0200
+@@ -405,6 +405,30 @@ public:
+ eIntID_PhysicalHomeButton,
+
+ /*
++ * A boolean value indicating whether client-side decorations are
++ * supported by the user's GTK version.
++ */
++ eIntID_GTKCSDAvailable,
++
++ /*
++ * A boolean value indicating whether client-side decorations should
++ * contain a minimize button.
++ */
++ eIntID_GTKCSDMinimizeButton,
++
++ /*
++ * A boolean value indicating whether client-side decorations should
++ * contain a maximize button.
++ */
++ eIntID_GTKCSDMaximizeButton,
++
++ /*
++ * A boolean value indicating whether client-side decorations should
++ * contain a close button.
++ */
++ eIntID_GTKCSDCloseButton,
++
++ /*
+ * Controls whether overlay scrollbars display when the user moves
+ * the mouse in a scrollable frame.
+ */
diff --git a/mozilla-1405267.patch b/mozilla-1405267.patch
deleted file mode 100644
index 27fb5ea..0000000
--- a/mozilla-1405267.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-diff -up firefox-56.0/widget/gtk/mozgtk/mozgtk.c.1405267 firefox-56.0/widget/gtk/mozgtk/mozgtk.c
---- firefox-56.0/widget/gtk/mozgtk/mozgtk.c.1405267 2017-09-14 22:16:02.000000000 +0200
-+++ firefox-56.0/widget/gtk/mozgtk/mozgtk.c 2017-10-04 09:16:58.512697973 +0200
-@@ -96,6 +96,7 @@ STUB(gdk_window_get_update_area)
- STUB(gdk_window_get_user_data)
- STUB(gdk_window_get_visual)
- STUB(gdk_window_get_width)
-+STUB(gdk_window_get_window_type)
- STUB(gdk_window_hide)
- STUB(gdk_window_input_shape_combine_region)
- STUB(gdk_window_invalidate_rect)
-@@ -520,7 +521,6 @@ STUB(gdk_display_get_device_manager)
- STUB(gdk_error_trap_pop_ignored)
- STUB(gdk_event_get_source_device)
- STUB(gdk_window_get_type)
--STUB(gdk_window_get_window_type)
- STUB(gdk_x11_window_get_xid)
- STUB(gdk_x11_display_get_type)
- STUB(gdk_wayland_display_get_type)
diff --git a/rhbz-1497932.patch b/rhbz-1497932.patch
deleted file mode 100644
index d6e7886..0000000
--- a/rhbz-1497932.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff -up firefox-56.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old firefox-56.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium
-diff -up firefox-56.0/media/webrtc/trunk/Makefile.old firefox-56.0/media/webrtc/trunk/Makefile
-diff -up firefox-56.0/widget/gtk/mozgtk/mozgtk.c.old firefox-56.0/widget/gtk/mozgtk/mozgtk.c
---- firefox-56.0/widget/gtk/mozgtk/mozgtk.c.old 2017-10-04 09:21:56.155553585 +0200
-+++ firefox-56.0/widget/gtk/mozgtk/mozgtk.c 2017-10-04 09:22:35.562427061 +0200
-@@ -61,7 +61,6 @@ STUB(gdk_screen_get_height_mm)
- STUB(gdk_screen_get_n_monitors)
- STUB(gdk_screen_get_monitor_at_window)
- STUB(gdk_screen_get_monitor_geometry)
--STUB(gdk_screen_get_monitor_workarea)
- STUB(gdk_screen_get_monitor_height_mm)
- STUB(gdk_screen_get_number)
- STUB(gdk_screen_get_resolution)
-@@ -550,6 +549,7 @@ STUB(gtk_render_line)
- STUB(gtk_render_option)
- STUB(gtk_render_slider)
- STUB(gtk_scale_new)
-+STUB(gdk_screen_get_monitor_workarea)
- STUB(gtk_scrollbar_new)
- STUB(gtk_style_context_add_class)
- STUB(gtk_style_context_add_region)
diff --git a/sources b/sources
index f078f75..df2fde5 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
-SHA512 (firefox-56.0.source.tar.xz) = 3aeb0ff54e10c83894f61734daa4f0801a1bb499d4667adad9c78520e588eae809d0e4d61e9227206466d62c3b453e2ce9ca8198f59f5354cd1b6804c00f0990
-SHA512 (firefox-langpacks-56.0-20170927.tar.xz) = e74d85410891b6faa388d37043d764a6c01a2c83479d9912aa3d0b23684ed66ca639eb3cdb579cafef6c3156b0d774a66987a605e0f9e25c2d4eed967ef7b627
+SHA512 (firefox-57.0b9.source.tar.xz) = 5d09a07ae48198de8d8ada4018afb4c1cfe16d9294bbbd502d3f23915c43496604f19761a409a41a23ec712d622a556b0b6dc9efd186f4528724e52c8305dda1
+SHA512 (firefox-langpacks-57.0b9-20171019.tar.xz) = 07a3182edf634a5151e4c599e9f8a886e286c1e708f5743db10efeeb5526b4aa120153491da926c5bfcd69cb0e683ff83f2637fca53c78b9e256151768c20712
diff --git a/xulrunner-24.0-jemalloc-ppc.patch b/xulrunner-24.0-jemalloc-ppc.patch
index be6f259..840fca2 100644
--- a/xulrunner-24.0-jemalloc-ppc.patch
+++ b/xulrunner-24.0-jemalloc-ppc.patch
@@ -1,7 +1,7 @@
-diff -up firefox-48.0/memory/mozjemalloc/jemalloc.c.jemalloc-ppc firefox-48.0/memory/mozjemalloc/jemalloc.c
---- firefox-48.0/memory/mozjemalloc/mozjemalloc.cpp.jemalloc-ppc 2016-07-26 10:51:46.385434384 +0200
-+++ firefox-48.0/memory/mozjemalloc/mozjemalloc.cpp 2016-07-26 10:53:49.061023106 +0200
-@@ -1090,7 +1090,7 @@ static const bool config_recycle = false
+diff -up firefox-57.0b5/memory/build/mozjemalloc.cpp.old firefox-57.0b5/memory/build/mozjemalloc.cpp
+--- firefox-57.0b5/memory/build/mozjemalloc.cpp.old 2017-10-06 12:00:27.938687498 +0200
++++ firefox-57.0b5/memory/build/mozjemalloc.cpp 2017-10-06 12:02:45.232151309 +0200
+@@ -780,7 +780,7 @@ struct arena_t {
* controlling the malloc behavior are defined as compile-time constants
* for best performance and cannot be altered at runtime.
*/
bgstack15