kalev / rpms / firefox

Forked from rpms/firefox 5 years ago
Clone
Blob Blame History Raw
diff -up firefox-66.0.1/widget/gtk/nsWindow.cpp.mozilla-1539471 firefox-66.0.1/widget/gtk/nsWindow.cpp
--- firefox-66.0.1/widget/gtk/nsWindow.cpp.mozilla-1539471	2019-03-28 14:08:42.351128620 +0100
+++ firefox-66.0.1/widget/gtk/nsWindow.cpp	2019-03-28 14:20:23.282890178 +0100
@@ -312,6 +312,9 @@ static nsWindow *gFocusWindow = nullptr;
 static bool gBlockActivateEvent = false;
 static bool gGlobalsInitialized = false;
 static bool gRaiseWindows = true;
+#ifdef MOZ_WAYLAND
+static GList *gCurrentPopupWindows = nullptr;
+#endif
 
 #if GTK_CHECK_VERSION(3, 4, 0)
 static uint32_t gLastTouchID = 0;
@@ -1136,8 +1139,16 @@ void nsWindow::NativeMoveResizeWaylandPo
     return;
   }
 
-  GtkWidget* parentWidget =
-    GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
+  GtkWidget *parentWidget;
+  if (mPopupType == ePopupTypeTooltip && gCurrentPopupWindows) {
+    // Attach tooltip window to the latest popup window
+    // to have both visible.
+    parentWidget = GTK_WIDGET(gCurrentPopupWindows->data);
+    gtk_window_set_transient_for(GTK_WINDOW(mShell),
+                                 GTK_WINDOW(parentWidget));
+  } else {
+    parentWidget = GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
+  }
 
   int x_parent, y_parent;
   gdk_window_get_origin(gtk_widget_get_window(parentWidget), &x_parent, &y_parent);
