diff --git a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index 5fcee58e8951f..89b236db170cc 100644 --- a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -603,31 +603,10 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { _subscriptions.add(html.document.onSelectionChange.listen(_handleChange)); - // The behavior for blur in DOM elements changes depending on the reason of - // blur: - // - // (1) If the blur is triggered due to tab change or browser minimize, same - // element receives the focus as soon as the page reopens. Hence, text - // editing connection does not need to be closed. In this case we dot blur - // the DOM element. - // - // (2) On the other hand if the blur is triggered due to interaction with - // another element on the page, the current text connection is obsolete so - // connection close request is send to Flutter. - // - // See [HybridTextEditing.sendTextConnectionClosedToFlutterIfAny]. - // - // In order to detect between these two cases, after a blur event is - // triggered [domRenderer.windowHasFocus] method which checks the window - // focus is called. + // Refocus on the domElement after blur, so that user can keep editing the + // text field. _subscriptions.add(domElement.onBlur.listen((_) { - if (domRenderer.windowHasFocus) { - // Focus is still on the body. Continue with blur. - owner.sendTextConnectionClosedToFrameworkIfAny(); - } else { - // Refocus. - domElement.focus(); - } + domElement.focus(); })); preventDefaultForMouseEvents(); @@ -1000,26 +979,10 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy { // enough for covering "Select All" functionality. _subscriptions.add(domElement.onSelect.listen(_handleChange)); - // For Firefox, we also use the same approach as the parent class. - // - // Do not blur the DOM element if the user goes to another tab or minimizes - // the browser. See [super.addEventHandlers] for more comments. - // - // The different part is, in Firefox, we are not able to get correct value - // when we check the window focus like [domRendered.windowHasFocus]. - // - // However [document.activeElement] always equals to [domElement] if the - // user goes to another tab, minimizes the browser or opens the dev tools. - // Hence [document.activeElement] is checked in this listener. + // Refocus on the domElement after blur, so that user can keep editing the + // text field. _subscriptions.add(domElement.onBlur.listen((_) { - html.Element activeElement = html.document.activeElement; - if (activeElement != domElement) { - // Focus is still on the body. Continue with blur. - owner.sendTextConnectionClosedToFrameworkIfAny(); - } else { - // Refocus. - domElement.focus(); - } + domElement.focus(); })); preventDefaultForMouseEvents(); diff --git a/lib/web_ui/test/text_editing_test.dart b/lib/web_ui/test/text_editing_test.dart index dbc760c05ab84..341fc68994e17 100644 --- a/lib/web_ui/test/text_editing_test.dart +++ b/lib/web_ui/test/text_editing_test.dart @@ -389,7 +389,7 @@ void main() { ); }); - test('Does not re-acquire focus', () { + test('Re-acquire focus', () { editingElement = SemanticsTextEditingStrategy(HybridTextEditing(), testInputElement); @@ -403,16 +403,17 @@ void main() { ); expect(document.activeElement, testInputElement); - // The input should lose focus now. + // The input should refocus after blur. editingElement.domElement.blur(); - expect(document.activeElement, document.body); + expect(document.activeElement, editingElement.domElement); editingElement.disable(); }, // TODO(nurhan): https://github.com/flutter/flutter/issues/50590 // TODO(nurhan): https://github.com/flutter/flutter/issues/50769 skip: (browserEngine == BrowserEngine.webkit || - browserEngine == BrowserEngine.edge)); + browserEngine == BrowserEngine.edge || + browserEngine == BrowserEngine.firefox)); test('Does not dispose and recreate dom elements in persistent mode', () { editingElement = @@ -447,8 +448,12 @@ void main() { // It doesn't remove the DOM element. expect(editingElement.domElement, testInputElement); expect(document.body.contains(editingElement.domElement), isTrue); - // But the DOM element loses focus. - expect(document.activeElement, document.body); + // The textArea does not lose focus. + // Even though this passes on manual tests it does not work on + // Firefox automated unit tests. + if (browserEngine != BrowserEngine.firefox) { + expect(document.activeElement, editingElement.domElement); + } }, // TODO(nurhan): https://github.com/flutter/flutter/issues/50590 // TODO(nurhan): https://github.com/flutter/flutter/issues/50769 @@ -465,12 +470,7 @@ void main() { onChange: trackEditingState, onAction: trackInputAction, ); - expect(document.activeElement, testInputElement); - - editingElement.domElement.blur(); - expect(document.activeElement, document.body); - - // The input should regain focus now. + // The input will have focus after editing state is set. editingElement.setEditingState(EditingState(text: 'foo')); expect(document.activeElement, testInputElement); @@ -508,20 +508,17 @@ void main() { // Focuses the textarea. expect(document.activeElement, textarea); - // Doesn't re-acquire focus. textarea.blur(); - expect(document.activeElement, document.body); - - // Re-focuses when setting editing state - editingElement.setEditingState(EditingState(text: 'foo')); - expect(document.activeElement, textarea); + // The textArea does not lose focus. + // Even though this passes on manual tests it does not work on + // Firefox automated unit tests. + if (browserEngine != BrowserEngine.firefox) { + expect(document.activeElement, textarea); + } editingElement.disable(); // It doesn't remove the textarea from the DOM. - expect(editingElement.domElement, textarea); expect(document.body.contains(editingElement.domElement), isTrue); - // But the textarea loses focus. - expect(document.activeElement, document.body); }, // TODO(nurhan): https://github.com/flutter/flutter/issues/50590 // TODO(nurhan): https://github.com/flutter/flutter/issues/50769 @@ -673,7 +670,7 @@ void main() { expect(spy.messages, isEmpty); }); - test('close connection on blur', () async { + test('do not close connection on blur', () async { final MethodCall setClient = MethodCall( 'TextInput.setClient', [123, flutterSinglelineConfig]); sendFrameworkMessage(codec.encodeMethodCall(setClient)); @@ -698,18 +695,14 @@ void main() { // DOM element is blurred. textEditing.editingElement.domElement.blur(); - expect(spy.messages, hasLength(1)); - expect(spy.messages[0].channel, 'flutter/textinput'); - expect(spy.messages[0].methodName, 'TextInputClient.onConnectionClosed'); - expect( - spy.messages[0].methodArguments, - [ - 123, // Client ID - ], - ); - spy.messages.clear(); - // Input element is removed from DOM. - expect(document.getElementsByTagName('input'), hasLength(0)); + expect(spy.messages, hasLength(0)); + + // DOM element still has focus. + // Even though this passes on manual tests it does not work on + // Firefox automated unit tests. + if (browserEngine != BrowserEngine.firefox) { + expect(document.activeElement, textEditing.editingElement.domElement); + } }, // TODO(nurhan): https://github.com/flutter/flutter/issues/50590 // TODO(nurhan): https://github.com/flutter/flutter/issues/50769 @@ -1482,7 +1475,7 @@ void main() { BrowserAutofillHints.instance.flutterToEngine(testHint)); expect(testInputElement.id, testId); expect(testInputElement.type, 'text'); - if (browserEngine == BrowserEngine.firefox) { + if (browserEngine == BrowserEngine.firefox) { expect(testInputElement.name, BrowserAutofillHints.instance.flutterToEngine(testHint)); } else {