ported from UXP: Issue #2790 - Part 4: Working non persistent autofill highlight (bf8cfcc9)

This commit is contained in:
2025-07-29 15:15:26 +08:00
parent eff68ee912
commit 2fae301fd1
12 changed files with 207 additions and 68 deletions
+81 -30
View File
@@ -367,16 +367,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);
}
}
@@ -570,6 +600,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)
{
@@ -594,6 +637,9 @@ HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
}
UpdateState(true);
// Defensive: re-apply autofill state if value is still autofilled value
EnsureAutofillState();
}
return NS_OK;
@@ -1200,6 +1246,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 {
@@ -1242,6 +1293,8 @@ HTMLTextAreaElement::IntrinsicState() const
state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
}
state |= NS_EVENT_STATE_AUTOFILL;
return state;
}
@@ -1642,30 +1695,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()
{
@@ -1681,11 +1710,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<JSObject*> aGivenProto)
{
return HTMLTextAreaElementBinding::Wrap(aCx, this, aGivenProto);
}
nsTextEditorState* HTMLTextAreaElement::GetEditorState() const {
return const_cast<nsTextEditorState*>(&mState);
}
} // namespace dom
} // namespace mozilla