Skip to content

Dashboard tile gestures: mixed drag/resize concurrency has no cross-gesture guard #606

Description

@BorisTyshkevich

src/ui/dashboard-tile-gestures.ts's createTileGestureController has no cross-gesture mutual exclusion, despite the natural reading of "one gesture at a time":

  • dragActive (declared line 191, guard at line 386 if (dragActive) return;) blocks only a second concurrent drag — a resize (wireGridResize) never checks it, so a resize can start and run while a drag is active, and vice versa.
  • The single "currently cancellable gesture" slot, installedGestureCancel (declared line 200), is last-writer-wins and self-clearing: whichever gesture (re)installs it last (drag at line 659, resize at line 307) owns it; each gesture's own cleanup only nulls the slot if it is still the one holding it (drag clears at line 623, resize at line 280) — so an older gesture's cleanup never stomps a newer one's slot, but a dispose()/rerender only ever cancels whichever gesture currently holds the slot, leaving the other orphaned against soon-to-be-replaced DOM.
  • Neither gesture filters its window pointermove/pointerup listeners by pointerId (module doc comment, lines 42-44) — a pointer other than the one that started the gesture still moves/ends it, and two concurrent resizes both terminate off one shared pointerup.

This is pinned by the "tile gesture concurrency characterization (#589 wave 2, CURRENT BEHAVIOR — not a guarantee, see inbox)" describe block in tests/unit/dashboard.test.ts and exercised at the controller-unit level across tests/unit/dashboard-tile-gestures.test.ts.

It is a pre-existing defect predating #589 (#593 refactor umbrella) — the extraction in wave 2 preserved it verbatim rather than introducing it. Fixing it is out of scope for a pure structural extraction; filing so a deliberate design decision (mutual exclusion vs. documented-intentional concurrency) can be made separately.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    inboxFiled mid-task; not yet triaged into the roadmap

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions