Revert "[web] Don't overwrite editing state with semantic updates (#38271)"
This reverts commit 45713ea105104ac45ad10d2db7090add5246622a.
diff --git a/lib/web_ui/lib/src/engine/semantics/text_field.dart b/lib/web_ui/lib/src/engine/semantics/text_field.dart
index 289248e..3e36ffb 100644
--- a/lib/web_ui/lib/src/engine/semantics/text_field.dart
+++ b/lib/web_ui/lib/src/engine/semantics/text_field.dart
@@ -364,7 +364,11 @@
// element, so that both the framework and the browser agree on what's
// currently focused.
bool needsDomFocusRequest = false;
-
+ final EditingState editingState = EditingState(
+ text: semanticsObject.value,
+ baseOffset: semanticsObject.textSelectionBase,
+ extentOffset: semanticsObject.textSelectionExtent,
+ );
if (semanticsObject.hasFocus) {
if (!_hasFocused) {
_hasFocused = true;
@@ -374,9 +378,14 @@
if (domDocument.activeElement != editableElement) {
needsDomFocusRequest = true;
}
+ // Focused elements should have full text editing state applied.
+ SemanticsTextEditingStrategy.instance.setEditingState(editingState);
} else if (_hasFocused) {
SemanticsTextEditingStrategy.instance.deactivate(this);
+ // Only apply text, because this node is not focused.
+ editingState.applyTextToDomElement(editableElement);
+
if (_hasFocused && domDocument.activeElement == editableElement) {
// Unlike `editableElement.focus()` we don't need to schedule `blur`
// post-update because `document.activeElement` implies that the
diff --git a/lib/web_ui/test/engine/semantics/text_field_test.dart b/lib/web_ui/test/engine/semantics/text_field_test.dart
index fb87725..91129dc 100644
--- a/lib/web_ui/test/engine/semantics/text_field_test.dart
+++ b/lib/web_ui/test/engine/semantics/text_field_test.dart
@@ -4,8 +4,6 @@
@TestOn('chrome || safari || firefox')
-import 'dart:typed_data';
-
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
@@ -50,11 +48,6 @@
testTextEditing.configuration = singlelineConfig;
});
- /// Emulates sending of a message by the framework to the engine.
- void sendFrameworkMessage(ByteData? message) {
- testTextEditing.channel.handleTextInput(message, (ByteData? data) {});
- }
-
test('renders a text field', () async {
semantics()
..debugOverrideTimestampFunction(() => _testTime)
@@ -134,7 +127,7 @@
// TODO(yjbanov): https://github.com/flutter/flutter/issues/50754
skip: browserEngine != BrowserEngine.blink);
- test('Syncs semantic state from framework', () async {
+ test('Syncs editing state from framework', () async {
semantics()
..debugOverrideTimestampFunction(() => _testTime)
..semanticsEnabled = true;
@@ -166,6 +159,7 @@
expect(domDocument.activeElement, flutterViewEmbedder.glassPaneElement);
expect(appHostNode.activeElement, strategy.domElement);
expect(textField.editableElement, strategy.domElement);
+ expect((textField.editableElement as dynamic).value, 'hello');
expect(textField.editableElement.getAttribute('aria-label'), 'greeting');
expect(textField.editableElement.style.width, '10px');
expect(textField.editableElement.style.height, '15px');
@@ -180,6 +174,7 @@
expect(domDocument.activeElement, domDocument.body);
expect(appHostNode.activeElement, null);
expect(strategy.domElement, null);
+ expect((textField.editableElement as dynamic).value, 'bye');
expect(textField.editableElement.getAttribute('aria-label'), 'farewell');
expect(textField.editableElement.style.width, '12px');
expect(textField.editableElement.style.height, '17px');
@@ -193,92 +188,6 @@
expect(actionCount, 0);
});
- test(
- 'Does not overwrite text value and selection editing state on semantic updates',
- () async {
- semantics()
- ..debugOverrideTimestampFunction(() => _testTime)
- ..semanticsEnabled = true;
-
- strategy.enable(
- singlelineConfig,
- onChange: (_, __) {},
- onAction: (_) {},
- );
-
- final SemanticsObject textFieldSemantics = createTextFieldSemantics(
- value: 'hello',
- textSelectionBase: 1,
- textSelectionExtent: 3,
- isFocused: true,
- rect: const ui.Rect.fromLTWH(0, 0, 10, 15));
-
- final TextField textField =
- textFieldSemantics.debugRoleManagerFor(Role.textField)! as TextField;
- final DomHTMLInputElement editableElement =
- textField.editableElement as DomHTMLInputElement;
-
- expect(editableElement, strategy.domElement);
- expect(editableElement.value, '');
- expect(editableElement.selectionStart, 0);
- expect(editableElement.selectionEnd, 0);
-
- strategy.disable();
- semantics().semanticsEnabled = false;
- });
-
- test(
- 'Updates editing state when receiving framework messages from the text input channel',
- () async {
- semantics()
- ..debugOverrideTimestampFunction(() => _testTime)
- ..semanticsEnabled = true;
-
- expect(domDocument.activeElement, domDocument.body);
- expect(appHostNode.activeElement, null);
-
- strategy.enable(
- singlelineConfig,
- onChange: (_, __) {},
- onAction: (_) {},
- );
-
- final SemanticsObject textFieldSemantics = createTextFieldSemantics(
- value: 'hello',
- textSelectionBase: 1,
- textSelectionExtent: 3,
- isFocused: true,
- rect: const ui.Rect.fromLTWH(0, 0, 10, 15));
-
- final TextField textField =
- textFieldSemantics.debugRoleManagerFor(Role.textField)! as TextField;
- final DomHTMLInputElement editableElement =
- textField.editableElement as DomHTMLInputElement;
-
- // No updates expected on semantic updates
- expect(editableElement, strategy.domElement);
- expect(editableElement.value, '');
- expect(editableElement.selectionStart, 0);
- expect(editableElement.selectionEnd, 0);
-
- // Update from framework
- const MethodCall setEditingState =
- MethodCall('TextInput.setEditingState', <String, dynamic>{
- 'text': 'updated',
- 'selectionBase': 2,
- 'selectionExtent': 3,
- });
- sendFrameworkMessage(codec.encodeMethodCall(setEditingState));
-
- // Editing state should now be updated
- expect(editableElement.value, 'updated');
- expect(editableElement.selectionStart, 2);
- expect(editableElement.selectionEnd, 3);
-
- strategy.disable();
- semantics().semanticsEnabled = false;
- });
-
test('Gives up focus after DOM blur', () async {
semantics()
..debugOverrideTimestampFunction(() => _testTime)
@@ -537,8 +446,6 @@
bool isFocused = false,
bool isMultiline = false,
ui.Rect rect = const ui.Rect.fromLTRB(0, 0, 100, 50),
- int textSelectionBase = 0,
- int textSelectionExtent = 0,
}) {
final SemanticsTester tester = SemanticsTester(semantics());
tester.updateNode(
@@ -551,8 +458,6 @@
hasTap: true,
rect: rect,
textDirection: ui.TextDirection.ltr,
- textSelectionBase: textSelectionBase,
- textSelectionExtent: textSelectionExtent
);
tester.apply();
return tester.getSemanticsObject(0);