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 8b4dd212c10a3..5e283f44a14d7 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 @@ -321,6 +321,14 @@ class EngineAutofillForm { } void placeForm(DomHTMLElement mainTextEditingElement) { + // Since we're disabling pointer events on the form to fix Safari autofill, + // we need to explicitly set pointer events on the active input element in + // order to calculate the correct pointer event offsets. + // See: https://github.com/flutter/flutter/issues/136006 + if(textEditing.strategy is SafariDesktopTextEditingStrategy) { + mainTextEditingElement.style.pointerEvents = 'all'; + } + formElement.insertBefore(mainTextEditingElement, insertionReferenceNode); defaultTextEditingRoot.append(formElement); } diff --git a/lib/web_ui/test/engine/text_editing_test.dart b/lib/web_ui/test/engine/text_editing_test.dart index 37d44b3f321ed..a82a104ef78be 100644 --- a/lib/web_ui/test/engine/text_editing_test.dart +++ b/lib/web_ui/test/engine/text_editing_test.dart @@ -2551,6 +2551,46 @@ Future testMain() async { expect(autofillForm.formElement.style.pointerEvents, 'none'); }, skip: !isSafari); + test( + 'the focused element within a form should explicitly set pointer events on Safari', + () { + final List fields = createFieldValues([ + 'email', + 'username', + 'password', + ], [ + 'field1', + 'field2', + 'field3' + ]); + final EngineAutofillForm autofillForm = + EngineAutofillForm.fromFrameworkMessage( + createAutofillInfo('email', 'field1'), fields)!; + + final DomHTMLInputElement testInputElement = createDomHTMLInputElement(); + testInputElement.name = 'email'; + autofillForm.placeForm(testInputElement); + + final List formChildNodes = + autofillForm.formElement.childNodes.toList() + as List; + final DomHTMLInputElement email = formChildNodes[0]; + final DomHTMLInputElement username = formChildNodes[1]; + final DomHTMLInputElement password = formChildNodes[2]; + + expect(email.name, 'email'); + expect(username.name, 'username'); + expect(password.name, 'current-password'); + + // pointer events are none on the form and all non-focused elements + expect(autofillForm.formElement.style.pointerEvents, 'none'); + expect(username.style.pointerEvents, 'none'); + expect(password.style.pointerEvents, 'none'); + + // pointer events are set to all on the activeDomElement + expect(email.style.pointerEvents, 'all'); + }, skip: !isSafari); + tearDown(() { clearForms(); });