Background
PR #193 introduces menu shortcuts as native OS menu accelerators (macOS/Linux). On Windows, Arto deliberately uses with_menu(None) (desktop/src/lib.rs:126-127) and a custom in-app menu (win_hamburger) instead of a native menu bar, so there is no native accelerator table. As an interim, #193 resolves menuShortcuts into the in-window keybinding engine on Windows (BindingSet::into_resolved_bindings, #[cfg(target_os = "windows")]) so those shortcuts still work — but only while a window has focus, and not as true native accelerators.
Goal
Give Windows real native menu accelerators without showing a native menu bar, and drive the existing hamburger UI (win_hamburger) from the same menu model.
Why it's feasible
On Windows, muda accelerators fire via a separate accelerator table (HACCEL) processed by TranslateAcceleratorW in the message loop — independent of whether a menu bar is visible. So the target architecture is:
menu::build_menu() becomes the single source of truth for both platforms.
- Windows: attach the muda menu to the window (for the
HACCEL + WM_COMMAND handling) but suppress the visible menu bar (frameless window / SetMenu(null) after init), and ensure the event loop runs TranslateAcceleratorW(hwnd, menu.haccel(), &msg).
win_hamburger renders its items and shortcut hints from that same menu model.
Net result: one menu model, native accelerators on every platform, hamburger UI on Windows as just another view of it.
Open questions / work
- Whether dioxus-desktop / tao expose enough control on Windows to attach the menu for
HACCEL while hiding the bar (or whether we need to drop below with_menu to init_for_hwnd + SetMenu(null) and confirm tao runs TranslateAcceleratorW).
- Coexistence with Arto's custom Windows decorations.
- Requires a real Windows environment to prototype and verify (Windows is not in CI today).
Follow-up cleanup
Once native accelerators work on Windows, remove the #[cfg(target_os = "windows")] engine-resolution branch in into_resolved_bindings and the #[cfg(not(target_os = "windows"))] gate on push_menu_accelerators_to_js — Windows would then own these chords via the native menu like macOS/Linux.
Related: #193
Background
PR #193 introduces menu shortcuts as native OS menu accelerators (macOS/Linux). On Windows, Arto deliberately uses
with_menu(None)(desktop/src/lib.rs:126-127) and a custom in-app menu (win_hamburger) instead of a native menu bar, so there is no native accelerator table. As an interim, #193 resolvesmenuShortcutsinto the in-window keybinding engine on Windows (BindingSet::into_resolved_bindings,#[cfg(target_os = "windows")]) so those shortcuts still work — but only while a window has focus, and not as true native accelerators.Goal
Give Windows real native menu accelerators without showing a native menu bar, and drive the existing hamburger UI (
win_hamburger) from the same menu model.Why it's feasible
On Windows, muda accelerators fire via a separate accelerator table (
HACCEL) processed byTranslateAcceleratorWin the message loop — independent of whether a menu bar is visible. So the target architecture is:menu::build_menu()becomes the single source of truth for both platforms.HACCEL+WM_COMMANDhandling) but suppress the visible menu bar (frameless window /SetMenu(null)after init), and ensure the event loop runsTranslateAcceleratorW(hwnd, menu.haccel(), &msg).win_hamburgerrenders its items and shortcut hints from that same menu model.Net result: one menu model, native accelerators on every platform, hamburger UI on Windows as just another view of it.
Open questions / work
HACCELwhile hiding the bar (or whether we need to drop belowwith_menutoinit_for_hwnd+SetMenu(null)and confirm tao runsTranslateAcceleratorW).Follow-up cleanup
Once native accelerators work on Windows, remove the
#[cfg(target_os = "windows")]engine-resolution branch ininto_resolved_bindingsand the#[cfg(not(target_os = "windows"))]gate onpush_menu_accelerators_to_js— Windows would then own these chords via the native menu like macOS/Linux.Related: #193