From 110edf32d0b2a2f0a49cdd76c977b9eedd06628e Mon Sep 17 00:00:00 2001
From: Henri Verbeet <hverbeet@locutus.nl>
Date: Mon, 17 Mar 2025 16:52:55 +0100
Subject: [PATCH] demos: Add basic DPI handling.

---
 demos/demo_win32.h | 17 +++++++++++++++++
 demos/demo_xcb.h   | 14 ++++++++++++++
 demos/gears.c      |  4 ++++
 demos/triangle.c   |  4 ++++
 4 files changed, 39 insertions(+)

diff --git a/demos/demo_win32.h b/demos/demo_win32.h
index 382e6030dd..55cb845954 100644
--- a/demos/demo_win32.h
+++ b/demos/demo_win32.h
@@ -31,6 +31,8 @@ struct demo
 
     void *user_data;
     void (*idle_func)(struct demo *demo, void *user_data);
+
+    UINT (*GetDpiForSystem)(void);
 };
 
 struct demo_window
@@ -48,6 +50,11 @@ struct demo_swapchain
     IDXGISwapChain3 *swapchain;
 };
 
+static inline void demo_get_dpi(struct demo *demo, double *dpi_x, double *dpi_y)
+{
+    *dpi_x = *dpi_y = demo->GetDpiForSystem();
+}
+
 static inline struct demo_window *demo_window_create(struct demo *demo, const char *title,
         unsigned int width, unsigned int height, void *user_data)
 {
@@ -191,6 +198,11 @@ static inline void demo_process_events(struct demo *demo)
     }
 }
 
+static inline UINT demo_GetDpiForSystem(void)
+{
+    return 96;
+}
+
 static inline bool demo_init(struct demo *demo, void *user_data)
 {
     WNDCLASSEXW wc;
@@ -215,6 +227,11 @@ static inline bool demo_init(struct demo *demo, void *user_data)
     demo->user_data = user_data;
     demo->idle_func = NULL;
 
+    if ((demo->GetDpiForSystem = (void *)GetProcAddress(GetModuleHandleA("user32"), "GetDpiForSystem")))
+        SetProcessDPIAware();
+    else
+        demo->GetDpiForSystem = demo_GetDpiForSystem;
+
     return true;
 }
 
diff --git a/demos/demo_xcb.h b/demos/demo_xcb.h
index f0ce8bc04a..b1f61212a5 100644
--- a/demos/demo_xcb.h
+++ b/demos/demo_xcb.h
@@ -198,6 +198,20 @@ static inline xcb_screen_t *demo_get_screen(xcb_connection_t *c, int idx)
     return NULL;
 }
 
+static inline void demo_get_dpi(struct demo *demo, double *dpi_x, double *dpi_y)
+{
+    xcb_screen_t *screen;
+
+    if (!(screen = demo_get_screen(demo->connection, demo->screen)))
+    {
+        *dpi_x = *dpi_y = 96.0;
+        return;
+    }
+
+    *dpi_x = screen->width_in_pixels * 25.4 / screen->width_in_millimeters;
+    *dpi_y = screen->height_in_pixels * 25.4 / screen->height_in_millimeters;
+}
+
 static inline struct demo_window *demo_window_create(struct demo *demo, const char *title,
         unsigned int width, unsigned int height, void *user_data)
 {
diff --git a/demos/gears.c b/demos/gears.c
index 1171c3c786..310958db10 100644
--- a/demos/gears.c
+++ b/demos/gears.c
@@ -849,12 +849,16 @@ static int cxg_main(void)
 {
     unsigned int width = 300, height = 300;
     struct cx_gears cxg;
+    double dpi_x, dpi_y;
 
     memset(&cxg, 0, sizeof(cxg));
     if (!demo_init(&cxg.demo, &cxg))
         return EXIT_FAILURE;
     demo_set_idle_func(&cxg.demo, cxg_idle);
 
+    demo_get_dpi(&cxg.demo, &dpi_x, &dpi_y);
+    width *= dpi_x / 96.0;
+    height *= dpi_y / 96.0;
     cxg.window = demo_window_create(&cxg.demo, "Vkd3d Gears", width, height, &cxg);
     demo_window_set_key_press_func(cxg.window, cxg_key_press);
     demo_window_set_expose_func(cxg.window, cxg_expose);
diff --git a/demos/triangle.c b/demos/triangle.c
index 936bab9769..bd106af5d8 100644
--- a/demos/triangle.c
+++ b/demos/triangle.c
@@ -368,12 +368,16 @@ static int cxt_main(void)
 {
     unsigned int width = 640, height = 480;
     struct cx_triangle cxt;
+    double dpi_x, dpi_y;
 
     memset(&cxt, 0, sizeof(cxt));
 
     if (!demo_init(&cxt.demo, NULL))
         return EXIT_FAILURE;
 
+    demo_get_dpi(&cxt.demo, &dpi_x, &dpi_y);
+    width *= dpi_x / 96.0;
+    height *= dpi_y / 96.0;
     cxt.window = demo_window_create(&cxt.demo, "Vkd3d Triangle", width, height, &cxt);
     demo_window_set_expose_func(cxt.window, cxt_render_frame);
     demo_window_set_key_press_func(cxt.window, cxt_key_press);
-- 
GitLab