A stationary modifier flip answers at the keystroke — the third client of the one shared retarget
Modifiers were sampled only inside resolveOperation, reached from dropUpdated and the commit — and drop callbacks arrive only while the mouse moves, so ⌥ pressed against a still pointer changed nothing until the next twitch. DragSession now arms a local .flagsChanged watch for exactly the session's lifetime (begin arms, end stops, the watchdog guarantees end; ⇧/⌃/caps don't count, a settled hold swallows) and publishes modifierGeneration; the three retargets record which window's surface resolved the proposal (RetargetOrigin — weak registry identity, never board root, so cross-board and two-windows- one-board both answer correctly), and the hovered window replays that same retarget with the operation re-resolved FIRST, since the index space is a function of it. The monitor is injectable — the real one needs a live event stream no test bundle has. Drag-perf card d491e7d3. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -112,6 +112,8 @@ Two carve-outs:
|
||||
|
||||
Geometry does not change across the boundary. The destination board's own resting layout answers the proposal, in the destination's own `standard` and gap; the arriving run's span is its unit counts measured against the destination's standard. What changes is only which commit runs and on which store — see below.
|
||||
|
||||
**"Sampled every frame" means sampled on every drop callback, and drop callbacks arrive only while the mouse moves.** A modifier pressed against a perfectly still pointer therefore reaches nothing: the operation decides what the *source* board's resting layout holds (a copy leaves its originals standing — see Resting-layout zones), whether the trash column takes the drop at all, and which index space the shadows are counted in, and all three used to wait for the next twitch of the mouse. So a `.flagsChanged` watch runs for exactly the drag's lifetime — armed at `begin`, stopped at `end`, which is where every way a drag can finish already funnels — and publishes a counter; the board window under the cursor turns that counter back into **the one shared retarget** (`BoardDropContext.retargetAfterModifierFlip`), the same seam the autoscroll driver's every scroll step goes through. The flip carries no location and needs none: the retargets read the physical mouse, so a stationary pointer is simply the cursor they already read. The window that answers is the one whose surface resolved the standing proposal — recorded per retarget as a `LaneDropRegistry`, which is per board *window* — so a cross-board drag re-proposes against the board being hovered and never against the one it came from. A settled release ignores flips entirely, the same freeze the committed-overlay hold applies to `propose` and to the operation itself.
|
||||
|
||||
## The drop commits
|
||||
|
||||
The commit is the store's, and it is one `performWrite` bracket per gesture whatever the set's size: one app-mediated reload, and (on git boards) one commit rather than N. Every one of them takes an index counted **against the destination's rendered items as the resting layout showed them** — so the number the geometry produced is the number the writer consumes, unrewritten. For every move that means "with the dragged run removed"; for the within-board ⌥-copy it means "with the originals still there", because a copy leaves them there and the zones counted them (see **Resting-layout zones**). Cross-board arrivals never face the question: the destination never held the originals.
|
||||
|
||||
Reference in New Issue
Block a user