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

View file

@ -482,12 +482,22 @@ WinUtils::Initialize()
if (IsWin10OrLater()) { if (IsWin10OrLater()) {
HMODULE user32Dll = ::GetModuleHandleW(L"user32"); HMODULE user32Dll = ::GetModuleHandleW(L"user32");
if (user32Dll) { if (user32Dll) {
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) sEnableNonClientDpiScaling = (EnableNonClientDpiScalingProc)
::GetProcAddress(user32Dll, "EnableNonClientDpiScaling"); ::GetProcAddress(user32Dll, "EnableNonClientDpiScaling");
sSetThreadDpiAwarenessContext = (SetThreadDpiAwarenessContextProc) sSetThreadDpiAwarenessContext = (SetThreadDpiAwarenessContextProc)
::GetProcAddress(user32Dll, "SetThreadDpiAwarenessContext"); ::GetProcAddress(user32Dll, "SetThreadDpiAwarenessContext");
} }
} }
}
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
sNtTestAlert = reinterpret_cast<NtTestAlertPtr>( sNtTestAlert = reinterpret_cast<NtTestAlertPtr>(
@ -501,7 +511,7 @@ LRESULT WINAPI
WinUtils::NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg, WinUtils::NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
if (msg == WM_NCCREATE && sEnableNonClientDpiScaling) { if (msg == WM_NCCREATE) {
sEnableNonClientDpiScaling(hWnd); sEnableNonClientDpiScaling(hWnd);
} }
return ::DefWindowProcW(hWnd, msg, wParam, lParam); return ::DefWindowProcW(hWnd, msg, wParam, lParam);

View file

@ -96,6 +96,11 @@ typedef enum DPI_AWARENESS {
#define DPI_AWARENESS_CONTEXT_DECLARED #define DPI_AWARENESS_CONTEXT_DECLARED
#endif // (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 DPI_AWARENESS_CONTEXT(WINAPI * SetThreadDpiAwarenessContextProc)(DPI_AWARENESS_CONTEXT);
typedef BOOL(WINAPI * EnableNonClientDpiScalingProc)(HWND); typedef BOOL(WINAPI * EnableNonClientDpiScalingProc)(HWND);
@ -152,6 +157,12 @@ class WinUtils
static SetThreadDpiAwarenessContextProc sSetThreadDpiAwarenessContext; static SetThreadDpiAwarenessContextProc sSetThreadDpiAwarenessContext;
static EnableNonClientDpiScalingProc sEnableNonClientDpiScaling; 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: public:
class AutoSystemDpiAware class AutoSystemDpiAware
{ {
@ -174,11 +185,11 @@ public:
DPI_AWARENESS_CONTEXT mPrevContext; DPI_AWARENESS_CONTEXT mPrevContext;
}; };
// Wrapper for DefWindowProc that will enable non-client dpi scaling on the static decltype(::DefWindowProcW)* GetDefWindowProc() {
// window during creation. return sEnableNonClientDpiScaling ?
static LRESULT WINAPI NonClientDpiScalingDefWindowProcW :
NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg, ::DefWindowProcW;
WPARAM wParam, LPARAM lParam); }
/** /**
* Get the system's default logical-to-physical DPI scaling factor, * 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.style = CS_DBLCLKS | aExtraStyle;
wc.lpfnWndProc = WinUtils::NonClientDpiScalingDefWindowProcW; wc.lpfnWndProc = WinUtils::GetDefWindowProc();
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
wc.cbWndExtra = 0; wc.cbWndExtra = 0;
wc.hInstance = nsToolkit::mDllInstance; wc.hInstance = nsToolkit::mDllInstance;