Unverified Commit 16e7218c authored by yim's avatar yim Committed by GitHub

Fixed cursor blinking during selection. (#141380)

The cursor now correctly stops blinking while it's being interacted with.
parent 025d18d7
...@@ -1193,6 +1193,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin, ...@@ -1193,6 +1193,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
/// in detail. /// in detail.
EdgeInsets floatingCursorAddedMargin; EdgeInsets floatingCursorAddedMargin;
/// Returns true if the floating cursor is visible, false otherwise.
bool get floatingCursorOn => _floatingCursorOn;
bool _floatingCursorOn = false; bool _floatingCursorOn = false;
late TextPosition _floatingCursorTextPosition; late TextPosition _floatingCursorTextPosition;
......
...@@ -4166,7 +4166,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -4166,7 +4166,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_cursorVisibilityNotifier.value = widget.showCursor && (EditableText.debugDeterministicCursor || _cursorBlinkOpacityController.value > 0); _cursorVisibilityNotifier.value = widget.showCursor && (EditableText.debugDeterministicCursor || _cursorBlinkOpacityController.value > 0);
} }
bool get _showBlinkingCursor => _hasFocus && _value.selection.isCollapsed && widget.showCursor && _tickersEnabled; bool get _showBlinkingCursor => _hasFocus && _value.selection.isCollapsed && widget.showCursor && _tickersEnabled && !renderEditable.floatingCursorOn;
/// Whether the blinking cursor is actually visible at this precise moment /// Whether the blinking cursor is actually visible at this precise moment
/// (it's hidden half the time, since it blinks). /// (it's hidden half the time, since it blinks).
...@@ -4230,7 +4230,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -4230,7 +4230,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
} }
void _stopCursorBlink({ bool resetCharTicks = true }) { void _stopCursorBlink({ bool resetCharTicks = true }) {
_cursorBlinkOpacityController.value = 0.0; // If the cursor is animating, stop the animation, and we always
// want the cursor to be visible when the floating cursor is enabled.
_cursorBlinkOpacityController.value = renderEditable.floatingCursorOn ? 1.0 : 0.0;
_cursorTimer?.cancel(); _cursorTimer?.cancel();
_cursorTimer = null; _cursorTimer = null;
if (resetCharTicks) { if (resetCharTicks) {
......
...@@ -17838,7 +17838,6 @@ void main() { ...@@ -17838,7 +17838,6 @@ void main() {
skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu. skip: isContextMenuProvidedByPlatform, // [intended] only applies to platforms where we supply the context menu.
); );
testWidgets('Start the floating cursor on long tap', (WidgetTester tester) async { testWidgets('Start the floating cursor on long tap', (WidgetTester tester) async {
EditableText.debugDeterministicCursor = true; EditableText.debugDeterministicCursor = true;
final TextEditingController controller = _textEditingController( final TextEditingController controller = _textEditingController(
...@@ -17879,6 +17878,58 @@ void main() { ...@@ -17879,6 +17878,58 @@ void main() {
}, },
variant: TargetPlatformVariant.only(TargetPlatform.iOS), variant: TargetPlatformVariant.only(TargetPlatform.iOS),
); );
testWidgets('Cursor should not blink when long-pressing to show floating cursor.', (WidgetTester tester) async {
final TextEditingController controller = _textEditingController(
text: 'abcdefghijklmnopqr',
);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(
autofocus: true,
controller: controller,
cursorOpacityAnimates: false
)
),
),
),
);
final EditableTextState state = tester.state(find.byType(EditableText));
Future<void> checkCursorBlinking({ bool isBlinking = true }) async {
bool initialShowCursor = true;
if (isBlinking) {
initialShowCursor = state.renderEditable.showCursor.value;
}
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(isBlinking ? !initialShowCursor : initialShowCursor));
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(initialShowCursor));
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(isBlinking ? !initialShowCursor : initialShowCursor));
await tester.pump(state.cursorBlinkInterval);
expect(state.cursorCurrentlyVisible, equals(initialShowCursor));
}
// Wait for autofocus.
await tester.pumpAndSettle();
// Before long-pressing, the cursor should blink.
await checkCursorBlinking();
final TestGesture gesture = await tester.startGesture(tester.getTopLeft(find.byType(TextField)));
await tester.pump(kLongPressTimeout);
// When long-pressing, the cursor shouldn't blink.
await checkCursorBlinking(isBlinking: false);
await gesture.moveBy(const Offset(20, 0));
await tester.pump();
// When long-pressing and dragging to move the cursor, the cursor shouldn't blink.
await checkCursorBlinking(isBlinking: false);
await gesture.up();
// After finishing the long-press, the cursor should blink.
await checkCursorBlinking();
},
variant: TargetPlatformVariant.only(TargetPlatform.iOS),
);
} }
/// A Simple widget for testing the obscure text. /// A Simple widget for testing the obscure text.
......
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