author | Jonathan Kew <jkew@mozilla.com> |
Tue, 01 Mar 2016 21:05:10 +0000 | |
changeset 287064 | c254f951e0ad68f047763f8e2c2fa9385b74a798 |
parent 287008 | 4b9a16cc88c2e2689dc2c9c47be8fc01ea5439da |
child 287065 | f637f149610bb15fdbbda534417d6743877738f5 |
push id | 30065 |
push user | kwierso@gmail.com |
push date | Wed, 09 Mar 2016 00:01:05 +0000 |
treeherder | mozilla-central@886b5480b578 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | emk |
bugs | 1242449 |
milestone | 47.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
|
xpfe/appshell/nsXULWindow.cpp | file | annotate | diff | comparison | revisions | |
xpfe/appshell/nsXULWindow.h | file | annotate | diff | comparison | revisions |
--- a/xpfe/appshell/nsXULWindow.cpp +++ b/xpfe/appshell/nsXULWindow.cpp @@ -1033,30 +1033,40 @@ void nsXULWindow::OnChromeLoaded() { nsresult rv = EnsureContentTreeOwner(); if (NS_SUCCEEDED(rv)) { mChromeLoaded = true; ApplyChromeFlags(); SyncAttributesToWidget(); + int32_t specWidth = -1, specHeight = -1; + bool gotSize = false; + + if (!mIgnoreXULSize) { + gotSize = LoadSizeFromXUL(specWidth, specHeight); + } + bool positionSet = !mIgnoreXULPosition; nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow)); #if defined(XP_UNIX) && !defined(XP_MACOSX) // don't override WM placement on unix for independent, top-level windows // (however, we think the benefits of intelligent dependent window placement // trump that override.) if (!parentWindow) positionSet = false; #endif - if (positionSet) - positionSet = LoadPositionFromXUL(); + if (positionSet) { + positionSet = LoadPositionFromXUL(specWidth, specHeight); + } - if (!mIgnoreXULSize) - LoadSizeFromXUL(); + if (gotSize) { + SetSpecifiedSize(specWidth, specHeight); + } + if (mIntrinsicallySized) { // (if LoadSizeFromXUL set the size, mIntrinsicallySized will be false) nsCOMPtr<nsIContentViewer> cv; mDocShell->GetContentViewer(getter_AddRefs(cv)); if (cv) { nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(mDocShell); nsCOMPtr<nsIDocShellTreeOwner> treeOwner; docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner)); @@ -1068,29 +1078,33 @@ void nsXULWindow::OnChromeLoaded() treeOwner->SizeShellTo(docShellAsItem, width, height); } } } } LoadMiscPersistentAttributesFromXUL(); - if (mCenterAfterLoad && !positionSet) + if (mCenterAfterLoad && !positionSet) { Center(parentWindow, parentWindow ? false : true, false); + } if (mShowAfterLoad) { SetVisibility(true); // At this point the window may have been closed during Show(), so // nsXULWindow::Destroy may already have been called. Take care! } } mPersistentAttributesMask |= PAD_POSITION | PAD_SIZE | PAD_MISC; } -bool nsXULWindow::LoadPositionFromXUL() +// If aSpecWidth and/or aSpecHeight are > 0, we will use these CSS px sizes +// to fit to the screen when staggering windows; if they're negative, +// we use the window's current size instead. +bool nsXULWindow::LoadPositionFromXUL(int32_t aSpecWidth, int32_t aSpecHeight) { bool gotPosition = false; // if we're the hidden window, don't try to validate our size/position. We're // special. if (mIsHiddenWindow) return false; @@ -1103,21 +1117,26 @@ bool nsXULWindow::LoadPositionFromXUL() 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->GetDesktopToDeviceScale().scale; - currX = NSToIntRound(currX / scale); - currY = NSToIntRound(currY / scale); - currWidth = NSToIntRound(currWidth / scale); - currHeight = NSToIntRound(currHeight / scale); + double devToDesktopScale = 1.0 / mWindow->GetDesktopToDeviceScale().scale; + currX = NSToIntRound(currX * devToDesktopScale); + currY = NSToIntRound(currY * devToDesktopScale); + + // For size, use specified value if > 0, else current value + double devToCSSScale = 1.0 / mWindow->GetDefaultScale().scale; + int32_t cssWidth = + aSpecWidth > 0 ? aSpecWidth : NSToIntRound(currWidth * devToCSSScale); + int32_t cssHeight = + aSpecHeight > 0 ? aSpecHeight : NSToIntRound(currHeight * devToCSSScale); // Obtain the position information from the <xul:window> element. int32_t specX = currX; int32_t specY = currY; nsAutoString posString; windowElement->GetAttribute(SCREENX_ATTRIBUTE, posString); temp = posString.ToInteger(&errorCode); @@ -1143,97 +1162,102 @@ bool nsXULWindow::LoadPositionFromXUL() parentX = NSToIntRound(parentX / scale); parentY = NSToIntRound(parentY / scale); } specX += parentX; specY += parentY; } } else { - StaggerPosition(specX, specY, currWidth, currHeight); + StaggerPosition(specX, specY, cssWidth, cssHeight); } } mWindow->ConstrainPosition(false, &specX, &specY); if (specX != currX || specY != currY) { SetPositionDesktopPix(specX, specY); } return gotPosition; } -bool nsXULWindow::LoadSizeFromXUL() +bool +nsXULWindow::LoadSizeFromXUL(int32_t& aSpecWidth, int32_t& aSpecHeight) { bool gotSize = false; // if we're the hidden window, don't try to validate our size/position. We're // special. - if (mIsHiddenWindow) + if (mIsHiddenWindow) { return false; + } nsCOMPtr<dom::Element> 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"); - - GetSize(&currWidth, &currHeight); - double displayToDevPx = - mWindow ? mWindow->GetDesktopToDeviceScale().scale : 1.0; - double cssToDevPx = mWindow ? mWindow->GetDefaultScale().scale : 1.0; - currWidth = NSToIntRound(currWidth * displayToDevPx / cssToDevPx); - currHeight = NSToIntRound(currHeight * displayToDevPx / cssToDevPx); - - // Obtain the position and sizing information from the <xul:window> element. - int32_t specWidth = currWidth; - int32_t specHeight = currHeight; + // Obtain the sizing information from the <xul:window> element. + aSpecWidth = 100; + aSpecHeight = 100; nsAutoString sizeString; windowElement->GetAttribute(WIDTH_ATTRIBUTE, sizeString); temp = sizeString.ToInteger(&errorCode); if (NS_SUCCEEDED(errorCode) && temp > 0) { - specWidth = std::max(temp, 100); + aSpecWidth = std::max(temp, 100); gotSize = true; } windowElement->GetAttribute(HEIGHT_ATTRIBUTE, sizeString); temp = sizeString.ToInteger(&errorCode); if (NS_SUCCEEDED(errorCode) && temp > 0) { - specHeight = std::max(temp, 100); + aSpecHeight = std::max(temp, 100); gotSize = true; } - if (gotSize) { - // constrain to screen size - nsCOMPtr<mozIDOMWindowProxy> domWindow; - GetWindowDOMWindow(getter_AddRefs(domWindow)); - if (domWindow) { - auto* window = nsPIDOMWindowOuter::From(domWindow); - nsCOMPtr<nsIDOMScreen> screen = window->GetScreen(); - if (screen) { - int32_t screenWidth; - int32_t screenHeight; - screen->GetAvailWidth(&screenWidth); // CSS pixels - screen->GetAvailHeight(&screenHeight); - if (specWidth > screenWidth) - specWidth = screenWidth; - if (specHeight > screenHeight) - specHeight = screenHeight; + return gotSize; +} + +void +nsXULWindow::SetSpecifiedSize(int32_t aSpecWidth, int32_t aSpecHeight) +{ + // constrain to screen size + nsCOMPtr<mozIDOMWindowProxy> domWindow; + GetWindowDOMWindow(getter_AddRefs(domWindow)); + if (domWindow) { + auto* window = nsPIDOMWindowOuter::From(domWindow); + nsCOMPtr<nsIDOMScreen> screen = window->GetScreen(); + if (screen) { + int32_t screenWidth; + int32_t screenHeight; + screen->GetAvailWidth(&screenWidth); // CSS pixels + screen->GetAvailHeight(&screenHeight); + if (aSpecWidth > screenWidth) { + aSpecWidth = screenWidth; } - } - - mIntrinsicallySized = false; - if (specWidth != currWidth || specHeight != currHeight) { - SetSize(specWidth * cssToDevPx, specHeight * cssToDevPx, false); + if (aSpecHeight > screenHeight) { + aSpecHeight = screenHeight; + } } } - return gotSize; + NS_ASSERTION(mWindow, "we expected to have a window already"); + + int32_t currWidth = 0; + int32_t currHeight = 0; + GetSize(&currWidth, &currHeight); // returns device pixels + + // convert specified values to device pixels, and resize if needed + double cssToDevPx = mWindow ? mWindow->GetDefaultScale().scale : 1.0; + aSpecWidth = NSToIntRound(aSpecWidth * cssToDevPx); + aSpecHeight = NSToIntRound(aSpecHeight * cssToDevPx); + mIntrinsicallySized = false; + if (aSpecWidth != currWidth || aSpecHeight != currHeight) { + SetSize(aSpecWidth, aSpecHeight, false); + } } /* 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 attributes (sizemode) and they require extra processing. */ bool nsXULWindow::LoadMiscPersistentAttributesFromXUL() { @@ -1310,22 +1334,27 @@ bool nsXULWindow::LoadMiscPersistentAttr return gotState; } /* 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. + The aRequested{X,Y} parameters here are in desktop pixels; + the aSpec{Width,Height} parameters are CSS pixel dimensions. */ void nsXULWindow::StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY, int32_t aSpecWidth, int32_t aSpecHeight) { - const int32_t kOffset = 22; - const uint32_t kSlop = 4; + // These "constants" will be converted from CSS to desktop pixels + // for the appropriate screen, assuming we find a screen to use... + // hence they're not actually declared const here. + int32_t kOffset = 22; + uint32_t kSlop = 4; 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)); if (!wm) @@ -1356,16 +1385,27 @@ void nsXULWindow::StaggerPosition(int32_ aSpecWidth, aSpecHeight, getter_AddRefs(ourScreen)); if (ourScreen) { int32_t screenWidth, screenHeight; ourScreen->GetAvailRectDisplayPix(&screenLeft, &screenTop, &screenWidth, &screenHeight); screenBottom = screenTop + screenHeight; screenRight = screenLeft + screenWidth; + // Get the screen's scaling factors and convert staggering constants + // from CSS px to desktop pixel units + double desktopToDeviceScale = 1.0, cssToDeviceScale = 1.0; + ourScreen->GetContentsScaleFactor(&desktopToDeviceScale); + ourScreen->GetDefaultCSSScaleFactor(&cssToDeviceScale); + double cssToDesktopFactor = cssToDeviceScale / desktopToDeviceScale; + kOffset = NSToIntRound(kOffset * cssToDesktopFactor); + kSlop = NSToIntRound(kSlop * cssToDesktopFactor); + // Convert dimensions from CSS to desktop pixels + aSpecWidth = NSToIntRound(aSpecWidth * cssToDesktopFactor); + aSpecHeight = NSToIntRound(aSpecHeight * cssToDesktopFactor); gotScreen = true; } } } // One full pass through all windows of this type, repeat until no collisions. do { keepTrying = false; @@ -1386,17 +1426,17 @@ void nsXULWindow::StaggerPosition(int32_ 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))) { + if (NS_SUCCEEDED(listBaseWindow->GetDevicePixelsPerDesktopPixel(&scale))) { listX = NSToIntRound(listX / scale); listY = NSToIntRound(listY / scale); } if (Abs(listX - aRequestedX) <= kSlop && Abs(listY - aRequestedY) <= kSlop) { // collision! offset and start over if (bouncedX & 0x1) aRequestedX -= kOffset;
--- a/xpfe/appshell/nsXULWindow.h +++ b/xpfe/appshell/nsXULWindow.h @@ -88,18 +88,19 @@ protected: NS_IMETHOD EnsureContentTreeOwner(); NS_IMETHOD EnsurePrimaryContentTreeOwner(); NS_IMETHOD EnsurePrompter(); NS_IMETHOD EnsureAuthPrompter(); void OnChromeLoaded(); void StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY, int32_t aSpecWidth, int32_t aSpecHeight); - bool LoadPositionFromXUL(); - bool LoadSizeFromXUL(); + bool LoadPositionFromXUL(int32_t aSpecWidth, int32_t aSpecHeight); + bool LoadSizeFromXUL(int32_t& aSpecWidth, int32_t& aSpecHeight); + void SetSpecifiedSize(int32_t aSpecWidth, int32_t aSpecHeight); bool LoadMiscPersistentAttributesFromXUL(); void SyncAttributesToWidget(); NS_IMETHOD SavePersistentAttributes(); NS_IMETHOD GetWindowDOMWindow(mozIDOMWindowProxy** aDOMWindow); mozilla::dom::Element* GetWindowDOMElement() const; // See nsIDocShellTreeOwner for docs on next two methods