Skip to content

Commit 0752af8

Browse files
authored
Add allowedButtonsFilter to prevent Draggable from appearing with secondary click. (#111852)
* DragTarget part 1. [WIP] Change GestureRecognizer. Sorry. [WIP] Move from GestureRecognizer to MultiDragGestureRecognizer. Make it a `Set<int>?` Get bitwise operations working. Fix test. Rename to allowedInputPointers. Convert into a builder. Improve code with default funciton. Refactor everything again. Rename to buttonEventFilter. Use static function. Fix analyzer. Fix private reference. Use // in private method. * Fix Renzo request. * Add `allowedButtonsFilter` everywhere. * Refactor monoDrag for multi pointer support. * Fix tests? * Change default to always true. * Fix PR comments. * Completely refactor long press. * Add forgotten class. * Revert "Completely refactor long press." This reverts commit 5038e8603e250e8c928b0f1754fb794b7b75738b. * Add default value to LongPress * Refactor doubleTap. * Relax double tap. * Write comment in LongPress. * Use template.
1 parent 9024a70 commit 0752af8

14 files changed

+358
-52
lines changed

packages/flutter/lib/src/gestures/eager.dart

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class EagerGestureRecognizer extends OneSequenceGestureRecognizer {
2424
)
2525
super.kind,
2626
super.supportedDevices,
27+
super.allowedButtonsFilter,
2728
});
2829

2930
@override

packages/flutter/lib/src/gestures/force_press.dart

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
133133
)
134134
super.kind,
135135
super.supportedDevices,
136+
super.allowedButtonsFilter,
136137
}) : assert(startPressure != null),
137138
assert(peakPressure != null),
138139
assert(interpolation != null),

packages/flutter/lib/src/gestures/long_press.dart

+9
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
247247
/// The [duration] argument can be used to overwrite the default duration
248248
/// after which the long press will be recognized.
249249
///
250+
/// {@macro flutter.gestures.tap.TapGestureRecognizer.allowedButtonsFilter}
251+
///
250252
/// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
251253
LongPressGestureRecognizer({
252254
Duration? duration,
@@ -258,6 +260,7 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
258260
super.kind,
259261
super.supportedDevices,
260262
super.debugOwner,
263+
super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
261264
}) : super(
262265
deadline: duration ?? kLongPressTimeout,
263266
);
@@ -268,6 +271,12 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
268271
// different set of buttons, the gesture is canceled.
269272
int? _initialButtons;
270273

274+
// Accept the input if, and only if, a single button is pressed.
275+
static bool _defaultButtonAcceptBehavior(int buttons) =>
276+
buttons == kPrimaryButton ||
277+
buttons == kSecondaryButton ||
278+
buttons == kTertiaryButton;
279+
271280
/// Called when a pointer has contacted the screen at a particular location
272281
/// with a primary button, which might be the start of a long-press.
273282
///

packages/flutter/lib/src/gestures/monodrag.dart

+20-25
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,8 @@ typedef GestureVelocityTrackerBuilder = VelocityTracker Function(PointerEvent ev
5959
/// consider using one of its subclasses to recognize specific types for drag
6060
/// gestures.
6161
///
62-
/// [DragGestureRecognizer] competes on pointer events of [kPrimaryButton]
63-
/// only when it has at least one non-null callback. If it has no callbacks, it
64-
/// is a no-op.
62+
/// [DragGestureRecognizer] competes on pointer events only when it has at
63+
/// least one non-null callback. If it has no callbacks, it is a no-op.
6564
///
6665
/// See also:
6766
///
@@ -84,10 +83,14 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
8483
this.dragStartBehavior = DragStartBehavior.start,
8584
this.velocityTrackerBuilder = _defaultBuilder,
8685
super.supportedDevices,
86+
super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
8787
}) : assert(dragStartBehavior != null);
8888

8989
static VelocityTracker _defaultBuilder(PointerEvent event) => VelocityTracker.withKind(event.kind);
9090

91+
// Accept the input if, and only if, [kPrimaryButton] is pressed.
92+
static bool _defaultButtonAcceptBehavior(int buttons) => buttons == kPrimaryButton;
93+
9194
/// Configure the behavior of offsets passed to [onStart].
9295
///
9396
/// If set to [DragStartBehavior.start], the [onStart] callback will be called
@@ -122,7 +125,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
122125
///
123126
/// See also:
124127
///
125-
/// * [kPrimaryButton], the button this callback responds to.
128+
/// * [allowedButtonsFilter], which decides which button will be allowed.
126129
/// * [DragDownDetails], which is passed as an argument to this callback.
127130
GestureDragDownCallback? onDown;
128131

@@ -137,7 +140,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
137140
///
138141
/// See also:
139142
///
140-
/// * [kPrimaryButton], the button this callback responds to.
143+
/// * [allowedButtonsFilter], which decides which button will be allowed.
141144
/// * [DragStartDetails], which is passed as an argument to this callback.
142145
GestureDragStartCallback? onStart;
143146

