1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file.
4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
5513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvar BASE_KEYBOARD = {
6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  top: 0,
7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  left: 0,
8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  width: 1237,
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  height: 514
10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch};
11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
12513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvar BASE_INSTRUCTIONS = {
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  top: 194,
14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  left: 370,
15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  width: 498,
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  height: 112
17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch};
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvar LABEL_TO_KEY_TEXT = {
20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  alt: 'alt',
21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  backspace: 'backspace',
22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ctrl: 'ctrl',
23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  enter: 'enter',
24513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  esc: 'esc',
25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_arrow_down: 'down',
26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_arrow_left: 'left',
27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_arrow_right: 'right',
28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_arrow_up: 'up',
29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_back: 'back',
30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_backspace: 'backspace',
31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_brightness_down: 'bright down',
32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_brightness_up: 'bright up',
33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_enter: 'enter',
34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_forward: 'forward',
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  glyph_fullscreen: 'full screen',
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  glyph_ime: 'ime',
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  glyph_lock: 'lock',
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  glyph_overview: 'switch window',
39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_power: 'power',
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  glyph_right: 'right',
41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_reload: 'reload',
42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_search: 'search',
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  glyph_shift: 'shift',
44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_tab: 'tab',
45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_tools: 'tools',
46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_volume_down: 'vol. down',
47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_volume_mute: 'mute',
48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  glyph_volume_up: 'vol. up',
49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  shift: 'shift',
50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  tab: 'tab'
51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch};
52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
53513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvar MODIFIER_TO_CLASS = {
54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  'SHIFT': 'modifier-shift',
55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  'CTRL': 'modifier-ctrl',
56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  'ALT': 'modifier-alt'
57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch};
58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
59513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvar IDENTIFIER_TO_CLASS = {
60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  '2A': 'is-shift',
61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  '1D': 'is-ctrl',
62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  '38': 'is-alt'
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch};
64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
65201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvar keyboardOverlayId = 'en_US';
66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns layouts data.
69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
70513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getLayouts() {
71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return keyboardOverlayData['layouts'];
72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns shortcut data.
76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
77513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getShortcutData() {
78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return keyboardOverlayData['shortcut'];
79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
82201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * Returns the keyboard overlay ID.
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochfunction getKeyboardOverlayId() {
85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return keyboardOverlayId
86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns keyboard glyph data.
90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
91513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getKeyboardGlyphData() {
92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return keyboardOverlayData['keyboardGlyph'][getKeyboardOverlayId()];
93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Converts a single hex number to a character.
97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
98513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction hex2char(hex) {
99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!hex) {
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return '';
101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var result = '';
103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var n = parseInt(hex, 16);
104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (n <= 0xFFFF) {
105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    result += String.fromCharCode(n);
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else if (n <= 0x10FFFF) {
107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    n -= 0x10000;
108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    result += (String.fromCharCode(0xD800 | (n >> 10)) +
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch               String.fromCharCode(0xDC00 | (n & 0x3FF)));
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    console.error('hex2Char error: Code point out of range :' + hex);
112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return result;
114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns a list of modifiers from the key event.
118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
119513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getModifiers(e) {
120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!e) {
121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return [];
122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var isKeyDown = (e.type == 'keydown');
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var keyCodeToModifier = {
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    16: 'SHIFT',
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    17: 'CTRL',
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    18: 'ALT',
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    91: 'ALT', // left ALT pressed with SHIFT
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    92: 'ALT', // right ALT pressed with SHIFT
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var modifierWithKeyCode = keyCodeToModifier[e.keyCode];
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var isPressed = {'SHIFT': e.shiftKey, 'CTRL': e.ctrlKey, 'ALT': e.altKey};
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // if e.keyCode is one of Shift, Ctrl and Alt, isPressed should
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // be changed because the key currently pressed
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // does not affect the values of e.shiftKey, e.ctrlKey and e.altKey
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if(modifierWithKeyCode){
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    isPressed[modifierWithKeyCode] = isKeyDown;
138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // make the result array
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ['SHIFT', 'CTRL', 'ALT'].filter(
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      function(modifier) {
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return isPressed[modifier];
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }).sort();
144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns an ID of the key.
148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
149513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction keyId(identifier, i) {
150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return identifier + '-key-' + i;
151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns an ID of the text on the key.
155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
156513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction keyTextId(identifier, i) {
157513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return identifier + '-key-text-' + i;
158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
160513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns an ID of the shortcut text.
162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
163513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction shortcutTextId(identifier, i) {
164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return identifier + '-shortcut-text-' + i;
165513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns true if |list| contains |e|.
169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
170513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction contains(list, e) {
171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return list.indexOf(e) != -1;
172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns a list of the class names corresponding to the identifier and
176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * modifiers.
177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
178513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getKeyClasses(identifier, modifiers) {
179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var classes = ['keyboard-overlay-key'];
180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (var i = 0; i < modifiers.length; ++i) {
181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    classes.push(MODIFIER_TO_CLASS[modifiers[i]]);
182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if ((identifier == '2A' && contains(modifiers, 'SHIFT')) ||
185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      (identifier == '1D' && contains(modifiers, 'CTRL')) ||
186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      (identifier == '38' && contains(modifiers, 'ALT'))) {
187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    classes.push('pressed');
188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    classes.push(IDENTIFIER_TO_CLASS[identifier]);
189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return classes;
191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
192513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns true if a character is a ASCII character.
195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
196513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction isAscii(c) {
197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var charCode = c.charCodeAt(0);
198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return 0x00 <= charCode && charCode <= 0x7F;
199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns a label of the key.
203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
204513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getKeyLabel(keyData, modifiers) {
205513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!keyData) {
206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return '';
207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (keyData.label in LABEL_TO_KEY_TEXT) {
209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return LABEL_TO_KEY_TEXT[keyData.label];
210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
211513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var keyLabel = '';
212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (var j = 1; j <= 9; j++) {
213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var pos =  keyData['p' + j];
214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!pos) {
215513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      continue;
216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (LABEL_TO_KEY_TEXT[pos]) {
218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return LABEL_TO_KEY_TEXT[pos];
219513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
220513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    keyLabel = hex2char(pos);
221513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!keyLabel) {
222513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      continue;
223513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch     }
224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (isAscii(keyLabel) &&
225513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        getShortcutData()[getAction(keyLabel, modifiers)]) {
226513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      break;
227513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
228513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
229513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return keyLabel;
230513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
231513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
232513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
233513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns a normalized string used for a key of shortcutData.
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Examples:
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *   keycode: 'd', modifiers: ['CTRL', 'SHIFT'] => 'd<>CTRL<>SHIFT'
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *   keycode: 'alt', modifiers: ['ALT', 'SHIFT'] => 'ALT<>SHIFT'
238513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
239513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getAction(keycode, modifiers) {
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const SEPARATOR = '<>';
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (keycode.toUpperCase() in MODIFIER_TO_CLASS) {
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    keycode = keycode.toUpperCase();
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (keycode in modifiers) {
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return modifiers.join(SEPARATOR);
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var action = [keycode].concat(modifiers)
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      action.sort();
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return action.join(SEPARATOR);
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return [keycode].concat(modifiers).join(SEPARATOR);
252513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
255513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Returns a text which displayed on a key.
256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
257513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction getKeyTextValue(keyData) {
258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (LABEL_TO_KEY_TEXT[keyData.label]) {
259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return LABEL_TO_KEY_TEXT[keyData.label];
260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
261513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var chars = [];
263513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (var j = 1; j <= 9; ++j) {
264513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var pos = keyData['p' + j];
265513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (LABEL_TO_KEY_TEXT[pos]) {
266513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return LABEL_TO_KEY_TEXT[pos];
267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (pos && pos.length > 0) {
269513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      chars.push(hex2char(pos));
270513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
271513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
272513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return chars.join(' ');
273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
274513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Updates the whole keyboard.
277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction update(modifiers) {
279513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var instructions = document.getElementById('instructions');
280513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (modifiers.length == 0) {
281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    instructions.style.visibility = 'visible';
282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    instructions.style.visibility = 'hidden';
284513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
285513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
286513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var keyboardGlyphData = getKeyboardGlyphData();
287513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var shortcutData = getShortcutData();
288513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var layout = getLayouts()[keyboardGlyphData.layoutName];
289513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (var i = 0; i < layout.length; ++i) {
290513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var identifier = layout[i][0];
291513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var keyData = keyboardGlyphData.keys[identifier];
292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var classes = getKeyClasses(identifier, modifiers, keyData);
293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var keyLabel = getKeyLabel(keyData, modifiers);
294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var shortcutId = shortcutData[getAction(keyLabel, modifiers)];
295513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (shortcutId) {
296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      classes.push('is-shortcut');
297513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var key = document.getElementById(keyId(identifier, i));
300513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.className = classes.join(' ');
301513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
302513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!keyData) {
303513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      continue;
304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
306513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var keyText = document.getElementById(keyTextId(identifier, i));
307513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var keyTextValue = getKeyTextValue(keyData);
308513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (keyTextValue) {
309513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch       keyText.style.visibility = 'visible';
310513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    } else {
311513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch       keyText.style.visibility = 'hidden';
312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    keyText.textContent = keyTextValue;
314513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
315513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var shortcutText = document.getElementById(shortcutTextId(identifier, i));
316513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (shortcutId) {
317513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      shortcutText.style.visibility = 'visible';
318513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      shortcutText.textContent = templateData[shortcutId];
319513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    } else {
320513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      shortcutText.style.visibility = 'hidden';
321513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
322513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
323513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (keyData.format) {
324513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      var format = keyData.format;
325513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (format == 'left' || format == 'right') {
326513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        shortcutText.style.textAlign = format;
327513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        keyText.style.textAlign = format;
328513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      }
329513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
330513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
331513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
332513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
333513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * A callback function for onkeydown and onkeyup events.
335513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction handleKeyEvent(e){
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var modifiers = getModifiers(e);
338201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!getKeyboardOverlayId()) {
339201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
340201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  update(modifiers);
342513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
343513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
344513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
345513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Initializes the layout of the keys.
346513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
347513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction initLayout() {
348513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var layout = getLayouts()[getKeyboardGlyphData().layoutName];
349513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var keyboard = document.body;
350513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var minX = window.innerWidth;
351513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var maxX = 0;
352513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var minY = window.innerHeight;
353513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var maxY = 0;
354513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var multiplier = 1.38 * window.innerWidth / BASE_KEYBOARD.width;
355513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var keyMargin = 7;
356513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var offsetX = 10;
357513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var offsetY = 7;
358513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (var i = 0; i < layout.length; i++) {
359513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var array = layout[i];
360513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var identifier = array[0];
361513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var x = Math.round((array[1] + offsetX) * multiplier);
362513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var y = Math.round((array[2] + offsetY) * multiplier);
363513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var w = Math.round((array[3] - keyMargin) * multiplier);
364513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var h = Math.round((array[4] - keyMargin) * multiplier);
365513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
366513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var key = document.createElement('div');
367513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.id = keyId(identifier, i);
368513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.className = 'keyboard-overlay-key';
369513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.style.left = x + 'px';
370513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.style.top = y + 'px';
371513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.style.width = w + 'px';
372513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.style.height = h + 'px';
373513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var keyText = document.createElement('div');
375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    keyText.id = keyTextId(identifier, i);
376513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    keyText.className = 'keyboard-overlay-key-text';
377513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    keyText.style.visibility = 'hidden';
378513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.appendChild(keyText);
379513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
380513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    var shortcutText = document.createElement('div');
381513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    shortcutText.id = shortcutTextId(identifier, i);
382513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    shortcutText.className = 'keyboard-overlay-shortcut-text';
383513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    shortcutText.style.visilibity = 'hidden';
384513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    key.appendChild(shortcutText);
385513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    keyboard.appendChild(key);
386513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
387513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    minX = Math.min(minX, x);
388513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    maxX = Math.max(maxX, x + w);
389513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    minY = Math.min(minY, y);
390513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    maxY = Math.max(maxY, y + h);
391513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
392513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
393513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var width = maxX - minX + 1;
394513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  var height = maxY - minY + 1;
395513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  keyboard.style.width = (width + 2 * (minX + 1)) + 'px';
396513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  keyboard.style.height = (height + 2 * (minY + 1)) + 'px';
397513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  var instructions = document.createElement('div');
399513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructions.id = 'instructions';
400513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructions.className = 'keyboard-overlay-instructions';
401513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructions.style.left = ((BASE_INSTRUCTIONS.left - BASE_KEYBOARD.left) *
402513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                             width / BASE_KEYBOARD.width + minX) + 'px';
403513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructions.style.top = ((BASE_INSTRUCTIONS.top - BASE_KEYBOARD.top) *
404513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                            height / BASE_KEYBOARD.height + minY) + 'px';
405513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructions.style.width = (width * BASE_INSTRUCTIONS.width /
406513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              BASE_KEYBOARD.width) + 'px';
407513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructions.style.height = (height * BASE_INSTRUCTIONS.height /
408513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                               BASE_KEYBOARD.height) + 'px';
409513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  var instructionsText = document.createElement('div');
411513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructionsText.id = 'instructions-text';
412513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructionsText.className = 'keyboard-overlay-instructions-text';
413513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructionsText.innerHTML = templateData.keyboardOverlayInstructions;
414513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  instructions.appendChild(instructionsText);
41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  var instructionsHideText = document.createElement('div');
41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  instructionsHideText.id = 'instructions-hide-text';
41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  instructionsHideText.className = 'keyboard-overlay-instructions-hide-text';
41872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  instructionsHideText.innerHTML = templateData.keyboardOverlayInstructionsHide;
41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  instructions.appendChild(instructionsHideText);
420513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  keyboard.appendChild(instructions);
421513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
422513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
423513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch/**
424513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * A callback function for the onload event of the body element.
425513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */
426513209b27ff55e2841eac0e4120199c23acce758Ben Murdochfunction init() {
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  document.addEventListener('keydown', handleKeyEvent);
428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  document.addEventListener('keyup', handleKeyEvent);
429201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  chrome.send('getKeyboardOverlayId');
430201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
431201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
432201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch/**
433201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * Initializes the global keyboad overlay ID and the layout of keys.
434201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * Called after sending the 'getKeyboardOverlayId' message.
435201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch */
436201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochfunction initKeyboardOverlayId(overlayId) {
43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Libcros returns an empty string when it cannot find the keyboard overlay ID
43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // corresponding to the current input method.
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // In such a case, fallback to the default ID (en_US).
44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (overlayId) {
44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    keyboardOverlayId = overlayId;
44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
443201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  while(document.body.firstChild) {
444201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    document.body.removeChild(document.body.firstChild);
445201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
446513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  initLayout();
447513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  update();
448513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
449513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
450513209b27ff55e2841eac0e4120199c23acce758Ben Murdochdocument.addEventListener('DOMContentLoaded', init);
451