commit b65113ed0849854fbc6833c0c9619e27bd89b890
parent 5e7833fdea31106939bf8f832f8606af5c3945ab
Author: Alexandru Marc <amarc@mozilla.com>
Date: Tue, 21 Oct 2025 17:36:17 +0300
Revert "Bug 1995498 - Assume per-monitor DPI awareness. r=win-reviewers,gstoll" for causing mass win failures
This reverts commit 47ae5f5f7b18ceeae9cd1b1405ddb1e20c65a9c7.
Diffstat:
5 files changed, 66 insertions(+), 19 deletions(-)
diff --git a/widget/windows/ScreenHelperWin.cpp b/widget/windows/ScreenHelperWin.cpp
@@ -94,7 +94,12 @@ BOOL CALLBACK CollectMonitors(HMONITOR aMon, HDC, LPRECT, LPARAM ioParam) {
}
double scale = WinUtils::LogToPhysFactor(aMon);
- DesktopToLayoutDeviceScale contentsScaleFactor(1.0);
+ DesktopToLayoutDeviceScale contentsScaleFactor;
+ if (WinUtils::IsPerMonitorDPIAware()) {
+ contentsScaleFactor.scale = 1.0;
+ } else {
+ contentsScaleFactor.scale = scale;
+ }
CSSToLayoutDeviceScale defaultCssScaleFactor(scale);
LayoutDeviceIntRect rect(info.rcMonitor.left, info.rcMonitor.top,
info.rcMonitor.right - info.rcMonitor.left,
diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp
@@ -244,12 +244,39 @@ typedef HRESULT(WINAPI* GETPROCESSDPIAWARENESSPROC)(HANDLE,
GETDPIFORMONITORPROC sGetDpiForMonitor;
GETPROCESSDPIAWARENESSPROC sGetProcessDpiAwareness;
+static bool SlowIsPerMonitorDPIAware() {
+ // Intentionally leak the handle.
+ HMODULE shcore = LoadLibraryEx(L"shcore", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (shcore) {
+ sGetDpiForMonitor =
+ (GETDPIFORMONITORPROC)GetProcAddress(shcore, "GetDpiForMonitor");
+ sGetProcessDpiAwareness = (GETPROCESSDPIAWARENESSPROC)GetProcAddress(
+ shcore, "GetProcessDpiAwareness");
+ }
+ PROCESS_DPI_AWARENESS dpiAwareness;
+ return sGetDpiForMonitor && sGetProcessDpiAwareness &&
+ SUCCEEDED(
+ sGetProcessDpiAwareness(GetCurrentProcess(), &dpiAwareness)) &&
+ dpiAwareness == PROCESS_PER_MONITOR_DPI_AWARE;
+}
+
+/* static */
+bool WinUtils::IsPerMonitorDPIAware() {
+ static bool perMonitorDPIAware = SlowIsPerMonitorDPIAware();
+ return perMonitorDPIAware;
+}
+
/* static */
float WinUtils::MonitorDPI(HMONITOR aMonitor) {
- UINT dpiX, dpiY = 96;
- sGetDpiForMonitor(aMonitor ? aMonitor : GetPrimaryMonitor(),
- MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
- return dpiY;
+ if (IsPerMonitorDPIAware()) {
+ UINT dpiX, dpiY = 96;
+ sGetDpiForMonitor(aMonitor ? aMonitor : GetPrimaryMonitor(),
+ MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
+ return dpiY;
+ }
+
+ // We're not per-monitor aware, use system DPI instead.
+ return SystemDPI();
}
/* static */
@@ -290,9 +317,14 @@ WinUtils::GetPrimaryMonitor() {
/* static */
HMONITOR
WinUtils::MonitorFromRect(const gfx::Rect& rect) {
- RECT globalWindowBounds = {NSToIntRound(rect.X()), NSToIntRound(rect.Y()),
- NSToIntRound(rect.XMost()),
- NSToIntRound(rect.YMost())};
+ // convert coordinates from desktop to device pixels for MonitorFromRect
+ double dpiScale =
+ IsPerMonitorDPIAware() ? 1.0 : LogToPhysFactor(GetPrimaryMonitor());
+
+ RECT globalWindowBounds = {NSToIntRound(dpiScale * rect.X()),
+ NSToIntRound(dpiScale * rect.Y()),
+ NSToIntRound(dpiScale * (rect.XMost())),
+ NSToIntRound(dpiScale * (rect.YMost()))};
return ::MonitorFromRect(&globalWindowBounds, MONITOR_DEFAULTTONEAREST);
}
@@ -309,7 +341,7 @@ int WinUtils::GetSystemMetricsForDpi(int nIndex, UINT dpi) {
if (HasSystemMetricsForDpi()) {
return sGetSystemMetricsForDpi(nIndex, dpi);
} else {
- double scale = dpi / SystemDPI();
+ double scale = IsPerMonitorDPIAware() ? dpi / SystemDPI() : 1.0;
return NSToIntRound(::GetSystemMetrics(nIndex) * scale);
}
}
diff --git a/widget/windows/WinUtils.h b/widget/windows/WinUtils.h
@@ -217,6 +217,7 @@ class WinUtils {
*/
static double SystemScaleFactor();
+ static bool IsPerMonitorDPIAware();
/**
* Get the DPI of the given monitor if it's per-monitor DPI aware, otherwise
* return the system DPI.
diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp
@@ -5518,16 +5518,18 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
case WM_MOVING:
FinishLiveResizing(MOVING);
- // Sometimes, we appear to miss a WM_DPICHANGED message while moving
- // a window around. Therefore, call ChangedDPI and ResetLayout here
- // if it appears that the window's scaling is not what we expect.
- // This causes the prescontext and appshell window management code to
- // check the appUnitsPerDevPixel value and current widget size, and
- // refresh them if necessary. If nothing has changed, these calls will
- // return without actually triggering any extra reflow or painting.
- if (WinUtils::LogToPhysFactor(mWnd) != mDefaultScale) {
- ChangedDPI();
- ResetLayout();
+ if (WinUtils::IsPerMonitorDPIAware()) {
+ // Sometimes, we appear to miss a WM_DPICHANGED message while moving
+ // a window around. Therefore, call ChangedDPI and ResetLayout here
+ // if it appears that the window's scaling is not what we expect.
+ // This causes the prescontext and appshell window management code to
+ // check the appUnitsPerDevPixel value and current widget size, and
+ // refresh them if necessary. If nothing has changed, these calls will
+ // return without actually triggering any extra reflow or painting.
+ if (WinUtils::LogToPhysFactor(mWnd) != mDefaultScale) {
+ ChangedDPI();
+ ResetLayout();
+ }
}
break;
diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h
@@ -196,6 +196,13 @@ class nsWindow final : public nsIWidget {
double GetDefaultScaleInternal() override;
void DidClearParent(nsIWidget* aOldParent) override;
int32_t LogToPhys(double aValue);
+ mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() override {
+ if (mozilla::widget::WinUtils::IsPerMonitorDPIAware()) {
+ return mozilla::DesktopToLayoutDeviceScale(1.0);
+ } else {
+ return mozilla::DesktopToLayoutDeviceScale(GetDefaultScaleInternal());
+ }
+ }
void Show(bool aState) override;
bool IsVisible() const override;