M8: draw the macOS shortcut glyphs the UI font lacks

Menus and tooltips showed boxes for ⌃ ⌥ ↵ ⌫ ⇥ ⇞ ⇟ (e.g. Present ⌥⌘↵):
egui's default face has ⌘ and ⇧ but not these. The desktop app now adds
a system face that has them after the UI fonts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
JimKnoxx
2026-10-17 17:05:49 +02:00
co-authored by Claude Opus 5.5
parent c6d6433473
commit b84ee179d4
2 changed files with 48 additions and 0 deletions
+47
View File
@@ -274,6 +274,7 @@ pub fn install_fonts(ctx: &Context, system: bool, cjk: u8) {
.any(|x| x.has_char(c))
};
extra.extend(crate::bidi::script_fallbacks(&embedded));
extra.extend(key_symbol_fallbacks(&embedded));
extra.extend(crate::cjk::faces(cjk, lang, &embedded).iter().map(|f| (format!("system-{}-{}", f.family, f.style), font_data(f))));
}
extra.extend(craft(true));
@@ -288,6 +289,26 @@ pub fn install_fonts(ctx: &Context, system: bool, cjk: u8) {
ctx.set_fonts(fonts);
}
/// The glyphs macOS shortcuts are written with ([`figcraft_engine::keymap::display`]).
const KEY_SYMBOLS: &str = "⌃⌥⇧⌘⌫↵⇥⇞⇟←→↑↓";
/// System faces for the shortcut glyphs the UI's own fonts lack (egui's default face has ⌘ but
/// not ⌥ or ↵).
fn key_symbol_fallbacks(have: &dyn Fn(char) -> bool) -> Vec<(String, FontData)> {
const FAMILIES: [&str; 6] = ["Lucida Grande", "Apple Symbols", "Segoe UI Symbol", "DejaVu Sans", "Noto Sans Symbols 2", "FreeSans"];
let mut out = Vec::new();
let mut taken: Vec<Arc<figcraft_text::Face>> = Vec::new();
for c in KEY_SYMBOLS.chars() {
if have(c) || taken.iter().any(|f| f.has_char(c)) {
continue;
}
let Some(face) = figcraft_text::face_with_char(c, &FAMILIES) else { continue };
out.push((format!("system-{}-{}", face.family, face.style), font_data(&face)));
taken.push(face);
}
out
}
/// egui font data over a face's bytes, without copying them (CJK faces are 10–20 MB). Font
/// database faces are never dropped, so a system face's shared bytes are kept for good: leaking
/// one more reference to them costs a pointer and gives egui the `'static` slice it needs.
@@ -331,3 +352,29 @@ pub fn doc_c32(ctx: &Context, c: figcraft_color::Color) -> Color32 {
let conv = ctx.data(|d| d.get_temp::<figcraft_color::ProfileConversion>(screen_conversion_id()));
c32(conv.map_or(c, |k| k.apply(c)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ui_font_draws_every_mac_shortcut_glyph() {
figcraft_text::scan_system_fonts();
if key_symbol_fallbacks(&|_| false).is_empty() {
eprintln!("no system face with shortcut glyphs; skipping");
return;
}
let ctx = Context::default();
install_fonts(&ctx, true, 0);
let input =
egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::pos2(0.0, 0.0), egui::vec2(100.0, 100.0))), ..Default::default() };
ctx.run_ui(input, |_| {}).textures_delta.clear();
ctx.fonts_mut(|f| {
for c in KEY_SYMBOLS.chars() {
for font in [regular(11.0), semibold(11.0)] {
assert!(f.has_glyphs(&font, &c.to_string()), "UI font draws {c:?}");
}
}
});
}
}
+1
View File
@@ -172,6 +172,7 @@ in the table. `crates/ui-egui/src/shortcut_keys_tests.rs` drives the keys a look
| Date | Change | Summary |
|---|---|---|
| 2026-10-17 | patch | macOS shortcut keycaps draw ⌃ ⌥ ↵ ⌫ ⇥ ⇞ ⇟ in menus and tooltips (they were boxes): the desktop app adds a system face with them (Lucida Grande, Apple Symbols, Segoe UI Symbol, DejaVu Sans…) after the UI fonts. Checked in the app on macOS. The web build on a Mac still shows boxes (no system fonts there). Summary and hours unchanged |
| 2026-10-17 | minor | The community batches #733, #735, #736, #729 and #753: submenus open after a short hover, keep their place along a safe triangle and reopen closed (main and context menus); the Actions palette's tabs, ranked search, keyboard highlight and recents; menu items that need a value ask for it, File ▸ Rename edits in place; Shift+I and Resources open Assets; a draggable Pages/Layers divider; Shift-drag moves the selection; a double-click near a thin stroke, merging dropped points and Flatten keeping open paths in vector editing; live font preview and the selection highlight after line breaks; the colour picker on a new fill or stroke; Paste over and Paste properties from the keyboard; Selection colors (partial: no library styles or variables there) and smart-selection spacing fields and canvas handles (partial: no reorder rings), both also checked by their author on macOS; the keyboard shortcuts panel closes on the home screen; Adwaita window controls on Wayland compositors without server decorations (checked by its author on GNOME; KDE not run). Checked in the app on Windows (submenus by their author), not side by side with Figma. Summary and hours unchanged |
| 2026-10-15 | minor | Hex fields take CSS colour names (`red` → `FF0000`): fills, strokes, effects, grids, variables, backgrounds and the colour picker |
| 2026-10-15 | minor | Typography: drag the line-height, letter-spacing and paragraph-spacing icons to scrub their values; shared numeric-field rates, resize cursor and one Undo step per gesture (#373). |