Skip to content

Windows: native menu accelerators via a hidden muda menu driving the hamburger UI #194

Description

@lambdalisue

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions