Bug 1481400 - Centralize keyboard activation code. r=masayuki

Differential Revision: https://phabricator.services.mozilla.com/D116584
This commit is contained in:
Emilio Cobos Álvarez 2021-06-03 08:15:24 +00:00
Родитель 1a8ab36ef2
Коммит 88bb474e07
5 изменённых файлов: 79 добавлений и 97 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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:

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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.