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:
@@ -334,6 +334,22 @@ LRESULT CALLBACK D3D11Window::wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARA
|
||||
self->resize_height_ = HIWORD(lparam);
|
||||
}
|
||||
return 0;
|
||||
case WM_DPICHANGED:
|
||||
// Per-monitor-v2: the DPI of the display we're on changed. Resize to the rect Windows suggests
|
||||
// in lparam (its recommended handling; the resulting WM_SIZE repaints the swap chain via the
|
||||
// deferred-resize path above), then latch the new DPI for the overlay to rescale its font/style.
|
||||
if (self != nullptr)
|
||||
{
|
||||
if (const auto* suggested = reinterpret_cast<const RECT*>(lparam); suggested != nullptr)
|
||||
{
|
||||
SetWindowPos(hwnd, nullptr, suggested->left, suggested->top,
|
||||
suggested->right - suggested->left, suggested->bottom - suggested->top,
|
||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
}
|
||||
self->dpi_pending_ = true;
|
||||
self->pending_dpi_ = HIWORD(wparam); // X and Y DPI are equal; HIWORD is the Y value
|
||||
}
|
||||
return 0;
|
||||
case WM_SYSKEYDOWN:
|
||||
// F10 is our screenshot key; ImGui already saw this message (handler runs above),
|
||||
// so swallow it here to stop DefWindowProc from flicking into Win32 menu mode.
|
||||
|
||||
Reference in New Issue
Block a user