mozilla-enable-csd.patch
author Wolfgang Rosenauer <wr@rosenauer.org>
Wed, 24 Jan 2018 17:02:23 +0100
branchfirefox58
changeset 1027 7071f6ebfda6
parent 1024 d14085eee2b2
permissions -rw-r--r--
CSD functionality

diff -up firefox-58.0/browser/base/moz.build.1399611 firefox-58.0/browser/base/moz.build
--- firefox-58.0/browser/base/moz.build.1399611	2017-11-02 17:16:30.000000000 +0100
+++ firefox-58.0/browser/base/moz.build	2018-01-24 10:57:03.717031953 +0100
@@ -57,7 +57,7 @@ DEFINES['APP_LICENSE_BLOCK'] = '%s/conte
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
     DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
     DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
diff -up firefox-58.0/browser/themes/linux/browser.css.1399611 firefox-58.0/browser/themes/linux/browser.css
--- firefox-58.0/browser/themes/linux/browser.css.1399611	2018-01-11 21:16:54.000000000 +0100
+++ firefox-58.0/browser/themes/linux/browser.css	2018-01-24 10:57:03.718031950 +0100
@@ -717,7 +717,7 @@ html|span.ac-emphasize-text-url {
   :root[tabsintitlebar] > #titlebar:-moz-lwtheme {
     visibility: hidden;
   }
-  :root[tabsintitlebar] > #titlebar-content:-moz-lwtheme {
+  :root[tabsintitlebar] #titlebar-content:-moz-lwtheme {
     visibility: visible;
   }
 
diff -up firefox-58.0/layout/style/nsMediaFeatures.cpp.1399611 firefox-58.0/layout/style/nsMediaFeatures.cpp
--- firefox-58.0/layout/style/nsMediaFeatures.cpp.1399611	2018-01-11 21:17:01.000000000 +0100
+++ firefox-58.0/layout/style/nsMediaFeatures.cpp	2018-01-24 10:57:03.718031950 +0100
@@ -831,6 +831,42 @@ nsMediaFeatures::features[] = {
     GetSystemMetric
   },
 
+  {
+    &nsGkAtoms::_moz_gtk_csd_available,
+    nsMediaFeature::eMinMaxNotAllowed,
+    nsMediaFeature::eBoolInteger,
+    nsMediaFeature::eNoRequirements,
+    { &nsGkAtoms::gtk_csd_available },
+    GetSystemMetric
+  },
+
+  {
+    &nsGkAtoms::_moz_gtk_csd_minimize_button,
+    nsMediaFeature::eMinMaxNotAllowed,
+    nsMediaFeature::eBoolInteger,
+    nsMediaFeature::eNoRequirements,
+    { &nsGkAtoms::gtk_csd_minimize_button },
+    GetSystemMetric
+  },
+
+  {
+    &nsGkAtoms::_moz_gtk_csd_maximize_button,
+    nsMediaFeature::eMinMaxNotAllowed,
+    nsMediaFeature::eBoolInteger,
+    nsMediaFeature::eNoRequirements,
+    { &nsGkAtoms::gtk_csd_maximize_button },
+    GetSystemMetric
+  },
+
+  {
+    &nsGkAtoms::_moz_gtk_csd_close_button,
+    nsMediaFeature::eMinMaxNotAllowed,
+    nsMediaFeature::eBoolInteger,
+    nsMediaFeature::eNoRequirements,
+    { &nsGkAtoms::gtk_csd_close_button },
+    GetSystemMetric
+  },
+
   // Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
   // Internal because it is really only useful in the user agent anyway
   //  and therefore not worth standardizing.
diff -up firefox-58.0/toolkit/modules/moz.build.1399611 firefox-58.0/toolkit/modules/moz.build
--- firefox-58.0/toolkit/modules/moz.build.1399611	2018-01-11 21:17:05.000000000 +0100
+++ firefox-58.0/toolkit/modules/moz.build	2018-01-24 10:57:03.718031950 +0100
@@ -259,7 +259,7 @@ EXTRA_JS_MODULES.sessionstore += [
 ]
 
 DEFINES['INSTALL_COMPACT_THEMES'] = 1
-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
     DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
diff -up firefox-58.0/widget/gtk/mozgtk/mozgtk.c.1399611 firefox-58.0/widget/gtk/mozgtk/mozgtk.c
--- firefox-58.0/widget/gtk/mozgtk/mozgtk.c.1399611	2018-01-11 21:17:06.000000000 +0100
+++ firefox-58.0/widget/gtk/mozgtk/mozgtk.c	2018-01-24 10:11:58.638648276 +0100
@@ -391,6 +391,7 @@ STUB(gtk_separator_menu_item_new)
 STUB(gtk_separator_tool_item_new)
 STUB(gtk_settings_get_default)
 STUB(gtk_settings_get_for_screen)
+STUB(gtk_show_uri)
 STUB(gtk_socket_add_id)
 STUB(gtk_socket_get_id)
 STUB(gtk_socket_get_type)
@@ -407,6 +408,7 @@ STUB(gtk_target_list_add_image_targets)
 STUB(gtk_target_list_new)
 STUB(gtk_target_list_unref)
 STUB(gtk_targets_include_image)
+STUB(gtk_targets_include_text)
 STUB(gtk_target_table_free)
 STUB(gtk_target_table_new_from_list)
 STUB(gtk_text_view_new)
@@ -479,6 +481,7 @@ STUB(gtk_widget_show_all)
 STUB(gtk_widget_size_allocate)
 STUB(gtk_widget_style_get)
 STUB(gtk_widget_unparent)
+STUB(gtk_widget_unrealize)
 STUB(gtk_window_deiconify)
 STUB(gtk_window_fullscreen)
 STUB(gtk_window_get_group)
@@ -582,6 +585,8 @@ STUB(gtk_style_context_set_state)
 STUB(gtk_style_properties_lookup_property)
 STUB(gtk_tree_view_column_get_button)
 STUB(gtk_widget_get_preferred_size)
+STUB(gtk_widget_get_preferred_width)
+STUB(gtk_widget_get_preferred_height)
 STUB(gtk_widget_get_state_flags)
 STUB(gtk_widget_get_style_context)
 STUB(gtk_widget_path_append_type)
diff -up firefox-58.0/widget/gtk/nsLookAndFeel.cpp.1399611 firefox-58.0/widget/gtk/nsLookAndFeel.cpp
--- firefox-58.0/widget/gtk/nsLookAndFeel.cpp.1399611	2018-01-11 21:17:06.000000000 +0100
+++ firefox-58.0/widget/gtk/nsLookAndFeel.cpp	2018-01-24 10:57:03.718031950 +0100
@@ -24,6 +24,7 @@
 #include "nsStyleConsts.h"
 #include "gfxFontConstants.h"
 #include "WidgetUtils.h"
+#include "nsWindow.h"
 
 #include <dlfcn.h>
 
