Bug 1490297 Use parent window scale factor for the popup windows under Wayland; r=mattwoodrow
authorJan Horak <jhorak@redhat.com>
Thu, 20 Sep 2018 08:17:18 +0000
changeset 495878 c5b3caf36ddf3e451feef98e271fea2107af6811
parent 495877 705f3c3d5d60ed20c255fbe33d79e0fc8f1e4526
child 495879 8842e929c30f1b44945f1b58ca1a9777d66ef5eb
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1490297
milestone64.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 1490297 Use parent window scale factor for the popup windows under Wayland; r=mattwoodrow In the Wayland we don't know the absolute position of the window, so we cannot use it to determine on which monitor the window is. We need to use parent window scale factor to scale popup windows, otherwise popup windows will be wrongly placed in the hi+normal dpi monitor setup. Differential Revision: https://phabricator.services.mozilla.com/D5528
view/nsView.cpp
view/nsView.h
--- a/view/nsView.cpp
+++ b/view/nsView.cpp
@@ -229,16 +229,27 @@ bool nsView::IsEffectivelyVisible()
 {
   for (nsView* v = this; v; v = v->mParent) {
     if (v->GetVisibility() == nsViewVisibility_kHide)
       return false;
   }
   return true;
 }
 
+uint32_t nsView::GetParentWindowScaleFactor()
+{
+  uint32_t scaleFactor = 1;
+  nsIWidget* parentWidget =
+    GetParent() ? GetParent()->GetNearestWidget(nullptr) : nullptr;
+  if (parentWidget) {
+    scaleFactor = parentWidget->RoundsWidgetCoordinatesTo();
+  }
+  return scaleFactor;
+}
+
 LayoutDeviceIntRect nsView::CalcWidgetBounds(nsWindowType aType)
 {
   int32_t p2a = mViewManager->AppUnitsPerDevPixel();
 
   nsRect viewBounds(mDimBounds);
 
   nsView* parent = GetParent();
   nsIWidget* parentWidget = nullptr;
@@ -315,17 +326,19 @@ void nsView::DoResetWidgetBounds(bool aM
   MOZ_ASSERT(mWindow, "Why was this called??");
 
   // Hold this ref to make sure it stays alive.
   nsCOMPtr<nsIWidget> widget = mWindow;
 
   // Stash a copy of these and use them so we can handle this being deleted (say
   // from sync painting/flushing from Show/Move/Resize on the widget).
   LayoutDeviceIntRect newBounds;
+#if !defined(MOZ_WIDGET_GTK)
   RefPtr<nsDeviceContext> dx = mViewManager->GetDeviceContext();
+#endif
 
   nsWindowType type = widget->WindowType();
 
   LayoutDeviceIntRect curBounds = widget->GetClientBounds();
   bool invisiblePopup = type == eWindowType_popup &&
                         ((curBounds.IsEmpty() && mDimBounds.IsEmpty()) ||
                          mVis == nsViewVisibility_kHide);
 
@@ -355,17 +368,25 @@ void nsView::DoResetWidgetBounds(bool aM
   bool changedSize = curBounds.Size() != newBounds.Size();
 
   // Child views are never attached to top level widgets, this is safe.
 
   // Coordinates are converted to desktop pixels for window Move/Resize APIs,
   // because of the potential for device-pixel coordinate spaces for mixed
   // hidpi/lodpi screens to overlap each other and result in bad placement
   // (bug 814434).
+#if defined(MOZ_WIDGET_GTK)
+  // The GetDesktopToDeviceScale does not work under Wayland because we
+  // don't know the absolute position of the window in Wayland. We can
+  // use the same for X11, because it always returns 1 for both calls.
+  DesktopToLayoutDeviceScale scale = mozilla::DesktopToLayoutDeviceScale(
+    GetParentWindowScaleFactor());
+#else
   DesktopToLayoutDeviceScale scale = dx->GetDesktopToDeviceScale();
+#endif
 
   DesktopRect deskRect = newBounds / scale;
   if (changedPos) {
     if (changedSize && !aMoveOnly) {
       widget->ResizeClient(deskRect.X(), deskRect.Y(),
                            deskRect.Width(), deskRect.Height(),
                            aInvalidateChangedSize);
     } else {
--- a/view/nsView.h
+++ b/view/nsView.h
@@ -457,16 +457,19 @@ private:
 
   void ResetWidgetBounds(bool aRecurse, bool aForceSync);
   void AssertNoWindow();
 
   void NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible);
 
   // Update the cached RootViewManager for all view manager descendents.
   void InvalidateHierarchy();
+  // Return current scale factor of the monitor where the parent window of the popup
+  // is mostly located.
+  uint32_t GetParentWindowScaleFactor();
 
   nsViewManager    *mViewManager;
   nsView           *mParent;
   nsCOMPtr<nsIWidget> mWindow;
   nsCOMPtr<nsIWidget> mPreviousWindow;
   nsView           *mNextSibling;
   nsView           *mFirstChild;
   nsIFrame         *mFrame;