Issue #1606 - Add support for multi-monitor DPI awareness v2 (W10 1706+)

This commit is contained in:
Moonchild 2020-10-06 09:23:59 +00:00 committed by roytam1
commit 810ce6aa74
4 changed files with 33 additions and 11 deletions

View file

@ -29,6 +29,7 @@
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
</ms_asmv3:windowsSettings>
</ms_asmv3:application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">

View file

@ -482,10 +482,20 @@ WinUtils::Initialize()
if (IsWin10OrLater()) {
HMODULE user32Dll = ::GetModuleHandleW(L"user32");
if (user32Dll) {
sEnableNonClientDpiScaling = (EnableNonClientDpiScalingProc)
::GetProcAddress(user32Dll, "EnableNonClientDpiScaling");
sSetThreadDpiAwarenessContext = (SetThreadDpiAwarenessContextProc)
::GetProcAddress(user32Dll, "SetThreadDpiAwarenessContext");
auto getThreadDpiAwarenessContext = (decltype(GetThreadDpiAwarenessContext)*)
::GetProcAddress(user32Dll, "GetThreadDpiAwarenessContext");
auto areDpiAwarenessContextsEqual = (decltype(AreDpiAwarenessContextsEqual)*)
::GetProcAddress(user32Dll, "AreDpiAwarenessContextsEqual");
if (getThreadDpiAwarenessContext && areDpiAwarenessContextsEqual &&
areDpiAwarenessContextsEqual(getThreadDpiAwarenessContext(),
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) {
// Only per-monitor DPI awareness v1 requires these workarounds.
// Since this was introduced in Win 8.1 we'll need to keep this indefinitely.
sEnableNonClientDpiScaling = (EnableNonClientDpiScalingProc)
::GetProcAddress(user32Dll, "EnableNonClientDpiScaling");
sSetThreadDpiAwarenessContext = (SetThreadDpiAwarenessContextProc)
::GetProcAddress(user32Dll, "SetThreadDpiAwarenessContext");
}
}
}
@ -501,7 +511,7 @@ LRESULT WINAPI
WinUtils::NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
if (msg == WM_NCCREATE && sEnableNonClientDpiScaling) {
if (msg == WM_NCCREATE) {
sEnableNonClientDpiScaling(hWnd);
}
return ::DefWindowProcW(hWnd, msg, wParam, lParam);

View file

@ -96,6 +96,11 @@ typedef enum DPI_AWARENESS {
#define DPI_AWARENESS_CONTEXT_DECLARED
#endif // (DPI_AWARENESS_CONTEXT_DECLARED)
#if WINVER < 0x0605
WINUSERAPI DPI_AWARENESS_CONTEXT WINAPI GetThreadDpiAwarenessContext();
WINUSERAPI BOOL WINAPI
AreDpiAwarenessContextsEqual(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT);
#endif /* WINVER < 0x0605 */
typedef DPI_AWARENESS_CONTEXT(WINAPI * SetThreadDpiAwarenessContextProc)(DPI_AWARENESS_CONTEXT);
typedef BOOL(WINAPI * EnableNonClientDpiScalingProc)(HWND);
@ -152,6 +157,12 @@ class WinUtils
static SetThreadDpiAwarenessContextProc sSetThreadDpiAwarenessContext;
static EnableNonClientDpiScalingProc sEnableNonClientDpiScaling;
// Wrapper for DefWindowProc that will enable non-client dpi scaling on the
// window during creation.
static LRESULT WINAPI
NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam);
public:
class AutoSystemDpiAware
{
@ -174,11 +185,11 @@ public:
DPI_AWARENESS_CONTEXT mPrevContext;
};
// Wrapper for DefWindowProc that will enable non-client dpi scaling on the
// window during creation.
static LRESULT WINAPI
NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam);
static decltype(::DefWindowProcW)* GetDefWindowProc() {
return sEnableNonClientDpiScaling ?
NonClientDpiScalingDefWindowProcW :
::DefWindowProcW;
}
/**
* Get the system's default logical-to-physical DPI scaling factor,

View file

@ -1007,7 +1007,7 @@ nsWindow::RegisterWindowClass(const wchar_t* aClassName,
}
wc.style = CS_DBLCLKS | aExtraStyle;
wc.lpfnWndProc = WinUtils::NonClientDpiScalingDefWindowProcW;
wc.lpfnWndProc = WinUtils::GetDefWindowProc();
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = nsToolkit::mDllInstance;