mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1119609 part.14 Reimplement/redesign EventUtils.synthesizeKey() with nsITextInputProcessor r=smaug
This commit is contained in:
parent
26f706d27e
commit
019965a1f6
@ -45,7 +45,7 @@ function escapeTest(contentWindow) {
|
||||
}
|
||||
contentWindow.addEventListener("tabviewsearchdisabled", onSearchDisabled,
|
||||
false);
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", { }, contentWindow);
|
||||
EventUtils.synthesizeKey("KEY_Escape", { code: "Escape" }, contentWindow);
|
||||
}
|
||||
|
||||
function toggleTabViewTest(contentWindow) {
|
||||
@ -57,5 +57,6 @@ function toggleTabViewTest(contentWindow) {
|
||||
}
|
||||
contentWindow.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
// Use keyboard shortcut to toggle back to browser view
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true });
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true,
|
||||
code: "KeyE", keyCode: KeyboardEvent.DOM_VK_E }, contentWindow);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ function onTabViewWindowLoaded() {
|
||||
// verify that the keyboard combo works (this is the crux of bug 595518)
|
||||
// Prepare the key combo
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, contentWindow);
|
||||
EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true, code: "KeyE", keyCode: KeyboardEvent.DOM_VK_E }, contentWindow);
|
||||
}
|
||||
|
||||
let onTabViewShown = function() {
|
||||
|
@ -72,7 +72,8 @@ if (observers.hasMoreElements()) {
|
||||
ok(true, "formnovalidate should not apply on if not set on the submit " +
|
||||
"control used for the submission");
|
||||
var c = document.getElementById('c');
|
||||
c.focus(); synthesizeKey("VK_RETURN", {type: "keypress"});
|
||||
c.focus();
|
||||
synthesizeKey("KEY_Enter", { code: "Enter" });
|
||||
}, false);
|
||||
|
||||
document.getElementById('c').addEventListener("invalid", function(aEvent) {
|
||||
|
@ -189,15 +189,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
||||
if (isDesktop) { // up/down arrow keys not supported on android/b2g
|
||||
number.value = "";
|
||||
number.focus();
|
||||
synthesizeKey("VK_UP", {});
|
||||
synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" });
|
||||
is(numberInput, 1, "input event should be dispatched for up/down arrow key keypress");
|
||||
is(number.value, 1, "sanity check value of number control after keypress");
|
||||
|
||||
synthesizeKey("VK_DOWN", { type: "keydown" });
|
||||
synthesizeKey("VK_DOWN", { type: "keypress" });
|
||||
synthesizeKey("VK_DOWN", { type: "keypress" });
|
||||
synthesizeKey("VK_DOWN", { type: "keypress" });
|
||||
synthesizeKey("VK_DOWN", { type: "keyup" });
|
||||
synthesizeKey("KEY_ArrowDown", { code: "ArrowDown", repeat: 3 });
|
||||
is(numberInput, 4, "input event should be dispatched for each up/down arrow key keypress event, even when rapidly repeated");
|
||||
is(number.value, -2, "sanity check value of number control after multiple keydown events");
|
||||
|
||||
|
@ -48,7 +48,8 @@ document.forms[1].addEventListener("submit", function(aEvent) {
|
||||
aEvent.target.removeEventListener("submit", arguments.callee, false);
|
||||
ok(true, "novalidate has been correctly used for second form");
|
||||
var c = document.getElementById('c');
|
||||
c.focus(); synthesizeKey("VK_RETURN", {type: "keypress"});
|
||||
c.focus();
|
||||
synthesizeKey("KEY_Enter", { code: "Enter" });
|
||||
}, false);
|
||||
|
||||
document.forms[2].addEventListener("submit", function(aEvent) {
|
||||
|
@ -107,7 +107,8 @@ function runTest()
|
||||
document.getElementById('a').click();
|
||||
document.getElementById('b').click();
|
||||
var c = document.getElementById('c');
|
||||
c.focus(); synthesizeKey("VK_RETURN", {type: "keypress"});
|
||||
c.focus();
|
||||
synthesizeKey("KEY_Enter", { code: "Enter" });
|
||||
document.getElementById('s2').click();
|
||||
}
|
||||
|
||||
|
@ -127,34 +127,6 @@ function runTests()
|
||||
aElement.focus();
|
||||
is(SpecialPowers.unwrap(fm.focusedElement), aElement, aDescription + "failed to move focus");
|
||||
|
||||
// Modifier keys:
|
||||
// Basically, modifier keys shouldn't cause keypress event. However,
|
||||
// even if it were dispatched by widget's bug, editor should consume
|
||||
// it when editor is editable.
|
||||
reset("");
|
||||
synthesizeKey("VK_META", { type: "keypress" });
|
||||
check(aDescription + "Meta", true, true, !aIsReadonly);
|
||||
|
||||
reset("");
|
||||
synthesizeKey("VK_WIN", { type: "keypress" });
|
||||
check(aDescription + "OS", true, true, !aIsReadonly);
|
||||
|
||||
reset("");
|
||||
synthesizeKey("VK_SHIFT", { type: "keypress" });
|
||||
check(aDescription + "Shift", true, true, !aIsReadonly);
|
||||
|
||||
reset("");
|
||||
synthesizeKey("VK_CONTROL", { type: "keypress" });
|
||||
check(aDescription + "Control", true, true, !aIsReadonly);
|
||||
|
||||
// Alt key press event installs menubar key event listener, so,
|
||||
// we should pass Alt key testing on Windows and Linux.
|
||||
if (!kIsWin && !kIsLinux) {
|
||||
reset("");
|
||||
synthesizeKey("VK_ALT", { type: "keypress" });
|
||||
check(aDescription + "Alt", true, true, !aIsReadonly);
|
||||
}
|
||||
|
||||
// Backspace key:
|
||||
// If editor is readonly, it doesn't consume.
|
||||
// If editor is editable, it consumes backspace and shift+backspace.
|
||||
|
@ -113,34 +113,6 @@ function runTests()
|
||||
aElement.focus();
|
||||
is(SpecialPowers.unwrap(fm.focusedElement), aElement, aDescription + "failed to move focus");
|
||||
|
||||
// Modifier keys:
|
||||
// Basically, modifier keys shouldn't cause keypress event. However,
|
||||
// even if it were dispatched by widget's bug, editor should consume
|
||||
// it when editor is editable.
|
||||
reset("");
|
||||
synthesizeKey("VK_META", { type: "keypress" });
|
||||
check(aDescription + "Meta", true, true, !aIsReadonly);
|
||||
|
||||
reset("");
|
||||
synthesizeKey("VK_WIN", { type: "keypress" });
|
||||
check(aDescription + "OS", true, true, !aIsReadonly);
|
||||
|
||||
reset("");
|
||||
synthesizeKey("VK_SHIFT", { type: "keypress" });
|
||||
check(aDescription + "Shift", true, true, !aIsReadonly);
|
||||
|
||||
reset("");
|
||||
synthesizeKey("VK_CONTROL", { type: "keypress" });
|
||||
check(aDescription + "Control", true, true, !aIsReadonly);
|
||||
|
||||
// Alt key press event installs menubar key event listener, so,
|
||||
// we should pass Alt key testing on Windows and Linux.
|
||||
if (!kIsWin && !kIsLinux) {
|
||||
reset("");
|
||||
synthesizeKey("VK_ALT", { type: "keypress" });
|
||||
check(aDescription + "Alt", true, true, !aIsReadonly);
|
||||
}
|
||||
|
||||
// Backspace key:
|
||||
// If editor is readonly, it doesn't consume.
|
||||
// If editor is editable, it consumes backspace and shift+backspace.
|
||||
|
@ -31,11 +31,10 @@ function runTest()
|
||||
|
||||
// key events should not be retargeted when the focus changes to an
|
||||
// element in the same document.
|
||||
synthesizeKey("a", { type: "keydown" });
|
||||
synthesizeKey("a", { type: "keydown", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_B });
|
||||
is(document.activeElement, $("i2"), "input 2 in focused");
|
||||
|
||||
synthesizeKey("a", { type: "keypress" });
|
||||
synthesizeKey("a", { type: "keyup" });
|
||||
synthesizeKey("a", { type: "keyup", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_B });
|
||||
|
||||
is(gKeyDown1, 1, "keydown on input 1");
|
||||
is(gKeyPress1, 0, "keypress on input 1");
|
||||
@ -53,9 +52,7 @@ function runTest()
|
||||
|
||||
var childWinObj = frames[0].wrappedJSObject;
|
||||
|
||||
synthesizeKey("b", { type: "keydown" });
|
||||
synthesizeKey("b", { type: "keypress" });
|
||||
synthesizeKey("b", { type: "keyup" });
|
||||
synthesizeKey("b", { code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B });
|
||||
is(gKeyDown3, 1, "keydown on input 3");
|
||||
is(gKeyPress3, 1, "keypress on input 3");
|
||||
is(gKeyUp3, 1, "keyup on input 3");
|
||||
@ -74,9 +71,7 @@ function runTest()
|
||||
// element in a chrome document from a content document.
|
||||
i4.addEventListener("keydown", function () $("i3").focus(), false);
|
||||
|
||||
synthesizeKey("c", { type: "keydown" });
|
||||
synthesizeKey("c", { type: "keypress" });
|
||||
synthesizeKey("c", { type: "keyup" });
|
||||
synthesizeKey("c", { code: "KeyC", keyCode: KeyboardEvent.DOM_VK_C });
|
||||
|
||||
is(gKeyDown3, 1, "keydown on input 3");
|
||||
is(gKeyPress3, 1, "keypress on input 3");
|
||||
|
@ -53,7 +53,7 @@ function doe3() {
|
||||
document.getElementById('a').focus();
|
||||
document.body.style.display = 'none';
|
||||
|
||||
synthesizeKey('VK_TAB', {type: "keypress", shiftKey: true});
|
||||
synthesizeKey('KEY_Tab', { code: "Tab", shiftKey: true });
|
||||
|
||||
is(0, 0, "this is a crash/assertion test, so we're ok if we survived this far");
|
||||
setTimeout(function() {document.body.style.display = ''; SimpleTest.finish();}, 0);
|
||||
|
@ -509,101 +509,73 @@ function _computeKeyCodeFromChar(aChar)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* isKeypressFiredKey() returns TRUE if the given key should cause keypress
|
||||
* event when widget handles the native key event. Otherwise, FALSE.
|
||||
*
|
||||
* aDOMKeyCode should be one of consts of nsIDOMKeyEvent::DOM_VK_*, or a key
|
||||
* name begins with "VK_", or a character.
|
||||
*/
|
||||
function isKeypressFiredKey(aDOMKeyCode)
|
||||
{
|
||||
if (typeof(aDOMKeyCode) == "string") {
|
||||
if (aDOMKeyCode.indexOf("VK_") == 0) {
|
||||
aDOMKeyCode = KeyEvent["DOM_" + aDOMKeyCode];
|
||||
if (!aDOMKeyCode) {
|
||||
throw "Unknown key: " + aDOMKeyCode;
|
||||
}
|
||||
} else {
|
||||
// If the key generates a character, it must cause a keypress event.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
switch (aDOMKeyCode) {
|
||||
case KeyEvent.DOM_VK_SHIFT:
|
||||
case KeyEvent.DOM_VK_CONTROL:
|
||||
case KeyEvent.DOM_VK_ALT:
|
||||
case KeyEvent.DOM_VK_CAPS_LOCK:
|
||||
case KeyEvent.DOM_VK_NUM_LOCK:
|
||||
case KeyEvent.DOM_VK_SCROLL_LOCK:
|
||||
case KeyEvent.DOM_VK_META:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a key event. It is targeted at whatever would be targeted by an
|
||||
* actual keypress by the user, typically the focused element.
|
||||
*
|
||||
* aKey should be either a character or a keycode starting with VK_ such as
|
||||
* VK_RETURN.
|
||||
* aKey should be:
|
||||
* - key value (recommended). If you specify a non-printable key name,
|
||||
* append "KEY_" prefix. Otherwise, specifying a printable key, the
|
||||
* key value should be specified.
|
||||
* - keyCode name starting with "VK_" (e.g., VK_RETURN). This is available
|
||||
* only for compatibility with legacy API. Don't use this with new tests.
|
||||
*
|
||||
* aEvent is an object which may contain the properties:
|
||||
* shiftKey, ctrlKey, altKey, metaKey, accessKey, type, location
|
||||
*
|
||||
* Sets one of KeyboardEvent.DOM_KEY_LOCATION_* to location. Otherwise,
|
||||
* DOMWindowUtils will choose good location from the keycode.
|
||||
*
|
||||
* If the type is specified, a key event of that type is fired. Otherwise,
|
||||
* a keydown, a keypress and then a keyup event are fired in sequence.
|
||||
* - code: If you emulates a physical keyboard's key event, this should be
|
||||
* specified.
|
||||
* - repeat: If you emulates auto-repeat, you should set the count of repeat.
|
||||
* This method will automatically synthesize keydown (and keypress).
|
||||
* - location: If you want to specify this, you can specify this explicitly.
|
||||
* However, if you don't specify this value, it will be computed
|
||||
* from code value.
|
||||
* - type: Basically, you shouldn't specify this. Then, this function will
|
||||
* synthesize keydown (, keypress) and keyup.
|
||||
* If keydown is specified, this only fires keydown (and keypress if
|
||||
* it should be fired).
|
||||
* If keyup is specified, this only fires keyup.
|
||||
* - altKey, altGraphKey, ctrlKey, capsLockKey, fnKey, fnLockKey, numLockKey,
|
||||
* metaKey, osKey, scrollLockKey, shiftKey, symbolKey, symbolLockKey:
|
||||
* Basically, you shouldn't use these attributes. nsITextInputProcessor
|
||||
* manages modifier key state when you synthesize modifier key events.
|
||||
* However, if some of these attributes are true, this function activates
|
||||
* the modifiers only during dispatching the key events.
|
||||
* Note that if some of these values are false, they are ignored (i.e.,
|
||||
* not inactivated with this function).
|
||||
* - keyCode: Must be 0 - 255 (0xFF). If this is specified explicitly,
|
||||
* .keyCode value is initialized with this value.
|
||||
*
|
||||
* aWindow is optional, and defaults to the current window object.
|
||||
*/
|
||||
function synthesizeKey(aKey, aEvent, aWindow)
|
||||
{
|
||||
var utils = _getDOMWindowUtils(aWindow);
|
||||
if (utils) {
|
||||
var keyEventDict = _createKeyboardEventDictionary(aKey, aEvent);
|
||||
var keyCode = keyEventDict.dictionary.keyCode;
|
||||
var charCode =
|
||||
(aKey.indexOf("VK_") == 0) ?
|
||||
0 : ((keyEventDict.dictionary.key != "") ?
|
||||
keyEventDict.dictionary.key.charCodeAt(0) : 0);
|
||||
var TIP = _getTIP(aWindow);
|
||||
if (!TIP) {
|
||||
return;
|
||||
}
|
||||
var modifiers = _emulateToActivateModifiers(TIP, aEvent);
|
||||
var keyEventDict = _createKeyboardEventDictionary(aKey, aEvent);
|
||||
var keyEvent = new KeyboardEvent("", keyEventDict.dictionary);
|
||||
var dispatchKeydown =
|
||||
!("type" in aEvent) || aEvent.type === "keydown" || !aEvent.type;
|
||||
var dispatchKeyup =
|
||||
!("type" in aEvent) || aEvent.type === "keyup" || !aEvent.type;
|
||||
|
||||
var modifiers = _parseModifiers(aEvent);
|
||||
var flags = 0;
|
||||
switch (keyEventDict.dictionary.location) {
|
||||
case KeyboardEvent.DOM_KEY_LOCATION_STANDARD:
|
||||
flags |= utils.KEY_FLAG_LOCATION_STANDARD;
|
||||
break;
|
||||
case KeyboardEvent.DOM_KEY_LOCATION_LEFT:
|
||||
flags |= utils.KEY_FLAG_LOCATION_LEFT;
|
||||
break;
|
||||
case KeyboardEvent.DOM_KEY_LOCATION_RIGHT:
|
||||
flags |= utils.KEY_FLAG_LOCATION_RIGHT;
|
||||
break;
|
||||
case KeyboardEvent.DOM_KEY_LOCATION_NUMPAD:
|
||||
flags |= utils.KEY_FLAG_LOCATION_NUMPAD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!("type" in aEvent) || !aEvent.type) {
|
||||
// Send keydown + (optional) keypress + keyup events.
|
||||
var keyDownDefaultHappened =
|
||||
utils.sendKeyEvent("keydown", keyCode, 0, modifiers, flags);
|
||||
if (isKeypressFiredKey(keyCode) && keyDownDefaultHappened) {
|
||||
utils.sendKeyEvent("keypress", keyCode, charCode, modifiers, flags);
|
||||
try {
|
||||
if (dispatchKeydown) {
|
||||
TIP.keydown(keyEvent, keyEventDict.flags);
|
||||
if ("repeat" in aEvent && aEvent.repeat > 1) {
|
||||
keyEventDict.dictionary.repeat = true;
|
||||
var repeatedKeyEvent = new KeyboardEvent("", keyEventDict.dictionary);
|
||||
for (var i = 1; i < aEvent.repeat; i++) {
|
||||
TIP.keydown(repeatedKeyEvent, keyEventDict.flags);
|
||||
}
|
||||
}
|
||||
utils.sendKeyEvent("keyup", keyCode, 0, modifiers, flags);
|
||||
} else if (aEvent.type == "keypress") {
|
||||
// Send standalone keypress event.
|
||||
utils.sendKeyEvent(aEvent.type, keyCode, charCode, modifiers, flags);
|
||||
} else {
|
||||
// Send other standalone event than keypress.
|
||||
utils.sendKeyEvent(aEvent.type, keyCode, 0, modifiers, flags);
|
||||
}
|
||||
if (dispatchKeyup) {
|
||||
TIP.keyup(keyEvent, keyEventDict.flags);
|
||||
}
|
||||
} finally {
|
||||
_emulateToInactivateModifiers(TIP, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1074,7 +1046,7 @@ function _createKeyboardEventDictionary(aKey, aKeyEvent)
|
||||
key: keyName,
|
||||
code: "code" in aKeyEvent ? aKeyEvent.code : "",
|
||||
location: locationIsDefined ? aKeyEvent.location : 0,
|
||||
repeat: "repeat" in aKeyEvent ? aKeyEvent.repeat : false,
|
||||
repeat: "repeat" in aKeyEvent ? aKeyEvent.repeat === true : false,
|
||||
keyCode: keyCode,
|
||||
};
|
||||
return result;
|
||||
|
@ -69,7 +69,7 @@ function test_richlistbox()
|
||||
ok(richListBox.currentIndex > currentIndex, "Selection should move upwards");
|
||||
richListBox.selectedItem = richListBox.lastChild;
|
||||
richListBox.focus();
|
||||
synthesizeKey("VK_DOWN", {shiftKey: true, type: "keypress"}, window);
|
||||
synthesizeKey("KEY_ArrowDown", { shiftKey: true, code: "ArrowDown" }, window);
|
||||
let items = [richListBox.selectedItems[0],
|
||||
richListBox.selectedItems[1]];
|
||||
is(items[0], richListBox.lastChild, "The last element should still be selected");
|
||||
@ -115,7 +115,7 @@ function test_richlistbox()
|
||||
ok(richListBox.currentIndex < currentIndex, "Selection should move upwards");
|
||||
richListBox.selectedItem = richListBox.firstChild;
|
||||
richListBox.focus();
|
||||
synthesizeKey("VK_DOWN", {shiftKey: true, type: "keypress"}, window);
|
||||
synthesizeKey("KEY_ArrowDown", { shiftKey: true, code: "ArrowDown" }, window);
|
||||
items = [richListBox.selectedItems[0],
|
||||
richListBox.selectedItems[1]];
|
||||
is(items[0], richListBox.firstChild, "The last element should still be selected");
|
||||
|
@ -784,9 +784,6 @@ var popupTests = [
|
||||
}, false);
|
||||
newWindow.close();
|
||||
thisWindow.focus();
|
||||
// Note that our window dispatches a hacky key event if IMM is installed
|
||||
// on the system during focus change only if Alt key is pressed.
|
||||
synthesizeKey("`", { type: "keypress" }, thisWindow);
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
@ -139,10 +139,7 @@ function startTests()
|
||||
|
||||
clear();
|
||||
synthesizeKey("a", { type: "keydown" });
|
||||
checkKeyEvents(true, false, false, false, "a keydown");
|
||||
clear();
|
||||
synthesizeKey("a", { type: "keypress" });
|
||||
checkKeyEvents(false, true, false, true, "a keypress");
|
||||
checkKeyEvents(true, true, false, true, "a keydown and a keypress");
|
||||
is(textarea.value, "a", "textarea value isn't 'a'");
|
||||
clear();
|
||||
synthesizeKey("a", { type: "keyup" });
|
||||
|
Loading…
Reference in New Issue
Block a user