blob: 103fe4448e45ab64e94a3751a99e529c02e8316f [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function() {
// Flag values for ctrl, alt and shift as defined by EventFlags
// in "event_constants.h".
// @enum {number}
var Modifier = {
NONE: 0,
ALT: 8,
CONTROL: 4,
SHIFT: 2
}
// Each virtual key event is assigned a unique ID.
var nextRequestID = 0;
// Keycodes have been deprecated in the KeyEvent specification, but are
// nonetheless required to support legacy web content. The Keycodes in the
// following table are based on subset of US-EN 101-key keyboard. These
// codes are used in the absence of explicit keycodes for kb-key and
// kb-keysequence elements. Keyboard layout authors may explicitly set the
// keyCode attribute for kb-key or kb-keysequence elements to refer to
// indices in this table in order to emulate a physical keyboard with an
// alternate layout. Not all keys on a virtual keyboard are required to
// have keyCodes. The shiftModifier specifies whether to always include or
// exclude the shift modifer when sending key events for this key. If it's
// undefined, it will defer to state of the keyboard.
// TODO(rsadam): Correctly propagate shutdown keycode. This is currently
// ignored due to chromoting (crbug/146609)
var keyCodes = {
'\b': {keyCode: 0x08, keyName: 'Backspace', shiftModifier: false},
'\t': {keyCode: 0x09, keyName: 'Tab', shiftModifier: false},
'\n': {keyCode: 0x0D, keyName: 'Enter', shiftModifier: false},
'Esc': {keyCode: 0x1B, keyName: 'Escape', shiftModifier: false},
' ': {keyCode: 0x20, keyName: 'Space', shiftModifier: false},
'Arrow-Left': {keyCode: 0x25, keyName: 'ArrowLeft',
shiftModifier: undefined},
'Arrow-Up': {keyCode: 0x26, keyName: 'ArrowUp', shiftModifier: undefined},
'Arrow-Right': {keyCode: 0x27, keyName: 'ArrowRight',
shiftModifier: undefined},
'Arrow-Down': {keyCode: 0x28, keyName: 'ArrowDown',
shiftModifier: undefined},
'0': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: false},
')': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: true},
'1': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: false},
'!': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: true},
'2': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: false},
'@': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: true},
'3': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: false},
'#': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: true},
'4': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: false},
'$': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: true},
'5': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: false},
'%': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: true},
'6': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: false},
'^': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: true},
'7': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: false},
'&': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: true},
'8': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: false},
'*': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: true},
'9': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: false},
'(': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: true},
'a': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: false},
'A': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: true},
'b': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: false},
'B': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: true},
'c': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: false},
'C': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: true},
'd': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: false},
'D': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: true},
'e': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: false},
'E': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: true},
'f': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: false},
'F': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: true},
'g': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: false},
'G': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: true},
'h': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: false},
'H': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: true},
'i': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: false},
'I': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: true},
'j': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: false},
'J': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: true},
'k': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: false},
'K': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: true},
'l': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: false},
'L': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: true},
'm': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: false},
'M': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: true},
'n': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: false},
'N': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: true},
'o': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: false},
'O': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: true},
'p': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: false},
'P': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: true},
'q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: false},
'Q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: true},
'r': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: false},
'R': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: true},
's': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: false},
'S': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: true},
't': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: false},
'T': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: true},
'u': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: false},
'U': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: true},
'v': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: false},
'V': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: true},
'w': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: false},
'W': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: true},
'x': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: false},
'X': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: true},
'y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: false},
'Y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: true},
'z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: false},
'Z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: true},
'Fullscreen': {keyCode: 0x7A, shiftModifier: false},
'Shutdown': {keyCode: 0x98, shiftModifier: false},
'Back': {keyCode: 0xA6, shiftModifier: false},
'Forward': {keyCode: 0xA7, shiftModifier: false},
'Reload': {keyCode: 0xA8, shiftModifier: false},
'Search': {keyCode: 0xAA, shiftModifier: false},
'Mute': {keyCode: 0xAD, keyName: 'VolumeMute', shiftModifier: false},
'Volume-Down': {keyCode: 0xAE, keyName: 'VolumeDown',
shiftModifier: false},
'Volume-Up': {keyCode: 0xAF, keyName: 'VolumeUp', shiftModifier: false},
'Change-Window': {keyCode: 0xB6, shiftModifier: false},
';': {keyCode: 0xBA, keyName: 'Semicolon', shiftModifier: false},
':': {keyCode: 0xBA, keyName: 'Semicolon',shiftModifier: true},
'=': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: false},
'+': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: true},
',': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: false},
'<': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: true},
'-': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: false},
'_': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: true},
'.': {keyCode: 0xBE, keyName: 'Period', shiftModifier: false},
'>': {keyCode: 0xBE, keyName: 'Period', shiftModifier: true},
'/': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: false},
'?': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: true},
'`': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: false},
'~': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: true},
'Brightness-Down': {keyCode: 0xD8, keyName: 'BrightnessDown',
shiftModifier: false},
'Brightness-Up': {keyCode: 0xD9, keyName: 'BrightnessUp',
shiftModifier: false},
'[': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: false},
'{': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: true},
'\\': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: false},
'|': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: true},
']': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: false},
'}': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: true},
'\'': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: false},
'"': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: true},
};
Polymer('kb-key-codes', {
/**
* Retrieves the keyCode and status of the shift modifier.
* @param {string} id ID of an entry in the code table.
* @return {keyCode: numeric, shiftModifier: boolean}
*/
GetKeyCodeAndModifiers: function(id) {
var entry = keyCodes[id];
if (entry) {
return {
keyCode: entry.keyCode,
keyName: entry.keyName || 'Unidentified',
shiftModifier: entry.shiftModifier
};
}
if (id.length != 1)
return;
// Special case of accented characters.
return {
keyCode: 0,
keyName: 'Unidentified',
shiftModifier: false
};
},
/**
* Creates a virtual key event for use with the keyboard extension API.
* See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent.
* @param {Object} detail Attribute of the key being pressed or released.
* @param {string} type The type of key event, which may be keydown
* or keyup.
* @return {?KeyboardEvent} A KeyboardEvent object, or undefined on
* failure.
*/
createVirtualKeyEvent: function(detail, type) {
var char = detail.char;
var keyCode = detail.keyCode;
var keyName = detail.keyName;
// The shift modifier is handled specially. Some charactares like '+'
// {keyCode: 0xBB, shiftModifier: true}, are available on non-upper
// keysets, and so we rely on caching the correct shiftModifier. If
// the cached value of the shiftModifier is undefined, we defer to
// the shiftModifier in the detail.
var shiftModifier = detail.shiftModifier;
if (keyCode == undefined || keyName == undefined) {
var state = this.GetKeyCodeAndModifiers(char);
if (state) {
keyCode = keyCode || state.keyCode;
keyName = keyName || state.keyName;
shiftModifier = (state.shiftModifier == undefined) ?
shiftModifier : state.shiftModifier;
} else {
// Keycode not defined.
return;
}
}
var modifiers = Modifier.NONE;
modifiers = shiftModifier ? modifiers | Modifier.SHIFT : modifiers;
modifiers = detail.controlModifier ?
modifiers | Modifier.CONTROL : modifiers;
modifiers = detail.altModifier ? modifiers | Modifier.ALT : modifiers;
return {
type: type,
charValue: char.charCodeAt(0),
keyCode: keyCode,
keyName: keyName,
modifiers: modifiers
};
},
});
})();