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';
export 'src/gestures/resampler.dart';
export 'src/gestures/scale.dart';
export 'src/gestures/tap.dart';
export 'src/gestures/tap_and_drag.dart';
export 'src/gestures/team.dart';
export 'src/gestures/velocity_tracker.dart';
......@@ -24,7 +24,6 @@ import 'gesture_detector.dart';
import 'magnifier.dart';
import 'overlay.dart';
import 'scrollable.dart';
import 'tap_and_drag_gestures.dart';
import 'tap_region.dart';
import 'ticker_provider.dart';
import 'transitions.dart';
......@@ -1993,11 +1992,6 @@ class TextSelectionGestureDetectorBuilder {
&& 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.
//
// Either base or extent will be moved to the last tapped position, whichever
......@@ -2074,6 +2068,10 @@ class TextSelectionGestureDetectorBuilder {
@protected
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
/// [RenderEditable] at the last drag start.
double _dragStartScrollOffset = 0.0;
......@@ -2113,6 +2111,30 @@ class TextSelectionGestureDetectorBuilder {
// focused, the cursor moves to the long press position.
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].
///
/// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets
......@@ -2145,11 +2167,9 @@ class TextSelectionGestureDetectorBuilder {
|| kind == PointerDeviceKind.touch
|| 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
// renderEditable.selection is invalid.
final bool isShiftPressedValid = isShiftPressed && renderEditable.selection?.baseOffset != null;
final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
......@@ -2246,11 +2266,9 @@ class TextSelectionGestureDetectorBuilder {
@protected
void onSingleTapUp(TapDragUpDetails details) {
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
// renderEditable.selection is invalid.
final bool isShiftPressedValid = isShiftPressed && renderEditable.selection?.baseOffset != null;
final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) {
case TargetPlatform.linux:
case TargetPlatform.macOS:
......@@ -2641,9 +2659,7 @@ class TextSelectionGestureDetectorBuilder {
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) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
......@@ -2730,9 +2746,7 @@ class TextSelectionGestureDetectorBuilder {
return;
}
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
if (!isShiftPressed) {
if (!_isShiftPressed) {
// Adjust the drag start offset for possible viewport offset changes.
final Offset editableOffset = renderEditable.maxLines == 1
? Offset(renderEditable.offset.pixels - _dragStartViewportOffset, 0.0)
......@@ -2931,14 +2945,13 @@ class TextSelectionGestureDetectorBuilder {
/// callback.
@protected
void onDragSelectionEnd(TapDragEndDetails details) {
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
_dragBeganOnPreviousSelection = null;
if (_shouldShowSelectionToolbar && _TextSelectionGestureDetectorState._getEffectiveConsecutiveTapCount(details.consecutiveTapCount) == 2) {
editableText.showToolbar();
}
if (isShiftPressed) {
if (_isShiftPressed) {
_dragStartSelection = null;
}
......@@ -2956,6 +2969,8 @@ class TextSelectionGestureDetectorBuilder {
}) {
return TextSelectionGestureDetector(
key: key,
onTapTrackStart: onTapTrackStart,
onTapTrackReset: onTapTrackReset,
onTapDown: onTapDown,
onForcePressStart: delegate.forcePressEnabled ? onForcePressStart : null,
onForcePressEnd: delegate.forcePressEnabled ? onForcePressEnd : null,
......@@ -2996,6 +3011,8 @@ class TextSelectionGestureDetector extends StatefulWidget {
/// The [child] parameter must not be null.
const TextSelectionGestureDetector({
super.key,
this.onTapTrackStart,
this.onTapTrackReset,
this.onTapDown,
this.onForcePressStart,
this.onForcePressEnd,
......@@ -3015,6 +3032,12 @@ class TextSelectionGestureDetector extends StatefulWidget {
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
/// double click or a long press, except touches that include enough movement
/// to not qualify as taps (e.g. pans and flings).
......@@ -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
// run before a long press success.
void _handleTapDown(TapDragDownDetails details) {
......@@ -3231,6 +3262,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
// Text selection should start from the position of the first pointer
// down event.
..dragStartBehavior = DragStartBehavior.down
..onTapTrackStart = _handleTapTrackStart
..onTapTrackReset = _handleTapTrackReset
..onTapDown = _handleTapDown
..onDragStart = _handleDragStart
..onDragUpdate = _handleDragUpdate
......@@ -3249,6 +3282,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
// Text selection should start from the position of the first pointer
// down event.
..dragStartBehavior = DragStartBehavior.down
..onTapTrackStart = _handleTapTrackStart
..onTapTrackReset = _handleTapTrackReset
..onTapDown = _handleTapDown
..onDragStart = _handleDragStart
..onDragUpdate = _handleDragUpdate
......
......@@ -140,7 +140,6 @@ export 'src/widgets/spacer.dart';
export 'src/widgets/spell_check.dart';
export 'src/widgets/status_transitions.dart';
export 'src/widgets/table.dart';
export 'src/widgets/tap_and_drag_gestures.dart';
export 'src/widgets/tap_region.dart';
export 'src/widgets/text.dart';
export 'src/widgets/text_editing_intents.dart';
......
......@@ -4,7 +4,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import '../gestures/gesture_tester.dart';
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
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/rendering.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