Follow the system UI font face

Detect the desktop's configured interface font and use its family for all
application UI text, instead of iced's generic sans-serif.

- sys::ui_font reads the setting per platform: GNOME/Cinnamon/MATE
  gsettings, KDE kdeglobals, Xfce xfconf, the XDG Settings portal, GTK
  settings.ini and a Fontconfig fallback on Linux; the non-client message
  font (SystemParametersInfoForDpi at 96 DPI) on Windows; the AppKit system
  font on macOS.
- ui_font::apply remaps generic sans-serif in iced's shared font database
  to that family. iced's Font::DEFAULT is sans-serif, so every widget,
  canvas text, bold/italic variant and ribbon measurement follows it with
  no call-site changes. A family that is not installed (or a generic alias)
  keeps iced's own choice. The font's weight and style are ignored.
- Live updates: portal SettingChanged on Linux, a 2 s poll on Windows. A
  change bumps the font-system version so laid-out text reshapes, and
  iced::font::set_defaults relays out every window; ribbon large-button
  widths re-measure. Without a portal, Linux needs a restart; macOS has no
  user-adjustable UI font.
- Monospaced text, drawing text (own cosmic-text font systems) and the web
  build's font loading are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Manu VarkeyandClaude Opus 5.5 committed 2026-10-16 01:59:17 +05:30
1 parent bec9e63679
commit 62175f4ed5
10 files changed
+1134 -7

No files matched your search

+7
View File
@@ -2460,6 +2460,10 @@ pub enum Message {
ApplyWebFont(crate::scene::text::web_font::Script),
/// Completion of the UI renderer's runtime font registration.
WebUiFontLoaded(crate::scene::text::web_font::Script, Result<(), String>),
/// The desktop reported (or a poll may have found) a UI-font change.
UiFontSettingsChanged,
/// A re-read of the desktop UI font finished.
UiFontDetected(Option<crate::sys::ui_font::SystemUiFont>),
/// Ctrl+V. Routed by `update` into an open text editor, the drawing-object
/// clipboard, or the system text clipboard.
PasteShortcut,
@@ -5551,6 +5555,9 @@ use std::path::PathBuf;
#[cfg(not(target_arch = "wasm32"))]
pub fn run() -> iced::Result {
// UI text follows the desktop's interface font: generic sans-serif, iced's
// default font, is remapped to it before the first window opens.
crate::sys::ui_font::apply(crate::sys::ui_font::detect().as_ref());
iced::daemon(
OpenCADStudio::boot,
OpenCADStudio::update,
+21
View File
@@ -1052,6 +1052,27 @@ impl OpenCADStudio {
Task::none()
}
#[cfg(not(target_arch = "wasm32"))]
Message::UiFontSettingsChanged => Task::perform(
async { crate::sys::ui_font::detect() },
Message::UiFontDetected,
),
#[cfg(target_arch = "wasm32")]
Message::UiFontSettingsChanged => Task::none(),
// Re-setting the defaults recreates the renderers and lays out
// every window again with the remapped sans-serif family.
#[cfg(not(target_arch = "wasm32"))]
Message::UiFontDetected(system) => {
if crate::sys::ui_font::apply(system.as_ref()) {
iced::font::set_defaults(iced::Font::DEFAULT, 16.0)
} else {
Task::none()
}
}
#[cfg(target_arch = "wasm32")]
Message::UiFontDetected(_) => Task::none(),
Message::Tick(t) => self.on_tick(t),
Message::OpenFile => self.on_open_file(),
+17
View File
@@ -146,6 +146,22 @@ pub(in crate::app) const VIEWPORT_CAPTURE_BOUNDS_ID: &str = "viewport-capture-bo
const VIEWCUBE_HIT_SIZE: f32 = VIEWCUBE_REGION_PX;
/// Desktop UI-font changes while running. Linux listens for the Settings
/// portal's `SettingChanged` (no portal: restart to apply). Windows exposes no
/// change notification through iced, but the metrics read is a cheap system
/// call, so it is polled. macOS has no user-adjustable UI font, and the web
/// build follows the font it loads for the UI language.
fn ui_font_changes() -> Subscription<Message> {
#[cfg(target_os = "linux")]
return Subscription::run(crate::sys::ui_font::change_signals)
.map(|()| Message::UiFontSettingsChanged);
#[cfg(target_os = "windows")]
return iced::time::every(std::time::Duration::from_secs(2))
.map(|_| Message::UiFontSettingsChanged);
#[allow(unreachable_code)]
Subscription::none()
}
/// Background used by drafting overlays in model or paper space.
fn crosshair_background(tab: &DocumentTab, is_paper: bool) -> [f32; 4] {
if !is_paper {
@@ -3052,6 +3068,7 @@ impl OpenCADStudio {
single_instance,
hatch_pattern_keys,
keyboard_events,
ui_font_changes(),
])
}