зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1481400 - Don't dispatch a simulated click on keyup for default-prevented keydown. r=masayuki
I decided to go with a separate flag instead of reusing :active because the :active handling WebKit uses for buttons is extremely weird: They apply :active only to the button, not to the whole element chain like mouse activeness does, and something like this keeps the :active state in the button ~forever: <!doctype html> <style> :active { outline: 2px solid red; } </style> <button onkeyup="return false">ABC</button> Differential Revision: https://phabricator.services.mozilla.com/D116585
This commit is contained in:
Родитель
88bb474e07
Коммит
21c786b30a
|
@ -2439,17 +2439,26 @@ bool nsGenericHTMLElement::PerformAccesskey(bool aKeyCausesActivation,
|
|||
void nsGenericHTMLElement::HandleKeyboardActivation(
|
||||
EventChainPostVisitor& aVisitor) {
|
||||
const auto message = aVisitor.mEvent->mMessage;
|
||||
if (message != eKeyUp && message != eKeyPress) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsEventStatus_eIgnore != aVisitor.mEventStatus) {
|
||||
if (message != eKeyDown && message != eKeyUp && message != eKeyPress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
|
||||
if (nsEventStatus_eIgnore != aVisitor.mEventStatus) {
|
||||
if (message == eKeyUp && keyEvent->mKeyCode == NS_VK_SPACE) {
|
||||
// Unset the flag even if the event is default-prevented or something.
|
||||
UnsetFlags(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldActivate = false;
|
||||
switch (message) {
|
||||
case eKeyDown:
|
||||
if (keyEvent->mKeyCode == NS_VK_SPACE) {
|
||||
SetFlags(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD);
|
||||
}
|
||||
return;
|
||||
case eKeyPress:
|
||||
shouldActivate = keyEvent->mKeyCode == NS_VK_RETURN;
|
||||
if (keyEvent->mKeyCode == NS_VK_SPACE) {
|
||||
|
@ -2458,7 +2467,11 @@ void nsGenericHTMLElement::HandleKeyboardActivation(
|
|||
}
|
||||
break;
|
||||
case eKeyUp:
|
||||
shouldActivate = keyEvent->mKeyCode == NS_VK_SPACE;
|
||||
shouldActivate = keyEvent->mKeyCode == NS_VK_SPACE &&
|
||||
HasFlag(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD);
|
||||
if (shouldActivate) {
|
||||
UnsetFlags(HTML_ELEMENT_ACTIVE_FOR_KEYBOARD);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("why didn't we bail out earlier?");
|
||||
|
|
|
@ -905,9 +905,24 @@ class HTMLFieldSetElement;
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#define FORM_ELEMENT_FLAG_BIT(n_) \
|
||||
#define HTML_ELEMENT_FLAG_BIT(n_) \
|
||||
NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
|
||||
// HTMLElement specific bits
|
||||
enum {
|
||||
// Used to handle keyboard activation.
|
||||
HTML_ELEMENT_ACTIVE_FOR_KEYBOARD = HTML_ELEMENT_FLAG_BIT(0),
|
||||
|
||||
// Remaining bits are type specific.
|
||||
HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET =
|
||||
ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1,
|
||||
};
|
||||
|
||||
ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
|
||||
|
||||
#define FORM_ELEMENT_FLAG_BIT(n_) \
|
||||
NODE_FLAG_BIT(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
|
||||
// Form element specific bits
|
||||
enum {
|
||||
// If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement,
|
||||
|
@ -931,7 +946,7 @@ enum {
|
|||
// MAYBE_ORPHAN_FORM_ELEMENT set at the same time, so if it becomes an issue we
|
||||
// can probably merge them into the same bit. --bz
|
||||
|
||||
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3);
|
||||
ASSERT_NODE_FLAGS_SPACE(HTML_ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3);
|
||||
|
||||
#undef FORM_ELEMENT_FLAG_BIT
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>Button activation submits on keyup, but not if keydown is defaultPrevented</title>
|
||||
<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1481400">
|
||||
<link rel=author href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel=author href="https://mozilla.org" title="Mozilla">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<button>The button</button>
|
||||
<script>
|
||||
let button = document.querySelector("button");
|
||||
promise_test(async t => {
|
||||
button.focus();
|
||||
assert_equals(document.activeElement, button, "Button should be focused");
|
||||
let clickPromise = new Promise(resolve => {
|
||||
button.addEventListener("click", resolve, { once: true });
|
||||
});
|
||||
|
||||
await test_driver.send_keys(button, " ");
|
||||
|
||||
await clickPromise;
|
||||
|
||||
assert_true(true, "Button should have activated");
|
||||
|
||||
document.addEventListener("keydown", t.step_func(function(e) {
|
||||
e.preventDefault();
|
||||
}));
|
||||
|
||||
button.addEventListener("click", t.unreached_func("button got incorrectly activated"));
|
||||
|
||||
await test_driver.send_keys(button, " ");
|
||||
|
||||
await new Promise(resolve => t.step_timeout(resolve, 0));
|
||||
assert_true(true, "Button should not have activated");
|
||||
});
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче