mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
Issue #2161 - Ctrl + Enter should cause keypress event even though the key combination doesn't input any character
Currently, we dispatch keypress event when Enter is pressed without modifiers or only with the Shift key (line break). However, other browsers dispatch keypress events for Ctrl + Enter also even if it doesn't cause any text input. So, we should fire keypress events for Ctrl + Enter, even in strict keypress dispatching mode. Note that with other modifiers, it depends on the browser and/or platform and we can't dispatch the event for consistent behavior. This means web developers shouldn't rely one keypress events to catch Alt + Enter, Meta + Enter and two or more modifiers + Enter. Based on BZ 1438133 Resolves #2161
This commit is contained in:
parent
b29522749a
commit
078b1b73dc
3 changed files with 187 additions and 2 deletions
|
|
@ -8,6 +8,9 @@
|
|||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<p><input type="text" id="input"></p>
|
||||
<p><input type="text" id="input_readonly" readonly></p>
|
||||
<p><textarea id="textarea"></textarea></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
|
|
@ -293,10 +296,163 @@ function testSynthesizedKeyLocation()
|
|||
window.removeEventListener("keyup", handler, true);
|
||||
}
|
||||
|
||||
// We're using TextEventDispatcher to decide if we should keypress event
|
||||
// on content in the default event group. So, we can test if keypress
|
||||
// event is NOT fired unexpectedly with synthesizeKey().
|
||||
function testEnterKeyPressEvent()
|
||||
{
|
||||
let keydownFired, keypressFired, beforeinputFired;
|
||||
function onEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "keydown":
|
||||
keydownFired = true;
|
||||
return;
|
||||
case "keypress":
|
||||
keypressFired = true;
|
||||
return;
|
||||
case "beforeinput":
|
||||
beforeinputFired = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (let targetId of ["input", "textarea", "input_readonly"]) {
|
||||
let target = document.getElementById(targetId);
|
||||
|
||||
function reset() {
|
||||
keydownFired = keypressFired = beforeinputFired = false;
|
||||
target.value = "";
|
||||
}
|
||||
|
||||
target.addEventListener("keydown", onEvent);
|
||||
target.addEventListener("keypress", onEvent);
|
||||
target.addEventListener("beforeinput", onEvent);
|
||||
|
||||
const kDescription = "<" + targetId.replace("_", " ") + ">: ";
|
||||
let isEditable = kDescription.includes("readonly");
|
||||
let isTextarea = kDescription.includes("textarea");
|
||||
|
||||
target.focus();
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Enter key is pressed");
|
||||
is(keypressFired, true,
|
||||
kDescription + "keypress event should be fired when Enter key is pressed");
|
||||
if (isEditable) {
|
||||
todo_is(beforeinputFired, true,
|
||||
kDescription + "beforeinput event should be fired when Enter key is pressed");
|
||||
} else {
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Enter key is pressed");
|
||||
}
|
||||
if (isTextarea) {
|
||||
is(target.value, "\n",
|
||||
kDescription + "Enter key should cause inputting a line break in <textarea>");
|
||||
} else {
|
||||
is(target.value, "",
|
||||
kDescription + "Enter key should not cause inputting a line break");
|
||||
}
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {shiftKey: true});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Shift + Enter key is pressed");
|
||||
is(keypressFired, true,
|
||||
kDescription + "keypress event should be fired when Shift + Enter key is pressed");
|
||||
if (isEditable) {
|
||||
todo_is(beforeinputFired, true,
|
||||
kDescription + "beforeinput event should be fired when Shift + Enter key is pressed");
|
||||
} else {
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Shift + Enter key is pressed");
|
||||
}
|
||||
if (isTextarea) {
|
||||
is(target.value, "\n",
|
||||
kDescription + "Shift + Enter key should cause inputting a line break in <textarea>");
|
||||
} else {
|
||||
is(target.value, "",
|
||||
kDescription + "Shift + Enter key should not cause inputting a line break");
|
||||
}
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {ctrlKey: true});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Ctrl + Enter key is pressed");
|
||||
is(keypressFired, true,
|
||||
kDescription + "keypress event should be fired when Ctrl + Enter key is pressed");
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Ctrl + Enter key is pressed");
|
||||
is(target.value, "",
|
||||
kDescription + "Ctrl + Enter key should not cause inputting a line break");
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {altKey: true});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Alt + Enter key is pressed");
|
||||
is(keypressFired, !kStrictKeyPressEvents,
|
||||
kDescription + "keypress event shouldn't be fired when Alt + Enter key is pressed in strict keypress dispatching mode");
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Alt + Enter key is pressed");
|
||||
is(target.value, "",
|
||||
kDescription + "Alt + Enter key should not cause inputting a line break");
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {metaKey: true});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Meta + Enter key is pressed");
|
||||
is(keypressFired, !kStrictKeyPressEvents,
|
||||
kDescription + "keypress event shouldn't be fired when Meta + Enter key is pressed in strict keypress dispatching mode");
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Meta + Enter key is pressed");
|
||||
is(target.value, "",
|
||||
kDescription + "Meta + Enter key should not cause inputting a line break");
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {shiftKey: true, ctrlKey: true});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Ctrl + Shift + Enter key is pressed");
|
||||
is(keypressFired, !kStrictKeyPressEvents,
|
||||
kDescription + "keypress event shouldn't be fired when Ctrl + Shift + Enter key is pressed in strict keypress dispatching mode");
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Ctrl + Shift + Enter key is pressed");
|
||||
is(target.value, "",
|
||||
kDescription + "Ctrl + Shift + Enter key should not cause inputting a line break");
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {shiftKey: true, altKey: true});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Alt + Shift + Enter key is pressed");
|
||||
is(keypressFired, !kStrictKeyPressEvents,
|
||||
kDescription + "keypress event shouldn't be fired when Alt + Shift + Enter key is pressed in strict keypress dispatching mode");
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Alt + Shift + Enter key is pressed");
|
||||
is(target.value, "",
|
||||
kDescription + "Alt + Shift + Enter key should not cause inputting a line break");
|
||||
|
||||
reset();
|
||||
synthesizeKey("KEY_Enter", {shiftKey: true, metaKey: true});
|
||||
is(keydownFired, true,
|
||||
kDescription + "keydown event should be fired when Meta + Shift + Enter key is pressed");
|
||||
is(keypressFired, !kStrictKeyPressEvents,
|
||||
kDescription + "keypress event shouldn't be fired when Meta + Shift + Enter key is pressed in strict keypress dispatching mode");
|
||||
is(beforeinputFired, false,
|
||||
kDescription + "beforeinput event shouldn't be fired when Meta + Shift + Enter key is pressed");
|
||||
is(target.value, "",
|
||||
kDescription + "Meta + Shift + Enter key should not cause inputting a line break");
|
||||
|
||||
target.removeEventListener("keydown", onEvent);
|
||||
target.removeEventListener("keypress", onEvent);
|
||||
target.removeEventListener("beforeinput", onEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
testInitializingUntrustedEvent();
|
||||
testSynthesizedKeyLocation();
|
||||
testEnterKeyPressEvent();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -538,8 +538,7 @@ TextEventDispatcher::DispatchKeyboardEventInternal(
|
|||
|
||||
if (!sDispatchKeyPressEventNonPrintableInContent &&
|
||||
keyEvent.mMessage == eKeyPress &&
|
||||
!keyEvent.IsInputtingText() &&
|
||||
!keyEvent.IsInputtingLineBreak()) {
|
||||
!keyEvent.ShouldKeyPressEventBeFiredOnContent()) {
|
||||
keyEvent.mFlags.mOnlySystemGroupDispatchInContent = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -207,6 +207,36 @@ public:
|
|||
MODIFIER_OS));
|
||||
}
|
||||
|
||||
/**
|
||||
* ShouldKeyPressEventBeFiredOnContent() should be called only when the
|
||||
* instance is eKeyPress event. This returns true when the eKeyPress
|
||||
* event should be fired even on content in the default event group.
|
||||
*/
|
||||
bool ShouldKeyPressEventBeFiredOnContent() const
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mMessage == eKeyPress);
|
||||
// Case 1: Inputting text or a line break: always fire keypress event.
|
||||
if (IsInputtingText() || IsInputtingLineBreak()) {
|
||||
return true;
|
||||
}
|
||||
// Case 2: Ctrl + Enter
|
||||
// Ctrl + Enter won't cause actual input in our editor so should not fire the event if people would be consistent
|
||||
// in setting rules for themselves (foreshadowing... ;P).
|
||||
// However, the other browsers fire the keypress event in this case (but not with other modifiers).
|
||||
// So, for compatibility with them, we should fire the keypress event for Ctrl + Enter too.
|
||||
if (mMessage == eKeyPress &&
|
||||
mKeyNameIndex == KEY_NAME_INDEX_Enter &&
|
||||
!(mModifiers & (MODIFIER_ALT |
|
||||
MODIFIER_META |
|
||||
MODIFIER_OS |
|
||||
MODIFIER_SHIFT))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Default: dont't fire in the default event group.
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual WidgetEvent* Duplicate() const override
|
||||
{
|
||||
MOZ_ASSERT(mClass == eKeyboardEventClass,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue