diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp index 1fa56a7bb7bd..7add074516cd 100644 --- a/dom/html/HTMLButtonElement.cpp +++ b/dom/html/HTMLButtonElement.cpp @@ -228,25 +228,7 @@ nsresult HTMLButtonElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { } if (nsEventStatus_eIgnore == aVisitor.mEventStatus) { - switch (aVisitor.mEvent->mMessage) { - case eKeyPress: - case eKeyUp: { - // For backwards compat, trigger buttons with space or enter - // (bug 25300) - WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent(); - if ((keyEvent->mKeyCode == NS_VK_RETURN && - eKeyPress == aVisitor.mEvent->mMessage) || - (keyEvent->mKeyCode == NS_VK_SPACE && - eKeyUp == aVisitor.mEvent->mMessage)) { - DispatchSimulatedClick(this, aVisitor.mEvent->IsTrusted(), - aVisitor.mPresContext); - aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; - } - } break; - - default: - break; - } + HandleKeyboardActivation(aVisitor); if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) { if (mForm) { // Hold a strong ref while dispatching diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 4fb7b96b7824..61c4ab681bc7 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -3593,6 +3593,22 @@ bool HTMLInputElement::StepsInputValue( return true; } +static bool ActivatesWithKeyboard(uint8_t aType) { + switch (aType) { + case NS_FORM_INPUT_CHECKBOX: + case NS_FORM_INPUT_RADIO: + case NS_FORM_INPUT_BUTTON: + case NS_FORM_INPUT_RESET: + case NS_FORM_INPUT_SUBMIT: + case NS_FORM_INPUT_FILE: + case NS_FORM_INPUT_IMAGE: // Bug 34418 + case NS_FORM_INPUT_COLOR: + return true; + default: + return false; + } +} + nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { if (aVisitor.mEvent->mMessage == eFocus || aVisitor.mEvent->mMessage == eBlur) { @@ -3733,6 +3749,16 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { FireChangeEventIfNeeded(); aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; } else if (!preventDefault) { + // Checkbox and Radio try to submit on Enter press + if (aVisitor.mEvent->mMessage == eKeyPress && + (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO) && + keyEvent->mKeyCode == NS_VK_RETURN && aVisitor.mPresContext) { + MaybeSubmitForm(aVisitor.mPresContext); + } else if (ActivatesWithKeyboard(mType)) { + // Otherwise we maybe dispatch a synthesized click. + HandleKeyboardActivation(aVisitor); + } + switch (aVisitor.mEvent->mMessage) { case eFocus: { // see if we should select the contents of the textbox. This happens @@ -3761,43 +3787,8 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { } break; } - - case eKeyPress: - case eKeyUp: { - // For backwards compat, trigger checks/radios/buttons with - // space or enter (bug 25300) - WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent(); - if ((aVisitor.mEvent->mMessage == eKeyPress && - keyEvent->mKeyCode == NS_VK_RETURN) || - (aVisitor.mEvent->mMessage == eKeyUp && - keyEvent->mKeyCode == NS_VK_SPACE)) { - switch (mType) { - case NS_FORM_INPUT_CHECKBOX: - case NS_FORM_INPUT_RADIO: { - // Checkbox and Radio try to submit on Enter press - if (keyEvent->mKeyCode != NS_VK_SPACE && - aVisitor.mPresContext) { - MaybeSubmitForm(aVisitor.mPresContext); - - break; // If we are submitting, do not send click event - } - // else fall through and treat Space like click... - [[fallthrough]]; - } - case NS_FORM_INPUT_BUTTON: - case NS_FORM_INPUT_RESET: - case NS_FORM_INPUT_SUBMIT: - case NS_FORM_INPUT_FILE: - case NS_FORM_INPUT_IMAGE: // Bug 34418 - case NS_FORM_INPUT_COLOR: { - DispatchSimulatedClick(this, aVisitor.mEvent->IsTrusted(), - aVisitor.mPresContext); - aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; - } // case - } // switch - } - if (aVisitor.mEvent->mMessage == eKeyPress && - mType == NS_FORM_INPUT_RADIO && !keyEvent->IsAlt() && + case eKeyPress: { + if (mType == NS_FORM_INPUT_RADIO && !keyEvent->IsAlt() && !keyEvent->IsControl() && !keyEvent->IsMeta()) { bool isMovingBack = false; switch (keyEvent->mKeyCode) { @@ -3849,8 +3840,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { * not submit, period. */ - if (aVisitor.mEvent->mMessage == eKeyPress && - keyEvent->mKeyCode == NS_VK_RETURN && + if (keyEvent->mKeyCode == NS_VK_RETURN && (IsSingleLineTextControl(false, mType) || mType == NS_FORM_INPUT_NUMBER || IsDateTimeInputType(mType))) { FireChangeEventIfNeeded(); @@ -3860,8 +3850,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { } } - if (aVisitor.mEvent->mMessage == eKeyPress && - mType == NS_FORM_INPUT_RANGE && !keyEvent->IsAlt() && + if (mType == NS_FORM_INPUT_RANGE && !keyEvent->IsAlt() && !keyEvent->IsControl() && !keyEvent->IsMeta() && (keyEvent->mKeyCode == NS_VK_LEFT || keyEvent->mKeyCode == NS_VK_RIGHT || @@ -3924,7 +3913,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { } } - } break; // eKeyPress || eKeyUp + } break; // eKeyPress case eMouseDown: case eMouseUp: diff --git a/dom/html/HTMLSummaryElement.cpp b/dom/html/HTMLSummaryElement.cpp index f557f3462ac4..37b52b373072 100644 --- a/dom/html/HTMLSummaryElement.cpp +++ b/dom/html/HTMLSummaryElement.cpp @@ -62,37 +62,7 @@ nsresult HTMLSummaryElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { } } // event->HasMouseEventMessage() - if (event->HasKeyEventMessage()) { - WidgetKeyboardEvent* keyboardEvent = event->AsKeyboardEvent(); - bool dispatchClick = false; - - switch (event->mMessage) { - case eKeyPress: - if (keyboardEvent->mCharCode == ' ') { - // Consume 'space' key to prevent scrolling the page down. - aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; - } - - dispatchClick = keyboardEvent->mKeyCode == NS_VK_RETURN; - break; - - case eKeyUp: - dispatchClick = keyboardEvent->mKeyCode == NS_VK_SPACE; - break; - - default: - break; - } - - if (dispatchClick) { - rv = DispatchSimulatedClick(this, event->mFlags.mIsTrusted, - aVisitor.mPresContext); - if (NS_SUCCEEDED(rv)) { - aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; - } - } - } // event->HasKeyEventMessage() - + HandleKeyboardActivation(aVisitor); return rv; } diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 8d629414737d..86d3cd4641d3 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -16,6 +16,7 @@ #include "mozilla/MouseEvents.h" #include "mozilla/PresShell.h" #include "mozilla/TextEditor.h" +#include "mozilla/TextEvents.h" #include "mozilla/StaticPrefs_html5.h" #include "mozilla/StaticPrefs_layout.h" #include "mozilla/StaticPrefs_accessibility.h" @@ -2435,6 +2436,44 @@ bool nsGenericHTMLElement::PerformAccesskey(bool aKeyCausesActivation, return focused; } +void nsGenericHTMLElement::HandleKeyboardActivation( + EventChainPostVisitor& aVisitor) { + const auto message = aVisitor.mEvent->mMessage; + if (message != eKeyUp && message != eKeyPress) { + return; + } + + if (nsEventStatus_eIgnore != aVisitor.mEventStatus) { + return; + } + + const WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent(); + bool shouldActivate = false; + switch (message) { + case eKeyPress: + shouldActivate = keyEvent->mKeyCode == NS_VK_RETURN; + if (keyEvent->mKeyCode == NS_VK_SPACE) { + // Consume 'space' key to prevent scrolling the page down. + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; + } + break; + case eKeyUp: + shouldActivate = keyEvent->mKeyCode == NS_VK_SPACE; + break; + default: + MOZ_ASSERT_UNREACHABLE("why didn't we bail out earlier?"); + break; + } + + if (!shouldActivate) { + return; + } + + DispatchSimulatedClick(this, aVisitor.mEvent->IsTrusted(), + aVisitor.mPresContext); + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; +} + nsresult nsGenericHTMLElement::DispatchSimulatedClick( nsGenericHTMLElement* aElement, bool aIsTrusted, nsPresContext* aPresContext) { diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index 57281d8b0a19..91e781b9d477 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -699,11 +699,13 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase { virtual mozilla::EventListenerManager* GetEventListenerManagerForAttr( nsAtom* aAttrName, bool* aDefer) override; - /** - * Dispatch a simulated mouse click by keyboard to the given element. - */ - nsresult DispatchSimulatedClick(nsGenericHTMLElement* aElement, - bool aIsTrusted, nsPresContext* aPresContext); + /** Handles dispatching a simulated click on `this` on space or enter. */ + void HandleKeyboardActivation(mozilla::EventChainPostVisitor&); + + /** Dispatch a simulated mouse click by keyboard to the given element. */ + static nsresult DispatchSimulatedClick(nsGenericHTMLElement* aElement, + bool aIsTrusted, + nsPresContext* aPresContext); /** * Create a URI for the given aURISpec string.