OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview A collection of JavaScript utilities used to simplify working | 6 * @fileoverview A collection of JavaScript utilities used to simplify working |
7 * with keyboard events. | 7 * with keyboard events. |
8 */ | 8 */ |
9 | 9 |
10 | 10 |
11 goog.provide('cvox.KeyUtil'); | 11 goog.provide('cvox.KeyUtil'); |
12 goog.provide('cvox.SimpleKeyEvent'); | 12 goog.provide('cvox.SimpleKeyEvent'); |
13 | 13 |
14 goog.require('Msgs'); | 14 goog.require('Msgs'); |
15 goog.require('cvox.ChromeVox'); | 15 goog.require('cvox.ChromeVox'); |
16 goog.require('cvox.KeySequence'); | 16 goog.require('cvox.KeySequence'); |
17 | 17 |
18 /** | 18 /** |
19 * @typedef {{ctrlKey: (boolean|undefined), | 19 * @typedef {{ctrlKey: (boolean|undefined), |
20 * altKey: (boolean|undefined), | 20 * altKey: (boolean|undefined), |
21 * shiftKey: (boolean|undefined), | 21 * shiftKey: (boolean|undefined), |
22 * keyCode: (number|undefined)}} | 22 * keyCode: (number|undefined)}} |
23 */ | 23 */ |
24 cvox.SimpleKeyEvent; | 24 cvox.SimpleKeyEvent; |
25 | 25 |
26 /** | 26 /** |
27 * Create the namespace | 27 * Create the namespace |
28 * @constructor | 28 * @constructor |
29 */ | 29 */ |
30 cvox.KeyUtil = function() { | 30 cvox.KeyUtil = function() {}; |
31 }; | |
32 | 31 |
33 /** | 32 /** |
34 * The time in ms at which the ChromeVox Sticky Mode key was pressed. | 33 * The time in ms at which the ChromeVox Sticky Mode key was pressed. |
35 * @type {number} | 34 * @type {number} |
36 */ | 35 */ |
37 cvox.KeyUtil.modeKeyPressTime = 0; | 36 cvox.KeyUtil.modeKeyPressTime = 0; |
38 | 37 |
39 /** | 38 /** |
40 * Indicates if sequencing is currently active for building a keyboard shortcut. | 39 * Indicates if sequencing is currently active for building a keyboard shortcut. |
41 * @type {boolean} | 40 * @type {boolean} |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 cvox.KeyUtil.keyEventToKeySequence = function(keyEvent) { | 73 cvox.KeyUtil.keyEventToKeySequence = function(keyEvent) { |
75 var util = cvox.KeyUtil; | 74 var util = cvox.KeyUtil; |
76 if (util.prevKeySequence && | 75 if (util.prevKeySequence && |
77 (util.maxSeqLength == util.prevKeySequence.length())) { | 76 (util.maxSeqLength == util.prevKeySequence.length())) { |
78 // Reset the sequence buffer if max sequence length is reached. | 77 // Reset the sequence buffer if max sequence length is reached. |
79 util.sequencing = false; | 78 util.sequencing = false; |
80 util.prevKeySequence = null; | 79 util.prevKeySequence = null; |
81 } | 80 } |
82 // Either we are in the middle of a key sequence (N > H), or the key prefix | 81 // Either we are in the middle of a key sequence (N > H), or the key prefix |
83 // was pressed before (Ctrl+Z), or sticky mode is enabled | 82 // was pressed before (Ctrl+Z), or sticky mode is enabled |
84 var keyIsPrefixed = util.sequencing || keyEvent['keyPrefix'] || | 83 var keyIsPrefixed = |
85 keyEvent['stickyMode']; | 84 util.sequencing || keyEvent['keyPrefix'] || keyEvent['stickyMode']; |
86 | 85 |
87 // Create key sequence. | 86 // Create key sequence. |
88 var keySequence = new cvox.KeySequence(keyEvent); | 87 var keySequence = new cvox.KeySequence(keyEvent); |
89 | 88 |
90 // Check if the Cvox key should be considered as pressed because the | 89 // Check if the Cvox key should be considered as pressed because the |
91 // modifier key combination is active. | 90 // modifier key combination is active. |
92 var keyWasCvox = keySequence.cvoxModifier; | 91 var keyWasCvox = keySequence.cvoxModifier; |
93 | 92 |
94 if (keyIsPrefixed || keyWasCvox) { | 93 if (keyIsPrefixed || keyWasCvox) { |
95 if (!util.sequencing && util.isSequenceSwitchKeyCode(keySequence)) { | 94 if (!util.sequencing && util.isSequenceSwitchKeyCode(keySequence)) { |
(...skipping 11 matching lines...) Expand all Loading... |
107 throw 'Think sequencing is enabled, yet util.prevKeySequence already' + | 106 throw 'Think sequencing is enabled, yet util.prevKeySequence already' + |
108 'has two key codes' + util.prevKeySequence; | 107 'has two key codes' + util.prevKeySequence; |
109 } | 108 } |
110 } | 109 } |
111 } else { | 110 } else { |
112 util.sequencing = false; | 111 util.sequencing = false; |
113 } | 112 } |
114 | 113 |
115 // Repeated keys pressed. | 114 // Repeated keys pressed. |
116 var currTime = new Date().getTime(); | 115 var currTime = new Date().getTime(); |
117 if (cvox.KeyUtil.isDoubleTapKey(keySequence) && | 116 if (cvox.KeyUtil.isDoubleTapKey(keySequence) && util.prevKeySequence && |
118 util.prevKeySequence && | |
119 keySequence.equals(util.prevKeySequence)) { | 117 keySequence.equals(util.prevKeySequence)) { |
120 var prevTime = util.modeKeyPressTime; | 118 var prevTime = util.modeKeyPressTime; |
121 var delta = currTime - prevTime; | 119 var delta = currTime - prevTime; |
122 if (prevTime > 0 && delta > 100 && delta < 300) { // Double tap | 120 if (prevTime > 0 && delta > 100 && delta < 300) { // Double tap |
123 keySequence = util.prevKeySequence; | 121 keySequence = util.prevKeySequence; |
124 keySequence.doubleTap = true; | 122 keySequence.doubleTap = true; |
125 util.prevKeySequence = null; | 123 util.prevKeySequence = null; |
126 util.sequencing = false; | 124 util.sequencing = false; |
127 // Resets the search key state tracked for ChromeOS because in OOBE, | 125 // Resets the search key state tracked for ChromeOS because in OOBE, |
128 // we never get a key up for the key down (keyCode 91). | 126 // we never get a key up for the key down (keyCode 91). |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 }; | 184 }; |
187 | 185 |
188 /** | 186 /** |
189 * Returns the keycode of a string representation of the specified modifier. | 187 * Returns the keycode of a string representation of the specified modifier. |
190 * | 188 * |
191 * @param {string} keyString Modifier key. | 189 * @param {string} keyString Modifier key. |
192 * @return {number} Key code. | 190 * @return {number} Key code. |
193 */ | 191 */ |
194 cvox.KeyUtil.modStringToKeyCode = function(keyString) { | 192 cvox.KeyUtil.modStringToKeyCode = function(keyString) { |
195 switch (keyString) { | 193 switch (keyString) { |
196 case 'Ctrl': | 194 case 'Ctrl': |
197 return 17; | 195 return 17; |
198 case 'Alt': | 196 case 'Alt': |
199 return 18; | 197 return 18; |
200 case 'Shift': | 198 case 'Shift': |
201 return 16; | 199 return 16; |
202 case 'Cmd': | 200 case 'Cmd': |
203 case 'Win': | 201 case 'Win': |
204 return 91; | 202 return 91; |
205 } | 203 } |
206 return -1; | 204 return -1; |
207 }; | 205 }; |
208 | 206 |
209 /** | 207 /** |
210 * Returns the key codes of a string respresentation of the ChromeVox modifiers. | 208 * Returns the key codes of a string respresentation of the ChromeVox modifiers. |
211 * | 209 * |
212 * @return {Array<number>} Array of key codes. | 210 * @return {Array<number>} Array of key codes. |
213 */ | 211 */ |
214 cvox.KeyUtil.cvoxModKeyCodes = function() { | 212 cvox.KeyUtil.cvoxModKeyCodes = function() { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 } else if (cvox.ChromeVox.isMac) { | 261 } else if (cvox.ChromeVox.isMac) { |
264 return 'Cmd'; | 262 return 'Cmd'; |
265 } else { | 263 } else { |
266 return 'Win'; | 264 return 'Win'; |
267 } | 265 } |
268 } else if (keyCode == 8) { | 266 } else if (keyCode == 8) { |
269 return 'Backspace'; | 267 return 'Backspace'; |
270 } else if (keyCode == 32) { | 268 } else if (keyCode == 32) { |
271 return 'Space'; | 269 return 'Space'; |
272 } else if (keyCode == 35) { | 270 } else if (keyCode == 35) { |
273 return'end'; | 271 return 'end'; |
274 } else if (keyCode == 36) { | 272 } else if (keyCode == 36) { |
275 return 'home'; | 273 return 'home'; |
276 } else if (keyCode == 37) { | 274 } else if (keyCode == 37) { |
277 return 'Left arrow'; | 275 return 'Left arrow'; |
278 } else if (keyCode == 38) { | 276 } else if (keyCode == 38) { |
279 return 'Up arrow'; | 277 return 'Up arrow'; |
280 } else if (keyCode == 39) { | 278 } else if (keyCode == 39) { |
281 return 'Right arrow'; | 279 return 'Right arrow'; |
282 } else if (keyCode == 40) { | 280 } else if (keyCode == 40) { |
283 return 'Down arrow'; | 281 return 'Down arrow'; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 return ''; | 339 return ''; |
342 }; | 340 }; |
343 | 341 |
344 /** | 342 /** |
345 * Get the platform specific sticky key keycode. | 343 * Get the platform specific sticky key keycode. |
346 * | 344 * |
347 * @return {number} The platform specific sticky key keycode. | 345 * @return {number} The platform specific sticky key keycode. |
348 */ | 346 */ |
349 cvox.KeyUtil.getStickyKeyCode = function() { | 347 cvox.KeyUtil.getStickyKeyCode = function() { |
350 // TODO (rshearer): This should not be hard-coded here. | 348 // TODO (rshearer): This should not be hard-coded here. |
351 var stickyKeyCode = 45; // Insert for Linux and Windows | 349 var stickyKeyCode = 45; // Insert for Linux and Windows |
352 if (cvox.ChromeVox.isChromeOS || cvox.ChromeVox.isMac) { | 350 if (cvox.ChromeVox.isChromeOS || cvox.ChromeVox.isMac) { |
353 stickyKeyCode = 91; // GUI key (Search/Cmd) for ChromeOs and Mac | 351 stickyKeyCode = 91; // GUI key (Search/Cmd) for ChromeOs and Mac |
354 } | 352 } |
355 return stickyKeyCode; | 353 return stickyKeyCode; |
356 }; | 354 }; |
357 | 355 |
358 | 356 |
359 /** | 357 /** |
360 * Get readable string description for an internal string representation of a | 358 * Get readable string description for an internal string representation of a |
361 * key or a keyboard shortcut. | 359 * key or a keyboard shortcut. |
362 * | 360 * |
363 * @param {string} keyStr The internal string repsentation of a key or | 361 * @param {string} keyStr The internal string repsentation of a key or |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 var tempStr = ''; | 415 var tempStr = ''; |
418 for (var keyPressed in keySequence.keys) { | 416 for (var keyPressed in keySequence.keys) { |
419 // This iterates through the actual key, taking into account any | 417 // This iterates through the actual key, taking into account any |
420 // modifiers. | 418 // modifiers. |
421 if (!keySequence.keys[keyPressed][index]) { | 419 if (!keySequence.keys[keyPressed][index]) { |
422 continue; | 420 continue; |
423 } | 421 } |
424 var modifier = ''; | 422 var modifier = ''; |
425 switch (keyPressed) { | 423 switch (keyPressed) { |
426 case 'ctrlKey': | 424 case 'ctrlKey': |
427 // TODO(rshearer): This is a hack to work around the special casing | 425 // TODO(rshearer): This is a hack to work around the special casing |
428 // of the Ctrl key that used to happen in keyEventToString. We won't | 426 // of the Ctrl key that used to happen in keyEventToString. We won't |
429 // need it once we move away from strings completely. | 427 // need it once we move away from strings completely. |
430 modifier = 'Ctrl'; | 428 modifier = 'Ctrl'; |
431 break; | 429 break; |
432 case 'searchKeyHeld': | 430 case 'searchKeyHeld': |
433 var searchKey = cvox.KeyUtil.getReadableNameForKeyCode(91); | 431 var searchKey = cvox.KeyUtil.getReadableNameForKeyCode(91); |
434 modifier = searchKey; | 432 modifier = searchKey; |
435 break; | 433 break; |
436 case 'altKey': | 434 case 'altKey': |
437 modifier = 'Alt'; | 435 modifier = 'Alt'; |
438 break; | 436 break; |
439 case 'altGraphKey': | 437 case 'altGraphKey': |
440 modifier = 'AltGraph'; | 438 modifier = 'AltGraph'; |
441 break; | 439 break; |
442 case 'shiftKey': | 440 case 'shiftKey': |
443 modifier = 'Shift'; | 441 modifier = 'Shift'; |
444 break; | 442 break; |
445 case 'metaKey': | 443 case 'metaKey': |
446 var metaKey = cvox.KeyUtil.getReadableNameForKeyCode(91); | 444 var metaKey = cvox.KeyUtil.getReadableNameForKeyCode(91); |
447 modifier = metaKey; | 445 modifier = metaKey; |
448 break; | 446 break; |
449 case 'keyCode': | 447 case 'keyCode': |
450 var keyCode = keySequence.keys[keyPressed][index]; | 448 var keyCode = keySequence.keys[keyPressed][index]; |
451 // We make sure the keyCode isn't for a modifier key. If it is, then | 449 // We make sure the keyCode isn't for a modifier key. If it is, then |
452 // we've already added that into the string above. | 450 // we've already added that into the string above. |
453 if (!keySequence.isModifierKey(keyCode) && !opt_modifiers) { | 451 if (!keySequence.isModifierKey(keyCode) && !opt_modifiers) { |
454 if (opt_readableKeyCode) { | 452 if (opt_readableKeyCode) { |
455 tempStr += cvox.KeyUtil.getReadableNameForKeyCode(keyCode); | 453 tempStr += cvox.KeyUtil.getReadableNameForKeyCode(keyCode); |
456 } else { | 454 } else { |
457 tempStr += cvox.KeyUtil.keyCodeToString(keyCode); | 455 tempStr += cvox.KeyUtil.keyCodeToString(keyCode); |
| 456 } |
458 } | 457 } |
459 } | |
460 } | 458 } |
461 if (str.indexOf(modifier) == -1) { | 459 if (str.indexOf(modifier) == -1) { |
462 tempStr += modifier + '+'; | 460 tempStr += modifier + '+'; |
463 } | 461 } |
464 } | 462 } |
465 str += tempStr; | 463 str += tempStr; |
466 | 464 |
467 // Strip trailing +. | 465 // Strip trailing +. |
468 if (str[str.length - 1] == '+') { | 466 if (str[str.length - 1] == '+') { |
469 str = str.slice(0, -1); | 467 str = str.slice(0, -1); |
470 } | 468 } |
471 } | 469 } |
472 | 470 |
(...skipping 23 matching lines...) Expand all Loading... |
496 key.doubleTap = true; | 494 key.doubleTap = true; |
497 for (var i = 0, keySeq; keySeq = cvox.KeySequence.doubleTapCache[i]; i++) { | 495 for (var i = 0, keySeq; keySeq = cvox.KeySequence.doubleTapCache[i]; i++) { |
498 if (keySeq.equals(key)) { | 496 if (keySeq.equals(key)) { |
499 isSet = true; | 497 isSet = true; |
500 break; | 498 break; |
501 } | 499 } |
502 } | 500 } |
503 key.doubleTap = originalState; | 501 key.doubleTap = originalState; |
504 return isSet; | 502 return isSet; |
505 }; | 503 }; |
OLD | NEW |