@@ -3489,7 +3500,7 @@ nsresult nsWindow::Create(nsIWidget *aPa
           gtkTypeHint = GDK_WINDOW_TYPE_HINT_DND;
           mIsDragPopup = true;
         } else {
-          switch (aInitData->mPopupHint) {
+          switch (mPopupType) {
             case ePopupTypeMenu:
               gtkTypeHint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
               break;
@@ -3610,6 +3621,8 @@ nsresult nsWindow::Create(nsIWidget *aPa
       return NS_ERROR_FAILURE;
 
     case eWindowType_child: {
+      MOZ_ASSERT(mIsX11Display,
+        "eWindowType_child is not supported on Wayland!");
       if (parentMozContainer) {
         mGdkWindow = CreateGdkWindow(parentGdkWindow, parentMozContainer);
         mHasMappedToplevel = parentnsWindow->mHasMappedToplevel;
@@ -3979,6 +3992,49 @@ void nsWindow::NativeMoveResize() {
   }
 }
 
+#ifdef MOZ_WAYLAND
+void nsWindow::OpenToplevelWaylandWindow() {
+  // 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
+  // popup needs to have an unique parent.
+  if (mWindowType == eWindowType_popup) {
+    GtkWidget *parentWidget =
+        GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(mShell)));
+
+    if (gCurrentPopupWindows) {
+      do {
+        GtkWidget *widget = GTK_WIDGET(gCurrentPopupWindows->data);
+        if (widget == parentWidget) {
+          break;
+        }
+        nsWindow* window = get_window_for_gtk_widget(widget);
+        NS_ASSERTION(window, "Unknown window in popup widget list!");
+        window->CloseToplevelWaylandWindow();
+
+      } while (gCurrentPopupWindows != nullptr);
+    }
+    gCurrentPopupWindows = g_list_prepend(gCurrentPopupWindows, mShell);
+  }
+
+  gtk_widget_show(mShell);
+}
+
+void nsWindow::CloseToplevelWaylandWindow() {
+  if (mContainer && moz_container_has_wl_egl_window(mContainer)) {
+    // Because wl_egl_window is destroyed on moz_container_unmap(),
+    // the current compositor cannot use it anymore. To avoid crash,
+    // destroy the compositor & recreate a new compositor on next
+    // expose event.
+    DestroyLayerManager();
+  }
+  if (mWindowType == eWindowType_popup) {
+    gCurrentPopupWindows = g_list_remove(gCurrentPopupWindows, mShell);
+  }
+  gtk_widget_hide(mShell);
+}
+#endif
+
 void nsWindow::NativeShow(bool aAction) {
   if (aAction) {
     // unset our flag now that our window has been shown
@@ -3990,51 +4046,55 @@ void nsWindow::NativeShow(bool aAction)
         SetUserTimeAndStartupIDForActivatedWindow(mShell);
       }
 
-      gtk_widget_show(mShell);
+#ifdef MOZ_WAYLAND
+      if (!mIsX11Display) {
+        OpenToplevelWaylandWindow();
+      } else
+#endif
+      {
+        gtk_widget_show(mShell);
+      }
     } else if (mContainer) {
       gtk_widget_show(GTK_WIDGET(mContainer));
     } else if (mGdkWindow) {
       gdk_window_show_unraised(mGdkWindow);
     }
   } else {
-#ifdef MOZ_WAYLAND
-    if (mContainer && moz_container_has_wl_egl_window(mContainer)) {
-      // Because wl_egl_window is destroyed on moz_container_unmap(),
-      // the current compositor cannot use it anymore. To avoid crash,
-      // destroy the compositor & recreate a new compositor on next
-      // expose event.
-      DestroyLayerManager();
-    }
-#endif
-
     if (mIsTopLevel) {
-      // Workaround window freezes on GTK versions before 3.21.2 by
-      // ensuring that configure events get dispatched to windows before
-      // they are unmapped. See bug 1225044.
-      if (gtk_check_version(3, 21, 2) != nullptr && mPendingConfigures > 0) {
-        GtkAllocation allocation;
-        gtk_widget_get_allocation(GTK_WIDGET(mShell), &allocation);
-
-        GdkEventConfigure event;
-        PodZero(&event);
-        event.type = GDK_CONFIGURE;
-        event.window = mGdkWindow;
-        event.send_event = TRUE;
-        event.x = allocation.x;
-        event.y = allocation.y;
-        event.width = allocation.width;
-        event.height = allocation.height;
-
-        auto shellClass = GTK_WIDGET_GET_CLASS(mShell);
-        for (unsigned int i = 0; i < mPendingConfigures; i++) {
-          Unused << shellClass->configure_event(mShell, &event);
+#ifdef MOZ_WAYLAND
+      if (!mIsX11Display) {
+        CloseToplevelWaylandWindow();
+      } else
+#endif
+      {
+        // Workaround window freezes on GTK versions before 3.21.2 by
+        // ensuring that configure events get dispatched to windows before
+        // they are unmapped. See bug 1225044.
+        if (gtk_check_version(3, 21, 2) != nullptr && mPendingConfigures > 0) {
+          GtkAllocation allocation;
+          gtk_widget_get_allocation(GTK_WIDGET(mShell), &allocation);
+
+          GdkEventConfigure event;
+          PodZero(&event);
+          event.type = GDK_CONFIGURE;
+          event.window = mGdkWindow;
+          event.send_event = TRUE;
+          event.x = allocation.x;
+          event.y = allocation.y;
+          event.width = allocation.width;
+          event.height = allocation.height;
+
+          auto shellClass = GTK_WIDGET_GET_CLASS(mShell);
+          for (unsigned int i = 0; i < mPendingConfigures; i++) {
+            Unused << shellClass->configure_event(mShell, &event);
+          }
+          mPendingConfigures = 0;
         }
-        mPendingConfigures = 0;
-      }
 
-      gtk_widget_hide(mShell);
+        gtk_widget_hide(mShell);
 
-      ClearTransparencyBitmap();  // Release some resources
+        ClearTransparencyBitmap();  // Release some resources
+      }
     } else if (mContainer) {
       gtk_widget_hide(GTK_WIDGET(mContainer));
     } else if (mGdkWindow) {
diff -up firefox-66.0.1/widget/gtk/nsWindow.h.mozilla-1539471 firefox-66.0.1/widget/gtk/nsWindow.h
--- firefox-66.0.1/widget/gtk/nsWindow.h.mozilla-1539471	2019-03-28 14:08:42.345128639 +0100
+++ firefox-66.0.1/widget/gtk/nsWindow.h	2019-03-28 14:08:42.355128607 +0100
@@ -603,6 +603,11 @@ class nsWindow final : public nsBaseWidg
 
   void ForceTitlebarRedraw();
 
+#ifdef MOZ_WAYLAND
+  void OpenToplevelWaylandWindow();
+  void CloseToplevelWaylandWindow();
+#endif
+
   /**
    * |mIMContext| takes all IME related stuff.
    *