#735: Converge frame composition — ~4,500 lines laying down the same surfaces in two hand-kept orders - #748
Merged
JDonaghy merged 3 commits intoSep 2, 2026
Conversation
Frame composition was written twice. The overlay band — the app-level surfaces both backends lay down on top of the editor and chrome — had already inverted against itself twice, in exactly the way #592 predicted: GTK menu dropdown -> command centre -> find/replace -> picker -> tab switcher -> **dialog -> context menu** -> window controls -> toasts TUI find/replace -> picker -> tab switcher -> **context menu -> dialog** -> menu dropdown -> command centre -> toasts 1. dialog vs. context menu. `route_modal_overlay_click` hands a dialog every event the moment it opens, ahead of every rung but toasts — yet GTK painted it *under* the context menu, so a context menu left open when a dialog opens covers the surface that owns the input. Paint and input disagreeing: the #587/#592 shape. 2. menu dropdown / command centre vs. the modal stack. TUI painted the title-bar band on top of every modal; GTK painted it underneath. `render::OVERLAY_Z_ORDER` is now the single artefact both backends walk, so the order is no longer something either one holds an opinion about. The canonical order takes GTK's placement for the title-bar chrome (chrome, so modals cover it) and TUI's for the modal stack (it agrees with `route_modal_overlay_click`). Geometry and rasterisation stay per backend — pixels vs cells, Cairo painter-order vs ratatui cell coalescence are the intrinsic differences #735 preserves. Both backends record what they actually painted into `painted_overlay_band`, which is the observable the z-order tests assert on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…lus the staging-1 answer Black-box coverage per CLAUDE.md, both backends, asserting on painted output: gtk/testing.rs overlay_band_z_order::overlay_band_paints_dialog_above_context_menu_via_gtk_driver shell_app.rs tests::overlay_band_paints_dialog_above_context_menu_via_shell_app Both assert the *same* expected band — [MenuDropdown, CommandCenter, ContextMenu, Dialog] — for the same engine state. A single test cannot drive both backends (the GTK App lives in the vimcode bin target, TuiShellApp in vcd), so "both backends emit the same FrameOp sequence" is two tests sharing one expected value. RED-verified, one backend at a time, by swapping two arm patterns in the OVERLAY_Z_ORDER walk — which reproduces each backend's own pre-#735 order: GTK Dialog before ContextMenu -> gtk_driver test FAILS TUI MenuDropdown after Dialog -> shell_app test FAILS Both also trip check_overlay_band_order's debug_assert inside render_content before the assertion is even reached. Restored before committing. The recorder names the variant it painted (push(OverlayOp::Dialog)) rather than push(op). With push(op) the record follows the *pattern* the walk is at, so swapping two arms' bodies paints them wrongly while still recording them rightly — the first cut did exactly that and the RED check passed, which is CLAUDE.md's "a test that cannot fail is not coverage" caught in the act. Also answers the issue's staging item 1 (PROJECT_STATE.md): draw_frame is #[cfg(test)]-gated and dead in production, so the raw-Buffer residue never blocked anything. Every rung of it is either owned by quadraui's AppShell, already trait-pure on the live path, or cursor placement the runner applies after render_content. The remaining slices do not have to compose around it. And records a verdict for each of the five ScreenLayout fields GTK never reads, on the fields themselves: menu_dropdown_open (deliberately not composed — MenuSystem owns its open state; the field feeds the parity harnesses), group_dividers (composed on TUI, hit-tested on both, unpainted on GTK — an editor-band gap, not an overlay-band one), and diff_toolbar / tab_scroll_offset / tab_bar_primitive (all superseded by the per-group GroupTabBar equivalents since #551). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eping
- overlay_band_paints_dialog_above_context_menu_via_gtk_driver no longer
checks dialog_layout.borrow().is_some() (set unconditionally in the same
match arm, so it can't disprove a paint that never reached the surface).
It now asserts h.driver.screen_contains("ZQXW735DIALOG") like the TUI
twin, plus a context-menu item label, so it actually proves both
surfaces reached the Cairo surface.
- overlay_band_holds_only_the_title_bar_when_no_overlay_is_open_via_gtk_driver
gets the same screen_contains("File") treatment for symmetry.
- Added render::overlay_band_dialog_over_context_menu_fixture() and
render::overlay_band_title_bar_only_fixture(), two #[cfg(test)] fns
built on compose_overlay_band(), so the GTK and TUI cross-backend tests
compute their shared expected Vec<OverlayOp> from one function instead
of two independently hand-copied literals.
RED-verified the fixed assertion by temporarily removing frame.draw(backend)
from the dialog arm in src/gtk/mod.rs: the test failed with the expected
"recorder and painter disagree" message, then passed again once restored.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #735
Automated PR opened by coordinator for review of issue #735.