Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: chrome/browser/resources/keyboard_overlay.js

Issue 8687012: Moved ChromeOS-specific resources from chrome/browser/resources to chrome/browser/resources/chrom... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <include src="keyboard_overlay_data.js"/>
6 <include src="keyboard_overlay_accessibility_helper.js"/>
7
8 var BASE_KEYBOARD = {
9 top: 0,
10 left: 0,
11 width: 1237,
12 height: 514
13 };
14
15 var BASE_INSTRUCTIONS = {
16 top: 194,
17 left: 370,
18 width: 498,
19 height: 112
20 };
21
22 var MODIFIER_TO_CLASS = {
23 'SHIFT': 'modifier-shift',
24 'CTRL': 'modifier-ctrl',
25 'ALT': 'modifier-alt'
26 };
27
28 var IDENTIFIER_TO_CLASS = {
29 '2A': 'is-shift',
30 '1D': 'is-ctrl',
31 '38': 'is-alt'
32 };
33
34 var LABEL_TO_IDENTIFIER = {
35 'search': 'E0 5B',
36 'ctrl': '1D',
37 'alt': '38',
38 'caps lock': '3A',
39 'disabled': 'DISABLED'
40 }
41
42 var keyboardOverlayId = 'en_US';
43 var identifierMap = {};
44
45 /**
46 * Returns layouts data.
47 */
48 function getLayouts() {
49 return keyboardOverlayData['layouts'];
50 }
51
52 /**
53 * Returns shortcut data.
54 */
55 function getShortcutData() {
56 return keyboardOverlayData['shortcut'];
57 }
58
59 /**
60 * Returns the keyboard overlay ID.
61 */
62 function getKeyboardOverlayId() {
63 return keyboardOverlayId;
64 }
65
66 /**
67 * Returns keyboard glyph data.
68 */
69 function getKeyboardGlyphData() {
70 return keyboardOverlayData['keyboardGlyph'][getKeyboardOverlayId()];
71 }
72
73 /**
74 * Converts a single hex number to a character.
75 */
76 function hex2char(hex) {
77 if (!hex) {
78 return '';
79 }
80 var result = '';
81 var n = parseInt(hex, 16);
82 if (n <= 0xFFFF) {
83 result += String.fromCharCode(n);
84 } else if (n <= 0x10FFFF) {
85 n -= 0x10000;
86 result += (String.fromCharCode(0xD800 | (n >> 10)) +
87 String.fromCharCode(0xDC00 | (n & 0x3FF)));
88 } else {
89 console.error('hex2Char error: Code point out of range :' + hex);
90 }
91 return result;
92 }
93
94 /**
95 * Returns a list of modifiers from the key event.
96 */
97 function getModifiers(e) {
98 if (!e) {
99 return [];
100 }
101 var isKeyDown = (e.type == 'keydown');
102 var keyCodeToModifier = {
103 16: 'SHIFT',
104 17: 'CTRL',
105 18: 'ALT',
106 91: 'ALT', // left ALT pressed with SHIFT
107 92: 'ALT', // right ALT pressed with SHIFT
108 };
109 var modifierWithKeyCode = keyCodeToModifier[e.keyCode];
110 var isPressed = {'SHIFT': e.shiftKey, 'CTRL': e.ctrlKey, 'ALT': e.altKey};
111 // if e.keyCode is one of Shift, Ctrl and Alt, isPressed should
112 // be changed because the key currently pressed
113 // does not affect the values of e.shiftKey, e.ctrlKey and e.altKey
114 if(modifierWithKeyCode){
115 isPressed[modifierWithKeyCode] = isKeyDown;
116 }
117 // make the result array
118 return ['SHIFT', 'CTRL', 'ALT'].filter(
119 function(modifier) {
120 return isPressed[modifier];
121 }).sort();
122 }
123
124 /**
125 * Returns an ID of the key.
126 */
127 function keyId(identifier, i) {
128 return identifier + '-key-' + i;
129 }
130
131 /**
132 * Returns an ID of the text on the key.
133 */
134 function keyTextId(identifier, i) {
135 return identifier + '-key-text-' + i;
136 }
137
138 /**
139 * Returns an ID of the shortcut text.
140 */
141 function shortcutTextId(identifier, i) {
142 return identifier + '-shortcut-text-' + i;
143 }
144
145 /**
146 * Returns true if |list| contains |e|.
147 */
148 function contains(list, e) {
149 return list.indexOf(e) != -1;
150 }
151
152 /**
153 * Returns a list of the class names corresponding to the identifier and
154 * modifiers.
155 */
156 function getKeyClasses(identifier, modifiers) {
157 var classes = ['keyboard-overlay-key'];
158 for (var i = 0; i < modifiers.length; ++i) {
159 classes.push(MODIFIER_TO_CLASS[modifiers[i]]);
160 }
161
162 if ((identifier == '2A' && contains(modifiers, 'SHIFT')) ||
163 (identifier == '1D' && contains(modifiers, 'CTRL')) ||
164 (identifier == '38' && contains(modifiers, 'ALT'))) {
165 classes.push('pressed');
166 classes.push(IDENTIFIER_TO_CLASS[identifier]);
167 }
168 return classes;
169 }
170
171 /**
172 * Returns true if a character is a ASCII character.
173 */
174 function isAscii(c) {
175 var charCode = c.charCodeAt(0);
176 return 0x00 <= charCode && charCode <= 0x7F;
177 }
178
179 /**
180 * Returns a remapped identiifer based on the preference.
181 */
182 function remapIdentifier(identifier) {
183 return identifierMap[identifier] || identifier;
184 }
185
186 /**
187 * Returns a label of the key.
188 */
189 function getKeyLabel(keyData, modifiers) {
190 if (!keyData) {
191 return '';
192 }
193 if (keyData.label) {
194 return keyData.label;
195 }
196 var keyLabel = '';
197 for (var j = 1; j <= 9; j++) {
198 var pos = keyData['p' + j];
199 if (!pos) {
200 continue;
201 }
202 keyLabel = hex2char(pos);
203 if (!keyLabel) {
204 continue;
205 }
206 if (isAscii(keyLabel) &&
207 getShortcutData()[getAction(keyLabel, modifiers)]) {
208 break;
209 }
210 }
211 return keyLabel;
212 }
213
214 /**
215 * Returns a normalized string used for a key of shortcutData.
216 *
217 * Examples:
218 * keycode: 'd', modifiers: ['CTRL', 'SHIFT'] => 'd<>CTRL<>SHIFT'
219 * keycode: 'alt', modifiers: ['ALT', 'SHIFT'] => 'ALT<>SHIFT'
220 */
221 function getAction(keycode, modifiers) {
222 const SEPARATOR = '<>';
223 if (keycode.toUpperCase() in MODIFIER_TO_CLASS) {
224 keycode = keycode.toUpperCase();
225 if (keycode in modifiers) {
226 return modifiers.join(SEPARATOR);
227 } else {
228 var action = [keycode].concat(modifiers)
229 action.sort();
230 return action.join(SEPARATOR);
231 }
232 }
233 return [keycode].concat(modifiers).join(SEPARATOR);
234 }
235
236 /**
237 * Returns a text which displayed on a key.
238 */
239 function getKeyTextValue(keyData) {
240 if (keyData.label) {
241 // Do not show text on the space key.
242 if (keyData.label == 'space') {
243 return '';
244 }
245 return keyData.label;
246 }
247
248 var chars = [];
249 for (var j = 1; j <= 9; ++j) {
250 var pos = keyData['p' + j];
251 if (pos && pos.length > 0) {
252 chars.push(hex2char(pos));
253 }
254 }
255 return chars.join(' ');
256 }
257
258 /**
259 * Updates the whole keyboard.
260 */
261 function update(modifiers) {
262 var instructions = document.getElementById('instructions');
263 if (modifiers.length == 0) {
264 instructions.style.visibility = 'visible';
265 } else {
266 instructions.style.visibility = 'hidden';
267 }
268
269 var keyboardGlyphData = getKeyboardGlyphData();
270 var shortcutData = getShortcutData();
271 var layout = getLayouts()[keyboardGlyphData.layoutName];
272 for (var i = 0; i < layout.length; ++i) {
273 var identifier = remapIdentifier(layout[i][0]);
274 var keyData = keyboardGlyphData.keys[identifier];
275 var classes = getKeyClasses(identifier, modifiers, keyData);
276 var keyLabel = getKeyLabel(keyData, modifiers);
277 var shortcutId = shortcutData[getAction(keyLabel, modifiers)];
278 if (modifiers.length == 1 && modifiers[0] == 'SHIFT' &&
279 identifier == '2A') {
280 // Currently there is no way to identify whether the left shift or the
281 // right shift is preesed from the key event, so I assume the left shift
282 // key is pressed here and do not show keyboard shortcut description for
283 // 'Shift - Shift' (Toggle caps lock) on the left shift key, the
284 // identifier of which is '2A'.
285 // TODO(mazda): Remove this workaround (http://crosbug.com/18047)
286 shortcutId = null;
287 }
288 if (shortcutId) {
289 classes.push('is-shortcut');
290 }
291
292 var key = document.getElementById(keyId(identifier, i));
293 key.className = classes.join(' ');
294
295 if (!keyData) {
296 continue;
297 }
298
299 var keyText = document.getElementById(keyTextId(identifier, i));
300 var keyTextValue = getKeyTextValue(keyData);
301 if (keyTextValue) {
302 keyText.style.visibility = 'visible';
303 } else {
304 keyText.style.visibility = 'hidden';
305 }
306 keyText.textContent = keyTextValue;
307
308 var shortcutText = document.getElementById(shortcutTextId(identifier, i));
309 if (shortcutId) {
310 shortcutText.style.visibility = 'visible';
311 shortcutText.textContent = templateData[shortcutId];
312 } else {
313 shortcutText.style.visibility = 'hidden';
314 }
315
316 if (keyData.format) {
317 var format = keyData.format;
318 if (format == 'left' || format == 'right') {
319 shortcutText.style.textAlign = format;
320 keyText.style.textAlign = format;
321 }
322 }
323 }
324 }
325
326 /**
327 * A callback function for onkeydown and onkeyup events.
328 */
329 function handleKeyEvent(e){
330 var modifiers = getModifiers(e);
331 if (!getKeyboardOverlayId()) {
332 return;
333 }
334 update(modifiers);
335 KeyboardOverlayAccessibilityHelper.maybeSpeakAllShortcuts(modifiers);
336 }
337
338 /**
339 * Initializes the layout of the keys.
340 */
341 function initLayout() {
342 // Add data for the caps lock key
343 var keys = getKeyboardGlyphData().keys;
344 if (!('3A' in keys)) {
345 keys['3A'] = {label: 'caps lock', format: 'left'};
346 }
347 // Add data for the special key representing a disabled key
348 keys['DISABLED'] = {label: 'disabled', format: 'left'};
349
350 var layout = getLayouts()[getKeyboardGlyphData().layoutName];
351 var keyboard = document.body;
352 var minX = window.innerWidth;
353 var maxX = 0;
354 var minY = window.innerHeight;
355 var maxY = 0;
356 var multiplier = 1.38 * window.innerWidth / BASE_KEYBOARD.width;
357 var keyMargin = 7;
358 var offsetX = 10;
359 var offsetY = 7;
360 for (var i = 0; i < layout.length; i++) {
361 var array = layout[i];
362 var identifier = remapIdentifier(array[0]);
363 var x = Math.round((array[1] + offsetX) * multiplier);
364 var y = Math.round((array[2] + offsetY) * multiplier);
365 var w = Math.round((array[3] - keyMargin) * multiplier);
366 var h = Math.round((array[4] - keyMargin) * multiplier);
367
368 var key = document.createElement('div');
369 key.id = keyId(identifier, i);
370 key.className = 'keyboard-overlay-key';
371 key.style.left = x + 'px';
372 key.style.top = y + 'px';
373 key.style.width = w + 'px';
374 key.style.height = h + 'px';
375
376 var keyText = document.createElement('div');
377 keyText.id = keyTextId(identifier, i);
378 keyText.className = 'keyboard-overlay-key-text';
379 keyText.style.visibility = 'hidden';
380 key.appendChild(keyText);
381
382 var shortcutText = document.createElement('div');
383 shortcutText.id = shortcutTextId(identifier, i);
384 shortcutText.className = 'keyboard-overlay-shortcut-text';
385 shortcutText.style.visilibity = 'hidden';
386 key.appendChild(shortcutText);
387 keyboard.appendChild(key);
388
389 minX = Math.min(minX, x);
390 maxX = Math.max(maxX, x + w);
391 minY = Math.min(minY, y);
392 maxY = Math.max(maxY, y + h);
393 }
394
395 var width = maxX - minX + 1;
396 var height = maxY - minY + 1;
397 keyboard.style.width = (width + 2 * (minX + 1)) + 'px';
398 keyboard.style.height = (height + 2 * (minY + 1)) + 'px';
399
400 var instructions = document.createElement('div');
401 instructions.id = 'instructions';
402 instructions.className = 'keyboard-overlay-instructions';
403 instructions.style.left = ((BASE_INSTRUCTIONS.left - BASE_KEYBOARD.left) *
404 width / BASE_KEYBOARD.width + minX) + 'px';
405 instructions.style.top = ((BASE_INSTRUCTIONS.top - BASE_KEYBOARD.top) *
406 height / BASE_KEYBOARD.height + minY) + 'px';
407 instructions.style.width = (width * BASE_INSTRUCTIONS.width /
408 BASE_KEYBOARD.width) + 'px';
409 instructions.style.height = (height * BASE_INSTRUCTIONS.height /
410 BASE_KEYBOARD.height) + 'px';
411
412 var instructionsText = document.createElement('div');
413 instructionsText.id = 'instructions-text';
414 instructionsText.className = 'keyboard-overlay-instructions-text';
415 instructionsText.innerHTML = templateData.keyboardOverlayInstructions;
416 instructions.appendChild(instructionsText);
417 var instructionsHideText = document.createElement('div');
418 instructionsHideText.id = 'instructions-hide-text';
419 instructionsHideText.className = 'keyboard-overlay-instructions-hide-text';
420 instructionsHideText.innerHTML = templateData.keyboardOverlayInstructionsHide;
421 instructions.appendChild(instructionsHideText);
422 keyboard.appendChild(instructions);
423 }
424
425 /**
426 * A callback function for the onload event of the body element.
427 */
428 function init() {
429 document.addEventListener('keydown', handleKeyEvent);
430 document.addEventListener('keyup', handleKeyEvent);
431 chrome.send('getLabelMap');
432 }
433
434 /**
435 * Initializes the global map for remapping identifiers of modifier keys based
436 * on the preference.
437 * Called after sending the 'getLabelMap' message.
438 */
439 function initIdentifierMap(remap) {
440 for (var key in remap) {
441 var val = remap[key];
442 if ((key in LABEL_TO_IDENTIFIER) &&
443 (val in LABEL_TO_IDENTIFIER)) {
444 identifierMap[LABEL_TO_IDENTIFIER[key]] =
445 LABEL_TO_IDENTIFIER[val];
446 } else {
447 console.error('Invalid label map element: ' + key + ', ' + val);
448 }
449 }
450 chrome.send('getInputMethodId');
451 }
452
453 /**
454 * Initializes the global keyboad overlay ID and the layout of keys.
455 * Called after sending the 'getInputMethodId' message.
456 */
457 function initKeyboardOverlayId(inputMethodId) {
458 // Libcros returns an empty string when it cannot find the keyboard overlay ID
459 // corresponding to the current input method.
460 // In such a case, fallback to the default ID (en_US).
461 var inputMethodIdToOverlayId = keyboardOverlayData['inputMethodIdToOverlayId']
462 if (inputMethodId) {
463 keyboardOverlayId = inputMethodIdToOverlayId[inputMethodId];
464 }
465 if (!keyboardOverlayId) {
466 console.error('No keyboard overlay ID for ' + inputMethodId);
467 keyboardOverlayId = 'en_US';
468 }
469 while(document.body.firstChild) {
470 document.body.removeChild(document.body.firstChild);
471 }
472 initLayout();
473 update([]);
474 }
475
476 document.addEventListener('DOMContentLoaded', init);
OLDNEW
« no previous file with comments | « chrome/browser/resources/keyboard_overlay.html ('k') | chrome/browser/resources/keyboard_overlay_accessibility_helper.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698