Home | History | Annotate | Download | only in elements
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 (function() {
      6 
      7   // Flag values for ctrl, alt and shift as defined by EventFlags
      8   // in "event_constants.h".
      9   // @enum {number}
     10   var Modifier = {
     11     NONE: 0,
     12     ALT: 8,
     13     CONTROL: 4,
     14     SHIFT: 2
     15   }
     16 
     17   // Each virtual key event is assigned a unique ID.
     18   var nextRequestID = 0;
     19 
     20   // Keycodes have been deprecated in the KeyEvent specification, but are
     21   // nonetheless required to support legacy web content.  The Keycodes in the
     22   // following table are based on subset of US-EN 101-key keyboard. These
     23   // codes are used in the absence of explicit keycodes for kb-key and
     24   // kb-keysequence elements. Keyboard layout authors may explicitly set the
     25   // keyCode attribute for kb-key or kb-keysequence elements to refer to
     26   // indices in this table in order to emulate a physical keyboard with an
     27   // alternate layout.  Not all keys on a virtual keyboard are required to
     28   // have keyCodes. The shiftModifier specifies whether to always include or
     29   // exclude the shift modifer when sending key events for this key. If it's
     30   // undefined, it will defer to state of the keyboard.
     31   // TODO(rsadam): Correctly propagate shutdown keycode. This is currently
     32   // ignored due to chromoting (crbug/146609)
     33   var keyCodes = {
     34     '\b': {keyCode: 0x08, keyName: 'Backspace', shiftModifier: false},
     35     '\t': {keyCode: 0x09, keyName: 'Tab', shiftModifier: false},
     36     '\n': {keyCode: 0x0D, keyName: 'Enter', shiftModifier: false},
     37     'Esc': {keyCode: 0x1B, keyName: 'Escape', shiftModifier: false},
     38     ' ': {keyCode: 0x20, keyName: 'Space', shiftModifier: false},
     39     'Arrow-Left': {keyCode: 0x25, keyName: 'ArrowLeft',
     40         shiftModifier: undefined},
     41     'Arrow-Up': {keyCode: 0x26, keyName: 'ArrowUp', shiftModifier: undefined},
     42     'Arrow-Right': {keyCode: 0x27, keyName: 'ArrowRight',
     43         shiftModifier: undefined},
     44     'Arrow-Down': {keyCode: 0x28, keyName: 'ArrowDown',
     45         shiftModifier: undefined},
     46     '0': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: false},
     47     ')': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: true},
     48     '1': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: false},
     49     '!': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: true},
     50     '2': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: false},
     51     '@': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: true},
     52     '3': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: false},
     53     '#': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: true},
     54     '4': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: false},
     55     '$': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: true},
     56     '5': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: false},
     57     '%': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: true},
     58     '6': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: false},
     59     '^': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: true},
     60     '7': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: false},
     61     '&': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: true},
     62     '8': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: false},
     63     '*': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: true},
     64     '9': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: false},
     65     '(': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: true},
     66     'a': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: false},
     67     'A': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: true},
     68     'b': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: false},
     69     'B': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: true},
     70     'c': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: false},
     71     'C': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: true},
     72     'd': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: false},
     73     'D': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: true},
     74     'e': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: false},
     75     'E': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: true},
     76     'f': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: false},
     77     'F': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: true},
     78     'g': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: false},
     79     'G': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: true},
     80     'h': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: false},
     81     'H': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: true},
     82     'i': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: false},
     83     'I': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: true},
     84     'j': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: false},
     85     'J': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: true},
     86     'k': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: false},
     87     'K': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: true},
     88     'l': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: false},
     89     'L': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: true},
     90     'm': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: false},
     91     'M': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: true},
     92     'n': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: false},
     93     'N': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: true},
     94     'o': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: false},
     95     'O': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: true},
     96     'p': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: false},
     97     'P': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: true},
     98     'q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: false},
     99     'Q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: true},
    100     'r': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: false},
    101     'R': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: true},
    102     's': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: false},
    103     'S': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: true},
    104     't': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: false},
    105     'T': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: true},
    106     'u': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: false},
    107     'U': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: true},
    108     'v': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: false},
    109     'V': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: true},
    110     'w': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: false},
    111     'W': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: true},
    112     'x': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: false},
    113     'X': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: true},
    114     'y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: false},
    115     'Y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: true},
    116     'z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: false},
    117     'Z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: true},
    118     'Fullscreen': {keyCode: 0x7A, shiftModifier: false},
    119     'Shutdown': {keyCode: 0x98, shiftModifier: false},
    120     'Back': {keyCode: 0xA6, shiftModifier: false},
    121     'Forward': {keyCode: 0xA7, shiftModifier: false},
    122     'Reload': {keyCode: 0xA8, shiftModifier: false},
    123     'Search': {keyCode: 0xAA, shiftModifier: false},
    124     'Mute': {keyCode: 0xAD, keyName: 'VolumeMute', shiftModifier: false},
    125     'Volume-Down': {keyCode: 0xAE, keyName: 'VolumeDown',
    126         shiftModifier: false},
    127     'Volume-Up': {keyCode: 0xAF, keyName: 'VolumeUp', shiftModifier: false},
    128     'Change-Window': {keyCode: 0xB6, shiftModifier: false},
    129     ';': {keyCode: 0xBA, keyName: 'Semicolon', shiftModifier: false},
    130     ':': {keyCode: 0xBA, keyName: 'Semicolon',shiftModifier: true},
    131     '=': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: false},
    132     '+': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: true},
    133     ',': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: false},
    134     '<': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: true},
    135     '-': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: false},
    136     '_': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: true},
    137     '.': {keyCode: 0xBE, keyName: 'Period', shiftModifier: false},
    138     '>': {keyCode: 0xBE, keyName: 'Period', shiftModifier: true},
    139     '/': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: false},
    140     '?': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: true},
    141     '`': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: false},
    142     '~': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: true},
    143     'Brightness-Down': {keyCode: 0xD8, keyName: 'BrightnessDown',
    144         shiftModifier: false},
    145     'Brightness-Up': {keyCode: 0xD9, keyName: 'BrightnessUp',
    146         shiftModifier: false},
    147     '[': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: false},
    148     '{': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: true},
    149     '\\': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: false},
    150     '|': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: true},
    151     ']': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: false},
    152     '}': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: true},
    153     '\'': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: false},
    154     '"': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: true},
    155   };
    156 
    157   Polymer('kb-key-codes', {
    158     /**
    159      * Retrieves the keyCode and status of the shift modifier.
    160      * @param {string} id ID of an entry in the code table.
    161      * @return {keyCode: numeric, shiftModifier: boolean}
    162      */
    163     GetKeyCodeAndModifiers: function(id) {
    164       var entry = keyCodes[id];
    165       if (entry) {
    166         return {
    167           keyCode: entry.keyCode,
    168           keyName: entry.keyName || 'Unidentified',
    169           shiftModifier: entry.shiftModifier
    170         };
    171       }
    172       if (id.length != 1)
    173         return;
    174       // Special case of accented characters.
    175       return {
    176         keyCode: 0,
    177         keyName: 'Unidentified',
    178         shiftModifier: false
    179       };
    180     },
    181 
    182    /**
    183     * Creates a virtual key event for use with the keyboard extension API.
    184     * See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent.
    185     * @param {Object} detail Attribute of the key being pressed or released.
    186     * @param {string} type The type of key event, which may be keydown
    187     *     or keyup.
    188     * @return {?KeyboardEvent} A KeyboardEvent object, or undefined on
    189     *     failure.
    190     */
    191    createVirtualKeyEvent: function(detail, type) {
    192      var char = detail.char;
    193      var keyCode = detail.keyCode;
    194      var keyName = detail.keyName;
    195      // The shift modifier is handled specially. Some charactares like '+'
    196      // {keyCode: 0xBB, shiftModifier: true}, are available on non-upper
    197      // keysets, and so we rely on caching the correct shiftModifier. If
    198      // the cached value of the shiftModifier is undefined, we defer to
    199      // the shiftModifier in the detail.
    200      var shiftModifier = detail.shiftModifier;
    201      if (keyCode == undefined || keyName == undefined) {
    202        var state = this.GetKeyCodeAndModifiers(char);
    203        if (state) {
    204          keyCode = keyCode || state.keyCode;
    205          keyName = keyName || state.keyName;
    206          shiftModifier = (state.shiftModifier == undefined) ?
    207              shiftModifier : state.shiftModifier;
    208        } else {
    209          // Keycode not defined.
    210          return;
    211        }
    212      }
    213      var modifiers = Modifier.NONE;
    214      modifiers = shiftModifier ? modifiers | Modifier.SHIFT : modifiers;
    215      modifiers = detail.controlModifier ?
    216          modifiers | Modifier.CONTROL : modifiers;
    217      modifiers = detail.altModifier ? modifiers | Modifier.ALT : modifiers;
    218      return {
    219        type: type,
    220        charValue: char.charCodeAt(0),
    221        keyCode: keyCode,
    222        keyName: keyName,
    223        modifiers: modifiers
    224      };
    225    },
    226   });
    227 })();
    228