diff options
-rw-r--r-- | firefox-mozconfig | 6 | ||||
-rw-r--r-- | firefox.spec | 6 | ||||
-rw-r--r-- | mozilla-1605795-popup-parent-fix.patch | 231 | ||||
-rw-r--r-- | mozilla-1609732-no-full-hide.patch | 60 | ||||
-rw-r--r-- | mozilla-1609732-pause-renderer.patch | 73 |
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); + } + + |