From fc10f01009dea7e87195592933c5c7ba29cd65f6 Mon Sep 17 00:00:00 2001 From: JDonaghy Date: Sun, 30 Aug 2026 18:22:52 -0500 Subject: [PATCH] =?UTF-8?q?fix(#704):=20item=201=20=E2=80=94=20real=20Linu?= =?UTF-8?q?x=20UI=20fonts=20ahead=20of=20generic=20Sans=20fallback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit quadraui#624 (already in the pinned rev, 097eb5f4) lifted `set_ui_font` onto non-dialog chrome (tab bar, status bar, tree, menu bar), clearing #704's "do not start before #624 lands" blocker for the font-family half of Tier 2b. `UI_FONT_FAMILY` led with "Segoe UI, Ubuntu, Droid Sans, Sans" — two names that never resolve on Linux, and no Cantarell (GNOME's default UI font) at all — so a GNOME box without the Ubuntu font package fell through to generic Sans/DejaVu Sans, wider and taller-x-height than VS Code's chrome text at the same nominal size. Reordered to try the two real Linux desktop UI fonts (Cantarell, Ubuntu) first, keeping the Windows/legacy names and the Sans catch-all after. Left ui_font_size at 10pt: VS Code's 13px is only a ~2% difference, dwarfed by the family fix's own metric change. Added a GtkDriver test proving `Backend::set_ui_font` reaches the tab bar (the sibling breadcrumb test already covered the status-bar half) — the practical form of #704's "chrome glyph extents change when UI_FONT_FAMILY changes on a non-dialog surface" acceptance bullet, since family has no runtime setting to vary directly but travels with size through the identical Pango font-description string. Item 2 (panel separator borders) needs no vimcode code change: I found quadraui's `AppShell::render` already paints a sidebar/main- content divider (`AppShellLayout.divider_bounds`, both backends, via the shared compose controller) — but its color is a hardcoded `Color::rgb(100, 100, 110)` with no themed-color parameter and no `Backend::theme()` getter for `AppShell` to read `border_fg` back from. The seam facility exists structurally; it isn't themeable. Per the issue's explicit branching instruction this is a "file a quadraui issue and stop" outcome, not a vimcode change — flagging for the coordinator to file on JDonaghy/quadraui (worker sessions don't run gh): AppShell's divider needs either a settable divider color or to read `border_fg` back from the backend, so vimcode can theme it to match VS Code Dark Modern's #2B2B2B. Co-Authored-By: Claude Sonnet 5 --- src/gtk/mod.rs | 29 ++++++++++++++++++++++++- src/gtk/testing.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/gtk/mod.rs b/src/gtk/mod.rs index 6a93f28b..3df8ca8f 100644 --- a/src/gtk/mod.rs +++ b/src/gtk/mod.rs @@ -61,7 +61,34 @@ type TabSlotMap = HashMap>; /// paints directly, e.g. the menu-bar font and the breadcrumb-heading /// font), so they moved rather than being deleted with the rest of /// the file. -const UI_FONT_FAMILY: &str = "Segoe UI, Ubuntu, Droid Sans, Sans"; +/// +/// #704 item 1: the old list (`"Segoe UI, Ubuntu, Droid Sans, Sans"`) +/// led with two names that never resolve on Linux — Segoe UI is +/// Windows-only, Droid Sans was retired from Android a decade ago — +/// and never listed Cantarell, the default UI font on GNOME (the most +/// common Linux desktop and the one this project targets). On a +/// GNOME box without the `Ubuntu` font package installed, fontconfig +/// fell through the whole list to the trailing generic `Sans`, which +/// resolves to DejaVu Sans: wider, with a taller x-height, than what +/// VS Code lands on at the same nominal point size (VS Code's own +/// `-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Ubuntu, +/// "Droid Sans", sans-serif` stack has the identical problem, but +/// Electron's Chromium has extra fallback logic Pango/fontconfig does +/// not). Reordered so the two real Linux desktop UI fonts — Cantarell +/// (GNOME) and Ubuntu (Ubuntu/Unity) — are tried first, ahead of the +/// Windows/legacy names kept only for a hypothetical native-Windows +/// GTK build; `Sans` remains the final catch-all so a system with none +/// of the above still gets *a* font rather than a Pango parse failure. +/// This was blocked on quadraui#624 landing `Backend::set_ui_font` +/// reaching non-dialog chrome (tab bar, status bar, tree, menu bar) — +/// before that, changing this constant only affected `draw_dialog`/ +/// `draw_rich_text_popup` and nothing else (see the issue's "Negative +/// example" reference to #700 item 1's no-op shape). `ui_font_size` +/// (`core::settings::default_ui_font_size`, 10pt ≈ 13.3px at 96dpi) is +/// left as-is: VS Code's 13px default is a ~2% difference, dwarfed by +/// the metric change from fixing the family, so nudging both at once +/// would make it impossible to tell which change did what. +const UI_FONT_FAMILY: &str = "Cantarell, Ubuntu, Segoe UI, Droid Sans, Sans"; /// Process-global UI font size (points). Synced from /// `settings.ui_font_size` at the start of each frame by diff --git a/src/gtk/testing.rs b/src/gtk/testing.rs index ed76ee2b..2537fc4e 100644 --- a/src/gtk/testing.rs +++ b/src/gtk/testing.rs @@ -1572,6 +1572,60 @@ mod tests { ); } + /// #704 item 1 / quadraui#624: tab labels must also honour + /// `Backend::set_ui_font` — the other non-dialog surface #704's + /// acceptance criterion names ("a tab label or status-bar segment"; + /// the sibling test just above already covers the status-bar/breadcrumb + /// half). `draw_tab_bar_icons`'s paint call and its no-paint measurement + /// twin both switched to `ui_font` under quadraui#624 — before that + /// landed, every chrome surface except `draw_dialog`/ + /// `draw_rich_text_popup` painted with the shared *editor* Pango layout, + /// so `set_ui_font` was silently a no-op here too (#704's "Do not start + /// this before quadraui#624 lands" blocker, now cleared). + /// + /// #704's actual code change is widening `UI_FONT_FAMILY` (this module, + /// `gtk/mod.rs`) to try real Linux desktop UI fonts (Cantarell, Ubuntu) + /// ahead of the generic `Sans` fallback it used to collapse to. There is + /// no user-facing `ui_font_family` setting to vary directly the way + /// `ui_font_size` can be (see the sibling test), and family+size travel + /// to the paint backend as ONE Pango font-description string + /// (`UI_FONT()`, `App::render_content`'s `backend.set_ui_font(&UI_FONT())` + /// call) with no separate code path for either half. So proving the + /// *size* half reaches the tab bar — mirroring quadraui#624's own GTK + /// positive control, `gtk_backend_menu_bar_layout_ui_font_size_is_not_inert` + /// — is proof the *family* half reaches it too: this is the practical + /// form of "chrome glyph extents change when `UI_FONT_FAMILY` changes, + /// on a surface that is not a dialog" that a hardcoded `const` (rather + /// than a runtime setting) admits. + #[test] + fn tab_label_width_tracks_ui_font_size_not_editor_font_size() { + let mut engine_small = engine_with_three_named_tabs(); + engine_small.settings.ui_font_size = 8; + let h_small = harness(engine_small, 1400, 900); + let small = h_small + .driver + .find_bounds("alpha703") + .expect("the tab label must paint"); + + let mut engine_big = engine_with_three_named_tabs(); + engine_big.settings.ui_font_size = 28; + let h_big = harness(engine_big, 1400, 900); + let big = h_big + .driver + .find_bounds("alpha703") + .expect("the tab label must paint"); + + assert!( + big.width > small.width * 1.5, + "tab label glyph width must track settings.ui_font_size (8 vs \ + 28 pt): got small={:?} big={:?} — if these are close, \ + `Backend::set_ui_font` isn't reaching the tab bar and labels \ + are stuck at quadraui's hardcoded chrome-font default", + small, + big + ); + } + /// #705 item 5 / quadraui#625: menu-bar mnemonic underlines must not /// paint unconditionally. Before quadraui#625, `alt_char_byte_range` /// fell back to underlining char 0 whenever a label carried no `&` at