Issue #2790 - Part 5: Persistent highlight despite blur click

This commit is contained in:
MeladJM 2025-07-26 03:06:37 +08:00 • committed by roytam1
commit 156c755085
5 changed files with 64 additions and 16 deletions

View file

@ -2607,7 +2607,7 @@ HTMLInputElement::MozSetFileNameArray(const Sequence<nsString>& aFileNames,
NS_IMETHODIMP NS_IMETHODIMP
HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames, HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames,
uint32_t aLength) uint32_t aLength)
{ {
if (!nsContentUtils::IsCallerChrome()) { if (!nsContentUtils::IsCallerChrome()) {
// setting the value of a "FILE" input widget requires chrome privilege // setting the value of a "FILE" input widget requires chrome privilege
@ -2631,7 +2631,7 @@ HTMLInputElement::MozSetFileNameArray(const char16_t** aFileNames,
void void
HTMLInputElement::MozSetDirectory(const nsAString& aDirectoryPath, HTMLInputElement::MozSetDirectory(const nsAString& aDirectoryPath,
ErrorResult& aRv) ErrorResult& aRv)
{ {
nsCOMPtr<nsIFile> file; nsCOMPtr<nsIFile> file;
aRv = NS_NewLocalFile(aDirectoryPath, true, getter_AddRefs(file)); aRv = NS_NewLocalFile(aDirectoryPath, true, getter_AddRefs(file));
@ -2835,11 +2835,14 @@ HTMLInputElement::SetUserInput(const nsAString& aValue)
void void
HTMLInputElement::SetAutofilled(bool aAutofilled) HTMLInputElement::SetAutofilled(bool aAutofilled)
{ {
nsAutoString value;
GetValueInternal(value);
if (aAutofilled) { if (aAutofilled) {
AddStates(NS_EVENT_STATE_AUTOFILL); AddStates(NS_EVENT_STATE_AUTOFILL);
mAutofilledValue = value;
} else { } else {
RemoveStates(NS_EVENT_STATE_AUTOFILL); RemoveStates(NS_EVENT_STATE_AUTOFILL);
mAutofilledValue.Truncate();
} }
} }
@ -7092,6 +7095,13 @@ HTMLInputElement::IntrinsicState() const
state |= NS_EVENT_STATE_MOZ_SUBMITINVALID; state |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
} }
// Autofill highlight should persist as long as the value matches the autofilled value
nsAutoString value;
GetValueInternal(value);
if (!mAutofilledValue.IsEmpty() && value == mAutofilledValue) {
state |= NS_EVENT_STATE_AUTOFILL;
}
return state; return state;
} }
@ -8533,10 +8543,15 @@ HTMLInputElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
// Only remove autofilled state if the value actually changed from autofilled value // Only remove autofilled state if the value actually changed from autofilled value
if (aWasInteractiveUserChange && State().HasState(NS_EVENT_STATE_AUTOFILL)) { if (aWasInteractiveUserChange && State().HasState(NS_EVENT_STATE_AUTOFILL)) {
if (mAutofilledValue != value) { if (!mAutofilledValue.IsEmpty() && mAutofilledValue != value) {
RemoveStates(NS_EVENT_STATE_AUTOFILL); RemoveStates(NS_EVENT_STATE_AUTOFILL);
mAutofilledValue.Truncate(); mAutofilledValue.Truncate();
} }
} else if (aWasInteractiveUserChange && !State().HasState(NS_EVENT_STATE_AUTOFILL)) {
// If the value is changed back to the autofilled value, restore the state
if (!mAutofilledValue.IsEmpty() && mAutofilledValue == value) {
AddStates(NS_EVENT_STATE_AUTOFILL);
}
} }
UpdateAllValidityStates(aNotify); UpdateAllValidityStates(aNotify);

View file

@ -849,9 +849,8 @@ public:
/** /**
* Sets or clears the autofilled state of this input element. * Sets or clears the autofilled state of this input element.
* This is used by the browser's autofill system to indicate when * When setting, also stores the autofilled value for persistence.
* a value has been automatically filled (e.g., from saved passwords * When clearing, clears the stored autofilled value.
* or form data).
* *
* @param aAutofilled Whether the element should be marked as autofilled * @param aAutofilled Whether the element should be marked as autofilled
*/ */
@ -872,6 +871,8 @@ public:
void UpdateEntries(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories); void UpdateEntries(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories);
void SetAutofilledValue(const nsAString& aValue) { mAutofilledValue = aValue; }
protected: protected:
virtual ~HTMLInputElement(); virtual ~HTMLInputElement();
@ -1641,6 +1642,10 @@ protected:
bool mNumberControlSpinnerSpinsUp : 1; bool mNumberControlSpinnerSpinsUp : 1;
bool mPickerRunning : 1; bool mPickerRunning : 1;
bool mSelectionCached : 1; bool mSelectionCached : 1;
/**
* The value that was autofilled by the browser. Used to persist the autofill
* highlight as long as the value matches, regardless of focus/blur.
*/
nsString mAutofilledValue; nsString mAutofilledValue;
private: private:
@ -1785,6 +1790,8 @@ private:
nsCOMPtr<nsIFilePicker> mFilePicker; nsCOMPtr<nsIFilePicker> mFilePicker;
RefPtr<HTMLInputElement> mInput; RefPtr<HTMLInputElement> mInput;
}; };
void EnsureAutofillState();
}; };
} // namespace dom } // namespace dom

View file

@ -383,11 +383,6 @@ HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange
{ {
nsAutoString value; nsAutoString value;
GetValueInternal(value, true); 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 // Only remove autofilled state if the value actually changed from autofilled value
if (State().HasState(NS_EVENT_STATE_AUTOFILL) || !mAutofilledValue.IsEmpty()) { if (State().HasState(NS_EVENT_STATE_AUTOFILL) || !mAutofilledValue.IsEmpty()) {
@ -395,7 +390,6 @@ HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange
RemoveStates(NS_EVENT_STATE_AUTOFILL); RemoveStates(NS_EVENT_STATE_AUTOFILL);
mAutofilledValue.Truncate(); mAutofilledValue.Truncate();
} else if (aWasInteractiveUserChange && mAutofilledValue == value) { } else if (aWasInteractiveUserChange && mAutofilledValue == value) {
// Defensive: re-add the autofill state if it was removed by something else
AddStates(NS_EVENT_STATE_AUTOFILL); AddStates(NS_EVENT_STATE_AUTOFILL);
} }
} }
@ -1248,7 +1242,6 @@ HTMLTextAreaElement::IntrinsicState() const
{ {
EventStates state = nsGenericHTMLFormElementWithState::IntrinsicState(); EventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
// PATCH: Persist autofill state if autofilled
if (!mAutofilledValue.IsEmpty()) { if (!mAutofilledValue.IsEmpty()) {
state |= NS_EVENT_STATE_AUTOFILL; state |= NS_EVENT_STATE_AUTOFILL;
} }
@ -1295,8 +1288,6 @@ HTMLTextAreaElement::IntrinsicState() const
state |= NS_EVENT_STATE_PLACEHOLDERSHOWN; state |= NS_EVENT_STATE_PLACEHOLDERSHOWN;
} }
state |= NS_EVENT_STATE_AUTOFILL;
return state; return state;
} }

View file

@ -82,8 +82,24 @@ label {
/* Note: Values in nsNativeTheme IsWidgetStyled function /* Note: Values in nsNativeTheme IsWidgetStyled function
need to match textfield background/border values here */ need to match textfield background/border values here */
/* Autofill persistent highlight styles */
input:-moz-autofill {
background-color: #FFEB3B !important;
background-image: none !important;
color: fieldtext !important;
}
input:-moz-autofill:hover,
input:-moz-autofill:focus,
input:-moz-autofill:active {
background-color: #FFEB3B !important;
background-image: none !important;
color: fieldtext !important;
}
input { input {
-moz-appearance: textfield; -moz-appearance: textfield;
appearance: textfield;
/* The sum of border and padding on block-start and block-end /* The sum of border and padding on block-start and block-end
must be the same here, for buttons, and for <select> (including its must be the same here, for buttons, and for <select> (including its
internal padding magic) */ internal padding magic) */
@ -91,6 +107,22 @@ input {
border: 2px inset ThreeDLightShadow; border: 2px inset ThreeDLightShadow;
background-color: -moz-Field; background-color: -moz-Field;
color: -moz-FieldText; color: -moz-FieldText;
}
/* Autofill styles - make highlighting persist */
input:-moz-autofill {
background-color: #FFEB3B !important;
color: fieldtext !important;
background-image: none !important;
}
/* Ensure highlight persists on focus/hover/active states */
input:-moz-autofill:hover,
input:-moz-autofill:focus,
input:-moz-autofill:active {
background-color: #FFEB3B !important;
color: fieldtext !important;
background-image: none !important;
font: -moz-field; font: -moz-field;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
line-height: normal; line-height: normal;

View file

@ -554,6 +554,9 @@ nsFormFillController::SetTextValue(const nsAString & aTextValue)
mozilla::dom::HTMLInputElement* htmlInput = mozilla::dom::HTMLInputElement::FromContentOrNull(content); mozilla::dom::HTMLInputElement* htmlInput = mozilla::dom::HTMLInputElement::FromContentOrNull(content);
if (htmlInput) { if (htmlInput) {
htmlInput->SetAutofilled(true); htmlInput->SetAutofilled(true);
nsAutoString value;
htmlInput->GetValue(value);
htmlInput->SetAutofilledValue(value);
} }
} }
} }