From d662f8c69f654d77068c8877edd9305701bf3997 Mon Sep 17 00:00:00 2001 From: Mouad Debbar Date: Wed, 28 Jan 2026 13:09:17 -0500 Subject: [PATCH 1/4] [web] Re-establish text input connection when system refocuses a text field --- .../src/engine/text_editing/text_editing.dart | 78 +++++++++++++++++-- .../flutter/lib/src/services/text_input.dart | 15 ++++ .../lib/src/widgets/editable_text.dart | 9 +++ 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index 5d07a5db843..e5e57d8e1e9 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -31,7 +31,7 @@ import 'text_capitalization.dart'; bool _debugVisibleTextEditing = false; /// Set this to `true` to print when text input commands are scheduled and run. -bool _debugPrintTextInputCommands = false; +bool _debugPrintTextInputCommands = true; /// The `keyCode` of the "Enter" key. const int _kReturnKeyCode = 13; @@ -213,6 +213,10 @@ class EngineAutofillForm { /// The ID of the view that this form is rendered into. final int viewId; + static bool get _isSafariStrategy => + textEditing.strategy is SafariDesktopTextEditingStrategy || + textEditing.strategy is IOSTextEditingStrategy; + /// Creates an [EngineAutofillFrom] from the JSON representation of a Flutter /// framework `TextInputConfiguration` object. /// @@ -241,7 +245,6 @@ class EngineAutofillForm { final elements = {}; final items = {}; final DomHTMLFormElement formElement = createDomHTMLFormElement(); - final isSafariDesktopStrategy = textEditing.strategy is SafariDesktopTextEditingStrategy; DomHTMLElement? insertionReferenceNode; // Validation is in the framework side. @@ -253,7 +256,7 @@ class EngineAutofillForm { // We need to explicitly disable pointer events on the form in Safari Desktop, // so that we don't have pointer event collisions if users hover over or click // into the invisible autofill elements within the form. - _styleAutofillElements(formElement, shouldDisablePointerEvents: isSafariDesktopStrategy); + _styleAutofillElements(formElement, shouldDisablePointerEvents: _isSafariStrategy); // We keep the ids in a list then sort them later, in case the text fields' // locations are re-ordered on the framework side. @@ -262,6 +265,7 @@ class EngineAutofillForm { // The focused text editing element will not be created here. final focusedElement = AutofillInfo.fromFrameworkMessage(focusedElementAutofill); + print('
'); if (fields != null) { var fieldIsFocusedElement = false; for (final Map field in fields.cast>()) { @@ -284,6 +288,10 @@ class EngineAutofillForm { autofill.editingState.applyToDomElement(htmlElement); autofill.applyToDomElement(htmlElement); + print( + ' ┣━━ ', + ); + // Safari Desktop does not respect elements that are invisible (or // have no size) and that leads to issues with autofill only partially // working (ref: https://github.com/flutter/flutter/issues/71275). @@ -292,8 +300,8 @@ class EngineAutofillForm { // sized and placed on the DOM, we also have to disable pointer events. _styleAutofillElements( htmlElement, - shouldHideElement: !isSafariDesktopStrategy, - shouldDisablePointerEvents: isSafariDesktopStrategy, + shouldHideElement: !_isSafariStrategy, + shouldDisablePointerEvents: _isSafariStrategy, ); items[autofill.uniqueIdentifier] = autofill; @@ -308,6 +316,7 @@ class EngineAutofillForm { fieldIsFocusedElement = false; } } else { + print(' ┣━━ '); // current field is the focused element that we create elsewhere fieldIsFocusedElement = true; } @@ -342,6 +351,7 @@ class EngineAutofillForm { _styleAutofillElements(submitButton, isOffScreen: true); submitButton.className = 'submitBtn'; submitButton.type = 'submit'; + print(' ┗━━