diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2018-12-28 21:40:36 +0100 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2018-12-28 21:40:36 +0100 |
| commit | 416fe35c67352dd23ad698d8f732545caee3d82d (patch) | |
| tree | 3a328b3e30d8ed0048fa342547efab413e971872 /alf | |
| parent | a5f3ea9ac12fccbc9faf3f152d4dfbe7f263268e (diff) | |
add per-monitor dpi support
Diffstat (limited to 'alf')
| -rw-r--r-- | alf/alf.cpp | 36 | ||||
| -rw-r--r-- | alf/alf.h | 12 | ||||
| -rw-r--r-- | alf/alfcompat.cpp | 49 | ||||
| -rw-r--r-- | alf/alfdpiaware.cpp | 46 |
4 files changed, 128 insertions, 15 deletions
diff --git a/alf/alf.cpp b/alf/alf.cpp index 2ec33ca..9b2f60f 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -1,5 +1,9 @@ #include "alfpriv.h" +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif + /* ALF App and Window */ static void @@ -39,31 +43,25 @@ ALF_UpdateFontForWidget(ALFWindowPriv *priv, ALFWidgetPriv *widget) { if (widget->hwnd && (widget->flags & ALF_MESSAGEFONT) == ALF_MESSAGEFONT) { SendMessage(widget->hwnd, WM_SETFONT, (WPARAM)priv->fonts.hMessageFont, (LPARAM)NULL); + + // XXX: Invalidating should IMHO be the decision of the control, but at + // least the commctl32 V5 static control doesn't do it. + InvalidateRect(widget->hwnd, NULL, TRUE); } } void ALF_UpdateFonts(HWND win) { - // TODO per-monitor DPI aware: GetDpiForWindow, SystemParametersInfoForDpi etc. ALFWindowPriv *priv = (ALFWindowPriv*)GetWindowLongPtr(win, 0); - priv->fonts.dpi = 0; - HDC hdcScreen = GetDC(NULL); - if (hdcScreen) { - priv->fonts.dpi = GetDeviceCaps(hdcScreen, LOGPIXELSY); - ReleaseDC(NULL, hdcScreen); - } - - if (!priv->fonts.dpi) { - priv->fonts.dpi = 96; // FIXME! fallback to default DPI - } + priv->fonts.dpi = priv->app->compatFn->GetDpiForWindow(win); NONCLIENTMETRICS ncm; ZeroMemory(&ncm, sizeof(ncm)); ncm.cbSize = sizeof(ncm); - if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0)) { + if (priv->app->compatFn->SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, priv->fonts.dpi)) { priv->fonts.lfMessageFont = ncm.lfMessageFont; } else { // FIXME! fallback to default font, 8pt MS Shell Dlg @@ -375,11 +373,12 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) tmp.right = priv->layout.totalMinWidth; tmp.bottom = priv->layout.totalMinHeight; - // TODO ..ForDpi - if (AdjustWindowRectEx(&tmp, + if (priv->app->compatFn->AdjustWindowRectExForDpi( + &tmp, GetWindowLong(hwnd, GWL_STYLE), GetMenu(hwnd) != NULL, - GetWindowLong(hwnd, GWL_EXSTYLE))) { + GetWindowLong(hwnd, GWL_EXSTYLE), + priv->fonts.dpi)) { MINMAXINFO *i = (MINMAXINFO *)lparam; i->ptMinTrackSize.x = tmp.right - tmp.left; i->ptMinTrackSize.y = tmp.bottom - tmp.top; @@ -417,6 +416,13 @@ ALF_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) ALF_DestroyWindowPriv(priv); } + if (msg == WM_DPICHANGED) { + ALF_UpdateFonts(hwnd); + ALF_RecalculateLayout(hwnd); + RECT *r = (RECT*)lparam; + SetWindowPos(hwnd, NULL, r->left, r->top, r->right-r->left, r->bottom-r->top, SWP_NOACTIVATE|SWP_NOZORDER); + } + if (msg == DM_GETDEFID) { if (priv->defid == (WORD)-1) { return 0; @@ -76,10 +76,22 @@ typedef struct { BOOL (WINAPI *RemoveWindowSubclass)(HWND, ALF_COMPAT_SUBCLASSPROC, UINT_PTR); int (WINAPI *GetSystemMetricsForDpi)(int, UINT); BOOL (WINAPI *IsAppThemed)(void); + UINT (WINAPI *GetDpiForWindow)(HWND); + BOOL (WINAPI *SystemParametersInfoForDpi)(UINT,UINT,PVOID,UINT,UINT); + BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT); } ALFCompatFunctions; typedef struct ALFAppPriv *ALFAPP; +typedef enum { + ALF_DPI_AWARENESS_UNAWARE, + ALF_DPI_AWARENESS_SYSTEM_AWARE, + ALF_DPI_AWARENESS_PER_MONITOR_AWARE_V2 +} ALFDpiAwareness; + +void +ALF_SetDpiAwareness(ALFDpiAwareness awareness); + ALFAPP ALF_CreateApplication(HINSTANCE hInstance); diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp index 3ffc9f9..e6a9851 100644 --- a/alf/alfcompat.cpp +++ b/alf/alfcompat.cpp @@ -41,6 +41,42 @@ fallbackIsAppThemed(void) return FALSE; } +static UINT WINAPI +fallbackGetDpiForWindow(HWND win) +{ + (void)win; + + UINT dpi = 0; + + HDC hdcScreen = GetDC(NULL); + if (hdcScreen) { + dpi = GetDeviceCaps(hdcScreen, LOGPIXELSY); + ReleaseDC(NULL, hdcScreen); + } + + if (!dpi) { + dpi = 96; // FIXME! fallback to default DPI + } + + return dpi; +} + +static BOOL WINAPI +fallbackSystemParametersInfoForDpi(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni, UINT dpi) +{ + (void)dpi; + + return SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni); +} + +static BOOL WINAPI +fallbackAdjustWindowRectExForDpi(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi) +{ + (void)dpi; + + return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle); +} + ALFCompatFunctions * ALF_CreateCompatFuncTable(void) { @@ -61,6 +97,19 @@ ALF_CreateCompatFuncTable(void) COMPAT(comctl32.dll, DefSubclassProc, 413, NULL); COMPAT(comctl32.dll, RemoveWindowSubclass, 412, NULL); COMPAT(user32.dll, GetSystemMetricsForDpi, 0, fallbackGetSystemMetricsForDpi); + COMPAT(user32.dll, GetDpiForWindow, 0, fallbackGetDpiForWindow); + + // FIXME: SystemParametersInfoForDpi is Unicode-Only. + // Writing a wrapper function would have been The Right Way, but such a function + // is yet to be written. So the current practical recommendation is to make + // ANSI builds System DPI aware only. +#ifdef UNICODE + COMPAT(user32.dll, SystemParametersInfoForDpi, 0, fallbackSystemParametersInfoForDpi); +#else + compatfn->SystemParametersInfoForDpi = fallbackSystemParametersInfoForDpi; +#endif + + COMPAT(user32.dll, AdjustWindowRectExForDpi, 0, fallbackAdjustWindowRectExForDpi); // IsAppThemed would return TRUE even when we're linked against comctl32 v5 if (ALF_DllGetVersion("comctl32.dll") >= 0x60000) { diff --git a/alf/alfdpiaware.cpp b/alf/alfdpiaware.cpp new file mode 100644 index 0000000..8f998f7 --- /dev/null +++ b/alf/alfdpiaware.cpp @@ -0,0 +1,46 @@ +#include "alfpriv.h" + +typedef BOOL (WINAPI *PSetProcessDpiAwarenessContext)(HANDLE); +typedef BOOL (WINAPI *PSetProcessDPIAware)(void); + +static void +ALF_SetSystemDpiAwareness(void) +{ + HMODULE user32 = GetModuleHandleA("user32.dll"); + + PSetProcessDPIAware p = (PSetProcessDPIAware) + (void*)GetProcAddress(user32, "SetProcessDPIAware"); + if (p) { + p(); + } +} + +static void +ALF_SetPerMonitorAwareness(void) +{ + HMODULE user32 = GetModuleHandleA("user32.dll"); + + PSetProcessDpiAwarenessContext p = (PSetProcessDpiAwarenessContext) + (void*)GetProcAddress(user32, "SetProcessDpiAwarenessContext"); + + if (p && p((HANDLE)-4)) /* DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 */ + return; + + ALF_SetSystemDpiAwareness(); +} + +void +ALF_SetDpiAwareness(ALFDpiAwareness awareness) +{ + switch (awareness) { + case ALF_DPI_AWARENESS_PER_MONITOR_AWARE_V2: + ALF_SetPerMonitorAwareness(); + return; + case ALF_DPI_AWARENESS_SYSTEM_AWARE: + ALF_SetSystemDpiAwareness(); + return; + default: + // unaware, or could not set awareness + return; + } +} |
