Background
#456 fixed a TUI bug where clicks on a context-menu entry passed through to the panel handlers underneath. The fix gates four panel-specific intercepts in `src/tui_main/mod.rs` on `engine.context_menu.is_none()` so the menu floats above them.
This works, but it's per-backend code: the GTK side doesn't need any of those gates because native event dispatch + overlay z-ordering give context menus priority for free. CLAUDE.md's platform-neutrality rule says minimal/none.
Proposed approach
Push `engine.context_menu` onto `quadraui::ModalStack` when it opens — the same pattern the editor hover popup already uses (`src/tui_main/mouse.rs` around line 1361). Then panel intercepts call `modal_stack.hit_test(point)` and yield when there's a modal at the click position.
After the migration:
Files
- `src/core/engine/windows.rs` — `open_*_context_menu` and `close_context_menu` need to push/pop the modal_stack entry. Open question: who owns the modal_stack reference? The engine, the backend, or a shared cell? Editor hover popup currently has the backend (mouse handler) push/pop in `src/tui_main/mouse.rs:209-227`.
- `src/tui_main/mod.rs` — replace the four `engine.context_menu.is_none()` gates with `modal_stack.hit_test(point).is_none()` checks. Drop the `continue` short-circuits when a click is inside a modal so the legacy ctx-menu intercept handles them.
- `src/gtk/` — verify no behavioural change (clicks should still be naturally consumed by the overlay).
Acceptance
Out of scope
- Refactoring `mouse.rs` itself. The legacy mouse handler is large; this issue just relocates the priority rule, not the handler structure.
Related
Update (chat session #676, 2026-07-11) — completed work found orphaned on an unmerged branch, rework not reimplementation
Diagnosis found this issue's work was actually done back on 2026-05-30 and pushed to
issue-459-migrate-context-menu-dispatch-to-modalst, but never opened as a PR and never tracked
as a coordinator work assignment — it just sat orphaned (which is why the board showed no
active work/test/review and the issue drifted through refinement on 5/31 and ready-marking on
6/26 without anyone noticing code already existed).
The branch itself is now 73+ commits behind develop and most of what it carries (bundled
quadraui API-compat shims) has since landed independently elsewhere — reapplying the whole
commit would just conflict against already-identical code, or in a couple of spots (render.rs
struct literals, render_impl.rs's dialog layout call) against code that's been refactored
further (render::dialog_generic_layout superseded the old call site entirely). Verified this
directly with git merge-tree (read-only) against current develop.
What's actually still missing from develop — confirmed via direct diff against current
origin/develop:
src/tui_main/mouse.rs — 14-line reconcile block: push/pop the context-menu's bounds onto
modal_stack when it opens/closes.
src/tui_main/mod.rs — the ctx_blocks_event hit-test + swapping the four
engine.context_menu.is_none() gates for !ctx_blocks_event. Confirmed all four gates are
still present, unmigrated, on current develop.
tests/context_menu.rs — one new regression test, appends cleanly at EOF (confirmed the file's
tail is unchanged since the archived commit's base).
Also confirmed the GTK side already has its own independent context-menu ↔ ModalStack wiring
(dispatch_context_menu_click in src/gtk/mod.rs, landed under #546, WidgetId::new("context_menu")
— note the underscore, whereas the archived TUI branch used a hyphen; align to underscore for
consistency) — so "both backends share ModalStack" is already true on the GTK side, this issue is
the TUI half.
Full step-by-step rework instructions (exact insertion points + verbatim code, since anchors have
shifted line numbers but not shape) are in /tmp/rework-briefing-459.md on the elitebook machine,
authored during this chat session. Next step: coord assign elitebook vimcode 459 --rework-of issue-459-migrate-context-menu-dispatch-to-modalst --interactive --briefing-file /tmp/rework-briefing-459.md.
Still valid, still on the critical path for milestone #7 (Platform-Neutral) per GOALS.md —
confirmed still needed, not stale scope. Sibling issue #454 (toast GTK wiring) was found in the
identical orphaned-branch situation from the same May 30 session; see that issue for its own
rework plan.
Background
#456 fixed a TUI bug where clicks on a context-menu entry passed through to the panel handlers underneath. The fix gates four panel-specific intercepts in `src/tui_main/mod.rs` on `engine.context_menu.is_none()` so the menu floats above them.
This works, but it's per-backend code: the GTK side doesn't need any of those gates because native event dispatch + overlay z-ordering give context menus priority for free. CLAUDE.md's platform-neutrality rule says minimal/none.
Proposed approach
Push `engine.context_menu` onto `quadraui::ModalStack` when it opens — the same pattern the editor hover popup already uses (`src/tui_main/mouse.rs` around line 1361). Then panel intercepts call `modal_stack.hit_test(point)` and yield when there's a modal at the click position.
After the migration:
Files
Acceptance
Out of scope
Related
Update (chat session #676, 2026-07-11) — completed work found orphaned on an unmerged branch, rework not reimplementation
Diagnosis found this issue's work was actually done back on 2026-05-30 and pushed to
issue-459-migrate-context-menu-dispatch-to-modalst, but never opened as a PR and never trackedas a coordinator work assignment — it just sat orphaned (which is why the board showed no
active work/test/review and the issue drifted through refinement on 5/31 and ready-marking on
6/26 without anyone noticing code already existed).
The branch itself is now 73+ commits behind
developand most of what it carries (bundledquadraui API-compat shims) has since landed independently elsewhere — reapplying the whole
commit would just conflict against already-identical code, or in a couple of spots (render.rs
struct literals,
render_impl.rs's dialog layout call) against code that's been refactoredfurther (
render::dialog_generic_layoutsuperseded the old call site entirely). Verified thisdirectly with
git merge-tree(read-only) against currentdevelop.What's actually still missing from
develop— confirmed via direct diff against currentorigin/develop:src/tui_main/mouse.rs— 14-line reconcile block: push/pop the context-menu's bounds ontomodal_stackwhen it opens/closes.src/tui_main/mod.rs— thectx_blocks_eventhit-test + swapping the fourengine.context_menu.is_none()gates for!ctx_blocks_event. Confirmed all four gates arestill present, unmigrated, on current
develop.tests/context_menu.rs— one new regression test, appends cleanly at EOF (confirmed the file'stail is unchanged since the archived commit's base).
Also confirmed the GTK side already has its own independent context-menu ↔
ModalStackwiring(
dispatch_context_menu_clickinsrc/gtk/mod.rs, landed under #546,WidgetId::new("context_menu")— note the underscore, whereas the archived TUI branch used a hyphen; align to underscore for
consistency) — so "both backends share ModalStack" is already true on the GTK side, this issue is
the TUI half.
Full step-by-step rework instructions (exact insertion points + verbatim code, since anchors have
shifted line numbers but not shape) are in
/tmp/rework-briefing-459.mdon the elitebook machine,authored during this chat session. Next step:
coord assign elitebook vimcode 459 --rework-of issue-459-migrate-context-menu-dispatch-to-modalst --interactive --briefing-file /tmp/rework-briefing-459.md.Still valid, still on the critical path for milestone #7 (Platform-Neutral) per
GOALS.md—confirmed still needed, not stale scope. Sibling issue #454 (toast GTK wiring) was found in the
identical orphaned-branch situation from the same May 30 session; see that issue for its own
rework plan.