@@ -68,6 +68,8 @@ void _hideAutofillElements(html.HtmlElement domElement) {
6868 ..outline = 'none'
6969 ..border = 'none'
7070 ..resize = 'none'
71+ ..width = '0'
72+ ..height = '0'
7173 ..textShadow = 'transparent'
7274 ..transformOrigin = '0 0 0' ;
7375
@@ -500,7 +502,22 @@ class GloballyPositionedTextEditingStrategy extends DefaultTextEditingStrategy {
500502 @override
501503 void placeElement () {
502504 super .placeElement ();
503- _geometry? .applyToDomElement (domElement);
505+ if (hasAutofillGroup) {
506+ _geometry? .applyToDomElement (focusedFormElement);
507+ placeForm ();
508+ // On Chrome, when a form is focused, it opens an autofill menu
509+ // immeddiately.
510+ // Flutter framework sends `setEditableSizeAndTransform` for informing
511+ // the engine about the location of the text field. This call will
512+ // arrive after `show` call.
513+ // Therefore on Chrome we place the element when
514+ // `setEditableSizeAndTransform` method is called and focus on the form
515+ // only after placing it to the correct position. Hence autofill menu
516+ // does not appear on top-left of the page.
517+ focusedFormElement.focus ();
518+ } else {
519+ _geometry? .applyToDomElement (domElement);
520+ }
504521 }
505522}
506523
@@ -549,6 +566,11 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy {
549566 final List <StreamSubscription <html.Event >> _subscriptions =
550567 < StreamSubscription <html.Event >> [];
551568
569+ bool get hasAutofillGroup => _inputConfiguration.autofillGroup != null ;
570+
571+ html.FormElement get focusedFormElement =>
572+ _inputConfiguration.autofillGroup.formElement;
573+
552574 @override
553575 void initializeTextEditing (
554576 InputConfiguration inputConfig, {
@@ -571,9 +593,11 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy {
571593
572594 _setStaticStyleAttributes (domElement);
573595 _style? .applyToDomElement (domElement);
574- if (_inputConfiguration.autofillGroup != null ) {
575- _inputConfiguration.autofillGroup.placeForm (domElement);
576- } else {
596+ if (! hasAutofillGroup) {
597+ // If there is an Autofill Group the `FormElement`, it will be appended to the
598+ // DOM later, when the first location information arrived.
599+ // Otherwise, on Blink based Desktop browsers, the autofill menu appears
600+ // on top left of the screen.
577601 domRenderer.glassPaneElement.append (domElement);
578602 }
579603
@@ -657,13 +681,14 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy {
657681 _lastEditingState.applyToDomElement (domElement);
658682 }
659683
660- /// Puts the DOM element used for text editing on the UI at the appropriate
661- /// location and sizes it accordingly.
662- @mustCallSuper
663684 void placeElement () {
664685 domElement.focus ();
665686 }
666687
688+ void placeForm () {
689+ _inputConfiguration.autofillGroup.placeForm (domElement);
690+ }
691+
667692 void _handleChange (html.Event event) {
668693 assert (isEnabled);
669694 assert (domElement != null );
@@ -789,6 +814,11 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
789814 super .initializeTextEditing (inputConfig,
790815 onChange: onChange, onAction: onAction);
791816 inputConfig.inputType.configureInputMode (domElement);
817+ if (hasAutofillGroup) {
818+ placeForm ();
819+ } else {
820+ domRenderer.glassPaneElement.append (domElement);
821+ }
792822 }
793823
794824 @override
@@ -887,6 +917,12 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
887917 placeElement ();
888918 });
889919 }
920+
921+ @override
922+ void placeElement () {
923+ domElement.focus ();
924+ _geometry? .applyToDomElement (domElement);
925+ }
890926}
891927
892928/// Android behaviour for text editing.
@@ -908,6 +944,11 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
908944 super .initializeTextEditing (inputConfig,
909945 onChange: onChange, onAction: onAction);
910946 inputConfig.inputType.configureInputMode (domElement);
947+ if (hasAutofillGroup) {
948+ placeForm ();
949+ } else {
950+ domRenderer.glassPaneElement.append (domElement);
951+ }
911952 }
912953
913954 @override
@@ -936,6 +977,12 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
936977 }
937978 }));
938979 }
980+
981+ @override
982+ void placeElement () {
983+ domElement.focus ();
984+ _geometry? .applyToDomElement (domElement);
985+ }
939986}
940987
941988/// Firefox behaviour for text editing.
@@ -945,6 +992,21 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
945992class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
946993 FirefoxTextEditingStrategy (HybridTextEditing owner) : super (owner);
947994
995+ @override
996+ void initializeTextEditing (
997+ InputConfiguration inputConfig, {
998+ @required _OnChangeCallback onChange,
999+ @required _OnActionCallback onAction,
1000+ }) {
1001+ super .initializeTextEditing (inputConfig,
1002+ onChange: onChange, onAction: onAction);
1003+ if (hasAutofillGroup) {
1004+ placeForm ();
1005+ } else {
1006+ domRenderer.glassPaneElement.append (domElement);
1007+ }
1008+ }
1009+
9481010 @override
9491011 void addEventHandlers () {
9501012 if (_inputConfiguration.autofillGroup != null ) {
@@ -987,6 +1049,12 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
9871049
9881050 preventDefaultForMouseEvents ();
9891051 }
1052+
1053+ @override
1054+ void placeElement () {
1055+ domElement.focus ();
1056+ _geometry? .applyToDomElement (domElement);
1057+ }
9901058}
9911059
9921060/// Translates the message-based communication between the framework and the
0 commit comments