fix!: Do not delegate onDragCancel to onDragEnd by default - #3934
Merged
Conversation
A cancellation is semantically different from a natural drag end: it has no velocity and means the gesture was interrupted (another recognizer won the arena, a scale takeover occurred, etc.). Delegating to onDragEnd made drag-to-dismiss style components apply their action on a cancel. With MultiDragScaleDispatcher every pinch cancels the individual pointer drags, so this is no longer the rare event the old comment claimed. onDragCancel now just resets isDragged; override it and call onDragEnd to keep the old behavior. Updated the docs and the tests that asserted delegation, and added a test isolating the new behavior. Closes flame-engine#3926
Adds the onDragCancel migration entry to doc/flame/migration.md and updates the examples and the Klondike tutorial that relied on a cancelled drag being delivered as an onDragEnd.
spydon
force-pushed
the
fix/on-drag-cancel-no-delegate
branch
from
August 5, 2026 19:56
dd7d162 to
d1950a0
Compare
spydon
approved these changes
Aug 5, 2026
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.
Description
DragCallbacks.onDragCancelused to delegate toonDragEndby default:But the two events mean different things.
onDragEndis the natural end of a drag and carriesvelocity for fling detection, while
onDragCancelmeans that the gesture was interrupted (anotherrecognizer won the arena, a second pointer triggered a scale takeover, a system event, etc.) and has
no meaningful velocity. Forwarding a cancel to
onDragEndmakes a drag-to-dismiss component applyits action even though the drag was actually cancelled. The old "very rare event" comment is no
longer true either: with
MultiDragScaleDispatcherevery two finger pinch cancels the individualpointer drags.
onDragCancelnow only resetsisDragged(the same state thatonDragEndclears) withoutforwarding. Anyone who wants the old behavior can override
onDragCanceland callonDragEnd(event.toDragEnd()), as the updated doc comment and the migration guide describe.The examples and the Klondike tutorial that relied on the old delegation have been updated to handle
onDragCancelexplicitly, otherwise a cancelled drag would leave a mouse joint alive, a ball withits drag paint, or a card floating in the middle of the table.
Checklist
docsand added dartdoc comments with///.examplesordocs.Breaking Change?
Migration instructions
onDragEndis no longer called when a drag is cancelled, onlyonDragCancelis. If you wererelying on the old behavior, forward the event yourself:
If a cancelled drag should instead be reverted, put that logic in
onDragCancelwithout callingonDragEnd. Seedoc/flame/migration.mdfor the full entry.Related Issues
Closes #3926