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