Bug 1242720 - Use (non-dynamic) resolution from GetDeviceCaps when dealing with native-theme code that does not handle dynamic changes to system DPI. r=emk

This commit is contained in:
Jonathan Kew 2016-01-28 15:08:33 +00:00
parent ce2dec23c9
commit 80e5f404c7
4 changed files with 30 additions and 6 deletions

View File

@ -524,6 +524,22 @@ WinUtils::Log(const char *fmt, ...)
delete[] buffer;
}
// static
double
WinUtils::SystemScaleFactor()
{
// The result of GetDeviceCaps won't change dynamically, as it predates
// per-monitor DPI and support for on-the-fly resolution changes.
// Therefore, we only need to look it up once.
static int logPixelsY = 0;
if (!logPixelsY) {
HDC screenDC = GetDC(nullptr);
logPixelsY = GetDeviceCaps(screenDC, LOGPIXELSY);
ReleaseDC(nullptr, screenDC);
}
return logPixelsY / 96.0;
}
#ifndef WM_DPICHANGED
typedef enum {
MDT_EFFECTIVE_DPI = 0,

View File

@ -128,6 +128,15 @@ public:
class WinUtils
{
public:
/**
* Get the system's default logical-to-physical DPI scaling factor,
* which is based on the primary display. Note however that unlike
* LogToPhysFactor(GetPrimaryMonitor()), this will not change during
* a session even if the displays are reconfigured. This scale factor
* is used by Windows theme metrics etc, which do not fully support
* dynamic resolution changes but are only updated on logout.
*/
static double SystemScaleFactor();
static bool IsPerMonitorDPIAware();
/**

View File

@ -584,7 +584,7 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID,
}
// Get scaling factor from physical to logical pixels
double pixelScale = 1.0 / WinUtils::LogToPhysFactor(aHDC);
double pixelScale = 1.0 / WinUtils::SystemScaleFactor();
// The lfHeight is in pixels, and it needs to be adjusted for the
// device it will be displayed on.

View File

@ -1547,18 +1547,17 @@ AssumeThemePartAndStateAreTransparent(int32_t aPart, int32_t aState)
}
// When running with per-monitor DPI (on Win8.1+), and rendering on a display
// with a different DPI setting from the system's primary monitor, we need to
// with a different DPI setting from the system's default scaling, we need to
// apply scaling to native-themed elements as the Windows theme APIs assume
// the primary monitor's resolution.
// the system default resolution.
static inline double
GetThemeDpiScaleFactor(nsIFrame* aFrame)
{
if (WinUtils::IsPerMonitorDPIAware() && GetSystemMetrics(SM_CMONITORS) > 1) {
nsIWidget* rootWidget = aFrame->PresContext()->GetRootWidget();
if (rootWidget) {
double primaryScale =
WinUtils::LogToPhysFactor(WinUtils::GetPrimaryMonitor());
return rootWidget->GetDefaultScale().scale / primaryScale;
double systemScale = WinUtils::SystemScaleFactor();
return rootWidget->GetDefaultScale().scale / systemScale;
}
}
return 1.0;