Bug 1607404 - Update mBounds when gdk_window_move_to_rect returns different position/size; r=stransky
authorJan Horak <jhorak@redhat.com>
Wed, 15 Jan 2020 10:28:47 +0000
changeset 510333 f4bba00d59cef29deb745e608689e58d45b80394
parent 510332 39f34852842e1d58860156cba9bc05e8a133a27a
child 510334 dbd45b7bb4495f9d0cdb232ce959adfc2f895c34
push id37020
push userccoroiu@mozilla.com
push dateWed, 15 Jan 2020 21:36:21 +0000
treeherdermozilla-central@c35bb210b8ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstransky
bugs1607404
milestone74.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1607404 - Update mBounds when gdk_window_move_to_rect returns different position/size; r=stransky Differential Revision: https://phabricator.services.mozilla.com/D59845
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -1328,30 +1328,77 @@ GtkWidget* nsWindow::ConfigureWaylandPop
   // Add current window to the visible popup list
   gVisibleWaylandPopupWindows =
       g_list_prepend(gVisibleWaylandPopupWindows, this);
 
   LOG(("  Parent window for %p: %p [GtkWindow]", this, parentGtkWindow));
   return GTK_WIDGET(parentGtkWindow);
 }
 
-#ifdef DEBUG
 static void NativeMoveResizeWaylandPopupCallback(
     GdkWindow* window, const GdkRectangle* flipped_rect,
     const GdkRectangle* final_rect, gboolean flipped_x, gboolean flipped_y,
     void* aWindow) {
   LOG(("NativeMoveResizeWaylandPopupCallback [%p] flipped_x %d flipped_y %d\n",
        aWindow, flipped_x, flipped_y));
 
-  LOG(("  flipped_rect x: %d y: %d width: %d height: %d\n", flipped_rect->x,
+  LOG(("  flipped_rect x=%d y=%d width=%d height=%d\n", flipped_rect->x,
        flipped_rect->y, flipped_rect->width, flipped_rect->height));
-  LOG(("  final_rect x: %d y: %d width: %d height: %d\n", final_rect->x,
+  LOG(("  final_rect   x=%d y=%d width=%d height=%d\n", final_rect->x,
        final_rect->y, final_rect->width, final_rect->height));
-}
-#endif
+  nsWindow* wnd = get_window_for_gdk_window(window);
+
+  wnd->NativeMoveResizeWaylandPopupCB(final_rect, flipped_x, flipped_y);
+}
+
+void nsWindow::NativeMoveResizeWaylandPopupCB(const GdkRectangle* aFinalSize,
+                                              bool aFlippedX, bool aFlippedY) {
+  LOG(("  orig mBounds x=%d y=%d width=%d height=%d\n", mBounds.x, mBounds.y,
+       mBounds.width, mBounds.height));
+
+  GtkWindow* parentGtkWindow = gtk_window_get_transient_for(GTK_WINDOW(mShell));
+  if (!parentGtkWindow) {
+    NS_WARNING("Popup has no parent!");
+    return;
+  }
+
+  // The position of the menu in GTK is relative to it's parent window while
+  // in mBounds we have position relative to toplevel window. We need to check
+  // and update mBounds in the toplevel coordinates.
+  int x_parent, y_parent;
+  gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentGtkWindow)),
+                        &x_parent, &y_parent);
+
+  LayoutDeviceIntRect newBounds(aFinalSize->x + x_parent,
+                                aFinalSize->y + y_parent, aFinalSize->width,
+                                aFinalSize->height);
+
+  newBounds.Scale(nsWindow::GdkScaleFactor());
+  LOG(("  new mBounds  x=%d y=%d width=%d height=%d\n", newBounds.x,
+       newBounds.y, newBounds.width, newBounds.height));
+
+  bool needsPositionUpdate =
+      (newBounds.x != mBounds.x || newBounds.y != mBounds.y);
+  bool needsSizeUpdate =
+      (newBounds.width != mBounds.width || newBounds.height != mBounds.height);
+
+  if (!needsPositionUpdate && !needsSizeUpdate) {
+    return;
+  }
+
+  if (needsPositionUpdate && needsSizeUpdate) {
+    Resize(newBounds.x, newBounds.y, newBounds.width, newBounds.height, true);
+    NotifyWindowMoved(newBounds.x, newBounds.y);
+  } else if (needsPositionUpdate) {
+    Move(newBounds.x, newBounds.y);
+    NotifyWindowMoved(newBounds.x, newBounds.y);
+  } else {
+    Resize(newBounds.width, newBounds.height, true);
+  }
+}
 
 void nsWindow::NativeMoveResizeWaylandPopup(GdkPoint* aPosition,
                                             GdkRectangle* aSize) {
   // Available as of GTK 3.24+
   static auto sGdkWindowMoveToRect = (void (*)(
       GdkWindow*, const GdkRectangle*, GdkGravity, GdkGravity, GdkAnchorHints,
       gint, gint))dlsym(RTLD_DEFAULT, "gdk_window_move_to_rect");
   LOG(("nsWindow::NativeMoveResizeWaylandPopup [%p]\n", (void*)this));
@@ -1387,25 +1434,26 @@ void nsWindow::NativeMoveResizeWaylandPo
   gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(parentWindow)),
                         &x_parent, &y_parent);
 
   GdkRectangle rect = {aPosition->x - x_parent, aPosition->y - y_parent, 1, 1};
   if (aSize) {
     rect.width = aSize->width;
     rect.height = aSize->height;
   }
-
-#ifdef DEBUG
+  LOG(("  x_parent    %d   y_parent    %d\n", x_parent, y_parent));
+  LOG(("  aPosition x %d   aPosition y %d\n", aPosition->x, aPosition->y));
+  LOG(("  rect.x      %d   rect.y      %d\n", rect.x, rect.y));
+
   if (!g_signal_handler_find(
           gdkWindow, G_SIGNAL_MATCH_FUNC, 0, 0, nullptr,
           FuncToGpointer(NativeMoveResizeWaylandPopupCallback), this)) {
     g_signal_connect(gdkWindow, "moved-to-rect",
                      G_CALLBACK(NativeMoveResizeWaylandPopupCallback), this);
   }
-#endif
 
   GdkGravity rectAnchor = GDK_GRAVITY_NORTH_WEST;
   GdkGravity menuAnchor = GDK_GRAVITY_NORTH_WEST;
   if (GetTextDirection() == GTK_TEXT_DIR_RTL) {
     rectAnchor = GDK_GRAVITY_NORTH_EAST;
     menuAnchor = GDK_GRAVITY_NORTH_EAST;
   }
 
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -422,16 +422,18 @@ class nsWindow final : public nsBaseWidg
   static bool HideTitlebarByDefault();
   static bool GetTopLevelWindowActiveState(nsIFrame* aFrame);
   static bool TitlebarCanUseShapeMask();
 #ifdef MOZ_WAYLAND
   virtual nsresult GetScreenRect(LayoutDeviceIntRect* aRect) override;
 #endif
   bool IsRemoteContent() { return HasRemoteContent(); }
   static void HideWaylandOpenedPopups();
+  void NativeMoveResizeWaylandPopupCB(const GdkRectangle* aFinalSize,
+                                      bool aFlippedX, bool aFlippedY);
 
  protected:
   virtual ~nsWindow();
 
   // event handling code
   void DispatchActivateEvent(void);
   void DispatchDeactivateEvent(void);
   void DispatchResized();