1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/keyboard/hotkeys.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,110 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +module.metadata = { 1.11 + "stability": "unstable" 1.12 +}; 1.13 + 1.14 +const { observer: keyboardObserver } = require("./observer"); 1.15 +const { getKeyForCode, normalize, isFunctionKey, 1.16 + MODIFIERS } = require("./utils"); 1.17 + 1.18 +/** 1.19 + * Register a global `hotkey` that executes `listener` when the key combination 1.20 + * in `hotkey` is pressed. If more then one `listener` is registered on the same 1.21 + * key combination only last one will be executed. 1.22 + * 1.23 + * @param {string} hotkey 1.24 + * Key combination in the format of 'modifier key'. 1.25 + * 1.26 + * Examples: 1.27 + * 1.28 + * "accel s" 1.29 + * "meta shift i" 1.30 + * "control alt d" 1.31 + * 1.32 + * Modifier keynames: 1.33 + * 1.34 + * - **shift**: The Shift key. 1.35 + * - **alt**: The Alt key. On the Macintosh, this is the Option key. On 1.36 + * Macintosh this can only be used in conjunction with another modifier, 1.37 + * since `Alt+Letter` combinations are reserved for entering special 1.38 + * characters in text. 1.39 + * - **meta**: The Meta key. On the Macintosh, this is the Command key. 1.40 + * - **control**: The Control key. 1.41 + * - **accel**: The key used for keyboard shortcuts on the user's platform, 1.42 + * which is Control on Windows and Linux, and Command on Mac. Usually, this 1.43 + * would be the value you would use. 1.44 + * 1.45 + * @param {function} listener 1.46 + * Function to execute when the `hotkey` is executed. 1.47 + */ 1.48 +exports.register = function register(hotkey, listener) { 1.49 + hotkey = normalize(hotkey); 1.50 + hotkeys[hotkey] = listener; 1.51 +}; 1.52 + 1.53 +/** 1.54 + * Unregister a global `hotkey`. If passed `listener` is not the one registered 1.55 + * for the given `hotkey`, the call to this function will be ignored. 1.56 + * 1.57 + * @param {string} hotkey 1.58 + * Key combination in the format of 'modifier key'. 1.59 + * @param {function} listener 1.60 + * Function that will be invoked when the `hotkey` is pressed. 1.61 + */ 1.62 +exports.unregister = function unregister(hotkey, listener) { 1.63 + hotkey = normalize(hotkey); 1.64 + if (hotkeys[hotkey] === listener) 1.65 + delete hotkeys[hotkey]; 1.66 +}; 1.67 + 1.68 +/** 1.69 + * Map of hotkeys and associated functions. 1.70 + */ 1.71 +const hotkeys = exports.hotkeys = {}; 1.72 + 1.73 +keyboardObserver.on("keydown", function onKeypress(event, window) { 1.74 + let key, modifiers = []; 1.75 + let isChar = "isChar" in event && event.isChar; 1.76 + let which = "which" in event ? event.which : null; 1.77 + let keyCode = "keyCode" in event ? event.keyCode : null; 1.78 + 1.79 + if ("shiftKey" in event && event.shiftKey) 1.80 + modifiers.push("shift"); 1.81 + if ("altKey" in event && event.altKey) 1.82 + modifiers.push("alt"); 1.83 + if ("ctrlKey" in event && event.ctrlKey) 1.84 + modifiers.push("control"); 1.85 + if ("metaKey" in event && event.metaKey) 1.86 + modifiers.push("meta"); 1.87 + 1.88 + // If it's not a printable character then we fall back to a human readable 1.89 + // equivalent of one of the following constants. 1.90 + // http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/events/nsIDOMKeyEvent.idl 1.91 + key = getKeyForCode(keyCode); 1.92 + 1.93 + // If only non-function (f1 - f24) key or only modifiers are pressed we don't 1.94 + // have a valid combination so we return immediately (Also, sometimes 1.95 + // `keyCode` may be one for the modifier which means we do not have a 1.96 + // modifier). 1.97 + if (!key || (!isFunctionKey(key) && !modifiers.length) || key in MODIFIERS) 1.98 + return; 1.99 + 1.100 + let combination = normalize({ key: key, modifiers: modifiers }); 1.101 + let hotkey = hotkeys[combination]; 1.102 + 1.103 + if (hotkey) { 1.104 + try { 1.105 + hotkey(); 1.106 + } catch (exception) { 1.107 + console.exception(exception); 1.108 + } finally { 1.109 + // Work around bug 582052 by preventing the (nonexistent) default action. 1.110 + event.preventDefault(); 1.111 + } 1.112 + } 1.113 +});