Skip to content

Commit

Permalink
Web - Fix selection jump on Android
Browse files Browse the repository at this point in the history
  • Loading branch information
bleroux committed Apr 14, 2023
1 parent 4b96e38 commit 79f64a3
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
9 changes: 7 additions & 2 deletions lib/web_ui/lib/src/engine/text_editing/text_editing.dart
Expand Up @@ -1416,9 +1416,12 @@ abstract class DefaultTextEditingStrategy with CompositionAwareMixin implements

/// Prevent default behavior for mouse down, up and move.
///
/// When normal mouse events are not prevented, in desktop browsers, mouse
/// selection conflicts with selection sent from the framework, which creates
/// When normal mouse events are not prevented, mouse selection
/// conflicts with selection sent from the framework, which creates
/// flickering during selection by mouse.
///
/// On mobile browsers, mouse events are sent after a touch event,
/// see: https://bugs.chromium.org/p/chromium/issues/detail?id=119216#c11.
void preventDefaultForMouseEvents() {
subscriptions.add(
DomSubscription(activeDomElement, 'mousedown', (_) {
Expand Down Expand Up @@ -1705,6 +1708,8 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
owner.sendTextConnectionClosedToFrameworkIfAny();
}
}));

preventDefaultForMouseEvents();
}

@override
Expand Down
54 changes: 54 additions & 0 deletions lib/web_ui/test/engine/text_editing_test.dart
Expand Up @@ -1896,6 +1896,59 @@ Future<void> testMain() async {
hideKeyboard();
});

test('prevent mouse events on Android', () {
// Regression test for https://github.com/flutter/flutter/issues/124483.
debugOperatingSystemOverride = OperatingSystem.android;
debugBrowserEngineOverride = BrowserEngine.blink;

/// During initialization [HybridTextEditing] will pick the correct
/// text editing strategy for [OperatingSystem.android].
textEditing = HybridTextEditing();

final MethodCall setClient = MethodCall(
'TextInput.setClient',
<dynamic>[123, flutterMultilineConfig],
);
sendFrameworkMessage(codec.encodeMethodCall(setClient));

// Editing shouldn't have started yet.
expect(defaultTextEditingRoot.ownerDocument?.activeElement, domDocument.body);

const MethodCall show = MethodCall('TextInput.show');
sendFrameworkMessage(codec.encodeMethodCall(show));

// The "setSizeAndTransform" message has to be here before we call
// checkInputEditingState, since on some platforms (e.g. Desktop Safari)
// we don't put the input element into the DOM until we get its correct
// dimensions from the framework.
final List<double> transform = Matrix4.translationValues(10.0, 20.0, 30.0).storage.toList();
final MethodCall setSizeAndTransform = configureSetSizeAndTransformMethodCall(150, 50, transform);
sendFrameworkMessage(codec.encodeMethodCall(setSizeAndTransform));

final DomHTMLTextAreaElement textarea = textEditing!.strategy.domElement! as DomHTMLTextAreaElement;
checkTextAreaEditingState(textarea, '', 0, 0);

// Can set editing state and preserve new lines.
const MethodCall setEditingState = MethodCall(
'TextInput.setEditingState',
<String, dynamic>{
'text': '1\n2\n3\n4\n',
'selectionBase': 8,
'selectionExtent': 8,
'composingBase': null,
'composingExtent': null,
},
);
sendFrameworkMessage(codec.encodeMethodCall(setEditingState));
checkTextAreaEditingState(textarea, '1\n2\n3\n4\n', 8, 8);

// 'mousedown' event should be prevented.
final bool prevented = !textarea.dispatchEvent(createDomEvent('Event', 'mousedown'));
expect(prevented, true);

hideKeyboard();
});

test('sets correct input type in iOS', () {
// Test on ios-safari only.
if (browserEngine == BrowserEngine.webkit &&
Expand Down Expand Up @@ -2324,6 +2377,7 @@ Future<void> testMain() async {
expect(textArea.selectionEnd, 2);
});


test('Configure input element editing state for a flipped base and extent',
() {
final DomHTMLInputElement input =
Expand Down

0 comments on commit 79f64a3

Please sign in to comment.