@@ -740,7 +741,7 @@ GetSystemFontInfo(GtkStyleContext *aStyl
     // Scale fonts up on HiDPI displays.
     // This would be done automatically with cairo, but we manually manage
     // the display scale for platform consistency.
-    size *= ScreenHelperGTK::GetGTKMonitorScaleFactor();
+    size *= mozilla::widget::ScreenHelperGTK::GetGTKMonitorScaleFactor();
 
     // |size| is now pixels
 
@@ -1076,17 +1077,13 @@ nsLookAndFeel::EnsureInit()
     gtk_widget_destroy(window);
     g_object_unref(labelWidget);
 
-    // Require GTK 3.20 for client-side decoration support.
-    mCSDAvailable = gtk_check_version(3, 20, 0) == nullptr;
-    if (mCSDAvailable) {
-        mCSDAvailable =
-            mozilla::Preferences::GetBool("widget.allow-client-side-decoration",
-                                          false);
-    }
+    // Require GTK 3.10 for GtkHeaderBar support and compatible window manager.
+    mCSDAvailable = (gtk_check_version(3, 10, 0) == nullptr &&
+        nsWindow::GetCSDSupportLevel() != nsWindow::CSD_SUPPORT_NONE);
 
     // We need to initialize whole CSD config explicitly because it's queried
     // as -moz-gtk* media features.
-    mCSDCloseButton = false;
+    mCSDCloseButton = true;
     mCSDMaximizeButton = false;
     mCSDMinimizeButton = false;
 
@@ -1095,18 +1092,24 @@ nsLookAndFeel::EnsureInit()
           (const gchar* (*)(GtkWidget*))
           dlsym(RTLD_DEFAULT, "gtk_header_bar_get_decoration_layout");
 
-        GtkWidget* headerBar = GetWidget(MOZ_GTK_HEADER_BAR);
-        const gchar* decorationLayout =
-            sGtkHeaderBarGetDecorationLayoutPtr(headerBar);
-        if (!decorationLayout) {
-            g_object_get(settings, "gtk-decoration-layout", &decorationLayout,
-                         nullptr);
-        }
+        if (sGtkHeaderBarGetDecorationLayoutPtr) {
+            GtkWidget* headerBar = GetWidget(MOZ_GTK_HEADER_BAR);
+            const gchar* decorationLayout =
+                sGtkHeaderBarGetDecorationLayoutPtr(headerBar);
+            if (!decorationLayout) {
+                g_object_get(settings, "gtk-decoration-layout",
+                             &decorationLayout,
+                             nullptr);
+            }
 
-        if (decorationLayout) {
-            mCSDCloseButton = (strstr(decorationLayout, "close") != nullptr);
-            mCSDMaximizeButton = (strstr(decorationLayout, "maximize") != nullptr);
-            mCSDMinimizeButton = (strstr(decorationLayout, "minimize") != nullptr);
+            if (decorationLayout) {
+                mCSDCloseButton =
+                    (strstr(decorationLayout, "close") != nullptr);
+                mCSDMaximizeButton =
+                    (strstr(decorationLayout, "maximize") != nullptr);
+                mCSDMinimizeButton =
+                    (strstr(decorationLayout, "minimize") != nullptr);
+            }
         }
     }
 }
diff -up firefox-58.0/widget/gtk/nsNativeThemeGTK.cpp.1399611 firefox-58.0/widget/gtk/nsNativeThemeGTK.cpp
--- firefox-58.0/widget/gtk/nsNativeThemeGTK.cpp.1399611	2018-01-11 21:17:06.000000000 +0100
+++ firefox-58.0/widget/gtk/nsNativeThemeGTK.cpp	2018-01-24 10:57:03.719031946 +0100
@@ -29,6 +29,7 @@
 
 #include <gdk/gdkprivate.h>
 #include <gtk/gtk.h>
+#include <gtk/gtkx.h>
 
 #include "gfxContext.h"
 #include "gfxPlatformGtk.h"
@@ -51,6 +52,7 @@
 
 using namespace mozilla;
 using namespace mozilla::gfx;
+using namespace mozilla::widget;
 
 NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeGTK, nsNativeTheme, nsITheme,
                                                              nsIObserver)
