An app you switch to while holding the mouse button stays off screen#324

opened4d agobySSamanyu Das

Steps to reproduce

  1. Run Miri Developer built from main at 546cfb04.
  2. Tile at least four columns on one display so that one app's only window (here Spotify) is parked off screen, and focus a Finder window on that display.
  3. Press the mouse button on a file in the Finder window and keep it held, as when you start dragging the file.
  4. While the button is held, switch to the app whose window is off screen, for example with Command-Tab. I sent the switch with osascript -e 'tell application id "com.spotify.client" to activate', which macOS reports to Miri as the same app activation.
  5. Release the button over a window that does not accept drops, and press Escape.

Expected result

The app you switch to comes into view while the button is held, so you can drop the file onto it. At the latest, it comes into view when you release the button.

Actual result

Spotify becomes the frontmost app and the engine focuses its window, but the window stays parked off screen while the button is held and after the release. The menu bar shows Spotify with no Spotify window in view. This happened in 2 of 2 tries with synthetic mouse events on 6 November 2026 (verify-miri run 20261106-150855). Control: the same activation with no button held scrolled Spotify into view. A screen capture during the hold showed no drag image, so the tries prove a held button, not necessarily a file drag in progress. Sam has not yet checked it with a real drag.

Cause, from the engine code at 20ba298:

  • A press on any tracked window spawns MouseHeldMarker (src/ecs/mouse.rs:289), whether or not it starts a window drag.
  • While that marker exists, autocenter_window_on_focus returns early (src/ecs/focus.rs:576), so the newly focused window is not revealed.
  • On release, mouse_up_trigger reshuffles around the pressed window (src/ecs/mouse.rs:314), here Finder, not around the focused window. Nothing reveals the focused window later.

Acceptance criteria

  • An engine test presses the mouse in one window's content, activates an app whose column is parked, and asserts that the column is visible while the button is held. Run with make engine-test.
  • An engine test asserts the same column is visible after the button is released.
  • A title-bar drag of a window still keeps the strip still while the window is held. The existing drag tests in make engine-test pass.
  • On the real desktop, Sam drags a file from Finder, presses Command-Tab to an app whose window is off screen, and that window comes into view before the file is dropped.

Miri version or commit

546cfb04 (engine 6c15fd6; the code above is unchanged on 4599ae7a, engine 20ba298)

macOS version and Mac model

macOS 27.0.1 (26A434), MacBook Air M3 (Mac15,12)

Displays and arrangement

Built-in (2048 x 1332 pt) to the left of a 27-inch external (2560 x 1440 pt, main display), Displays have separate Spaces on; tested on the external display

Note

🤖 Claude Opus 5.5 responding on behalf of samanyudas

Reproduced on current main and root-caused. The cause in the issue is right, and it has two parts that each need a change.

Reproduction on main

Build: /tmp/miri123/final (Miri 471737fb, engine a20f56e, the current pin). main at ffefedfa only adds docs on top. verify-miri run 20261106-201727, external display, eight AXFixture columns, so fixture-1 is parked at x 2555.

TryStepsfixture-1 during holdfixture-1 after release
h1Left button held in fixture-8's content, activate fixture-1's app, release after 4 sengine focus and frontmost, x 2555, not visiblex 2555, not visible
h2Same, release after 8 s (past the marker's 5 s timeout)engine focus and frontmost, x 2555, not visiblex 2555, not visible
c1Control, no button heldengine focus and frontmost, x 4, visiblen/a

The layout check at end passed and the previous build was restored. h2 shows that nothing reveals the window even after the held marker times out.

Root cause, confirmed in the engine harness

  1. autocenter_window_on_focus returns when any MouseHeldMarker exists (src/ecs/focus.rs:576). The guard comes from upstream 80f59e1 ("Clicking a window defers the reshuffle until mouse-up so content doesn't shift mid-click"). That intent covers the pressed window, but the check skips every newly focused window. A temporary print showed the early return for the activated window with one held marker.
  2. mouse_up_trigger reshuffles around the pressed window (src/ecs/mouse.rs:314) even when focus has moved to another window. With only part 1 fixed, the release scrolls the strip back to the pressed window and parks the activated one again.

Why the harness did not catch it: the mock's focus_window queues both ApplicationFrontSwitched and WindowFocused. front_switched_trigger turns the first into a WindowFocused too, so the second counts as a repeat and reaches the unguarded ensure_visible at src/ecs/triggers.rs:418, which reveals the window. On the Mac, activating an app whose only window is already its focused window gives one focus event (inferred from the live result, not logged), so only the guarded path runs. A faithful test gives the parked window its own app and calls activate_app alone.

Experiments (engine harness, nothing pushed)

Four tests: the two acceptance criteria, a no-hold control, and a new guard-purpose test (press a partly hidden window, which gets focus on the click, and check it stays put until release). No existing test covered this.

EngineHeld showsShows after releaseControlPressed window waits for releaseFull suite
a20f56e unchangedfailfailpasspass
A: drop !mouse_held.is_empty()passfailpass
B: A, plus skip the release reshuffle when the pressed window lost focuspasspasspassfail1311 passed (guard purpose untested)
C: B, but keep the guard for the pressed window onlypasspasspasspass1312 passed, 221 drag tests included

Fix options

  1. Recommended: C. In autocenter_window_on_focus, return only when the held marker names the focused entity. In mouse_up_trigger, reshuffle around the pressed window only if it still holds focus. About five changed lines plus the four tests. A title-bar drag stays covered by the separate DragState::holds_window guard.
  2. Keep the global guard, and on release reshuffle around the focused window instead of the pressed one. This meets only the release criterion. The window still stays hidden while the file is held, which is the case the issue is about.

Acceptance criteria

All four can be checked. Criteria 1 to 3 run in make engine-test. Criterion 4 is Sam's hand check with a real file drag, because synthetic drags in my run showed no drag image, as the issue already notes.

Related gap seen only in the harness: the repeat-focus path at triggers.rs:418 ignores a held button, so a duplicate focus event can still shift the strip mid-click. I have not seen this on the Mac and did not file it.

Note

🤖 T3 Tots responding on behalf of Sam

Scope decision (v1 readiness audit, 6 Nov 2026): blocks v1. Labelled v1 blocker. The fix choice from triage is still open.