Bug 947490: Move Marionette sendKeys code to it's own file and delete dead code; r=jgriffin

This commit is contained in:
David Burns 2014-09-19 00:52:40 +01:00
Родитель fc53ede9d6
Коммит b0755c7fd5
4 изменённых файлов: 203 добавлений и 545 удалений

Просмотреть файл

@ -169,6 +169,7 @@ class TestTyping(MarionetteTestCase):
# And leave no rubbish/printable keys in the "keyReporter"
self.assertEqual(element.get_attribute("value"), "")
''' Disabled. Reenable in Bug 1068728
def testNumericShiftKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -179,6 +180,7 @@ class TestTyping(MarionetteTestCase):
element.send_keys(numericShiftsEtc)
self.assertEqual(element.get_attribute("value"), numericShiftsEtc)
self.assertTrue(" up: 16" in result.text.strip())
'''
def testLowerCaseAlphaKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
@ -189,6 +191,7 @@ class TestTyping(MarionetteTestCase):
element.send_keys(lowerAlphas)
self.assertEqual(element.get_attribute("value"), lowerAlphas)
''' Disabled. Reenable in Bug 1068735
def testUppercaseAlphaKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -199,7 +202,9 @@ class TestTyping(MarionetteTestCase):
element.send_keys(upperAlphas)
self.assertEqual(element.get_attribute("value"), upperAlphas)
self.assertTrue(" up: 16" in result.text.strip())
'''
''' Disabled. Reenable in Bug 1068726
def testAllPrintableKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -211,7 +216,9 @@ class TestTyping(MarionetteTestCase):
self.assertTrue(element.get_attribute("value"), allPrintable)
self.assertTrue(" up: 16" in result.text.strip())
'''
''' Disabled. Reenable in Bug 1068733
def testSpecialSpaceKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -219,6 +226,7 @@ class TestTyping(MarionetteTestCase):
element = self.marionette.find_element("id", "keyReporter")
element.send_keys("abcd" + Keys.SPACE + "fgh" + Keys.SPACE + "ij")
self.assertEqual(element.get_attribute("value"), "abcd fgh ij")
'''
def testShouldTypeAnInteger(self):
test_html = self.marionette.absolute_url("javascriptPage.html")

Просмотреть файл

@ -42,7 +42,6 @@ disabled = "Bug 896046"
[test_clearing.py]
[test_typing.py]
disabled = "Bug 123456"
[test_log.py]
[test_emulator.py]

Просмотреть файл