@@ -1375,6 +1377,10 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev
   switch (aWidgetType) {
     case NS_THEME_BUTTON_FOCUS:
     case NS_THEME_TOOLBARBUTTON:
+    case NS_THEME_WINDOW_BUTTON_CLOSE:
+    case NS_THEME_WINDOW_BUTTON_MINIMIZE:
+    case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
+    case NS_THEME_WINDOW_BUTTON_RESTORE:
     case NS_THEME_DUALBUTTON:
     case NS_THEME_TAB_SCROLL_ARROW_BACK:
     case NS_THEME_TAB_SCROLL_ARROW_FORWARD:
diff -up firefox-58.0/widget/gtk/nsWindow.cpp.1399611 firefox-58.0/widget/gtk/nsWindow.cpp
--- firefox-58.0/widget/gtk/nsWindow.cpp.1399611	2018-01-24 10:57:03.714031963 +0100
+++ firefox-58.0/widget/gtk/nsWindow.cpp	2018-01-24 10:57:03.720031943 +0100
@@ -178,13 +178,8 @@ static int    is_parent_ungrab_enter(Gdk
 static int    is_parent_grab_leave(GdkEventCrossing *aEvent);
 
 /* callbacks from widgets */
-#if (MOZ_WIDGET_GTK == 2)
-static gboolean expose_event_cb           (GtkWidget *widget,
-                                           GdkEventExpose *event);
-#else
 static gboolean expose_event_cb           (GtkWidget *widget,
                                            cairo_t *rect);
-#endif
 static gboolean configure_event_cb        (GtkWidget *widget,
                                            GdkEventConfigure *event);
 static void     container_unrealize_cb    (GtkWidget *widget);
@@ -230,11 +225,9 @@ static void     screen_composited_change
 static void     widget_composited_changed_cb     (GtkWidget* widget,
                                                   gpointer user_data);
 
-#if (MOZ_WIDGET_GTK == 3)
 static void     scale_changed_cb          (GtkWidget* widget,
                                            GParamSpec* aPSpec,
                                            gpointer aPointer);
-#endif
 #if GTK_CHECK_VERSION(3,4,0)
 static gboolean touch_event_cb            (GtkWidget* aWidget,
                                            GdkEventTouch* aEvent);
@@ -390,7 +383,7 @@ static guint gButtonState;
 static inline int32_t
 GetBitmapStride(int32_t width)
 {
-#if defined(MOZ_X11) || (MOZ_WIDGET_GTK == 2)
+#if defined(MOZ_X11)
   return (width+7)/8;
 #else
   return cairo_format_stride_for_width(CAIRO_FORMAT_A1, width);
@@ -458,11 +451,23 @@ nsWindow::nsWindow()
     mXVisual  = nullptr;
     mXDepth   = 0;
 #endif /* MOZ_X11 */
+
     if (!gGlobalsInitialized) {
         gGlobalsInitialized = true;
 
         // It's OK if either of these fail, but it may not be one day.
         initialize_prefs();
+
+#ifdef MOZ_WAYLAND
+        // Wayland provides clipboard data to application on focus-in event
+        // so we need to init our clipboard hooks before we create window
+        // and get focus.
+        if (!mIsX11Display) {
+            nsCOMPtr<nsIClipboard> clipboard =
+                do_GetService("@mozilla.org/widget/clipboard;1");
+            NS_ASSERTION(clipboard, "Failed to init clipboard!");
+        }
+#endif
     }
 
     mLastMotionPressure = 0;
@@ -1521,7 +1526,7 @@ nsWindow::UpdateClientOffset()
 {
     AUTO_PROFILER_LABEL("nsWindow::UpdateClientOffset", GRAPHICS);
 
-    if (!mIsTopLevel || !mShell || !mGdkWindow || !mIsX11Display ||
+    if (!mIsTopLevel || !mShell || !mIsX11Display ||
         gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP) {
         mClientOffset = nsIntPoint(0, 0);
         return;
@@ -1534,7 +1539,7 @@ nsWindow::UpdateClientOffset()
     int length_returned;
     long *frame_extents;
 
-    if (!gdk_property_get(mGdkWindow,
+    if (!gdk_property_get(gtk_widget_get_window(mShell),
                           gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
                           cardinal_atom,
                           0, // offset
@@ -1710,16 +1715,22 @@ nsWindow::GetNativeData(uint32_t aDataTy
 #ifdef MOZ_X11
         GdkDisplay* gdkDisplay = gdk_display_get_default();
         if (GDK_IS_X11_DISPLAY(gdkDisplay)) {
-          return GDK_DISPLAY_XDISPLAY(gdkDisplay);
+            return GDK_DISPLAY_XDISPLAY(gdkDisplay);
         }
 #endif /* MOZ_X11 */
+        // Don't bother to return native display on Wayland as it's for
+        // X11 only NPAPI plugins.
         return nullptr;
     }
     case NS_NATIVE_SHELLWIDGET:
         return GetToplevelWidget();
 
     case NS_NATIVE_SHAREABLE_WINDOW:
-        return (void *) GDK_WINDOW_XID(gdk_window_get_toplevel(mGdkWindow));
+        if (mIsX11Display) {
+            return (void *) GDK_WINDOW_XID(gdk_window_get_toplevel(mGdkWindow));
+        }
+        NS_WARNING("nsWindow::GetNativeData(): NS_NATIVE_SHAREABLE_WINDOW is not handled on Wayland!");
+        return nullptr;
     case NS_RAW_NATIVE_IME_CONTEXT: {
         void* pseudoIMEContext = GetPseudoIMEContext();
         if (pseudoIMEContext) {
@@ -1800,18 +1811,18 @@ nsWindow::SetIcon(const nsAString& aIcon
         // The last two entries (for the old XPM format) will be ignored unless
         // no icons are found using other suffixes. XPM icons are deprecated.
 
-        const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
-                                    ".xpm", "16.xpm" };
+        const char16_t extensions[9][8] = { u".png", u"16.png", u"32.png",
+                                            u"48.png", u"64.png", u"128.png",
+                                            u"256.png",
+                                            u".xpm", u"16.xpm" };
 
         for (uint32_t i = 0; i < ArrayLength(extensions); i++) {
             // Don't bother looking for XPM versions if we found a PNG.
             if (i == ArrayLength(extensions) - 2 && foundIcon)
                 break;
 
-            nsAutoString extension;
-            extension.AppendASCII(extensions[i]);
-
-            ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
+            ResolveIconName(aIconSpec, nsDependentString(extensions[i]),
+                            getter_AddRefs(iconFile));
             if (iconFile) {
                 iconFile->GetNativePath(path);
                 GdkPixbuf *icon = gdk_pixbuf_new_from_file(path.get(), nullptr);
@@ -2024,30 +2035,6 @@ gdk_window_flash(GdkWindow *    aGdkWind
 #endif // DEBUG
 #endif
 
-#if (MOZ_WIDGET_GTK == 2)
-static bool
-ExtractExposeRegion(LayoutDeviceIntRegion& aRegion, GdkEventExpose* aEvent)
-{
-  GdkRectangle* rects;
-  gint nrects;
-  gdk_region_get_rectangles(aEvent->region, &rects, &nrects);
-
-  if (nrects > MAX_RECTS_IN_REGION) {
-      // Just use the bounding box
-      rects[0] = aEvent->area;
-      nrects = 1;
-  }
-
-  for (GdkRectangle* r = rects; r < rects + nrects; r++) {
-      aRegion.Or(aRegion, LayoutDeviceIntRect(r->x, r->y, r->width, r->height));
-      LOGDRAW(("\t%d %d %d %d\n", r->x, r->y, r->width, r->height));
-  }
-
-  g_free(rects);
-  return true;
-}
-
-#else
 # ifdef cairo_copy_clip_rectangle_list
 #  error "Looks like we're including Mozilla's cairo instead of system cairo"
 # endif
@@ -2069,15 +2056,9 @@ ExtractExposeRegion(LayoutDeviceIntRegio
   cairo_rectangle_list_destroy(rects);
   return true;
 }
-#endif
 
-#if (MOZ_WIDGET_GTK == 2)
-gboolean
-nsWindow::OnExposeEvent(GdkEventExpose *aEvent)
-#else
 gboolean
 nsWindow::OnExposeEvent(cairo_t *cr)
-#endif
 {
     // Send any pending resize events so that layout can update.
     // May run event loop.
@@ -2096,11 +2077,7 @@ nsWindow::OnExposeEvent(cairo_t *cr)
         return FALSE;
 
     LayoutDeviceIntRegion exposeRegion;
-#if (MOZ_WIDGET_GTK == 2)
-    if (!ExtractExposeRegion(exposeRegion, aEvent)) {
-#else
     if (!ExtractExposeRegion(exposeRegion, cr)) {
-#endif
         return FALSE;
     }
 
@@ -2141,7 +2118,7 @@ nsWindow::OnExposeEvent(cairo_t *cr)
 
     LOGDRAW(("sending expose event [%p] %p 0x%lx (rects follow):\n",
              (void *)this, (void *)mGdkWindow,
-             gdk_x11_window_get_xid(mGdkWindow)));
+             mIsX11Display ? gdk_x11_window_get_xid(mGdkWindow) : 0));
 
     // Our bounds may have changed after calling WillPaintWindow.  Clip
     // to the new bounds here.  The region is relative to this
@@ -2304,19 +2281,11 @@ nsWindow::OnExposeEvent(cairo_t *cr)
     listener->DidPaintWindow();
 
     // Synchronously flush any new dirty areas
-#if (MOZ_WIDGET_GTK == 2)
-    GdkRegion* dirtyArea = gdk_window_get_update_area(mGdkWindow);
-#else
     cairo_region_t* dirtyArea = gdk_window_get_update_area(mGdkWindow);
-#endif
 
     if (dirtyArea) {
         gdk_window_invalidate_region(mGdkWindow, dirtyArea, false);
-#if (MOZ_WIDGET_GTK == 2)
-        gdk_region_destroy(dirtyArea);
-#else
         cairo_region_destroy(dirtyArea);
-#endif
         gdk_window_process_updates(mGdkWindow, false);
     }
 
@@ -2466,7 +2435,7 @@ nsWindow::OnSizeAllocate(GtkAllocation *
     mBounds.SizeTo(size);
 
 #ifdef MOZ_X11
-    // Notify the X11CompositorWidget of a ClientSizeChange
+    // Notify the GtkCompositorWidget of a ClientSizeChange
     if (mCompositorWidgetDelegate) {
       mCompositorWidgetDelegate->NotifyClientSizeChanged(GetClientSize());
     }
@@ -3550,21 +3519,9 @@ CreateGdkWindow(GdkWindow *parent, GtkWi
     attributes.visual = gtk_widget_get_visual(widget);
     attributes.window_type = GDK_WINDOW_CHILD;
 
-#if (MOZ_WIDGET_GTK == 2)
-    attributes_mask |= GDK_WA_COLORMAP;
-    attributes.colormap = gtk_widget_get_colormap(widget);
-#endif
-
     GdkWindow *window = gdk_window_new(parent, &attributes, attributes_mask);
     gdk_window_set_user_data(window, widget);
 
-// GTK3 TODO?
-#if (MOZ_WIDGET_GTK == 2)
-    /* set the default pixmap to None so that you don't end up with the
-       gtk default which is BlackPixel. */
-    gdk_window_set_back_pixmap(window, nullptr, FALSE);
-#endif
-
     return window;
 }
 
@@ -3653,10 +3610,14 @@ nsWindow::Create(nsIWidget* aParent,
         // which will use a Window with the override-redirect attribute
         // (for temporary windows).
         // For long-lived windows, their stacking order is managed by the
-        // window manager, as indicated by GTK_WINDOW_TOPLEVEL ...
-        GtkWindowType type =
-            mWindowType != eWindowType_popup || aInitData->mNoAutoHide ?
-              GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
+        // window manager, as indicated by GTK_WINDOW_TOPLEVEL.
+        // For Wayland we have to always use GTK_WINDOW_POPUP to control
+        // popup window position.
+        GtkWindowType type = GTK_WINDOW_TOPLEVEL;
+        if (mWindowType == eWindowType_popup) {
+            type = (mIsX11Display && aInitData->mNoAutoHide) ?
+                GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
+        }
         mShell = gtk_window_new(type);
 
         bool useAlphaVisual = (mWindowType == eWindowType_popup &&
@@ -3674,13 +3635,8 @@ nsWindow::Create(nsIWidget* aParent,
         if (useAlphaVisual) {
             GdkScreen *screen = gtk_widget_get_screen(mShell);
             if (gdk_screen_is_composited(screen)) {
-#if (MOZ_WIDGET_GTK == 2)
-                GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
-                gtk_widget_set_colormap(mShell, colormap);
-#else
                 GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
                 gtk_widget_set_visual(mShell, visual);
-#endif
             }
         }
 
@@ -3728,9 +3684,11 @@ nsWindow::Create(nsIWidget* aParent,
 #ifdef MOZ_X11
                 // ... but when the window manager offers focus through
                 // WM_TAKE_FOCUS, focus is requested on the parent window.
-                gtk_widget_realize(mShell);
-                gdk_window_add_filter(gtk_widget_get_window(mShell),
-                                      popup_take_focus_filter, nullptr);
+                if (mIsX11Display) {
+                    gtk_widget_realize(mShell);
+                    gdk_window_add_filter(gtk_widget_get_window(mShell),
+                                          popup_take_focus_filter, nullptr);
+                }
 #endif
             }
 
@@ -3742,7 +3700,11 @@ nsWindow::Create(nsIWidget* aParent,
             else {
                 switch (aInitData->mPopupHint) {
                     case ePopupTypeMenu:
-                        gtkTypeHint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
+                        // Use GDK_WINDOW_TYPE_HINT_UTILITY on Wayland which
+                        // guides Gtk to create the popup as subsurface
+                        // instead of xdg_shell popup (see Bug 1423598).
+                        gtkTypeHint = mIsX11Display ? GDK_WINDOW_TYPE_HINT_POPUP_MENU :
+                                                      GDK_WINDOW_TYPE_HINT_UTILITY;
                         break;
                     case ePopupTypeTooltip:
                         gtkTypeHint = GDK_WINDOW_TYPE_HINT_TOOLTIP;
@@ -3769,13 +3731,11 @@ nsWindow::Create(nsIWidget* aParent,
             gtk_window_group_add_window(group, GTK_WINDOW(mShell));
             g_object_unref(group);
 
-            if (GetCSDSupportLevel() != CSD_SUPPORT_NONE) {
-                int32_t isCSDAvailable = false;
-                nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
-                                                &isCSDAvailable);
-                if (NS_SUCCEEDED(rv)) {
-                   mIsCSDAvailable = isCSDAvailable;
-                }
+            int32_t isCSDAvailable = false;
+            nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
+                                              &isCSDAvailable);
+            if (NS_SUCCEEDED(rv)) {
+               mIsCSDAvailable = isCSDAvailable;
             }
         }
 
@@ -3783,7 +3743,6 @@ nsWindow::Create(nsIWidget* aParent,
         GtkWidget *container = moz_container_new();
         mContainer = MOZ_CONTAINER(container);
 
-#if (MOZ_WIDGET_GTK == 3)
         // "csd" style is set when widget is realized so we need to call
         // it explicitly now.
         gtk_widget_realize(mShell);
@@ -3793,16 +3752,22 @@ nsWindow::Create(nsIWidget* aParent,
          * 1) We're running on Gtk+ without client side decorations.
          *    Content is rendered to mShell window and we listen
          *    to the Gtk+ events on mShell
-         * 2) We're running on Gtk+ > 3.20 and client side decorations
+         * 2) We're running on Gtk+ and client side decorations
          *    are drawn by Gtk+ to mShell. Content is rendered to mContainer
          *    and we listen to the Gtk+ events on mContainer.
+         * 3) We're running on Wayland. All gecko content is rendered
+         *    to mContainer and we listen to the Gtk+ events on mContainer.
          */
         GtkStyleContext* style = gtk_widget_get_style_context(mShell);
-        drawToContainer = gtk_style_context_has_class(style, "csd");
-#endif
+        drawToContainer =
+            !mIsX11Display ||
+            (mIsCSDAvailable && GetCSDSupportLevel() == CSD_SUPPORT_FLAT ) ||
+            gtk_style_context_has_class(style, "csd");
         eventWidget = (drawToContainer) ? container : mShell;
 
         gtk_widget_add_events(eventWidget, kEvents);
+        if (drawToContainer)
+            gtk_widget_add_events(mShell, GDK_PROPERTY_CHANGE_MASK);
 
         // Prevent GtkWindow from painting a background to avoid flickering.
         gtk_widget_set_app_paintable(eventWidget, TRUE);
@@ -3839,19 +3804,11 @@ nsWindow::Create(nsIWidget* aParent,
 
             // If the popup ignores mouse events, set an empty input shape.
             if (aInitData->mMouseTransparent) {
-#if (MOZ_WIDGET_GTK == 2)
-              GdkRectangle rect = { 0, 0, 0, 0 };
-              GdkRegion *region = gdk_region_rectangle(&rect);
-
-              gdk_window_input_shape_combine_region(mGdkWindow, region, 0, 0);
-              gdk_region_destroy(region);
-#else
               cairo_rectangle_int_t rect = { 0, 0, 0, 0 };
               cairo_region_t *region = cairo_region_create_rectangle(&rect);
 
               gdk_window_input_shape_combine_region(mGdkWindow, region, 0, 0);
               cairo_region_destroy(region);
-#endif
             }
         }
     }
@@ -3893,6 +3850,12 @@ nsWindow::Create(nsIWidget* aParent,
 
     // label the drawing window with this object so we can find our way home
     g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
+    if (drawToContainer) {
+        // Also label mShell toplevel window,
+        // property_notify_event_cb callback also needs to find its way home
+        g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)),
+                          "nsWindow", this);
+    }
 
     if (mContainer)
         g_object_set_data(G_OBJECT(mContainer), "nsWindow", this);
@@ -3910,12 +3873,12 @@ nsWindow::Create(nsIWidget* aParent,
                          G_CALLBACK(window_state_event_cb), nullptr);
         g_signal_connect(mShell, "check-resize",
                          G_CALLBACK(check_resize_cb), nullptr);
-
-        GdkScreen *screen = gtk_widget_get_screen(mShell);
-
         g_signal_connect(mShell, "composited-changed",
                          G_CALLBACK(widget_composited_changed_cb), nullptr);
+        g_signal_connect(mShell, "property-notify-event",
+                         G_CALLBACK(property_notify_event_cb), nullptr);
 
+        GdkScreen *screen = gtk_widget_get_screen(mShell);
         if (!g_signal_handler_find(screen, G_SIGNAL_MATCH_FUNC,
                                    0, 0, nullptr,
                                    FuncToGpointer(screen_composited_changed_cb), 0)) {
@@ -3940,21 +3903,14 @@ nsWindow::Create(nsIWidget* aParent,
                                G_CALLBACK(size_allocate_cb), nullptr);
         g_signal_connect(mContainer, "hierarchy-changed",
                          G_CALLBACK(hierarchy_changed_cb), nullptr);
-#if (MOZ_WIDGET_GTK == 3)
         g_signal_connect(mContainer, "notify::scale-factor",
                          G_CALLBACK(scale_changed_cb), nullptr);
-#endif
         // Initialize mHasMappedToplevel.
         hierarchy_changed_cb(GTK_WIDGET(mContainer), nullptr);
         // Expose, focus, key, and drag events are sent even to GTK_NO_WINDOW
         // widgets.
-#if (MOZ_WIDGET_GTK == 2)
-        g_signal_connect(mContainer, "expose_event",
-                         G_CALLBACK(expose_event_cb), nullptr);
-#else
         g_signal_connect(G_OBJECT(mContainer), "draw",
                          G_CALLBACK(expose_event_cb), nullptr);
-#endif
         g_signal_connect(mContainer, "focus_in_event",
                          G_CALLBACK(focus_in_event_cb), nullptr);
         g_signal_connect(mContainer, "focus_out_event",
@@ -4006,10 +3962,6 @@ nsWindow::Create(nsIWidget* aParent,
     }
 
     if (eventWidget) {
-#if (MOZ_WIDGET_GTK == 2)
-        // Don't let GTK mess with the shapes of our GdkWindows
-        GTK_PRIVATE_SET_FLAG(eventWidget, GTK_HAS_SHAPE_MASK);
-#endif
 
         // These events are sent to the owning widget of the relevant window
         // and propagate up to the first widget that handles the events, so we
@@ -4025,8 +3977,6 @@ nsWindow::Create(nsIWidget* aParent,
                          G_CALLBACK(button_press_event_cb), nullptr);
         g_signal_connect(eventWidget, "button-release-event",
                          G_CALLBACK(button_release_event_cb), nullptr);
-        g_signal_connect(eventWidget, "property-notify-event",
-                         G_CALLBACK(property_notify_event_cb), nullptr);
         g_signal_connect(eventWidget, "scroll-event",
                          G_CALLBACK(scroll_event_cb), nullptr);
 #if GTK_CHECK_VERSION(3,4,0)
@@ -4039,7 +3989,7 @@ nsWindow::Create(nsIWidget* aParent,
     if (mShell) {
         LOG(("\tmShell %p mContainer %p mGdkWindow %p 0x%lx\n",
              mShell, mContainer, mGdkWindow,
-             gdk_x11_window_get_xid(mGdkWindow)));
+             mIsX11Display ? gdk_x11_window_get_xid(mGdkWindow) : 0));
     } else if (mContainer) {
         LOG(("\tmContainer %p mGdkWindow %p\n", mContainer, mGdkWindow));
     }
@@ -4063,8 +4013,12 @@ nsWindow::Create(nsIWidget* aParent,
 
       mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth);
     }
+#ifdef MOZ_WAYLAND
+    else if (!mIsX11Display) {
+      mSurfaceProvider.Initialize(this);
+    }
+#endif
 #endif
-
     return NS_OK;
 }
 
@@ -4099,7 +4053,8 @@ nsWindow::SetWindowClass(const nsAString
   res_name[0] = toupper(res_name[0]);
   if (!role) role = res_name;
 
-  gdk_window_set_role(mGdkWindow, role);
+  GdkWindow* gdkWindow = gtk_widget_get_window(mShell);
+  gdk_window_set_role(gdkWindow, role);
 
 #ifdef MOZ_X11
   if (mIsX11Display) {
@@ -4115,7 +4070,7 @@ nsWindow::SetWindowClass(const nsAString
       // a warning & refuses to make the change.
       GdkDisplay *display = gdk_display_get_default();
       XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
-                    gdk_x11_window_get_xid(mGdkWindow),
+                    gdk_x11_window_get_xid(gdkWindow),
                     class_hint);
       XFree(class_hint);
   }
@@ -4164,7 +4119,7 @@ nsWindow::NativeResize()
     }
 
 #ifdef MOZ_X11
-    // Notify the X11CompositorWidget of a ClientSizeChange
+    // Notify the GtkCompositorWidget of a ClientSizeChange
     // This is different than OnSizeAllocate to catch initial sizing
     if (mCompositorWidgetDelegate) {
       mCompositorWidgetDelegate->NotifyClientSizeChanged(GetClientSize());
@@ -4220,7 +4175,7 @@ nsWindow::NativeMoveResize()
     }
 
 #ifdef MOZ_X11
-    // Notify the X11CompositorWidget of a ClientSizeChange
+    // Notify the GtkCompositorWidget of a ClientSizeChange
     // This is different than OnSizeAllocate to catch initial sizing
     if (mCompositorWidgetDelegate) {
       mCompositorWidgetDelegate->NotifyClientSizeChanged(GetClientSize());
@@ -4529,17 +4484,6 @@ nsWindow::SetWindowClipRegion(const nsTA
     if (!mGdkWindow)
         return NS_OK;
 
-#if (MOZ_WIDGET_GTK == 2)
-    GdkRegion *region = gdk_region_new(); // aborts on OOM
-    for (uint32_t i = 0; i < newRects->Length(); ++i) {
-        const LayoutDeviceIntRect& r = newRects->ElementAt(i);
-        GdkRectangle rect = { r.x, r.y, r.width, r.height };
-        gdk_region_union_with_rect(region, &rect);
-    }
-
-    gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
-    gdk_region_destroy(region);
-#else
     cairo_region_t *region = cairo_region_create();
     for (uint32_t i = 0; i < newRects->Length(); ++i) {
         const LayoutDeviceIntRect& r = newRects->ElementAt(i);
@@ -4549,7 +4493,6 @@ nsWindow::SetWindowClipRegion(const nsTA
 
     gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
     cairo_region_destroy(region);
-#endif
 
     return NS_OK;
 }
@@ -4658,17 +4601,6 @@ nsWindow::ApplyTransparencyBitmap()
                       maskPixmap, ShapeSet);
     XFreePixmap(xDisplay, maskPixmap);
 #else
-#if (MOZ_WIDGET_GTK == 2)
-    gtk_widget_reset_shapes(mShell);
-    GdkBitmap* maskBitmap = gdk_bitmap_create_from_data(mGdkWindow,
-            mTransparencyBitmap,
-            mTransparencyBitmapWidth, mTransparencyBitmapHeight);
-    if (!maskBitmap)
-        return;
-
-    gtk_widget_shape_combine_mask(mShell, maskBitmap, 0, 0);
-    g_object_unref(maskBitmap);
-#else
     cairo_surface_t *maskBitmap;
     maskBitmap = cairo_image_surface_create_for_data((unsigned char*)mTransparencyBitmap,
                                                      CAIRO_FORMAT_A1,
@@ -4682,7 +4614,6 @@ nsWindow::ApplyTransparencyBitmap()
     gtk_widget_shape_combine_region(mShell, maskRegion);
     cairo_region_destroy(maskRegion);
     cairo_surface_destroy(maskBitmap);
-#endif // MOZ_WIDGET_GTK == 2
 #endif // MOZ_X11
 }
 
@@ -4779,6 +4710,12 @@ nsWindow::GrabPointer(guint32 aTime)
     if (!mGdkWindow)
         return;
 
+    if (!mIsX11Display) {
+        // Don't to the grab on Wayland as it causes a regression
+        // from Bug 1377084.
+        return;
+    }
+
     gint retval;
     retval = gdk_pointer_grab(mGdkWindow, TRUE,
                               (GdkEventMask)(GDK_BUTTON_PRESS_MASK |
@@ -4812,6 +4749,13 @@ nsWindow::ReleaseGrabs(void)
     LOG(("ReleaseGrabs\n"));
 
     mRetryPointerGrab = false;
+
+    if (!mIsX11Display) {
+        // Don't to the ungrab on Wayland as it causes a regression
+        // from Bug 1377084.
+        return;
+    }
+
     gdk_pointer_ungrab(GDK_CURRENT_TIME);
 }
 
@@ -5058,7 +5002,7 @@ nsWindow::MakeFullScreen(bool aFullScree
     LOG(("nsWindow::MakeFullScreen [%p] aFullScreen %d\n",
          (void *)this, aFullScreen));
 
-    if (!IsFullscreenSupported(mShell)) {
+    if (mIsX11Display && !IsFullscreenSupported(mShell)) {
         return NS_ERROR_NOT_AVAILABLE;
     }
 
@@ -5080,7 +5024,7 @@ nsWindow::MakeFullScreen(bool aFullScree
 }
 
 void
-nsWindow::HideWindowChrome(bool aShouldHide)
+nsWindow::SetWindowDecoration(nsBorderStyle aStyle)
 {
     if (!mShell) {
         // Pass the request to the toplevel window
@@ -5092,30 +5036,29 @@ nsWindow::HideWindowChrome(bool aShouldH
         if (!topWindow)
             return;
 
-        topWindow->HideWindowChrome(aShouldHide);
+        topWindow->SetWindowDecoration(aStyle);
         return;
     }
 
+    // We can't use mGdkWindow directly here as it can be
+    // derived from mContainer which is not a top-level GdkWindow.
+    GdkWindow *window = gtk_widget_get_window(mShell);
+
     // Sawfish, metacity, and presumably other window managers get
     // confused if we change the window decorations while the window
     // is visible.
     bool wasVisible = false;
-    if (gdk_window_is_visible(mGdkWindow)) {
-        gdk_window_hide(mGdkWindow);
+    if (gdk_window_is_visible(window)) {
+        gdk_window_hide(window);
         wasVisible = true;
     }
 
-    gint wmd;
-    if (aShouldHide)
-        wmd = 0;
-    else
-        wmd = ConvertBorderStyles(mBorderStyle);
-
+    gint wmd = ConvertBorderStyles(aStyle);
     if (wmd != -1)
-      gdk_window_set_decorations(mGdkWindow, (GdkWMDecoration) wmd);
+      gdk_window_set_decorations(window, (GdkWMDecoration) wmd);
 
     if (wasVisible)
-        gdk_window_show(mGdkWindow);
+        gdk_window_show(window);
 
     // For some window managers, adding or removing window decorations
     // requires unmapping and remapping our toplevel window.  Go ahead
@@ -5123,10 +5066,19 @@ nsWindow::HideWindowChrome(bool aShouldH
     // error later when this happens (when the persistence timer fires
     // and GetWindowPos is called)
 #ifdef MOZ_X11
-    XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) , False);
-#else
-    gdk_flush ();
+    if (mIsX11Display) {
+        XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) , False);
+    } else
 #endif /* MOZ_X11 */
+    {
+        gdk_flush ();
+    }
+}
+
+void
+nsWindow::HideWindowChrome(bool aShouldHide)
+{
+    SetWindowDecoration(aShouldHide ? eBorderStyle_none : mBorderStyle);
 }
 
 bool
@@ -5237,12 +5189,8 @@ is_mouse_in_window (GdkWindow* aWindow,
         window = gdk_window_get_parent(window);
     }
 
-#if (MOZ_WIDGET_GTK == 2)
-    gdk_drawable_get_size(aWindow, &w, &h);
-#else
     w = gdk_window_get_width(aWindow);
     h = gdk_window_get_height(aWindow);
-#endif
 
     if (aMouseX > x && aMouseX < x + w &&
         aMouseY > y && aMouseY < y + h)
@@ -5498,18 +5446,6 @@ get_gtk_cursor(nsCursor aCursor)
 
 // gtk callbacks
 
-#if (MOZ_WIDGET_GTK == 2)
-static gboolean
-expose_event_cb(GtkWidget *widget, GdkEventExpose *event)
-{
-    RefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
-    if (!window)
-        return FALSE;
-
-    window->OnExposeEvent(event);
-    return FALSE;
-}
-#else
 void
 draw_window_of_widget(GtkWidget *widget, GdkWindow *aWindow, cairo_t *cr)
 {
@@ -5561,7 +5497,6 @@ expose_event_cb(GtkWidget *widget, cairo
 
     return FALSE;
 }
-#endif //MOZ_WIDGET_GTK == 2
 
 static gboolean
 configure_event_cb(GtkWidget *widget,
@@ -5980,7 +5915,6 @@ widget_composited_changed_cb (GtkWidget*
     window->OnCompositedChanged();
 }
 
-#if (MOZ_WIDGET_GTK == 3)
 static void
 scale_changed_cb (GtkWidget* widget, GParamSpec* aPSpec, gpointer aPointer)
 {
@@ -5996,7 +5930,6 @@ scale_changed_cb (GtkWidget* widget, GPa
     gtk_widget_get_allocation(widget, &allocation);
     window->OnSizeAllocate(&allocation);
 }
-#endif
 
 #if GTK_CHECK_VERSION(3,4,0)
 static gboolean
@@ -6174,11 +6107,7 @@ get_inner_gdk_window (GdkWindow *aWindow
          child = g_list_previous(child)) {
         auto *childWindow = (GdkWindow *) child->data;
         if (get_window_for_gdk_window(childWindow)) {
-#if (MOZ_WIDGET_GTK == 2)
-            gdk_window_get_geometry(childWindow, &cx, &cy, &cw, &ch, nullptr);
-#else
             gdk_window_get_geometry(childWindow, &cx, &cy, &cw, &ch);
-#endif
             if ((cx < x) && (x < (cx + cw)) &&
                 (cy < y) && (y < (cy + ch)) &&
                 gdk_window_is_visible(childWindow)) {
@@ -6386,53 +6315,6 @@ nsWindow::GetEditCommands(NativeKeyBindi
     keyBindings->GetEditCommands(aEvent, aCommands);
 }
 
-#if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
-/* static */ already_AddRefed<DrawTarget>
-nsWindow::GetDrawTargetForGdkDrawable(GdkDrawable* aDrawable,
-                                      const IntSize& aSize)
-{
-    GdkVisual* visual = gdk_drawable_get_visual(aDrawable);
-    Screen* xScreen =
-        gdk_x11_screen_get_xscreen(gdk_drawable_get_screen(aDrawable));
-    Display* xDisplay = DisplayOfScreen(xScreen);
-    Drawable xDrawable = gdk_x11_drawable_get_xid(aDrawable);
-
-    RefPtr<gfxASurface> surface;
-
-    if (visual) {
-        Visual* xVisual = gdk_x11_visual_get_xvisual(visual);
-
-        surface = new gfxXlibSurface(xDisplay, xDrawable, xVisual, aSize);
-    } else {
-        // no visual? we must be using an xrender format.  Find a format
-        // for this depth.
-        XRenderPictFormat *pf = nullptr;
-        switch (gdk_drawable_get_depth(aDrawable)) {
-            case 32:
-                pf = XRenderFindStandardFormat(xDisplay, PictStandardARGB32);
-                break;
-            case 24:
-                pf = XRenderFindStandardFormat(xDisplay, PictStandardRGB24);
-                break;
-            default:
-                NS_ERROR("Don't know how to handle the given depth!");
-                break;
-        }
-
-        surface = new gfxXlibSurface(xScreen, xDrawable, pf, aSize);
-    }
-
-    RefPtr<DrawTarget> dt =
-        gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, aSize);
-
-    if (!dt || !dt->IsValid()) {
-        return nullptr;
-    }
-
-    return dt.forget();
-}
-#endif
-
 already_AddRefed<DrawTarget>
 nsWindow::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, BufferMode* aBufferMode)
 {
@@ -6649,9 +6531,66 @@ nsWindow::SetDrawsInTitlebar(bool aState
       return;
 
   if (mShell) {
-      gint wmd = aState ? GDK_DECOR_BORDER : ConvertBorderStyles(mBorderStyle);
-      gdk_window_set_decorations(gtk_widget_get_window(mShell),
-                                 (GdkWMDecoration) wmd);
+      if (GetCSDSupportLevel() == CSD_SUPPORT_FULL) {
+          SetWindowDecoration(aState ? eBorderStyle_border : mBorderStyle);
+      }
+      else {
+          /* Window manager does not support GDK_DECOR_BORDER,
+           * emulate it by CSD.
+           *
+           * gtk_window_set_titlebar() works on unrealized widgets only,
+           * we need to handle mShell carefully here.
+           * When CSD is enabled mGdkWindow is owned by mContainer which is good
+           * as we can't delete our mGdkWindow. To make mShell unrealized while
+           * mContainer is preserved we temporary reparent mContainer to an
+           * invisible GtkWindow.
+           */
+          NativeShow(false);
+
+          // Using GTK_WINDOW_POPUP rather than
+          // GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less
+          // initialization and window manager interaction.
+          GtkWidget* tmpWindow = gtk_window_new(GTK_WINDOW_POPUP);
+          gtk_widget_realize(tmpWindow);
+
+          gtk_widget_reparent(GTK_WIDGET(mContainer), tmpWindow);
+          gtk_widget_unrealize(GTK_WIDGET(mShell));
+
+          // Available as of GTK 3.10+
+          static auto sGtkWindowSetTitlebar = (void (*)(GtkWindow*, GtkWidget*))
+              dlsym(RTLD_DEFAULT, "gtk_window_set_titlebar");
+          MOZ_ASSERT(sGtkWindowSetTitlebar,
+              "Missing gtk_window_set_titlebar(), old Gtk+ library?");
+
+          if (aState) {
+              // Add a hidden titlebar widget to trigger CSD, but disable the default
+              // titlebar.  GtkFixed is a somewhat random choice for a simple unused
+              // widget. gtk_window_set_titlebar() takes ownership of the titlebar
+              // widget.
+              sGtkWindowSetTitlebar(GTK_WINDOW(mShell), gtk_fixed_new());
+          } else {
+              sGtkWindowSetTitlebar(GTK_WINDOW(mShell), nullptr);
+          }
+
+          /* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=791081
+           * gtk_widget_realize() throws:
+           * "In pixman_region32_init_rect: Invalid rectangle passed"
+           * when mShell has default 1x1 size.
+           */
+          GtkAllocation allocation = {0, 0, 0, 0};
+          gtk_widget_get_preferred_width(GTK_WIDGET(mShell), nullptr,
+                                         &allocation.width);
+          gtk_widget_get_preferred_height(GTK_WIDGET(mShell), nullptr,
+                                          &allocation.height);
+          gtk_widget_size_allocate(GTK_WIDGET(mShell), &allocation);
+
+          gtk_widget_realize(GTK_WIDGET(mShell));
+          gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell));
+          mNeedsShow = true;
+          NativeResize();
+
+          gtk_widget_destroy(tmpWindow);
+      }
   }
 
   mIsCSDEnabled = aState;
@@ -6762,11 +6701,9 @@ nsWindow::SynthesizeNativeMouseEvent(Lay
     event.button.window = mGdkWindow;
     event.button.time = GDK_CURRENT_TIME;
 
-#if (MOZ_WIDGET_GTK == 3)
     // Get device for event source
     GdkDeviceManager *device_manager = gdk_display_get_device_manager(display);
     event.button.device = gdk_device_manager_get_client_pointer(device_manager);
-#endif
 
     event.button.x_root = DevicePixelsToGdkCoordRoundDown(aPoint.x);
     event.button.y_root = DevicePixelsToGdkCoordRoundDown(aPoint.y);
@@ -6809,12 +6746,10 @@ nsWindow::SynthesizeNativeMouseScrollEve
   event.type = GDK_SCROLL;
   event.scroll.window = mGdkWindow;
   event.scroll.time = GDK_CURRENT_TIME;
-#if (MOZ_WIDGET_GTK == 3)
   // Get device for event source
   GdkDisplay* display = gdk_window_get_display(mGdkWindow);
   GdkDeviceManager *device_manager = gdk_display_get_device_manager(display);
   event.scroll.device = gdk_device_manager_get_client_pointer(device_manager);
-#endif
   event.scroll.x_root = DevicePixelsToGdkCoordRoundDown(aPoint.x);
   event.scroll.y_root = DevicePixelsToGdkCoordRoundDown(aPoint.y);
 
@@ -6938,27 +6873,54 @@ nsWindow::GetCSDSupportLevel() {
     if (sCSDSupportLevel != CSD_SUPPORT_UNKNOWN) {
         return sCSDSupportLevel;
     }
-    // TODO: MATE
+
     const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
     if (currentDesktop) {
-        if (strcmp(currentDesktop, "GNOME") == 0) {
-            sCSDSupportLevel = CSD_SUPPORT_FULL;
-        } else if (strcmp(currentDesktop, "XFCE") == 0) {
+        if (strstr(currentDesktop, "GNOME") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_FULL;
-        } else if (strcmp(currentDesktop, "X-Cinnamon") == 0) {
+        } else if (strstr(currentDesktop, "XFCE") != nullptr) {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        } else if (strstr(currentDesktop, "X-Cinnamon") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_FULL;
-        } else if (strcmp(currentDesktop, "KDE") == 0) {
+        } else if (strstr(currentDesktop, "KDE") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_FLAT;
-        } else if (strcmp(currentDesktop, "LXDE") == 0) {
+        } else if (strstr(currentDesktop, "LXDE") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_FLAT;
-        } else if (strcmp(currentDesktop, "openbox") == 0) {
+        } else if (strstr(currentDesktop, "openbox") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_FLAT;
-        } else if (strcmp(currentDesktop, "i3") == 0) {
+        } else if (strstr(currentDesktop, "i3") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_NONE;
+        } else if (strstr(currentDesktop, "MATE") != nullptr) {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        } else if (strstr(currentDesktop, "Unity") != nullptr) {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        } else if (strstr(currentDesktop, "Pantheon") != nullptr) {
+            sCSDSupportLevel = CSD_SUPPORT_FULL;
         } else {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        }
+    } else {
+        sCSDSupportLevel = CSD_SUPPORT_NONE;
+    }
+
+    // We don't support CSD_SUPPORT_FULL on Wayland
+    if (!GDK_IS_X11_DISPLAY(gdk_display_get_default()) &&
+        sCSDSupportLevel == CSD_SUPPORT_FULL) {
+        sCSDSupportLevel = CSD_SUPPORT_FLAT;
+    }
+
+    // Allow MOZ_GTK_TITLEBAR_DECORATION to override our heuristics
+    const char* decorationOverride = getenv("MOZ_GTK_TITLEBAR_DECORATION");
+    if (decorationOverride) {
+        if (strcmp(decorationOverride, "none") == 0) {
             sCSDSupportLevel = CSD_SUPPORT_NONE;
+        } else if (strcmp(decorationOverride, "client") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        } else if (strcmp(decorationOverride, "system") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FULL;
         }
     }
+
     return sCSDSupportLevel;
 }
 
@@ -6991,3 +6953,24 @@ nsWindow::IsComposited() const
          (gdk_window_get_visual(mGdkWindow)
             == gdk_screen_get_rgba_visual(gdkScreen));
 }
+
+#ifdef MOZ_WAYLAND
+wl_display*
+nsWindow::GetWaylandDisplay()
+{
+  // Available as of GTK 3.8+
+  static auto sGdkWaylandDisplayGetWlDisplay =
+      (wl_display *(*)(GdkDisplay *))
+      dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
+
+  GdkDisplay* gdkDisplay = gdk_display_get_default();
+  return mIsX11Display ? nullptr :
+                         sGdkWaylandDisplayGetWlDisplay(gdkDisplay);
+}
+
+wl_surface*
+nsWindow::GetWaylandSurface()
+{
+  return moz_container_get_wl_surface(MOZ_CONTAINER(mContainer));
+}
+#endif
diff -up firefox-58.0/widget/gtk/nsWindow.h.1399611 firefox-58.0/widget/gtk/nsWindow.h
--- firefox-58.0/widget/gtk/nsWindow.h.1399611	2018-01-11 21:17:06.000000000 +0100
+++ firefox-58.0/widget/gtk/nsWindow.h	2018-01-24 10:57:03.720031943 +0100
@@ -23,7 +23,11 @@
 
 #ifdef MOZ_X11
 #include <gdk/gdkx.h>
+#include "X11UndefineNone.h"
 #endif /* MOZ_X11 */
+#ifdef MOZ_WAYLAND
+#include <gdk/gdkwayland.h>
+#endif
 
 #include "mozilla/widget/WindowSurface.h"
 #include "mozilla/widget/WindowSurfaceProvider.h"
@@ -172,11 +176,7 @@ public:
     GdkRectangle DevicePixelsToGdkRectRoundOut(LayoutDeviceIntRect aRect);
 
     // event callbacks
-#if (MOZ_WIDGET_GTK == 2)
-    gboolean           OnExposeEvent(GdkEventExpose *aEvent);
-#else
     gboolean           OnExposeEvent(cairo_t *cr);
-#endif
     gboolean           OnConfigureEvent(GtkWidget *aWidget,
                                         GdkEventConfigure *aEvent);
     void               OnContainerUnrealize();
@@ -315,10 +315,6 @@ public:
    nsresult            UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
                                                             uint8_t* aAlphas, int32_t aStride);
 
-#if (MOZ_WIDGET_GTK == 2)
-    static already_AddRefed<DrawTarget> GetDrawTargetForGdkDrawable(GdkDrawable* aDrawable,
-                                                                    const mozilla::gfx::IntSize& aSize);
-#endif
     virtual void       ReparentNativeWidget(nsIWidget* aNewParent) override;
 
     virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
@@ -348,9 +344,14 @@ public:
                                                 nsIObserver* aObserver) override;
 #endif
 
+
 #ifdef MOZ_X11
     Display* XDisplay() { return mXDisplay; }
 #endif
+#ifdef MOZ_WAYLAND
+    wl_display* GetWaylandDisplay();
+    wl_surface* GetWaylandSurface();
+#endif
     virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
 
     virtual nsresult SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
@@ -374,6 +375,18 @@ public:
     virtual bool WidgetTypeSupportsAcceleration() override;
 
     bool DoDrawTitlebar() const;
+
+    typedef enum { CSD_SUPPORT_FULL,    // CSD including shadows
+                   CSD_SUPPORT_FLAT,    // CSD without shadows
+                   CSD_SUPPORT_NONE,    // WM does not support CSD at all
+                   CSD_SUPPORT_UNKNOWN
+    } CSDSupportLevel;
+    /**
+     * Get the support of Client Side Decoration by checking
+     * the XDG_CURRENT_DESKTOP environment variable.
+     */
+    static CSDSupportLevel GetCSDSupportLevel();
+
 protected:
     virtual ~nsWindow();
 
@@ -423,6 +436,7 @@ private:
     nsWindow          *GetContainerWindow();
     void               SetUrgencyHint(GtkWidget *top_window, bool state);
     void               SetDefaultIcon(void);
+    void               SetWindowDecoration(nsBorderStyle aStyle);
     void               InitButtonEvent(mozilla::WidgetMouseEvent& aEvent,
                                        GdkEventButton* aGdkEvent);
     bool               DispatchCommandEvent(nsAtom* aCommand);
@@ -441,7 +455,6 @@ private:
     nsIWidgetListener* GetListener();
     bool               IsComposited() const;
 
-
     GtkWidget          *mShell;
     MozContainer       *mContainer;
     GdkWindow          *mGdkWindow;
@@ -578,16 +591,6 @@ private:
     RefPtr<mozilla::widget::IMContextWrapper> mIMContext;
 
     mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter;
-    typedef enum { CSD_SUPPORT_FULL,    // CSD including shadows
-                   CSD_SUPPORT_FLAT,    // CSD without shadows
-                   CSD_SUPPORT_NONE,    // WM does not support CSD at all
-                   CSD_SUPPORT_UNKNOWN
-    } CSDSupportLevel;
-    /**
-     * Get the support of Client Side Decoration by checking
-     * the XDG_CURRENT_DESKTOP environment variable.
-     */
-    static CSDSupportLevel GetCSDSupportLevel();
     static CSDSupportLevel sCSDSupportLevel;
 };