bug 794038 pt 1.0 - use global display pixel coordinates to persist and restore XUL window position and size. r=roc
authorJonathan Kew <jkew@mozilla.com>
Tue, 16 Oct 2012 20:41:19 +0100
changeset 110460 4120e702e25bc06052fc984a0cef151f87ddaa3d
parent 110459 5ec67c1dd2e1d5b737a60a8118034e40171dfc5b
child 110461 b0be2ef452df5e18259c9ecba2870ff0e3e8c3ca
push id1157
push userphilringnalda@gmail.com
push dateSat, 20 Oct 2012 05:15:32 +0000
treeherderfx-team@0c34dd4742b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs794038
milestone19.0a1
bug 794038 pt 1.0 - use global display pixel coordinates to persist and restore XUL window position and size. r=roc
layout/xul/base/src/nsResizerFrame.cpp
widget/cocoa/nsCocoaWindow.mm
widget/cocoa/nsScreenCocoa.h
widget/cocoa/nsScreenCocoa.mm
widget/nsIScreen.idl
widget/xpwidgets/nsBaseScreen.cpp
widget/xpwidgets/nsBaseScreen.h
widget/xpwidgets/nsBaseWidget.cpp
xpfe/appshell/src/nsWebShellWindow.cpp
xpfe/appshell/src/nsXULWindow.cpp
xpfe/appshell/src/nsXULWindow.h
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -203,17 +203,22 @@ nsResizerFrame::HandleEvent(nsPresContex
 
       // Don't allow resizing a window or a popup past the edge of the screen,
       // so adjust the rectangle to fit within the available screen area.
       if (window) {
         nsCOMPtr<nsIScreen> screen;
         nsCOMPtr<nsIScreenManager> sm(do_GetService("@mozilla.org/gfx/screenmanager;1"));
         if (sm) {
           nsIntRect frameRect = GetScreenRect();
-          sm->ScreenForRect(frameRect.x, frameRect.y, 1, 1, getter_AddRefs(screen));
+          // ScreenForRect requires display pixels, so scale from device pix
+          double scale;
+          window->GetUnscaledDevicePixelsPerCSSPixel(&scale);
+          sm->ScreenForRect(NSToIntRound(frameRect.x / scale),
+                            NSToIntRound(frameRect.y / scale), 1, 1,
+                            getter_AddRefs(screen));
           if (screen) {
             nsIntRect screenRect;
             screen->GetRect(&screenRect.x, &screenRect.y,
                             &screenRect.width, &screenRect.height);
             rect.IntersectRect(rect, screenRect);
           }
         }
       }
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -1018,55 +1018,58 @@ NS_IMETHODIMP nsCocoaWindow::ConstrainPo
                                                int32_t *aX, int32_t *aY)
 {
   if (!mWindow || ![mWindow screen]) {
     return NS_OK;
   }
 
   nsIntRect screenBounds;
 
+  int32_t width, height;
+
+  NSRect frame = [mWindow frame];
+
+  // zero size rects confuse the screen manager
+  width = NS_MAX<int32_t>(frame.size.width, 1);
+  height = NS_MAX<int32_t>(frame.size.height, 1);
+
   nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
   if (screenMgr) {
     nsCOMPtr<nsIScreen> screen;
-    int32_t width, height;
-
-    // zero size rects confuse the screen manager
-    width = mBounds.width > 0 ? mBounds.width : 1;
-    height = mBounds.height > 0 ? mBounds.height : 1;
     screenMgr->ScreenForRect(*aX, *aY, width, height, getter_AddRefs(screen));
 
     if (screen) {
-      screen->GetRect(&(screenBounds.x), &(screenBounds.y),
-                      &(screenBounds.width), &(screenBounds.height));
+      screen->GetRectDisplayPix(&(screenBounds.x), &(screenBounds.y),
+                                &(screenBounds.width), &(screenBounds.height));
     }
   }
 
   if (aAllowSlop) {
-    if (*aX < screenBounds.x - mBounds.width + kWindowPositionSlop) {
-      *aX = screenBounds.x - mBounds.width + kWindowPositionSlop;
+    if (*aX < screenBounds.x - width + kWindowPositionSlop) {
+      *aX = screenBounds.x - width + kWindowPositionSlop;
     } else if (*aX >= screenBounds.x + screenBounds.width - kWindowPositionSlop) {
       *aX = screenBounds.x + screenBounds.width - kWindowPositionSlop;
     }
 
-    if (*aY < screenBounds.y - mBounds.height + kWindowPositionSlop) {
-      *aY = screenBounds.y - mBounds.height + kWindowPositionSlop;
+    if (*aY < screenBounds.y - height + kWindowPositionSlop) {
+      *aY = screenBounds.y - height + kWindowPositionSlop;
     } else if (*aY >= screenBounds.y + screenBounds.height - kWindowPositionSlop) {
       *aY = screenBounds.y + screenBounds.height - kWindowPositionSlop;
     }
   } else {
     if (*aX < screenBounds.x) {
       *aX = screenBounds.x;
-    } else if (*aX >= screenBounds.x + screenBounds.width - mBounds.width) {
-      *aX = screenBounds.x + screenBounds.width - mBounds.width;
+    } else if (*aX >= screenBounds.x + screenBounds.width - width) {
+      *aX = screenBounds.x + screenBounds.width - width;
     }
 
     if (*aY < screenBounds.y) {
       *aY = screenBounds.y;
-    } else if (*aY >= screenBounds.y + screenBounds.height - mBounds.height) {
-      *aY = screenBounds.y + screenBounds.height - mBounds.height;
+    } else if (*aY >= screenBounds.y + screenBounds.height - height) {
+      *aY = screenBounds.y + screenBounds.height - height;
     }
   }
 
   return NS_OK;
 }
 
 void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints)
 {
--- a/widget/cocoa/nsScreenCocoa.h
+++ b/widget/cocoa/nsScreenCocoa.h
@@ -13,16 +13,18 @@
 class nsScreenCocoa : public nsBaseScreen
 {
 public:
     nsScreenCocoa (NSScreen *screen);
     ~nsScreenCocoa ();
 
     NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
     NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
+    NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
+    NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
     NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth);
     NS_IMETHOD GetColorDepth(int32_t* aColorDepth);
     NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor);
 
     NSScreen *CocoaScreen() { return mScreen; }
 
 private:
     CGFloat BackingScaleFactor();
--- a/widget/cocoa/nsScreenCocoa.mm
+++ b/widget/cocoa/nsScreenCocoa.mm
@@ -51,16 +51,46 @@ nsScreenCocoa::GetAvailRect(int32_t *out
   *outY = r.y;
   *outWidth = r.width;
   *outHeight = r.height;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsScreenCocoa::GetRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight)
+{
+  NSRect frame = [mScreen frame];
+
+  nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame);
+
+  *outX = r.x;
+  *outY = r.y;
+  *outWidth = r.width;
+  *outHeight = r.height;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScreenCocoa::GetAvailRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight)
+{
+  NSRect frame = [mScreen visibleFrame];
+
+  nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame);
+
+  *outX = r.x;
+  *outY = r.y;
+  *outWidth = r.width;
+  *outHeight = r.height;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsScreenCocoa::GetPixelDepth(int32_t *aPixelDepth)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   NSWindowDepth depth = [mScreen depth];
   int bpp = NSBitsPerPixelFromDepth(depth);
 
   *aPixelDepth = bpp;
