aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-05-21 21:28:08 -0400
committerDavid Robillard <d@drobilla.net>2022-05-21 22:03:22 -0400
commitfdd6de0d12ea17f713ec3e73e7968198339b7b6d (patch)
tree800b75e676f8320c2e22b3590751a63be3741fc5
parenta88b470d9c954073fcfcfeca2242809532eaf048 (diff)
downloadpugl-fdd6de0d12ea17f713ec3e73e7968198339b7b6d.tar.gz
pugl-fdd6de0d12ea17f713ec3e73e7968198339b7b6d.tar.bz2
pugl-fdd6de0d12ea17f713ec3e73e7968198339b7b6d.zip
Add puglGetScaleFactor()
-rw-r--r--include/pugl/pugl.h16
-rw-r--r--src/mac.m12
-rw-r--r--src/win.c43
-rw-r--r--src/win.h1
-rw-r--r--src/x11.c37
-rw-r--r--src/x11.h1
6 files changed, 106 insertions, 4 deletions
diff --git a/include/pugl/pugl.h b/include/pugl/pugl.h
index a7dd7eb..0d4642c 100644
--- a/include/pugl/pugl.h
+++ b/include/pugl/pugl.h
@@ -973,6 +973,22 @@ int
puglGetViewHint(const PuglView* view, PuglViewHint hint);
/**
+ Return the scale factor of the view.
+
+ This factor describe how large UI elements (especially text) should be
+ compared to "normal". For example, 2.0 means the UI should be drawn twice
+ as large.
+
+ "Normal" is loosely defined, but means a good size on a "standard DPI"
+ display (around 96 DPI). In other words, the scale 1.0 should have text
+ that is reasonably sized on a 96 DPI display, and the scale 2.0 should have
+ text twice that large.
+*/
+PUGL_API
+double
+puglGetScaleFactor(const PuglView* view);
+
+/**
@}
@defgroup frame Frame
Functions for working with the position and size of a view.
diff --git a/src/mac.m b/src/mac.m
index 67422a5..9cd3e1c 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -35,10 +35,12 @@ rectToScreen(NSScreen* screen, NSRect rect)
}
static NSScreen*
-viewScreen(PuglView* view)
+viewScreen(const PuglView* view)
{
return view->impl->window ? [view->impl->window screen]
- : [NSScreen mainScreen];
+ : [view->impl->wrapperView window]
+ ? [[view->impl->wrapperView window] screen]
+ : [NSScreen mainScreen];
}
static NSRect
@@ -1365,6 +1367,12 @@ puglSetWindowTitle(PuglView* view, const char* title)
return PUGL_SUCCESS;
}
+double
+puglGetScaleFactor(const PuglView* const view)
+{
+ return [viewScreen(view) backingScaleFactor];
+}
+
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
diff --git a/src/win.c b/src/win.c
index 8f2a26b..5e70b6f 100644
--- a/src/win.c
+++ b/src/win.c
@@ -35,6 +35,8 @@
#define PUGL_USER_TIMER_MIN 9470
typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void);
+typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*);
+typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*);
LRESULT CALLBACK
wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
@@ -112,6 +114,35 @@ puglWinGetWindowExFlags(const PuglView* const view)
return WS_EX_NOINHERITLAYOUT | (view->parent ? 0u : WS_EX_APPWINDOW);
}
+static double
+puglWinGetViewScaleFactor(const PuglView* const view)
+{
+ const HMODULE shcore = LoadLibrary("Shcore.dll");
+ if (!shcore) {
+ return 1.0;
+ }
+
+ const PFN_GetProcessDpiAwareness GetProcessDpiAwareness =
+ (PFN_GetProcessDpiAwareness)GetProcAddress(shcore,
+ "GetProcessDpiAwareness");
+
+ const PFN_GetScaleFactorForMonitor GetScaleFactorForMonitor =
+ (PFN_GetScaleFactorForMonitor)GetProcAddress(shcore,
+ "GetScaleFactorForMonitor");
+
+ DWORD dpiAware = 0;
+ DWORD scaleFactor = 100;
+ if (GetProcessDpiAwareness && GetScaleFactorForMonitor &&
+ !GetProcessDpiAwareness(NULL, &dpiAware) && dpiAware) {
+ GetScaleFactorForMonitor(
+ MonitorFromWindow(view->impl->hwnd, MONITOR_DEFAULTTOPRIMARY),
+ &scaleFactor);
+ }
+
+ FreeLibrary(shcore);
+ return (double)scaleFactor / 100.0;
+}
+
PuglWorldInternals*
puglInitWorldInternals(PuglWorldType type, PuglWorldFlags PUGL_UNUSED(flags))
{
@@ -214,7 +245,8 @@ puglRealize(PuglView* view)
puglSetWindowTitle(view, view->title);
}
- view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
+ view->impl->scaleFactor = puglWinGetViewScaleFactor(view);
+ view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
puglSetFrame(view, view->frame);
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
@@ -604,6 +636,9 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
InvalidateRect(view->impl->hwnd, NULL, false);
}
break;
+ case WM_DISPLAYCHANGE:
+ view->impl->scaleFactor = puglWinGetViewScaleFactor(view);
+ break;
case WM_WINDOWPOSCHANGED:
handleConfigure(view, &event);
break;
@@ -1002,6 +1037,12 @@ adjustedWindowRect(PuglView* const view,
return rect;
}
+double
+puglGetScaleFactor(const PuglView* const view)
+{
+ return view->impl->scaleFactor;
+}
+
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
diff --git a/src/win.h b/src/win.h
index 5c70e1e..f71dcf8 100644
--- a/src/win.h
+++ b/src/win.h
@@ -25,6 +25,7 @@ struct PuglInternalsImpl {
HCURSOR cursor;
HDC hdc;
PuglSurface* surface;
+ double scaleFactor;
bool flashing;
bool mouseTracked;
};
diff --git a/src/x11.c b/src/x11.c
index 5ae6b12..c2e9e96 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -14,6 +14,7 @@
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
+#include <X11/Xresource.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
@@ -106,6 +107,33 @@ initXSync(PuglWorldInternals* const impl)
return false;
}
+static double
+puglX11GetDisplayScaleFactor(Display* const display)
+{
+ double dpi = 96.0;
+ const char* const rms = XResourceManagerString(display);
+ if (rms) {
+ XrmDatabase db = XrmGetStringDatabase(rms);
+ if (db) {
+ XrmValue value = {0u, NULL};
+ char* type = NULL;
+ if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value)) {
+ if (!type || !strcmp(type, "String")) {
+ char* end = NULL;
+ const double xftDpi = strtod(value.addr, &end);
+ if (xftDpi > 0.0 && xftDpi < HUGE_VAL) {
+ dpi = xftDpi;
+ }
+ }
+ }
+
+ XrmDestroyDatabase(db);
+ }
+ }
+
+ return dpi / 96.0;
+}
+
PuglWorldInternals*
puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags)
{
@@ -121,7 +149,8 @@ puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags)
PuglWorldInternals* impl =
(PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals));
- impl->display = display;
+ impl->display = display;
+ impl->scaleFactor = puglX11GetDisplayScaleFactor(display);
// Intern the various atoms we will need
impl->atoms.CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0);
@@ -1367,6 +1396,12 @@ puglSetWindowTitle(PuglView* const view, const char* const title)
return PUGL_SUCCESS;
}
+double
+puglGetScaleFactor(const PuglView* const view)
+{
+ return view->world->impl->scaleFactor;
+}
+
PuglStatus
puglSetFrame(PuglView* const view, const PuglRect frame)
{
diff --git a/src/x11.h b/src/x11.h
index 49a1d06..1be54ad 100644
--- a/src/x11.h
+++ b/src/x11.h
@@ -39,6 +39,7 @@ struct PuglWorldInternalsImpl {
Display* display;
PuglX11Atoms atoms;
XIM xim;
+ double scaleFactor;
PuglTimer* timers;
size_t numTimers;
XID serverTimeCounter;