From 67ec657af6fea892b254cbbee88bc732fb2014e9 Mon Sep 17 00:00:00 2001 From: Martin Ball <98639962+benandez@users.noreply.github.com> Date: Thu, 22 Oct 2026 00:30:13 +0100 Subject: [PATCH] Legacy menu keys: Alt, V, U and 17 more Word 2003 sequences (#1697) (#1769) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #1678: Focus fills the screen; Full Screen View is a bindable command View › Focus goes full screen with the document on black and a slim bar whose "⋯" drops the ribbon over the page. Full Screen View (view.fullScreenView, no default key; bind one in Customize Keyboard) shows the pages alone with the search box above them; the two turn each other off. Full Screen (view.fullScreen, F11, #980) keeps its whole-window behaviour. Escape leaves Focus or Full Screen View, then Full Screen, once nothing nearer takes it; the system leaving full screen ends all three. Ctrl+F1 collapses the ribbon (not on macOS). Immersive Reader no longer turns Focus on. The page widget keeps a fixed id so it keeps focus when the rulers hide. Fixes #1678 Co-Authored-By: Claude Opus 5.5 (1M context) * #1678: one Focus path after the rebase; pin the dropped ribbon staying down on a ribbon click main's Focus (#1017) consumed Escape in WordApp::ui before leave_full_screen, so Escape would leave Focus even when it should first collapse a selection or close a popup. That handler is removed: Focus, Full Screen View and Full Screen are left through leave_full_screen only. main's focus_hides_the_ribbon_and_escape_brings_it_back still pins the panes coming back. Full Screen View and Show the ribbon added to the hr, ko and sv catalogs, which main gained since. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013kKPnx8r1vcYumjyL3kcuz * #1678: Show the ribbon is a named button; a bound Ctrl+F1 wins; Esc in Read Mode leaves a dialog's Escape alone Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013kKPnx8r1vcYumjyL3kcuz * #1678: parity checklist regenerated after the rebase (Full Screen View counted) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013kKPnx8r1vcYumjyL3kcuz * #1678: harness tests for the one Escape path and Ctrl+F1 through the app In Focus with text selected on the page, the first Escape collapses the selection and keeps Focus; the second leaves Focus (fails if the old focus_mode Escape handler in WordApp::ui comes back). Ctrl+F1 sent as a key event collapses the ribbon when unbound, and runs the user's command when bound in the keymap, leaving the ribbon alone (not on macOS). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013kKPnx8r1vcYumjyL3kcuz * #1678: review — a click on the dropped Focus ribbon gives the page the keyboard; only Ctrl+F1 yields to a binding The ribbon dropped over the page in Focus lies over the canvas viewport and in a Middle-order area, so refocus_after_chrome_click skipped clicks on it and typing went nowhere until the page was clicked (which also put the ribbon away). Clicks on the focus_ribbon layer now count as chrome. The Focus test asserts the page has the keyboard after a ribbon click and that typing reaches it with the ribbon still down. dispatch checks the keymap ahead of an interface shortcut only for Ctrl+F1; Alt+Q and Cmd+Option+R keep their place ahead of user bindings, as before #1678 (test: a_bound_alt_q_still_opens_command_search). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr * #1678: review — Ctrl+F1 (⌘⌥R on macOS) collapses or expands the ribbon; a shortcut of your own on Ctrl+F1 wins Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr * #1678: review — ui-parity's Word column gives Word for Mac's ribbon shortcut (⌘⌥R) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr * #1678: review — Focus's dropped ribbon is a command, ui.focusRibbon; "⋯" and a click on the page run it Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr * #1678: review — the Focus UI test turns Focus on from the status bar's Focus button Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr * #1697: legacy menu keys (Alt, V, U and 17 more Word 2003 sequences) After Alt, a letter no tab keytip or Search uses starts a legacy menu sequence, as Word for Windows still takes them (observed there): Alt, V, U turns on Full Screen View; also views, ruler, zoom, Select All, Find / Replace / Go To, Symbol, Picture, Font, Paragraph, Word Count and Insert Table. Hidden as in Word; a hint under the tab row names the keys so far. A letter that leads nowhere is ignored, Esc cancels, Alt goes back to the tab badges. Tests keep the first letters off every ribbon letter and check each target exists. Fixes #1697 Co-Authored-By: Claude Opus 5.5 (1M context) * #1697: legacy menu keys stay off on macOS, F10's badges included Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013kKPnx8r1vcYumjyL3kcuz * #1697: review — the legacy hint shows without a ribbon; Alt, V, U through the app; not on macOS in the docs With no ribbon showing (Focus, Full Screen View) no tab rects are recorded, so Alt, V's hint didn't show; it now hangs under the slim bar at the top of the window. A harness test drives Alt, V, U through the whole app and checks no letter is typed. The parity row and progress log say the sequences are not on macOS. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012WEhZXSxzS8orX7f9J3qpr --------- Co-authored-by: Claude Opus 5.5 (1M context) Co-authored-by: aiongg --- ROADMAP.md | 4 +- crates/ui-egui/src/chrome.rs | 7 +- crates/ui-egui/src/i18n/bg.tsv | 1 + crates/ui-egui/src/i18n/cs.tsv | 1 + crates/ui-egui/src/i18n/de.tsv | 1 + crates/ui-egui/src/i18n/es.tsv | 1 + crates/ui-egui/src/i18n/et.tsv | 1 + crates/ui-egui/src/i18n/fr.tsv | 1 + crates/ui-egui/src/i18n/hr.tsv | 1 + crates/ui-egui/src/i18n/hu.tsv | 1 + crates/ui-egui/src/i18n/it.tsv | 1 + crates/ui-egui/src/i18n/ja.tsv | 1 + crates/ui-egui/src/i18n/ko.tsv | 1 + crates/ui-egui/src/i18n/pl.tsv | 1 + crates/ui-egui/src/i18n/pt-br.tsv | 1 + crates/ui-egui/src/i18n/ru.tsv | 1 + crates/ui-egui/src/i18n/sr-latn.tsv | 1 + crates/ui-egui/src/i18n/sr.tsv | 1 + crates/ui-egui/src/i18n/sv.tsv | 1 + crates/ui-egui/src/i18n/tr.tsv | 1 + crates/ui-egui/src/i18n/uk.tsv | 1 + crates/ui-egui/src/i18n/vi.tsv | 1 + crates/ui-egui/src/i18n/zh-hans.tsv | 1 + crates/ui-egui/src/i18n/zh-hant.tsv | 1 + crates/ui-egui/src/keytips.rs | 196 ++++++++++++++++++++++++++++ crates/ui-egui/src/ribbon.rs | 3 + docs/ui-parity.md | 5 +- 27 files changed, 232 insertions(+), 5 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 774f6893d..1e11bdd9b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,7 +2,7 @@ **Stage: alpha** · next: beta, ~15 points (60% → 75% ready for real work) and ~150–230 h away -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-21 · **Change:** trivial (progress log: shape gradients and transparency, #1500; previously trivial: progress log: Focus fills the screen, and Full Screen View shows the pages alone, #1678; previously trivial: progress log: text above a float's anchor wraps around it, #2048; previously trivial: progress log: File › Recover follows the app theme, #3243; previously trivial: progress log: caret inside ligatures, #1974; previously trivial: text typed into a content control takes the control's formatting; localized placeholder styles recognised; previously trivial: forms protection keeps its content controls: no inserting, Properties or Remove Content Control; previously trivial: long navigation headings wrap onto further lines within the pane, #3015; previously trivial: clearing a no-match font query keeps the recent heading visible, #2068; previously trivial: a word after a slash wraps whole, like Word, #2963; previously trivial: progress log: a header-cell picture watermark sits behind the text, #1775; previously trivial: symbols keep their font when the text font changes, #2036; previously trivial: opening a DOCX no longer copies its pictures; previously trivial: Add Font imports every selected font file, #1789); previously trivial (RTF export writes sections (gap 19); previously trivial: ODT export writes sections (gap 19); previously trivial: Read Aloud speaks each sentence in its own language, #1843; previously trivial: hint-reliant CJK outlines; previously trivial: Ctrl+wheel zoom no longer scrolls the document, #1743; previously trivial: progress log: Turkish case mapping in AutoCorrect, #1923; previously trivial: a mouse drag on a table leaves the view where it is, #1738; previously trivial: progress log: Hebrew field results and smart quotes, #1670; previously trivial: Backspace removes a selected table, rows or columns, #1844; previously trivial: progress log: mixed Hebrew/Latin text keeps its order in Word, #1543; previously trivial: progress log: web typing in non-Latin text no longer repeats, #1480; previously trivial: progress log: font family caches bounded and math font lookups follow font changes, #1354; previously trivial: `-->` AutoCorrect replacement, #2223; previously trivial: numbered headings, #1793; previously trivial: Navigation Find exposes Results, #2096; previously trivial: progress log: Columns on selected text, #2024; previously trivial: progress log: legacy outline, shadow, emboss and imprint text effects drawn, #2534; previously trivial: progress log: Indonesian proofing, #498; previously trivial: progress log: DOCX glossary documents (building blocks); previously trivial: progress log: Read Mode keeps the keyboard and shows whole, unobscured columns, #1772); previously trivial: progress log: font list entries of tall-ascent fonts no longer cut off, #2570); previously trivial: progress log: Split Cells and Convert Text to Table dialogs follow the Word check, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout fills the window width, #1876; previously trivial: progress log: Different First Page headers reachable from page 1, #2826; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717); previously trivial: progress log: web preferences kept between visits, #2132; previously trivial: progress log: undrawable private-use list bullets show the level's default bullet, #1683; previously trivial: progress log: `w:eastAsianLayout` kept on save; previously trivial: table style editor formats every part, #714); previously trivial: VML freeforms read and kept on save; previously trivial: progress log: consistent preferred cell widths; previously trivial: multi-paragraph field instructions no longer add blank lines; previously trivial: page-break-only list paragraphs hide their labels; previously trivial: progress log: grouped `flowChartOr` shapes draw their circle and crossing spokes; previously trivial: progress log: copies keep their formatting in other programs, #1523; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-21 · **Change:** trivial (progress log: legacy menu keys, #1697; previously trivial: progress log: shape gradients and transparency, #1500; previously trivial: progress log: Focus fills the screen, and Full Screen View shows the pages alone, #1678; previously trivial: progress log: text above a float's anchor wraps around it, #2048; previously trivial: progress log: File › Recover follows the app theme, #3243; previously trivial: progress log: caret inside ligatures, #1974; previously trivial: text typed into a content control takes the control's formatting; localized placeholder styles recognised; previously trivial: forms protection keeps its content controls: no inserting, Properties or Remove Content Control; previously trivial: long navigation headings wrap onto further lines within the pane, #3015; previously trivial: clearing a no-match font query keeps the recent heading visible, #2068; previously trivial: a word after a slash wraps whole, like Word, #2963; previously trivial: progress log: a header-cell picture watermark sits behind the text, #1775; previously trivial: symbols keep their font when the text font changes, #2036; previously trivial: opening a DOCX no longer copies its pictures; previously trivial: Add Font imports every selected font file, #1789); previously trivial (RTF export writes sections (gap 19); previously trivial: ODT export writes sections (gap 19); previously trivial: Read Aloud speaks each sentence in its own language, #1843; previously trivial: hint-reliant CJK outlines; previously trivial: Ctrl+wheel zoom no longer scrolls the document, #1743; previously trivial: progress log: Turkish case mapping in AutoCorrect, #1923; previously trivial: a mouse drag on a table leaves the view where it is, #1738; previously trivial: progress log: Hebrew field results and smart quotes, #1670; previously trivial: Backspace removes a selected table, rows or columns, #1844; previously trivial: progress log: mixed Hebrew/Latin text keeps its order in Word, #1543; previously trivial: progress log: web typing in non-Latin text no longer repeats, #1480; previously trivial: progress log: font family caches bounded and math font lookups follow font changes, #1354; previously trivial: `-->` AutoCorrect replacement, #2223; previously trivial: numbered headings, #1793; previously trivial: Navigation Find exposes Results, #2096; previously trivial: progress log: Columns on selected text, #2024; previously trivial: progress log: legacy outline, shadow, emboss and imprint text effects drawn, #2534; previously trivial: progress log: Indonesian proofing, #498; previously trivial: progress log: DOCX glossary documents (building blocks); previously trivial: progress log: Read Mode keeps the keyboard and shows whole, unobscured columns, #1772); previously trivial: progress log: font list entries of tall-ascent fonts no longer cut off, #2570); previously trivial: progress log: Split Cells and Convert Text to Table dialogs follow the Word check, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout fills the window width, #1876; previously trivial: progress log: Different First Page headers reachable from page 1, #2826; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717); previously trivial: progress log: web preferences kept between visits, #2132; previously trivial: progress log: undrawable private-use list bullets show the level's default bullet, #1683; previously trivial: progress log: `w:eastAsianLayout` kept on save; previously trivial: table style editor formats every part, #714); previously trivial: VML freeforms read and kept on save; previously trivial: progress log: consistent preferred cell widths; previously trivial: multi-paragraph field instructions no longer add blank lines; previously trivial: page-break-only list paragraphs hide their labels; previously trivial: progress log: grouped `flowChartOr` shapes draw their circle and crossing spokes; previously trivial: progress log: copies keep their formatting in other programs, #1523; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 > **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-18 · **Change:** trivial (triple borders draw three lines, #1740; previously trivial: progress log: double-clicking a later page's footer no longer scrolls up, #2103; previously trivial: long navigation headings wrap onto further lines within the pane, #3015; previously trivial: clearing a no-match font query keeps the recent heading visible, #2068; previously trivial: a word after a slash wraps whole, like Word, #2963; previously trivial: RTF export writes sections (gap 19); previously trivial: ODT export writes sections (gap 19); previously trivial: progress log: pasted blockquotes are indented paragraphs, #1270; previously trivial: progress log: print-area strings translated in every catalog; previously trivial: progress log: comments readable in the dark theme, #2045; previously trivial: progress log: ODT sections, #1379; previously trivial: progress log: table deletes, Change Case and Unlink Fields respect Track Changes and locked content controls, #1329; previously trivial: progress log: rounded rectangle corners, #1476; previously trivial: progress log: Save As type list, #1399; previously trivial: progress log: privacy options on save, #1062; previously trivial: progress log: equation pictures in theme colours on Windows, #1002; previously trivial: symbol fonts, #776; previously trivial: the save prompt answers from the keyboard, #861; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 > **Printing update:** 2026-10-12 · direct desktop printing through craft-print; details below. @@ -233,6 +233,7 @@ Imported Word 97–2003 `.doc`/`.dot` files now ask for a supported DOCX target | 2026-10-12 | Fields keep `w:dirty` through DOCX saves (#877): a begin marker flagged by a generator that couldn't compute a result (pandoc-style TOC placeholders) keeps the flag on open/save — as a buffered field or a range field — so Word still refreshes it on open; computing a result (Update Field, Update Table) clears it, like Word's F9 | | 2026-10-18 | Different First Page works from page 1 (#2826): Insert › Header and Edit Header with the caret on page 1, and a double-click there while another header is being edited, go into page 1's own header instead of the default one page 1 no longer shows. | | 2026-10-15 | Track Changes Options › Moves (gap #5): Moved from and Moved to each have a mark and a colour (by default green double strikethrough and double underline, as before and as in Word for Mac), saved per user; `review.trackingOptions` takes `moveFromMark`, `moveFromColor`, `moveToMark`, `moveToColor`, and `trackMoves`, the document's Track moves setting: off, a tracked cut and paste is an ordinary deletion and insertion. DOCX `w:doNotTrackMoves` round-trips | +| 2026-10-18 | Legacy menu keys (#1697; not on macOS): Alt, V, U turns on Full Screen View, as in Word for Windows, along with 17 other Word 2003 menu sequences observed there (views, ruler, zoom, Select All, Find/Replace/Go To, Symbol, Picture, Font, Paragraph, Word Count, Insert Table). Hidden as in Word, with a hint under the tab row while a sequence waits | | 2026-10-18 | View › Focus now fills the screen (#1678): the document on black with a slim bar whose "⋯" drops the ribbon over the page. Full Screen View (`view.fullScreenView`) shows the pages alone with Search at the top and can be bound to any key in Customize Keyboard; the two turn each other off. F11's Full Screen (#980) still fills the screen with the whole window. Esc leaves either; Ctrl+F1 (⌘⌥R on macOS) collapses or expands the ribbon, and a shortcut of your own on Ctrl+F1 wins. Immersive Reader no longer switches Focus on | | 2026-10-17 | Language dialog keeps inherited proofing language and no-proof choices (#2717). Opening and accepting unchanged no longer replaces style-derived values with English US and proofing enabled. | | 2026-10-16 | Text with the legacy Outline, Shadow, Emboss or Engrave font effects (`w:outline`, `w:shadow`, `w:emboss`, `w:imprint`) is drawn with them on screen and in PDFs, no longer as plain text: hollow outlined letters, or a grey copy behind the letters; the PDF keeps the text (#2534) | @@ -530,6 +531,7 @@ Footer page-table height and body wrapping are corrected. Other pagination gaps | 2026-10-18 | trivial | #2445: pending Save As answers keep their originating document identity, so a replacement document is never written to an old picker destination; real Save-button and focused-editor shortcut controls verified | | 2026-10-16 | trivial | #2445: interactive Save on import-only .doc/.dot paths uses the existing DOCX Save As flow; cancel and failed writes keep the draft, and Close waits for a successful save. Explicit/script saves still report unsupported legacy output | | 2026-10-16 | trivial | Save Changes exposes an alert-dialog role, the document-specific question and loss/failure context to accessibility; full-app focus/ancestry regression. Native screen-reader verification remains pending. | +| 2026-10-18 | trivial | Progress log: legacy menu keys (#1697) | | 2026-10-18 | trivial | Progress log: Focus fills the screen; Full Screen View (#1678) | | 2026-10-16 | trivial | Progress log: the Spike | | 2026-10-16 | trivial | Progress log: `w:eastAsianLayout` kept on save | diff --git a/crates/ui-egui/src/chrome.rs b/crates/ui-egui/src/chrome.rs index 803a9f6ea..5c0c2cf56 100644 --- a/crates/ui-egui/src/chrome.rs +++ b/crates/ui-egui/src/chrome.rs @@ -462,12 +462,15 @@ impl Screen { /// Focus's background around the page, in both themes (our own value, #1678). pub const FOCUS_CANVAS: egui::Color32 = egui::Color32::BLACK; +/// Height of the slim bar Focus and Full Screen View show in place of the chrome (#1678). +pub const SCREEN_BAR_HEIGHT: f32 = 30.0; + /// The slim bar across the top in Focus ("⋯" drops the ribbon down over the page) and Full /// Screen View (Search, which finds and runs any command). pub fn screen_bar(app: &mut WordApp, ui: &mut Ui, screen: Screen) { let t = Tokens::get(ui.ctx()); let fill = if screen == Screen::Focus { FOCUS_CANVAS } else { t.title_bar }; - egui::Panel::top("screen_bar").exact_size(30.0).show_separator_line(false).frame(egui::Frame::NONE.fill(fill)).show(ui, |ui| { + egui::Panel::top("screen_bar").exact_size(SCREEN_BAR_HEIGHT).show_separator_line(false).frame(egui::Frame::NONE.fill(fill)).show(ui, |ui| { let full = ui.max_rect(); if screen == Screen::Focus { let r = Rect::from_center_size(full.center(), vec2(40.0, 20.0)); @@ -491,7 +494,7 @@ pub fn screen_bar(app: &mut WordApp, ui: &mut Ui, screen: Screen) { /// click on the page puts it away; Focus stays on. pub fn focus_ribbon(app: &mut WordApp, ctx: &egui::Context) { let width = ctx.content_rect().width(); - egui::Area::new(egui::Id::new("focus_ribbon")).fixed_pos(pos2(0.0, 30.0)).order(egui::Order::Middle).show(ctx, |ui| { + egui::Area::new(egui::Id::new("focus_ribbon")).fixed_pos(pos2(0.0, SCREEN_BAR_HEIGHT)).order(egui::Order::Middle).show(ctx, |ui| { ui.set_width(width); ui.set_max_width(width); crate::ribbon::show(app, ui); diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index 7a784f108..845de1e9a 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -357,6 +357,7 @@ Focus Фокус Full Screen View Изглед на цял екран Show the ribbon Показване на лентата + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Стари клавиши за менюта: Alt, {keys}. Продължете да пишете или натиснете Esc за отказ. Font Шрифт Font Color Цвят на шрифта Font Dialog Диалогов прозорец за шрифт diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 2fb37ec4c..a935ad9c1 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -457,6 +457,7 @@ Focus Soustředění Full Screen View Zobrazení na celou obrazovku Show the ribbon Zobrazit pás karet + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Staré klávesy nabídek: Alt, {keys}. Pokračujte v psaní, nebo zrušte klávesou Esc. Follow number with: Znak za číslem: Font Písmo Font Color Barva písma diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 11601b01d..7215abe31 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -360,6 +360,7 @@ Focus Fokus Full Screen View Vollbildansicht Show the ribbon Menüband anzeigen + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Alte Menütasten: Alt, {keys}. Weitertippen oder mit Esc abbrechen. Font Schriftart Font Color Schriftfarbe Font color: Schriftfarbe: diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 43161b38f..3f9dfe423 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -415,6 +415,7 @@ Focus Modo concentración Full Screen View Vista de pantalla completa Show the ribbon Mostrar la cinta + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Teclas de menú antiguas: Alt, {keys}. Siga escribiendo o pulse Esc para cancelar. Font Fuente Font Color Color de fuente Font Dialog Cuadro de diálogo Fuente diff --git a/crates/ui-egui/src/i18n/et.tsv b/crates/ui-egui/src/i18n/et.tsv index e473f5534..a6b1e7f59 100644 --- a/crates/ui-egui/src/i18n/et.tsv +++ b/crates/ui-egui/src/i18n/et.tsv @@ -279,6 +279,7 @@ Focus Keskendu Full Screen View Täisekraanvaade Show the ribbon Kuva menüülint + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Vanad menüüklahvid: Alt, {keys}. Jätkake tippimist või tühistage Esc-klahviga. Font Font Font Color Fondi värv Font Dialog Fondi dialoog diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index ab8948237..cbdc98927 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -370,6 +370,7 @@ Focus Focus Full Screen View Affichage plein écran Show the ribbon Afficher le ruban + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Anciennes touches de menu : Alt, {keys}. Continuez la saisie ou appuyez sur Échap pour annuler. Font Police Font Color Couleur de police Font color: Couleur de police : diff --git a/crates/ui-egui/src/i18n/hr.tsv b/crates/ui-egui/src/i18n/hr.tsv index 638440f9d..7fc010bb2 100644 --- a/crates/ui-egui/src/i18n/hr.tsv +++ b/crates/ui-egui/src/i18n/hr.tsv @@ -1498,6 +1498,7 @@ template Letter Pismo Offset: Top Pomak: gore Offset: Top Left Pomak: gore lijevo Offset: Top Right Pomak: gore desno + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Stare tipke izbornika: Alt, {keys}. Nastavite tipkati ili pritisnite Esc za odustajanje. Omit Izostavi On Uključeno On: WordCraft opens on File › Home, with a blank document, the templates and your recent documents. Off: it opens a blank document. Uključeno: WordCraft se otvara na Datoteka › Početna, s praznim dokumentom, predlošcima i vašim nedavnim dokumentima. Isključeno: otvara prazan dokument. diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 3f1ff135e..9074fa5bb 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -278,6 +278,7 @@ Focus Fókusz Full Screen View Teljes képernyős nézet Show the ribbon Menüszalag megjelenítése + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Régi menübillentyűk: Alt, {keys}. Gépeljen tovább, vagy a megszakításhoz nyomja meg az Esc billentyűt. Font Betűtípus Font Color Betűszín Font color: Betűszín: diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index c257e7646..0d7c6651b 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -352,6 +352,7 @@ Focus Concentrazione Full Screen View Visualizzazione a schermo intero Show the ribbon Mostra la barra multifunzione + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Vecchi tasti dei menu: Alt, {keys}. Continua a digitare o premi Esc per annullare. Font Carattere Font Color Colore carattere Font Dialog Finestra di dialogo Carattere diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index 2673474eb..afdb08a55 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -417,6 +417,7 @@ Focus フォーカス Full Screen View 全画面ビュー Show the ribbon リボンを表示 + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. 旧メニュー キー: Alt, {keys}。続けて入力するか、Esc キーで取り消します。 Font フォント Font Color フォントの色 Font color: フォントの色: diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index c4bc8cb43..59073631c 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -114,6 +114,7 @@ Number alignment: 번호 맞춤: Number format 번호 서식 Number style for this level: 이 수준의 번호 스타일: + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. 이전 메뉴 키: Alt, {keys}. 계속 입력하거나 Esc 키를 눌러 취소하세요. Outside border 바깥쪽 테두리 Overtype 겹쳐쓰기 Overtype (typing replaces the characters after the caret) 겹쳐쓰기(입력한 문자가 커서 뒤의 문자를 대체함) diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index 641865b5b..6f027ae53 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -273,6 +273,7 @@ Focus Skupienie Full Screen View Widok pełnoekranowy Show the ribbon Pokaż wstążkę + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Stare klawisze menu: Alt, {keys}. Pisz dalej lub naciśnij Esc, aby anulować. Font Czcionka Font Color Kolor czcionki Font Dialog Okno dialogowe Czcionka diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 575e146c3..1bced14da 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -418,6 +418,7 @@ Focus Foco Full Screen View Modo de tela inteira Show the ribbon Mostrar a faixa de opções + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Teclas de menu antigas: Alt, {keys}. Continue digitando ou pressione Esc para cancelar. Font Fonte Font Color Cor da fonte Font color: Cor da fonte: diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 7224ecdf1..7d50ccaed 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -280,6 +280,7 @@ Focus Фокус Full Screen View Полноэкранный режим Show the ribbon Показать ленту + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Старые клавиши меню: Alt, {keys}. Продолжайте ввод или нажмите Esc для отмены. Font Шрифт Font Color Цвет шрифта Font color: Цвет шрифта: diff --git a/crates/ui-egui/src/i18n/sr-latn.tsv b/crates/ui-egui/src/i18n/sr-latn.tsv index 0bbcd28cc..0a73fa34f 100644 --- a/crates/ui-egui/src/i18n/sr-latn.tsv +++ b/crates/ui-egui/src/i18n/sr-latn.tsv @@ -465,6 +465,7 @@ Focus Fokus Full Screen View Prikaz preko celog ekrana Show the ribbon Prikaži traku + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Stari tasteri menija: Alt, {keys}. Nastavite da kucate ili pritisnite Esc da otkažete. Font Font Font Color Boja fonta Font color: Boja fonta: diff --git a/crates/ui-egui/src/i18n/sr.tsv b/crates/ui-egui/src/i18n/sr.tsv index 9fc0b9b2c..ea9ef96b7 100644 --- a/crates/ui-egui/src/i18n/sr.tsv +++ b/crates/ui-egui/src/i18n/sr.tsv @@ -469,6 +469,7 @@ Focus Фокус Full Screen View Приказ преко целог екрана Show the ribbon Прикажи траку + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Стари тастери менија: Alt, {keys}. Наставите да куцате или притисните Esc да откажете. Font Фонт Font Color Боја фонта Font color: Боја фонта: diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index 80d94737f..051c6c3a4 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -123,6 +123,7 @@ Number alignment: Justering av nummer: Number format Nummerformat Number style for this level: Numreringsstil för den här nivån: + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Gamla menytangenter: Alt, {keys}. Fortsätt skriva eller tryck på Esc för att avbryta. Outside border Yttre kantlinje Overtype Överskrivning Overtype (typing replaces the characters after the caret) Överskrivning (det du skriver ersätter tecknen efter markören) diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 809a70f0c..8b9f5ac18 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -276,6 +276,7 @@ Focus Odak Full Screen View Tam Ekran Görünümü Show the ribbon Şeridi göster + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Eski menü tuşları: Alt, {keys}. Yazmaya devam edin ya da iptal etmek için Esc tuşuna basın. Font Yazı Tipi Font Color Yazı Tipi Rengi Font color: Yazı tipi rengi: diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 2751a11aa..c8026b53b 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -427,6 +427,7 @@ Focus Зосередження Full Screen View Повноекранний режим Show the ribbon Показати стрічку + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Старі клавіші меню: Alt, {keys}. Продовжуйте вводити або натисніть Esc, щоб скасувати. Font Шрифт Font Color Колір шрифту Font color: Колір шрифту: diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 46ce3ebcd..e31955acf 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -351,6 +351,7 @@ Focus Tập trung Full Screen View Chế độ xem toàn màn hình Show the ribbon Hiện dải lệnh + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. Phím menu cũ: Alt, {keys}. Tiếp tục gõ hoặc nhấn Esc để hủy. Font Phông chữ Font Color Màu phông chữ Font Dialog Hộp thoại phông chữ diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 522e3ae38..f1d671af7 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -429,6 +429,7 @@ Focus 专注 Full Screen View 全屏视图 Show the ribbon 显示功能区 + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. 旧菜单键: Alt, {keys}。继续输入,或按 Esc 取消。 Font 字体 Font Color 字体颜色 Font color: 字体颜色: diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index dfa7cb689..4184ca04b 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -418,6 +418,7 @@ Focus 專注 Full Screen View 全螢幕檢視 Show the ribbon 顯示功能區 + Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel. 舊功能表鍵: Alt, {keys}。繼續輸入,或按 Esc 取消。 Font 字型 Font Color 字型色彩 Font color: 字型色彩: diff --git a/crates/ui-egui/src/keytips.rs b/crates/ui-egui/src/keytips.rs index 4b08d2967..7b5c307de 100644 --- a/crates/ui-egui/src/keytips.rs +++ b/crates/ui-egui/src/keytips.rs @@ -36,6 +36,9 @@ pub enum Phase { Tabs, /// Badges over one tab's groups and buttons. Commands, + /// Partway through a legacy menu key sequence (#1697); the letters so far are in + /// `keytip_prefix`, and a hint stands in for the badges. + Legacy, } /// Which ribbon item a letter is bound to, and what pressing it does. @@ -87,6 +90,49 @@ const TABLE_TAB_LETTERS: [(&str, &str); 2] = [("Table Design", "JT"), ("Table La /// The Search box's badge beside the tab badges (Word's Alt, Q). pub const SEARCH_LETTER: &str = "Q"; +/// Legacy menu keys (#1697): Word 2003 menu sequences Word for Windows still takes after Alt, +/// observed there. Hidden, as in Word: no badges, not in Customize Keyboard. They start only on +/// letters no tab keytip or Search uses (see the test). +fn legacy() -> Vec<(&'static str, Target)> { + let cmd = |id| Target::Cmd { id, params: serde_json::json!({}) }; + let dialog = |name| Target::Dialog { name }; + vec![ + ("VU", cmd("view.fullScreenView")), + ("VP", cmd("view.printLayout")), + ("VW", cmd("view.webLayout")), + ("VO", cmd("view.outline")), + ("VN", cmd("view.draft")), + ("VD", cmd("view.navigationPane")), + ("VL", cmd("view.ruler")), + ("VZ", dialog("zoom")), + ("EL", cmd("select.all")), + ("EF", dialog("find")), + ("EE", dialog("replace")), + ("EG", dialog("goto")), + ("IS", dialog("symbol")), + ("IPF", cmd("insert.picture")), + ("OF", dialog("font")), + ("OP", dialog("paragraph")), + ("TW", cmd("review.wordCount")), + ("AIT", dialog("insertTable")), + ] +} + +/// A letter in a legacy menu key sequence: run it once complete, wait while it can still grow, +/// and ignore a letter that leads nowhere, as Word does. +fn legacy_key(app: &mut WordApp, name: &str) { + let keys = format!("{}{name}", app.ui.keytip_prefix); + let rows = legacy(); + if let Some((_, target)) = rows.iter().find(|(k, _)| *k == keys) { + app.ui.keytips = Phase::Off; + app.ui.keytip_prefix.clear(); + target.clone().run(app); + } else if rows.iter().any(|(k, _)| k.starts_with(&keys)) { + app.ui.keytips = Phase::Legacy; + app.ui.keytip_prefix = keys; + } +} + /// The letter badge for a tab (empty when it has none). pub fn tab_letter(tab: &str) -> &'static str { TAB_LETTERS.iter().chain(&TABLE_TAB_LETTERS).find(|(t, _)| *t == tab).map(|(_, l)| *l).unwrap_or("") @@ -559,9 +605,18 @@ pub fn handle_key(app: &mut WordApp, key: egui::Key) -> bool { app.ui.keytips = Phase::Off; let _ = app.run("tools.search", serde_json::json!({})); } + // Word 2003's menu keys: off on macOS, where F10 still shows badges. + None if !cfg!(target_os = "macos") && legacy().iter().any(|(k, _)| k.starts_with(name.as_str())) => { + legacy_key(app, &name); + return true; + } None => app.ui.keytips = Phase::Off, } } + Phase::Legacy => { + legacy_key(app, &name); + return true; + } Phase::Commands => { let tab = app.ui.tab.clone(); let ls = letters_for(app, &tab); @@ -768,12 +823,37 @@ pub fn show(app: &mut WordApp, ctx: &egui::Context, ui: &mut Ui) { // Tab badges were recorded during layout; command badges were published to egui memory by // the widgets themselves (they own their rects). let tabs = std::mem::take(&mut app.keytip_rects); + if app.ui.keytips == Phase::Legacy { + legacy_hint(app, ui, tabs.iter().map(|(r, _)| *r).reduce(|a, b| a.union(b))); + return; + } let cmds: Vec<(Rect, String)> = ui.data(|d| d.get_temp::>(rects_id())).unwrap_or_default(); for (r, l) in tabs.into_iter().chain(cmds) { badge(ui, r, &l); } } +/// Where the legacy hint hangs from: the tab row, or, with no ribbon showing (Focus, Full Screen +/// View), the top of the window under the slim bar, so Alt, V still says it's waiting. +fn legacy_hint_anchor(tabs: Option, window: Rect) -> Rect { + tabs.unwrap_or_else(|| Rect::from_min_size(window.left_top(), Vec2::new(0.0, crate::chrome::SCREEN_BAR_HEIGHT))) +} + +/// The hint under the tab row while a legacy menu key sequence waits for its next letter. +fn legacy_hint(app: &WordApp, ui: &Ui, tabs: Option) { + let tabs = legacy_hint_anchor(tabs, ui.ctx().content_rect()); + let t = Tokens::get(ui.ctx()); + let keys: Vec = app.ui.keytip_prefix.chars().map(String::from).collect(); + let text = crate::i18n::fmt(tl!("Old menu keys: Alt, {keys}. Keep typing, or press Esc to cancel."), &[("keys", &keys.join(", "))]); + let font = egui::FontId::proportional(12.0); + let galley = ui.ctx().fonts_mut(|f| f.layout_no_wrap(text, font, t.text)); + let r = Rect::from_min_size(tabs.left_bottom() + Vec2::new(4.0, 2.0), galley.size() + Vec2::new(16.0, 10.0)); + let p = ui.ctx().layer_painter(egui::LayerId::new(egui::Order::Tooltip, egui::Id::new("wc_legacy_keys"))); + p.rect_filled(r, CornerRadius::same(4), t.menu); + p.rect_stroke(r, CornerRadius::same(4), Stroke::new(1.0, t.border), egui::StrokeKind::Inside); + p.galley(r.min + Vec2::new(8.0, 5.0), galley, t.text); +} + #[cfg(test)] mod tests { use super::*; @@ -982,6 +1062,86 @@ mod tests { assert_eq!(a.ui.keytips, tap); } + /// #1697: Alt, V, U turns on Full Screen View, as in Word for Windows; Alt, V waits with a hint + /// instead of tab badges; a letter that leads nowhere is ignored; Esc ends the sequence and + /// Alt goes back to the tab badges. + #[test] + fn legacy_menu_keys() { + let mut a = app(); + let keys = |a: &mut WordApp, ks: &[egui::Key]| { + activate(a); + for k in ks { + assert!(handle_key(a, *k)); + } + }; + if cfg!(target_os = "macos") { + // Off on macOS: F10's badges take only the ribbon's letters. + keys(&mut a, &[egui::Key::V]); + assert_eq!(a.ui.keytips, Phase::Off); + return; + } + keys(&mut a, &[egui::Key::V]); + assert_eq!((a.ui.keytips, a.ui.keytip_prefix.as_str()), (Phase::Legacy, "V")); + assert!(handle_key(&mut a, egui::Key::S), "S leads nowhere after V"); + assert_eq!((a.ui.keytips, a.ui.keytip_prefix.as_str()), (Phase::Legacy, "V"), "and is ignored"); + assert!(handle_key(&mut a, egui::Key::U)); + assert_eq!(a.ui.keytips, Phase::Off); + assert!(a.ui.keytip_prefix.is_empty()); + assert!(a.session.view.full_screen_view, "Alt, V, U: Full Screen View"); + // Three letters: Alt, A, I, T opens Insert Table. + keys(&mut a, &[egui::Key::A, egui::Key::I]); + assert_eq!((a.ui.keytips, a.ui.keytip_prefix.as_str()), (Phase::Legacy, "AI")); + assert!(handle_key(&mut a, egui::Key::T)); + assert!(matches!(a.dialog, Some(crate::dialogs::Dialog::InsertTable { .. }))); + a.dialog = None; + // Esc ends the whole sequence; Alt goes back to the tab badges. + keys(&mut a, &[egui::Key::A, egui::Key::I, egui::Key::Escape]); + assert_eq!(a.ui.keytips, Phase::Off); + assert!(a.ui.keytip_prefix.is_empty()); + keys(&mut a, &[egui::Key::E, egui::Key::AltLeft]); + assert_eq!(a.ui.keytips, Phase::Tabs); + assert!(a.ui.keytip_prefix.is_empty()); + // The ribbon comes first: W is still the View tab. + a.ui.keytips = Phase::Off; + keys(&mut a, &[egui::Key::W]); + assert_eq!((a.ui.tab.as_str(), a.ui.keytips), ("View", Phase::Commands)); + } + + /// #1697 review: with no ribbon showing (Focus, Full Screen View) no tab rects are recorded, + /// so the hint hangs under the slim bar at the top of the window instead of not showing. + #[test] + fn the_legacy_hint_hangs_under_the_slim_bar_without_a_ribbon() { + let window = Rect::from_min_size(egui::pos2(0.0, 0.0), Vec2::new(1440.0, 900.0)); + let anchor = legacy_hint_anchor(None, window); + assert_eq!(anchor.left_bottom(), egui::pos2(0.0, crate::chrome::SCREEN_BAR_HEIGHT)); + let tabs = Rect::from_min_max(egui::pos2(10.0, 40.0), egui::pos2(600.0, 64.0)); + assert_eq!(legacy_hint_anchor(Some(tabs), window), tabs, "under the tab row when the ribbon shows"); + } + + /// #1697: legacy sequences never start on a tab keytip (table tabs included) or Search, and + /// every one reaches a command or dialog that exists. + #[test] + fn legacy_menu_keys_stay_off_the_ribbon_letters_and_all_resolve() { + let mut a = app(); + a.run("insert.table", serde_json::json!({"rows": 2, "cols": 2})).unwrap(); + let mut taken: Vec<&str> = badge_tabs(&a).into_iter().map(tab_letter).collect(); + taken.push(SEARCH_LETTER); + for (keys, target) in legacy() { + let first = &keys[..1]; + assert!(!taken.contains(&first), "{keys} starts on a ribbon letter"); + assert!(!legacy().iter().any(|(k, _)| *k != keys && k.starts_with(keys)), "{keys} hides a longer sequence"); + let mut b = app(); + match target { + Target::Cmd { id, .. } => assert!(b.session.registry.get(id).is_some(), "{keys}: {id}"), + Target::Dialog { name } => { + Target::Dialog { name }.run(&mut b); + assert!(b.dialog.is_some(), "{keys}: dialog {name}"); + } + Target::Tab(_) => panic!("{keys}: a tab"), + } + } + } + #[test] fn keytip_state_machine() { let mut a = app(); @@ -1162,6 +1322,42 @@ mod tests { } } + /// #1697 review: Alt, V, U through the whole app (the canvas has the keyboard), not only + /// `handle_key`: Full Screen View turns on and neither letter types into the document. + #[test] + fn legacy_menu_keys_through_the_app_never_type() { + if cfg!(target_os = "macos") { + return; + } + let mut a = app(); + a.canvas.focused = true; + a.canvas.want_focus = true; + let mut h = egui_kittest::Harness::builder().with_size(egui::vec2(1440.0, 900.0)).build_ui_state( + |ui, app: &mut WordApp| { + let ctx = ui.ctx().clone(); + app.logic(&ctx); + app.ui(ui); + }, + a, + ); + h.run_steps(4); + let alt = egui::Modifiers { alt: true, ..Default::default() }; + h.input_mut().events.extend([key_event(egui::Key::AltLeft, true, egui::Modifiers::NONE), egui::Event::ModifiersChanged(alt)]); + h.step(); + h.input_mut().events.extend([key_event(egui::Key::AltLeft, false, alt), egui::Event::ModifiersChanged(egui::Modifiers::NONE)]); + h.step(); + assert_eq!(h.state().ui.keytips, Phase::Tabs); + let key = |key| key_event(key, true, egui::Modifiers::NONE); + h.input_mut().events.extend([key(egui::Key::V), egui::Event::Text("v".into())]); + h.step(); + assert_eq!((h.state().ui.keytips, h.state().ui.keytip_prefix.as_str()), (Phase::Legacy, "V")); + h.input_mut().events.extend([key(egui::Key::U), egui::Event::Text("u".into())]); + h.run_steps(3); + assert_eq!(h.state().ui.keytips, Phase::Off); + assert!(h.state().session.view.full_screen_view, "Alt, V, U: Full Screen View"); + assert!(h.state().session.doc.plain_text(wordcraft_doc::StoryRef::Body).is_empty(), "no letter typed"); + } + #[test] fn keytips_option_persists_and_disabled_keytips_leave_f10_alone() { let mut a = app(); diff --git a/crates/ui-egui/src/ribbon.rs b/crates/ui-egui/src/ribbon.rs index 31578b6ee..6aa43fe59 100644 --- a/crates/ui-egui/src/ribbon.rs +++ b/crates/ui-egui/src/ribbon.rs @@ -396,6 +396,9 @@ pub fn show(app: &mut WordApp, ui: &mut Ui) { let (r, resp) = ui.allocate_exact_size(vec2(w, 30.0), Sense::click()); if app.ui.keytips == crate::keytips::Phase::Tabs { crate::keytips::record_tab(r, tab, &app.ui.keytip_prefix, &mut app.keytip_rects); + } else if app.ui.keytips == crate::keytips::Phase::Legacy { + // Every tab: they only place the legacy keys' hint (#1697). + crate::keytips::record_tab(r, tab, "", &mut app.keytip_rects); } let active = app.ui.tab == tab && !app.ui.backstage; resp.widget_info(|| egui::WidgetInfo::selected(egui::WidgetType::SelectableLabel, true, active, shown)); diff --git a/docs/ui-parity.md b/docs/ui-parity.md index fe8bbdf54..fe71b73b4 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -1,6 +1,6 @@ # UI parity with Microsoft Word -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-21 · **Change:** trivial (Shape Fill › Gradient and the Format Shape pane, #1500; previously trivial: Focus fills the screen, and Full Screen View shows the pages alone, #1678; previously trivial: the text pointer over the page is drawn black or white on Windows, #1746; previously trivial: a click in the header/footer band from the body no longer scrolls to the body text, #2103; previously trivial: File › Recover follows the app theme, #3243; previously trivial: long navigation headings wrap onto further lines within the pane, #3015; previously trivial: clearing a no-match font query keeps the recent heading visible, #2068; previously trivial: dragging the vertical scrollbar names the page at the top of the window, #2551; previously trivial: Add Font imports every selected font file, #1789); previously trivial (File › Close keeps the window, #1712; previously trivial: the Spike: Ctrl+F3 and Ctrl+Shift+F3; previously trivial: Ctrl+wheel zoom no longer scrolls the document, #1743; previously trivial: a mouse drag on a table leaves the view where it is, #1738; previously trivial: numbered headings, #1793; previously trivial: Navigation Find exposes Results, #2096; previously trivial: the tab strip never draws tabs over Comments / Editing / Share, #2026; previously trivial: Columns on selected text, #2024; previously trivial: Different First Page headers reachable from page 1, #2826; previously trivial: a copied equation also goes in the clipboard's MathML formats, #1297; previously trivial: Read Mode keeps the keyboard, shows whole columns and keeps text clear of the page-turn bar, #1772); previously trivial: font list entries of tall-ascent fonts sit in their row, not cut off, #2570); previously trivial: Split Cells and Convert Text to Table dialogs follow Word's merged-cell limits and Initial column width, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout text fills the window width, #1876; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717)); previously trivial: comment balloons readable in the dark theme, #2045; previously trivial: Recently Used Fonts section at the top of the font list, #2068; previously trivial: web preferences kept between visits, #2132; previously trivial: dialog close control: a Windows-style box at the title bar's right end, the whole box clickable, red on hover, #1885); previously trivial (Modify Table Style formats every table style part, #714); previously trivial: a click on the ribbon chrome hands the keyboard to the page in the same frame, #1093 follow-up; previously trivial: Page Setup vertical alignment, #1320; previously trivial: the app opens on the Home tab every launch, as in Word; previously trivial: no document behind the Start screen, #1129; previously trivial: equation pictures share a few textures, #1002; previously trivial: selection bar in the left margin, #856; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously major: first version; ribbon, dialogs, shortcuts and on-canvas interaction measured from `crates/ui-egui` and the command registry) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-21 · **Change:** trivial (legacy menu keys, #1697; previously trivial: Shape Fill › Gradient and the Format Shape pane, #1500; previously trivial: Focus fills the screen, and Full Screen View shows the pages alone, #1678; previously trivial: the text pointer over the page is drawn black or white on Windows, #1746; previously trivial: a click in the header/footer band from the body no longer scrolls to the body text, #2103; previously trivial: File › Recover follows the app theme, #3243; previously trivial: long navigation headings wrap onto further lines within the pane, #3015; previously trivial: clearing a no-match font query keeps the recent heading visible, #2068; previously trivial: dragging the vertical scrollbar names the page at the top of the window, #2551; previously trivial: Add Font imports every selected font file, #1789); previously trivial (File › Close keeps the window, #1712; previously trivial: the Spike: Ctrl+F3 and Ctrl+Shift+F3; previously trivial: Ctrl+wheel zoom no longer scrolls the document, #1743; previously trivial: a mouse drag on a table leaves the view where it is, #1738; previously trivial: numbered headings, #1793; previously trivial: Navigation Find exposes Results, #2096; previously trivial: the tab strip never draws tabs over Comments / Editing / Share, #2026; previously trivial: Columns on selected text, #2024; previously trivial: Different First Page headers reachable from page 1, #2826; previously trivial: a copied equation also goes in the clipboard's MathML formats, #1297; previously trivial: Read Mode keeps the keyboard, shows whole columns and keeps text clear of the page-turn bar, #1772); previously trivial: font list entries of tall-ascent fonts sit in their row, not cut off, #2570); previously trivial: Split Cells and Convert Text to Table dialogs follow Word's merged-cell limits and Initial column width, #2592; previously trivial: a new source's Tag is made like Word's, three letters of the author and two digits of the year with a number added when taken, and an edit keeps the Tag, #2094; previously trivial: Web Layout text fills the window width, #1876; previously trivial: Language dialog keeps inherited proofing language and no-proof choices (#2717)); previously trivial: comment balloons readable in the dark theme, #2045; previously trivial: Recently Used Fonts section at the top of the font list, #2068; previously trivial: web preferences kept between visits, #2132; previously trivial: dialog close control: a Windows-style box at the title bar's right end, the whole box clickable, red on hover, #1885); previously trivial (Modify Table Style formats every table style part, #714); previously trivial: a click on the ribbon chrome hands the keyboard to the page in the same frame, #1093 follow-up; previously trivial: Page Setup vertical alignment, #1320; previously trivial: the app opens on the Home tab every launch, as in Word; previously trivial: no document behind the Start screen, #1129; previously trivial: equation pictures share a few textures, #1002; previously trivial: selection bar in the left margin, #856; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously major: first version; ribbon, dialogs, shortcuts and on-canvas interaction measured from `crates/ui-egui` and the command registry) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 How WordCraft looks and feels next to Word: ribbon, dialogs, panes, keyboard, mouse and touch. Typing behaviour has its own checklist ([`typing-parity.md`](typing-parity.md)). All assets are our @@ -13,7 +13,7 @@ Document title opens Rename Document; the account badge opens Options › Genera | Area | WordCraft | Word | Parity | Hours | |---|---|---|---|---| | Ribbon tabs and groups | All Word tabs including contextual Table Design/Layout, Picture Format, Shape Format, Header & Footer, Equation, Outlining (Outline view, #493); ribbon overflow (#43, #129). Draw tab: Select, Eraser, Pen, Pencil, Highlighter with colour and thickness (#307); Lasso (drag to move, Delete, recolour), Add Pen gallery (right-click to remove), Ink to Shape (lines, arrows, rectangles, ellipses, polygons), Ink Replay with play/pause/rewind/forward bar (#395); missing: Ink to Math. The app opens on Home every launch, as in Word: the active tab is not restored between runs, but going File and back to the editor returns to the tab that was showing, contextual tabs included. Home › Font: the font box lists Recently Used Fonts (the fonts applied from the box, the mini toolbar or the Font dialog, most recent first, ten at most, kept between runs) above All Fonts, as in Word; the sections show while nothing is typed, including after a no-match query is cleared in a scrollable list (#2068) | Same plus Draw | 85% | (Draw in features) | -| Keytips (Alt / F10) | Ribbon badges (#43) and numbered Quick Access Toolbar badges in the user's button order (#620; none while the toolbar is hidden, #1945); File › Options › Advanced › Display switch saved per user (`ui.keytips`); Alt leaves macOS Option typing alone | ✅ | 85% | 1–2 | +| Keytips (Alt / F10) | Ribbon badges (#43) and numbered Quick Access Toolbar badges in the user's button order (#620; none while the toolbar is hidden, #1945); File › Options › Advanced › Display switch saved per user (`ui.keytips`); Alt leaves macOS Option typing alone; legacy menu keys (#1697; not on macOS): 18 Word 2003 sequences Word for Windows still takes, as observed there (Alt, V, U Full Screen View; V, P/W/O/N views; V, D/L/Z; E, L/F/E/G; I, S; I, P, F; O, F/P; T, W; A, I, T), hidden, with a hint under the tab row (under the slim bar in Focus and Full Screen View); an unknown letter is ignored, Esc cancels; Alt, I, B left out (no Break dialog) | ✅ | 85% | 1–2 | | Mini-toolbar on selection | ✅ (#43, two rows #535; Recently Used Fonts in its font box #2068) | ✅ | 80% | 1–2 | | Colour drop-downs: theme/standard colours, Recent Colors, More Colors… → Colors dialog (Standard honeycomb, Custom hue/saturation field with lightness, RGB/HSL and hex) | ✅ Font Color (ribbon, mini toolbar, Font dialog), Shading, Page Color, Shape Fill/Outline/Glow, pen colours, dialog colour fields (#606); Shape Fill › Gradient: Light and Dark Variations of the shape's colour, More Gradients… (#1500); no eyedropper | ✅ | 90% | 1 | | Quick Access Toolbar | AutoSave, then the user's commands (Save, Undo, Redo by default); add, remove and reorder from its … menu (common commands, More Commands…), right-click on any ribbon button, or Customize Ribbon; saved per user (#379, #376). Undo's ▾ list: recent steps newest first, hover highlights the steps a click undoes ("Undo 3 Actions"), one click undoes them all (#701; `edit.undoTo`, `edit.undoHistory`). Its menu ends with Hide Quick Access Toolbar, which takes it out of the title bar; Show Quick Access Toolbar on the ribbon's right-click menu, or in Customize Ribbon › Quick Access Toolbar, brings it back; kept between runs; `ui.quickAccessToolbar` for scripts (#1945). Not shown below the ribbon | customizable | 92% | 0.5 | @@ -84,6 +84,7 @@ Footnote and endnote editing keeps body and note text at normal opacity, on ligh | 2026-10-15 | trivial | File › Close (Mod+W, Mod+F4) closes the document and keeps the window, showing no page, as Word does (it quit the whole app); the window's close button still asks to save and quits (#1712) | | 2026-10-16 | trivial | Save Changes exposes an alert-dialog role, the document-specific question and loss/failure context to accessibility; full-app focus/ancestry regression. Native screen-reader verification remains pending. | | 2026-10-16 | trivial | Dragging the vertical scrollbar shows a tip beside the pointer with the page at the top of the window ("Page 7 of 10"); nothing said where the drag would land (#2551) | +| 2026-10-18 | trivial | Legacy menu keys (#1697; not on macOS): Alt, V, U and 17 more Word 2003 sequences, observed in Word for Windows; hidden, with a hint under the tab row | | 2026-10-18 | trivial | Focus works (full screen, document on black, "⋯" drops the ribbon over the page) and Full Screen View is a bindable command (pages alone, Search at the top), beside Full Screen (#980, F11, whole window); the two rows merged; Esc leaves either; Ctrl+F1 collapses the ribbon (#1678) | | 2026-10-15 | trivial | Dialogs, the Read Aloud player and the file browser: the close control is a box at the title bar's right end, the full title-bar height and 1.6× as wide, all of it clickable; red with a white ✕ while the pointer is over it, darker red pressed, in both themes; Escape as before (#1885) | | 2026-10-15 | trivial | Font box (ribbon and mini toolbar): a Recently Used Fonts section at the top of the list holds the fonts applied from the box, the mini toolbar or the Font dialog, most recent first, once each, ten at most, kept between runs in `ui.json`; All Fonts follows; the sections show while nothing is typed and a query lists its matches only; Up/Down walk the recent entries then the list, Enter applies the highlighted one; a recent font no longer installed stays listed (#2068) |