--- a/widget/nsIScreen.idl
+++ b/widget/nsIScreen.idl
@@ -24,20 +24,29 @@ interface nsIScreen : nsISupports
    *
    * ROTATION_0_DEG is the default, unrotated configuration.
    */
   const unsigned long   ROTATION_0_DEG = 0;
   const unsigned long  ROTATION_90_DEG = 1;
   const unsigned long ROTATION_180_DEG = 2;
   const unsigned long ROTATION_270_DEG = 3;
 
+  /**
+   * These report screen dimensions in (screen-specific) device pixels
+   */
   void GetRect(out long left, out long top, out long width, out long height);
   void GetAvailRect(out long left, out long top, out long width, out long height);
 
   /**
+   * And these report in global display pixels
+   */
+  void GetRectDisplayPix(out long left, out long top, out long width, out long height);
+  void GetAvailRectDisplayPix(out long left, out long top, out long width, out long height);
+
+  /**
    * Locks the minimum brightness of the screen, forcing it to be at
    * least as bright as a certain brightness level. Each call to this
    * function must eventually be followed by a corresponding call to
    * unlockMinimumBrightness, with the same brightness level.
    *
    * @param brightness A brightness level, one of the above constants.
    */
   void lockMinimumBrightness(in unsigned long brightness);
