commit ec10c7ec7e6c28249852472f7aea8d1484303e8e
parent f85b6b318c0e4f89bcd3011dc30c9b81867b42ff
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Fri, 17 Oct 2025 00:23:57 +0000
Bug 1994762 - Default to parent widget scale factor for popups. r=mac-reviewers,spohl
What seems to happen is that, when showing widgets on a previous or updated
position, we now have the right rect (because we've sized the popup frame
correctly already). So we create the window with a frame, and get the wrong
scale factor.
If we have a parent window (i.e. if we're a popup) we can pull the scale factor
from our parent if we're not visible. This matches GTK, and nsMenuPopupFrame
doesn't consider having a different DPI (the AppUnitsPerDevPixel is
per-prescontext), so I think it's fine.
Differential Revision: https://phabricator.services.mozilla.com/D268968
Diffstat:
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h
@@ -520,6 +520,7 @@ class nsCocoaWindow final : public nsIWidget {
void UpdateBounds();
int32_t GetWorkspaceID();
void MoveVisibleWindowToWorkspace(int32_t workspaceID);
+ CGFloat ComputeBackingScaleFactor() const;
void DoResize(double aX, double aY, double aWidth, double aHeight,
bool aRepaint, bool aConstrainToCurrentScreen);
diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
@@ -6405,12 +6405,14 @@ LayoutDeviceIntRect nsCocoaWindow::GetScreenBounds() {
double nsCocoaWindow::GetDefaultScaleInternal() { return BackingScaleFactor(); }
-static CGFloat GetBackingScaleFactor(NSWindow* aWindow) {
- NSRect frame = aWindow.frame;
+CGFloat nsCocoaWindow::ComputeBackingScaleFactor() const {
+ if (nsIWidget* parent = GetParent()) {
+ return parent->GetDesktopToDeviceScale().scale;
+ }
+ NSRect frame = mWindow.frame;
if (frame.size.width > 0 && frame.size.height > 0) {
- return nsCocoaUtils::GetBackingScaleFactor(aWindow);
+ return nsCocoaUtils::GetBackingScaleFactor(mWindow);
}
-
// For windows with zero width or height, the backingScaleFactor method
// is broken - it will always return 2 on a retina macbook, even when
// the window position implies it's on a non-hidpi external display
@@ -6421,18 +6423,17 @@ static CGFloat GetBackingScaleFactor(NSWindow* aWindow) {
// NSBackingPropertyOldScaleFactorKey key when a window on an
// external display is resized to/from zero height, even though it hasn't
// really changed screens.
-
+ //
// This causes us to handle popup window sizing incorrectly when the
// popup is resized to zero height (bug 820327) - nsXULPopupManager
// becomes (incorrectly) convinced the popup has been explicitly forced
// to a non-default size and needs to have size attributes attached.
-
+ //
// Workaround: instead of asking the window, we'll find the screen it is on
// and ask that for *its* backing scale factor.
-
+ //
// (See bug 853252 and additional comments in windowDidChangeScreen: below
// for further complications this causes.)
-
// First, expand the rect so that it actually has a measurable area,
// for FindTargetScreenForRect to use.
if (frame.size.width == 0) {
@@ -6441,7 +6442,6 @@ static CGFloat GetBackingScaleFactor(NSWindow* aWindow) {
if (frame.size.height == 0) {
frame.size.height = 1;
}
-
// Then identify the screen it belongs to, and return its scale factor.
NSScreen* screen =
FindTargetScreenForRect(nsCocoaUtils::CocoaRectToGeckoRect(frame));
@@ -6455,12 +6455,12 @@ CGFloat nsCocoaWindow::BackingScaleFactor() const {
if (!mWindow) {
return 1.0;
}
- mBackingScaleFactor = GetBackingScaleFactor(mWindow);
+ mBackingScaleFactor = ComputeBackingScaleFactor();
return mBackingScaleFactor;
}
void nsCocoaWindow::BackingScaleFactorChanged() {
- CGFloat newScale = GetBackingScaleFactor(mWindow);
+ CGFloat newScale = ComputeBackingScaleFactor();
// Ignore notification if it hasn't really changed
if (BackingScaleFactor() == newScale) {