@ -1590,193 +1590,9 @@ function sendKeysToElement(msg) {
let command_id = msg.json.command_id;
let el = elementManager.getKnownElement(msg.json.id, curFrame);
if (checkVisible(el)) {
el.focus();
var value = msg.json.value.join("");
let hasShift = null;
let hasCtrl = null;
let hasAlt = null;
let hasMeta = null;
for (var i = 0; i < value.length; i++) {
let upper = value.charAt(i).toUpperCase();
var keyCode = null;
var c = value.charAt(i);
switch (c) {
case '\uE001':
keyCode = "VK_CANCEL";
break;
case '\uE002':
keyCode = "VK_HELP";
break;
case '\uE003':
keyCode = "VK_BACK_SPACE";
break;
case '\uE004':
keyCode = "VK_TAB";
break;
case '\uE005':
keyCode = "VK_CLEAR";
break;
case '\uE006':
case '\uE007':
keyCode = "VK_RETURN";
break;
case '\uE008':
keyCode = "VK_SHIFT";
hasShift = !hasShift;
break;
case '\uE009':
keyCode = "VK_CONTROL";
controlKey = !controlKey;
break;
case '\uE00A':
keyCode = "VK_ALT";
altKey = !altKey;
break;
case '\uE03D':
keyCode = "VK_META";
metaKey = !metaKey;
break;
case '\uE00B':
keyCode = "VK_PAUSE";
break;
case '\uE00C':
keyCode = "VK_ESCAPE";
break;
case '\uE00D':
keyCode = "VK_Space"; // printable
break;
case '\uE00E':
keyCode = "VK_PAGE_UP";
break;
case '\uE00F':
keyCode = "VK_PAGE_DOWN";
break;
case '\uE010':
keyCode = "VK_END";
break;
case '\uE011':
keyCode = "VK_HOME";
break;
case '\uE012':
keyCode = "VK_LEFT";
break;
case '\uE013':
keyCode = "VK_UP";
break;
case '\uE014':
keyCode = "VK_RIGHT";
break;
case '\uE015':
keyCode = "VK_DOWN";
break;
case '\uE016':
keyCode = "VK_INSERT";
break;
case '\uE017':
keyCode = "VK_DELETE";
break;
case '\uE018':
keyCode = "VK_SEMICOLON";
break;
case '\uE019':
keyCode = "VK_EQUALS";
break;
case '\uE01A':
keyCode = "VK_NUMPAD0";
break;
case '\uE01B':
keyCode = "VK_NUMPAD1";
break;
case '\uE01C':
keyCode = "VK_NUMPAD2";
break;
case '\uE01D':
keyCode = "VK_NUMPAD3";
break;
case '\uE01E':
keyCode = "VK_NUMPAD4";
break;
case '\uE01F':
keyCode = "VK_NUMPAD5";
break;
case '\uE020':
keyCode = "VK_NUMPAD6";
break;
case '\uE021':
keyCode = "VK_NUMPAD7";
break;
case '\uE022':
keyCode = "VK_NUMPAD8";
break;
case '\uE023':
keyCode = "VK_NUMPAD9";
break;
case '\uE024':
keyCode = "VK_MULTIPLY";
break;
case '\uE025':
keyCode = "VK_ADD";
break;
case '\uE026':
keyCode = "VK_SEPARATOR";
break;
case '\uE027':
keyCode = "VK_SUBTRACT";
break;
case '\uE028':
keyCode = "VK_DECIMAL";
break;
case '\uE029':
keyCode = "VK_DIVIDE";
break;
case '\uE031':
keyCode = "VK_F1";
break;
case '\uE032':
keyCode = "VK_F2";
break;
case '\uE033':
keyCode = "VK_F3";
break;
case '\uE034':
keyCode = "VK_F4";
break;
case '\uE035':
keyCode = "VK_F5";
break;
case '\uE036':
keyCode = "VK_F6";
break;
case '\uE037':
keyCode = "VK_F7";
break;
case '\uE038':
keyCode = "VK_F8";
break;
case '\uE039':
keyCode = "VK_F9";
break;
case '\uE03A':
keyCode = "VK_F10";
break;
case '\uE03B':
keyCode = "VK_F11";
break;
case '\uE03C':
keyCode = "VK_F12";
break;
}
hasShift = value.charAt(i) == upper;
utils.synthesizeKey(keyCode || value[i],
{ shiftKey: hasShift, ctrlKey: hasCtrl, altKey: hasAlt, metaKey: hasMeta },
curFrame);
};
sendOk(command_id);
}
else {
sendError("Element is not visible", 11, null, command_id)
}
let keysToSend = msg.json.value;
utils.sendKeysToElement(curFrame, el, keysToSend, sendOk, sendError, command_id);
}
/**

Просмотреть файл

@ -16,365 +16,200 @@
* limitations under the License.
*/
let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
var type = function(doc, element, text, releaseModifiers,
opt_keysState) {
let utils = {};
loader.loadSubScript("chrome://marionette/content/EventUtils.js", utils);
loader.loadSubScript("chrome://marionette/content/ChromeUtils.js", utils);
var currentTextLength = element.value ? element.value.length : 0;
element.selectionStart = currentTextLength;
element.selectionEnd = currentTextLength;
// For consistency between native and synthesized events, convert common
// escape sequences to their Key enum aliases.
text = text.replace(new RegExp('\b', 'g'), '\uE003'). // DOM_VK_BACK_SPACE
replace(/\t/g, '\uE004'). // DOM_VK_TAB
replace(/(\r\n|\n|\r)/g, '\uE006'); // DOM_VK_RETURN
var controlKey = false;
var shiftKey = false;
var altKey = false;
var metaKey = false;
if (opt_keysState) {
controlKey = opt_keysState.control;
shiftKey = opt_keysState.shiftKey;
altKey = opt_keysState.alt;
metaKey = opt_keysState.meta;
}
shiftCount = 0;
var upper = text.toUpperCase();
for (var i = 0; i < text.length; i++) {
var c = text.charAt(i);
// NULL key: reset modifier key states, and continue
if (c == '\uE000') {
if (controlKey) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey = false, shiftKey, altKey, metaKey, false);
}
if (shiftKey) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey, shiftKey = false, altKey, metaKey, false);
}
if (altKey) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey, shiftKey, altKey = false, metaKey, false);
}
if (metaKey) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey, shiftKey, altKey, metaKey = false, false);
}
continue;
}
// otherwise decode keyCode, charCode, modifiers ...
var modifierEvent = "";
var charCode = 0;
var keyCode = 0;
if (c == '\uE001') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CANCEL;
} else if (c == '\uE002') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HELP;
} else if (c == '\uE003') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SPACE;
} else if (c == '\uE004') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_TAB;
} else if (c == '\uE005') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLEAR;
} else if (c == '\uE006' || c == '\uE007') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RETURN;
} else if (c == '\uE008') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
shiftKey = !shiftKey;
modifierEvent = shiftKey ? "keydown" : "keyup";
} else if (c == '\uE009') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
function sendKeysToElement (document, element, keysToSend, successCallback, errorCallback, command_id) {
if (checkVisible(element)) {
element.focus();
var value = keysToSend.join("");
let hasShift = null;
let hasCtrl = null;
let hasAlt = null;
let hasMeta = null;
for (var i = 0; i < value.length; i++) {
let upper = value.charAt(i).toUpperCase();
var keyCode = null;
var c = value.charAt(i);
switch (c) {
case '\uE001':
keyCode = "VK_CANCEL";
break;
case '\uE002':
keyCode = "VK_HELP";
break;
case '\uE003':
keyCode = "VK_BACK_SPACE";
break;
case '\uE004':
keyCode = "VK_TAB";
break;
case '\uE005':
keyCode = "VK_CLEAR";
break;
case '\uE006':
case '\uE007':
keyCode = "VK_RETURN";
break;
case '\uE008':
keyCode = "VK_SHIFT";
hasShift = !hasShift;
break;
case '\uE009':
keyCode = "VK_CONTROL";
controlKey = !controlKey;
modifierEvent = controlKey ? "keydown" : "keyup";
} else if (c == '\uE00A') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
break;
case '\uE00A':
keyCode = "VK_ALT";
altKey = !altKey;
modifierEvent = altKey ? "keydown" : "keyup";
} else if (c == '\uE03D') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
break;
case '\uE03D':
keyCode = "VK_META";
metaKey = !metaKey;
modifierEvent = metaKey ? "keydown" : "keyup";
} else if (c == '\uE00B') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAUSE;
} else if (c == '\uE00C') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ESCAPE;
} else if (c == '\uE00D') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SPACE;
keyCode = charCode = ' '.charCodeAt(0); // printable
} else if (c == '\uE00E') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_UP;
} else if (c == '\uE00F') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN;
} else if (c == '\uE010') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_END;
} else if (c == '\uE011') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_HOME;
} else if (c == '\uE012') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_LEFT;
} else if (c == '\uE013') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_UP;
} else if (c == '\uE014') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_RIGHT;
} else if (c == '\uE015') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DOWN;
} else if (c == '\uE016') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_INSERT;
} else if (c == '\uE017') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DELETE;
} else if (c == '\uE018') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEMICOLON;
charCode = ';'.charCodeAt(0);
} else if (c == '\uE019') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_EQUALS;
charCode = '='.charCodeAt(0);
} else if (c == '\uE01A') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD0;
charCode = '0'.charCodeAt(0);
} else if (c == '\uE01B') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD1;
charCode = '1'.charCodeAt(0);
} else if (c == '\uE01C') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD2;
charCode = '2'.charCodeAt(0);
} else if (c == '\uE01D') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD3;
charCode = '3'.charCodeAt(0);
} else if (c == '\uE01E') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD4;
charCode = '4'.charCodeAt(0);
} else if (c == '\uE01F') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD5;
charCode = '5'.charCodeAt(0);
} else if (c == '\uE020') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD6;
charCode = '6'.charCodeAt(0);
} else if (c == '\uE021') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD7;
charCode = '7'.charCodeAt(0);
} else if (c == '\uE022') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD8;
charCode = '8'.charCodeAt(0);
} else if (c == '\uE023') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_NUMPAD9;
charCode = '9'.charCodeAt(0);
} else if (c == '\uE024') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_MULTIPLY;
charCode = '*'.charCodeAt(0);
} else if (c == '\uE025') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ADD;
charCode = '+'.charCodeAt(0);
} else if (c == '\uE026') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SEPARATOR;
charCode = ','.charCodeAt(0);
} else if (c == '\uE027') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SUBTRACT;
charCode = '-'.charCodeAt(0);
} else if (c == '\uE028') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DECIMAL;
charCode = '.'.charCodeAt(0);
} else if (c == '\uE029') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_DIVIDE;
charCode = '/'.charCodeAt(0);
} else if (c == '\uE031') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F1;
} else if (c == '\uE032') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F2;
} else if (c == '\uE033') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F3;
} else if (c == '\uE034') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F4;
} else if (c == '\uE035') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F5;
} else if (c == '\uE036') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F6;
} else if (c == '\uE037') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F7;
} else if (c == '\uE038') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F8;
} else if (c == '\uE039') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F9;
} else if (c == '\uE03A') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F10;
} else if (c == '\uE03B') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F11;
} else if (c == '\uE03C') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_F12;
} else if (c == ',' || c == '<') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_COMMA;
charCode = c.charCodeAt(0);
} else if (c == '.' || c == '>') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_PERIOD;
charCode = c.charCodeAt(0);
} else if (c == '/' || c == '?') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SLASH;
charCode = text.charCodeAt(i);
} else if (c == '`' || c == '~') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_QUOTE;
charCode = c.charCodeAt(0);
} else if (c == '{' || c == '[') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET;
charCode = c.charCodeAt(0);
} else if (c == '\\' || c == '|') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_BACK_SLASH;
charCode = c.charCodeAt(0);
} else if (c == '}' || c == ']') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET;
charCode = c.charCodeAt(0);
} else if (c == '\'' || c == '"') {
keyCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_QUOTE;
charCode = c.charCodeAt(0);
} else {
keyCode = upper.charCodeAt(i);
charCode = text.charCodeAt(i);
break;
case '\uE00B':
keyCode = "VK_PAUSE";
break;
case '\uE00C':
keyCode = "VK_ESCAPE";
break;
case '\uE00D':
keyCode = "VK_SPACE"; // printable
break;
case '\uE00E':
keyCode = "VK_PAGE_UP";
break;
case '\uE00F':
keyCode = "VK_PAGE_DOWN";
break;
case '\uE010':
keyCode = "VK_END";
break;
case '\uE011':
keyCode = "VK_HOME";
break;
case '\uE012':
keyCode = "VK_LEFT";
break;
case '\uE013':
keyCode = "VK_UP";
break;
case '\uE014':
keyCode = "VK_RIGHT";
break;
case '\uE015':
keyCode = "VK_DOWN";
break;
case '\uE016':
keyCode = "VK_INSERT";
break;
case '\uE017':
keyCode = "VK_DELETE";
break;
case '\uE018':
keyCode = "VK_SEMICOLON";
break;
case '\uE019':
keyCode = "VK_EQUALS";
break;
case '\uE01A':
keyCode = "VK_NUMPAD0";
break;
case '\uE01B':
keyCode = "VK_NUMPAD1";
break;
case '\uE01C':
keyCode = "VK_NUMPAD2";
break;
case '\uE01D':
keyCode = "VK_NUMPAD3";
break;
case '\uE01E':
keyCode = "VK_NUMPAD4";
break;
case '\uE01F':
keyCode = "VK_NUMPAD5";
break;
case '\uE020':
keyCode = "VK_NUMPAD6";
break;
case '\uE021':
keyCode = "VK_NUMPAD7";
break;
case '\uE022':
keyCode = "VK_NUMPAD8";
break;
case '\uE023':
keyCode = "VK_NUMPAD9";
break;
case '\uE024':
keyCode = "VK_MULTIPLY";
break;
case '\uE025':
keyCode = "VK_ADD";
break;
case '\uE026':
keyCode = "VK_SEPARATOR";
break;
case '\uE027':
keyCode = "VK_SUBTRACT";
break;
case '\uE028':
keyCode = "VK_DECIMAL";
break;
case '\uE029':
keyCode = "VK_DIVIDE";
break;
case '\uE031':
keyCode = "VK_F1";
break;
case '\uE032':
keyCode = "VK_F2";
break;
case '\uE033':
keyCode = "VK_F3";
break;
case '\uE034':
keyCode = "VK_F4";
break;
case '\uE035':
keyCode = "VK_F5";
break;
case '\uE036':
keyCode = "VK_F6";
break;
case '\uE037':
keyCode = "VK_F7";
break;
case '\uE038':
keyCode = "VK_F8";
break;
case '\uE039':
keyCode = "VK_F9";
break;
case '\uE03A':
keyCode = "VK_F10";
break;
case '\uE03B':
keyCode = "VK_F11";
break;
case '\uE03C':
keyCode = "VK_F12";
break;
}
// generate modifier key event if needed, and continue
if (modifierEvent) {
keyEvent(doc, element, modifierEvent, keyCode, 0,
controlKey, shiftKey, altKey, metaKey, false);
continue;
hasShift = value.charAt(i) == upper;
utils.synthesizeKey(keyCode || value[i],
{ shiftKey: hasShift, ctrlKey: hasCtrl, altKey: hasAlt, metaKey: hasMeta },
document);
}
// otherwise, shift down if needed
var needsShift = false;
if (charCode) {
needsShift = /[A-Z\!\$\^\*\(\)\+\{\}\:\?\|~@#%&_"<>]/.test(c);
successCallback(command_id);
}
if (needsShift && !shiftKey) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
keyEvent(doc, element, "keydown", kCode, 0,
controlKey, true, altKey, metaKey, false);
shiftCount += 1;
else {
errorCallback("Element is not visible", 11, null, command_id);
}
// generate key[down/press/up] for key
var pressCode = keyCode;
if (charCode >= 32 && charCode < 127) {
pressCode = 0;
if (!needsShift && shiftKey && charCode > 32) {
// If typing a lowercase character key and the shiftKey is down, the
// charCode should be mapped to the shifted key value. This assumes
// a default 104 international keyboard layout.
if (charCode >= 97 && charCode <= 122) {
charCode = charCode + 65 - 97; // [a-z] -> [A-Z]
} else {
var mapFrom = '`1234567890-=[]\\;\',./';
var mapTo = '~!@#$%^&*()_+{}|:"<>?';
var value = String.fromCharCode(charCode).
replace(/([\[\\\.])/g, '\\$1');
var index = mapFrom.search(value);
if (index >= 0) {
charCode = mapTo.charCodeAt(index);
}
}
}
}
var accepted =
keyEvent(doc, element, "keydown", keyCode, 0,
controlKey, needsShift || shiftKey, altKey, metaKey, false);
keyEvent(doc, element, "keypress", pressCode, charCode,
controlKey, needsShift || shiftKey, altKey, metaKey, !accepted);
keyEvent(doc, element, "keyup", keyCode, 0,
controlKey, needsShift || shiftKey, altKey, metaKey, false);
// shift up if needed
if (needsShift && !shiftKey) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey, false, altKey, metaKey, false);
}
}
// exit cleanup: keyup active modifier keys
if (controlKey && releaseModifiers) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_CONTROL;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey = false, shiftKey, altKey, metaKey, false);
}
if (shiftKey && releaseModifiers) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_SHIFT;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey, shiftKey = false, altKey, metaKey, false);
}
if (altKey && releaseModifiers) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_ALT;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey, shiftKey, altKey = false, metaKey, false);
}
if (metaKey && releaseModifiers) {
var kCode = Components.interfaces.nsIDOMKeyEvent.DOM_VK_META;
keyEvent(doc, element, "keyup", kCode, 0,
controlKey, shiftKey, altKey, metaKey = false, false);
}
return {
shiftKey: shiftKey,
alt: altKey,
meta: metaKey,
control: controlKey
};
};
var keyEvent = function(doc, element, type, keyCode, charCode,
controlState, shiftState, altState, metaState,
shouldPreventDefault) {
var preventDefault = shouldPreventDefault == undefined ? false
: shouldPreventDefault;
var keyboardEvent = doc.createEvent("KeyEvents");
var currentView = doc.defaultView;
keyboardEvent.initKeyEvent(
type, // in DOMString typeArg,
true, // in boolean canBubbleArg
true, // in boolean cancelableArg
currentView, // in nsIDOMAbstractView viewArg
controlState, // in boolean ctrlKeyArg
altState, // in boolean altKeyArg
shiftState, // in boolean shiftKeyArg
metaState, // in boolean metaKeyArg
keyCode, // in unsigned long keyCodeArg
charCode); // in unsigned long charCodeArg
if (preventDefault) {
keyboardEvent.preventDefault();
}
var win = doc.defaultView;
var domUtil = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
return domUtil.dispatchDOMEventViaPresShell(element, keyboardEvent, true);
};