Unverified Commit e078c93b authored by Callum Moffat's avatar Callum Moffat Committed by GitHub

SelectionChangedCause for iOS keyboard-select (#122144)

SelectionChangedCause for iOS keyboard-select
parent d7e85174
...@@ -2775,7 +2775,15 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -2775,7 +2775,15 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (value.text == _value.text && value.composing == _value.composing) { if (value.text == _value.text && value.composing == _value.composing) {
// `selection` is the only change. // `selection` is the only change.
_handleSelectionChanged(value.selection, (_textInputConnection?.scribbleInProgress ?? false) ? SelectionChangedCause.scribble : SelectionChangedCause.keyboard); SelectionChangedCause cause;
if (_textInputConnection?.scribbleInProgress ?? false) {
cause = SelectionChangedCause.scribble;
} else if (_pointOffsetOrigin != null) {
cause = SelectionChangedCause.forcePress;
} else {
cause = SelectionChangedCause.keyboard;
}
_handleSelectionChanged(value.selection, cause);
} else { } else {
if (value.text != _value.text) { if (value.text != _value.text) {
// Hide the toolbar if the text was changed, but only hide the toolbar // Hide the toolbar if the text was changed, but only hide the toolbar
......
...@@ -2751,6 +2751,8 @@ void main() { ...@@ -2751,6 +2751,8 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(selectionCause, SelectionChangedCause.scribble); expect(selectionCause, SelectionChangedCause.scribble);
await tester.testTextInput.finishScribbleInteraction();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
testWidgets('Requests focus and changes the selection when onScribbleFocus is called', (WidgetTester tester) async { testWidgets('Requests focus and changes the selection when onScribbleFocus is called', (WidgetTester tester) async {
...@@ -12411,6 +12413,7 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12411,6 +12413,7 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
EditableText.debugDeterministicCursor = true; EditableText.debugDeterministicCursor = true;
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
SelectionChangedCause? lastSelectionChangedCause;
final TextEditingController controller = TextEditingController(text: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ\n1234567890'); final TextEditingController controller = TextEditingController(text: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ\n1234567890');
controller.selection = const TextSelection.collapsed(offset: 0); controller.selection = const TextSelection.collapsed(offset: 0);
...@@ -12425,6 +12428,9 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12425,6 +12428,9 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
cursorColor: Colors.blue, cursorColor: Colors.blue,
backgroundCursorColor: Colors.grey, backgroundCursorColor: Colors.grey,
cursorOpacityAnimates: true, cursorOpacityAnimates: true,
onSelectionChanged: (TextSelection selection, SelectionChangedCause? cause) {
lastSelectionChangedCause = cause;
},
maxLines: 2, maxLines: 2,
), ),
), ),
...@@ -12461,6 +12467,8 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12461,6 +12467,8 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
// Selection should be updated based on the floating cursor location. // Selection should be updated based on the floating cursor location.
expect(controller.selection.isCollapsed, true); expect(controller.selection.isCollapsed, true);
expect(controller.selection.baseOffset, 4); expect(controller.selection.baseOffset, 4);
expect(lastSelectionChangedCause, SelectionChangedCause.forcePress);
lastSelectionChangedCause = null;
state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start, offset: Offset.zero)); state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start, offset: Offset.zero));
await tester.pump(); await tester.pump();
...@@ -12486,7 +12494,7 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12486,7 +12494,7 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
)); ));
// Simulate UIKit setting the selection using keyboard selection. // Simulate UIKit setting the selection using keyboard selection.
controller.selection = const TextSelection(baseOffset: 0, extentOffset: 4); state.updateEditingValue(state.currentTextEditingValue.copyWith(selection: const TextSelection(baseOffset: 0, extentOffset: 4)));
await tester.pump(); await tester.pump();
state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End, offset: Offset.zero)); state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End, offset: Offset.zero));
...@@ -12496,9 +12504,11 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12496,9 +12504,11 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
expect(controller.selection.isCollapsed, false); expect(controller.selection.isCollapsed, false);
expect(controller.selection.baseOffset, 0); expect(controller.selection.baseOffset, 0);
expect(controller.selection.extentOffset, 4); expect(controller.selection.extentOffset, 4);
expect(lastSelectionChangedCause, SelectionChangedCause.forcePress);
lastSelectionChangedCause = null;
// Now test using keyboard selection in a forwards direction. // Now test using keyboard selection in a forwards direction.
controller.selection = const TextSelection.collapsed(offset: 0); state.updateEditingValue(state.currentTextEditingValue.copyWith(selection: const TextSelection.collapsed(offset: 0)));
await tester.pump(); await tester.pump();
state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start, offset: Offset.zero)); state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start, offset: Offset.zero));
await tester.pump(); await tester.pump();
...@@ -12523,7 +12533,7 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12523,7 +12533,7 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
)); ));
// Simulate UIKit setting the selection using keyboard selection. // Simulate UIKit setting the selection using keyboard selection.
controller.selection = const TextSelection(baseOffset: 0, extentOffset: 4); state.updateEditingValue(state.currentTextEditingValue.copyWith(selection: const TextSelection(baseOffset: 0, extentOffset: 4)));
await tester.pump(); await tester.pump();
state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End, offset: Offset.zero)); state.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End, offset: Offset.zero));
...@@ -12533,11 +12543,13 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12533,11 +12543,13 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
expect(controller.selection.isCollapsed, false); expect(controller.selection.isCollapsed, false);
expect(controller.selection.baseOffset, 0); expect(controller.selection.baseOffset, 0);
expect(controller.selection.extentOffset, 4); expect(controller.selection.extentOffset, 4);
expect(lastSelectionChangedCause, SelectionChangedCause.forcePress);
lastSelectionChangedCause = null;
// Test that the affinity is updated in case the floating cursor ends at the same offset. // Test that the affinity is updated in case the floating cursor ends at the same offset.
// Put the selection at the beginning of the second line. // Put the selection at the beginning of the second line.
controller.selection = const TextSelection.collapsed(offset: 27); state.updateEditingValue(state.currentTextEditingValue.copyWith(selection: const TextSelection.collapsed(offset: 27)));
await tester.pump(); await tester.pump();
// Now test using keyboard selection in a forwards direction. // Now test using keyboard selection in a forwards direction.
...@@ -12572,6 +12584,8 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async ...@@ -12572,6 +12584,8 @@ testWidgets('Floating cursor ending with selection', (WidgetTester tester) async
expect(controller.selection.isCollapsed, true); expect(controller.selection.isCollapsed, true);
expect(controller.selection.baseOffset, 27); expect(controller.selection.baseOffset, 27);
expect(controller.selection.extentOffset, 27); expect(controller.selection.extentOffset, 27);
expect(lastSelectionChangedCause, SelectionChangedCause.forcePress);
lastSelectionChangedCause = null;
EditableText.debugDeterministicCursor = false; EditableText.debugDeterministicCursor = false;
}); });
......
...@@ -296,6 +296,21 @@ class TestTextInput { ...@@ -296,6 +296,21 @@ class TestTextInput {
); );
} }
/// Simulates a scribble interaction finishing.
Future<void> finishScribbleInteraction() async {
assert(isRegistered);
await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.textInput.name,
SystemChannels.textInput.codec.encodeMethodCall(
MethodCall(
'TextInputClient.scribbleInteractionFinished',
<dynamic>[_client ?? -1,]
),
),
(ByteData? data) { /* response from framework is discarded */ },
);
}
/// Simulates a Scribble focus. /// Simulates a Scribble focus.
Future<void> scribbleFocusElement(String elementIdentifier, Offset offset) async { Future<void> scribbleFocusElement(String elementIdentifier, Offset offset) async {
assert(isRegistered); assert(isRegistered);
......
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