Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 5713a21

Browse files
authored
Revert "[web] Don't overwrite editing state with semantic updates (#38271)" (#38562)
This reverts commit 45713ea.
1 parent e012dc8 commit 5713a21

File tree

2 files changed

+13
-99
lines changed

2 files changed

+13
-99
lines changed

lib/web_ui/lib/src/engine/semantics/text_field.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,11 @@ class TextField extends RoleManager {
364364
// element, so that both the framework and the browser agree on what's
365365
// currently focused.
366366
bool needsDomFocusRequest = false;
367-
367+
final EditingState editingState = EditingState(
368+
text: semanticsObject.value,
369+
baseOffset: semanticsObject.textSelectionBase,
370+
extentOffset: semanticsObject.textSelectionExtent,
371+
);
368372
if (semanticsObject.hasFocus) {
369373
if (!_hasFocused) {
370374
_hasFocused = true;
@@ -374,9 +378,14 @@ class TextField extends RoleManager {
374378
if (domDocument.activeElement != editableElement) {
375379
needsDomFocusRequest = true;
376380
}
381+
// Focused elements should have full text editing state applied.
382+
SemanticsTextEditingStrategy.instance.setEditingState(editingState);
377383
} else if (_hasFocused) {
378384
SemanticsTextEditingStrategy.instance.deactivate(this);
379385

386+
// Only apply text, because this node is not focused.
387+
editingState.applyTextToDomElement(editableElement);
388+
380389
if (_hasFocused && domDocument.activeElement == editableElement) {
381390
// Unlike `editableElement.focus()` we don't need to schedule `blur`
382391
// post-update because `document.activeElement` implies that the

lib/web_ui/test/engine/semantics/text_field_test.dart

Lines changed: 3 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
@TestOn('chrome || safari || firefox')
66

7-
import 'dart:typed_data';
8-
97
import 'package:test/bootstrap/browser.dart';
108
import 'package:test/test.dart';
119

@@ -50,11 +48,6 @@ void testMain() {
5048
testTextEditing.configuration = singlelineConfig;
5149
});
5250

53-
/// Emulates sending of a message by the framework to the engine.
54-
void sendFrameworkMessage(ByteData? message) {
55-
testTextEditing.channel.handleTextInput(message, (ByteData? data) {});
56-
}
57-
5851
test('renders a text field', () async {
5952
semantics()
6053
..debugOverrideTimestampFunction(() => _testTime)
@@ -134,7 +127,7 @@ void testMain() {
134127
// TODO(yjbanov): https://github.com/flutter/flutter/issues/50754
135128
skip: browserEngine != BrowserEngine.blink);
136129

137-
test('Syncs semantic state from framework', () async {
130+
test('Syncs editing state from framework', () async {
138131
semantics()
139132
..debugOverrideTimestampFunction(() => _testTime)
140133
..semanticsEnabled = true;
@@ -166,6 +159,7 @@ void testMain() {
166159
expect(domDocument.activeElement, flutterViewEmbedder.glassPaneElement);
167160
expect(appHostNode.activeElement, strategy.domElement);
168161
expect(textField.editableElement, strategy.domElement);
162+
expect((textField.editableElement as dynamic).value, 'hello');
169163
expect(textField.editableElement.getAttribute('aria-label'), 'greeting');
170164
expect(textField.editableElement.style.width, '10px');
171165
expect(textField.editableElement.style.height, '15px');
@@ -180,6 +174,7 @@ void testMain() {
180174
expect(domDocument.activeElement, domDocument.body);
181175
expect(appHostNode.activeElement, null);
182176
expect(strategy.domElement, null);
177+
expect((textField.editableElement as dynamic).value, 'bye');
183178
expect(textField.editableElement.getAttribute('aria-label'), 'farewell');
184179
expect(textField.editableElement.style.width, '12px');
185180
expect(textField.editableElement.style.height, '17px');
@@ -193,92 +188,6 @@ void testMain() {
193188
expect(actionCount, 0);
194189
});
195190

196-
test(
197-
'Does not overwrite text value and selection editing state on semantic updates',
198-
() async {
199-
semantics()
200-
..debugOverrideTimestampFunction(() => _testTime)
201-
..semanticsEnabled = true;
202-
203-
strategy.enable(
204-
singlelineConfig,
205-
onChange: (_, __) {},
206-
onAction: (_) {},
207-
);
208-
209-
final SemanticsObject textFieldSemantics = createTextFieldSemantics(
210-
value: 'hello',
211-
textSelectionBase: 1,
212-
textSelectionExtent: 3,
213-
isFocused: true,
214-
rect: const ui.Rect.fromLTWH(0, 0, 10, 15));
215-
216-
final TextField textField =
217-
textFieldSemantics.debugRoleManagerFor(Role.textField)! as TextField;
218-
final DomHTMLInputElement editableElement =
219-
textField.editableElement as DomHTMLInputElement;
220-
221-
expect(editableElement, strategy.domElement);
222-
expect(editableElement.value, '');
223-
expect(editableElement.selectionStart, 0);
224-
expect(editableElement.selectionEnd, 0);
225-
226-
strategy.disable();
227-
semantics().semanticsEnabled = false;
228-
});
229-
230-
test(
231-
'Updates editing state when receiving framework messages from the text input channel',
232-
() async {
233-
semantics()
234-
..debugOverrideTimestampFunction(() => _testTime)
235-
..semanticsEnabled = true;
236-
237-
expect(domDocument.activeElement, domDocument.body);
238-
expect(appHostNode.activeElement, null);
239-
240-
strategy.enable(
241-
singlelineConfig,
242-
onChange: (_, __) {},
243-
onAction: (_) {},
244-
);
245-
246-
final SemanticsObject textFieldSemantics = createTextFieldSemantics(
247-
value: 'hello',
248-
textSelectionBase: 1,
249-
textSelectionExtent: 3,
250-
isFocused: true,
251-
rect: const ui.Rect.fromLTWH(0, 0, 10, 15));
252-
253-
final TextField textField =
254-
textFieldSemantics.debugRoleManagerFor(Role.textField)! as TextField;
255-
final DomHTMLInputElement editableElement =
256-
textField.editableElement as DomHTMLInputElement;
257-
258-
// No updates expected on semantic updates
259-
expect(editableElement, strategy.domElement);
260-
expect(editableElement.value, '');
261-
expect(editableElement.selectionStart, 0);
262-
expect(editableElement.selectionEnd, 0);
263-
264-
// Update from framework
265-
const MethodCall setEditingState =
266-
MethodCall('TextInput.setEditingState', <String, dynamic>{
267-
'text': 'updated',
268-
'selectionBase': 2,
269-
'selectionExtent': 3,
270-
});
271-
sendFrameworkMessage(codec.encodeMethodCall(setEditingState));
272-
273-
// Editing state should now be updated
274-
expect(editableElement.value, 'updated');
275-
expect(editableElement.selectionStart, 2);
276-
expect(editableElement.selectionEnd, 3);
277-
278-
strategy.disable();
279-
semantics().semanticsEnabled = false;
280-
});
281-
282191
test('Gives up focus after DOM blur', () async {
283192
semantics()
284193
..debugOverrideTimestampFunction(() => _testTime)
@@ -537,8 +446,6 @@ SemanticsObject createTextFieldSemantics({
537446
bool isFocused = false,
538447
bool isMultiline = false,
539448
ui.Rect rect = const ui.Rect.fromLTRB(0, 0, 100, 50),
540-
int textSelectionBase = 0,
541-
int textSelectionExtent = 0,
542449
}) {
543450
final SemanticsTester tester = SemanticsTester(semantics());
544451
tester.updateNode(
@@ -551,8 +458,6 @@ SemanticsObject createTextFieldSemantics({
551458
hasTap: true,
552459
rect: rect,
553460
textDirection: ui.TextDirection.ltr,
554-
textSelectionBase: textSelectionBase,
555-
textSelectionExtent: textSelectionExtent
556461
);
557462
tester.apply();
558463
return tester.getSemanticsObject(0);

0 commit comments

Comments
 (0)