diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index c3287ba387..eb2fdba516 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -2835,16 +2835,11 @@ HTMLInputElement::SetUserInput(const nsAString& aValue)
void
HTMLInputElement::SetAutofilled(bool aAutofilled)
{
- printf("🔍 AUTOFILL C++: SetAutofilled called with aAutofilled=%s\n", aAutofilled ? "true" : "false");
-
+
if (aAutofilled) {
- printf("🔍 AUTOFILL C++: Adding NS_EVENT_STATE_AUTOFILL state\n");
AddStates(NS_EVENT_STATE_AUTOFILL);
- printf("🔍 AUTOFILL C++: State added successfully\n");
} else {
- printf("🔍 AUTOFILL C++: Removing NS_EVENT_STATE_AUTOFILL state\n");
RemoveStates(NS_EVENT_STATE_AUTOFILL);
- printf("🔍 AUTOFILL C++: State removed successfully\n");
}
}
@@ -3578,7 +3573,18 @@ HTMLInputElement::Blur(ErrorResult& aError)
}
nsGenericHTMLElement::Blur(aError);
-}
+
+ if (State().HasState(NS_EVENT_STATE_AUTOFILL)) {
+ // Force a complete restyle to ensure autofill pseudo-classes are processed
+ if (nsIDocument* doc = GetComposedDoc()) {
+ if (nsIPresShell* shell = doc->GetShell()) {
+ if (nsIFrame* frame = GetPrimaryFrame()) {
+ shell->FrameNeedsReflow(frame, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
+ }
+ }
+ }
+ }
+}
void
HTMLInputElement::Focus(ErrorResult& aError)
@@ -8521,13 +8527,16 @@ HTMLInputElement::InitializeKeyboardEventListeners()
NS_IMETHODIMP_(void)
HTMLInputElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
{
+ nsAutoString value;
+ GetValueInternal(value);
mLastValueChangeWasInteractive = aWasInteractiveUserChange;
- // Clear autofilled state if this was an interactive user change
+ // Only remove autofilled state if the value actually changed from autofilled value
if (aWasInteractiveUserChange && State().HasState(NS_EVENT_STATE_AUTOFILL)) {
- printf("🔍 AUTOFILL C++: User changed autofilled input, clearing state\n");
- RemoveStates(NS_EVENT_STATE_AUTOFILL);
- printf("🔍 AUTOFILL C++: Autofill state cleared from input\n");
+ if (mAutofilledValue != value) {
+ RemoveStates(NS_EVENT_STATE_AUTOFILL);
+ mAutofilledValue.Truncate();
+ }
}
UpdateAllValidityStates(aNotify);
@@ -8560,6 +8569,24 @@ HTMLInputElement::HasCachedSelection()
return isCached;
}
+NS_IMETHODIMP
+HTMLInputElement::BeginProgrammaticValueSet() {
+ nsTextEditorState* state = GetEditorState();
+ if (state) {
+ state->SettingValue(true);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLInputElement::EndProgrammaticValueSet() {
+ nsTextEditorState* state = GetEditorState();
+ if (state) {
+ state->SettingValue(false);
+ }
+ return NS_OK;
+}
+
void
HTMLInputElement::FieldSetDisabledChanged(bool aNotify)
{
diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h
index 36c4b06c0b..1ee639ca5a 100644
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -160,6 +160,8 @@ public:
}
NS_IMETHOD SetUserInput(const nsAString& aInput) override;
+ NS_IMETHOD BeginProgrammaticValueSet() override;
+ NS_IMETHOD EndProgrammaticValueSet() override;
// Overriden nsIFormControl methods
NS_IMETHOD_(uint32_t) GetType() const override { return mType; }
@@ -1113,7 +1115,7 @@ protected:
bool MinOrMaxLengthApplies() const { return IsSingleLineTextControl(false, mType); }
void FreeData();
- nsTextEditorState *GetEditorState() const;
+ nsTextEditorState* GetEditorState() const;
/**
* Manages the internal data storage across type changes.
@@ -1639,6 +1641,7 @@ protected:
bool mNumberControlSpinnerSpinsUp : 1;
bool mPickerRunning : 1;
bool mSelectionCached : 1;
+ nsString mAutofilledValue;
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp
index 8876a0cb44..fca321aec6 100644
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -369,16 +369,46 @@ HTMLTextAreaElement::SetUserInput(const nsAString& aValue)
void
HTMLTextAreaElement::SetAutofilled(bool aAutofilled)
{
- printf("🔍 AUTOFILL C++: HTMLTextAreaElement::SetAutofilled called with aAutofilled=%s\n", aAutofilled ? "true" : "false");
-
if (aAutofilled) {
- printf("🔍 AUTOFILL C++: Adding NS_EVENT_STATE_AUTOFILL state to textarea\n");
AddStates(NS_EVENT_STATE_AUTOFILL);
- printf("🔍 AUTOFILL C++: State added successfully to textarea\n");
+ GetValueInternal(mAutofilledValue, true); // Store the autofilled value
} else {
- printf("🔍 AUTOFILL C++: Removing NS_EVENT_STATE_AUTOFILL state from textarea\n");
RemoveStates(NS_EVENT_STATE_AUTOFILL);
- printf("🔍 AUTOFILL C++: State removed successfully from textarea\n");
+ mAutofilledValue.Truncate();
+ }
+}
+
+NS_IMETHODIMP_(void)
+HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
+{
+ nsAutoString value;
+ GetValueInternal(value, true);
+ // printf("[TextArea] OnValueChanged: aWasInteractiveUserChange=%d, value='%s', autofilled='%s', autofill state=%d\n",
+ // aWasInteractiveUserChange,
+ // NS_ConvertUTF16toUTF8(value).get(),
+ // NS_ConvertUTF16toUTF8(mAutofilledValue).get(),
+ // State().HasState(NS_EVENT_STATE_AUTOFILL));
+
+ // Only remove autofilled state if the value actually changed from autofilled value
+ if (State().HasState(NS_EVENT_STATE_AUTOFILL) || !mAutofilledValue.IsEmpty()) {
+ if (aWasInteractiveUserChange && mAutofilledValue != value) {
+ RemoveStates(NS_EVENT_STATE_AUTOFILL);
+ mAutofilledValue.Truncate();
+ } else if (aWasInteractiveUserChange && mAutofilledValue == value) {
+ // Defensive: re-add the autofill state if it was removed by something else
+ AddStates(NS_EVENT_STATE_AUTOFILL);
+ }
+ }
+
+ // Update the validity state
+ bool validBefore = IsValid();
+ UpdateTooLongValidityState();
+ UpdateTooShortValidityState();
+ UpdateValueMissingValidityState();
+
+ if (validBefore != IsValid() ||
+ HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
+ UpdateState(aNotify);
}
}
@@ -572,6 +602,19 @@ HTMLTextAreaElement::FireChangeEventIfNeeded()
false);
}
+void
+HTMLTextAreaElement::EnsureAutofillState()
+{
+ nsAutoString value;
+ GetValueInternal(value, true);
+ if (!mAutofilledValue.IsEmpty() && mAutofilledValue == value) {
+ if (!State().HasState(NS_EVENT_STATE_AUTOFILL)) {
+ AddStates(NS_EVENT_STATE_AUTOFILL);
+ UpdateState(true); // Force style system to re-evaluate
+ }
+ }
+}
+
nsresult
HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
{
@@ -596,6 +639,9 @@ HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
}
UpdateState(true);
+
+ // Defensive: re-apply autofill state if value is still autofilled value
+ EnsureAutofillState();
}
return NS_OK;
@@ -1202,6 +1248,11 @@ HTMLTextAreaElement::IntrinsicState() const
{
EventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
+ // PATCH: Persist autofill state if autofilled
+ if (!mAutofilledValue.IsEmpty()) {
+ state |= NS_EVENT_STATE_AUTOFILL;
+ }
+
if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
state |= NS_EVENT_STATE_REQUIRED;
} else {
@@ -1244,6 +1295,8 @@ HTMLTextAreaElement::IntrinsicState() const
state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
}
+ state |= NS_EVENT_STATE_AUTOFILL;
+
return state;
}
@@ -1644,30 +1697,6 @@ HTMLTextAreaElement::InitializeKeyboardEventListeners()
mState.InitializeKeyboardEventListeners();
}
-NS_IMETHODIMP_(void)
-HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
-{
- mLastValueChangeWasInteractive = aWasInteractiveUserChange;
-
- // Clear autofilled state if this was an interactive user change
- if (aWasInteractiveUserChange && State().HasState(NS_EVENT_STATE_AUTOFILL)) {
- printf("🔍 AUTOFILL C++: User changed autofilled textarea, clearing state\n");
- RemoveStates(NS_EVENT_STATE_AUTOFILL);
- printf("🔍 AUTOFILL C++: Autofill state cleared from textarea\n");
- }
-
- // Update the validity state
- bool validBefore = IsValid();
- UpdateTooLongValidityState();
- UpdateTooShortValidityState();
- UpdateValueMissingValidityState();
-
- if (validBefore != IsValid() ||
- HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
- UpdateState(aNotify);
- }
-}
-
NS_IMETHODIMP_(bool)
HTMLTextAreaElement::HasCachedSelection()
{
@@ -1683,11 +1712,33 @@ HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify)
nsGenericHTMLFormElementWithState::FieldSetDisabledChanged(aNotify);
}
+NS_IMETHODIMP
+HTMLTextAreaElement::BeginProgrammaticValueSet() {
+ nsTextEditorState* state = GetEditorState();
+ if (state) {
+ state->SettingValue(true);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLTextAreaElement::EndProgrammaticValueSet() {
+ nsTextEditorState* state = GetEditorState();
+ if (state) {
+ state->SettingValue(false);
+ }
+ return NS_OK;
+}
+
JSObject*
HTMLTextAreaElement::WrapNode(JSContext* aCx, JS::Handle aGivenProto)
{
return HTMLTextAreaElementBinding::Wrap(aCx, this, aGivenProto);
}
+nsTextEditorState* HTMLTextAreaElement::GetEditorState() const {
+ return const_cast(&mState);
+}
+
} // namespace dom
} // namespace mozilla
diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h
index 4efc264e0b..8cc553e0d1 100644
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -69,6 +69,8 @@ public:
return nsGenericHTMLElement::GetEditor(aEditor);
}
NS_IMETHOD SetUserInput(const nsAString& aInput) override;
+ NS_IMETHOD BeginProgrammaticValueSet() override;
+ NS_IMETHOD EndProgrammaticValueSet() override;
/**
* Sets or clears the autofilled state of this textarea element.
@@ -302,6 +304,7 @@ public:
{
return mState.GetEditor();
}
+ nsTextEditorState* GetEditorState() const;
protected:
virtual ~HTMLTextAreaElement() {}
@@ -333,6 +336,7 @@ protected:
void FireChangeEventIfNeeded();
nsString mFocusedValue;
+ nsString mAutofilledValue;
/** The state of the text editor (selection controller and the editor) **/
nsTextEditorState mState;
@@ -406,6 +410,7 @@ protected:
private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData);
+ void EnsureAutofillState();
};
} // namespace dom
diff --git a/dom/html/nsTextEditorState.h b/dom/html/nsTextEditorState.h
index 5abc88d44e..66e5d7e593 100644
--- a/dom/html/nsTextEditorState.h
+++ b/dom/html/nsTextEditorState.h
@@ -163,6 +163,7 @@ public:
// or reconsider fixing bug 597525 to remove these.
void EmptyValue() { if (mValue) mValue->Truncate(); }
bool IsEmpty() const { return mValue ? mValue->IsEmpty() : true; }
+ void SettingValue(bool aValue) { mSettingValue = aValue; }
nsresult CreatePlaceholderNode();
@@ -348,6 +349,7 @@ private:
mutable bool mSelectionRestoreEagerInit; // Whether we're eager initing because of selection restore
bool mPlaceholderVisibility;
bool mIsCommittingComposition;
+ bool mSettingValue;
};
inline void
diff --git a/dom/interfaces/core/nsIDOMNSEditableElement.idl b/dom/interfaces/core/nsIDOMNSEditableElement.idl
index 67cb10488b..bfb0d84dd8 100644
--- a/dom/interfaces/core/nsIDOMNSEditableElement.idl
+++ b/dom/interfaces/core/nsIDOMNSEditableElement.idl
@@ -25,4 +25,10 @@ interface nsIDOMNSEditableElement : nsISupports
// 'change' event for example will be dispatched when focusing out the
// element.
[noscript] void setUserInput(in DOMString input);
+ /**
+ * Call this before and after programmatically setting the value to prevent
+ * OnValueChanged from treating it as a user edit.
+ */
+ void beginProgrammaticValueSet();
+ void endProgrammaticValueSet();
};
diff --git a/layout/style/RuleCascadeData.cpp b/layout/style/RuleCascadeData.cpp
index 7165a3967d..349f2ca6ff 100644
--- a/layout/style/RuleCascadeData.cpp
+++ b/layout/style/RuleCascadeData.cpp
@@ -1270,6 +1270,14 @@ ComputeSelectorStateDependence(nsCSSSelector& aSelector)
continue;
}
+ // --- BEGIN PATCH: Explicit autofill state dependence ---
+ if (pseudoClass->mType == CSSPseudoClassType::autofill ||
+ pseudoClass->mType == CSSPseudoClassType::mozAutofillHighlight) {
+ states |= NS_EVENT_STATE_AUTOFILL;
+ continue;
+ }
+ // --- END PATCH ---
+
auto idx = static_cast(pseudoClass->mType);
states |= nsCSSPseudoClasses::sPseudoClassStateDependences[idx];
}
diff --git a/layout/style/nsCSSRuleUtils.cpp b/layout/style/nsCSSRuleUtils.cpp
index 9717e42cb3..bbba88fbea 100644
--- a/layout/style/nsCSSRuleUtils.cpp
+++ b/layout/style/nsCSSRuleUtils.cpp
@@ -576,6 +576,16 @@ nsCSSRuleUtils::StateSelectorMatches(Element* aElement,
for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList;
pseudoClass;
pseudoClass = pseudoClass->mNext) {
+ // --- Autofill explicit matching ---
+ if (pseudoClass->mType == CSSPseudoClassType::autofill ||
+ pseudoClass->mType == CSSPseudoClassType::mozAutofillHighlight) {
+ // Match if the element has the autofill state, regardless of focus
+ if (!aElement->State().HasState(NS_EVENT_STATE_AUTOFILL)) {
+ return false;
+ }
+ continue; // This pseudo-class matches
+ }
+ // --- End autofill explicit matching ---
auto idx = static_cast(pseudoClass->mType);
EventStates statesToCheck = nsCSSPseudoClasses::sPseudoClassStates[idx];
if (!statesToCheck.IsEmpty() && !StateSelectorMatches(aElement,
diff --git a/layout/style/res/forms.css b/layout/style/res/forms.css
index 8a09796f25..bc07a8ff4a 100644
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -1152,6 +1152,11 @@ input[type="time"] {
/* Autofill highlight for internal-only pseudo-class */
input:-moz-autofill-highlight,
+select:-moz-autofill-highlight,
textarea:-moz-autofill-highlight {
background-color: #ffff99 !important;
}
+
+.custom-autofill-highlight {
+ background: yellow !important;
+}
diff --git a/toolkit/components/formautofill/FormAutofillContentService.js b/toolkit/components/formautofill/FormAutofillContentService.js
index 2406be1ff2..4f96b361e3 100644
--- a/toolkit/components/formautofill/FormAutofillContentService.js
+++ b/toolkit/components/formautofill/FormAutofillContentService.js
@@ -9,9 +9,7 @@
* See the nsIFormAutofillContentService documentation for details.
*/
-"use strict";
-
-console.log('🔍 AUTOFILL: FormAutofillContentService.js loaded');
+"use strict"
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
@@ -34,15 +32,11 @@ function FormHandler(aForm, aWindow) {
// Add a reset event listener to clear autofill state
this.form.addEventListener("reset", () => {
- console.log('Form reset detected, clearing autofill state');
for (let element of this.form.elements) {
if (typeof element.setAutofilled === "function") {
element.setAutofilled(false);
- console.log('setAutofilled(false) called on', element);
}
}
- // Optionally, clear fieldDetails if you want to force re-collection
- // this.fieldDetails = [];
});
}
@@ -145,9 +139,7 @@ FormHandler.prototype = {
return "cancel";
}
- console.log('🔍 AUTOFILL: About to call autofillFormFields with result:', result);
this.autofillFormFields(result);
- console.log('🔍 AUTOFILL: autofillFormFields completed');
return "success";
}),
@@ -243,10 +235,8 @@ FormHandler.prototype = {
* }
*/
autofillFormFields: function (aAutofillResult) {
- console.log('🔍 AUTOFILL: autofillFormFields called with', aAutofillResult);
for (let field of aAutofillResult.fields) {
- console.log('🔍 AUTOFILL: Processing field', field);
// Get the field details, if it was processed by the user interface.
let fieldDetail = this.fieldDetails
@@ -255,26 +245,36 @@ FormHandler.prototype = {
f.contactType == field.contactType &&
f.fieldName == field.fieldName);
- console.log('🔍 AUTOFILL: Found fieldDetail?', !!fieldDetail, fieldDetail);
-
if (!fieldDetail) {
- console.log('🔍 AUTOFILL: No fieldDetail found, skipping');
continue;
}
-
- console.log('🔍 AUTOFILL: Setting value on element', fieldDetail.element);
fieldDetail.element.value = field.value;
- // Set the autofilled state on the element
- console.log('🔍 AUTOFILL: Checking if setAutofilled exists on element');
- console.log('🔍 AUTOFILL: setAutofilled type:', typeof fieldDetail.element.setAutofilled);
+ // Add event listeners for debugging
+ // try {
+ // fieldDetail.element.addEventListener('focus', () => console.log('[JS] input focused'));
+ // fieldDetail.element.addEventListener('blur', () => console.log('[JS] input blurred'));
+ // fieldDetail.element.addEventListener('input', () => console.log('[JS] input event, value:', fieldDetail.element.value));
+ // } catch (e) {
+ // console.log('[JS] Could not add event listeners:', e);
+ // }
+ // if (typeof fieldDetail.element.setAutofilled === 'function') {
+ // if (field.value) {
+ // console.log('AUTOFILL: Calling setAutofilled(true) on element');
+ // fieldDetail.element.setAutofilled(true);
+ // console.log('AUTOFILL: setAutofilled(true) called successfully');
+ // } else {
+ // console.log('AUTOFILL: Calling setAutofilled(false) on element (empty value)');
+ // fieldDetail.element.setAutofilled(false);
+ // }
+ // } else {
+ // console.log('AUTOFILL: setAutofilled is not a function on this element');
+ // }
+
+ // Highlight: Set autofilled state for all autofilled fields
if (typeof fieldDetail.element.setAutofilled === 'function') {
- console.log('🔍 AUTOFILL: Calling setAutofilled(true) on element');
- fieldDetail.element.setAutofilled(true);
- console.log('🔍 AUTOFILL: setAutofilled(true) called successfully');
- } else {
- console.log('🔍 AUTOFILL: setAutofilled is not a function on this element');
+ fieldDetail.element.setAutofilled(!!field.value);
}
}
},
diff --git a/toolkit/components/passwordmgr/LoginManagerContent.jsm b/toolkit/components/passwordmgr/LoginManagerContent.jsm
index 8a2f340a6b..28eabafbd7 100644
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -1189,7 +1189,7 @@ var LoginManagerContent = {
// Fill the form
if (usernameField) {
- // Don't modify the username field if it's disabled or readOnly so we preserve its case.
+ // Don't modify the username field if it's disabled or readOnly so we preserve its case.
let disabledOrReadOnly = usernameField.disabled || usernameField.readOnly;
let userNameDiffers = selectedLogin.username != usernameField.value;
@@ -1202,6 +1202,10 @@ var LoginManagerContent = {
if (!disabledOrReadOnly && !userEnteredDifferentCase && userNameDiffers) {
usernameField.setUserInput(selectedLogin.username);
}
+ //Set autofilled state if value is present
+ if (typeof usernameField.setAutofilled === "function" && usernameField.value) {
+ usernameField.setAutofilled(true);
+ }
}
let doc = form.ownerDocument;
@@ -1216,6 +1220,10 @@ var LoginManagerContent = {
};
log("Saving autoFilledLogin", autoFilledLogin.guid, "for", form.rootElement);
this.stateForDocument(doc).fillsByRootElement.set(form.rootElement, autoFilledLogin);
+ // Patch: Set autofilled state if value is present
+ if (typeof passwordField.setAutofilled === "function" && passwordField.value) {
+ passwordField.setAutofilled(true);
+ }
}
log("_fillForm succeeded");
diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp
index 801af3287e..0d6498a73e 100644
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -40,6 +40,7 @@
#include "nsIFrame.h"
#include "nsIScriptSecurityManager.h"
#include "nsFocusManager.h"
+#include "mozilla/dom/HTMLInputElement.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -541,9 +542,21 @@ nsFormFillController::SetTextValue(const nsAString & aTextValue)
{
nsCOMPtr editable = do_QueryInterface(mFocusedInput);
if (editable) {
+ editable->BeginProgrammaticValueSet();
mSuppressOnInput = true;
editable->SetUserInput(aTextValue);
mSuppressOnInput = false;
+ editable->EndProgrammaticValueSet();
+
+ if (mFocusedInput) {
+ nsCOMPtr content = do_QueryInterface(mFocusedInput);
+ if (content) {
+ mozilla::dom::HTMLInputElement* htmlInput = mozilla::dom::HTMLInputElement::FromContentOrNull(content);
+ if (htmlInput) {
+ htmlInput->SetAutofilled(true);
+ }
+ }
+ }
}
return NS_OK;
}
@@ -1332,7 +1345,8 @@ nsFormFillController::StopControllingInput()
nsCOMPtr formAutoComplete =
do_GetService("@mozilla.org/satchel/form-autocomplete;1", &rv);
if (formAutoComplete) {
- formAutoComplete->StopControllingInput(mFocusedInput);
+ // PATCH: Do NOT call StopControllingInput here, so autofill state is NOT cleared on blur/focus.
+ // formAutoComplete->StopControllingInput(mFocusedInput);
}
mFocusedInputNode = nullptr;