@@ -151,7 +154,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
151154
///
152155
/// See also:
153156
///
154-
/// * [kPrimaryButton], the button this callback responds to.
157+
/// * [allowedButtonsFilter], which decides which button will be allowed.
155158
/// * [DragUpdateDetails], which is passed as an argument to this callback.
156159
GestureDragUpdateCallback? onUpdate;
157160

@@ -166,15 +169,15 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
166169
///
167170
/// See also:
168171
///
169-
/// * [kPrimaryButton], the button this callback responds to.
172+
/// * [allowedButtonsFilter], which decides which button will be allowed.
170173
/// * [DragEndDetails], which is passed as an argument to this callback.
171174
GestureDragEndCallback? onEnd;
172175

173176
/// The pointer that previously triggered [onDown] did not complete.
174177
///
175178
/// See also:
176179
///
177-
/// * [kPrimaryButton], the button this callback responds to.
180+
/// * [allowedButtonsFilter], which decides which button will be allowed.
178181
GestureDragCancelCallback? onCancel;
179182

180183
/// The minimum distance an input pointer drag must have moved to
@@ -251,18 +254,12 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
251254
@override
252255
bool isPointerAllowed(PointerEvent event) {
253256
if (_initialButtons == null) {
254-
switch (event.buttons) {
255-
case kPrimaryButton:
256-
if (onDown == null &&
257-
onStart == null &&
258-
onUpdate == null &&
259-
onEnd == null &&
260-
onCancel == null) {
261-
return false;
262-
}
263-
break;
264-
default:
265-
return false;
257+
if (onDown == null &&
258+
onStart == null &&
259+
onUpdate == null &&
260+
onEnd == null &&
261+
onCancel == null) {
262+
return false;
266263
}
267264
} else {
268265
// There can be multiple drags simultaneously. Their effects are combined.
@@ -449,7 +446,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
449446
}
450447

451448
void _checkDown() {
452-
assert(_initialButtons == kPrimaryButton);
453449
if (onDown != null) {
454450
final DragDownDetails details = DragDownDetails(
455451
globalPosition: _initialPosition.global,
@@ -460,7 +456,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
460456
}
461457

462458
void _checkStart(Duration timestamp, int pointer) {
463-
assert(_initialButtons == kPrimaryButton);
464459
if (onStart != null) {
465460
final DragStartDetails details = DragStartDetails(
466461
sourceTimeStamp: timestamp,
@@ -479,7 +474,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
479474
required Offset globalPosition,
480475
Offset? localPosition,
481476
}) {
482-
assert(_initialButtons == kPrimaryButton);
483477
if (onUpdate != null) {
484478
final DragUpdateDetails details = DragUpdateDetails(
485479
sourceTimeStamp: sourceTimeStamp,
@@ -493,7 +487,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
493487
}
494488

495489
void _checkEnd(int pointer) {
496-
assert(_initialButtons == kPrimaryButton);
497490
if (onEnd == null) {
498491
return;
499492
}
@@ -530,7 +523,6 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
530523
}
531524

532525
void _checkCancel() {
533-
assert(_initialButtons == kPrimaryButton);
534526
if (onCancel != null) {
535527
invokeCallback<void>('onCancel', onCancel!);
536528
}
@@ -570,6 +562,7 @@ class VerticalDragGestureRecognizer extends DragGestureRecognizer {
570562
)
571563
super.kind,
572564
super.supportedDevices,
565+
super.allowedButtonsFilter,
573566
});
574567

575568
@override
@@ -616,6 +609,7 @@ class HorizontalDragGestureRecognizer extends DragGestureRecognizer {
616609
)
617610
super.kind,
618611
super.supportedDevices,
612+
super.allowedButtonsFilter,
619613
});
620614

621615
@override
@@ -654,6 +648,7 @@ class PanGestureRecognizer extends DragGestureRecognizer {
654648
PanGestureRecognizer({
655649
super.debugOwner,
656650
super.supportedDevices,
651+
super.allowedButtonsFilter,
657652
});
658653

659654
@override

packages/flutter/lib/src/gestures/multidrag.dart

+8
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,12 @@ abstract class MultiDragGestureRecognizer extends GestureRecognizer {
223223
)
224224
super.kind,
225225
super.supportedDevices,
226+
super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
226227
});
227228

229+
// Accept the input if, and only if, [kPrimaryButton] is pressed.
230+
static bool _defaultButtonAcceptBehavior(int buttons) => buttons == kPrimaryButton;
231+
228232
/// Called when this class recognizes the start of a drag gesture.
229233
///
230234
/// The remaining notifications for this drag gesture are delivered to the
@@ -382,6 +386,7 @@ class ImmediateMultiDragGestureRecognizer extends MultiDragGestureRecognizer {
382386
)
383387
super.kind,
384388
super.supportedDevices,
389+
super.allowedButtonsFilter,
385390
});
386391

387392
@override
@@ -439,6 +444,7 @@ class HorizontalMultiDragGestureRecognizer extends MultiDragGestureRecognizer {
439444
)
440445
super.kind,
441446
super.supportedDevices,
447+
super.allowedButtonsFilter,
442448
});
443449

