/* vim:set ts=2 sw=2 sts=2 et: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Jetpack. * * The Initial Developer of the Original Code is * the Mozilla Foundation. * Portions created by the Initial Developer are Copyright (C) 2011 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Irakli Gozalishvili (Original Author) * Paul Vet * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ "use strict"; const { observer: keyboardObserver } = require("./observer"); const { getKeyForCode, normalize, isFunctionKey, MODIFIERS } = require("./utils"); /** * Register a global `hotkey` that executes `listener` when the key combination * in `hotkey` is pressed. If more then one `listener` is registered on the same * key combination only last one will be executed. * * @param {string} hotkey * Key combination in the format of 'modifier key'. * * Examples: * * "accel s" * "meta shift i" * "control alt d" * * Modifier keynames: * * - **shift**: The Shift key. * - **alt**: The Alt key. On the Macintosh, this is the Option key. On * Macintosh this can only be used in conjunction with another modifier, * since `Alt+Letter` combinations are reserved for entering special * characters in text. * - **meta**: The Meta key. On the Macintosh, this is the Command key. * - **control**: The Control key. * - **accel**: The key used for keyboard shortcuts on the user's platform, * which is Control on Windows and Linux, and Command on Mac. Usually, this * would be the value you would use. * * @param {function} listener * Function to execute when the `hotkey` is executed. */ exports.register = function register(hotkey, listener) { hotkey = normalize(hotkey); hotkeys[hotkey] = listener; }; /** * Unregister a global `hotkey`. If passed `listener` is not the one registered * for the given `hotkey`, the call to this function will be ignored. * * @param {string} hotkey * Key combination in the format of 'modifier key'. * @param {function} listener * Function that will be invoked when the `hotkey` is pressed. */ exports.unregister = function unregister(hotkey, listener) { hotkey = normalize(hotkey); if (hotkeys[hotkey] === listener) delete hotkeys[hotkey]; }; /** * Map of hotkeys and associated functions. */ const hotkeys = exports.hotkeys = {}; keyboardObserver.on("keydown", function onKeypress(event, window) { let key, modifiers = []; let isChar = "isChar" in event && event.isChar; let which = "which" in event ? event.which : null; let keyCode = "keyCode" in event ? event.keyCode : null; if ("shiftKey" in event && event.shiftKey) modifiers.push("shift"); if ("altKey" in event && event.altKey) modifiers.push("alt"); if ("ctrlKey" in event && event.ctrlKey) modifiers.push("control"); if ("metaKey" in event && event.metaKey) modifiers.push("meta"); // If it's not a printable character then we fall back to a human readable // equivalent of one of the following constants. // http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/events/nsIDOMKeyEvent.idl key = getKeyForCode(keyCode); // If only non-function (f1 - f24) key or only modifiers are pressed we don't // have a valid combination so we return immediately (Also, sometimes // `keyCode` may be one for the modifier which means we do not have a // modifier). if (!key || (!isFunctionKey(key) && !modifiers.length) || key in MODIFIERS) return; let combination = normalize({ key: key, modifiers: modifiers }); let hotkey = hotkeys[combination]; if (hotkey) { try { hotkey(); } catch (exception) { console.exception(exception); } finally { // Work around bug 582052 by preventing the (nonexistent) default action. event.preventDefault(); } } });