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 @@ -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 #include +#include #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 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 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 -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 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 dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, aSize); - - if (!dt || !dt->IsValid()) { - return nullptr; - } - - return dt.forget(); -} -#endif - already_AddRefed 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 +#include "X11UndefineNone.h" #endif /* MOZ_X11 */ +#ifdef MOZ_WAYLAND +#include +#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 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 mIMContext; mozilla::UniquePtr 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; };