Make the host per-monitor DPI aware and scale the ImGui overlay

The window sized itself to GetSystemMetrics(SM_CXSCREEN/CYSCREEN) but the
process was DPI-unaware, so on a scaled display (e.g. 4K @ 150%) Windows
handed us a virtualized resolution and bitmap-stretched the whole window up
to native -- softening the mirror, which is the tool's entire point.

Declare per-monitor-v2 awareness at startup so GetSystemMetrics/GetDpiForWindow
report true pixels. That alone would shrink the fixed-13px ImGui overlay to
crisp-but-tiny, so pair it with UI scaling: rebuild the default-font atlas at a
DPI-scaled SizePixels (crisp at the target size, unlike FontGlobalScale's
bitmap stretch) and ScaleAllSizes() the style. Net: same physical size as
before, now sharp.

- common/include/coop/dpi.hpp: pure DPI->scale math (uses USER_DEFAULT_SCREEN_DPI
  and a named kBaseFontPx, not bare 96/13 literals), with a zero fallback and
  clamping. Unit-tested by tests/dpi_test.cpp.
- imgui_layer: apply_dpi() at init from GetDpiForWindow; set_dpi() for runtime
  changes (rebuild atlas + reset/scale style + invalidate the DX11 font texture).
- d3d11_window: latch WM_DPICHANGED (honor the suggested rect), expose
  take_dpi_change(); main loop polls it and calls imgui.set_dpi() between frames.

The DPI math is unit-tested; the actual awareness + font rasterization + live
WM_DPICHANGED rescale are verified by hand.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 23:23:41 +02:00
parent e4aafa08db
commit d73b43ad0d
8 changed files with 198 additions and 1 deletions

View File

@@ -105,6 +105,11 @@ add_executable(tool_paths_test tool_paths_test.cpp)
target_link_libraries(tool_paths_test PRIVATE coop_common)
add_test(NAME tool_paths_test COMMAND tool_paths_test)
# Unit test for the DPI -> UI scale math (baseline/known scalings, zero fallback, clamping, font px).
add_executable(dpi_test dpi_test.cpp)
target_link_libraries(dpi_test PRIVATE coop_common)
add_test(NAME dpi_test COMMAND dpi_test)
# Unit test for the audio mixer math (decode/sum/soft-clip/encode). Header-only.
add_executable(audio_mix_test audio_mix_test.cpp)
target_include_directories(audio_mix_test PRIVATE ${CMAKE_SOURCE_DIR}/host/src)
@@ -388,6 +393,7 @@ coop_output_subdir(tests
shared_memory_test
wav_test
tool_paths_test
dpi_test
mkb_map_test
audio_mix_test
tone_analysis_test