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 110423 4120e702e25bc06052fc984a0cef151f87ddaa3d
parent 110422 5ec67c1dd2e1d5b737a60a8118034e40171dfc5b
child 110424 b0be2ef452df5e18259c9ecba2870ff0e3e8c3ca
push id16548
push userjkew@mozilla.com
push dateTue, 16 Oct 2012 19:43:27 +0000
treeherdermozilla-inbound@eaccb5bb50c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs794038
milestone19.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 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)