Unverified Commit e4e9dde4 authored by Tomasz Gucio's avatar Tomasz Gucio Committed by GitHub

Move TapAndDragGestureRecognizer code under gestures (#119508)

parent 3213588c
...@@ -30,5 +30,6 @@ export 'src/gestures/recognizer.dart'; ...@@ -30,5 +30,6 @@ export 'src/gestures/recognizer.dart';
export 'src/gestures/resampler.dart'; export 'src/gestures/resampler.dart';
export 'src/gestures/scale.dart'; export 'src/gestures/scale.dart';
export 'src/gestures/tap.dart'; export 'src/gestures/tap.dart';
export 'src/gestures/tap_and_drag.dart';
export 'src/gestures/team.dart'; export 'src/gestures/team.dart';
export 'src/gestures/velocity_tracker.dart'; export 'src/gestures/velocity_tracker.dart';
...@@ -24,7 +24,6 @@ import 'gesture_detector.dart'; ...@@ -24,7 +24,6 @@ import 'gesture_detector.dart';
import 'magnifier.dart'; import 'magnifier.dart';
import 'overlay.dart'; import 'overlay.dart';
import 'scrollable.dart'; import 'scrollable.dart';
import 'tap_and_drag_gestures.dart';
import 'tap_region.dart'; import 'tap_region.dart';
import 'ticker_provider.dart'; import 'ticker_provider.dart';
import 'transitions.dart'; import 'transitions.dart';
...@@ -1993,11 +1992,6 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1993,11 +1992,6 @@ class TextSelectionGestureDetectorBuilder {
&& targetSelection.end >= textPosition.offset; && targetSelection.end >= textPosition.offset;
} }
/// Returns true if shift left or right is contained in the given set.
static bool _containsShift(Set<LogicalKeyboardKey> keysPressed) {
return keysPressed.any(<LogicalKeyboardKey>{ LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.shiftRight }.contains);
}
// Expand the selection to the given global position. // Expand the selection to the given global position.
// //
// Either base or extent will be moved to the last tapped position, whichever // Either base or extent will be moved to the last tapped position, whichever
...@@ -2074,6 +2068,10 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2074,6 +2068,10 @@ class TextSelectionGestureDetectorBuilder {
@protected @protected
RenderEditable get renderEditable => editableText.renderEditable; RenderEditable get renderEditable => editableText.renderEditable;
/// Whether the Shift key was pressed when the most recent [PointerDownEvent]
/// was tracked by the [BaseTapAndDragGestureRecognizer].
bool _isShiftPressed = false;
/// The viewport offset pixels of any [Scrollable] containing the /// The viewport offset pixels of any [Scrollable] containing the
/// [RenderEditable] at the last drag start. /// [RenderEditable] at the last drag start.
double _dragStartScrollOffset = 0.0; double _dragStartScrollOffset = 0.0;
...@@ -2113,6 +2111,30 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2113,6 +2111,30 @@ class TextSelectionGestureDetectorBuilder {
// focused, the cursor moves to the long press position. // focused, the cursor moves to the long press position.
bool _longPressStartedWithoutFocus = false; bool _longPressStartedWithoutFocus = false;
/// Handler for [TextSelectionGestureDetector.onTapTrackStart].
///
/// See also:
///
/// * [TextSelectionGestureDetector.onTapTrackStart], which triggers this
/// callback.
@protected
void onTapTrackStart() {
_isShiftPressed = HardwareKeyboard.instance.logicalKeysPressed
.intersection(<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.shiftRight})
.isNotEmpty;
}
/// Handler for [TextSelectionGestureDetector.onTapTrackReset].
///
/// See also:
///
/// * [TextSelectionGestureDetector.onTapTrackReset], which triggers this
/// callback.
@protected
void onTapTrackReset() {
_isShiftPressed = false;
}
/// Handler for [TextSelectionGestureDetector.onTapDown]. /// Handler for [TextSelectionGestureDetector.onTapDown].
/// ///
/// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets /// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets
...@@ -2145,11 +2167,9 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2145,11 +2167,9 @@ class TextSelectionGestureDetectorBuilder {
|| kind == PointerDeviceKind.touch || kind == PointerDeviceKind.touch
|| kind == PointerDeviceKind.stylus; || kind == PointerDeviceKind.stylus;
// Handle shift + click selection if needed.
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
// It is impossible to extend the selection when the shift key is pressed, if the // It is impossible to extend the selection when the shift key is pressed, if the
// renderEditable.selection is invalid. // renderEditable.selection is invalid.
final bool isShiftPressedValid = isShiftPressed && renderEditable.selection?.baseOffset != null; final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
...@@ -2246,11 +2266,9 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2246,11 +2266,9 @@ class TextSelectionGestureDetectorBuilder {
@protected @protected
void onSingleTapUp(TapDragUpDetails details) { void onSingleTapUp(TapDragUpDetails details) {
if (delegate.selectionEnabled) { if (delegate.selectionEnabled) {
// Handle shift + click selection if needed.
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
// It is impossible to extend the selection when the shift key is pressed, if the // It is impossible to extend the selection when the shift key is pressed, if the
// renderEditable.selection is invalid. // renderEditable.selection is invalid.
final bool isShiftPressedValid = isShiftPressed && renderEditable.selection?.baseOffset != null; final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.linux: case TargetPlatform.linux:
case TargetPlatform.macOS: case TargetPlatform.macOS:
...@@ -2641,9 +2659,7 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2641,9 +2659,7 @@ class TextSelectionGestureDetectorBuilder {
return; return;
} }
final bool isShiftPressed = _containsShift(details.keysPressedOnDown); if (_isShiftPressed && renderEditable.selection != null && renderEditable.selection!.isValid) {
if (isShiftPressed && renderEditable.selection != null && renderEditable.selection!.isValid) {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
case TargetPlatform.macOS: case TargetPlatform.macOS:
...@@ -2730,9 +2746,7 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2730,9 +2746,7 @@ class TextSelectionGestureDetectorBuilder {
return; return;
} }
final bool isShiftPressed = _containsShift(details.keysPressedOnDown); if (!_isShiftPressed) {
if (!isShiftPressed) {
// Adjust the drag start offset for possible viewport offset changes. // Adjust the drag start offset for possible viewport offset changes.
final Offset editableOffset = renderEditable.maxLines == 1 final Offset editableOffset = renderEditable.maxLines == 1
? Offset(renderEditable.offset.pixels - _dragStartViewportOffset, 0.0) ? Offset(renderEditable.offset.pixels - _dragStartViewportOffset, 0.0)
...@@ -2931,14 +2945,13 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2931,14 +2945,13 @@ class TextSelectionGestureDetectorBuilder {
/// callback. /// callback.
@protected @protected
void onDragSelectionEnd(TapDragEndDetails details) { void onDragSelectionEnd(TapDragEndDetails details) {
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
_dragBeganOnPreviousSelection = null; _dragBeganOnPreviousSelection = null;
if (_shouldShowSelectionToolbar && _TextSelectionGestureDetectorState._getEffectiveConsecutiveTapCount(details.consecutiveTapCount) == 2) { if (_shouldShowSelectionToolbar && _TextSelectionGestureDetectorState._getEffectiveConsecutiveTapCount(details.consecutiveTapCount) == 2) {
editableText.showToolbar(); editableText.showToolbar();
} }
if (isShiftPressed) { if (_isShiftPressed) {
_dragStartSelection = null; _dragStartSelection = null;
} }
...@@ -2956,6 +2969,8 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2956,6 +2969,8 @@ class TextSelectionGestureDetectorBuilder {
}) { }) {
return TextSelectionGestureDetector( return TextSelectionGestureDetector(
key: key, key: key,
onTapTrackStart: onTapTrackStart,
onTapTrackReset: onTapTrackReset,
onTapDown: onTapDown, onTapDown: onTapDown,
onForcePressStart: delegate.forcePressEnabled ? onForcePressStart : null, onForcePressStart: delegate.forcePressEnabled ? onForcePressStart : null,
onForcePressEnd: delegate.forcePressEnabled ? onForcePressEnd : null, onForcePressEnd: delegate.forcePressEnabled ? onForcePressEnd : null,
...@@ -2996,6 +3011,8 @@ class TextSelectionGestureDetector extends StatefulWidget { ...@@ -2996,6 +3011,8 @@ class TextSelectionGestureDetector extends StatefulWidget {
/// The [child] parameter must not be null. /// The [child] parameter must not be null.
const TextSelectionGestureDetector({ const TextSelectionGestureDetector({
super.key, super.key,
this.onTapTrackStart,
this.onTapTrackReset,
this.onTapDown, this.onTapDown,
this.onForcePressStart, this.onForcePressStart,
this.onForcePressEnd, this.onForcePressEnd,
...@@ -3015,6 +3032,12 @@ class TextSelectionGestureDetector extends StatefulWidget { ...@@ -3015,6 +3032,12 @@ class TextSelectionGestureDetector extends StatefulWidget {
required this.child, required this.child,
}); });
/// {@macro flutter.gestures.selectionrecognizers.BaseTapAndDragGestureRecognizer.onTapTrackStart}
final VoidCallback? onTapTrackStart;
/// {@macro flutter.gestures.selectionrecognizers.BaseTapAndDragGestureRecognizer.onTapTrackReset}
final VoidCallback? onTapTrackReset;
/// Called for every tap down including every tap down that's part of a /// Called for every tap down including every tap down that's part of a
/// double click or a long press, except touches that include enough movement /// double click or a long press, except touches that include enough movement
/// to not qualify as taps (e.g. pans and flings). /// to not qualify as taps (e.g. pans and flings).
...@@ -3125,6 +3148,14 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec ...@@ -3125,6 +3148,14 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
} }
} }
void _handleTapTrackStart() {
widget.onTapTrackStart?.call();
}
void _handleTapTrackReset() {
widget.onTapTrackReset?.call();
}
// The down handler is force-run on success of a single tap and optimistically // The down handler is force-run on success of a single tap and optimistically
// run before a long press success. // run before a long press success.
void _handleTapDown(TapDragDownDetails details) { void _handleTapDown(TapDragDownDetails details) {
...@@ -3231,6 +3262,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec ...@@ -3231,6 +3262,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
// Text selection should start from the position of the first pointer // Text selection should start from the position of the first pointer
// down event. // down event.
..dragStartBehavior = DragStartBehavior.down ..dragStartBehavior = DragStartBehavior.down
..onTapTrackStart = _handleTapTrackStart
..onTapTrackReset = _handleTapTrackReset
..onTapDown = _handleTapDown ..onTapDown = _handleTapDown
..onDragStart = _handleDragStart ..onDragStart = _handleDragStart
..onDragUpdate = _handleDragUpdate ..onDragUpdate = _handleDragUpdate
...@@ -3249,6 +3282,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec ...@@ -3249,6 +3282,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
// Text selection should start from the position of the first pointer // Text selection should start from the position of the first pointer
// down event. // down event.
..dragStartBehavior = DragStartBehavior.down ..dragStartBehavior = DragStartBehavior.down
..onTapTrackStart = _handleTapTrackStart
..onTapTrackReset = _handleTapTrackReset
..onTapDown = _handleTapDown ..onTapDown = _handleTapDown
..onDragStart = _handleDragStart ..onDragStart = _handleDragStart
..onDragUpdate = _handleDragUpdate ..onDragUpdate = _handleDragUpdate
......
...@@ -140,7 +140,6 @@ export 'src/widgets/spacer.dart'; ...@@ -140,7 +140,6 @@ export 'src/widgets/spacer.dart';
export 'src/widgets/spell_check.dart'; export 'src/widgets/spell_check.dart';
export 'src/widgets/status_transitions.dart'; export 'src/widgets/status_transitions.dart';
export 'src/widgets/table.dart'; export 'src/widgets/table.dart';
export 'src/widgets/tap_and_drag_gestures.dart';
export 'src/widgets/tap_region.dart'; export 'src/widgets/tap_region.dart';
export 'src/widgets/text.dart'; export 'src/widgets/text.dart';
export 'src/widgets/text_editing_intents.dart'; export 'src/widgets/text_editing_intents.dart';
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import '../gestures/gesture_tester.dart'; import '../gestures/gesture_tester.dart';
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart' show ValueListenable, defaultTargetPlatform; import 'package:flutter/foundation.dart' show ValueListenable, defaultTargetPlatform;
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment