summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firefox-mozconfig6
-rw-r--r--firefox.spec6
-rw-r--r--mozilla-1605795-popup-parent-fix.patch231
-rw-r--r--mozilla-1609732-no-full-hide.patch60
-rw-r--r--mozilla-1609732-pause-renderer.patch73
5 files changed, 373 insertions, 3 deletions
diff --git a/firefox-mozconfig b/firefox-mozconfig
index 3605a29..8975cbf 100644
--- a/firefox-mozconfig
+++ b/firefox-mozconfig
@@ -10,9 +10,9 @@ ac_add_options --disable-updater
ac_add_options --enable-chrome-format=omni
ac_add_options --enable-pulseaudio
ac_add_options --without-system-icu
-ac_add_options --with-mozilla-api-keyfile=../mozilla-api-key
-ac_add_options --with-google-location-service-api-keyfile=../google-api-key
-ac_add_options --with-google-safebrowsing-api-keyfile=../google-api-key
+ac_add_options --with-mozilla-api-keyfile=../../mozilla-api-key
+ac_add_options --with-google-location-service-api-keyfile=../../google-api-key
+ac_add_options --with-google-safebrowsing-api-keyfile=../../google-api-key
ac_add_options --enable-release
ac_add_options --update-channel=release
ac_add_options --disable-system-sqlite
diff --git a/firefox.spec b/firefox.spec
index fba67d4..48fba14 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -163,6 +163,9 @@ Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch
Patch417: bug1375074-save-restore-x28.patch
Patch422: mozilla-1580174-webrtc-popup.patch
Patch427: mozilla-1607404-fix-remote-offset.patch
+Patch428: mozilla-1609732-no-full-hide.patch
+Patch429: mozilla-1609732-pause-renderer.patch
+Patch430: mozilla-1605795-popup-parent-fix.patch
# Wayland specific upstream patches
Patch574: firefox-pipewire.patch
@@ -362,6 +365,9 @@ This package contains results of tests executed during build.
# dropdown missing on multimonitor
# fix for wrong intl.accept_lang when using non en-us langpack
%patch427 -p1 -b .1607404-fix-remote-offset
+%patch428 -p1 -b .1609732-no-full-hide
+%patch429 -p1 -b .1609732-pause-renderer
+%patch430 -p1 -b .1605795-popup-parent-fix
# Wayland specific upstream patches
%patch574 -p1 -b .firefox-pipewire
diff --git a/mozilla-1605795-popup-parent-fix.patch b/mozilla-1605795-popup-parent-fix.patch
new file mode 100644
index 0000000..d859893
--- /dev/null
+++ b/mozilla-1605795-popup-parent-fix.patch
@@ -0,0 +1,231 @@
+diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
+--- a/widget/gtk/nsWindow.h
++++ b/widget/gtk/nsWindow.h
+@@ -687,6 +687,9 @@
+ void HideWaylandPopupAndAllChildren();
+ void CleanupWaylandPopups();
+ GtkWindow* GetCurrentTopmostWindow();
++ GtkWindow* GetCurrentWindow();
++ GtkWindow* GetTopmostWindow();
++ bool IsWidgetOverflowWindow();
+
+ /**
+ * |mIMContext| takes all IME related stuff.
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -1193,20 +1193,26 @@
+ while (popupList) {
+ LOG((" Looking for %p [nsWindow]\n", popupList->data));
+ nsWindow* waylandWnd = static_cast<nsWindow*>(popupList->data);
+- bool popupFound = false;
+- for (unsigned long i = 0; i < widgetChain.Length(); i++) {
+- if (waylandWnd == widgetChain[i]) {
+- popupFound = true;
+- break;
++ // Remove only menu popups or empty frames - they are most likely
++ // already rolledup popups
++ if (waylandWnd->IsMainMenuWindow() || !waylandWnd->GetFrame()) {
++ bool popupFound = false;
++ for (unsigned long i = 0; i < widgetChain.Length(); i++) {
++ if (waylandWnd == widgetChain[i]) {
++ popupFound = true;
++ break;
++ }
+ }
+- }
+- if (!popupFound) {
+- LOG((" nsWindow [%p] not found in PopupManager, hiding it.\n",
+- waylandWnd));
+- waylandWnd->HideWaylandWindow();
+- popupList = gVisibleWaylandPopupWindows;
++ if (!popupFound) {
++ LOG((" nsWindow [%p] not found in PopupManager, hiding it.\n",
++ waylandWnd));
++ waylandWnd->HideWaylandWindow();
++ popupList = gVisibleWaylandPopupWindows;
++ } else {
++ LOG((" nsWindow [%p] is still open.\n", waylandWnd));
++ popupList = popupList->next;
++ }
+ } else {
+- LOG((" nsWindow [%p] is still open.\n", waylandWnd));
+ popupList = popupList->next;
+ }
+ }
+@@ -1229,6 +1235,55 @@
+ return false;
+ }
+
++GtkWindow* nsWindow::GetTopmostWindow() {
++ nsView* view = nsView::GetViewFor(this);
++ if (view) {
++ nsView* parentView = view->GetParent();
++ if (parentView) {
++ nsIWidget* parentWidget = parentView->GetNearestWidget(nullptr);
++ if (parentWidget) {
++ nsWindow* parentnsWindow = static_cast<nsWindow*>(parentWidget);
++ LOG((" Topmost window: %p [nsWindow]\n", parentnsWindow));
++ return GTK_WINDOW(parentnsWindow->mShell);
++ }
++ }
++ }
++ return nullptr;
++}
++
++GtkWindow* nsWindow::GetCurrentWindow() {
++ GtkWindow* parentGtkWindow = nullptr;
++ // get the last opened window from gVisibleWaylandPopupWindows
++ if (gVisibleWaylandPopupWindows) {
++ nsWindow* parentnsWindow =
++ static_cast<nsWindow*>(gVisibleWaylandPopupWindows->data);
++ if (parentnsWindow) {
++ LOG((" Setting parent to last opened window: %p [nsWindow]\n",
++ parentnsWindow));
++ parentGtkWindow = GTK_WINDOW(parentnsWindow->GetGtkWidget());
++ }
++ }
++ // get the topmost window if the last opened windows are empty
++ if (!parentGtkWindow) {
++ parentGtkWindow = GetTopmostWindow();
++ }
++ if (parentGtkWindow && GTK_IS_WINDOW(parentGtkWindow)) {
++ return GTK_WINDOW(parentGtkWindow);
++ } else {
++ LOG((" Failed to get current window for %p: %p\n", this, parentGtkWindow));
++ }
++ return nullptr;
++}
++
++bool nsWindow::IsWidgetOverflowWindow() {
++ if (this->GetFrame() && this->GetFrame()->GetContent()->GetID()) {
++ nsCString nodeId;
++ this->GetFrame()->GetContent()->GetID()->ToUTF8String(nodeId);
++ return nodeId.Equals("widget-overflow");
++ }
++ return false;
++}
++
+ // Wayland keeps strong popup window hierarchy. We need to track active
+ // (visible) popup windows and make sure we hide popup on the same level
+ // before we open another one on that level. It means that every open
+@@ -1247,9 +1302,18 @@
+ }
+ #endif
+
+- // Check if we're already configured.
++ if (!GetFrame()) {
++ LOG((" Window without frame cannot be configured.\n"));
++ return nullptr;
++ }
++
++ // Check if we're already configured. Popup can be reattached to various
++ // windows, so don't consider them configured. Also the widget-overflow needs
++ // special care because the opened (remote) popups has to be closed before is
++ // it shown again.
+ if (gVisibleWaylandPopupWindows &&
+- g_list_find(gVisibleWaylandPopupWindows, this)) {
++ g_list_find(gVisibleWaylandPopupWindows, this) &&
++ mPopupType != ePopupTypeTooltip && !IsWidgetOverflowWindow()) {
+ LOG((" [%p] is already configured.\n", (void*)this));
+ return GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
+ }
+@@ -1257,80 +1321,30 @@
+ // If we're opening a new window we don't want to attach it to a tooltip
+ // as it's short lived temporary window.
+ HideWaylandTooltips();
++ // Cleanup already closed menus
++ CleanupWaylandPopups();
+
+ GtkWindow* parentGtkWindow = nullptr;
+-
+- if (IsMainMenuWindow()) {
+- // Remove and hide already closed popups from the
+- // gVisibleWaylandPopupWindows which were not yet been hidden.
+- CleanupWaylandPopups();
+- // Since the popups are shown by unknown order it can happen that child
+- // popup is shown before parent popup.
+- // We look for the current window parent in nsXULPopupManager since it
+- // always has correct popup hierarchy while gVisibleWaylandPopupWindows may
+- // not.
+- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+- AutoTArray<nsIWidget*, 5> widgetChain;
+- pm->GetSubmenuWidgetChain(&widgetChain);
+- for (unsigned long i = 0; i < widgetChain.Length() - 1; i++) {
+- unsigned long parentIndex = i + 1;
+- if (widgetChain.Length() > parentIndex && widgetChain[i] == this) {
+- nsWindow* parentWindow =
+- static_cast<nsWindow*>(widgetChain[parentIndex]);
+- parentGtkWindow = GTK_WINDOW(parentWindow->GetGtkWidget());
+- LOG((" [%p] Found %p as parent in nsXULPopupManager.", this,
+- parentWindow));
+- break;
+- }
+- }
+- } else {
+- // Panels usually ends there
+- if (gVisibleWaylandPopupWindows && HasRemoteContent()) {
+- // If the new panel is remote content, we need to close all other popups
+- // before to keep the correct hierarchy because the remote content popup
+- // can replace the overflow-widget panel.
+- HideWaylandOpenedPopups();
+- } else if (gVisibleWaylandPopupWindows) {
+- // If there is any remote content panel currently opened, close all
+- // opened popups to keep the correct hierarchy.
+- GList* popupList = gVisibleWaylandPopupWindows;
+- while (popupList) {
+- nsWindow* waylandWnd = static_cast<nsWindow*>(popupList->data);
+- LOG((" Checking [%p] IsRemoteContent %d\n", popupList->data,
+- waylandWnd->IsRemoteContent()));
+- if (waylandWnd->IsRemoteContent()) {
+- // close all popups including remote content before showing our panel
+- // Most likely returning from addon panel to overflow-widget.
+- HideWaylandOpenedPopups();
+- break;
+- }
+- popupList = popupList->next;
+- }
+- }
+- // For popups in panels use the last opened popup window as parent,
+- // panels are not stored in nsXULPopupManager.
+- if (gVisibleWaylandPopupWindows) {
+- nsWindow* parentWindow =
+- static_cast<nsWindow*>(gVisibleWaylandPopupWindows->data);
+- parentGtkWindow = GTK_WINDOW(parentWindow->GetGtkWidget());
+- }
+- }
++ if (HasRemoteContent() || IsWidgetOverflowWindow()) {
++ LOG(
++ (" Hiding all opened popups because the window is remote content or "
++ "overflow-widget"));
++ HideWaylandOpenedPopups();
++ }
++
++ parentGtkWindow = GetCurrentWindow();
+ if (parentGtkWindow) {
+ MOZ_ASSERT(parentGtkWindow != GTK_WINDOW(this->GetGtkWidget()),
+ "Cannot set self as parent");
+ gtk_window_set_transient_for(GTK_WINDOW(mShell),
+ GTK_WINDOW(parentGtkWindow));
+- } else {
+- // Fallback to the parent given in nsWindow::Create (most likely the
+- // toplevel window).
+- parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell));
+- LOG((" Setting parent from transient: %p [GtkWindow]\n", parentGtkWindow));
+- }
+- // Add current window to the visible popup list
+- gVisibleWaylandPopupWindows =
+- g_list_prepend(gVisibleWaylandPopupWindows, this);
+-
+- LOG((" Parent window for %p: %p [GtkWindow]", this, parentGtkWindow));
++ // Add current window to the visible popup list
++ gVisibleWaylandPopupWindows =
++ g_list_prepend(gVisibleWaylandPopupWindows, this);
++ LOG((" Parent window for %p: %p [GtkWindow]", this, parentGtkWindow));
++ }
++
++ MOZ_ASSERT(parentGtkWindow, "NO parent window for %p: expect popup glitches");
+ return GTK_WIDGET(parentGtkWindow);
+ }
+
+
diff --git a/mozilla-1609732-no-full-hide.patch b/mozilla-1609732-no-full-hide.patch
new file mode 100644
index 0000000..9894ed4
--- /dev/null
+++ b/mozilla-1609732-no-full-hide.patch
@@ -0,0 +1,60 @@
+diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
+--- a/widget/gtk/WindowSurfaceWayland.cpp
++++ b/widget/gtk/WindowSurfaceWayland.cpp
+@@ -805,6 +805,10 @@
+ mBufferCommitAllowed = false;
+
+ LayoutDeviceIntRect lockedScreenRect = mWindow->GetBounds();
++ // The window bounds of popup windows contains relative position to
++ // the transient window. We need to remove that effect because by changing
++ // position of the popup window the buffer has not changed its size.
++ lockedScreenRect.x = lockedScreenRect.y = 0;
+ gfx::IntRect lockSize = aRegion.GetBounds().ToUnknownRect();
+
+ bool isTransparentPopup =
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -1324,6 +1324,7 @@
+ // Fallback to the parent given in nsWindow::Create (most likely the
+ // toplevel window).
+ parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell));
++ LOG((" Setting parent from transient: %p [GtkWindow]\n", parentGtkWindow));
+ }
+ // Add current window to the visible popup list
+ gVisibleWaylandPopupWindows =
+@@ -1355,7 +1356,7 @@
+ mBounds.width, mBounds.height));
+
+ GtkWindow* parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell));
+- if (!parentGtkWindow) {
++ if (!parentGtkWindow || !GTK_IS_WIDGET(parentGtkWindow)) {
+ NS_WARNING("Popup has no parent!");
+ return;
+ }
+@@ -1431,8 +1432,13 @@
+ parentWindow));
+
+ int x_parent, y_parent;
+- gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentWindow)),
+- &x_parent, &y_parent);
++ if (parentWindow) {
++ gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentWindow)),
++ &x_parent, &y_parent);
++ } else {
++ NS_WARNING(("no parent window, this should not happen for popup!"));
++ x_parent = y_parent = 0;
++ }
+
+ GdkRectangle rect = {aPosition->x - x_parent, aPosition->y - y_parent, 1, 1};
+ if (aSize) {
+@@ -1470,7 +1476,7 @@
+ bool isWidgetVisible =
+ (sGtkWidgetIsVisible != nullptr) && sGtkWidgetIsVisible(mShell);
+ if (isWidgetVisible) {
+- HideWaylandWindow();
++ gtk_widget_hide(mShell);
+ }
+
+ LOG((" requested rect: x: %d y: %d width: %d height: %d\n", rect.x, rect.y,
+
diff --git a/mozilla-1609732-pause-renderer.patch b/mozilla-1609732-pause-renderer.patch
new file mode 100644
index 0000000..6f159e1
--- /dev/null
+++ b/mozilla-1609732-pause-renderer.patch
@@ -0,0 +1,73 @@
+diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
+--- a/widget/gtk/nsWindow.h
++++ b/widget/gtk/nsWindow.h
+@@ -681,6 +681,7 @@
+
+ bool IsMainMenuWindow();
+ GtkWidget* ConfigureWaylandPopupWindows();
++ void PauseRemoteRenderer();
+ void HideWaylandWindow();
+ void HideWaylandTooltips();
+ void HideWaylandPopupAndAllChildren();
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -1386,10 +1386,10 @@
+ }
+
+ if (needsPositionUpdate && needsSizeUpdate) {
+- Resize(newBounds.x, newBounds.y, newBounds.width, newBounds.height, true);
++ mBounds = newBounds;
+ NotifyWindowMoved(newBounds.x, newBounds.y);
+ } else if (needsPositionUpdate) {
+- Move(newBounds.x, newBounds.y);
++ mBounds = newBounds;
+ NotifyWindowMoved(newBounds.x, newBounds.y);
+ } else {
+ Resize(newBounds.width, newBounds.height, true);
+@@ -1476,6 +1476,7 @@
+ bool isWidgetVisible =
+ (sGtkWidgetIsVisible != nullptr) && sGtkWidgetIsVisible(mShell);
+ if (isWidgetVisible) {
++ PauseRemoteRenderer();
+ gtk_widget_hide(mShell);
+ }
+
+@@ -4497,16 +4498,8 @@
+ }
+ }
+
+-void nsWindow::HideWaylandWindow() {
++void nsWindow::PauseRemoteRenderer() {
+ #ifdef MOZ_WAYLAND
+- if (mWindowType == eWindowType_popup) {
+- LOG(("nsWindow::HideWaylandWindow: popup [%p]\n", this));
+- GList* foundWindow = g_list_find(gVisibleWaylandPopupWindows, this);
+- if (foundWindow) {
+- gVisibleWaylandPopupWindows =
+- g_list_delete_link(gVisibleWaylandPopupWindows, foundWindow);
+- }
+- }
+ if (!mIsDestroyed) {
+ if (mContainer && moz_container_has_wl_egl_window(mContainer)) {
+ // Because wl_egl_window is destroyed on moz_container_unmap(),
+@@ -4529,6 +4522,18 @@
+ }
+ }
+ #endif
++}
++
++void nsWindow::HideWaylandWindow() {
++ if (mWindowType == eWindowType_popup) {
++ LOG(("nsWindow::HideWaylandWindow: popup [%p]\n", this));
++ GList* foundWindow = g_list_find(gVisibleWaylandPopupWindows, this);
++ if (foundWindow) {
++ gVisibleWaylandPopupWindows =
++ g_list_delete_link(gVisibleWaylandPopupWindows, foundWindow);
++ }
++ }
++ PauseRemoteRenderer();
+ gtk_widget_hide(mShell);
+ }
+
+
bgstack15