mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1119609 part.5 Compute KeyboardEvent.location and .keyCode if they are 0 r=smaug, sr=smaug
This commit is contained in:
parent
b6df689270
commit
a05a4768db
@ -448,6 +448,38 @@ TextInputProcessor::PrepareKeyboardEventToDispatch(
|
||||
aKeyboardEvent.GetDOMKeyName(aKeyboardEvent.mKeyValue);
|
||||
aKeyboardEvent.mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
|
||||
}
|
||||
if (aKeyFlags & KEY_KEEP_KEY_LOCATION_STANDARD) {
|
||||
// If .location is initialized with specific value, using
|
||||
// KEY_KEEP_KEY_LOCATION_STANDARD must be a bug of the caller.
|
||||
// Let's throw an exception for notifying the developer of this bug.
|
||||
if (NS_WARN_IF(aKeyboardEvent.location)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
} else if (!aKeyboardEvent.location) {
|
||||
// If KeyboardEvent.location is 0, it may be uninitialized. If so, we
|
||||
// should compute proper location value from its .code value.
|
||||
aKeyboardEvent.location =
|
||||
WidgetKeyboardEvent::ComputeLocationFromCodeValue(
|
||||
aKeyboardEvent.mCodeNameIndex);
|
||||
}
|
||||
|
||||
if (aKeyFlags & KEY_KEEP_KEYCODE_ZERO) {
|
||||
// If .keyCode is initialized with specific value, using
|
||||
// KEY_KEEP_KEYCODE_ZERO must be a bug of the caller. Let's throw an
|
||||
// exception for notifying the developer of such bug.
|
||||
if (NS_WARN_IF(aKeyboardEvent.keyCode)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
} else if (!aKeyboardEvent.keyCode &&
|
||||
aKeyboardEvent.mKeyNameIndex > KEY_NAME_INDEX_Unidentified &&
|
||||
aKeyboardEvent.mKeyNameIndex < KEY_NAME_INDEX_USE_STRING) {
|
||||
// If KeyboardEvent.keyCode is 0, it may be uninitialized. If so, we may
|
||||
// be able to decide a good .keyCode value if the .key value is a
|
||||
// non-printable key.
|
||||
aKeyboardEvent.keyCode =
|
||||
WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(
|
||||
aKeyboardEvent.mKeyNameIndex);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -692,9 +692,9 @@ function runKeyTests()
|
||||
is(events.length, 2,
|
||||
description + "TIP.keydown(keyEnter) should cause keydown and keypress event");
|
||||
checkKeyAttrs("TIP.keydown(keyEnter)", events[0],
|
||||
{ type: "keydown", key: "Enter", code: "Enter" });
|
||||
{ type: "keydown", key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
|
||||
checkKeyAttrs("TIP.keydown(keyEnter)", events[1],
|
||||
{ type: "keypress", key: "Enter", code: "Enter" });
|
||||
{ type: "keypress", key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
|
||||
is(input.value, "a",
|
||||
description + "input.value should stay \"a\" which was inputted by TIP.keydown(keyA)");
|
||||
|
||||
@ -706,7 +706,7 @@ function runKeyTests()
|
||||
is(events.length, 1,
|
||||
description + "TIP.keyup(keyEnter) should cause keyup event");
|
||||
checkKeyAttrs("TIP.keyup(keyEnter)", events[0],
|
||||
{ type: "keyup", key: "Enter", code: "Enter" });
|
||||
{ type: "keyup", key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
|
||||
is(input.value, "a",
|
||||
description + "input.value should stay \"a\" which was inputted by TIP.keydown(keyA)");
|
||||
|
||||
@ -803,11 +803,11 @@ function runKeyTests()
|
||||
is(events.length, 3,
|
||||
description + "TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers) should cause keydown, keypress and keyup event");
|
||||
checkKeyAttrs("TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers)", events[0],
|
||||
{ type: "keydown", key: "Escape", code: "Escape" });
|
||||
{ type: "keydown", key: "Escape", code: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE });
|
||||
checkKeyAttrs("TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers)", events[1],
|
||||
{ type: "keypress", key: "Escape", code: "Escape" });
|
||||
{ type: "keypress", key: "Escape", code: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE });
|
||||
checkKeyAttrs("TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers)", events[2],
|
||||
{ type: "keyup", key: "Escape", code: "Escape" });
|
||||
{ type: "keyup", key: "Escape", code: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE });
|
||||
is(input.value, "Enter",
|
||||
description + "input.value should stay \"Enter\" which was inputted by TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY)");
|
||||
|
||||
@ -909,6 +909,246 @@ function runKeyTests()
|
||||
SpecialPowers.clearUserPref("dom.keyboardevent.dispatch_during_composition");
|
||||
}
|
||||
|
||||
// Test .location computation
|
||||
const kCodeToLocation = [
|
||||
{ code: "BracketLeft", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "BracketRight", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Comma", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit0", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit1", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit2", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit3", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit4", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit5", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit6", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit7", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit8", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Digit9", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Equal", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Minus", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Period", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Slash", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "AltLeft", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
|
||||
{ code: "AltRight", location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
|
||||
{ code: "CapsLock", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "ContextMenu", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "ControlLeft", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
|
||||
{ code: "ControlRight", location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
|
||||
{ code: "Enter", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "OSLeft", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
|
||||
{ code: "OSRight", location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
|
||||
{ code: "ShiftLeft", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT },
|
||||
{ code: "ShiftRight", location: KeyboardEvent.DOM_KEY_LOCATION_RIGHT },
|
||||
{ code: "Space", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Tab", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "ArrowDown", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "ArrowLeft", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "ArrowRight", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "ArrowUp", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "NumLock", location: KeyboardEvent.DOM_KEY_LOCATION_STANDARD },
|
||||
{ code: "Numpad0", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad1", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad2", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad3", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad4", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad5", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad6", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad7", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad8", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "Numpad9", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadAdd", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadBackspace", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadClear", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadClearEntry", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadComma", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadDecimal", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadDivide", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadEnter", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadEqual", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadMemoryAdd", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadMemoryClear", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadMemoryRecall", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadMemoryStore", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadMemorySubtract", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadMultiply", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadParenLeft", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
// { code: "NumpadParenRight", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
{ code: "NumpadSubtract", location: KeyboardEvent.DOM_KEY_LOCATION_NUMPAD },
|
||||
];
|
||||
for (var i = 0; i < kCodeToLocation.length; i++) {
|
||||
var keyEvent = new KeyboardEvent("", { code: kCodeToLocation[i].code });
|
||||
reset();
|
||||
doPreventDefaults = [ "keypress" ];
|
||||
// If the location isn't initialized or initialized with 0, it should be computed from the code value.
|
||||
TIP.keydown(keyEvent);
|
||||
TIP.keyup(keyEvent);
|
||||
var longDesc = description + "testing computation of .location of \"" + kCodeToLocation[i].code + "\", ";
|
||||
is(events.length, 3,
|
||||
longDesc + "keydown, keypress and keyup events should be fired");
|
||||
for (var j = 0; j < events.length; j++) {
|
||||
is(events[j].location, kCodeToLocation[i].location,
|
||||
longDesc + " type=\"" + events[j].type + "\", location value is wrong");
|
||||
}
|
||||
// However, if KEY_KEEP_KEY_LOCATION_STANDARD is specified, .location value should be kept as DOM_KEY_LOCATION_STANDARD (0).
|
||||
reset();
|
||||
doPreventDefaults = [ "keypress" ];
|
||||
TIP.keydown(keyEvent, TIP.KEY_KEEP_KEY_LOCATION_STANDARD);
|
||||
TIP.keyup(keyEvent, TIP.KEY_KEEP_KEY_LOCATION_STANDARD);
|
||||
var longDesc = description + "testing if .location is forcibly set to DOM_KEY_LOCATION_STANDARD, ";
|
||||
is(events.length, 3,
|
||||
longDesc + "keydown, keypress and keyup events should be fired");
|
||||
for (var j = 0; j < events.length; j++) {
|
||||
is(events[j].location, KeyboardEvent.DOM_KEY_LOCATION_STANDARD,
|
||||
longDesc + " type=\"" + events[j].type + "\", location value is not 0");
|
||||
}
|
||||
// If .location is initialized with non-zero value, the value shouldn't be computed again.
|
||||
var keyEventWithLocation = new KeyboardEvent("", { code: kCodeToLocation[i].code, location: 0xFF });
|
||||
reset();
|
||||
doPreventDefaults = [ "keypress" ];
|
||||
TIP.keydown(keyEventWithLocation);
|
||||
TIP.keyup(keyEventWithLocation);
|
||||
longDesc = description + "testing if .location is not computed for \"" + kCodeToLocation[i].location + "\", ";
|
||||
is(events.length, 3,
|
||||
longDesc + "keydown, keypress and keyup events should be fired");
|
||||
for (var j = 0; j < events.length; j++) {
|
||||
is(events[j].location, 0xFF,
|
||||
longDesc + " type=\"" + events[j].type + "\", location shouldn't be computed if it's initialized with non-zero value");
|
||||
}
|
||||
}
|
||||
|
||||
// Test .keyCode value computation
|
||||
const kKeyToKeyCode = [
|
||||
{ key: "Cancel", keyCode: KeyboardEvent.DOM_VK_CANCEL },
|
||||
{ key: "Help", keyCode: KeyboardEvent.DOM_VK_HELP },
|
||||
{ key: "Backspace", keyCode: KeyboardEvent.DOM_VK_BACK_SPACE },
|
||||
{ key: "Tab", keyCode: KeyboardEvent.DOM_VK_TAB },
|
||||
{ key: "Clear", keyCode: KeyboardEvent.DOM_VK_CLEAR },
|
||||
{ key: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN },
|
||||
{ key: "Shift", keyCode: KeyboardEvent.DOM_VK_SHIFT, isModifier: true },
|
||||
{ key: "Control", keyCode: KeyboardEvent.DOM_VK_CONTROL, isModifier: true },
|
||||
{ key: "Alt", keyCode: KeyboardEvent.DOM_VK_ALT, isModifier: true },
|
||||
{ key: "Pause", keyCode: KeyboardEvent.DOM_VK_PAUSE },
|
||||
{ key: "CapsLock", keyCode: KeyboardEvent.DOM_VK_CAPS_LOCK, isModifier: true },
|
||||
{ key: "Hiragana", keyCode: KeyboardEvent.DOM_VK_KANA },
|
||||
{ key: "Katakana", keyCode: KeyboardEvent.DOM_VK_KANA },
|
||||
{ key: "HiraganaKatakana", keyCode: KeyboardEvent.DOM_VK_KANA },
|
||||
{ key: "KanaMode", keyCode: KeyboardEvent.DOM_VK_KANA },
|
||||
{ key: "HangulMode", keyCode: KeyboardEvent.DOM_VK_HANGUL },
|
||||
{ key: "Eisu", keyCode: KeyboardEvent.DOM_VK_EISU },
|
||||
{ key: "JunjaMode", keyCode: KeyboardEvent.DOM_VK_JUNJA },
|
||||
{ key: "FinalMode", keyCode: KeyboardEvent.DOM_VK_FINAL },
|
||||
{ key: "HanjaMode", keyCode: KeyboardEvent.DOM_VK_HANJA },
|
||||
{ key: "KanjiMode", keyCode: KeyboardEvent.DOM_VK_KANJI },
|
||||
{ key: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE },
|
||||
{ key: "Convert", keyCode: KeyboardEvent.DOM_VK_CONVERT },
|
||||
{ key: "NonConvert", keyCode: KeyboardEvent.DOM_VK_NONCONVERT },
|
||||
{ key: "Accept", keyCode: KeyboardEvent.DOM_VK_ACCEPT },
|
||||
{ key: "ModeChange", keyCode: KeyboardEvent.DOM_VK_MODECHANGE },
|
||||
{ key: "PageUp", keyCode: KeyboardEvent.DOM_VK_PAGE_UP },
|
||||
{ key: "PageDown", keyCode: KeyboardEvent.DOM_VK_PAGE_DOWN },
|
||||
{ key: "End", keyCode: KeyboardEvent.DOM_VK_END },
|
||||
{ key: "Home", keyCode: KeyboardEvent.DOM_VK_HOME },
|
||||
{ key: "ArrowLeft", keyCode: KeyboardEvent.DOM_VK_LEFT },
|
||||
{ key: "ArrowUp", keyCode: KeyboardEvent.DOM_VK_UP },
|
||||
{ key: "ArrowRight", keyCode: KeyboardEvent.DOM_VK_RIGHT },
|
||||
{ key: "ArrowDown", keyCode: KeyboardEvent.DOM_VK_DOWN },
|
||||
{ key: "Select", keyCode: KeyboardEvent.DOM_VK_SELECT },
|
||||
{ key: "Print", keyCode: KeyboardEvent.DOM_VK_PRINT },
|
||||
{ key: "Execute", keyCode: KeyboardEvent.DOM_VK_EXECUTE },
|
||||
{ key: "PrintScreen", keyCode: KeyboardEvent.DOM_VK_PRINTSCREEN },
|
||||
{ key: "Insert", keyCode: KeyboardEvent.DOM_VK_INSERT },
|
||||
{ key: "Delete", keyCode: KeyboardEvent.DOM_VK_DELETE },
|
||||
{ key: "OS", keyCode: KeyboardEvent.DOM_VK_WIN, isModifier: true },
|
||||
{ key: "ContextMenu", keyCode: KeyboardEvent.DOM_VK_CONTEXT_MENU },
|
||||
{ key: "F1", keyCode: KeyboardEvent.DOM_VK_F1 },
|
||||
{ key: "F2", keyCode: KeyboardEvent.DOM_VK_F2 },
|
||||
{ key: "F3", keyCode: KeyboardEvent.DOM_VK_F3 },
|
||||
{ key: "F4", keyCode: KeyboardEvent.DOM_VK_F4 },
|
||||
{ key: "F5", keyCode: KeyboardEvent.DOM_VK_F5 },
|
||||
{ key: "F6", keyCode: KeyboardEvent.DOM_VK_F6 },
|
||||
{ key: "F7", keyCode: KeyboardEvent.DOM_VK_F7 },
|
||||
{ key: "F8", keyCode: KeyboardEvent.DOM_VK_F8 },
|
||||
{ key: "F9", keyCode: KeyboardEvent.DOM_VK_F9 },
|
||||
{ key: "F10", keyCode: KeyboardEvent.DOM_VK_F10 },
|
||||
{ key: "F11", keyCode: KeyboardEvent.DOM_VK_F11 },
|
||||
{ key: "F12", keyCode: KeyboardEvent.DOM_VK_F12 },
|
||||
{ key: "F13", keyCode: KeyboardEvent.DOM_VK_F13 },
|
||||
{ key: "F14", keyCode: KeyboardEvent.DOM_VK_F14 },
|
||||
{ key: "F15", keyCode: KeyboardEvent.DOM_VK_F15 },
|
||||
{ key: "F16", keyCode: KeyboardEvent.DOM_VK_F16 },
|
||||
{ key: "F17", keyCode: KeyboardEvent.DOM_VK_F17 },
|
||||
{ key: "F18", keyCode: KeyboardEvent.DOM_VK_F18 },
|
||||
{ key: "F19", keyCode: KeyboardEvent.DOM_VK_F19 },
|
||||
{ key: "F20", keyCode: KeyboardEvent.DOM_VK_F20 },
|
||||
{ key: "F21", keyCode: KeyboardEvent.DOM_VK_F21 },
|
||||
{ key: "F22", keyCode: KeyboardEvent.DOM_VK_F22 },
|
||||
{ key: "F23", keyCode: KeyboardEvent.DOM_VK_F23 },
|
||||
{ key: "F24", keyCode: KeyboardEvent.DOM_VK_F24 },
|
||||
{ key: "NumLock", keyCode: KeyboardEvent.DOM_VK_NUM_LOCK, isModifier: true },
|
||||
{ key: "ScrollLock", keyCode: KeyboardEvent.DOM_VK_SCROLL_LOCK, isModifier: true },
|
||||
{ key: "VolumeMute", keyCode: KeyboardEvent.DOM_VK_VOLUME_MUTE },
|
||||
{ key: "VolumeDown", keyCode: KeyboardEvent.DOM_VK_VOLUME_DOWN },
|
||||
{ key: "VolumeUp", keyCode: KeyboardEvent.DOM_VK_VOLUME_UP },
|
||||
{ key: "Meta", keyCode: KeyboardEvent.DOM_VK_META, isModifier: true },
|
||||
{ key: "AltGraph", keyCode: KeyboardEvent.DOM_VK_ALTGR, isModifier: true },
|
||||
{ key: "Attn", keyCode: KeyboardEvent.DOM_VK_ATTN },
|
||||
{ key: "CrSel", keyCode: KeyboardEvent.DOM_VK_CRSEL },
|
||||
{ key: "ExSel", keyCode: KeyboardEvent.DOM_VK_EXSEL },
|
||||
{ key: "EraseEof", keyCode: KeyboardEvent.DOM_VK_EREOF },
|
||||
{ key: "Play", keyCode: KeyboardEvent.DOM_VK_PLAY },
|
||||
{ key: "ZoomToggle", keyCode: KeyboardEvent.DOM_VK_ZOOM },
|
||||
{ key: "ZoomIn", keyCode: KeyboardEvent.DOM_VK_ZOOM },
|
||||
{ key: "ZoomOut", keyCode: KeyboardEvent.DOM_VK_ZOOM },
|
||||
{ key: "Unidentified", keyCode: 0 },
|
||||
{ key: "a", keyCode: 0, isPrintable: true },
|
||||
{ key: "A", keyCode: 0, isPrintable: true },
|
||||
{ key: " ", keyCode: 0, isPrintable: true },
|
||||
{ key: "", keyCode: 0, isPrintable: true },
|
||||
];
|
||||
|
||||
for (var i = 0; i < kKeyToKeyCode.length; i++) {
|
||||
var keyEvent = new KeyboardEvent("", { key: kKeyToKeyCode[i].key });
|
||||
var causeKeypress = !kKeyToKeyCode[i].isModifier;
|
||||
var baseFlags = kKeyToKeyCode[i].isPrintable ? 0 : TIP.KEY_NON_PRINTABLE_KEY;
|
||||
reset();
|
||||
doPreventDefaults = [ "keypress" ];
|
||||
// If the keyCode isn't initialized or initialized with 0, it should be computed from the key value only when it's a printable key.
|
||||
TIP.keydown(keyEvent, baseFlags);
|
||||
TIP.keyup(keyEvent, baseFlags);
|
||||
var longDesc = description + "testing computation of .keyCode of \"" + kKeyToKeyCode[i].key + "\", ";
|
||||
is(events.length, causeKeypress ? 3 : 2,
|
||||
longDesc + "keydown" + (causeKeypress ? ", keypress" : "") + " and keyup events should be fired");
|
||||
for (var j = 0; j < events.length; j++) {
|
||||
is(events[j].keyCode, events[j].type == "keypress" && kKeyToKeyCode[i].isPrintable ? 0 : kKeyToKeyCode[i].keyCode,
|
||||
longDesc + " type=\"" + events[j].type + "\", keyCode value is wrong");
|
||||
}
|
||||
// However, if KEY_KEEP_KEYCODE_ZERO is specified, .keyCode value should be kept as 0.
|
||||
reset();
|
||||
doPreventDefaults = [ "keypress" ];
|
||||
TIP.keydown(keyEvent, TIP.KEY_KEEP_KEYCODE_ZERO | baseFlags);
|
||||
TIP.keyup(keyEvent, TIP.KEY_KEEP_KEYCODE_ZERO | baseFlags);
|
||||
var longDesc = description + "testing if .keyCode is forcibly set to KEY_KEEP_KEYCODE_ZERO, ";
|
||||
is(events.length, causeKeypress ? 3 : 2,
|
||||
longDesc + "keydown" + (causeKeypress ? ", keypress" : "") + " and keyup events should be fired");
|
||||
for (var j = 0; j < events.length; j++) {
|
||||
is(events[j].keyCode, 0,
|
||||
longDesc + " type=\"" + events[j].type + "\", keyCode value is not 0");
|
||||
}
|
||||
// If .keyCode is initialized with non-zero value, the value shouldn't be computed again.
|
||||
var keyEventWithLocation = new KeyboardEvent("", { key: kKeyToKeyCode[i].key, keyCode: 0xFF });
|
||||
reset();
|
||||
doPreventDefaults = [ "keypress" ];
|
||||
TIP.keydown(keyEventWithLocation, baseFlags);
|
||||
TIP.keyup(keyEventWithLocation, baseFlags);
|
||||
longDesc = description + "testing if .keyCode is not computed for \"" + kKeyToKeyCode[i].key + "\", ";
|
||||
is(events.length, causeKeypress ? 3 : 2,
|
||||
longDesc + "keydown" + (causeKeypress ? ", keypress" : "") + " and keyup events should be fired");
|
||||
for (var j = 0; j < events.length; j++) {
|
||||
is(events[j].keyCode, events[j].type == "keypress" && kKeyToKeyCode[i].isPrintable ? 0 : 0xFF,
|
||||
longDesc + " type=\"" + events[j].type + "\", keyCode shouldn't be computed if it's initialized with non-zero value");
|
||||
}
|
||||
}
|
||||
|
||||
window.removeEventListener("keydown", handler, false);
|
||||
window.removeEventListener("keypress", handler, false);
|
||||
window.removeEventListener("keyup", handler, false);
|
||||
@ -1116,6 +1356,46 @@ function runErrorTests()
|
||||
is(input.value, "",
|
||||
description + "The input element should not be modified");
|
||||
}
|
||||
|
||||
// KEY_KEEP_KEY_LOCATION_STANDARD flag should be used only when .location is not initialized with non-zero value.
|
||||
try {
|
||||
var keyEvent = new KeyboardEvent("", { code: "Enter", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT });
|
||||
TIP.keydown(keyEvent, TIP.KEY_KEEP_KEY_LOCATION_STANDARD);
|
||||
ok(false,
|
||||
description + "keydown(KEY_KEEP_KEY_LOCATION_STANDARD) should fail if the .location of the key event is initialized with non-zero value");
|
||||
} catch (e) {
|
||||
ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
|
||||
description + "keydown(KEY_KEEP_KEY_LOCATION_STANDARD) should cause NS_ERROR_ILLEGAL_VALUE if the .location of the key event is initialized with nonzero value");
|
||||
}
|
||||
try {
|
||||
var keyEvent = new KeyboardEvent("", { code: "Enter", location: KeyboardEvent.DOM_KEY_LOCATION_LEFT });
|
||||
TIP.keyup(keyEvent, TIP.KEY_KEEP_KEY_LOCATION_STANDARD);
|
||||
ok(false,
|
||||
description + "keyup(KEY_KEEP_KEY_LOCATION_STANDARD) should fail if the .location of the key event is initialized with non-zero value");
|
||||
} catch (e) {
|
||||
ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
|
||||
description + "keyup(KEY_KEEP_KEY_LOCATION_STANDARD) should cause NS_ERROR_ILLEGAL_VALUE if the .location of the key event is initialized with nonzero value");
|
||||
}
|
||||
|
||||
// KEY_KEEP_KEYCODE_ZERO flag should be used only when .keyCode is not initialized with non-zero value.
|
||||
try {
|
||||
var keyEvent = new KeyboardEvent("", { key: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
|
||||
TIP.keydown(keyEvent, TIP.KEY_KEEP_KEYCODE_ZERO);
|
||||
ok(false,
|
||||
description + "keydown(KEY_KEEP_KEYCODE_ZERO) should fail if the .keyCode of the key event is initialized with non-zero value");
|
||||
} catch (e) {
|
||||
ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
|
||||
description + "keydown(KEY_KEEP_KEYCODE_ZERO) should cause NS_ERROR_ILLEGAL_VALUE if the .keyCode of the key event is initialized with nonzero value");
|
||||
}
|
||||
try {
|
||||
var keyEvent = new KeyboardEvent("", { key: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
|
||||
TIP.keyup(keyEvent, TIP.KEY_KEEP_KEYCODE_ZERO);
|
||||
ok(false,
|
||||
description + "keyup(KEY_KEEP_KEYCODE_ZERO) should fail if the .keyCode of the key event is initialized with non-zero value");
|
||||
} catch (e) {
|
||||
ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
|
||||
description + "keyup(KEY_KEEP_KEYCODE_ZERO) should cause NS_ERROR_ILLEGAL_VALUE if the .keyCode of the key event is initialized with nonzero value");
|
||||
}
|
||||
}
|
||||
|
||||
function runCommitCompositionTests()
|
||||
|
@ -199,7 +199,7 @@ interface nsITextInputProcessorCallback;
|
||||
* }
|
||||
*/
|
||||
|
||||
[scriptable, builtinclass, uuid(60371ca6-a8a7-4e24-bf02-e262aa74ba5a)]
|
||||
[scriptable, builtinclass, uuid(16144d6e-a97a-4733-aa6a-3a1287cfe539)]
|
||||
interface nsITextInputProcessor : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -373,6 +373,17 @@ interface nsITextInputProcessor : nsISupports
|
||||
// If KEY_FORCE_PRINTABLE_KEY is specified and even if the .key value is a
|
||||
// registered key name, it's treated as inputting text value.
|
||||
const unsigned long KEY_FORCE_PRINTABLE_KEY = 0x00000004;
|
||||
// If KEY_KEEP_KEY_LOCATION_STANDARD is specified when its .location is not
|
||||
// initialized or initialized with 0, the value isn't computed with .code
|
||||
// value. Note that if .location is initialized with non-zero value,
|
||||
// this flag causes throwing an exception.
|
||||
// NOTE: This is not recommended to use except for tests.
|
||||
const unsigned long KEY_KEEP_KEY_LOCATION_STANDARD = 0x00000008;
|
||||
// If KEY_KEEP_KEYCODE_ZERO is specified when its .keyCode is not initialized
|
||||
// or initialized with 0, the value isn't computed with .key value when it
|
||||
// represents non-printable key. Note that if .keyCode is initialized with
|
||||
// non-zero value, this flag causes throwing an exception.
|
||||
const unsigned long KEY_KEEP_KEYCODE_ZERO = 0x00000010;
|
||||
|
||||
/**
|
||||
* keydown() may dispatch a keydown event and some keypress events if
|
||||
@ -380,6 +391,16 @@ interface nsITextInputProcessor : nsISupports
|
||||
* Note that even if this is called during composition, key events may not
|
||||
* be dispatched. In this case, this returns false.
|
||||
*
|
||||
* You should initialize at least .key value and .code value of the event.
|
||||
* Additionally, if you try to emulate a printable key, .keyCode value should
|
||||
* be specified if there is proper key value. See the comment of above
|
||||
* example how to decide .keyCode value of a printable key. On the other
|
||||
* hand, .keyCode value is automatically computed when you try to emulate
|
||||
* non-printable key. However, if you try to emulate physical keyboard of
|
||||
* desktop platform, you need to specify proper value explicitly because
|
||||
* the mapping table of this API isn't enough to emulate the behavior of
|
||||
* Gecko for desktop platforms.
|
||||
*
|
||||
* NOTE: Even if this has composition, JS-Keyboard should call keydown() and
|
||||
* keyup(). Although, with the default preferences and normal
|
||||
* conditions, DOM key events won't be fired during composition.
|
||||
@ -397,6 +418,8 @@ interface nsITextInputProcessor : nsISupports
|
||||
* #3 Non-defined code names are not allowed. If your
|
||||
* key isn't registered, file a bug. If your key isn't
|
||||
* defined by any standards, use "" (empty string).
|
||||
* #4 .keyCode is guessed from .key value if the key
|
||||
* name is registered and .keyCode isn't initialized.
|
||||
* @param aKeyFlags Special flags. The values can be some of KEY_*
|
||||
* constants.
|
||||
* @return true if neither the keydown event or following
|
||||
|
@ -190,8 +190,21 @@ public:
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
* ComputeLocationFromCodeValue() returns one of .location value
|
||||
* (nsIDOMKeyEvent::DOM_KEY_LOCATION_*) which is the most preferred value
|
||||
* for the specified specified code value.
|
||||
*/
|
||||
static uint32_t ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex);
|
||||
|
||||
/**
|
||||
* ComputeKeyCodeFromKeyNameIndex() return a .keyCode value which can be
|
||||
* mapped from the specified key value. Note that this returns 0 if the
|
||||
* key name index is KEY_NAME_INDEX_Unidentified or KEY_NAME_INDEX_USE_STRING.
|
||||
* This means that this method is useful only for non-printable keys.
|
||||
*/
|
||||
static uint32_t ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex);
|
||||
|
||||
static void GetDOMKeyName(KeyNameIndex aKeyNameIndex,
|
||||
nsAString& aKeyName);
|
||||
static void GetDOMCodeName(CodeNameIndex aCodeNameIndex,
|
||||
|
@ -470,4 +470,174 @@ WidgetKeyboardEvent::ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex)
|
||||
{
|
||||
switch (aKeyNameIndex) {
|
||||
case KEY_NAME_INDEX_Cancel:
|
||||
return nsIDOMKeyEvent::DOM_VK_CANCEL;
|
||||
case KEY_NAME_INDEX_Help:
|
||||
return nsIDOMKeyEvent::DOM_VK_HELP;
|
||||
case KEY_NAME_INDEX_Backspace:
|
||||
return nsIDOMKeyEvent::DOM_VK_BACK_SPACE;
|
||||
case KEY_NAME_INDEX_Tab:
|
||||
return nsIDOMKeyEvent::DOM_VK_TAB;
|
||||
case KEY_NAME_INDEX_Clear:
|
||||
return nsIDOMKeyEvent::DOM_VK_CLEAR;
|
||||
case KEY_NAME_INDEX_Enter:
|
||||
return nsIDOMKeyEvent::DOM_VK_RETURN;
|
||||
case KEY_NAME_INDEX_Shift:
|
||||
return nsIDOMKeyEvent::DOM_VK_SHIFT;
|
||||
case KEY_NAME_INDEX_Control:
|
||||
return nsIDOMKeyEvent::DOM_VK_CONTROL;
|
||||
case KEY_NAME_INDEX_Alt:
|
||||
return nsIDOMKeyEvent::DOM_VK_ALT;
|
||||
case KEY_NAME_INDEX_Pause:
|
||||
return nsIDOMKeyEvent::DOM_VK_PAUSE;
|
||||
case KEY_NAME_INDEX_CapsLock:
|
||||
return nsIDOMKeyEvent::DOM_VK_CAPS_LOCK;
|
||||
case KEY_NAME_INDEX_Hiragana:
|
||||
case KEY_NAME_INDEX_Katakana:
|
||||
case KEY_NAME_INDEX_HiraganaKatakana:
|
||||
case KEY_NAME_INDEX_KanaMode:
|
||||
return nsIDOMKeyEvent::DOM_VK_KANA;
|
||||
case KEY_NAME_INDEX_HangulMode:
|
||||
return nsIDOMKeyEvent::DOM_VK_HANGUL;
|
||||
case KEY_NAME_INDEX_Eisu:
|
||||
return nsIDOMKeyEvent::DOM_VK_EISU;
|
||||
case KEY_NAME_INDEX_JunjaMode:
|
||||
return nsIDOMKeyEvent::DOM_VK_JUNJA;
|
||||
case KEY_NAME_INDEX_FinalMode:
|
||||
return nsIDOMKeyEvent::DOM_VK_FINAL;
|
||||
case KEY_NAME_INDEX_HanjaMode:
|
||||
return nsIDOMKeyEvent::DOM_VK_HANJA;
|
||||
case KEY_NAME_INDEX_KanjiMode:
|
||||
return nsIDOMKeyEvent::DOM_VK_KANJI;
|
||||
case KEY_NAME_INDEX_Escape:
|
||||
return nsIDOMKeyEvent::DOM_VK_ESCAPE;
|
||||
case KEY_NAME_INDEX_Convert:
|
||||
return nsIDOMKeyEvent::DOM_VK_CONVERT;
|
||||
case KEY_NAME_INDEX_NonConvert:
|
||||
return nsIDOMKeyEvent::DOM_VK_NONCONVERT;
|
||||
case KEY_NAME_INDEX_Accept:
|
||||
return nsIDOMKeyEvent::DOM_VK_ACCEPT;
|
||||
case KEY_NAME_INDEX_ModeChange:
|
||||
return nsIDOMKeyEvent::DOM_VK_MODECHANGE;
|
||||
case KEY_NAME_INDEX_PageUp:
|
||||
return nsIDOMKeyEvent::DOM_VK_PAGE_UP;
|
||||
case KEY_NAME_INDEX_PageDown:
|
||||
return nsIDOMKeyEvent::DOM_VK_PAGE_DOWN;
|
||||
case KEY_NAME_INDEX_End:
|
||||
return nsIDOMKeyEvent::DOM_VK_END;
|
||||
case KEY_NAME_INDEX_Home:
|
||||
return nsIDOMKeyEvent::DOM_VK_HOME;
|
||||
case KEY_NAME_INDEX_ArrowLeft:
|
||||
return nsIDOMKeyEvent::DOM_VK_LEFT;
|
||||
case KEY_NAME_INDEX_ArrowUp:
|
||||
return nsIDOMKeyEvent::DOM_VK_UP;
|
||||
case KEY_NAME_INDEX_ArrowRight:
|
||||
return nsIDOMKeyEvent::DOM_VK_RIGHT;
|
||||
case KEY_NAME_INDEX_ArrowDown:
|
||||
return nsIDOMKeyEvent::DOM_VK_DOWN;
|
||||
case KEY_NAME_INDEX_Select:
|
||||
return nsIDOMKeyEvent::DOM_VK_SELECT;
|
||||
case KEY_NAME_INDEX_Print:
|
||||
return nsIDOMKeyEvent::DOM_VK_PRINT;
|
||||
case KEY_NAME_INDEX_Execute:
|
||||
return nsIDOMKeyEvent::DOM_VK_EXECUTE;
|
||||
case KEY_NAME_INDEX_PrintScreen:
|
||||
return nsIDOMKeyEvent::DOM_VK_PRINTSCREEN;
|
||||
case KEY_NAME_INDEX_Insert:
|
||||
return nsIDOMKeyEvent::DOM_VK_INSERT;
|
||||
case KEY_NAME_INDEX_Delete:
|
||||
return nsIDOMKeyEvent::DOM_VK_DELETE;
|
||||
case KEY_NAME_INDEX_OS:
|
||||
// case KEY_NAME_INDEX_Super:
|
||||
// case KEY_NAME_INDEX_Hyper:
|
||||
return nsIDOMKeyEvent::DOM_VK_WIN;
|
||||
case KEY_NAME_INDEX_ContextMenu:
|
||||
return nsIDOMKeyEvent::DOM_VK_CONTEXT_MENU;
|
||||
case KEY_NAME_INDEX_Standby:
|
||||
return nsIDOMKeyEvent::DOM_VK_SLEEP;
|
||||
case KEY_NAME_INDEX_F1:
|
||||
return nsIDOMKeyEvent::DOM_VK_F1;
|
||||
case KEY_NAME_INDEX_F2:
|
||||
return nsIDOMKeyEvent::DOM_VK_F2;
|
||||
case KEY_NAME_INDEX_F3:
|
||||
return nsIDOMKeyEvent::DOM_VK_F3;
|
||||
case KEY_NAME_INDEX_F4:
|
||||
return nsIDOMKeyEvent::DOM_VK_F4;
|
||||
case KEY_NAME_INDEX_F5:
|
||||
return nsIDOMKeyEvent::DOM_VK_F5;
|
||||
case KEY_NAME_INDEX_F6:
|
||||
return nsIDOMKeyEvent::DOM_VK_F6;
|
||||
case KEY_NAME_INDEX_F7:
|
||||
return nsIDOMKeyEvent::DOM_VK_F7;
|
||||
case KEY_NAME_INDEX_F8:
|
||||
return nsIDOMKeyEvent::DOM_VK_F8;
|
||||
case KEY_NAME_INDEX_F9:
|
||||
return nsIDOMKeyEvent::DOM_VK_F9;
|
||||
case KEY_NAME_INDEX_F10:
|
||||
return nsIDOMKeyEvent::DOM_VK_F10;
|
||||
case KEY_NAME_INDEX_F11:
|
||||
return nsIDOMKeyEvent::DOM_VK_F11;
|
||||
case KEY_NAME_INDEX_F12:
|
||||
return nsIDOMKeyEvent::DOM_VK_F12;
|
||||
case KEY_NAME_INDEX_F13:
|
||||
return nsIDOMKeyEvent::DOM_VK_F13;
|
||||
case KEY_NAME_INDEX_F14:
|
||||
return nsIDOMKeyEvent::DOM_VK_F14;
|
||||
case KEY_NAME_INDEX_F15:
|
||||
return nsIDOMKeyEvent::DOM_VK_F15;
|
||||
case KEY_NAME_INDEX_F16:
|
||||
return nsIDOMKeyEvent::DOM_VK_F16;
|
||||
case KEY_NAME_INDEX_F17:
|
||||
return nsIDOMKeyEvent::DOM_VK_F17;
|
||||
case KEY_NAME_INDEX_F18:
|
||||
return nsIDOMKeyEvent::DOM_VK_F18;
|
||||
case KEY_NAME_INDEX_F19:
|
||||
return nsIDOMKeyEvent::DOM_VK_F19;
|
||||
case KEY_NAME_INDEX_F20:
|
||||
return nsIDOMKeyEvent::DOM_VK_F20;
|
||||
case KEY_NAME_INDEX_F21:
|
||||
return nsIDOMKeyEvent::DOM_VK_F21;
|
||||
case KEY_NAME_INDEX_F22:
|
||||
return nsIDOMKeyEvent::DOM_VK_F22;
|
||||
case KEY_NAME_INDEX_F23:
|
||||
return nsIDOMKeyEvent::DOM_VK_F23;
|
||||
case KEY_NAME_INDEX_F24:
|
||||
return nsIDOMKeyEvent::DOM_VK_F24;
|
||||
case KEY_NAME_INDEX_NumLock:
|
||||
return nsIDOMKeyEvent::DOM_VK_NUM_LOCK;
|
||||
case KEY_NAME_INDEX_ScrollLock:
|
||||
return nsIDOMKeyEvent::DOM_VK_SCROLL_LOCK;
|
||||
case KEY_NAME_INDEX_VolumeMute:
|
||||
return nsIDOMKeyEvent::DOM_VK_VOLUME_MUTE;
|
||||
case KEY_NAME_INDEX_VolumeDown:
|
||||
return nsIDOMKeyEvent::DOM_VK_VOLUME_DOWN;
|
||||
case KEY_NAME_INDEX_VolumeUp:
|
||||
return nsIDOMKeyEvent::DOM_VK_VOLUME_UP;
|
||||
case KEY_NAME_INDEX_Meta:
|
||||
return nsIDOMKeyEvent::DOM_VK_META;
|
||||
case KEY_NAME_INDEX_AltGraph:
|
||||
return nsIDOMKeyEvent::DOM_VK_ALTGR;
|
||||
case KEY_NAME_INDEX_Attn:
|
||||
return nsIDOMKeyEvent::DOM_VK_ATTN;
|
||||
case KEY_NAME_INDEX_CrSel:
|
||||
return nsIDOMKeyEvent::DOM_VK_CRSEL;
|
||||
case KEY_NAME_INDEX_ExSel:
|
||||
return nsIDOMKeyEvent::DOM_VK_EXSEL;
|
||||
case KEY_NAME_INDEX_EraseEof:
|
||||
return nsIDOMKeyEvent::DOM_VK_EREOF;
|
||||
case KEY_NAME_INDEX_Play:
|
||||
return nsIDOMKeyEvent::DOM_VK_PLAY;
|
||||
case KEY_NAME_INDEX_ZoomToggle:
|
||||
case KEY_NAME_INDEX_ZoomIn:
|
||||
case KEY_NAME_INDEX_ZoomOut:
|
||||
return nsIDOMKeyEvent::DOM_VK_ZOOM;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
Loading…
Reference in New Issue
Block a user