summaryrefslogtreecommitdiff
path: root/alf
diff options
context:
space:
mode:
authorJonas Kümmerlin <jonas@kuemmerlin.eu>2018-12-28 21:40:36 +0100
committerJonas Kümmerlin <jonas@kuemmerlin.eu>2018-12-28 21:40:36 +0100
commit416fe35c67352dd23ad698d8f732545caee3d82d (patch)
tree3a328b3e30d8ed0048fa342547efab413e971872 /alf
parenta5f3ea9ac12fccbc9faf3f152d4dfbe7f263268e (diff)
add per-monitor dpi support
Diffstat (limited to 'alf')
-rw-r--r--alf/alf.cpp36
-rw-r--r--alf/alf.h12
-rw-r--r--alf/alfcompat.cpp49
-rw-r--r--alf/alfdpiaware.cpp46
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;
diff --git a/alf/alf.h b/alf/alf.h
index d21a295..16767a7 100644
--- a/alf/alf.h
+++ b/alf/alf.h
@@ -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;
+ }
+}