зеркало из https://github.com/mozilla/gecko-dev.git
268 строки
6.8 KiB
JavaScript
268 строки
6.8 KiB
JavaScript
// ***********************************
|
|
// * Global variables
|
|
// ***********************************
|
|
const kIsWin = navigator.platform.indexOf("Win") == 0;
|
|
|
|
// Bit value for the keyboard events
|
|
const kKeyDown = 0x01;
|
|
const kKeyPress = 0x02;
|
|
const kKeyUp = 0x04;
|
|
|
|
// Pair the event name to its bit value
|
|
const kEventCode = {
|
|
'keydown' : kKeyDown,
|
|
'keypress' : kKeyPress,
|
|
'keyup' : kKeyUp
|
|
};
|
|
|
|
// Holding the current test case's infomation:
|
|
var gCurrentTest;
|
|
|
|
// The current used input method of this test
|
|
var gInputMethod;
|
|
|
|
// ***********************************
|
|
// * Utilities
|
|
// ***********************************
|
|
function addKeyEventListeners(eventTarget, handler)
|
|
{
|
|
Object.keys(kEventCode).forEach(function(type) {
|
|
eventTarget.addEventListener(type, handler);
|
|
});
|
|
}
|
|
|
|
function eventToCode(type)
|
|
{
|
|
return kEventCode[type];
|
|
}
|
|
|
|
// To test key events that will be generated by input method here,
|
|
// we need to convert alphabets to native key code.
|
|
// (Our input method for testing will handle alphabets)
|
|
// On the other hand, to test key events that will not be generated by IME,
|
|
// we use 0-9 for such case in our testing.
|
|
function guessNativeKeyCode(key)
|
|
{
|
|
let nativeCodeName = (kIsWin)? 'WIN_VK_' : 'MAC_VK_ANSI_';
|
|
if (/^[A-Z]$/.test(key)) {
|
|
nativeCodeName += key;
|
|
} else if (/^[a-z]$/.test(key)) {
|
|
nativeCodeName += key.toUpperCase();
|
|
} else if (/^[0-9]$/.test(key)) {
|
|
nativeCodeName += key.toString();
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
return eval(nativeCodeName);
|
|
}
|
|
|
|
// ***********************************
|
|
// * Frame loader and frame scripts
|
|
// ***********************************
|
|
function frameScript()
|
|
{
|
|
function handler(e) {
|
|
sendAsyncMessage("forwardevent", { type: e.type, key: e.key });
|
|
}
|
|
function notifyFinish(e) {
|
|
if (e.type != 'keyup') return;
|
|
sendAsyncMessage("finish");
|
|
}
|
|
let input = content.document.getElementById('test-input');
|
|
input.addEventListener('keydown', handler);
|
|
input.addEventListener('keypress', handler);
|
|
input.addEventListener('keyup', handler);
|
|
input.addEventListener('keyup', notifyFinish);
|
|
}
|
|
|
|
function loadTestFrame(goNext) {
|
|
let iframe = document.createElement('iframe');
|
|
iframe.src = 'file_test_empty_app.html';
|
|
iframe.setAttribute('mozbrowser', true);
|
|
|
|
iframe.addEventListener("mozbrowserloadend", function onloadend() {
|
|
iframe.removeEventListener("mozbrowserloadend", onloadend);
|
|
iframe.focus();
|
|
var mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
|
mm.addMessageListener("forwardevent", function(msg) {
|
|
inputtextEventReceiver(msg.json);
|
|
});
|
|
mm.addMessageListener("finish", function(msg) {
|
|
if(goNext) {
|
|
goNext();
|
|
}
|
|
});
|
|
mm.loadFrameScript("data:,(" + frameScript.toString() + ")();", false);
|
|
return;
|
|
});
|
|
|
|
document.body.appendChild(iframe);
|
|
}
|
|
|
|
// ***********************************
|
|
// * Event firer and listeners
|
|
// ***********************************
|
|
function fireEvent(callback)
|
|
{
|
|
let key = gCurrentTest.key;
|
|
synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, guessNativeKeyCode(key), {},
|
|
key, key, (callback) ? callback : null);
|
|
}
|
|
|
|
function hardwareEventReceiver(evt)
|
|
{
|
|
if (!gCurrentTest) {
|
|
return;
|
|
}
|
|
gCurrentTest.hardwareinput.receivedEvents |= eventToCode(evt.type);
|
|
gCurrentTest.hardwareinput.receivedKeys += evt.key;
|
|
}
|
|
|
|
function inputtextEventReceiver(evt)
|
|
{
|
|
if (!gCurrentTest) {
|
|
return;
|
|
}
|
|
gCurrentTest.inputtext.receivedEvents |= eventToCode(evt.type);
|
|
gCurrentTest.inputtext.receivedKeys += evt.key;
|
|
}
|
|
|
|
// ***********************************
|
|
// * Event verifier
|
|
// ***********************************
|
|
function verifyResults(test)
|
|
{
|
|
// Verify results received from inputcontent.hardwareinput
|
|
is(test.hardwareinput.receivedEvents,
|
|
test.hardwareinput.expectedEvents,
|
|
"received events from inputcontent.hardwareinput are wrong");
|
|
|
|
is(test.hardwareinput.receivedKeys,
|
|
test.hardwareinput.expectedKeys,
|
|
"received keys from inputcontent.hardwareinput are wrong");
|
|
|
|
// Verify results received from actual input text
|
|
is(test.inputtext.receivedEvents,
|
|
test.inputtext.expectedEvents,
|
|
"received events from input text are wrong");
|
|
|
|
is(test.inputtext.receivedKeys,
|
|
test.inputtext.expectedKeys,
|
|
"received keys from input text are wrong");
|
|
}
|
|
|
|
function areEventsSame(test)
|
|
{
|
|
return (test.hardwareinput.receivedEvents ==
|
|
test.hardwareinput.expectedEvents) &&
|
|
(test.inputtext.receivedEvents ==
|
|
test.inputtext.expectedEvents);
|
|
}
|
|
|
|
// ***********************************
|
|
// * Input Method
|
|
// ***********************************
|
|
// The method input used in this test
|
|
// only handles alphabets
|
|
function InputMethod(inputContext)
|
|
{
|
|
this._inputContext = inputContext;
|
|
this.init();
|
|
}
|
|
|
|
InputMethod.prototype = {
|
|
init: function im_init() {
|
|
this._setKepMap();
|
|
},
|
|
|
|
handler: function im_handler(evt) {
|
|
// Ignore the key if the event is defaultPrevented
|
|
if (evt.defaultPrevented) {
|
|
return;
|
|
}
|
|
|
|
// Finish if there is no _inputContext
|
|
if (!this._inputContext) {
|
|
return;
|
|
}
|
|
|
|
// Generate the keyDict for inputcontext.keydown/keyup
|
|
let keyDict = this._generateKeyDict(evt);
|
|
|
|
// Ignore the key if IME doesn't want to handle it
|
|
if (!keyDict) {
|
|
return;
|
|
}
|
|
|
|
// Call preventDefault if the key will be handled.
|
|
evt.preventDefault();
|
|
|
|
// Call inputcontext.keydown/keyup
|
|
this._inputContext[evt.type](keyDict);
|
|
},
|
|
|
|
mapKey: function im_keymapping(key) {
|
|
if (!this._mappingTable) {
|
|
return;
|
|
}
|
|
return this._mappingTable[key];
|
|
},
|
|
|
|
_setKepMap: function im_setKeyMap() {
|
|
// A table to map characters:
|
|
// {
|
|
// 'A': 'B'
|
|
// 'a': 'b'
|
|
// 'B': 'C'
|
|
// 'b': 'c'
|
|
// ..
|
|
// ..
|
|
// 'Z': 'A',
|
|
// 'z': 'a',
|
|
// }
|
|
this._mappingTable = {};
|
|
|
|
let rotation = 1;
|
|
|
|
for (let i = 0 ; i < 26 ; i++) {
|
|
// Convert 'A' to 'B', 'B' to 'C', ..., 'Z' to 'A'
|
|
this._mappingTable[String.fromCharCode(i + 'A'.charCodeAt(0))] =
|
|
String.fromCharCode((i+rotation)%26 + 'A'.charCodeAt(0));
|
|
|
|
// Convert 'a' to 'b', 'b' to 'c', ..., 'z' to 'a'
|
|
this._mappingTable[String.fromCharCode(i + 'a'.charCodeAt(0))] =
|
|
String.fromCharCode((i+rotation)%26 + 'a'.charCodeAt(0));
|
|
}
|
|
},
|
|
|
|
_generateKeyDict: function im_generateKeyDict(evt) {
|
|
|
|
let mappedKey = this.mapKey(evt.key);
|
|
|
|
if (!mappedKey) {
|
|
return;
|
|
}
|
|
|
|
let keyDict = {
|
|
key: mappedKey,
|
|
code: this._guessCodeFromKey(mappedKey),
|
|
repeat: evt.repeat,
|
|
};
|
|
|
|
return keyDict;
|
|
},
|
|
|
|
_guessCodeFromKey: function im_guessCodeFromKey(key) {
|
|
if (/^[A-Z]$/.test(key)) {
|
|
return "Key" + key;
|
|
} else if (/^[a-z]$/.test(key)) {
|
|
return "Key" + key.toUpperCase();
|
|
} else if (/^[0-9]$/.test(key)) {
|
|
return "Digit" + key.toString();
|
|
} else {
|
|
return 0;
|
|
}
|
|
},
|
|
};
|