444450
@override
@@ -496,6 +502,7 @@ class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer {
496502
)
497503
super.kind,
498504
super.supportedDevices,
505+
super.allowedButtonsFilter,
499506
});
500507

501508
@override
@@ -606,6 +613,7 @@ class DelayedMultiDragGestureRecognizer extends MultiDragGestureRecognizer {
606613
)
607614
super.kind,
608615
super.supportedDevices,
616+
super.allowedButtonsFilter,
609617
}) : assert(delay != null);
610618

611619
/// The amount of time the pointer must remain in the same place for the drag

packages/flutter/lib/src/gestures/multitap.dart

+23-17
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ class _TapTracker {
113113
/// Recognizes when the user has tapped the screen at the same location twice in
114114
/// quick succession.
115115
///
116-
/// [DoubleTapGestureRecognizer] competes on pointer events of [kPrimaryButton]
117-
/// only when it has a non-null callback. If it has no callbacks, it is a no-op.
116+
/// [DoubleTapGestureRecognizer] competes on pointer events when it
117+
/// has a non-null callback. If it has no callbacks, it is a no-op.
118118
///
119119
class DoubleTapGestureRecognizer extends GestureRecognizer {
120120
/// Create a gesture recognizer for double taps.
@@ -128,8 +128,13 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
128128
)
129129
super.kind,
130130
super.supportedDevices,
131+
super.allowedButtonsFilter = _defaultButtonAcceptBehavior,
131132
});
132133

134+
// The default value for [allowedButtonsFilter].
135+
// Accept the input if, and only if, [kPrimaryButton] is pressed.
136+
static bool _defaultButtonAcceptBehavior(int buttons) => buttons == kPrimaryButton;
137+
133138
// Implementation notes:
134139
//
135140
// The double tap recognizer can be in one of four states. There's no
@@ -165,7 +170,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
165170
///
166171
/// See also:
167172
///
168-
/// * [kPrimaryButton], the button this callback responds to.
173+
/// * [allowedButtonsFilter], which decides which button will be allowed.
169174
/// * [TapDownDetails], which is passed as an argument to this callback.
170175
/// * [GestureDetector.onDoubleTapDown], which exposes this callback.
171176
GestureTapDownCallback? onDoubleTapDown;
@@ -178,7 +183,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
178183
///
179184
/// See also:
180185
///
181-
/// * [kPrimaryButton], the button this callback responds to.
186+
/// * [allowedButtonsFilter], which decides which button will be allowed.
182187
/// * [GestureDetector.onDoubleTap], which exposes this callback.
183188
GestureDoubleTapCallback? onDoubleTap;
184189

@@ -192,7 +197,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
192197
///
193198
/// See also:
194199
///
195-
/// * [kPrimaryButton], the button this callback responds to.
200+
/// * [allowedButtonsFilter], which decides which button will be allowed.
196201
/// * [GestureDetector.onDoubleTapCancel], which exposes this callback.
197202
GestureTapCancelCallback? onDoubleTapCancel;
198203

@@ -203,19 +208,19 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
203208
@override
204209
bool isPointerAllowed(PointerDownEvent event) {
205210
if (_firstTap == null) {
206-
switch (event.buttons) {
207-
case kPrimaryButton:
208-
if (onDoubleTapDown == null &&
209-
onDoubleTap == null &&
210-
onDoubleTapCancel == null) {
211-
return false;
212-
}
213-
break;
214-
default:
215-
return false;
211+
if (onDoubleTapDown == null &&
212+
onDoubleTap == null &&
213+
onDoubleTapCancel == null) {
214+
return false;
216215
}
217216
}
218-
return super.isPointerAllowed(event);
217+
218+
// If second tap is not allowed, reset the state.
219+
final bool isPointerAllowed = super.isPointerAllowed(event);
220+
if (isPointerAllowed == false) {
221+
_reset();
222+
}
223+
return isPointerAllowed;
219224
}
220225

221226
@override
@@ -367,7 +372,6 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
367372
}
368373

369374
void _checkUp(int buttons) {
370-
assert(buttons == kPrimaryButton);
371375
if (onDoubleTap != null) {
372376
invokeCallback<void>('onDoubleTap', onDoubleTap!);
373377
}
@@ -492,6 +496,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
492496
)
493497
super.kind,
494498
super.supportedDevices,
499+
super.allowedButtonsFilter,
495500
});
496501

497502
/// A pointer that might cause a tap has contacted the screen at a particular
@@ -813,6 +818,7 @@ class SerialTapGestureRecognizer extends GestureRecognizer {
813818
SerialTapGestureRecognizer({
814819
super.debugOwner,
815820
super.supportedDevices,
821+
super.allowedButtonsFilter,
816822
});
817823

818824
/// A pointer has contacted the screen at a particular location, which might

0 commit comments

Comments
 (0)