Skip to content

Commit

Permalink
Bug 1773813 - Incorporate OS zoom factor in window sizing calculation…
Browse files Browse the repository at this point in the history
…s. r=tnikkel

In bug 1773342 I made OS text scale factor behave like a full zoom
factor which applies to all pages (including the browser chrome). That's
generally straight forward but it makes some callsites that use unzoomed
CSS coordinates misbehave (or behave correctly accidentally actually in
some other cases).

The main fix here is making
nsIBaseWindow::UnscaledDevicePixelsPerCSSPixel() and
nsIScreen::GetDefaultCSSScaleFactor() account for OS zoom as necessary.
However, I also went through the relevant code and cleaned it up to use
typed units and operations when possible.

The setup means:

 * nsIWidget::GetDefaultScale() doesn't account for OS full zoom.
 * nsIBaseWindow and nsIScreen does.

These are the places where this should matter and stuff can get
confused, but this works surprisingly well for all callers (except one
nsDeviceContext one which we use only for PuppetWidget and we can
remove by falling back to 1.0 like all other widgets until the update
comes).

Differential Revision: https://phabricator.services.mozilla.com/D149033
  • Loading branch information
emilio committed Jun 14, 2022
1 parent 2e99fd0 commit 2fc2f53
Show file tree
Hide file tree
Showing 20 changed files with 242 additions and 366 deletions.
16 changes: 5 additions & 11 deletions docshell/base/nsDocShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4641,20 +4641,14 @@ nsDocShell::Destroy() {
return NS_OK;
}

NS_IMETHODIMP
nsDocShell::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) {
double nsDocShell::GetWidgetCSSToDeviceScale() {
if (mParentWidget) {
*aScale = mParentWidget->GetDefaultScale().scale;
return NS_OK;
return mParentWidget->GetDefaultScale().scale;
}

nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
if (ownerWindow) {
return ownerWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale);
if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
return ownerWindow->GetWidgetCSSToDeviceScale();
}

*aScale = 1.0;
return NS_OK;
return 1.0;
}

NS_IMETHODIMP
Expand Down
10 changes: 2 additions & 8 deletions docshell/base/nsDocShellTreeOwner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,14 +552,8 @@ nsDocShellTreeOwner::Destroy() {
return NS_ERROR_NULL_POINTER;
}

NS_IMETHODIMP
nsDocShellTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) {
if (mWebBrowser) {
return mWebBrowser->GetUnscaledDevicePixelsPerCSSPixel(aScale);
}

*aScale = 1.0;
return NS_OK;
double nsDocShellTreeOwner::GetWidgetCSSToDeviceScale() {
return mWebBrowser ? mWebBrowser->GetWidgetCSSToDeviceScale() : 1.0;
}

NS_IMETHODIMP
Expand Down
45 changes: 15 additions & 30 deletions dom/base/nsGlobalWindowInner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7518,53 +7518,37 @@ void nsGlobalWindowInner::SetReplaceableWindowCoord(
if (innerWidthSpecified || innerHeightSpecified || outerWidthSpecified ||
outerHeightSpecified) {
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = outer->GetTreeOwnerWindow();
nsCOMPtr<nsIScreen> screen;
nsCOMPtr<nsIScreenManager> screenMgr(
do_GetService("@mozilla.org/gfx/screenmanager;1"));
int32_t winLeft = 0;
int32_t winTop = 0;
int32_t winWidth = 0;
int32_t winHeight = 0;
double scale = 1.0;

if (treeOwnerAsWin && screenMgr) {
// Acquire current window size.
treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&scale);
treeOwnerAsWin->GetPositionAndSize(&winLeft, &winTop, &winWidth,
&winHeight);
winLeft = NSToIntRound(winHeight / scale);
winTop = NSToIntRound(winWidth / scale);
winWidth = NSToIntRound(winWidth / scale);
winHeight = NSToIntRound(winHeight / scale);
//
// FIXME: This needs to account for full zoom like the outer window code
// does! Ideally move there?
auto cssScale = treeOwnerAsWin->UnscaledDevicePixelsPerCSSPixel();
LayoutDeviceIntRect devWinRect = treeOwnerAsWin->GetPositionAndSize();
CSSIntRect cssWinRect = RoundedToInt(devWinRect / cssScale);

// Acquire content window size.
CSSSize contentSize;
outer->GetInnerSize(contentSize);

screenMgr->ScreenForRect(winLeft, winTop, winWidth, winHeight,
getter_AddRefs(screen));

nsCOMPtr<nsIScreen> screen = screenMgr->ScreenForRect(RoundedToInt(
devWinRect / treeOwnerAsWin->DevicePixelsPerDesktopPixel()));
if (screen) {
int32_t roundedValue = std::round(value);
int32_t* targetContentWidth = nullptr;
int32_t* targetContentHeight = nullptr;
int32_t screenWidth = 0;
int32_t screenHeight = 0;
int32_t chromeWidth = 0;
int32_t chromeHeight = 0;
int32_t inputWidth = 0;
int32_t inputHeight = 0;
int32_t unused = 0;

// Get screen dimensions (in device pixels)
screen->GetAvailRect(&unused, &unused, &screenWidth, &screenHeight);
// Convert them to CSS pixels
screenWidth = NSToIntRound(screenWidth / scale);
screenHeight = NSToIntRound(screenHeight / scale);
CSSIntSize availScreenSize =
RoundedToInt(screen->GetAvailRect().Size() / cssScale);

// Calculate the chrome UI size.
chromeWidth = winWidth - contentSize.width;
chromeHeight = winHeight - contentSize.height;
CSSIntSize chromeSize = cssWinRect.Size() - RoundedToInt(contentSize);

if (innerWidthSpecified || outerWidthSpecified) {
inputWidth = value;
Expand All @@ -7577,9 +7561,10 @@ void nsGlobalWindowInner::SetReplaceableWindowCoord(
}

nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
chromeWidth, chromeHeight, screenWidth, screenHeight, inputWidth,
inputHeight, outerWidthSpecified, outerHeightSpecified,
targetContentWidth, targetContentHeight);
chromeSize.width, chromeSize.height, availScreenSize.width,
availScreenSize.height, inputWidth, inputHeight,
outerWidthSpecified, outerHeightSpecified, targetContentWidth,
targetContentHeight);
value = T(roundedValue);
}
}
Expand Down
Loading

0 comments on commit 2fc2f53

Please sign in to comment.