| 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 |