--- a/widget/xpwidgets/nsBaseScreen.cpp
+++ b/widget/xpwidgets/nsBaseScreen.cpp
@@ -15,16 +15,30 @@ nsBaseScreen::nsBaseScreen()
 {
   for (uint32_t i = 0; i < nsIScreen::BRIGHTNESS_LEVELS; i++)
     mBrightnessLocks[i] = 0;
 }
 
 nsBaseScreen::~nsBaseScreen() { }
 
 NS_IMETHODIMP
+nsBaseScreen::GetRectDisplayPix(int32_t *outLeft,  int32_t *outTop,
+                                int32_t *outWidth, int32_t *outHeight)
+{
+  return GetRect(outLeft, outTop, outWidth, outHeight);
+}
+
+NS_IMETHODIMP
+nsBaseScreen::GetAvailRectDisplayPix(int32_t *outLeft,  int32_t *outTop,
+                                     int32_t *outWidth, int32_t *outHeight)
+{
+  return GetAvailRect(outLeft, outTop, outWidth, outHeight);
+}
+
+NS_IMETHODIMP
 nsBaseScreen::LockMinimumBrightness(uint32_t aBrightness)
 {
   NS_ABORT_IF_FALSE(
     aBrightness < nsIScreen::BRIGHTNESS_LEVELS,
     "Invalid brightness level to lock");
   mBrightnessLocks[aBrightness]++;
   NS_ABORT_IF_FALSE(mBrightnessLocks[aBrightness] > 0,
     "Overflow after locking brightness level");
--- a/widget/xpwidgets/nsBaseScreen.h
+++ b/widget/xpwidgets/nsBaseScreen.h
@@ -16,16 +16,24 @@ class nsBaseScreen : public nsIScreen
 public:
   nsBaseScreen();
   virtual ~nsBaseScreen();
   
   NS_DECL_ISUPPORTS
 
   // nsIScreen interface
 
+  // These simply forward to the device-pixel versions;
+  // implementations where global display pixels may not correspond
+  // to per-screen device pixels must override.
+  NS_IMETHOD GetRectDisplayPix(int32_t *outLeft,  int32_t *outTop,
+                               int32_t *outWidth, int32_t *outHeight);
+  NS_IMETHOD GetAvailRectDisplayPix(int32_t *outLeft,  int32_t *outTop,
+                                    int32_t *outWidth, int32_t *outHeight);
+
   /**
    * Simple management of screen brightness locks. This abstract base class
    * allows all widget implementations to share brightness locking code.
    */
   NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness);
   NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness);
 
   NS_IMETHOD GetRotation(uint32_t* aRotation) {
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -687,18 +687,22 @@ NS_IMETHODIMP nsBaseWidget::MakeFullScre
     GetScreenBounds(*mOriginalBounds);
 
     // Move to top-left corner of screen and size to the screen dimensions
     nsCOMPtr<nsIScreenManager> screenManager;
     screenManager = do_GetService("@mozilla.org/gfx/screenmanager;1"); 
     NS_ASSERTION(screenManager, "Unable to grab screenManager.");
     if (screenManager) {
       nsCOMPtr<nsIScreen> screen;
-      screenManager->ScreenForRect(mOriginalBounds->x, mOriginalBounds->y,
-                                   mOriginalBounds->width, mOriginalBounds->height,
+      // convert dev pix to display/CSS pix for ScreenForRect
+      double scale = GetDefaultScale();
+      screenManager->ScreenForRect(mOriginalBounds->x / scale,
+                                   mOriginalBounds->y / scale,
+                                   mOriginalBounds->width / scale,
+                                   mOriginalBounds->height / scale,
                                    getter_AddRefs(screen));
       if (screen) {
         int32_t left, top, width, height;
         if (NS_SUCCEEDED(screen->GetRect(&left, &top, &width, &height))) {
           Resize(left, top, width, height, true);
         }
       }
     }
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -122,16 +122,23 @@ nsresult nsWebShellWindow::Initialize(ns
   if (base) {
     rv = base->GetPositionAndSize(&mOpenerScreenRect.x,
                                   &mOpenerScreenRect.y,
                                   &mOpenerScreenRect.width,
                                   &mOpenerScreenRect.height);
     if (NS_FAILED(rv)) {
       mOpenerScreenRect.SetEmpty();
     } else {
+      double scale;
+      if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
+        mOpenerScreenRect.x = NSToIntRound(mOpenerScreenRect.x / scale);
+        mOpenerScreenRect.y = NSToIntRound(mOpenerScreenRect.y / scale);
+        mOpenerScreenRect.width = NSToIntRound(mOpenerScreenRect.width / scale);
+        mOpenerScreenRect.height = NSToIntRound(mOpenerScreenRect.height / scale);
+      }
       initialX = mOpenerScreenRect.x;
       initialY = mOpenerScreenRect.y;
       ConstrainToOpenerScreen(&initialX, &initialY);
     }
   }
 
   // XXX: need to get the default window size from prefs...
   // Doesn't come from prefs... will come from CSS/XUL/RDF
@@ -713,17 +720,17 @@ void nsWebShellWindow::ConstrainToOpener
   // Constrain initial positions to the same screen as opener
   nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
   if (screenmgr) {
     nsCOMPtr<nsIScreen> screen;
     screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
                              mOpenerScreenRect.width, mOpenerScreenRect.height,
                              getter_AddRefs(screen));
     if (screen) {
-      screen->GetAvailRect(&left, &top, &width, &height);
+      screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
       if (*aX < left || *aX > left + width) {
         *aX = left;
       }
       if (*aY < top || *aY > top + height) {
         *aY = top;
       }
     }
   }
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -68,31 +68,16 @@ using namespace mozilla;
 #define PERSIST_ATTRIBUTE  NS_LITERAL_STRING("persist")
 #define SCREENX_ATTRIBUTE  NS_LITERAL_STRING("screenX")
 #define SCREENY_ATTRIBUTE  NS_LITERAL_STRING("screenY")
 #define WIDTH_ATTRIBUTE    NS_LITERAL_STRING("width")
 #define HEIGHT_ATTRIBUTE   NS_LITERAL_STRING("height")
 #define MODE_ATTRIBUTE     NS_LITERAL_STRING("sizemode")
 #define ZLEVEL_ATTRIBUTE   NS_LITERAL_STRING("zlevel")
 
-// Unit conversion helpers
-static int32_t
-CSSToDevPixels(int32_t aPixels, int32_t aAppPerDev)
-{
-  return NSAppUnitsToIntPixels(nsPresContext::CSSPixelsToAppUnits(aPixels),
-                               aAppPerDev);
-}
-
-static int32_t
-DevToCSSPixels(int32_t aPixels, int32_t aAppPerDev)
-{
-  return nsPresContext::AppUnitsToIntCSSPixels(
-    NSIntPixelsToAppUnits(aPixels, aAppPerDev));
-}
-
 
 //*****************************************************************************
 //***    nsXULWindow: Object Management
 //*****************************************************************************
 
 nsXULWindow::nsXULWindow(uint32_t aChromeFlags)
   : mChromeTreeOwner(nullptr), 
     mContentTreeOwner(nullptr),
@@ -108,19 +93,17 @@ nsXULWindow::nsXULWindow(uint32_t aChrom
     mLockedUntilChromeLoad(false),
     mIgnoreXULSize(false),
     mIgnoreXULPosition(false),
     mChromeFlagsFrozen(false),
     mIgnoreXULSizeMode(false),
     mContextFlags(0),
     mPersistentAttributesDirty(0),
     mPersistentAttributesMask(0),
-    mChromeFlags(aChromeFlags),
-    // best guess till we have a widget
-    mAppPerDev(nsPresContext::AppUnitsPerCSSPixel())
+    mChromeFlags(aChromeFlags)
 {
 }
 
 nsXULWindow::~nsXULWindow()
 {
   Destroy();
 }
 
@@ -657,51 +640,65 @@ NS_IMETHODIMP nsXULWindow::Center(nsIXUL
   nsCOMPtr<nsIScreen> screen;
 
   if (aRelative) {
     nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aRelative, &result));
     if (base) {
       // get window rect
       result = base->GetPositionAndSize(&left, &top, &width, &height);
       if (NS_SUCCEEDED(result)) {
+        double scale;
+        if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
+          // convert device-pixel coordinates to global display pixels
+          left = NSToIntRound(left / scale);
+          top = NSToIntRound(top / scale);
+          width = NSToIntRound(width / scale);
+          height = NSToIntRound(height / scale);
+        }
         // if centering on screen, convert that to the corresponding screen
         if (aScreen)
           screenmgr->ScreenForRect(left, top, width, height, getter_AddRefs(screen));
         else
           windowCoordinates = true;
       } else {
         // something's wrong with the reference window.
         // fall back to the primary screen
         aRelative = 0;
         aScreen = true;
       }
     }
   }
   if (!aRelative) {
     if (!mOpenerScreenRect.IsEmpty()) {
+      // FIXME - check if these are device or display pixels
       screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
                                mOpenerScreenRect.width, mOpenerScreenRect.height,
                                getter_AddRefs(screen));
     } else {
       screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
     }
   }
 
   if (aScreen && screen) {
-    screen->GetAvailRect(&left, &top, &width, &height);
+    screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
     screenCoordinates = true;
   }
 
   if (screenCoordinates || windowCoordinates) {
+    NS_ASSERTION(mWindow, "what, no window?");
+    double scale = mWindow->GetDefaultScale();
     GetSize(&ourWidth, &ourHeight);
+    ourWidth = NSToIntRound(ourWidth / scale);
+    ourHeight = NSToIntRound(ourHeight / scale);
     left += (width - ourWidth) / 2;
     top += (height - ourHeight) / (aAlert ? 3 : 2);
-    if (windowCoordinates)
+    if (windowCoordinates) {
       mWindow->ConstrainPosition(false, &left, &top);
-    SetPosition(left, top);
+    }
+    SetPosition(left * scale, top * scale);
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP nsXULWindow::Repaint(bool aForce)
 {
   //XXX First Check In
@@ -1017,56 +1014,70 @@ bool nsXULWindow::LoadPositionFromXUL()
   int32_t currY = 0;
   int32_t currWidth = 0;
   int32_t currHeight = 0;
   nsresult errorCode;
   int32_t temp;
 
   GetPositionAndSize(&currX, &currY, &currWidth, &currHeight);
 
+  // Convert to global display pixels for consistent window management across
+  // screens with diverse resolutions
+  double scale = mWindow->GetDefaultScale();
+  currX = NSToIntRound(currX / scale);
+  currY = NSToIntRound(currY / scale);
+  currWidth = NSToIntRound(currWidth / scale);
+  currHeight = NSToIntRound(currHeight / scale);
+
   // Obtain the position information from the <xul:window> element.
   int32_t specX = currX;
   int32_t specY = currY;
   nsAutoString posString;
-  int32_t appPerDev = AppUnitsPerDevPixel();
 
   rv = windowElement->GetAttribute(SCREENX_ATTRIBUTE, posString);
   if (NS_SUCCEEDED(rv)) {
     temp = posString.ToInteger(&errorCode);
     if (NS_SUCCEEDED(errorCode)) {
-      specX = CSSToDevPixels(temp, appPerDev);
+      specX = temp;
       gotPosition = true;
     }
   }
   rv = windowElement->GetAttribute(SCREENY_ATTRIBUTE, posString);
   if (NS_SUCCEEDED(rv)) {
     temp = posString.ToInteger(&errorCode);
     if (NS_SUCCEEDED(errorCode)) {
-      specY = CSSToDevPixels(temp, appPerDev);
+      specY = temp;
       gotPosition = true;
     }
   }
     
   if (gotPosition) {
     // our position will be relative to our parent, if any
     nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
     if (parent) {
       int32_t parentX, parentY;
       if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
+        double scale;
+        if (NS_SUCCEEDED(parent->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
+          parentX = NSToIntRound(parentX / scale);
+          parentY = NSToIntRound(parentY / scale);
+        }
         specX += parentX;
         specY += parentY;
       }
     }
     else {
       StaggerPosition(specX, specY, currWidth, currHeight);
     }
   }
   mWindow->ConstrainPosition(false, &specX, &specY);
-  if (specX != currX || specY != currY)
-    SetPosition(specX, specY);
+  if (specX != currX || specY != currY) {
+    double scale = mWindow->GetDefaultScale();
+    SetPosition(specX * scale, specY * scale);
+  }
 
   return gotPosition;
 }
 
 bool nsXULWindow::LoadSizeFromXUL()
 {
   nsresult rv;
   bool     gotSize = false;
@@ -1079,65 +1090,69 @@ bool nsXULWindow::LoadSizeFromXUL()
   nsCOMPtr<nsIDOMElement> windowElement = GetWindowDOMElement();
   NS_ENSURE_TRUE(windowElement, false);
 
   int32_t currWidth = 0;
   int32_t currHeight = 0;
   nsresult errorCode;
   int32_t temp;
 
+  NS_ASSERTION(mWindow, "we expected to have a window already");
+
+  double scale = mWindow ? mWindow->GetDefaultScale() : 1.0;
   GetSize(&currWidth, &currHeight);
+  currWidth = NSToIntRound(currWidth / scale);
+  currHeight = NSToIntRound(currHeight / scale);
 
   // Obtain the position and sizing information from the <xul:window> element.
   int32_t specWidth = currWidth;
   int32_t specHeight = currHeight;
   nsAutoString sizeString;
-  int32_t appPerDev = AppUnitsPerDevPixel();
 
   rv = windowElement->GetAttribute(WIDTH_ATTRIBUTE, sizeString);
   if (NS_SUCCEEDED(rv)) {
     temp = sizeString.ToInteger(&errorCode);
     if (NS_SUCCEEDED(errorCode) && temp > 0) {
-      specWidth = CSSToDevPixels(NS_MAX(temp, 100), appPerDev);
+      specWidth = NS_MAX(temp, 100);
       gotSize = true;
     }
   }
   rv = windowElement->GetAttribute(HEIGHT_ATTRIBUTE, sizeString);
   if (NS_SUCCEEDED(rv)) {
     temp = sizeString.ToInteger(&errorCode);
     if (NS_SUCCEEDED(errorCode) && temp > 0) {
-      specHeight = CSSToDevPixels(NS_MAX(temp, 100), appPerDev);
+      specHeight = NS_MAX(temp, 100);
       gotSize = true;
     }
   }
 
   if (gotSize) {
     // constrain to screen size
     nsCOMPtr<nsIDOMWindow> domWindow;
     GetWindowDOMWindow(getter_AddRefs(domWindow));
     if (domWindow) {
       nsCOMPtr<nsIDOMScreen> screen;
       domWindow->GetScreen(getter_AddRefs(screen));
       if (screen) {
         int32_t screenWidth;
         int32_t screenHeight;
         screen->GetAvailWidth(&screenWidth);
         screen->GetAvailHeight(&screenHeight);
-        screenWidth = CSSToDevPixels(screenWidth, appPerDev);
-        screenHeight = CSSToDevPixels(screenHeight, appPerDev);
         if (specWidth > screenWidth)
           specWidth = screenWidth;
         if (specHeight > screenHeight)
           specHeight = screenHeight;
       }
     }
 
     mIntrinsicallySized = false;
-    if (specWidth != currWidth || specHeight != currHeight)
-      SetSize(specWidth, specHeight, false);
+    if (specWidth != currWidth || specHeight != currHeight) {
+      double scale = mWindow->GetDefaultScale();
+      SetSize(specWidth * scale, specHeight * scale, false);
+    }
   }
 
   return gotSize;
 }
 
 /* Miscellaneous persistent attributes are attributes named in the
    |persist| attribute, other than size and position. Those are special
    because it's important to load those before one of the misc
@@ -1222,19 +1237,18 @@ bool nsXULWindow::LoadMiscPersistentAttr
 /* Stagger windows of the same type so they don't appear on top of each other.
    This code does have a scary double loop -- it'll keep passing through
    the entire list of open windows until it finds a non-collision. Doesn't
    seem to be a problem, but it deserves watching.
 */
 void nsXULWindow::StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY,
                                   int32_t aSpecWidth, int32_t aSpecHeight)
 {
-  const int32_t appPerDev = AppUnitsPerDevPixel();
-  const int32_t kOffset = CSSToDevPixels(22, appPerDev);
-  const int32_t kSlop   = CSSToDevPixels(4, appPerDev);
+  const int32_t kOffset = 22;
+  const int32_t kSlop   = 4;
 
   nsresult rv;
   bool     keepTrying;
   int      bouncedX = 0, // bounced off vertical edge of screen
            bouncedY = 0; // bounced off horizontal edge
 
   // look for any other windows of this type
   nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
@@ -1258,23 +1272,24 @@ void nsXULWindow::StaggerPosition(int32_
           screenLeft = 0;   // ... issuing warnings.
   bool    gotScreen = false;
 
   { // fetch screen coordinates
     nsCOMPtr<nsIScreenManager> screenMgr(do_GetService(
                                          "@mozilla.org/gfx/screenmanager;1"));
     if (screenMgr) {
       nsCOMPtr<nsIScreen> ourScreen;
+      // the coordinates here are already display pixels
       screenMgr->ScreenForRect(aRequestedX, aRequestedY,
                                aSpecWidth, aSpecHeight,
                                getter_AddRefs(ourScreen));
       if (ourScreen) {
         int32_t screenWidth, screenHeight;
-        ourScreen->GetAvailRect(&screenLeft, &screenTop,
-                                &screenWidth, &screenHeight);
+        ourScreen->GetAvailRectDisplayPix(&screenLeft, &screenTop,
+                                          &screenWidth, &screenHeight);
         screenBottom = screenTop + screenHeight;
         screenRight = screenLeft + screenWidth;
         gotScreen = true;
       }
     }
   }
 
   // One full pass through all windows of this type, repeat until no collisions.
@@ -1296,16 +1311,21 @@ void nsXULWindow::StaggerPosition(int32_
       nsCOMPtr<nsISupports> supportsWindow;
       windowList->GetNext(getter_AddRefs(supportsWindow));
 
       nsCOMPtr<nsIXULWindow> listXULWindow(do_QueryInterface(supportsWindow));
       if (listXULWindow != ourXULWindow) {
         int32_t listX, listY;
         nsCOMPtr<nsIBaseWindow> listBaseWindow(do_QueryInterface(supportsWindow));
         listBaseWindow->GetPosition(&listX, &listY);
+        double scale;
+        if (NS_SUCCEEDED(listBaseWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
+          listX = NSToIntRound(listX / scale);
+          listY = NSToIntRound(listY / scale);
+        }
 
         if (NS_ABS(listX - aRequestedX) <= kSlop &&
             NS_ABS(listY - aRequestedY) <= kSlop) {
           // collision! offset and start over
           if (bouncedX & 0x1)
             aRequestedX -= kOffset;
           else
             aRequestedX += kOffset;
@@ -1421,76 +1441,72 @@ NS_IMETHODIMP nsXULWindow::SavePersisten
   }
 
   int32_t x, y, cx, cy;
   int32_t sizeMode;
 
   // get our size, position and mode to persist
   NS_ENSURE_SUCCESS(GetPositionAndSize(&x, &y, &cx, &cy), NS_ERROR_FAILURE);
   mWindow->GetSizeMode(&sizeMode);
+  double scale = mWindow->GetDefaultScale();
 
   // make our position relative to our parent, if any
   nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
   if (parent) {
     int32_t parentX, parentY;
     if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
       x -= parentX;
       y -= parentY;
     }
   }
 
   char                        sizeBuf[10];
   nsAutoString                sizeString;
   nsAutoString                windowElementId;
   nsCOMPtr<nsIDOMXULDocument> ownerXULDoc;
-  int32_t appPerDev = AppUnitsPerDevPixel();
 
   { // fetch docShellElement's ID and XUL owner document
     nsCOMPtr<nsIDOMDocument> ownerDoc;
     docShellElement->GetOwnerDocument(getter_AddRefs(ownerDoc));
     ownerXULDoc = do_QueryInterface(ownerDoc);
     nsCOMPtr<nsIDOMXULElement> XULElement(do_QueryInterface(docShellElement));
     if (XULElement)
       XULElement->GetId(windowElementId);
   }
 
   // (only for size elements which are persisted)
   if ((mPersistentAttributesDirty & PAD_POSITION) &&
       sizeMode == nsSizeMode_Normal) {
     if (persistString.Find("screenX") >= 0) {
-      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%ld",
-                  (long)DevToCSSPixels(x, appPerDev));
+      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(x / scale));
       sizeString.AssignWithConversion(sizeBuf);
       docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString);
       if (ownerXULDoc) // force persistence in case the value didn't change
         ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE);
     }
     if (persistString.Find("screenY") >= 0) {
-      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%ld",
-                  (long)DevToCSSPixels(y, appPerDev));
+      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(y / scale));
       sizeString.AssignWithConversion(sizeBuf);
       docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString);
       if (ownerXULDoc)
         ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE);
     }
   }
 
   if ((mPersistentAttributesDirty & PAD_SIZE) &&
       sizeMode == nsSizeMode_Normal) {
     if (persistString.Find("width") >= 0) {
-      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%ld",
-                  (long)DevToCSSPixels(cx, appPerDev));
+      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cx / scale));
       sizeString.AssignWithConversion(sizeBuf);
       docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString);
       if (ownerXULDoc)
         ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE);
     }
     if (persistString.Find("height") >= 0) {
-      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%ld",
-                  (long)DevToCSSPixels(cy, appPerDev));
+      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cy / scale));
       sizeString.AssignWithConversion(sizeBuf);
       docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString);
       if (ownerXULDoc)
         ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE);
     }
   }
 
   if (mPersistentAttributesDirty & PAD_MISC) {
@@ -2043,31 +2059,16 @@ NS_IMETHODIMP nsXULWindow::GetXULBrowser
 
 NS_IMETHODIMP nsXULWindow::SetXULBrowserWindow(nsIXULBrowserWindow * aXULBrowserWindow)
 {
   mXULBrowserWindow = aXULBrowserWindow;
   return NS_OK;
 }
 
 //*****************************************************************************
-// nsXULWindow: Accessors
-//*****************************************************************************
-
-uint32_t nsXULWindow::AppUnitsPerDevPixel()
-{
-  if (mWindow && mWindow->GetDeviceContext()) {
-    mAppPerDev = mWindow->GetDeviceContext()->AppUnitsPerDevPixel();
-  } else {
-    NS_ERROR("nsXULWindow::AppUnitsPerDevPixel called with no window "
-             "or no dev context");
-  }
-  return mAppPerDev;
-}
-
-//*****************************************************************************
 //*** nsContentShellInfo: Object Management
 //*****************************************************************************   
 
 nsContentShellInfo::nsContentShellInfo(const nsAString& aID,
                                        nsIWeakReference* aContentShell)
   : id(aID),
     child(aContentShell)
 {
--- a/xpfe/appshell/src/nsXULWindow.h
+++ b/xpfe/appshell/src/nsXULWindow.h
@@ -107,17 +107,16 @@ protected:
    void       EnableParent(bool aEnable);
    bool       ConstrainToZLevel(bool aImmediate, nsWindowZ *aPlacement,
                                 nsIWidget *aReqBelow, nsIWidget **aActualBelow);
    void       PlaceWindowLayersBehind(uint32_t aLowLevel, uint32_t aHighLevel,
                                       nsIXULWindow *aBehind);
    void       SetContentScrollbarVisibility(bool aVisible);
    bool       GetContentScrollbarVisibility();
    void       PersistentAttributesDirty(uint32_t aDirtyFlags);
-   uint32_t   AppUnitsPerDevPixel();
 
    nsChromeTreeOwner*      mChromeTreeOwner;
    nsContentTreeOwner*     mContentTreeOwner;
    nsContentTreeOwner*     mPrimaryContentTreeOwner;
    nsCOMPtr<nsIWidget>     mWindow;
    nsCOMPtr<nsIDocShell>   mDocShell;
    nsCOMPtr<nsIDOMWindow>  mDOMWindow;
    nsCOMPtr<nsIWeakReference> mParentWindow;
@@ -138,18 +137,16 @@ protected:
    bool                    mIgnoreXULSize;
    bool                    mIgnoreXULPosition;
    bool                    mChromeFlagsFrozen;
    bool                    mIgnoreXULSizeMode;
    uint32_t                mContextFlags;
    uint32_t                mPersistentAttributesDirty; // persistentAttributes
    uint32_t                mPersistentAttributesMask;
    uint32_t                mChromeFlags;
-   uint32_t                mAppPerDev; // sometimes needed when we can't get
-                                       // it from the widget
    nsString                mTitle;
    nsIntRect               mOpenerScreenRect; // the screen rect of the opener
 
    nsCOMArray<nsIWeakReference> mTargetableShells; // targetable shells only
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXULWindow, NS_XULWINDOW_IMPL_CID)