diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -401,6 +401,8 @@ #ifdef MOZ_WAYLAND virtual nsresult GetScreenRect(LayoutDeviceIntRect* aRect) override; #endif + bool IsRemoteContent() { return HasRemoteContent(); } + static void HideWaylandOpenedPopups(); protected: virtual ~nsWindow(); diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -1165,6 +1165,14 @@ } } +void nsWindow::HideWaylandOpenedPopups() { + while (gVisibleWaylandPopupWindows) { + nsWindow* window = + static_cast(gVisibleWaylandPopupWindows->data); + window->HideWaylandWindow(); + } +} + // Hide popup nsWindows which are no longer in the nsXULPopupManager widget // chain list. void nsWindow::CleanupWaylandPopups() { @@ -1218,7 +1226,10 @@ // popup needs to have an unique parent. GtkWidget* nsWindow::ConfigureWaylandPopupWindows() { MOZ_ASSERT(this->mWindowType == eWindowType_popup); - LOG(("nsWindow::ConfigureWaylandPopupWindows [%p]\n", (void*)this)); + LOG( + ("nsWindow::ConfigureWaylandPopupWindows [%p], frame %p hasRemoteContent " + "%d\n", + (void*)this, this->GetFrame(), this->HasRemoteContent())); #if DEBUG if (this->GetFrame() && this->GetFrame()->GetContent()->GetID()) { nsCString nodeId; @@ -1245,14 +1256,14 @@ // 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. The + // 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 widgetChain; pm->GetSubmenuWidgetChain(&widgetChain); - for (unsigned long i = 0; i < widgetChain.Length(); i++) { + for (unsigned long i = 0; i < widgetChain.Length() - 1; i++) { unsigned long parentIndex = i + 1; if (widgetChain.Length() > parentIndex && widgetChain[i] == this) { nsWindow* parentWindow = @@ -1264,6 +1275,29 @@ } } } 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(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) { @@ -4380,6 +4414,7 @@ void nsWindow::HideWaylandWindow() { #ifdef MOZ_WAYLAND if (mWindowType == eWindowType_popup) { + LOG(("nsWindow::HideWaylandWindow: popup [%p]\n", this)); GList* foundWindow = g_list_find(gVisibleWaylandPopupWindows, this); if (foundWindow) { gVisibleWaylandPopupWindows =