summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firefox.spec28
-rw-r--r--mozilla-1548475.patch34
-rw-r--r--mozilla-1562827.patch141
-rw-r--r--mozilla-1567434-1.patch226
-rw-r--r--mozilla-1567434-2.patch35
-rw-r--r--mozilla-1573813.patch29
-rw-r--r--mozilla-1574036.patch425
-rw-r--r--mozilla-1576268.patch17
8 files changed, 931 insertions, 4 deletions
diff --git a/firefox.spec b/firefox.spec
index 59ed950..eb6b7a6 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -21,7 +21,7 @@ ExcludeArch: s390x
%global build_with_clang 0
%global use_bundled_cbindgen 1
# FIXME disable PGO because of -j1 build would take ages
-%global disable_multiprocess_compilation 1
+%global disable_multiprocess_compilation 0
# Build PGO+LTO on x86_64 and aarch64 only due to build issues
# on other arches.
%ifarch x86_64 aarch64
@@ -90,7 +90,7 @@ ExcludeArch: s390x
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 69.0
-Release: 1%{?pre_tag}%{?dist}
+Release: 2%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz
@@ -127,7 +127,7 @@ Patch38: build-cacheFlush-missing.patch
Patch40: build-aarch64-skia.patch
Patch41: build-disable-elfhack.patch
Patch44: build-arm-libopus.patch
-Patch45: build-disable-multijobs-rust.patch
+#Patch45: build-disable-multijobs-rust.patch
# Fedora specific patches
Patch215: firefox-enable-addons.patch
@@ -150,6 +150,13 @@ Patch420: mozilla-1566876-webrtc-ind.patch
# Wayland specific upstream patches
Patch574: firefox-pipewire.patch
+Patch575: mozilla-1548475.patch
+Patch576: mozilla-1562827.patch
+Patch578: mozilla-1567434-1.patch
+Patch579: mozilla-1567434-2.patch
+Patch580: mozilla-1573813.patch
+Patch581: mozilla-1574036.patch
+Patch582: mozilla-1576268.patch
# PGO/LTO patches
Patch600: pgo.patch
@@ -326,7 +333,7 @@ This package contains results of tests executed during build.
%endif
%patch3 -p1 -b .arm
%patch44 -p1 -b .build-arm-libopus
-%patch45 -p1 -b .build-disable-multijobs-rust
+#%patch45 -p1 -b .build-disable-multijobs-rust
# Patch for big endian platforms only
%if 0%{?big_endian}
%patch26 -p1 -b .icu
@@ -356,6 +363,13 @@ This package contains results of tests executed during build.
# Wayland specific upstream patches
%patch574 -p1 -b .firefox-pipewire
+%patch575 -p1 -b .mozilla-1548475
+%patch576 -p1 -b .mozilla-1562827
+%patch578 -p1 -b .mozilla-1567434-1
+%patch579 -p1 -b .mozilla-1567434-2
+%patch580 -p1 -b .mozilla-1573813
+%patch581 -p1 -b .mozilla-1574036
+%patch582 -p1 -b .mozilla-1576268
# PGO patches
%patch600 -p1 -b .pgo
@@ -932,6 +946,12 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Mon Sep 2 2019 Martin Stransky <stransky@redhat.com> - 69.0-1
+- Added upstream Wayland patches (mozilla-1548475, mozilla-1562827,
+ mozilla-1567434, mozilla-1573813, mozilla-1574036,
+ mozilla-1576268).
+- Enable multiprocess compilation.
+
* Thu Aug 29 2019 Jan Horak <jhorak@redhat.com> - 69.0-1
- Update to 69.0
diff --git a/mozilla-1548475.patch b/mozilla-1548475.patch
new file mode 100644
index 0000000..b325683
--- /dev/null
+++ b/mozilla-1548475.patch
@@ -0,0 +1,34 @@
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -105,6 +105,10 @@
+ # include "windows.h"
+ # include "winbase.h"
+ #endif
++#if (MOZ_WIDGET_GTK)
++# include <gdk/gdk.h>
++# include <gdk/gdkx.h>
++#endif
+
+ #include "npapi.h"
+
+@@ -358,9 +362,15 @@
+ mOverrideInternalTypes =
+ Preferences::GetBool("plugin.override_internal_types", false);
+
+- mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
+-
+- Preferences::AddStrongObserver(this, "plugin.disable");
++ bool waylandBackend = false;
++#if MOZ_WIDGET_GTK
++ waylandBackend = !GDK_IS_X11_DISPLAY(gdk_display_get_default());
++#endif
++ mPluginsDisabled =
++ Preferences::GetBool("plugin.disable", false) || waylandBackend;
++ if (!waylandBackend) {
++ Preferences::AddStrongObserver(this, "plugin.disable");
++ }
+
+ nsCOMPtr<nsIObserverService> obsService =
+ mozilla::services::GetObserverService();
+
diff --git a/mozilla-1562827.patch b/mozilla-1562827.patch
new file mode 100644
index 0000000..497133c
--- /dev/null
+++ b/mozilla-1562827.patch
@@ -0,0 +1,141 @@
+diff -up firefox-69.0/widget/gtk/nsWindow.cpp.mozilla-1562827 firefox-69.0/widget/gtk/nsWindow.cpp
+--- firefox-69.0/widget/gtk/nsWindow.cpp.mozilla-1562827 2019-09-02 15:16:15.031528276 +0200
++++ firefox-69.0/widget/gtk/nsWindow.cpp 2019-09-02 15:16:15.037528254 +0200
+@@ -818,7 +818,6 @@ void nsWindow::SetParent(nsIWidget* aNew
+ if (mParent) {
+ mParent->RemoveChild(this);
+ }
+-
+ mParent = aNewParent;
+
+ GtkWidget* oldContainer = GetMozContainerWidget();
+@@ -830,88 +829,73 @@ void nsWindow::SetParent(nsIWidget* aNew
+ return;
+ }
+
++ nsWindow* newParent = static_cast<nsWindow*>(aNewParent);
++ GdkWindow* newParentWindow = nullptr;
++ GtkWidget* newContainer = nullptr;
+ if (aNewParent) {
+ aNewParent->AddChild(this);
+- ReparentNativeWidget(aNewParent);
++ newParentWindow = newParent->mGdkWindow;
++ newContainer = newParent->GetMozContainerWidget();
+ } else {
+ // aNewParent is nullptr, but reparent to a hidden window to avoid
+ // destroying the GdkWindow and its descendants.
+ // An invisible container widget is needed to hold descendant
+ // GtkWidgets.
+- GtkWidget* newContainer = EnsureInvisibleContainer();
+- GdkWindow* newParentWindow = gtk_widget_get_window(newContainer);
+- ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
+- oldContainer);
+- }
+-}
+-
+-bool nsWindow::WidgetTypeSupportsAcceleration() { return !IsSmallPopup(); }
+-
+-void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) {
+- MOZ_ASSERT(aNewParent, "null widget");
+- NS_ASSERTION(!mIsDestroyed, "");
+- NS_ASSERTION(!static_cast<nsWindow*>(aNewParent)->mIsDestroyed, "");
+-
+- GtkWidget* oldContainer = GetMozContainerWidget();
+- if (!oldContainer) {
+- // The GdkWindows have been destroyed so there is nothing else to
+- // reparent.
+- MOZ_ASSERT(gdk_window_is_destroyed(mGdkWindow),
+- "live GdkWindow with no widget");
+- return;
++ newContainer = EnsureInvisibleContainer();
++ newParentWindow = gtk_widget_get_window(newContainer);
+ }
+- MOZ_ASSERT(!gdk_window_is_destroyed(mGdkWindow),
+- "destroyed GdkWindow with widget");
+
+- auto* newParent = static_cast<nsWindow*>(aNewParent);
+- GdkWindow* newParentWindow = newParent->mGdkWindow;
+- GtkWidget* newContainer = newParent->GetMozContainerWidget();
+- GtkWindow* shell = GTK_WINDOW(mShell);
+-
+- if (shell && gtk_window_get_transient_for(shell)) {
+- GtkWindow* topLevelParent =
+- GTK_WINDOW(gtk_widget_get_toplevel(newContainer));
+- gtk_window_set_transient_for(shell, topLevelParent);
+- }
+-
+- ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
+- oldContainer);
+-}
+-
+-void nsWindow::ReparentNativeWidgetInternal(nsIWidget* aNewParent,
+- GtkWidget* aNewContainer,
+- GdkWindow* aNewParentWindow,
+- GtkWidget* aOldContainer) {
+- if (!aNewContainer) {
++ if (!newContainer) {
+ // The new parent GdkWindow has been destroyed.
+- MOZ_ASSERT(!aNewParentWindow || gdk_window_is_destroyed(aNewParentWindow),
++ MOZ_ASSERT(!newParentWindow || gdk_window_is_destroyed(newParentWindow),
+ "live GdkWindow with no widget");
+ Destroy();
+ } else {
+- if (aNewContainer != aOldContainer) {
+- MOZ_ASSERT(!gdk_window_is_destroyed(aNewParentWindow),
++ if (newContainer != oldContainer) {
++ MOZ_ASSERT(!gdk_window_is_destroyed(newParentWindow),
+ "destroyed GdkWindow with widget");
+- SetWidgetForHierarchy(mGdkWindow, aOldContainer, aNewContainer);
++ SetWidgetForHierarchy(mGdkWindow, oldContainer, newContainer);
+
+- if (aOldContainer == gInvisibleContainer) {
++ if (oldContainer == gInvisibleContainer) {
+ CheckDestroyInvisibleContainer();
+ }
+ }
+
+- if (!mIsTopLevel) {
+- gdk_window_reparent(mGdkWindow, aNewParentWindow,
+- DevicePixelsToGdkCoordRoundDown(mBounds.x),
+- DevicePixelsToGdkCoordRoundDown(mBounds.y));
+- }
++ gdk_window_reparent(mGdkWindow, newParentWindow,
++ DevicePixelsToGdkCoordRoundDown(mBounds.x),
++ DevicePixelsToGdkCoordRoundDown(mBounds.y));
++ mToplevelParentWindow = GTK_WINDOW(gtk_widget_get_toplevel(newContainer));
+ }
+
+- auto* newParent = static_cast<nsWindow*>(aNewParent);
+ bool parentHasMappedToplevel = newParent && newParent->mHasMappedToplevel;
+ if (mHasMappedToplevel != parentHasMappedToplevel) {
+ SetHasMappedToplevel(parentHasMappedToplevel);
+ }
+ }
+
++bool nsWindow::WidgetTypeSupportsAcceleration() { return !IsSmallPopup(); }
++
++void nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) {
++ MOZ_ASSERT(aNewParent, "null widget");
++ MOZ_ASSERT(!mIsDestroyed, "");
++ MOZ_ASSERT(!static_cast<nsWindow*>(aNewParent)->mIsDestroyed, "");
++ MOZ_ASSERT(!gdk_window_is_destroyed(mGdkWindow),
++ "destroyed GdkWindow with widget");
++
++ MOZ_ASSERT(
++ !mParent,
++ "nsWindow::ReparentNativeWidget() works on toplevel windows only.");
++
++ auto* newParent = static_cast<nsWindow*>(aNewParent);
++ GtkWindow* newParentWidget = GTK_WINDOW(newParent->GetGtkWidget());
++ GtkWindow* shell = GTK_WINDOW(mShell);
++
++ if (shell && gtk_window_get_transient_for(shell)) {
++ gtk_window_set_transient_for(shell, newParentWidget);
++ mToplevelParentWindow = newParentWidget;
++ }
++}
++
+ void nsWindow::SetModal(bool aModal) {
+ LOG(("nsWindow::SetModal [%p] %d\n", (void*)this, aModal));
+ if (mIsDestroyed) return;
+diff -up firefox-69.0/widget/gtk/nsWindow.h.mozilla-1562827 firefox-69.0/widget/gtk/nsWindow.h
diff --git a/mozilla-1567434-1.patch b/mozilla-1567434-1.patch
new file mode 100644
index 0000000..446cd6b
--- /dev/null
+++ b/mozilla-1567434-1.patch
@@ -0,0 +1,226 @@
+diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
+--- a/widget/gtk/WindowSurfaceWayland.cpp
++++ b/widget/gtk/WindowSurfaceWayland.cpp
+@@ -616,8 +616,6 @@
+ }
+
+ if (!aFullScreenUpdate) {
+- NS_WARNING(
+- "We can't create a new Wayland buffer for non-fullscreen updates!");
+ return nullptr;
+ }
+
+@@ -674,8 +672,6 @@
+ (void*)buffer));
+
+ if (!buffer) {
+- NS_WARNING(
+- "WindowSurfaceWayland::LockWaylandBuffer(): No buffer available");
+ return nullptr;
+ }
+
+diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
+--- a/widget/gtk/nsWindow.h
++++ b/widget/gtk/nsWindow.h
+@@ -487,6 +487,7 @@
+ GtkWidget* mShell;
+ MozContainer* mContainer;
+ GdkWindow* mGdkWindow;
++ GtkWindow* mToplevelParentWindow;
+ bool mWindowShouldStartDragging = false;
+ PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
+
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -401,6 +401,7 @@
+ mContainer = nullptr;
+ mGdkWindow = nullptr;
+ mShell = nullptr;
++ mToplevelParentWindow = nullptr;
+ mCompositorWidgetDelegate = nullptr;
+ mHasMappedToplevel = false;
+ mIsFullyObscured = false;
+@@ -1144,6 +1145,8 @@
+ nsWindow* window =
+ static_cast<nsWindow*>(gVisibleWaylandPopupWindows->data);
+ if (window->mPopupType != ePopupTypeTooltip) break;
++ LOG(("nsWindow::HideWaylandTooltips [%p] hidding tooltip [%p].\n",
++ (void*)this, window));
+ window->HideWaylandWindow();
+ gVisibleWaylandPopupWindows = g_list_delete_link(
+ gVisibleWaylandPopupWindows, gVisibleWaylandPopupWindows);
+@@ -1172,9 +1175,12 @@
+ // before we open another one on that level. It means that every open
+ // popup needs to have an unique parent.
+ GtkWidget* nsWindow::ConfigureWaylandPopupWindows() {
++ LOG(("nsWindow::ConfigureWaylandPopupWindows [%p]\n", (void*)this));
++
+ // Check if we're already configured.
+ if (gVisibleWaylandPopupWindows &&
+ g_list_find(gVisibleWaylandPopupWindows, this)) {
++ LOG(("...[%p] is already configured.\n", (void*)this));
+ return GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
+ }
+
+@@ -1182,9 +1188,15 @@
+ // as it's short lived temporary window.
+ HideWaylandTooltips();
+
+- GtkWindow* parentWidget = nullptr;
++ GtkWindow* parentWidget = mToplevelParentWindow;
+ if (gVisibleWaylandPopupWindows) {
++ LOG(("... there's visible active popup [%p]\n",
++ gVisibleWaylandPopupWindows->data));
++
+ if (mPopupType == ePopupTypeTooltip) {
++ LOG(("...[%p] is tooltip, parent [%p]\n", (void*)this,
++ gVisibleWaylandPopupWindows->data));
++
+ // Attach tooltip window to the latest popup window
+ // to have both visible.
+ nsWindow* window =
+@@ -1200,12 +1212,19 @@
+ // nsWindow::Create()) or we're toplevel popup without parent.
+ // In both cases just use parent which was passed to nsWindow::Create().
+ if (!menuPopupFrame) {
+- return GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
++ LOG(("...[%p] menuPopupFrame = null, using given parent widget [%p]\n",
++ (void*)this, parentWidget));
++ return GTK_WIDGET(parentWidget);
+ }
+
+ nsWindow* parentWindow =
+ static_cast<nsWindow*>(menuPopupFrame->GetParentMenuWidget());
++ LOG(("...[%p] GetParentMenuWidget() = %p\n", (void*)this, parentWindow));
++
+ if (!parentWindow) {
++ LOG(("...[%p] using active/visible popups as a parent [%p]\n",
++ (void*)this, gVisibleWaylandPopupWindows->data));
++
+ // We're toplevel popup menu attached to another menu. Just use our
+ // latest popup as a parent.
+ parentWindow =
+@@ -1234,10 +1253,10 @@
+ }
+ }
+
++ MOZ_ASSERT(parentWidget, "Missing parent widget for wayland popup!");
+ if (parentWidget) {
++ LOG(("...[%p] set parent widget [%p]\n", (void*)this, parentWidget));
+ gtk_window_set_transient_for(GTK_WINDOW(mShell), parentWidget);
+- } else {
+- parentWidget = gtk_window_get_transient_for(GTK_WINDOW(mShell));
+ }
+ gVisibleWaylandPopupWindows =
+ g_list_prepend(gVisibleWaylandPopupWindows, this);
+@@ -1248,9 +1267,11 @@
+ static void NativeMoveResizeWaylandPopupCallback(
+ GdkWindow* window, const GdkRectangle* flipped_rect,
+ const GdkRectangle* final_rect, gboolean flipped_x, gboolean flipped_y,
+- void* unused) {
+- LOG(("%s flipped %d %d\n", __FUNCTION__, flipped_rect->x, flipped_rect->y));
+- LOG(("%s final %d %d\n", __FUNCTION__, final_rect->x, final_rect->y));
++ void* aWindow) {
++ LOG(("%s [%p] flipped %d %d\n", __FUNCTION__, aWindow, flipped_rect->x,
++ flipped_rect->y));
++ LOG(("%s [%p] final %d %d\n", __FUNCTION__, aWindow, final_rect->x,
++ final_rect->y));
+ }
+ #endif
+
+@@ -1264,6 +1285,8 @@
+ // Compositor may be confused by windows with width/height = 0
+ // and positioning such windows leads to Bug 1555866.
+ if (!AreBoundsSane()) {
++ LOG(("nsWindow::NativeMoveResizeWaylandPopup [%p] Bounds are not sane\n",
++ (void*)this));
+ return;
+ }
+
+@@ -1277,6 +1300,8 @@
+ // - gdk_window_move_to_rect() is not available
+ // - the widget doesn't have a valid GdkWindow
+ if (!sGdkWindowMoveToRect || !gdkWindow) {
++ LOG(("nsWindow::NativeMoveResizeWaylandPopup [%p] use gtk_window_move()\n",
++ (void*)this));
+ gtk_window_move(GTK_WINDOW(mShell), aPosition->x, aPosition->y);
+ return;
+ }
+@@ -1302,8 +1327,12 @@
+ }
+ LOG((" request result %d %d\n", rect.x, rect.y));
+ #ifdef DEBUG
+- g_signal_connect(gdkWindow, "moved-to-rect",
+- G_CALLBACK(NativeMoveResizeWaylandPopupCallback), this);
++ if (!g_signal_handler_find(
++ gdkWindow, G_SIGNAL_MATCH_FUNC, 0, 0, nullptr,
++ FuncToGpointer(NativeMoveResizeWaylandPopupCallback), this)) {
++ g_signal_connect(gdkWindow, "moved-to-rect",
++ G_CALLBACK(NativeMoveResizeWaylandPopupCallback), this);
++ }
+ #endif
+
+ GdkGravity rectAnchor = GDK_GRAVITY_NORTH_WEST;
+@@ -3508,7 +3537,6 @@
+ GtkWidget* parentMozContainer = nullptr;
+ GtkContainer* parentGtkContainer = nullptr;
+ GdkWindow* parentGdkWindow = nullptr;
+- GtkWindow* topLevelParent = nullptr;
+ nsWindow* parentnsWindow = nullptr;
+ GtkWidget* eventWidget = nullptr;
+ bool drawToContainer = false;
+@@ -3534,7 +3562,8 @@
+
+ // get the toplevel window just in case someone needs to use it
+ // for setting transients or whatever.
+- topLevelParent = GTK_WINDOW(gtk_widget_get_toplevel(parentMozContainer));
++ mToplevelParentWindow =
++ GTK_WINDOW(gtk_widget_get_toplevel(parentMozContainer));
+ }
+
+ if (!mIsX11Display) {
+@@ -3542,7 +3571,7 @@
+ // eWindowType_child is not supported on Wayland. Just switch to toplevel
+ // as a workaround.
+ mWindowType = eWindowType_toplevel;
+- } else if (mWindowType == eWindowType_popup && !topLevelParent) {
++ } else if (mWindowType == eWindowType_popup && !mToplevelParentWindow) {
+ // Workaround for Wayland where the popup windows always need to have
+ // parent window. For example webrtc ui is a popup window without parent.
+ mWindowType = eWindowType_toplevel;
+@@ -3677,7 +3706,7 @@
+ gdk_get_program_class());
+ gtk_window_set_type_hint(GTK_WINDOW(mShell),
+ GDK_WINDOW_TYPE_HINT_DIALOG);
+- gtk_window_set_transient_for(GTK_WINDOW(mShell), topLevelParent);
++ gtk_window_set_transient_for(GTK_WINDOW(mShell), mToplevelParentWindow);
+ } else if (mWindowType == eWindowType_popup) {
+ gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup",
+ gdk_get_program_class());
+@@ -3730,10 +3759,11 @@
+ }
+ gtk_window_set_type_hint(GTK_WINDOW(mShell), gtkTypeHint);
+
+- if (topLevelParent) {
++ if (mToplevelParentWindow) {
+ LOG(("nsWindow::Create [%p] Set popup parent %p\n", (void*)this,
+- topLevelParent));
+- gtk_window_set_transient_for(GTK_WINDOW(mShell), topLevelParent);
++ mToplevelParentWindow));
++ gtk_window_set_transient_for(GTK_WINDOW(mShell),
++ mToplevelParentWindow);
+ }
+
+ // We need realized mShell at NativeMove().
+@@ -4011,7 +4041,8 @@
+ #endif
+ }
+
+- LOG(("nsWindow [%p]\n", (void*)this));
++ LOG(("nsWindow [%p] %s\n", (void*)this,
++ mWindowType == eWindowType_toplevel ? "Toplevel" : "Popup"));
+ if (mShell) {
+ LOG(("\tmShell %p mContainer %p mGdkWindow %p 0x%lx\n", mShell, mContainer,
+ mGdkWindow, mIsX11Display ? gdk_x11_window_get_xid(mGdkWindow) : 0));
+
diff --git a/mozilla-1567434-2.patch b/mozilla-1567434-2.patch
new file mode 100644
index 0000000..966118a
--- /dev/null
+++ b/mozilla-1567434-2.patch
@@ -0,0 +1,35 @@
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -1208,6 +1208,7 @@
+ if (frame) {
+ menuPopupFrame = do_QueryFrame(frame);
+ }
++
+ // The popup is not fully created yet (we're called from
+ // nsWindow::Create()) or we're toplevel popup without parent.
+ // In both cases just use parent which was passed to nsWindow::Create().
+@@ -1217,10 +1218,22 @@
+ return GTK_WIDGET(parentWidget);
+ }
+
++ LOG(("...[%p] is %s\n", (void*)this,
++ menuPopupFrame->IsContextMenu() ? "context menu" : "popup"));
++
+ nsWindow* parentWindow =
+ static_cast<nsWindow*>(menuPopupFrame->GetParentMenuWidget());
+ LOG(("...[%p] GetParentMenuWidget() = %p\n", (void*)this, parentWindow));
+
++ // If the popup is a regular menu but GetParentMenuWidget() returns
++ // nullptr which means it's connected non-menu parent
++ // (bookmark toolbar for instance).
++ // In this case use a parent given at nsWindow::Create().
++ if (!parentWindow && !menuPopupFrame->IsContextMenu()) {
++ parentWindow =
++ get_window_for_gtk_widget(GTK_WIDGET(mToplevelParentWindow));
++ }
++
+ if (!parentWindow) {
+ LOG(("...[%p] using active/visible popups as a parent [%p]\n",
+ (void*)this, gVisibleWaylandPopupWindows->data));
+
diff --git a/mozilla-1573813.patch b/mozilla-1573813.patch
new file mode 100644
index 0000000..e9fca07
--- /dev/null
+++ b/mozilla-1573813.patch
@@ -0,0 +1,29 @@
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -6577,11 +6577,22 @@
+ }
+
+ gint nsWindow::GdkScaleFactor() {
++ // For popup windows with parent window we need to get scale factor of the
++ // parent window. Otherwise the scale factor of the popup is not updated
++ // during it's hidden.
++ GdkWindow* scaledGdkWindow = mGdkWindow;
++ if (mToplevelParentWindow) {
++ scaledGdkWindow = gtk_widget_get_window(GTK_WIDGET(mToplevelParentWindow));
++ // Fallback for windows which parent has been unrealized.
++ if (!scaledGdkWindow) {
++ scaledGdkWindow = mGdkWindow;
++ }
++ }
+ // Available as of GTK 3.10+
+ static auto sGdkWindowGetScaleFactorPtr =
+ (gint(*)(GdkWindow*))dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor");
+- if (sGdkWindowGetScaleFactorPtr && mGdkWindow)
+- return (*sGdkWindowGetScaleFactorPtr)(mGdkWindow);
++ if (sGdkWindowGetScaleFactorPtr && scaledGdkWindow)
++ return (*sGdkWindowGetScaleFactorPtr)(scaledGdkWindow);
+ return ScreenHelperGTK::GetGTKMonitorScaleFactor();
+ }
+
+
diff --git a/mozilla-1574036.patch b/mozilla-1574036.patch
new file mode 100644
index 0000000..c3ecdc7
--- /dev/null
+++ b/mozilla-1574036.patch
@@ -0,0 +1,425 @@
+diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h
+--- a/widget/gtk/WindowSurfaceWayland.h
++++ b/widget/gtk/WindowSurfaceWayland.h
+@@ -177,12 +177,9 @@
+
+ private:
+ WindowBackBuffer* CreateWaylandBuffer(int aWidth, int aHeight);
+- WindowBackBuffer* GetWaylandBufferToDraw(int aWidth, int aHeight,
+- bool aFullScreenUpdate);
++ WindowBackBuffer* GetWaylandBufferToDraw(bool aCanSwitchBuffer);
+
+- already_AddRefed<gfx::DrawTarget> LockWaylandBuffer(int aWidth, int aHeight,
+- bool aClearBuffer,
+- bool aFullScreenUpdate);
++ already_AddRefed<gfx::DrawTarget> LockWaylandBuffer(bool aCanSwitchBuffer);
+ void UnlockWaylandBuffer();
+
+ already_AddRefed<gfx::DrawTarget> LockImageSurface(
+@@ -198,7 +195,10 @@
+
+ // TODO: Do we need to hold a reference to nsWindow object?
+ nsWindow* mWindow;
+- LayoutDeviceIntRect mLastScreenRect;
++ // Buffer screen rects helps us understand if we operate on
++ // the same window size as we're called on WindowSurfaceWayland::Lock().
++ // mBufferScreenRect is window size when our wayland buffer was allocated.
++ LayoutDeviceIntRect mBufferScreenRect;
+ nsWaylandDisplay* mWaylandDisplay;
+ WindowBackBuffer* mWaylandBuffer;
+ LayoutDeviceIntRegion mWaylandBufferDamage;
+@@ -211,7 +211,8 @@
+ AutoTArray<WindowImageSurface, 30> mDelayedImageCommits;
+ bool mDrawToWaylandBufferDirectly;
+ bool mPendingCommit;
+- bool mWaylandBufferFullScreenDamage;
++ bool mWholeWindowBufferDamage;
++ bool mBufferNeedsClear;
+ bool mIsMainThread;
+ bool mNeedScaleFactorUpdate;
+
+diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
+--- a/widget/gtk/WindowSurfaceWayland.cpp
++++ b/widget/gtk/WindowSurfaceWayland.cpp
+@@ -499,7 +499,8 @@
+ mDelayedCommitHandle(nullptr),
+ mDrawToWaylandBufferDirectly(true),
+ mPendingCommit(false),
+- mWaylandBufferFullScreenDamage(false),
++ mWholeWindowBufferDamage(false),
++ mBufferNeedsClear(false),
+ mIsMainThread(NS_IsMainThread()),
+ mNeedScaleFactorUpdate(true) {
+ for (int i = 0; i < BACK_BUFFER_NUM; i++) mBackupBuffer[i] = nullptr;
+@@ -565,18 +566,20 @@
+ }
+
+ WindowBackBuffer* WindowSurfaceWayland::GetWaylandBufferToDraw(
+- int aWidth, int aHeight, bool aFullScreenUpdate) {
++ bool aCanSwitchBuffer) {
+ LOGWAYLAND(("%s [%p] Requested buffer [%d x %d]\n", __PRETTY_FUNCTION__,
+- (void*)this, aWidth, aHeight));
++ (void*)this, mBufferScreenRect.width, mBufferScreenRect.height));
+
+ // There's no buffer created yet, create a new one.
+ if (!mWaylandBuffer) {
+- MOZ_ASSERT(aFullScreenUpdate, "Created new buffer for partial drawing!");
++ MOZ_ASSERT(aCanSwitchBuffer && mWholeWindowBufferDamage,
++ "Created new buffer for partial drawing!");
+ LOGWAYLAND(("%s [%p] Created new buffer [%d x %d]\n", __PRETTY_FUNCTION__,
+- (void*)this, aWidth, aHeight));
++ (void*)this, mBufferScreenRect.width,
++ mBufferScreenRect.height));
+
+- mWaylandBuffer = CreateWaylandBuffer(aWidth, aHeight);
+- mWaylandBufferFullScreenDamage = true;
++ mWaylandBuffer =
++ CreateWaylandBuffer(mBufferScreenRect.width, mBufferScreenRect.height);
+ mNeedScaleFactorUpdate = true;
+ return mWaylandBuffer;
+ }
+@@ -593,29 +596,31 @@
+ LOGWAYLAND(
+ ("%s [%p] Use recent buffer.\n", __PRETTY_FUNCTION__, (void*)this));
+
+- if (mWaylandBuffer->IsMatchingSize(aWidth, aHeight)) {
++ if (mWaylandBuffer->IsMatchingSize(mBufferScreenRect.width,
++ mBufferScreenRect.height)) {
+ LOGWAYLAND(("%s [%p] Size is ok, use the buffer [%d x %d]\n",
+- __PRETTY_FUNCTION__, (void*)this, aWidth, aHeight));
++ __PRETTY_FUNCTION__, (void*)this, mBufferScreenRect.width,
++ mBufferScreenRect.height));
+ return mWaylandBuffer;
+ }
+
+- if (!aFullScreenUpdate) {
++ if (!aCanSwitchBuffer) {
+ NS_WARNING("We can't resize Wayland buffer for non-fullscreen updates!");
+ return nullptr;
+ }
+
+ LOGWAYLAND(("%s [%p] Reuse buffer with resize [%d x %d]\n",
+- __PRETTY_FUNCTION__, (void*)this, aWidth, aHeight));
++ __PRETTY_FUNCTION__, (void*)this, mBufferScreenRect.width,
++ mBufferScreenRect.height));
+
+- mWaylandBuffer->Resize(aWidth, aHeight);
++ mWaylandBuffer->Resize(mBufferScreenRect.width, mBufferScreenRect.height);
+ // There's a chance that scale factor has been changed
+ // when buffer size changed
+- mWaylandBufferFullScreenDamage = true;
+ mNeedScaleFactorUpdate = true;
+ return mWaylandBuffer;
+ }
+
+- if (!aFullScreenUpdate) {
++ if (!aCanSwitchBuffer) {
+ return nullptr;
+ }
+
+@@ -625,8 +630,10 @@
+ availableBuffer++) {
+ if (!mBackupBuffer[availableBuffer]) {
+ LOGWAYLAND(("%s [%p] Created new buffer [%d x %d]\n", __PRETTY_FUNCTION__,
+- (void*)this, aWidth, aHeight));
+- mBackupBuffer[availableBuffer] = CreateWaylandBuffer(aWidth, aHeight);
++ (void*)this, mBufferScreenRect.width,
++ mBufferScreenRect.height));
++ mBackupBuffer[availableBuffer] = CreateWaylandBuffer(
++ mBufferScreenRect.width, mBufferScreenRect.height);
+ break;
+ }
+
+@@ -650,23 +657,23 @@
+ __PRETTY_FUNCTION__, (void*)this, (void*)lastWaylandBuffer,
+ (void*)mWaylandBuffer));
+
+- mWaylandBufferFullScreenDamage = true;
+ mNeedScaleFactorUpdate = true;
+
+- bool bufferNeedsResize = !mWaylandBuffer->IsMatchingSize(aWidth, aHeight);
++ bool bufferNeedsResize = !mWaylandBuffer->IsMatchingSize(
++ mBufferScreenRect.width, mBufferScreenRect.height);
+ if (bufferNeedsResize) {
+ LOGWAYLAND(("%s [%p] Resize buffer to [%d x %d]\n", __PRETTY_FUNCTION__,
+- (void*)this, aWidth, aHeight));
+- mWaylandBuffer->Resize(aWidth, aHeight);
++ (void*)this, mBufferScreenRect.width,
++ mBufferScreenRect.height));
++ mWaylandBuffer->Resize(mBufferScreenRect.width, mBufferScreenRect.height);
+ }
+
+ return mWaylandBuffer;
+ }
+
+ already_AddRefed<gfx::DrawTarget> WindowSurfaceWayland::LockWaylandBuffer(
+- int aWidth, int aHeight, bool aClearBuffer, bool aFullScreenUpdate) {
+- WindowBackBuffer* buffer =
+- GetWaylandBufferToDraw(aWidth, aHeight, aFullScreenUpdate);
++ bool aCanSwitchBuffer) {
++ WindowBackBuffer* buffer = GetWaylandBufferToDraw(aCanSwitchBuffer);
+
+ LOGWAYLAND(("%s [%p] Got buffer %p\n", __PRETTY_FUNCTION__, (void*)this,
+ (void*)buffer));
+@@ -675,8 +682,9 @@
+ return nullptr;
+ }
+
+- if (aClearBuffer) {
++ if (mBufferNeedsClear && mWholeWindowBufferDamage) {
+ buffer->Clear();
++ mBufferNeedsClear = false;
+ }
+
+ return buffer->Lock();
+@@ -744,7 +752,7 @@
+ const LayoutDeviceIntRegion& aRegion) {
+ MOZ_ASSERT(mIsMainThread == NS_IsMainThread());
+
+- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
++ LayoutDeviceIntRect lockedScreenRect = mWindow->GetBounds();
+ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
+ gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
+
+@@ -753,54 +761,77 @@
+ mWindow->IsWaylandPopup() &&
+ (eTransparencyTransparent == mWindow->GetTransparencyMode());
+
+- mDrawToWaylandBufferDirectly =
+- isTransparentPopup ? IsPopupFullScreenUpdate(screenRect, aRegion)
+- : IsWindowFullScreenUpdate(screenRect, aRegion);
++ // We have request to lock whole buffer/window.
++ mWholeWindowBufferDamage =
++ isTransparentPopup ? IsPopupFullScreenUpdate(lockedScreenRect, aRegion)
++ : IsWindowFullScreenUpdate(lockedScreenRect, aRegion);
+
+- bool needsClear = mWindow->WaylandSurfaceNeedsClear() ||
+- (isTransparentPopup && mDrawToWaylandBufferDirectly);
++ // Clear buffer when we (re)draw new transparent popup window,
++ // otherwise leave it as-is, mBufferNeedsClear can be set from previous
++ // (already pending) commits which are cached now.
++ if (mWholeWindowBufferDamage) {
++ mBufferNeedsClear =
++ mWindow->WaylandSurfaceNeedsClear() || isTransparentPopup;
++ }
+
+ LOGWAYLAND(("%s [%p] lockSize [%d x %d] windowSize [%d x %d]\n",
+ __PRETTY_FUNCTION__, (void*)this, lockSize.width, lockSize.height,
+- screenRect.width, screenRect.height));
++ lockedScreenRect.width, lockedScreenRect.height));
+ LOGWAYLAND((" nsWindow = %p\n", mWindow));
+ LOGWAYLAND((" isPopup = %d\n", mWindow->IsWaylandPopup()));
+ LOGWAYLAND((" isTransparentPopup = %d\n", isTransparentPopup));
+ LOGWAYLAND((" IsPopupFullScreenUpdate = %d\n",
+- IsPopupFullScreenUpdate(screenRect, aRegion)));
++ IsPopupFullScreenUpdate(lockedScreenRect, aRegion)));
+ LOGWAYLAND((" IsWindowFullScreenUpdate = %d\n",
+- IsWindowFullScreenUpdate(screenRect, aRegion)));
+- LOGWAYLAND((" needsClear = %d\n", needsClear));
+- LOGWAYLAND(
+- (" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
++ IsWindowFullScreenUpdate(lockedScreenRect, aRegion)));
++ LOGWAYLAND((" mBufferNeedsClear = %d\n", mBufferNeedsClear));
++ LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
++
++#if DEBUG
++ if (!(mBufferScreenRect == lockedScreenRect)) {
++ LOGWAYLAND((" screen size changed\n"));
++ }
++#endif
+
+- // Allow full screen allocation and clear
+- // when window size changed.
+- bool bufferRedraw = !(screenRect == mLastScreenRect);
+- if (bufferRedraw) {
+- mDrawToWaylandBufferDirectly = true;
+- needsClear = true;
++ if (!(mBufferScreenRect == lockedScreenRect)) {
++ // Screen (window) size changed and we still have some painting pending
++ // for the last window size. That can happen when window is resized.
++ // We can't commit them any more as they're for former window size, so
++ // scratch them.
++ mDelayedImageCommits.Clear();
++
++ if (!mWholeWindowBufferDamage) {
++ NS_WARNING("Partial screen update when window is resized!");
++ // This should not happen. Screen size changed but we got only
++ // partal screen update instead of whole screen. Discard this painting
++ // as it produces artifacts.
++ return nullptr;
++ }
++ mBufferScreenRect = lockedScreenRect;
+ }
+
+- if (mDrawToWaylandBufferDirectly) {
++ if (mWholeWindowBufferDamage) {
++ // We can lock/commit entire buffer direcly.
++ mDrawToWaylandBufferDirectly = true;
++
+ // If there's any pending image commit scratch them as we're going
+ // to redraw the whole sceen anyway.
+ mDelayedImageCommits.Clear();
+
+- RefPtr<gfx::DrawTarget> dt =
+- LockWaylandBuffer(screenRect.width, screenRect.height, needsClear,
+- /* aFullScreenUpdate */ true);
++ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
++ /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
+ if (dt) {
+- if (bufferRedraw) {
+- mLastScreenRect = screenRect;
+- }
+ return dt.forget();
+ }
++ }
+
+- // We don't have any front buffer available. Try indirect drawing
+- // to mImageSurface which is mirrored to front buffer at commit.
+- mDrawToWaylandBufferDirectly = false;
+- }
++ // We do indirect drawing due to:
++ //
++ // 1) We don't have any front buffer available. Try indirect drawing
++ // to mImageSurface which is mirrored to front buffer at commit.
++ // 2) Only part of the screen is locked. We can't lock entire screen for
++ // such drawing as it produces visible artifacts.
++ mDrawToWaylandBufferDirectly = false;
+
+ LOGWAYLAND((" Indirect drawing.\n"));
+ return LockImageSurface(lockSize);
+@@ -851,16 +882,14 @@
+ LayoutDeviceIntRegion& aWaylandBufferDamage) {
+ MOZ_ASSERT(!mDrawToWaylandBufferDirectly);
+
+- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
++#ifdef DEBUG
+ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect();
+-
+ gfx::Rect rect(bounds);
+- if (rect.IsEmpty()) {
+- return false;
+- }
++ MOZ_ASSERT(!rect.IsEmpty(), "Empty drawing?");
++#endif
+
+ LOGWAYLAND(("%s [%p] screenSize [%d x %d]\n", __PRETTY_FUNCTION__,
+- (void*)this, screenRect.width, screenRect.height));
++ (void*)this, mBufferScreenRect.width, mBufferScreenRect.height));
+
+ RefPtr<gfx::SourceSurface> surf =
+ gfx::Factory::CreateSourceSurfaceForCairoSurface(
+@@ -871,13 +900,8 @@
+ return false;
+ }
+
+- // Allow full screen allocation and clear
+- // when window size changed.
+- bool bufferRedraw = !(screenRect == mLastScreenRect);
+- RefPtr<gfx::DrawTarget> dt =
+- LockWaylandBuffer(screenRect.width, screenRect.height,
+- /* needs clear*/ bufferRedraw,
+- /* aFullScreenUpdate */ bufferRedraw);
++ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
++ /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
+ if (dt) {
+ LOGWAYLAND(
+ (" Flushing %ld cached WindowImageSurfaces to Wayland buffer\n",
+@@ -885,14 +909,11 @@
+
+ // Draw any delayed image commits first
+ DrawDelayedImageCommits(dt, aWaylandBufferDamage);
++ // Draw image from recent WindowSurfaceWayland::Lock().
+ WindowImageSurface::Draw(surf, dt, aRegion);
+ // Submit all drawing to final Wayland buffer upload
+ aWaylandBufferDamage.OrWith(aRegion);
+ UnlockWaylandBuffer();
+-
+- if (bufferRedraw) {
+- mLastScreenRect = screenRect;
+- }
+ } else {
+ mDelayedImageCommits.AppendElement(WindowImageSurface(surf, aRegion));
+ LOGWAYLAND((" Added WindowImageSurfaces, cached surfaces %ld\n",
+@@ -930,29 +951,25 @@
+ LOGWAYLAND(("%s [%p]\n", __PRETTY_FUNCTION__, (void*)this));
+ LOGWAYLAND(
+ (" mDrawToWaylandBufferDirectly = %d\n", mDrawToWaylandBufferDirectly));
+- LOGWAYLAND((" mWaylandBufferFullScreenDamage = %d\n",
+- mWaylandBufferFullScreenDamage));
++ LOGWAYLAND((" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
+ LOGWAYLAND((" mDelayedCommitHandle = %p\n", mDelayedCommitHandle));
+ LOGWAYLAND((" mFrameCallback = %p\n", mFrameCallback));
+ LOGWAYLAND((" mLastCommittedSurface = %p\n", mLastCommittedSurface));
+
+ if (!mDrawToWaylandBufferDirectly) {
++ MOZ_ASSERT(mDelayedImageCommits.Length(),
++ "Indirect drawing without any image?");
++
+ // There's some cached drawings - try to flush them now.
+- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
+- bool bufferRedraw = !(screenRect == mLastScreenRect);
+- RefPtr<gfx::DrawTarget> dt =
+- LockWaylandBuffer(screenRect.width, screenRect.height,
+- /* needsClear */ bufferRedraw,
+- /* full screen update */ bufferRedraw);
++ RefPtr<gfx::DrawTarget> dt = LockWaylandBuffer(
++ /* aCanSwitchBuffer */ mWholeWindowBufferDamage);
++
+ if (dt) {
+ LOGWAYLAND(("%s [%p] flushed indirect drawing\n", __PRETTY_FUNCTION__,
+ (void*)this));
+ DrawDelayedImageCommits(dt, mWaylandBufferDamage);
+ UnlockWaylandBuffer();
+ mDrawToWaylandBufferDirectly = true;
+- if (bufferRedraw) {
+- mLastScreenRect = screenRect;
+- }
+ }
+ }
+
+@@ -1000,10 +1017,10 @@
+ mLastCommittedSurface = nullptr;
+ }
+
+- if (mWaylandBufferFullScreenDamage) {
+- LayoutDeviceIntRect rect = mWindow->GetBounds();
+- wl_surface_damage(waylandSurface, 0, 0, rect.width, rect.height);
+- mWaylandBufferFullScreenDamage = false;
++ if (mWholeWindowBufferDamage) {
++ wl_surface_damage(waylandSurface, 0, 0, mBufferScreenRect.width,
++ mBufferScreenRect.height);
++ mWholeWindowBufferDamage = false;
+ mNeedScaleFactorUpdate = true;
+ } else {
+ gint scaleFactor = mWindow->GdkScaleFactor();
+@@ -1043,24 +1060,24 @@
+
+ #ifdef DEBUG
+ {
+- LayoutDeviceIntRect screenRect = mWindow->GetBounds();
+ gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect();
+ gfx::IntSize lockSize(bounds.XMost(), bounds.YMost());
+
+ LOGWAYLAND(("%s [%p] lockSize [%d x %d] screenSize [%d x %d]\n",
+ __PRETTY_FUNCTION__, (void*)this, lockSize.width,
+- lockSize.height, screenRect.width, screenRect.height));
++ lockSize.height, mBufferScreenRect.width,
++ mBufferScreenRect.height));
+ LOGWAYLAND((" mDrawToWaylandBufferDirectly = %d\n",
+ mDrawToWaylandBufferDirectly));
+- LOGWAYLAND((" mWaylandBufferFullScreenDamage = %d\n",
+- mWaylandBufferFullScreenDamage));
++ LOGWAYLAND(
++ (" mWholeWindowBufferDamage = %d\n", mWholeWindowBufferDamage));
+ }
+ #endif
+
+ if (mDrawToWaylandBufferDirectly) {
+ MOZ_ASSERT(mWaylandBuffer->IsLocked());
+ // If we're not at fullscreen damage add drawing area from aInvalidRegion
+- if (!mWaylandBufferFullScreenDamage) {
++ if (!mWholeWindowBufferDamage) {
+ mWaylandBufferDamage.OrWith(aInvalidRegion);
+ }
+ UnlockWaylandBuffer();
+
diff --git a/mozilla-1576268.patch b/mozilla-1576268.patch
new file mode 100644
index 0000000..85fd1a8
--- /dev/null
+++ b/mozilla-1576268.patch
@@ -0,0 +1,17 @@
+diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp
+--- a/widget/gtk/nsClipboardWayland.cpp
++++ b/widget/gtk/nsClipboardWayland.cpp
+@@ -195,6 +195,12 @@
+ uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+
++ /* Default to move D&D action (Bug 1576268).
++ */
++ if (dnd_actions == 0) {
++ all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
++ }
++
+ wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions);
+
+ /* Workaround Wayland D&D architecture here. To get the data_device_drop()
+
bgstack15