Bug 1760709 - Take directionality into account when handling left/right on radios. r=smaug
We have similar code for range inputs. This matches Blink (but not WebKit), but I think it's a better default. The spec seems to leave this up to UAs, so for now landing a moz-specific WPT. Should be trivial to upstream if we want. Depends on D141705 Differential Revision: https://phabricator.services.mozilla.com/D141706
This commit is contained in:
@@ -3773,41 +3773,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
||||
case eKeyPress: {
|
||||
if (mType == FormControlType::InputRadio && !keyEvent->IsAlt() &&
|
||||
!keyEvent->IsControl() && !keyEvent->IsMeta()) {
|
||||
bool isMovingBack = false;
|
||||
switch (keyEvent->mKeyCode) {
|
||||
case NS_VK_UP:
|
||||
case NS_VK_LEFT:
|
||||
isMovingBack = true;
|
||||
[[fallthrough]];
|
||||
case NS_VK_DOWN:
|
||||
case NS_VK_RIGHT:
|
||||
// Arrow key pressed, focus+select prev/next radio button
|
||||
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||
if (container) {
|
||||
nsAutoString name;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||
RefPtr<HTMLInputElement> selectedRadioButton;
|
||||
container->GetNextRadioButton(
|
||||
name, isMovingBack, this,
|
||||
getter_AddRefs(selectedRadioButton));
|
||||
if (selectedRadioButton) {
|
||||
FocusOptions options;
|
||||
ErrorResult error;
|
||||
|
||||
selectedRadioButton->Focus(options, CallerType::System,
|
||||
error);
|
||||
rv = error.StealNSResult();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = DispatchSimulatedClick(selectedRadioButton,
|
||||
aVisitor.mEvent->IsTrusted(),
|
||||
aVisitor.mPresContext);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rv = MaybeHandleRadioButtonNavigation(aVisitor, keyEvent->mKeyCode);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4100,6 +4066,52 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
|
||||
return MaybeInitPickers(aVisitor);
|
||||
}
|
||||
|
||||
enum class RadioButtonMove { Back, Forward, None };
|
||||
nsresult HTMLInputElement::MaybeHandleRadioButtonNavigation(
|
||||
EventChainPostVisitor& aVisitor, uint32_t aKeyCode) {
|
||||
auto move = [&] {
|
||||
switch (aKeyCode) {
|
||||
case NS_VK_UP:
|
||||
return RadioButtonMove::Back;
|
||||
case NS_VK_DOWN:
|
||||
return RadioButtonMove::Forward;
|
||||
case NS_VK_LEFT:
|
||||
case NS_VK_RIGHT: {
|
||||
const bool isRtl = GetComputedDirectionality() == eDir_RTL;
|
||||
return isRtl == (aKeyCode == NS_VK_LEFT) ? RadioButtonMove::Forward
|
||||
: RadioButtonMove::Back;
|
||||
}
|
||||
}
|
||||
return RadioButtonMove::None;
|
||||
}();
|
||||
if (move == RadioButtonMove::None) {
|
||||
return NS_OK;
|
||||
}
|
||||
// Arrow key pressed, focus+select prev/next radio button
|
||||
RefPtr<HTMLInputElement> selectedRadioButton;
|
||||
if (nsIRadioGroupContainer* container = GetRadioGroupContainer()) {
|
||||
nsAutoString name;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||
container->GetNextRadioButton(name, move == RadioButtonMove::Back, this,
|
||||
getter_AddRefs(selectedRadioButton));
|
||||
}
|
||||
if (!selectedRadioButton) {
|
||||
return NS_OK;
|
||||
}
|
||||
FocusOptions options;
|
||||
ErrorResult error;
|
||||
selectedRadioButton->Focus(options, CallerType::System, error);
|
||||
if (error.Failed()) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
nsresult rv = DispatchSimulatedClick(
|
||||
selectedRadioButton, aVisitor.mEvent->IsTrusted(), aVisitor.mPresContext);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void HTMLInputElement::PostHandleEventForRangeThumb(
|
||||
EventChainPostVisitor& aVisitor) {
|
||||
MOZ_ASSERT(mType == FormControlType::InputRange);
|
||||
|
||||
Reference in New Issue
Block a user