fix issue: #13911 'Double Click' bug on iPad with Magic Mouse (#14086)

* fix issue: #13911 'Double Click' bug on iPad with Magic Mouse

* remote_input.dart comments - gestures.dart organization and clean states of all interrupted gestures
This commit is contained in:
ThallesWS
2026-01-28 04:14:06 -03:00
committed by GitHub
parent 216ec9d52b
commit 45cab7f808
2 changed files with 35 additions and 1 deletions

View File

@@ -25,6 +25,7 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
GestureDragStartCallback? onOneFingerPanStart; GestureDragStartCallback? onOneFingerPanStart;
GestureDragUpdateCallback? onOneFingerPanUpdate; GestureDragUpdateCallback? onOneFingerPanUpdate;
GestureDragEndCallback? onOneFingerPanEnd; GestureDragEndCallback? onOneFingerPanEnd;
GestureDragCancelCallback? onOneFingerPanCancel;
// twoFingerScale : scale + pan event // twoFingerScale : scale + pan event
GestureScaleStartCallback? onTwoFingerScaleStart; GestureScaleStartCallback? onTwoFingerScaleStart;
@@ -169,6 +170,27 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
DragEndDetails _getDragEndDetails(ScaleEndDetails d) => DragEndDetails _getDragEndDetails(ScaleEndDetails d) =>
DragEndDetails(velocity: d.velocity); DragEndDetails(velocity: d.velocity);
@override
void rejectGesture(int pointer) {
super.rejectGesture(pointer);
switch (_currentState) {
case GestureState.oneFingerPan:
if (onOneFingerPanCancel != null) {
onOneFingerPanCancel!();
}
break;
case GestureState.twoFingerScale:
// Reset scale state if needed, currently self-contained
break;
case GestureState.threeFingerVerticalDrag:
// Reset drag state if needed, currently self-contained
break;
default:
break;
}
_currentState = GestureState.none;
}
} }
class HoldTapMoveGestureRecognizer extends GestureRecognizer { class HoldTapMoveGestureRecognizer extends GestureRecognizer {
@@ -717,6 +739,7 @@ RawGestureDetector getMixinGestureDetector({
GestureDragStartCallback? onOneFingerPanStart, GestureDragStartCallback? onOneFingerPanStart,
GestureDragUpdateCallback? onOneFingerPanUpdate, GestureDragUpdateCallback? onOneFingerPanUpdate,
GestureDragEndCallback? onOneFingerPanEnd, GestureDragEndCallback? onOneFingerPanEnd,
GestureDragCancelCallback? onOneFingerPanCancel,
GestureScaleUpdateCallback? onTwoFingerScaleUpdate, GestureScaleUpdateCallback? onTwoFingerScaleUpdate,
GestureScaleEndCallback? onTwoFingerScaleEnd, GestureScaleEndCallback? onTwoFingerScaleEnd,
GestureDragUpdateCallback? onThreeFingerVerticalDragUpdate, GestureDragUpdateCallback? onThreeFingerVerticalDragUpdate,
@@ -765,6 +788,7 @@ RawGestureDetector getMixinGestureDetector({
..onOneFingerPanStart = onOneFingerPanStart ..onOneFingerPanStart = onOneFingerPanStart
..onOneFingerPanUpdate = onOneFingerPanUpdate ..onOneFingerPanUpdate = onOneFingerPanUpdate
..onOneFingerPanEnd = onOneFingerPanEnd ..onOneFingerPanEnd = onOneFingerPanEnd
..onOneFingerPanCancel = onOneFingerPanCancel
..onTwoFingerScaleUpdate = onTwoFingerScaleUpdate ..onTwoFingerScaleUpdate = onTwoFingerScaleUpdate
..onTwoFingerScaleEnd = onTwoFingerScaleEnd ..onTwoFingerScaleEnd = onTwoFingerScaleEnd
..onThreeFingerVerticalDragUpdate = onThreeFingerVerticalDragUpdate; ..onThreeFingerVerticalDragUpdate = onThreeFingerVerticalDragUpdate;

View File

@@ -158,7 +158,8 @@ class _RawTouchGestureDetectorRegionState
final isMoved = final isMoved =
await ffi.cursorModel.move(d.localPosition.dx, d.localPosition.dy); await ffi.cursorModel.move(d.localPosition.dx, d.localPosition.dy);
if (isMoved) { if (isMoved) {
if (lastTapDownDetails != null) { // If pan already handled 'down', don't send it again.
if (lastTapDownDetails != null && !_touchModePanStarted) {
await inputModel.tapDown(MouseButtons.left); await inputModel.tapDown(MouseButtons.left);
} }
await inputModel.tapUp(MouseButtons.left); await inputModel.tapUp(MouseButtons.left);
@@ -424,6 +425,14 @@ class _RawTouchGestureDetectorRegionState
} }
} }
// Reset `_touchModePanStarted` if the one-finger pan gesture is cancelled
// or rejected by the gesture arena. Without this, the flag can remain
// stuck in the "started" state and cause issues such as the Magic Mouse
// double-click problem on iPad with magic mouse.
onOneFingerPanCancel() {
_touchModePanStarted = false;
}
// scale + pan event // scale + pan event
onTwoFingerScaleStart(ScaleStartDetails d) { onTwoFingerScaleStart(ScaleStartDetails d) {
_lastTapDownDetails = null; _lastTapDownDetails = null;
@@ -557,6 +566,7 @@ class _RawTouchGestureDetectorRegionState
instance instance
..onOneFingerPanUpdate = onOneFingerPanUpdate ..onOneFingerPanUpdate = onOneFingerPanUpdate
..onOneFingerPanEnd = onOneFingerPanEnd ..onOneFingerPanEnd = onOneFingerPanEnd
..onOneFingerPanCancel = onOneFingerPanCancel
..onTwoFingerScaleStart = onTwoFingerScaleStart ..onTwoFingerScaleStart = onTwoFingerScaleStart
..onTwoFingerScaleUpdate = onTwoFingerScaleUpdate ..onTwoFingerScaleUpdate = onTwoFingerScaleUpdate
..onTwoFingerScaleEnd = onTwoFingerScaleEnd ..onTwoFingerScaleEnd = onTwoFingerScaleEnd