Blob Blame History Raw
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<nsWindow*>(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<nsIWidget*, 5> 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<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) {
@@ -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 =