Repository navigation
fix(shell): a press on the window in front never reaches a card window behind it - #277
Merged
Merged
Conversation
…w behind it A click on Mail, cascaded over News, opened the News story under the click (instrument scenario X1, bug B3). The desk offers a press to its tiles topmost first, and Mail's tile claims it (`handled`) where none of Mail's widgets took it. News's tile still handed the claimed press to its app and counted on the claim to keep the app's widgets off it. The claim does not do that: News's story rows are GestureViews, whose makepad hit test is `hits_with_capture_overload(.., true)`, and that captures a press another area has already claimed (touches it reads from the raw stream). On release the row tapped and opened its story. List drags and a View's `on_item_tap` co-capture the same way. A module tile now lets an already claimed press go by, as it lets one outside it go by. Something in front of the tile took it (a window over it, or a shell surface), so the app never sees it. A process tile has had this gate all along through `event.hits`. The closed face of a stopped app takes presses the same way and claims the one it takes, so a click on a window over its Restart no longer restarts it, and a click on the face no longer raises the window behind it. Tests (module_input_tests.rs): two cascaded module tiles, each press offered front to back as the desk does: a click and a touch with a probe app that takes presses as GestureView does, makepad's own GestureView's capture, and the closed face. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymote
force-pushed
the
fix/wm-click-through
branch
from
October 2, 2026 17:52
6524358 to
d030129
Compare
Contributor
Author
|
Local CI passed on d030129 ( GitHub would run for this PR: desktop.yml, phone.yml, apps.yml. Merged on this local pass (macOS runner queue); GitHub CI runs on the merge commit on main.
Skipped (these did NOT pass; (!) marks a skip that blocks tools/ci-local-merge.sh):
Notes:
|
This was referenced Oct 2, 2026
ymote
added a commit
that referenced
this pull request
Oct 2, 2026
…w behind it A module tile claimed presses but never a hover. A mouse move over a part of a card window that takes no hover (Mail's empty page) went on to the tile behind unclaimed, and the app there took it: a News button under Mail lit up and showed its hand cursor. A tile behind also handed its app every move, claimed or not, as it handed presses before #277. The live tile now treats a hover (a mouse move with no button held) the way #277 treats a press. A hover inside it that none of its app's widgets took is the tile's, and one a window in front already took is let by, so its app never sees it. The one exception is the move that leaves a widget of the app still holding the hover: it reaches the root, so that widget sees its hover end, and being claimed it lets no other hover start. The closed face of a stopped app claims a hover inside it too. Moves with a button held (drags) pass as before, so captures keep working. Tests, in module_input_tests.rs: a hover on the window in front never reaches the app behind; makepad's Button behind it never lights up or shows its hand; a hover on a stopped face never reaches the app behind it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymote
added a commit
that referenced
this pull request
Oct 2, 2026
…ot at its top left The closed face draws its line and Restart button centred, but it kept the rect `walk_turtle` returned for the button as Restart's hit rect. The face's turtle centres its content when it ends, which moves the drawn button after it was walked, so the kept rect stayed at the face's top left. A press on the visible button only raised the window, and a press at the top left, where nothing is drawn, restarted the app. The face now hit-tests Restart by the button's drawn area, as any widget is hit-tested: clipped, at the time of the press. It keeps no rect of its own. Tests, in module_input_tests.rs: Restart responds where it is drawn (a click and a tap on the visible button restart the app, a press at the top left only raises the window), and #277's stopped-face test now presses the drawn Restart. Co-Authored-By: Claude Opus 5.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.
Fixes B3 from the headless instrument run (scenario X1): a click on the focused top window reached the window beneath it.
Root cause
News and Mail are script apps in App Hub's Card runner, hosted in-process as module tiles (
MpModuleView,crates/shell/src/module_view.rs). Open News, then Mail: Mail cascades over it (News at 54,105, Mail at 84,135, on top and focused). A click at (700, 700) lands on Mail where Mail has nothing to take it, over News's third story.desk.rs,WmDesk::handle_event) and relies on makepad's first-wins claim (handled). Mail's tile claims a press inside it when none of Mail's widgets took it.GestureView{on_tap: …}(apps/news/bundle/main.splash). makepad's GestureView hit-tests a mouse press withhits_with_capture_overload(cx, area, true)(widgets/src/gesture_view.rs), which captures a press another area has already claimed, and it reads touches straight from the raw stream. So the row captured the press and firedon_tapon release, and News opened the story. PortalList and FlatList drags, and a View'son_item_tap, co-capture the same way.The same happens when the press does land on a Mail widget. During the Mail sign-in, the press on Mail's "Add account" button, and the presses on the host sheet's fields, opened the News story under them (the instrument saw this in every run).
A process tile never had this problem: its gate is
event.hits(cx, self.area), which never yields a press another area claimed.The cause is in the shell, not makepad. Capture overload is how makepad lets a widget share a press with the scroll view around it, and that is by design. Keeping separate windows apart is the window manager's job.
Fix
crates/shell/src/module_view.rs:Tests
New
crates/shell/src/module_input_tests.rsdraws module tiles cascaded, as the desk draws windows, and offers each press to them front to back, as the desk does:a_click_on_the_window_in_front_never_reaches_the_app_behinda_touch_on_the_window_in_front_never_reaches_the_app_behindA click, then a touch, on the front window where it takes nothing, over a probe row behind it. The probe takes presses the way GestureView does. Only the front window is raised, and the app behind never sees the press. Control: where the back window is uncovered, its row takes the click or tap.
a_gesture_view_behind_the_window_in_front_never_captures_its_pressThe same press with makepad's own
GestureViewas the row behind. It no longer captures the press, which is what its tap fires on. Control: it does capture where it is in front.a_stopped_tile_takes_only_a_press_nothing_in_front_tookA click on the window over the closed face's Restart does not restart the app. A click on the face raises only it, and the app under the face never sees the press. With nothing over it, Restart still restarts.
All of the following ran on the Linux build host, at this head (
6524358, on mainc56ae14e). It merges cleanly with main4f73ab34; #274 does not touchmodule_view.rsordesk.rs.Main c56ae14 plus only these tests (no fix): all 4 fail, each at its bug assertion.
(1, 1)where(0, 0)is expected.[Raise(2), Restart(1)]; the click on Mail restarted the stopped app under it.With the fix:
phone/:cargo test --locked --features mobile-apps -p octosense-shellgives 770 passed, 0 failed.desktop/:cargo check --locked -p octosense, the same with--features mobile-apps, andbash ../tools/check-shell-graph.sh -p octosense.phone/:cargo check --locked -p octosense-home --features mobile-appsand its graph guard.python3 tools/setup.py --check --cargo.Instrument, before and after
Setup:
weston --backend=headless --renderer=pixman --idle-time=0and makepad's Wayland backend (llvmpipe).cargo build --release --locked -p octosense, driven over--remote.MAKEPAD_WRITE_FRAMEBUFFER_PNG. The home is a fresh scratch home, with the mock model.Layout from
/snap: News's card is at 54,105 (990×611) and Mail's at 84,135, on top. News's story rows (GestureView) start at y 349, 458 and 637.reader_title"" → "The Guardian" / "axios.com")reader_titlestays ""; Mail stays focusedFound on the way, not changed here
event.hitsclaims hovers too. So a hover over the empty part of a window can highlight a widget, or set its cursor, in the window behind. This comes from reading the code; I did not drive it.draw_stoppedkeepscx.walk_turtle(…)'s rect. A host-only scratch test measured it: for a face at (100, 100) 400×500,restart_rectis at (100, 134.8), but the button is drawn at (240, 349.4). So a click on the visible Restart does not restart. The test above clicks Restart where the face hit-tests it (restart_button()), so it holds either way.🤖 Generated with Claude Code