mozilla-bmo1399611-csd.patch
branchfirefox57
changeset 1012 0c59a30173da
equal deleted inserted replaced
1011:85bd01789b6f 1012:0c59a30173da
       
     1 diff -up firefox-57.0b8/browser/app/profile/firefox.js.1399611 firefox-57.0b8/browser/app/profile/firefox.js
       
     2 --- firefox-57.0b8/browser/app/profile/firefox.js.1399611	2017-10-16 12:11:45.364240654 +0200
       
     3 +++ firefox-57.0b8/browser/app/profile/firefox.js	2017-10-16 12:28:03.860720910 +0200
       
     4 @@ -457,11 +457,7 @@ pref("browser.tabs.loadBookmarksInBackgr
       
     5  pref("browser.tabs.loadBookmarksInTabs", false);
       
     6  pref("browser.tabs.tabClipWidth", 140);
       
     7  pref("browser.tabs.tabMinWidth", 76);
       
     8 -#ifdef UNIX_BUT_NOT_MAC
       
     9 -pref("browser.tabs.drawInTitlebar", false);
       
    10 -#else
       
    11  pref("browser.tabs.drawInTitlebar", true);
       
    12 -#endif
       
    13  
       
    14  // Offer additional drag space to the user. The drag space
       
    15  // will only be shown if browser.tabs.drawInTitlebar is true.
       
    16 diff -up firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js.1399611 firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js
       
    17 --- firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js.1399611	2017-10-09 22:17:13.000000000 +0200
       
    18 +++ firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js	2017-10-16 12:11:45.364240654 +0200
       
    19 @@ -14,6 +14,11 @@ var TabsInTitlebar = {
       
    20      this._readPref();
       
    21      Services.prefs.addObserver(this._prefName, this);
       
    22  
       
    23 +    // Always disable on unsupported GTK versions.
       
    24 +    if (AppConstants.MOZ_WIDGET_TOOLKIT == "gtk3") {
       
    25 +      this.allowedBy("gtk", window.matchMedia("(-moz-gtk-csd-available)"));
       
    26 +    }
       
    27 +
       
    28      // We need to update the appearance of the titlebar when the menu changes
       
    29      // from the active to the inactive state. We can't, however, rely on
       
    30      // DOMMenuBarInactive, because the menu fires this event and then removes
       
    31 diff -up firefox-57.0b8/browser/base/moz.build.1399611 firefox-57.0b8/browser/base/moz.build
       
    32 --- firefox-57.0b8/browser/base/moz.build.1399611	2017-09-29 18:16:45.000000000 +0200
       
    33 +++ firefox-57.0b8/browser/base/moz.build	2017-10-16 12:11:45.364240654 +0200
       
    34 @@ -57,7 +57,7 @@ DEFINES['APP_LICENSE_BLOCK'] = '%s/conte
       
    35  if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
       
    36      DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1
       
    37  
       
    38 -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
       
    39 +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
       
    40      DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
       
    41  
       
    42  if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
       
    43 diff -up firefox-57.0b8/browser/themes/linux/browser.css.1399611 firefox-57.0b8/browser/themes/linux/browser.css
       
    44 --- firefox-57.0b8/browser/themes/linux/browser.css.1399611	2017-10-05 06:17:37.000000000 +0200
       
    45 +++ firefox-57.0b8/browser/themes/linux/browser.css	2017-10-16 12:11:45.365240651 +0200
       
    46 @@ -556,7 +556,9 @@ html|span.ac-emphasize-text-url {
       
    47  
       
    48  #nav-bar,
       
    49  #toolbar-menubar:not([autohide="true"]):not(:-moz-lwtheme):-moz-system-metric(menubar-drag),
       
    50 -#TabsToolbar:not(:-moz-lwtheme):-moz-system-metric(menubar-drag) {
       
    51 +#TabsToolbar:not(:-moz-lwtheme):-moz-system-metric(menubar-drag),
       
    52 +#main-window[tabsintitlebar] #toolbar-menubar:not([autohide="true"]),
       
    53 +#main-window[tabsintitlebar] #TabsToolbar {
       
    54    -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-drag");
       
    55  }
       
    56  
       
    57 @@ -713,3 +715,85 @@ html|span.ac-emphasize-text-url {
       
    58  .restore-tabs-button:hover:active:not([disabled="true"]) {
       
    59    padding: 3px;
       
    60  }
       
    61 +
       
    62 +@media not all and (-moz-gtk-csd-available) {
       
    63 +  #main-window > #titlebar {
       
    64 +    /* We need to hide the titlebar explicitly on versions of GTK without CSD. */
       
    65 +    display: none;
       
    66 +  }
       
    67 +}
       
    68 +
       
    69 +/* Titlebar/CSD */
       
    70 +@media (-moz-gtk-csd-available) {
       
    71 +  #main-window[tabsintitlebar][sizemode="normal"] > #titlebar {
       
    72 +    min-height: calc(var(--tab-min-height) + 12px);
       
    73 +  }
       
    74 +
       
    75 +  #main-window[tabsintitlebar] #titlebar:-moz-lwtheme {
       
    76 +    visibility: hidden;
       
    77 +  }
       
    78 +  #main-window[tabsintitlebar] #titlebar-content:-moz-lwtheme {
       
    79 +    visibility: visible;
       
    80 +  }
       
    81 +
       
    82 +  #main-window[tabsintitlebar][sizemode="normal"] > #titlebar {
       
    83 +    -moz-appearance: -moz-window-titlebar;
       
    84 +  }
       
    85 +  #main-window[tabsintitlebar][sizemode="maximized"] > #titlebar {
       
    86 +    -moz-appearance: -moz-window-titlebar-maximized;
       
    87 +  }
       
    88 +
       
    89 +  /* The button box must appear on top of the navigator-toolbox in order for
       
    90 +   * click and hover mouse events to work properly for the button in the restored
       
    91 +   * window state. Otherwise, elements in the navigator-toolbox, like the menubar,
       
    92 +   * can swallow those events.
       
    93 +   */
       
    94 +  #titlebar-buttonbox {
       
    95 +    z-index: 1;
       
    96 +  }
       
    97 +
       
    98 +  /* titlebar command buttons */
       
    99 +  /* Use full scale icons here as the Gtk+ does. */
       
   100 +  @media (-moz-gtk-csd-minimize-button) {
       
   101 +    #titlebar-min {
       
   102 +      list-style-image: url("moz-icon://stock/window-minimize-symbolic");
       
   103 +      -moz-appearance: -moz-window-button-minimize;
       
   104 +    }
       
   105 +  }
       
   106 +  @media not all and (-moz-gtk-csd-minimize-button) {
       
   107 +    #titlebar-min {
       
   108 +      display: none;
       
   109 +    }
       
   110 +  }
       
   111 +
       
   112 +  @media (-moz-gtk-csd-maximize-button) {
       
   113 +    #titlebar-max {
       
   114 +      list-style-image: url("moz-icon://stock/window-maximize-symbolic");
       
   115 +      -moz-appearance: -moz-window-button-maximize;
       
   116 +    }
       
   117 +    #main-window[sizemode="maximized"] #titlebar-max {
       
   118 +      list-style-image: url("moz-icon://stock/window-restore-symbolic");
       
   119 +      -moz-appearance: -moz-window-button-restore;
       
   120 +    }
       
   121 +  }
       
   122 +  @media not all and (-moz-gtk-csd-maximize-button) {
       
   123 +    #titlebar-max {
       
   124 +      display: none;
       
   125 +    }
       
   126 +    #main-window[sizemode="maximized"] #titlebar-max {
       
   127 +      display: none;
       
   128 +    }
       
   129 +  }
       
   130 +
       
   131 +  @media (-moz-gtk-csd-close-button) {
       
   132 +    #titlebar-close {
       
   133 +      list-style-image: url("moz-icon://stock/window-close-symbolic");
       
   134 +      -moz-appearance: -moz-window-button-close;
       
   135 +    }
       
   136 +  }
       
   137 +  @media not all and (-moz-gtk-csd-close-button) {
       
   138 +    #titlebar-close {
       
   139 +      display: none;
       
   140 +    }
       
   141 +  }
       
   142 +}
       
   143 diff -up firefox-57.0b8/dom/base/nsGkAtomList.h.1399611 firefox-57.0b8/dom/base/nsGkAtomList.h
       
   144 --- firefox-57.0b8/dom/base/nsGkAtomList.h.1399611	2017-09-15 06:15:41.000000000 +0200
       
   145 +++ firefox-57.0b8/dom/base/nsGkAtomList.h	2017-10-16 12:11:45.365240651 +0200
       
   146 @@ -2270,6 +2270,10 @@ GK_ATOM(touch_enabled, "touch-enabled")
       
   147  GK_ATOM(menubar_drag, "menubar-drag")
       
   148  GK_ATOM(swipe_animation_enabled, "swipe-animation-enabled")
       
   149  GK_ATOM(physical_home_button, "physical-home-button")
       
   150 +GK_ATOM(gtk_csd_available, "gtk-csd-available")
       
   151 +GK_ATOM(gtk_csd_minimize_button, "gtk-csd-minimize-button")
       
   152 +GK_ATOM(gtk_csd_maximize_button, "gtk-csd-maximize-button")
       
   153 +GK_ATOM(gtk_csd_close_button, "gtk-csd-close-button")
       
   154  
       
   155  // windows theme selector metrics
       
   156  GK_ATOM(windows_classic, "windows-classic")
       
   157 @@ -2306,6 +2310,10 @@ GK_ATOM(_moz_device_orientation, "-moz-d
       
   158  GK_ATOM(_moz_is_resource_document, "-moz-is-resource-document")
       
   159  GK_ATOM(_moz_swipe_animation_enabled, "-moz-swipe-animation-enabled")
       
   160  GK_ATOM(_moz_physical_home_button, "-moz-physical-home-button")
       
   161 +GK_ATOM(_moz_gtk_csd_available, "-moz-gtk-csd-available")
       
   162 +GK_ATOM(_moz_gtk_csd_minimize_button, "-moz-gtk-csd-minimize-button")
       
   163 +GK_ATOM(_moz_gtk_csd_maximize_button, "-moz-gtk-csd-maximize-button")
       
   164 +GK_ATOM(_moz_gtk_csd_close_button, "-moz-gtk-csd-close-button")
       
   165  
       
   166  // application commands
       
   167  GK_ATOM(Back, "Back")
       
   168 diff -up firefox-57.0b8/gfx/src/nsThemeConstants.h.1399611 firefox-57.0b8/gfx/src/nsThemeConstants.h
       
   169 --- firefox-57.0b8/gfx/src/nsThemeConstants.h.1399611	2017-06-12 18:37:10.000000000 +0200
       
   170 +++ firefox-57.0b8/gfx/src/nsThemeConstants.h	2017-10-16 12:11:45.365240651 +0200
       
   171 @@ -299,6 +299,7 @@ enum ThemeWidgetType : uint8_t {
       
   172    NS_THEME_MAC_SOURCE_LIST,
       
   173    NS_THEME_MAC_SOURCE_LIST_SELECTION,
       
   174    NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION,
       
   175 +  NS_THEME_GTK_WINDOW_DECORATION,
       
   176  
       
   177    ThemeWidgetType_COUNT
       
   178  };
       
   179 diff -up firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp.1399611 firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp
       
   180 --- firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp.1399611	2017-08-02 14:27:54.000000000 +0200
       
   181 +++ firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp	2017-10-16 12:11:45.365240651 +0200
       
   182 @@ -1180,6 +1180,30 @@ nsCSSRuleProcessor::InitSystemMetrics()
       
   183      sSystemMetrics->AppendElement(nsGkAtoms::physical_home_button);
       
   184    }
       
   185  
       
   186 +  rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
       
   187 +                           &metricResult);
       
   188 +  if (NS_SUCCEEDED(rv) && metricResult) {
       
   189 +    sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_available);
       
   190 +  }
       
   191 +
       
   192 +  rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDMinimizeButton,
       
   193 +                           &metricResult);
       
   194 +  if (NS_SUCCEEDED(rv) && metricResult) {
       
   195 +    sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_minimize_button);
       
   196 +  }
       
   197 +
       
   198 +  rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDMaximizeButton,
       
   199 +                           &metricResult);
       
   200 +  if (NS_SUCCEEDED(rv) && metricResult) {
       
   201 +    sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_maximize_button);
       
   202 +  }
       
   203 +
       
   204 +  rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDCloseButton,
       
   205 +                           &metricResult);
       
   206 +  if (NS_SUCCEEDED(rv) && metricResult) {
       
   207 +    sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_close_button);
       
   208 +  }
       
   209 +
       
   210  #ifdef XP_WIN
       
   211    if (NS_SUCCEEDED(
       
   212          LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsThemeIdentifier,
       
   213 diff -up firefox-57.0b8/layout/style/nsMediaFeatures.cpp.1399611 firefox-57.0b8/layout/style/nsMediaFeatures.cpp
       
   214 --- firefox-57.0b8/layout/style/nsMediaFeatures.cpp.1399611	2017-09-15 06:15:42.000000000 +0200
       
   215 +++ firefox-57.0b8/layout/style/nsMediaFeatures.cpp	2017-10-16 12:11:45.366240647 +0200
       
   216 @@ -788,6 +788,42 @@ nsMediaFeatures::features[] = {
       
   217      GetSystemMetric
       
   218    },
       
   219  
       
   220 +  {
       
   221 +    &nsGkAtoms::_moz_gtk_csd_available,
       
   222 +    nsMediaFeature::eMinMaxNotAllowed,
       
   223 +    nsMediaFeature::eBoolInteger,
       
   224 +    nsMediaFeature::eNoRequirements,
       
   225 +    { &nsGkAtoms::gtk_csd_available },
       
   226 +    GetSystemMetric
       
   227 +  },
       
   228 +
       
   229 +  {
       
   230 +    &nsGkAtoms::_moz_gtk_csd_minimize_button,
       
   231 +    nsMediaFeature::eMinMaxNotAllowed,
       
   232 +    nsMediaFeature::eBoolInteger,
       
   233 +    nsMediaFeature::eNoRequirements,
       
   234 +    { &nsGkAtoms::gtk_csd_minimize_button },
       
   235 +    GetSystemMetric
       
   236 +  },
       
   237 +
       
   238 +  {
       
   239 +    &nsGkAtoms::_moz_gtk_csd_maximize_button,
       
   240 +    nsMediaFeature::eMinMaxNotAllowed,
       
   241 +    nsMediaFeature::eBoolInteger,
       
   242 +    nsMediaFeature::eNoRequirements,
       
   243 +    { &nsGkAtoms::gtk_csd_maximize_button },
       
   244 +    GetSystemMetric
       
   245 +  },
       
   246 +
       
   247 +  {
       
   248 +    &nsGkAtoms::_moz_gtk_csd_close_button,
       
   249 +    nsMediaFeature::eMinMaxNotAllowed,
       
   250 +    nsMediaFeature::eBoolInteger,
       
   251 +    nsMediaFeature::eNoRequirements,
       
   252 +    { &nsGkAtoms::gtk_csd_close_button },
       
   253 +    GetSystemMetric
       
   254 +  },
       
   255 +
       
   256    // Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
       
   257    // Internal because it is really only useful in the user agent anyway
       
   258    //  and therefore not worth standardizing.
       
   259 diff -up firefox-57.0b8/modules/libpref/init/all.js.1399611 firefox-57.0b8/modules/libpref/init/all.js
       
   260 --- firefox-57.0b8/modules/libpref/init/all.js.1399611	2017-10-12 18:12:09.000000000 +0200
       
   261 +++ firefox-57.0b8/modules/libpref/init/all.js	2017-10-16 12:11:45.366240647 +0200
       
   262 @@ -4911,6 +4911,7 @@ pref("gfx.apitrace.enabled",false);
       
   263  pref("gfx.xrender.enabled",false);
       
   264  pref("widget.chrome.allow-gtk-dark-theme", false);
       
   265  pref("widget.content.allow-gtk-dark-theme", false);
       
   266 +pref("widget.allow-client-side-decoration", false);
       
   267  #endif
       
   268  #endif
       
   269  
       
   270 diff -up firefox-57.0b8/toolkit/modules/moz.build.1399611 firefox-57.0b8/toolkit/modules/moz.build
       
   271 --- firefox-57.0b8/toolkit/modules/moz.build.1399611	2017-09-15 06:15:40.000000000 +0200
       
   272 +++ firefox-57.0b8/toolkit/modules/moz.build	2017-10-16 12:11:45.366240647 +0200
       
   273 @@ -259,7 +259,7 @@ EXTRA_JS_MODULES.sessionstore += [
       
   274  ]
       
   275  
       
   276  DEFINES['INSTALL_COMPACT_THEMES'] = 1
       
   277 -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
       
   278 +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
       
   279      DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
       
   280  
       
   281  if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
       
   282 diff -up firefox-57.0b8/widget/gtk/gtk3drawing.cpp.1399611 firefox-57.0b8/widget/gtk/gtk3drawing.cpp
       
   283 --- firefox-57.0b8/widget/gtk/gtk3drawing.cpp.1399611	2017-09-15 06:15:40.000000000 +0200
       
   284 +++ firefox-57.0b8/widget/gtk/gtk3drawing.cpp	2017-10-16 12:11:45.367240644 +0200
       
   285 @@ -17,6 +17,7 @@
       
   286  #include "WidgetStyleCache.h"
       
   287  
       
   288  #include <math.h>
       
   289 +#include <dlfcn.h>
       
   290  
       
   291  static gboolean checkbox_check_state;
       
   292  static gboolean notebook_has_tab_gap;
       
   293 @@ -39,9 +40,25 @@ static gint
       
   294  moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
       
   295                          GtkWidgetState* state, GtkTextDirection direction);
       
   296  
       
   297 +static void
       
   298 +moz_gtk_add_style_margin(GtkStyleContext* style,
       
   299 +                         gint* left, gint* top, gint* right, gint* bottom);
       
   300 +static void
       
   301 +moz_gtk_add_style_border(GtkStyleContext* style,
       
   302 +                         gint* left, gint* top, gint* right, gint* bottom);
       
   303 +static void
       
   304 +moz_gtk_add_style_padding(GtkStyleContext* style,
       
   305 +                          gint* left, gint* top, gint* right, gint* bottom);
       
   306 +static void moz_gtk_add_margin_border_padding(GtkStyleContext *style,
       
   307 +                                              gint* left, gint* top,
       
   308 +                                              gint* right, gint* bottom);
       
   309 +static void moz_gtk_add_border_padding(GtkStyleContext *style,
       
   310 +                                       gint* left, gint* top,
       
   311 +                                       gint* right, gint* bottom);
       
   312  static GtkBorder
       
   313  GetMarginBorderPadding(GtkStyleContext* aStyle);
       
   314  
       
   315 +
       
   316  // GetStateFlagsFromGtkWidgetState() can be safely used for the specific
       
   317  // GtkWidgets that set both prelight and active flags.  For other widgets,
       
   318  // either the GtkStateFlags or Gecko's GtkWidgetState need to be carefully
       
   319 @@ -233,6 +250,43 @@ moz_gtk_splitter_get_metrics(gint orient
       
   320      return MOZ_GTK_SUCCESS;
       
   321  }
       
   322  
       
   323 +void
       
   324 +moz_gtk_get_window_border(gint* top, gint* right, gint* bottom, gint* left)
       
   325 +{
       
   326 +  MOZ_ASSERT(gtk_check_version(3, 20, 0) == nullptr,
       
   327 +             "Window decorations are only supported on GTK 3.20+.");
       
   328 +
       
   329 +  GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW);
       
   330 +
       
   331 +  *top = *right = *bottom = *left = 0;
       
   332 +  moz_gtk_add_border_padding(style, left, top, right, bottom);
       
   333 +  GtkBorder windowMargin;
       
   334 +  gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &windowMargin);
       
   335 +
       
   336 +  style = GetStyleContext(MOZ_GTK_WINDOW_DECORATION);
       
   337 +
       
   338 +  // Available on GTK 3.20+.
       
   339 +  static auto sGtkRenderBackgroundGetClip =
       
   340 +    (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*))
       
   341 +    dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip");
       
   342 +
       
   343 +  GdkRectangle shadowClip;
       
   344 +  sGtkRenderBackgroundGetClip(style, 0, 0, 0, 0, &shadowClip);
       
   345 +
       
   346 +  // Transfer returned inset rectangle to GtkBorder
       
   347 +  GtkBorder shadowBorder = {
       
   348 +      static_cast<gint16>(-shadowClip.x),                    // left
       
   349 +      static_cast<gint16>(shadowClip.width + shadowClip.x),  // right
       
   350 +      static_cast<gint16>(-shadowClip.y),                    // top
       
   351 +      static_cast<gint16>(shadowClip.height + shadowClip.y), // bottom
       
   352 +  };
       
   353 +
       
   354 +  *left += MAX(windowMargin.left, shadowBorder.left);
       
   355 +  *right += MAX(windowMargin.right, shadowBorder.right);
       
   356 +  *top += MAX(windowMargin.top, shadowBorder.top);
       
   357 +  *bottom += MAX(windowMargin.bottom, shadowBorder.bottom);
       
   358 +}
       
   359 +
       
   360  static gint
       
   361  moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect,
       
   362                       GtkTextDirection direction)
       
   363 @@ -302,6 +356,24 @@ moz_gtk_button_paint(cairo_t *cr, GdkRec
       
   364  }
       
   365  
       
   366  static gint
       
   367 +moz_gtk_header_bar_button_paint(cairo_t *cr, GdkRectangle* rect,
       
   368 +                                GtkWidgetState* state,
       
   369 +                                GtkReliefStyle relief, GtkWidget* widget,
       
   370 +                                GtkTextDirection direction)
       
   371 +{
       
   372 +    GtkBorder margin;
       
   373 +    GtkStyleContext* style = gtk_widget_get_style_context(widget);
       
   374 +    gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin);
       
   375 +
       
   376 +    rect->x += margin.left;
       
   377 +    rect->y += margin.top;
       
   378 +    rect->width -= margin.left + margin.right;
       
   379 +    rect->height -= margin.top + margin.bottom;
       
   380 +
       
   381 +    return moz_gtk_button_paint(cr, rect, state, relief, widget, direction);
       
   382 +}
       
   383 +
       
   384 +static gint
       
   385  moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect,
       
   386                       GtkWidgetState* state,
       
   387                       gboolean selected, gboolean inconsistent,
       
   388 @@ -1948,6 +2020,38 @@ moz_gtk_info_bar_paint(cairo_t *cr, GdkR
       
   389      return MOZ_GTK_SUCCESS;
       
   390  }
       
   391  
       
   392 +static gint
       
   393 +moz_gtk_header_bar_paint(WidgetNodeType widgetType,
       
   394 +                         cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state)
       
   395 +{
       
   396 +    GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
       
   397 +    GtkStyleContext *style;
       
   398 +
       
   399 +    style = GetStyleContext(widgetType, GTK_TEXT_DIR_LTR,
       
   400 +                            state_flags);
       
   401 +    InsetByMargin(rect, style);
       
   402 +    gtk_render_background(style, cr, rect->x, rect->y, rect->width,
       
   403 +                          rect->height);
       
   404 +    gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   405 +
       
   406 +    return MOZ_GTK_SUCCESS;
       
   407 +}
       
   408 +
       
   409 +void
       
   410 +moz_gtk_header_bar_paint(cairo_t *cr, GdkRectangle* rect)
       
   411 +{
       
   412 +    static GtkWidgetState state;
       
   413 +    moz_gtk_header_bar_paint(MOZ_GTK_HEADER_BAR, cr, rect, &state);
       
   414 +}
       
   415 +
       
   416 +void
       
   417 +moz_gtk_get_header_bar_border(gint* top, gint* right, gint* bottom, gint* left)
       
   418 +{
       
   419 +    *left = *top = *right = *bottom = 0;
       
   420 +    moz_gtk_add_border_padding(GetStyleContext(MOZ_GTK_HEADER_BAR),
       
   421 +                               left, top, right, bottom);
       
   422 +}
       
   423 +
       
   424  static void
       
   425  moz_gtk_add_style_margin(GtkStyleContext* style,
       
   426                           gint* left, gint* top, gint* right, gint* bottom)
       
   427 @@ -1999,6 +2103,14 @@ static void moz_gtk_add_margin_border_pa
       
   428      moz_gtk_add_style_padding(style, left, top, right, bottom);
       
   429  }
       
   430  
       
   431 +static void moz_gtk_add_border_padding(GtkStyleContext *style,
       
   432 +                                       gint* left, gint* top,
       
   433 +                                       gint* right, gint* bottom)
       
   434 +{
       
   435 +    moz_gtk_add_style_border(style, left, top, right, bottom);
       
   436 +    moz_gtk_add_style_padding(style, left, top, right, bottom);
       
   437 +}
       
   438 +
       
   439  static GtkBorder
       
   440  GetMarginBorderPadding(GtkStyleContext* aStyle)
       
   441  {
       
   442 @@ -2054,8 +2166,7 @@ moz_gtk_get_widget_border(WidgetNodeType
       
   443              // XXX: Subtract 1 pixel from the padding to account for the default
       
   444              // padding in forms.css. See bug 1187385.
       
   445              *left = *top = *right = *bottom = -1;
       
   446 -            moz_gtk_add_style_padding(style, left, top, right, bottom);
       
   447 -            moz_gtk_add_style_border(style, left, top, right, bottom);
       
   448 +            moz_gtk_add_border_padding(style, left, top, right, bottom);
       
   449  
       
   450              return MOZ_GTK_SUCCESS;
       
   451          }
       
   452 @@ -2076,10 +2187,8 @@ moz_gtk_get_widget_border(WidgetNodeType
       
   453              *left = *top = *right = *bottom =
       
   454                  gtk_container_get_border_width(GTK_CONTAINER(
       
   455                                                 GetWidget(MOZ_GTK_TREE_HEADER_CELL)));
       
   456 -
       
   457              style = GetStyleContext(MOZ_GTK_TREE_HEADER_CELL);
       
   458 -            moz_gtk_add_style_border(style, left, top, right, bottom);
       
   459 -            moz_gtk_add_style_padding(style, left, top, right, bottom);
       
   460 +            moz_gtk_add_border_padding(style, left, top, right, bottom);
       
   461              return MOZ_GTK_SUCCESS;
       
   462          }
       
   463      case MOZ_GTK_TREE_HEADER_SORTARROW:
       
   464 @@ -2105,8 +2214,7 @@ moz_gtk_get_widget_border(WidgetNodeType
       
   465                  gtk_container_get_border_width(GTK_CONTAINER(
       
   466                                                 GetWidget(MOZ_GTK_COMBOBOX_BUTTON)));
       
   467              style = GetStyleContext(MOZ_GTK_COMBOBOX_BUTTON);
       
   468 -            moz_gtk_add_style_padding(style, left, top, right, bottom);
       
   469 -            moz_gtk_add_style_border(style, left, top, right, bottom);
       
   470 +            moz_gtk_add_border_padding(style, left, top, right, bottom);
       
   471  
       
   472              /* If there is no separator, don't try to count its width. */
       
   473              separator_width = 0;
       
   474 @@ -2160,10 +2268,8 @@ moz_gtk_get_widget_border(WidgetNodeType
       
   475              style = gtk_widget_get_style_context(w);
       
   476  
       
   477              *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w));
       
   478 -            moz_gtk_add_style_border(style,
       
   479 -                                     left, top, right, bottom);
       
   480 -            moz_gtk_add_style_padding(style,
       
   481 -                                      left, top, right, bottom);
       
   482 +            moz_gtk_add_border_padding(style,
       
   483 +                                       left, top, right, bottom);
       
   484              return MOZ_GTK_SUCCESS;
       
   485          }
       
   486      case MOZ_GTK_MENUPOPUP:
       
   487 @@ -2210,6 +2316,21 @@ moz_gtk_get_widget_border(WidgetNodeType
       
   488  
       
   489              return MOZ_GTK_SUCCESS;
       
   490          }
       
   491 +    case MOZ_GTK_HEADER_BAR:
       
   492 +    case MOZ_GTK_HEADER_BAR_MAXIMIZED:
       
   493 +        {
       
   494 +            style = GetStyleContext(widget);
       
   495 +            moz_gtk_add_border_padding(style, left, top, right, bottom);
       
   496 +            return MOZ_GTK_SUCCESS;
       
   497 +        }
       
   498 +    case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
       
   499 +    case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
       
   500 +    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
       
   501 +        {
       
   502 +            style = GetStyleContext(widget);
       
   503 +            moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
       
   504 +            return MOZ_GTK_SUCCESS;
       
   505 +        }
       
   506  
       
   507      /* These widgets have no borders, since they are not containers. */
       
   508      case MOZ_GTK_CHECKBUTTON_LABEL:
       
   509 @@ -2646,6 +2767,36 @@ GetScrollbarMetrics(GtkOrientation aOrie
       
   510      return metrics;
       
   511  }
       
   512  
       
   513 +void
       
   514 +moz_gtk_window_decoration_paint(cairo_t *cr, GdkRectangle* rect)
       
   515 +{
       
   516 +    gint top, right, bottom, left;
       
   517 +    moz_gtk_get_window_border(&top, &right, &bottom, &left);
       
   518 +
       
   519 +    cairo_save(cr);
       
   520 +    cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
       
   521 +    cairo_rectangle(cr, rect->x, rect->y, left, rect->height);
       
   522 +    cairo_fill(cr);
       
   523 +    cairo_rectangle(cr, rect->x+rect->width-right, rect->y, right, rect->height);
       
   524 +    cairo_fill(cr);
       
   525 +    cairo_rectangle(cr, rect->x, rect->y, rect->width, top);
       
   526 +    cairo_fill(cr);
       
   527 +    cairo_rectangle(cr, rect->x, rect->height-bottom, rect->width, bottom);
       
   528 +    cairo_fill(cr);
       
   529 +    cairo_restore(cr);
       
   530 +
       
   531 +    GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW_DECORATION,
       
   532 +                                               GTK_TEXT_DIR_NONE);
       
   533 +    rect->x += left;
       
   534 +    rect->y += top;
       
   535 +    rect->width -= left + right;
       
   536 +    rect->height -= top + bottom;
       
   537 +
       
   538 +    gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   539 +    gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
       
   540 +}
       
   541 +
       
   542 +
       
   543  /* cairo_t *cr argument has to be a system-cairo. */
       
   544  gint
       
   545  moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr,
       
   546 @@ -2671,6 +2822,14 @@ moz_gtk_widget_paint(WidgetNodeType widg
       
   547                                      GetWidget(MOZ_GTK_BUTTON),
       
   548                                      direction);
       
   549          break;
       
   550 +    case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
       
   551 +    case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
       
   552 +    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
       
   553 +        return moz_gtk_header_bar_button_paint(cr, rect, state,
       
   554 +                                               (GtkReliefStyle) flags,
       
   555 +                                               GetWidget(widget),
       
   556 +                                               direction);
       
   557 +        break;
       
   558      case MOZ_GTK_CHECKBUTTON:
       
   559      case MOZ_GTK_RADIOBUTTON:
       
   560          return moz_gtk_toggle_paint(cr, rect, state,
       
   561 @@ -2877,6 +3036,10 @@ moz_gtk_widget_paint(WidgetNodeType widg
       
   562      case MOZ_GTK_INFO_BAR:
       
   563          return moz_gtk_info_bar_paint(cr, rect, state);
       
   564          break;
       
   565 +    case MOZ_GTK_HEADER_BAR:
       
   566 +    case MOZ_GTK_HEADER_BAR_MAXIMIZED:
       
   567 +        return moz_gtk_header_bar_paint(widget, cr, rect, state);
       
   568 +        break;
       
   569      default:
       
   570          g_warning("Unknown widget type: %d", widget);
       
   571      }
       
   572 diff -up firefox-57.0b8/widget/gtk/gtkdrawing.h.1399611 firefox-57.0b8/widget/gtk/gtkdrawing.h
       
   573 --- firefox-57.0b8/widget/gtk/gtkdrawing.h.1399611	2017-06-12 18:37:20.000000000 +0200
       
   574 +++ firefox-57.0b8/widget/gtk/gtkdrawing.h	2017-10-16 12:11:45.367240644 +0200
       
   575 @@ -268,8 +268,14 @@ typedef enum {
       
   576    MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL,
       
   577    /* Paints the background of a window, dialog or page. */
       
   578    MOZ_GTK_WINDOW,
       
   579 +  /* Used only as a container for MOZ_GTK_HEADER_BAR_MAXIMIZED. */
       
   580 +  MOZ_GTK_WINDOW_MAXIMIZED,
       
   581    /* Window container for all widgets */
       
   582    MOZ_GTK_WINDOW_CONTAINER,
       
   583 +  /* Window with the 'csd' style class. */
       
   584 +  MOZ_GTK_WINDOW_CSD,
       
   585 +  /* Client-side window decoration node. Available on GTK 3.20+. */
       
   586 +  MOZ_GTK_WINDOW_DECORATION,
       
   587    /* Paints a GtkInfoBar, for notifications. */
       
   588    MOZ_GTK_INFO_BAR,
       
   589    /* Used for widget tree construction. */
       
   590 @@ -290,6 +296,14 @@ typedef enum {
       
   591    MOZ_GTK_COMBOBOX_ENTRY_ARROW,
       
   592    /* Used for scrolled window shell. */
       
   593    MOZ_GTK_SCROLLED_WINDOW,
       
   594 +  /* Paints a GtkHeaderBar */
       
   595 +  MOZ_GTK_HEADER_BAR,
       
   596 +  /* Paints a GtkHeaderBar in maximized state */
       
   597 +  MOZ_GTK_HEADER_BAR_MAXIMIZED,
       
   598 +  /* Paints a GtkHeaderBar title buttons */
       
   599 +  MOZ_GTK_HEADER_BAR_BUTTON_CLOSE,
       
   600 +  MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE,
       
   601 +  MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE,
       
   602  
       
   603    MOZ_GTK_WIDGET_NODE_COUNT
       
   604  } WidgetNodeType;
       
   605 @@ -542,6 +556,32 @@ gint moz_gtk_get_menu_separator_height(g
       
   606   */
       
   607  gint moz_gtk_splitter_get_metrics(gint orientation, gint* size);
       
   608  
       
   609 +#if (MOZ_WIDGET_GTK == 3)
       
   610 +/**
       
   611 + * Gets the margins to be used for window decorations, typically the extra space
       
   612 + * required to draw a drop shadow (obtained from gtk_render_background_get_clip).
       
   613 + * Only available on GTK 3.20+.
       
   614 + */
       
   615 +void moz_gtk_get_window_border(gint* top, gint* right, gint* bottom, gint* left);
       
   616 +
       
   617 +/**
       
   618 + * Draw window decorations, typically a shadow.
       
   619 + * Only available on GTK 3.20+.
       
   620 + */
       
   621 +void moz_gtk_window_decoration_paint(cairo_t *cr, GdkRectangle* rect);
       
   622 +
       
   623 +/**
       
   624 + * Gets the border of window header bar, only available on GTK 3.20+.
       
   625 + */
       
   626 +void moz_gtk_get_header_bar_border(gint* top, gint* right, gint* bottom, gint* left);
       
   627 +
       
   628 +/**
       
   629 + * Draw window header bar, only available on GTK 3.20+.
       
   630 + */
       
   631 +void moz_gtk_header_bar_paint(cairo_t *cr, GdkRectangle* rect);
       
   632 +
       
   633 +#endif
       
   634 +
       
   635  /**
       
   636   * Get the YTHICKNESS of a tab (notebook extension).
       
   637   */
       
   638 diff -up firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c.1399611 firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c
       
   639 --- firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c.1399611	2017-10-09 22:17:13.000000000 +0200
       
   640 +++ firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c	2017-10-16 12:11:45.367240644 +0200
       
   641 @@ -580,6 +580,8 @@ STUB(gtk_style_context_set_state)
       
   642  STUB(gtk_style_properties_lookup_property)
       
   643  STUB(gtk_tree_view_column_get_button)
       
   644  STUB(gtk_widget_get_preferred_size)
       
   645 +STUB(gtk_widget_get_preferred_width)
       
   646 +STUB(gtk_widget_get_preferred_height)
       
   647  STUB(gtk_widget_get_state_flags)
       
   648  STUB(gtk_widget_get_style_context)
       
   649  STUB(gtk_widget_path_append_type)
       
   650 @@ -589,6 +591,10 @@ STUB(gtk_widget_path_iter_add_class)
       
   651  STUB(gtk_widget_path_get_object_type)
       
   652  STUB(gtk_widget_path_new)
       
   653  STUB(gtk_widget_path_unref)
       
   654 +STUB(gtk_widget_set_margin_left)
       
   655 +STUB(gtk_widget_set_margin_right)
       
   656 +STUB(gtk_widget_set_margin_top)
       
   657 +STUB(gtk_widget_set_margin_bottom)
       
   658  STUB(gtk_widget_set_visual)
       
   659  STUB(gtk_app_chooser_dialog_new_for_content_type)
       
   660  STUB(gtk_app_chooser_get_type)
       
   661 @@ -601,6 +607,7 @@ STUB(gtk_color_chooser_get_type)
       
   662  STUB(gtk_color_chooser_set_rgba)
       
   663  STUB(gtk_color_chooser_get_rgba)
       
   664  STUB(gtk_color_chooser_set_use_alpha)
       
   665 +STUB(gtk_window_get_size)
       
   666  #endif
       
   667  
       
   668  #ifdef GTK2_SYMBOLS
       
   669 diff -up firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp.1399611 firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp
       
   670 --- firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp.1399611	2017-09-21 06:10:10.000000000 +0200
       
   671 +++ firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp	2017-10-16 12:11:45.367240644 +0200
       
   672 @@ -642,6 +642,22 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
       
   673      case eIntID_ContextMenuOffsetHorizontal:
       
   674          aResult = 2;
       
   675          break;
       
   676 +    case eIntID_GTKCSDAvailable:
       
   677 +        EnsureInit();
       
   678 +        aResult = sCSDAvailable;
       
   679 +        break;
       
   680 +    case eIntID_GTKCSDMaximizeButton:
       
   681 +        EnsureInit();
       
   682 +        aResult = sCSDMaximizeButton;
       
   683 +        break;
       
   684 +    case eIntID_GTKCSDMinimizeButton:
       
   685 +        EnsureInit();
       
   686 +        aResult = sCSDMinimizeButton;
       
   687 +        break;
       
   688 +    case eIntID_GTKCSDCloseButton:
       
   689 +        EnsureInit();
       
   690 +        aResult = sCSDCloseButton;
       
   691 +        break;
       
   692      default:
       
   693          aResult = 0;
       
   694          res     = NS_ERROR_FAILURE;
       
   695 @@ -1048,6 +1064,40 @@ nsLookAndFeel::EnsureInit()
       
   696  
       
   697      gtk_widget_destroy(window);
       
   698      g_object_unref(labelWidget);
       
   699 +
       
   700 +    // Require GTK 3.20 for client-side decoration support.
       
   701 +    // 3.20 exposes gtk_render_background_get_clip, which is required for
       
   702 +    // calculating shadow metrics for decorated windows.
       
   703 +    sCSDAvailable = gtk_check_version(3, 20, 0) == nullptr;
       
   704 +    if (sCSDAvailable) {
       
   705 +        sCSDAvailable =
       
   706 +            mozilla::Preferences::GetBool("widget.allow-client-side-decoration",
       
   707 +                                          false);
       
   708 +    }
       
   709 +
       
   710 +    const gchar* decorationLayout = nullptr;
       
   711 +    if (gtk_check_version(3, 12, 0) == nullptr) {
       
   712 +        static auto sGtkHeaderBarGetDecorationLayoutPtr =
       
   713 +          (const gchar* (*)(GtkWidget*))
       
   714 +          dlsym(RTLD_DEFAULT, "gtk_header_bar_get_decoration_layout");
       
   715 +
       
   716 +        GtkWidget* headerBar = GetWidget(MOZ_GTK_HEADER_BAR);
       
   717 +        decorationLayout = sGtkHeaderBarGetDecorationLayoutPtr(headerBar);
       
   718 +        if (!decorationLayout) {
       
   719 +            g_object_get(settings, "gtk-decoration-layout", &decorationLayout,
       
   720 +                         nullptr);
       
   721 +        }
       
   722 +    }
       
   723 +
       
   724 +    if (decorationLayout) {
       
   725 +        sCSDCloseButton = (strstr(decorationLayout, "close") != nullptr);
       
   726 +        sCSDMaximizeButton = (strstr(decorationLayout, "maximize") != nullptr);
       
   727 +        sCSDMinimizeButton = (strstr(decorationLayout, "minimize") != nullptr);
       
   728 +    } else {
       
   729 +        sCSDCloseButton = true;
       
   730 +        sCSDMaximizeButton = true;
       
   731 +        sCSDMinimizeButton = true;
       
   732 +    }
       
   733  }
       
   734  
       
   735  // virtual
       
   736 diff -up firefox-57.0b8/widget/gtk/nsLookAndFeel.h.1399611 firefox-57.0b8/widget/gtk/nsLookAndFeel.h
       
   737 --- firefox-57.0b8/widget/gtk/nsLookAndFeel.h.1399611	2017-09-21 06:10:10.000000000 +0200
       
   738 +++ firefox-57.0b8/widget/gtk/nsLookAndFeel.h	2017-10-16 12:11:45.367240644 +0200
       
   739 @@ -32,6 +32,8 @@ public:
       
   740      virtual char16_t GetPasswordCharacterImpl();
       
   741      virtual bool GetEchoPasswordImpl();
       
   742  
       
   743 +    bool IsCSDAvailable() const { return sCSDAvailable; }
       
   744 +
       
   745  protected:
       
   746  
       
   747      // Cached fonts
       
   748 @@ -82,6 +84,10 @@ protected:
       
   749      char16_t sInvisibleCharacter;
       
   750      float   sCaretRatio;
       
   751      bool    sMenuSupportsDrag;
       
   752 +    bool    sCSDAvailable;
       
   753 +    bool    sCSDMaximizeButton;
       
   754 +    bool    sCSDMinimizeButton;
       
   755 +    bool    sCSDCloseButton;
       
   756      bool    mInitialized;
       
   757  
       
   758      void EnsureInit();
       
   759 diff -up firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp.1399611 firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp
       
   760 --- firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp.1399611	2017-09-19 06:18:28.000000000 +0200
       
   761 +++ firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp	2017-10-16 12:11:45.368240640 +0200
       
   762 @@ -23,6 +23,7 @@
       
   763  #include "nsIDOMHTMLInputElement.h"
       
   764  #include "nsGkAtoms.h"
       
   765  #include "nsAttrValueInlines.h"
       
   766 +#include "nsWindow.h"
       
   767  
       
   768  #include "mozilla/EventStates.h"
       
   769  #include "mozilla/Services.h"
       
   770 @@ -703,6 +704,24 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
       
   771    case NS_THEME_GTK_INFO_BAR:
       
   772      aGtkWidgetType = MOZ_GTK_INFO_BAR;
       
   773      break;
       
   774 +  case NS_THEME_WINDOW_TITLEBAR:
       
   775 +    aGtkWidgetType = MOZ_GTK_HEADER_BAR;
       
   776 +    break;
       
   777 +  case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
       
   778 +    aGtkWidgetType = MOZ_GTK_HEADER_BAR_MAXIMIZED;
       
   779 +    break;
       
   780 +  case NS_THEME_WINDOW_BUTTON_CLOSE:
       
   781 +    aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE;
       
   782 +    break;
       
   783 +  case NS_THEME_WINDOW_BUTTON_MINIMIZE:
       
   784 +    aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE;
       
   785 +    break;
       
   786 +  case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
       
   787 +    aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
       
   788 +    break;
       
   789 +  case NS_THEME_WINDOW_BUTTON_RESTORE:
       
   790 +    aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
       
   791 +    break;
       
   792    default:
       
   793      return false;
       
   794    }
       
   795 @@ -1627,6 +1646,10 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
       
   796    case NS_THEME_MENULIST:
       
   797    case NS_THEME_TOOLBARBUTTON:
       
   798    case NS_THEME_TREEHEADERCELL:
       
   799 +  case NS_THEME_WINDOW_BUTTON_CLOSE:
       
   800 +  case NS_THEME_WINDOW_BUTTON_MINIMIZE:
       
   801 +  case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
       
   802 +  case NS_THEME_WINDOW_BUTTON_RESTORE:
       
   803      {
       
   804        if (aWidgetType == NS_THEME_MENULIST) {
       
   805          // Include the arrow size.
       
   806 @@ -1892,9 +1915,21 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns
       
   807    case NS_THEME_DIALOG:
       
   808  #if (MOZ_WIDGET_GTK == 3)
       
   809    case NS_THEME_GTK_INFO_BAR:
       
   810 +  case NS_THEME_GTK_WINDOW_DECORATION:
       
   811  #endif
       
   812      return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
       
   813  
       
   814 +  case NS_THEME_WINDOW_BUTTON_CLOSE:
       
   815 +  case NS_THEME_WINDOW_BUTTON_MINIMIZE:
       
   816 +  case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
       
   817 +  case NS_THEME_WINDOW_BUTTON_RESTORE:
       
   818 +  case NS_THEME_WINDOW_TITLEBAR:
       
   819 +  case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
       
   820 +    // GtkHeaderBar is available on GTK 3.10+, which is used for styling
       
   821 +    // title bars and title buttons.
       
   822 +    return gtk_check_version(3, 10, 0) == nullptr &&
       
   823 +           !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
       
   824 +
       
   825    case NS_THEME_MENULIST_BUTTON:
       
   826      if (aFrame && aFrame->GetWritingMode().IsVertical()) {
       
   827        return false;
       
   828 @@ -1978,6 +2013,13 @@ nsNativeThemeGTK::GetWidgetTransparency(
       
   829  #else
       
   830      return eTransparent;
       
   831  #endif
       
   832 +  case NS_THEME_GTK_WINDOW_DECORATION:
       
   833 +  {
       
   834 +    nsWindow* window = static_cast<nsWindow*>(aFrame->GetNearestWidget());
       
   835 +    if (window)
       
   836 +      return window->IsComposited() ? eTransparent : eOpaque;
       
   837 +    return eOpaque;
       
   838 +  }
       
   839    }
       
   840  
       
   841    return eUnknownTransparency;
       
   842 diff -up firefox-57.0b8/widget/gtk/nsWindow.cpp.1399611 firefox-57.0b8/widget/gtk/nsWindow.cpp
       
   843 --- firefox-57.0b8/widget/gtk/nsWindow.cpp.1399611	2017-10-16 12:11:45.361240666 +0200
       
   844 +++ firefox-57.0b8/widget/gtk/nsWindow.cpp	2017-10-16 12:11:45.369240636 +0200
       
   845 @@ -85,6 +85,7 @@
       
   846  #include "nsIPropertyBag2.h"
       
   847  #include "GLContext.h"
       
   848  #include "gfx2DGlue.h"
       
   849 +#include "nsLookAndFeel.h"
       
   850  
       
   851  #ifdef ACCESSIBILITY
       
   852  #include "mozilla/a11y/Accessible.h"
       
   853 @@ -139,6 +140,8 @@ using namespace mozilla::widget;
       
   854  
       
   855  #include "mozilla/layers/APZCTreeManager.h"
       
   856  
       
   857 +#include "gtkdrawing.h"
       
   858 +
       
   859  using namespace mozilla;
       
   860  using namespace mozilla::gfx;
       
   861  using namespace mozilla::widget;
       
   862 @@ -186,6 +189,8 @@ static gboolean expose_event_cb
       
   863  #else
       
   864  static gboolean expose_event_cb           (GtkWidget *widget,
       
   865                                             cairo_t *rect);
       
   866 +static gboolean expose_event_decoration_draw_cb (GtkWidget *widget,
       
   867 +                                                cairo_t *cr);
       
   868  #endif
       
   869  static gboolean configure_event_cb        (GtkWidget *widget,
       
   870                                             GdkEventConfigure *event);
       
   871 @@ -231,7 +236,6 @@ static void     screen_composited_change
       
   872                                                    gpointer user_data);
       
   873  static void     widget_composited_changed_cb     (GtkWidget* widget,
       
   874                                                    gpointer user_data);
       
   875 -
       
   876  #if (MOZ_WIDGET_GTK == 3)
       
   877  static void     scale_changed_cb          (GtkWidget* widget,
       
   878                                             GParamSpec* aPSpec,
       
   879 @@ -440,6 +444,7 @@ nsWindow::nsWindow()
       
   880  
       
   881      mContainer           = nullptr;
       
   882      mGdkWindow           = nullptr;
       
   883 +    mIsCSDEnabled        = false;
       
   884      mShell               = nullptr;
       
   885      mCompositorWidgetDelegate = nullptr;
       
   886      mHasMappedToplevel   = false;
       
   887 @@ -481,6 +486,9 @@ nsWindow::nsWindow()
       
   888      mLastScrollEventTime = GDK_CURRENT_TIME;
       
   889  #endif
       
   890      mPendingConfigures = 0;
       
   891 +    mDrawWindowDecoration = false;
       
   892 +    mDecorationSize = {0,0,0,0};
       
   893 +    mCSDSupportLevel = CSD_SUPPORT_UNKNOWN;
       
   894  }
       
   895  
       
   896  nsWindow::~nsWindow()
       
   897 @@ -1479,8 +1487,8 @@ LayoutDeviceIntRect
       
   898  nsWindow::GetScreenBounds()
       
   899  {
       
   900      LayoutDeviceIntRect rect;
       
   901 -    if (mIsTopLevel && mContainer) {
       
   902 -        // use the point including window decorations
       
   903 +    if (mIsTopLevel && mContainer && !IsClientDecorated()) {
       
   904 +        // use the point including default Gtk+ window decorations
       
   905          gint x, y;
       
   906          gdk_window_get_root_origin(gtk_widget_get_window(GTK_WIDGET(mContainer)), &x, &y);
       
   907          rect.MoveTo(GdkPointToDevicePixels({ x, y }));
       
   908 @@ -1606,6 +1614,10 @@ nsWindow::SetCursor(nsCursor aCursor)
       
   909                  return;
       
   910  
       
   911              gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), newCursor);
       
   912 +            if (IsClientDecorated()) {
       
   913 +                gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mShell)),
       
   914 +                                      newCursor);
       
   915 +            }
       
   916          }
       
   917      }
       
   918  }
       
   919 @@ -1662,6 +1674,10 @@ nsWindow::SetCursor(imgIContainer* aCurs
       
   920      if (cursor) {
       
   921          if (mContainer) {
       
   922              gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), cursor);
       
   923 +            if (IsClientDecorated()) {
       
   924 +                gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mShell)),
       
   925 +                                      cursor);
       
   926 +            }
       
   927              rv = NS_OK;
       
   928          }
       
   929  #if (MOZ_WIDGET_GTK == 3)
       
   930 @@ -2176,6 +2192,12 @@ nsWindow::OnExposeEvent(cairo_t *cr)
       
   931          return TRUE;
       
   932      }
       
   933  
       
   934 +    // Clip upper part of the mContainer to get visible rounded corners
       
   935 +    // of GtkHeaderBar which is renderd to mShell.
       
   936 +    if (mIsCSDEnabled) {
       
   937 +        ApplyCSDClipping();
       
   938 +    }
       
   939 +
       
   940      // If this widget uses OMTC...
       
   941      if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT ||
       
   942          GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR) {
       
   943 @@ -2586,6 +2608,53 @@ nsWindow::OnMotionNotifyEvent(GdkEventMo
       
   944          }
       
   945      }
       
   946  #endif /* MOZ_X11 */
       
   947 +    // Client is decorated and we're getting the motion event for mShell
       
   948 +    // window which draws the CSD decorations around mContainer.
       
   949 +    if (IsClientDecorated()) {
       
   950 +        if (aEvent->window == gtk_widget_get_window(mShell)) {
       
   951 +            GdkWindowEdge edge;
       
   952 +            LayoutDeviceIntPoint refPoint =
       
   953 +                GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
       
   954 +            if (CheckResizerEdge(refPoint, edge)) {
       
   955 +                nsCursor cursor = eCursor_none;
       
   956 +                switch (edge) {
       
   957 +                case GDK_WINDOW_EDGE_NORTH:
       
   958 +                    cursor = eCursor_n_resize;
       
   959 +                    break;
       
   960 +                case GDK_WINDOW_EDGE_NORTH_WEST:
       
   961 +                    cursor = eCursor_nw_resize;
       
   962 +                    break;
       
   963 +                case GDK_WINDOW_EDGE_NORTH_EAST:
       
   964 +                    cursor = eCursor_ne_resize;
       
   965 +                    break;
       
   966 +                case GDK_WINDOW_EDGE_WEST:
       
   967 +                    cursor = eCursor_w_resize;
       
   968 +                    break;
       
   969 +                case GDK_WINDOW_EDGE_EAST:
       
   970 +                    cursor = eCursor_e_resize;
       
   971 +                    break;
       
   972 +                case GDK_WINDOW_EDGE_SOUTH:
       
   973 +                    cursor = eCursor_s_resize;
       
   974 +                    break;
       
   975 +                case GDK_WINDOW_EDGE_SOUTH_WEST:
       
   976 +                    cursor = eCursor_sw_resize;
       
   977 +                    break;
       
   978 +                case GDK_WINDOW_EDGE_SOUTH_EAST:
       
   979 +                    cursor = eCursor_se_resize;
       
   980 +                    break;
       
   981 +                }
       
   982 +                SetCursor(cursor);
       
   983 +                return;
       
   984 +            }
       
   985 +        }
       
   986 +        // We're not on resize handle - check if we need to reset cursor back.
       
   987 +        if (mCursor == eCursor_n_resize || mCursor == eCursor_nw_resize ||
       
   988 +            mCursor == eCursor_ne_resize ||  mCursor == eCursor_w_resize ||
       
   989 +            mCursor == eCursor_e_resize || mCursor == eCursor_s_resize ||
       
   990 +            mCursor == eCursor_sw_resize || mCursor == eCursor_se_resize) {
       
   991 +            SetCursor(eCursor_standard);
       
   992 +        }
       
   993 +    }
       
   994  
       
   995      WidgetMouseEvent event(true, eMouseMove, this, WidgetMouseEvent::eReal);
       
   996  
       
   997 @@ -2756,6 +2825,20 @@ nsWindow::OnButtonPressEvent(GdkEventBut
       
   998      if (CheckForRollup(aEvent->x_root, aEvent->y_root, false, false))
       
   999          return;
       
  1000  
       
  1001 +    if (IsClientDecorated() && aEvent->window == gtk_widget_get_window(mShell)) {
       
  1002 +        // Check to see if the event is within our window's resize region
       
  1003 +        GdkWindowEdge edge;
       
  1004 +        LayoutDeviceIntPoint refPoint =
       
  1005 +            GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
       
  1006 +        if (CheckResizerEdge(refPoint, edge)) {
       
  1007 +            gdk_window_begin_resize_drag(gtk_widget_get_window(mShell),
       
  1008 +                                         edge, aEvent->button,
       
  1009 +                                         aEvent->x_root, aEvent->y_root,
       
  1010 +                                         aEvent->time);
       
  1011 +            return;
       
  1012 +        }
       
  1013 +    }
       
  1014 +
       
  1015      gdouble pressure = 0;
       
  1016      gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
       
  1017      mLastMotionPressure = pressure;
       
  1018 @@ -3341,6 +3424,8 @@ nsWindow::OnWindowStateEvent(GtkWidget *
       
  1019  #endif //ACCESSIBILITY
       
  1020      }
       
  1021  
       
  1022 +    UpdateClientDecorations();
       
  1023 +
       
  1024      if (mWidgetListener) {
       
  1025        mWidgetListener->SizeModeChanged(mSizeState);
       
  1026        if (aEvent->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
       
  1027 @@ -3405,6 +3490,7 @@ nsWindow::OnCompositedChanged()
       
  1028        presShell->ThemeChanged();
       
  1029      }
       
  1030    }
       
  1031 +  UpdateClientDecorations();
       
  1032  }
       
  1033  
       
  1034  void
       
  1035 @@ -3593,7 +3679,8 @@ nsWindow::Create(nsIWidget* aParent,
       
  1036      GtkWindow      *topLevelParent = nullptr;
       
  1037      nsWindow       *parentnsWindow = nullptr;
       
  1038      GtkWidget      *eventWidget = nullptr;
       
  1039 -    bool            shellHasCSD = false;
       
  1040 +    GtkWidget      *drawWidget = nullptr;
       
  1041 +    bool            drawToContainer = false;
       
  1042  
       
  1043      if (aParent) {
       
  1044          parentnsWindow = static_cast<nsWindow*>(aParent);
       
  1045 @@ -3640,29 +3727,47 @@ nsWindow::Create(nsIWidget* aParent,
       
  1046                GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
       
  1047          mShell = gtk_window_new(type);
       
  1048  
       
  1049 -        bool useAlphaVisual = (mWindowType == eWindowType_popup &&
       
  1050 -                               aInitData->mSupportTranslucency);
       
  1051 +        bool useAlphaVisual = false;
       
  1052 +#if (MOZ_WIDGET_GTK == 3)
       
  1053 +        // When CSD is available we can emulate it for toplevel windows.
       
  1054 +        // Content is rendered to mContainer and transparent decorations to mShell.
       
  1055 +        if (GetCSDSupportLevel() != CSD_SUPPORT_NONE &&
       
  1056 +            mWindowType == eWindowType_toplevel) {
       
  1057 +            int32_t isCSDAvailable = false;
       
  1058 +            nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
       
  1059 +                                             &isCSDAvailable);
       
  1060 +            if (NS_SUCCEEDED(rv)) {
       
  1061 +                mIsCSDEnabled = useAlphaVisual = isCSDAvailable;
       
  1062 +            }
       
  1063 +        } else
       
  1064 +#endif
       
  1065 +        if (mWindowType == eWindowType_popup) {
       
  1066 +            useAlphaVisual = aInitData->mSupportTranslucency;
       
  1067 +        }
       
  1068  
       
  1069          // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false
       
  1070          // to allow experimentation
       
  1071          if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false))
       
  1072              useAlphaVisual = true;
       
  1073  
       
  1074 +        // An ARGB visual is only useful if we are on a compositing
       
  1075 +        // window manager.
       
  1076 +        GdkScreen *screen = gtk_widget_get_screen(mShell);
       
  1077 +        if (useAlphaVisual && !gdk_screen_is_composited(screen)) {
       
  1078 +            useAlphaVisual = false;
       
  1079 +        }
       
  1080 +
       
  1081          // We need to select an ARGB visual here instead of in
       
  1082          // SetTransparencyMode() because it has to be done before the
       
  1083 -        // widget is realized.  An ARGB visual is only useful if we
       
  1084 -        // are on a compositing window manager.
       
  1085 +        // widget is realized.
       
  1086          if (useAlphaVisual) {
       
  1087 -            GdkScreen *screen = gtk_widget_get_screen(mShell);
       
  1088 -            if (gdk_screen_is_composited(screen)) {
       
  1089  #if (MOZ_WIDGET_GTK == 2)
       
  1090 -                GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
       
  1091 -                gtk_widget_set_colormap(mShell, colormap);
       
  1092 +            GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
       
  1093 +            gtk_widget_set_colormap(mShell, colormap);
       
  1094  #else
       
  1095 -                GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
       
  1096 -                gtk_widget_set_visual(mShell, visual);
       
  1097 +            GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
       
  1098 +            gtk_widget_set_visual(mShell, visual);
       
  1099  #endif
       
  1100 -            }
       
  1101          }
       
  1102  
       
  1103          // We only move a general managed toplevel window if someone has
       
  1104 @@ -3756,24 +3861,56 @@ nsWindow::Create(nsIWidget* aParent,
       
  1105          mContainer = MOZ_CONTAINER(container);
       
  1106  
       
  1107  #if (MOZ_WIDGET_GTK == 3)
       
  1108 -        // "csd" style is set when widget is realized so we need to call
       
  1109 -        // it explicitly now.
       
  1110 -        gtk_widget_realize(mShell);
       
  1111 -
       
  1112 -        // We can't draw directly to top-level window when client side
       
  1113 -        // decorations are enabled. We use container with GdkWindow instead.
       
  1114 -        GtkStyleContext* style = gtk_widget_get_style_context(mShell);
       
  1115 -        shellHasCSD = gtk_style_context_has_class(style, "csd");
       
  1116 -#endif
       
  1117 -        if (!shellHasCSD) {
       
  1118 -            // Use mShell's window for drawing and events.
       
  1119 -            gtk_widget_set_has_window(container, FALSE);
       
  1120 -            // Prevent GtkWindow from painting a background to flicker.
       
  1121 -            gtk_widget_set_app_paintable(mShell, TRUE);
       
  1122 -        }
       
  1123 -        // Set up event widget
       
  1124 -        eventWidget = shellHasCSD ? container : mShell;
       
  1125 +        /* There are tree possible situations here:
       
  1126 +         *
       
  1127 +         * 1) We're running on Gtk+ < 3.20 without any decorations. Content
       
  1128 +         *    is rendered to mShell window and we listen Gtk+ events on mShell.
       
  1129 +         * 2) We're running on Gtk+ > 3.20 and window decorations are drawn
       
  1130 +         *    by default by Gtk+. Content is rendered to mContainer,
       
  1131 +         *    we listen events on mContainer. mShell contains default Gtk+
       
  1132 +         *    window decorations rendered by Gtk+.
       
  1133 +         * 3) We're running on Gtk+ > 3.20 and both window decorations and
       
  1134 +         *    content is rendered by gecko. We emulate Gtk+ decoration rendering
       
  1135 +         *    to mShell and we need to listen Gtk events on both mShell
       
  1136 +         *    and mContainer.
       
  1137 +         */
       
  1138 +
       
  1139 +        // When client side decorations are enabled (rendered by us or by Gtk+)
       
  1140 +        // the decoration is rendered to mShell (toplevel) window and
       
  1141 +        // we draw our content to mContainer.
       
  1142 +        if (mIsCSDEnabled) {
       
  1143 +            drawToContainer = true;
       
  1144 +        } else {
       
  1145 +            // mIsCSDEnabled can be disabled by preference so look at actual
       
  1146 +            // toplevel window style to to detect active "csd" style.
       
  1147 +            // The "csd" style is set when widget is realized so we need to call
       
  1148 +            // it explicitly now.
       
  1149 +            gtk_widget_realize(mShell);
       
  1150 +
       
  1151 +            GtkStyleContext* style = gtk_widget_get_style_context(mShell);
       
  1152 +            drawToContainer = gtk_style_context_has_class(style, "csd");
       
  1153 +        }
       
  1154 +#endif
       
  1155 +        drawWidget = (drawToContainer) ? container : mShell;
       
  1156 +        // When we draw decorations on our own we need to handle resize events
       
  1157 +        // because Gtk+ does not provide resizers for undecorated windows.
       
  1158 +        // The CSD on mShell borders act as resize handlers
       
  1159 +        // so we need to listen there.
       
  1160 +        eventWidget = (drawToContainer && !mIsCSDEnabled) ? container : mShell;
       
  1161 +
       
  1162          gtk_widget_add_events(eventWidget, kEvents);
       
  1163 +        if (eventWidget != drawWidget) {
       
  1164 +            // CSD is rendered by us (not by Gtk+) so we also need to listen
       
  1165 +            // at mShell window for events.
       
  1166 +            gtk_widget_add_events(drawWidget, kEvents);
       
  1167 +        }
       
  1168 +
       
  1169 +        // Prevent GtkWindow from painting a background to flicker.
       
  1170 +        gtk_widget_set_app_paintable(drawWidget, TRUE);
       
  1171 +
       
  1172 +        // gtk_container_add() realizes the child widget so we need to
       
  1173 +        // set it now.
       
  1174 +        gtk_widget_set_has_window(container, drawToContainer);
       
  1175  
       
  1176          gtk_container_add(GTK_CONTAINER(mShell), container);
       
  1177          gtk_widget_realize(container);
       
  1178 @@ -3783,7 +3920,7 @@ nsWindow::Create(nsIWidget* aParent,
       
  1179          gtk_widget_grab_focus(container);
       
  1180  
       
  1181          // the drawing window
       
  1182 -        mGdkWindow = gtk_widget_get_window(eventWidget);
       
  1183 +        mGdkWindow = gtk_widget_get_window(drawWidget);
       
  1184  
       
  1185          if (mWindowType == eWindowType_popup) {
       
  1186              // gdk does not automatically set the cursor for "temporary"
       
  1187 @@ -3856,6 +3993,11 @@ nsWindow::Create(nsIWidget* aParent,
       
  1188  
       
  1189      // label the drawing window with this object so we can find our way home
       
  1190      g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
       
  1191 +    if (mIsCSDEnabled) {
       
  1192 +        // label the CSD window with this object so we can find our way home
       
  1193 +        g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)),
       
  1194 +                          "nsWindow", this);
       
  1195 +    }
       
  1196  
       
  1197      if (mContainer)
       
  1198          g_object_set_data(G_OBJECT(mContainer), "nsWindow", this);
       
  1199 @@ -3893,6 +4035,10 @@ nsWindow::Create(nsIWidget* aParent,
       
  1200          g_signal_connect_after(default_settings,
       
  1201                                 "notify::gtk-font-name",
       
  1202                                 G_CALLBACK(theme_changed_cb), this);
       
  1203 +        if (mIsCSDEnabled) {
       
  1204 +            g_signal_connect(G_OBJECT(mShell), "draw",
       
  1205 +                             G_CALLBACK(expose_event_decoration_draw_cb), nullptr);
       
  1206 +        }
       
  1207      }
       
  1208  
       
  1209      if (mContainer) {
       
  1210 @@ -3943,7 +4089,7 @@ nsWindow::Create(nsIWidget* aParent,
       
  1211                           G_CALLBACK(drag_data_received_event_cb), nullptr);
       
  1212  
       
  1213          GtkWidget *widgets[] = { GTK_WIDGET(mContainer),
       
  1214 -                                 !shellHasCSD ? mShell : nullptr };
       
  1215 +                                 !drawToContainer ? mShell : nullptr };
       
  1216          for (size_t i = 0; i < ArrayLength(widgets) && widgets[i]; ++i) {
       
  1217              // Visibility events are sent to the owning widget of the relevant
       
  1218              // window but do not propagate to parent widgets so connect on
       
  1219 @@ -3973,7 +4119,6 @@ nsWindow::Create(nsIWidget* aParent,
       
  1220          // Don't let GTK mess with the shapes of our GdkWindows
       
  1221          GTK_PRIVATE_SET_FLAG(eventWidget, GTK_HAS_SHAPE_MASK);
       
  1222  #endif
       
  1223 -
       
  1224          // These events are sent to the owning widget of the relevant window
       
  1225          // and propagate up to the first widget that handles the events, so we
       
  1226          // need only connect on mShell, if it exists, to catch events on its
       
  1227 @@ -4110,6 +4255,12 @@ nsWindow::NativeResize()
       
  1228           size.width, size.height));
       
  1229  
       
  1230      if (mIsTopLevel) {
       
  1231 +        // When we draw decorations add extra space to draw shadows
       
  1232 +        // around the main window.
       
  1233 +        if (mDrawWindowDecoration) {
       
  1234 +            size.width += mDecorationSize.left + mDecorationSize.right;
       
  1235 +            size.height += mDecorationSize.top + mDecorationSize.bottom;
       
  1236 +        }
       
  1237          gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
       
  1238      }
       
  1239      else if (mContainer) {
       
  1240 @@ -4166,6 +4317,11 @@ nsWindow::NativeMoveResize()
       
  1241      if (mIsTopLevel) {
       
  1242          // x and y give the position of the window manager frame top-left.
       
  1243          gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y);
       
  1244 +
       
  1245 +        if (mDrawWindowDecoration) {
       
  1246 +            size.width += mDecorationSize.left + mDecorationSize.right;
       
  1247 +            size.height += mDecorationSize.top + mDecorationSize.bottom;
       
  1248 +        }
       
  1249          // This sets the client window size.
       
  1250          gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
       
  1251      }
       
  1252 @@ -5524,6 +5680,33 @@ expose_event_cb(GtkWidget *widget, cairo
       
  1253  
       
  1254      return FALSE;
       
  1255  }
       
  1256 +
       
  1257 +/* static */
       
  1258 +gboolean
       
  1259 +expose_event_decoration_draw_cb(GtkWidget *widget, cairo_t *cr)
       
  1260 +{
       
  1261 +  GdkWindow* gdkWindow = gtk_widget_get_window(widget);
       
  1262 +  if (gtk_cairo_should_draw_window(cr, gdkWindow)) {
       
  1263 +      RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
       
  1264 +      if (!window) {
       
  1265 +          NS_WARNING("Cannot get nsWindow from GtkWidget");
       
  1266 +      }
       
  1267 +      else if (window->IsClientDecorated()) {
       
  1268 +          cairo_save(cr);
       
  1269 +          gtk_cairo_transform_to_window(cr, widget, gdkWindow);
       
  1270 +
       
  1271 +          GdkRectangle rect = {0,0,0,0};
       
  1272 +          gtk_window_get_size(GTK_WINDOW(widget), &rect.width, &rect.height);
       
  1273 +          moz_gtk_window_decoration_paint(cr, &rect);
       
  1274 +
       
  1275 +          rect.height = 40;
       
  1276 +          moz_gtk_header_bar_paint(cr, &rect);
       
  1277 +          cairo_restore(cr);
       
  1278 +      }
       
  1279 +  }
       
  1280 +  return TRUE;
       
  1281 +}
       
  1282 +
       
  1283  #endif //MOZ_WIDGET_GTK == 2
       
  1284  
       
  1285  static gboolean
       
  1286 @@ -6576,6 +6759,28 @@ nsWindow::ClearCachedResources()
       
  1287      }
       
  1288  }
       
  1289  
       
  1290 +NS_IMETHODIMP
       
  1291 +nsWindow::SetNonClientMargins(LayoutDeviceIntMargin &aMargins)
       
  1292 +{
       
  1293 +  SetDrawsInTitlebar(aMargins.top == 0);
       
  1294 +  return NS_OK;
       
  1295 +}
       
  1296 +
       
  1297 +void
       
  1298 +nsWindow::SetDrawsInTitlebar(bool aState)
       
  1299 +{
       
  1300 +  if (!mIsCSDEnabled || aState == mDrawWindowDecoration)
       
  1301 +    return;
       
  1302 +
       
  1303 +  if (mShell) {
       
  1304 +    gtk_window_set_decorated(GTK_WINDOW(mShell), !aState);
       
  1305 +    gtk_widget_set_app_paintable(mShell, aState);
       
  1306 +  }
       
  1307 +
       
  1308 +  mDrawWindowDecoration = aState;
       
  1309 +  UpdateClientDecorations();
       
  1310 +}
       
  1311 +
       
  1312  gint
       
  1313  nsWindow::GdkScaleFactor()
       
  1314  {
       
  1315 @@ -6846,6 +7051,157 @@ nsWindow::SynthesizeNativeTouchPoint(uin
       
  1316  }
       
  1317  #endif
       
  1318  
       
  1319 +bool
       
  1320 +nsWindow::IsClientDecorated() const
       
  1321 +{
       
  1322 +    return mDrawWindowDecoration && mSizeState == nsSizeMode_Normal;
       
  1323 +}
       
  1324 +
       
  1325 +int
       
  1326 +nsWindow::GetClientResizerSize()
       
  1327 +{
       
  1328 +  if (!mShell)
       
  1329 +    return 0;
       
  1330 +
       
  1331 +  // GTK uses a default size of 20px as of 3.20.
       
  1332 +  gint size = 20;
       
  1333 +  gtk_widget_style_get(mShell, "decoration-resize-handle", &size, nullptr);
       
  1334 +
       
  1335 +  return GdkCoordToDevicePixels(size);
       
  1336 +}
       
  1337 +
       
  1338 +nsWindow::CSDSupportLevel
       
  1339 +nsWindow::GetCSDSupportLevel() {
       
  1340 +    if (mCSDSupportLevel != CSD_SUPPORT_UNKNOWN) {
       
  1341 +        return mCSDSupportLevel;
       
  1342 +    }
       
  1343 +    // TODO: MATE
       
  1344 +    const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
       
  1345 +    if (currentDesktop) {
       
  1346 +        if (strcmp(currentDesktop, "GNOME") == 0) {
       
  1347 +            mCSDSupportLevel = CSD_SUPPORT_FULL;
       
  1348 +        } else if (strcmp(currentDesktop, "XFCE") == 0) {
       
  1349 +            mCSDSupportLevel = CSD_SUPPORT_FULL;
       
  1350 +        } else if (strcmp(currentDesktop, "X-Cinnamon") == 0) {
       
  1351 +            mCSDSupportLevel = CSD_SUPPORT_FULL;
       
  1352 +        } else if (strcmp(currentDesktop, "KDE") == 0) {
       
  1353 +            mCSDSupportLevel = CSD_SUPPORT_FLAT;
       
  1354 +        } else if (strcmp(currentDesktop, "LXDE") == 0) {
       
  1355 +            mCSDSupportLevel = CSD_SUPPORT_FLAT;
       
  1356 +        } else if (strcmp(currentDesktop, "openbox") == 0) {
       
  1357 +            mCSDSupportLevel = CSD_SUPPORT_FLAT;
       
  1358 +        } else if (strcmp(currentDesktop, "i3") == 0) {
       
  1359 +            mCSDSupportLevel = CSD_SUPPORT_NONE;
       
  1360 +        } else {
       
  1361 +            mCSDSupportLevel = CSD_SUPPORT_NONE;
       
  1362 +        }
       
  1363 +    }
       
  1364 +    return mCSDSupportLevel;
       
  1365 +}
       
  1366 +
       
  1367 +void
       
  1368 +nsWindow::UpdateClientDecorations()
       
  1369 +{
       
  1370 +  // When the CSD is not fully supported by window manager (ie. WM is not
       
  1371 +  // expecting that application is going to draw window shadows) we can't
       
  1372 +  // add shadows widths to the window margin. That would lead to completely
       
  1373 +  // opaque black border of the window.
       
  1374 +  if (!mDrawWindowDecoration || GetCSDSupportLevel() != CSD_SUPPORT_FULL)
       
  1375 +      return;
       
  1376 +
       
  1377 +  gint top = 0, right = 0, bottom = 0, left = 0;
       
  1378 +  if (mSizeState == nsSizeMode_Normal) {
       
  1379 +      moz_gtk_get_window_border(&top, &right, &bottom, &left);
       
  1380 +  }
       
  1381 +
       
  1382 +  static auto sGdkWindowSetShadowWidth =
       
  1383 +     (void (*)(GdkWindow*, gint, gint, gint, gint))
       
  1384 +     dlsym(RTLD_DEFAULT, "gdk_window_set_shadow_width");
       
  1385 +  sGdkWindowSetShadowWidth(gtk_widget_get_window(mShell),
       
  1386 +                           left, right, top, bottom);
       
  1387 +
       
  1388 +  mDecorationSize.left = left;
       
  1389 +  mDecorationSize.right = right;
       
  1390 +  mDecorationSize.top = top;
       
  1391 +  mDecorationSize.bottom = bottom;
       
  1392 +
       
  1393 +  // Gtk+ doesn't like when we set mContainer margin bigger than actual
       
  1394 +  // mContainer window size. That happens when we're called early and the
       
  1395 +  // mShell/mContainer is not allocated/resized yet and has default 1x1 size.
       
  1396 +  // Just resize to some minimal value which will be changed
       
  1397 +  // by Gecko soon.
       
  1398 +  GtkAllocation allocation;
       
  1399 +  gtk_widget_get_allocation(GTK_WIDGET(mContainer), &allocation);
       
  1400 +  if (allocation.width < left + right || allocation.height < top + bottom) {
       
  1401 +      gtk_widget_get_preferred_width(GTK_WIDGET(mContainer), nullptr,
       
  1402 +                                     &allocation.width);
       
  1403 +      gtk_widget_get_preferred_height(GTK_WIDGET(mContainer), nullptr,
       
  1404 +                                      &allocation.height);
       
  1405 +      allocation.width += left + right + 1;
       
  1406 +      allocation.height += top + bottom + 1;
       
  1407 +      gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
       
  1408 +  }
       
  1409 +
       
  1410 +  gtk_widget_set_margin_left(GTK_WIDGET(mContainer), mDecorationSize.left);
       
  1411 +  gtk_widget_set_margin_right(GTK_WIDGET(mContainer), mDecorationSize.right);
       
  1412 +  gtk_widget_set_margin_top(GTK_WIDGET(mContainer), mDecorationSize.top);
       
  1413 +  gtk_widget_set_margin_bottom(GTK_WIDGET(mContainer), mDecorationSize.bottom);
       
  1414 +}
       
  1415 +
       
  1416 +void
       
  1417 +nsWindow::ApplyCSDClipping()
       
  1418 +{
       
  1419 +  if (IsClientDecorated()) {
       
  1420 +      gint top, right, bottom, left;
       
  1421 +      moz_gtk_get_header_bar_border(&top, &right, &bottom, &left);
       
  1422 +      cairo_rectangle_int_t rect = { 0, top, mBounds.width, mBounds.height};
       
  1423 +      cairo_region_t *region = cairo_region_create_rectangle(&rect);
       
  1424 +      gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
       
  1425 +      cairo_region_destroy(region);
       
  1426 +  } else {
       
  1427 +      gdk_window_shape_combine_region(mGdkWindow, nullptr, 0, 0);
       
  1428 +  }
       
  1429 +}
       
  1430 +
       
  1431 +bool
       
  1432 +nsWindow::CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge)
       
  1433 +{
       
  1434 +  gint scale = GdkScaleFactor();
       
  1435 +  gint left = scale * mDecorationSize.left;
       
  1436 +  gint top = scale * mDecorationSize.top;
       
  1437 +  gint right = scale * mDecorationSize.right;
       
  1438 +  gint bottom = scale * mDecorationSize.bottom;
       
  1439 +
       
  1440 +  int resizerSize = GetClientResizerSize();
       
  1441 +  int topDist = aPoint.y;
       
  1442 +  int leftDist = aPoint.x;
       
  1443 +  int rightDist = mBounds.width - aPoint.x;
       
  1444 +  int bottomDist = mBounds.height - aPoint.y;
       
  1445 +
       
  1446 +  //TODO -> wrong sizes
       
  1447 +
       
  1448 +  if (leftDist <= resizerSize && topDist <= resizerSize) {
       
  1449 +    aOutEdge = GDK_WINDOW_EDGE_NORTH_WEST;
       
  1450 +  } else if (rightDist <= resizerSize && topDist <= resizerSize) {
       
  1451 +    aOutEdge = GDK_WINDOW_EDGE_NORTH_EAST;
       
  1452 +  } else if (leftDist <= resizerSize && bottomDist <= resizerSize) {
       
  1453 +    aOutEdge = GDK_WINDOW_EDGE_SOUTH_WEST;
       
  1454 +  } else if (rightDist <= resizerSize && bottomDist <= resizerSize) {
       
  1455 +    aOutEdge = GDK_WINDOW_EDGE_SOUTH_EAST;
       
  1456 +  } else if (topDist <= top) {
       
  1457 +    aOutEdge = GDK_WINDOW_EDGE_NORTH;
       
  1458 +  } else if (leftDist <= left) {
       
  1459 +    aOutEdge = GDK_WINDOW_EDGE_WEST;
       
  1460 +  } else if (rightDist <= right) {
       
  1461 +    aOutEdge = GDK_WINDOW_EDGE_EAST;
       
  1462 +  } else if (bottomDist <= bottom) {
       
  1463 +    aOutEdge = GDK_WINDOW_EDGE_SOUTH;
       
  1464 +  } else {
       
  1465 +    return false;
       
  1466 +  }
       
  1467 +  return true;
       
  1468 +}
       
  1469 +
       
  1470  int32_t
       
  1471  nsWindow::RoundsWidgetCoordinatesTo()
       
  1472  {
       
  1473 diff -up firefox-57.0b8/widget/gtk/nsWindow.h.1399611 firefox-57.0b8/widget/gtk/nsWindow.h
       
  1474 --- firefox-57.0b8/widget/gtk/nsWindow.h.1399611	2017-09-15 06:15:40.000000000 +0200
       
  1475 +++ firefox-57.0b8/widget/gtk/nsWindow.h	2017-10-16 12:11:45.369240636 +0200
       
  1476 @@ -123,6 +123,7 @@ public:
       
  1477                                           double aHeight,
       
  1478                                           bool   aRepaint) override;
       
  1479      virtual bool       IsEnabled() const override;
       
  1480 +    bool               IsComposited() const;
       
  1481  
       
  1482      void               SetZIndex(int32_t aZIndex) override;
       
  1483      virtual void       SetSizeMode(nsSizeMode aMode) override;
       
  1484 @@ -351,6 +352,9 @@ public:
       
  1485  #endif
       
  1486      virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
       
  1487  
       
  1488 +    NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
       
  1489 +    void SetDrawsInTitlebar(bool aState) override;
       
  1490 +
       
  1491      // HiDPI scale conversion
       
  1492      gint GdkScaleFactor();
       
  1493  
       
  1494 @@ -367,6 +371,9 @@ public:
       
  1495      LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect);
       
  1496  
       
  1497      virtual bool WidgetTypeSupportsAcceleration() override;
       
  1498 +
       
  1499 +    // Decorations
       
  1500 +    bool IsClientDecorated() const;
       
  1501  protected:
       
  1502      virtual ~nsWindow();
       
  1503  
       
  1504 @@ -384,6 +391,16 @@ protected:
       
  1505  
       
  1506      virtual void RegisterTouchWindow() override;
       
  1507  
       
  1508 +    int GetClientResizerSize();
       
  1509 +
       
  1510 +    // Informs the window manager about the size of the shadows surrounding
       
  1511 +    // a client-side decorated window.
       
  1512 +    void UpdateClientDecorations();
       
  1513 +
       
  1514 +    // Returns true if the given point (in device pixels) is within a resizer
       
  1515 +    // region of the window. Only used when drawing decorations client side.
       
  1516 +    bool CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge);
       
  1517 +
       
  1518      nsCOMPtr<nsIWidget> mParent;
       
  1519      // Is this a toplevel window?
       
  1520      bool                mIsTopLevel;
       
  1521 @@ -432,12 +449,12 @@ private:
       
  1522                                     gint* aRootX, gint* aRootY);
       
  1523      void               ClearCachedResources();
       
  1524      nsIWidgetListener* GetListener();
       
  1525 -    bool               IsComposited() const;
       
  1526 -
       
  1527 +    void               ApplyCSDClipping();
       
  1528  
       
  1529      GtkWidget          *mShell;
       
  1530      MozContainer       *mContainer;
       
  1531      GdkWindow          *mGdkWindow;
       
  1532 +    bool                mIsCSDEnabled;
       
  1533      PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
       
  1534  
       
  1535  
       
  1536 @@ -536,6 +553,10 @@ private:
       
  1537      // leaving fullscreen
       
  1538      nsSizeMode         mLastSizeMode;
       
  1539  
       
  1540 +    // If true, draw our own window decorations (where supported).
       
  1541 +    bool              mDrawWindowDecoration;
       
  1542 +    GtkBorder         mDecorationSize;
       
  1543 +
       
  1544      static bool DragInProgress(void);
       
  1545  
       
  1546      void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent);
       
  1547 @@ -567,6 +588,17 @@ private:
       
  1548      RefPtr<mozilla::widget::IMContextWrapper> mIMContext;
       
  1549  
       
  1550      mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter;
       
  1551 +    typedef enum { CSD_SUPPORT_FULL,    // CSD including shadows
       
  1552 +                   CSD_SUPPORT_FLAT,    // CSD without shadows
       
  1553 +                   CSD_SUPPORT_NONE,    // WM does not support CSD at all
       
  1554 +                   CSD_SUPPORT_UNKNOWN
       
  1555 +    } CSDSupportLevel;
       
  1556 +    /**
       
  1557 +     * Get the support of Client Side Decoration by checking
       
  1558 +     * the XDG_CURRENT_DESKTOP environment variable.
       
  1559 +     */
       
  1560 +    CSDSupportLevel GetCSDSupportLevel();
       
  1561 +    CSDSupportLevel mCSDSupportLevel;
       
  1562  };
       
  1563  
       
  1564  #endif /* __nsWindow_h__ */
       
  1565 diff -up firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp.1399611 firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp
       
  1566 --- firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp.1399611	2017-09-15 06:15:40.000000000 +0200
       
  1567 +++ firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp	2017-10-16 12:11:45.369240636 +0200
       
  1568 @@ -26,10 +26,14 @@ static GtkStyleContext*
       
  1569  GetCssNodeStyleInternal(WidgetNodeType aNodeType);
       
  1570  
       
  1571  static GtkWidget*
       
  1572 -CreateWindowWidget()
       
  1573 +CreateWindowWidget(WidgetNodeType type)
       
  1574  {
       
  1575    GtkWidget *widget = gtk_window_new(GTK_WINDOW_POPUP);
       
  1576    gtk_widget_set_name(widget, "MozillaGtkWidget");
       
  1577 +  if (type == MOZ_GTK_WINDOW_CSD) {
       
  1578 +      GtkStyleContext* style = gtk_widget_get_style_context(widget);
       
  1579 +      gtk_style_context_add_class(style, "csd");
       
  1580 +  }
       
  1581    return widget;
       
  1582  }
       
  1583  
       
  1584 @@ -101,7 +105,7 @@ CreateTooltipWidget()
       
  1585  {
       
  1586    MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr,
       
  1587               "CreateTooltipWidget should be used for Gtk < 3.20 only.");
       
  1588 -  GtkWidget* widget = CreateWindowWidget();
       
  1589 +  GtkWidget* widget = CreateWindowWidget(MOZ_GTK_WINDOW);
       
  1590    GtkStyleContext* style = gtk_widget_get_style_context(widget);
       
  1591    gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
       
  1592    return widget;
       
  1593 @@ -529,11 +533,82 @@ CreateNotebookWidget()
       
  1594  }
       
  1595  
       
  1596  static GtkWidget*
       
  1597 +CreateHeaderBar(bool aMaximized)
       
  1598 +{
       
  1599 +  MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
       
  1600 +             "GtkHeaderBar is only available on GTK 3.10+.");
       
  1601 +  if (gtk_check_version(3, 10, 0) != nullptr)
       
  1602 +    return nullptr;
       
  1603 +
       
  1604 +  static auto sGtkHeaderBarNewPtr = (GtkWidget* (*)())
       
  1605 +    dlsym(RTLD_DEFAULT, "gtk_header_bar_new");
       
  1606 +  static const char* MOZ_GTK_STYLE_CLASS_TITLEBAR = "titlebar";
       
  1607 +
       
  1608 +  GtkWidget* headerbar = sGtkHeaderBarNewPtr();
       
  1609 +  if (aMaximized) {
       
  1610 +    GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
       
  1611 +    gtk_widget_set_name(window, "MozillaMaximizedGtkWidget");
       
  1612 +    GtkStyleContext* style = gtk_widget_get_style_context(window);
       
  1613 +    gtk_style_context_add_class(style, "maximized");
       
  1614 +    GtkWidget *fixed = gtk_fixed_new();
       
  1615 +    gtk_container_add(GTK_CONTAINER(window), fixed);
       
  1616 +    gtk_container_add(GTK_CONTAINER(fixed), headerbar);
       
  1617 +    // Save the window container so we don't leak it.
       
  1618 +    sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED] = window;
       
  1619 +  } else {
       
  1620 +    AddToWindowContainer(headerbar);
       
  1621 +  }
       
  1622 +
       
  1623 +  // Emulate what create_titlebar() at gtkwindow.c does.
       
  1624 +  GtkStyleContext* style = gtk_widget_get_style_context(headerbar);
       
  1625 +  gtk_style_context_add_class(style, MOZ_GTK_STYLE_CLASS_TITLEBAR);
       
  1626 +  gtk_style_context_add_class(style, "default-decoration");
       
  1627 +
       
  1628 +  return headerbar;
       
  1629 +}
       
  1630 +
       
  1631 +// TODO - Also return style for buttons located at Maximized toolbar.
       
  1632 +static GtkWidget*
       
  1633 +CreateHeaderBarButton(WidgetNodeType aWidgetType)
       
  1634 +{
       
  1635 +  MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
       
  1636 +             "GtkHeaderBar is only available on GTK 3.10+.");
       
  1637 +
       
  1638 +  if (gtk_check_version(3, 10, 0) != nullptr)
       
  1639 +    return nullptr;
       
  1640 +
       
  1641 +  static const char* MOZ_GTK_STYLE_CLASS_TITLEBUTTON = "titlebutton";
       
  1642 +
       
  1643 +  GtkWidget* widget = gtk_button_new();
       
  1644 +  gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_HEADER_BAR)), widget);
       
  1645 +
       
  1646 +  GtkStyleContext* style = gtk_widget_get_style_context(widget);
       
  1647 +  gtk_style_context_add_class(style, MOZ_GTK_STYLE_CLASS_TITLEBUTTON);
       
  1648 +
       
  1649 +  switch (aWidgetType) {
       
  1650 +    case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
       
  1651 +      gtk_style_context_add_class(style, "close");
       
  1652 +      break;
       
  1653 +    case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
       
  1654 +      gtk_style_context_add_class(style, "minimize");
       
  1655 +      break;
       
  1656 +    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
       
  1657 +      gtk_style_context_add_class(style, "maximize");
       
  1658 +      break;
       
  1659 +    default:
       
  1660 +      break;
       
  1661 +  }
       
  1662 +
       
  1663 +  return widget;
       
  1664 +}
       
  1665 +
       
  1666 +static GtkWidget*
       
  1667  CreateWidget(WidgetNodeType aWidgetType)
       
  1668  {
       
  1669    switch (aWidgetType) {
       
  1670      case MOZ_GTK_WINDOW:
       
  1671 -      return CreateWindowWidget();
       
  1672 +    case MOZ_GTK_WINDOW_CSD:
       
  1673 +      return CreateWindowWidget(aWidgetType);
       
  1674      case MOZ_GTK_WINDOW_CONTAINER:
       
  1675        return CreateWindowContainerWidget();
       
  1676      case MOZ_GTK_CHECKBUTTON_CONTAINER:
       
  1677 @@ -610,6 +685,13 @@ CreateWidget(WidgetNodeType aWidgetType)
       
  1678        return CreateComboBoxEntryButtonWidget();
       
  1679      case MOZ_GTK_COMBOBOX_ENTRY_ARROW:
       
  1680        return CreateComboBoxEntryArrowWidget();
       
  1681 +    case MOZ_GTK_HEADER_BAR:
       
  1682 +    case MOZ_GTK_HEADER_BAR_MAXIMIZED:
       
  1683 +      return CreateHeaderBar(aWidgetType == MOZ_GTK_HEADER_BAR_MAXIMIZED);
       
  1684 +    case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
       
  1685 +    case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
       
  1686 +    case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
       
  1687 +      return CreateHeaderBarButton(aWidgetType);
       
  1688      default:
       
  1689        /* Not implemented */
       
  1690        return nullptr;
       
  1691 @@ -1049,6 +1131,10 @@ GetCssNodeStyleInternal(WidgetNodeType a
       
  1692        GtkWidget* widget = GetWidget(MOZ_GTK_NOTEBOOK);
       
  1693        return gtk_widget_get_style_context(widget);
       
  1694      }
       
  1695 +    case MOZ_GTK_WINDOW_DECORATION:
       
  1696 +      style = CreateChildCSSNode("decoration",
       
  1697 +                                 MOZ_GTK_WINDOW_CSD);
       
  1698 +      break;
       
  1699      default:
       
  1700        return GetWidgetRootStyle(aNodeType);
       
  1701    }
       
  1702 @@ -1214,6 +1300,8 @@ ResetWidgetCache(void)
       
  1703    /* This will destroy all of our widgets */
       
  1704    if (sWidgetStorage[MOZ_GTK_WINDOW])
       
  1705      gtk_widget_destroy(sWidgetStorage[MOZ_GTK_WINDOW]);
       
  1706 +  if (sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED])
       
  1707 +    gtk_widget_destroy(sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED]);
       
  1708  
       
  1709    /* Clear already freed arrays */
       
  1710    mozilla::PodArrayZero(sWidgetStorage);
       
  1711 diff -up firefox-57.0b8/widget/LookAndFeel.h.1399611 firefox-57.0b8/widget/LookAndFeel.h
       
  1712 --- firefox-57.0b8/widget/LookAndFeel.h.1399611	2017-09-16 18:22:54.000000000 +0200
       
  1713 +++ firefox-57.0b8/widget/LookAndFeel.h	2017-10-16 12:11:45.369240636 +0200
       
  1714 @@ -405,6 +405,30 @@ public:
       
  1715       eIntID_PhysicalHomeButton,
       
  1716  
       
  1717       /*
       
  1718 +      * A boolean value indicating whether client-side decorations are
       
  1719 +      * supported by the user's GTK version.
       
  1720 +      */
       
  1721 +     eIntID_GTKCSDAvailable,
       
  1722 +
       
  1723 +     /*
       
  1724 +      * A boolean value indicating whether client-side decorations should
       
  1725 +      * contain a minimize button.
       
  1726 +      */
       
  1727 +     eIntID_GTKCSDMinimizeButton,
       
  1728 +
       
  1729 +     /*
       
  1730 +      * A boolean value indicating whether client-side decorations should
       
  1731 +      * contain a maximize button.
       
  1732 +      */
       
  1733 +     eIntID_GTKCSDMaximizeButton,
       
  1734 +
       
  1735 +     /*
       
  1736 +      * A boolean value indicating whether client-side decorations should
       
  1737 +      * contain a close button.
       
  1738 +      */
       
  1739 +     eIntID_GTKCSDCloseButton,
       
  1740 +
       
  1741 +     /*
       
  1742        * Controls whether overlay scrollbars display when the user moves
       
  1743        * the mouse in a scrollable frame.
       
  1744        */