Skip to content

win32: the system UI font at the monitor's DPI, not DEFAULT_GUI_FONT - #170

Merged
nicolas-maman merged 3 commits into
mainfrom
feat/win32-system-font
Sep 19, 2026
Merged

nicolas-maman merged 3 commits into
mainfrom
feat/win32-system-font

Conversation

@nicolas-maman

Copy link
Copy Markdown
Contributor

A design-quality fix for Windows: every control was set in DEFAULT_GUI_FONT, the stock object that still answers "MS Shell Dlg" — Tahoma at 8 points, the face of 2001 — while the message font every Windows app has drawn its controls in since Vista is what NONCLIENTMETRICS carries (Segoe UI at 9 points, or whatever the user chose in Accessibility). A stock font also never scales, and the backend declares itself per-monitor DPI aware (v2), so on a 150% monitor Windows scaled nothing for it and every label drew at 96-DPI size.

  • w32_ui_font_for_dpi(dpi): SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS)'s lfMessageFont (Windows 10 1607+; pre-1607 the system-DPI metrics scaled), cached per DPI, outliving every window. w32_ui_font(hwnd) picks the window's monitor DPI (GetDpiForWindow), the system's while the widget is on the hidden holder.
  • The eight WM_SETFONT sites, the tab strip's bold base, apply_font's base (a custom font_size is now points at the window's DPI, from GetDpiForWindow, not GetDeviceCaps), and the vg text-metrics face go through it.
  • WM_DPICHANGED (w32_refont_tree): every widget under the window in the font at the new DPI — one with a size, weight or face of its own re-derived from the new base — then every stack laid out again, since every text just changed its measure.

Before/after on this box (system: Segoe UI 9pt, 96 DPI) — themes_demo, screen grabs: the Tahoma face with its squared letterforms and tighter em dashes, then Segoe UI. Verified natively: runtime test, 74 headless driver specs identical to main, 13 on-screen specs (typography, tables, lists, tabs, splits, weight clamp, themes, frames) pass.

Not in this PR, filed as a follow-up: the fixed pixel defaults in measure_widget (fields 140×26, progress 140×16, textarea 200×80, button/label padding) do not scale with DPI either.

Every control was set in DEFAULT_GUI_FONT, the stock object that still
answers "MS Shell Dlg" -- Tahoma at 8 points -- while the message font
every Windows app has drawn its controls in since Vista is what
NONCLIENTMETRICS carries (Segoe UI at 9 points, or the user's choice).
And a stock font never scales: the backend declares itself per-monitor
DPI aware, so on a 150% monitor nothing scaled it and every label drew
at 96-DPI size.

w32_ui_font_for_dpi answers SystemParametersInfoForDpi's message font,
cached per DPI; the eight WM_SETFONT sites, the tab strip's bold base,
apply_font's base (a custom size is now in points at the window's DPI)
and the vg metrics face go through it. WM_DPICHANGED re-fonts every
widget under the window and lays the stacks out again.
@nicolas-maman
nicolas-maman merged commit 02bbef8 into main Sep 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant