From bda6f1a93f915f4156bc344651dcfc9b7bb3b9ee Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 6 Oct 2020 09:23:59 +0000 Subject: Issue #1606 - Add support for multi-monitor DPI awareness v2 (W10 1706+) --- widget/windows/WinUtils.cpp | 20 +++++++++++++++----- widget/windows/WinUtils.h | 21 ++++++++++++++++----- widget/windows/nsWindow.cpp | 2 +- 3 files changed, 32 insertions(+), 11 deletions(-) (limited to 'widget') diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index 28033193f..a43c92b69 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -449,10 +449,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"); + } } } @@ -468,7 +478,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); diff --git a/widget/windows/WinUtils.h b/widget/windows/WinUtils.h index 1281171be..f268f907f 100644 --- a/widget/windows/WinUtils.h +++ b/widget/windows/WinUtils.h @@ -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, diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 907d8b9a5..b9c3ea154 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -999,7 +999,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; -- cgit v1.2.3