incorrect screen resolution reported by JS API under some multi monitor conditions
Categories
(Core :: Widget: Cocoa, defect, P3)
Tracking
()
People
(Reporter: nsdmitry, Assigned: jaas)
References
Details
(Whiteboard: [mac:multimonitor])
Attachments
(3 files)
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0
Steps to reproduce:
- Connect an external monitor to a Retina MacBook Pro
- Rotate external monitor 90 degrees (make it vertical)
- Open Firefox on your laptop monitor
- Maximize Firefox window
- Go to http://whatsmyscreenresolution.com/
Actual results:
Firefox report resolution of my external monitor divided by 2(while it is opened on my laptop screen).
Fun fact: if I make Firefox window small and put it in the top left corner it will report resolution of my laptop screen divided by 2 (probably this should be the case for full screen as well).
Expected results:
Firefox should report resolution of my Laptop monitor (maybe divided by 2 as it is retina).
To show my exact monitor setup I made a photo of my both screens.
Comment 1•7 years ago
|
||
Hi Dmitry,
Is this reproducible on Chrome as well or it is happening only on Firefox?
It is not reproducible in Chrome 72 or Safari 12.0.3, only Firefox is affected.
macOS 10.14.3 if it matters
Comment 3•7 years ago
|
||
Thanks for the feedback Dmitry!
Adding this issue to a component. Unfortunately, I don't have the right setup to test this.
Updated•7 years ago
|
I've found one more condition that helps to reproduce the bug. Laptop screen should be the main screen (one with the white line that represents macOS Dock).
So there is a workaround: if I switch my primary display to my secondary monitor, Firefox detect laptop screen resolution correct (1440x900). Hope that helps.
Ok getting all things together:
It doesn't matter if connected monitor vertical or horizontal.
If firefox occupies full screen on the primary monitor, it will report screen resolution as secondary monitor resolution.
This bug is very annoying as it breaks some websites, can you please dig into this folks?
And one more clarification, if an external monitor is on the left side - everything works as expected, only when it is on the right side of the main one - then this bug happens.
Updated•5 years ago
|
Updated•3 years ago
|
Hi - adding to this thread as this issue still persists. We followed the above steps (external monitor connected and arranged to the right of the laptop, laptop screen is set as main screen) and we were able to reproduce.
Mac model - macOS: 14.3 (Sonoma), MacBook Pro M3 Pro 14 inch
Firefox version - 131.0 (aarch64)
We also tested other arrangements - Macbook air M3, M1 16 inch Macbook Pro, connecting two external monitors. Could not reproduce the bug here.
Hope this can be resolved soon!
I have a fix for this, will post shortly. I updated the title to reflect the fact that reproducing this doesn't actually require a vertical monitor. This can be reproduced with two monitors in normal orientation.
The easiest way to reproduce this:
- Make a Retina screen your default screen
- Set up a 4k screen at max resolution (3840 × 2160), logically situated to the right of the main Retina screen
- Open a Firefox window on the main Retina screen and make it take up most of the available screen space
- Visit http://whatsmyscreenresolution.com/
It will report an incorrect screen resolution, probably 1920x1080 (half of the 4k resolution).
The three key components for reproducing are:
- The monitor logically on the left have a scaling factor (e.g. 2.0)
- There is a monitor logically to the right with a different scaling factor (e.g. 1.0).
- You open a Firefox window on the left (main) monitor that is big enough to take up most of the screen. If the test window is small enough, and far enough to the left, it won't be incorrectly considered to be on the right screen.
There are two issues leading to this:
- The JS API thinks the window is on the wrong screen because it's incorrectly using device coordinates that are larger than the actual display coordinates. It thinks the window is far to the right of where it actually is, on the other screen.
- Then it's using the wrong scaling factor for that screen (2.0), dividing the resolution by two. That's why the incorrect resolution doesn't even match the other monitor.
More details when I post the patch.
Based on the fix I would think this is likely to affect Windows and Linux as well, but I haven't tested or looked into it on anything other than macOS so I'm not sure.
| Assignee | ||
Comment 10•1 month ago
|
||
In content processes, PuppetWidget is the widget implementation used for tab content. When JS code queries screen resolution (e.g., window.screen.width/height), it ultimately calls GetWidgetScreen() to find which screen the widget is on, then returns that screen's properties.
The root cause of the issue here is a scale mismatch in the base class GetWidgetScreen().
The inherited implementation in widget/nsIWidget.cpp does:
LayoutDeviceIntRect bounds = GetScreenBounds();
DesktopIntRect deskBounds = RoundedToInt(bounds / GetDesktopToDeviceScale());
return screenManager.ScreenForRect(deskBounds);
It converts the widget's screen bounds from layout-device pixels to desktop pixels by dividing by GetDesktopToDeviceScale(). It then passes the desktop-pixel rect to ScreenForRect() to find the matching screen.
PuppetWidget doesn't override GetDesktopToDeviceScale(), so it inherits the base class default in nsIWidget.h which returns 1.0. But PuppetWidget's bounds (GetScreenBounds()) are actually in device pixels scaled by GetDefaultScaleInternal() (which reflects the actual DPI scale e.g. 2.0 on a Retina display).
So on a 2x display, the widget bounds might be at position (2000, 400) in device pixels, but the base GetWidgetScreen() divides by 1.0 (no-op), producing desktop coordinates of (2000, 400). The actual desktop coordinates should be (1000, 200). ScreenForRect() then fails to match the correct screen. It may match the wrong screen or no screen at all, returning a default/fallback screen with incorrect resolution information.
The fix overrides GetWidgetScreen() in PuppetWidget and uses GetDefaultScaleInternal() (the actual CSS-to-device scale) instead of GetDesktopToDeviceScale() (which is hardcoded to 1.0) for the coordinate conversion:
DesktopIntRect deskBounds =
RoundedToInt(bounds / DesktopToLayoutDeviceScale(GetDefaultScaleInternal()));
This produces correct desktop-pixel coordinates, so ScreenForRect() matches the correct screen, and JS APIs like screen.width, screen.height, screen.availWidth, etc. return the correct values.
Comment 11•1 month ago
|
||
I think your diagnostic is correct, but using the css scale is wrong for windows and X11: https://searchfox.org/firefox-main/rev/7095e662eec49a42856e0d99f2ff96c08130119c/widget/windows/ScreenHelperWin.cpp#98
So you probably need to pass that scale from the parent instead, or expose "desktop bounds are css" as a global LookAndFeel int or something that PuppetWidget can access
| Assignee | ||
Comment 12•1 month ago
|
||
(In reply to Emilio Cobos Álvarez [:emilio] from comment #11)
So you probably need to pass that scale from the parent instead, or expose "desktop bounds are css" as a global LookAndFeel int or something that PuppetWidget can access
Good to know. Patch has been updated to get the scale from the parent.
Comment 13•1 month ago
|
||
Comment 14•1 month ago
|
||
| bugherder | ||
Updated•11 days ago
|
| Assignee | ||
Comment 15•9 days ago
|
||
Release Note Request (optional, but appreciated)
[Why is this notable]: Firefox will frequently report an entirely incorrect screen resolution via JS APIs in multi-monitor setups. It's a major problem for anyone relying on those APIs.
[Affects Firefox for Android]: No
[Suggested wording]: Correct screen resolution reporting via JS APIs in multiple monitor setups.
Comment 16•9 days ago
|
||
Thanks, added to the Fx151 nightly release notes, please allow 30 minutes for the site to update.
Keeping the relnote-firefox flag as ? to keep it on the radar for inclusion in the final Fx151 release notes.
Description
•