| /* |
| * Copyright (C) 2009 Apple Inc. All rights reserved. |
| * Copyright (C) 2009 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @constructor |
| */ |
| WebInspector.KeyboardShortcut = function() |
| { |
| } |
| |
| /** |
| * Constants for encoding modifier key set as a bit mask. |
| * @see #_makeKeyFromCodeAndModifiers |
| */ |
| WebInspector.KeyboardShortcut.Modifiers = { |
| None: 0, // Constant for empty modifiers set. |
| Shift: 1, |
| Ctrl: 2, |
| Alt: 4, |
| Meta: 8, // Command key on Mac, Win key on other platforms. |
| get CtrlOrMeta() |
| { |
| // "default" command/ctrl key for platform, Command on Mac, Ctrl on other platforms |
| return WebInspector.isMac() ? this.Meta : this.Ctrl; |
| }, |
| get ShiftOrOption() |
| { |
| // Option on Mac, Shift on other platforms |
| return WebInspector.isMac() ? this.Alt : this.Shift; |
| } |
| }; |
| |
| /** @typedef {!{code: number, name: (string|!Object.<string, string>)}} */ |
| WebInspector.KeyboardShortcut.Key; |
| |
| /** @type {!Object.<string, !WebInspector.KeyboardShortcut.Key>} */ |
| WebInspector.KeyboardShortcut.Keys = { |
| Backspace: { code: 8, name: "\u21a4" }, |
| Tab: { code: 9, name: { mac: "\u21e5", other: "Tab" } }, |
| Enter: { code: 13, name: { mac: "\u21a9", other: "Enter" } }, |
| Shift: { code: 16, name: { mac: "\u21e7", other: "Shift" } }, |
| Ctrl: { code: 17, name: "Ctrl" }, |
| Esc: { code: 27, name: "Esc" }, |
| Space: { code: 32, name: "Space" }, |
| PageUp: { code: 33, name: { mac: "\u21de", other: "PageUp" } }, // also NUM_NORTH_EAST |
| PageDown: { code: 34, name: { mac: "\u21df", other: "PageDown" } }, // also NUM_SOUTH_EAST |
| End: { code: 35, name: { mac: "\u2197", other: "End" } }, // also NUM_SOUTH_WEST |
| Home: { code: 36, name: { mac: "\u2196", other: "Home" } }, // also NUM_NORTH_WEST |
| Left: { code: 37, name: "\u2190" }, // also NUM_WEST |
| Up: { code: 38, name: "\u2191" }, // also NUM_NORTH |
| Right: { code: 39, name: "\u2192" }, // also NUM_EAST |
| Down: { code: 40, name: "\u2193" }, // also NUM_SOUTH |
| Delete: { code: 46, name: "Del" }, |
| Zero: { code: 48, name: "0" }, |
| H: { code: 72, name: "H" }, |
| Meta: { code: 91, name: "Meta" }, |
| F1: { code: 112, name: "F1" }, |
| F2: { code: 113, name: "F2" }, |
| F3: { code: 114, name: "F3" }, |
| F4: { code: 115, name: "F4" }, |
| F5: { code: 116, name: "F5" }, |
| F6: { code: 117, name: "F6" }, |
| F7: { code: 118, name: "F7" }, |
| F8: { code: 119, name: "F8" }, |
| F9: { code: 120, name: "F9" }, |
| F10: { code: 121, name: "F10" }, |
| F11: { code: 122, name: "F11" }, |
| F12: { code: 123, name: "F12" }, |
| Semicolon: { code: 186, name: ";" }, |
| NumpadPlus: { code: 107, name: "Numpad +" }, |
| NumpadMinus: { code: 109, name: "Numpad -" }, |
| Numpad0: { code: 96, name: "Numpad 0" }, |
| Plus: { code: 187, name: "+" }, |
| Comma: { code: 188, name: "," }, |
| Minus: { code: 189, name: "-" }, |
| Period: { code: 190, name: "." }, |
| Slash: { code: 191, name: "/" }, |
| QuestionMark: { code: 191, name: "?" }, |
| Apostrophe: { code: 192, name: "`" }, |
| Tilde: { code: 192, name: "Tilde" }, |
| LeftSquareBracket: { code: 219, name: "[" }, |
| RightSquareBracket: { code: 221, name: "]" }, |
| Backslash: { code: 220, name: "\\" }, |
| SingleQuote: { code: 222, name: "\'" }, |
| get CtrlOrMeta() |
| { |
| // "default" command/ctrl key for platform, Command on Mac, Ctrl on other platforms |
| return WebInspector.isMac() ? this.Meta : this.Ctrl; |
| }, |
| }; |
| |
| WebInspector.KeyboardShortcut.KeyBindings = {}; |
| |
| (function() { |
| for (var key in WebInspector.KeyboardShortcut.Keys) { |
| var descriptor = WebInspector.KeyboardShortcut.Keys[key]; |
| if (typeof descriptor === "object" && descriptor["code"]) { |
| var name = typeof descriptor["name"] === "string" ? descriptor["name"] : key; |
| WebInspector.KeyboardShortcut.KeyBindings[name] = descriptor; |
| } |
| } |
| })(); |
| |
| /** |
| * Creates a number encoding keyCode in the lower 8 bits and modifiers mask in the higher 8 bits. |
| * It is useful for matching pressed keys. |
| * |
| * @param {number|string} keyCode The code of the key, or a character "a-z" which is converted to a keyCode value. |
| * @param {number=} modifiers Optional list of modifiers passed as additional parameters. |
| * @return {number} |
| */ |
| WebInspector.KeyboardShortcut.makeKey = function(keyCode, modifiers) |
| { |
| if (typeof keyCode === "string") |
| keyCode = keyCode.charCodeAt(0) - (/^[a-z]/.test(keyCode) ? 32 : 0); |
| modifiers = modifiers || WebInspector.KeyboardShortcut.Modifiers.None; |
| return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers); |
| } |
| |
| /** |
| * @param {?KeyboardEvent} keyboardEvent |
| * @return {number} |
| */ |
| WebInspector.KeyboardShortcut.makeKeyFromEvent = function(keyboardEvent) |
| { |
| var modifiers = WebInspector.KeyboardShortcut.Modifiers.None; |
| if (keyboardEvent.shiftKey) |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift; |
| if (keyboardEvent.ctrlKey) |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Ctrl; |
| if (keyboardEvent.altKey) |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Alt; |
| if (keyboardEvent.metaKey) |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Meta; |
| |
| // Use either a real or a synthetic keyCode (for events originating from extensions). |
| var keyCode = keyboardEvent.keyCode || keyboardEvent["__keyCode"]; |
| return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers); |
| } |
| |
| /** |
| * @param {?KeyboardEvent} keyboardEvent |
| * @return {number} |
| */ |
| WebInspector.KeyboardShortcut.makeKeyFromEventIgnoringModifiers = function(keyboardEvent) |
| { |
| var keyCode = keyboardEvent.keyCode || keyboardEvent["__keyCode"]; |
| return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, WebInspector.KeyboardShortcut.Modifiers.None); |
| } |
| |
| /** |
| * @param {(?KeyboardEvent|?MouseEvent)} event |
| * @return {boolean} |
| */ |
| WebInspector.KeyboardShortcut.eventHasCtrlOrMeta = function(event) |
| { |
| return WebInspector.isMac() ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey; |
| } |
| |
| /** |
| * @param {!Event} event |
| * @return {boolean} |
| */ |
| WebInspector.KeyboardShortcut.hasNoModifiers = function(event) |
| { |
| return !event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey; |
| } |
| |
| /** @typedef {!{key: number, name: string}} */ |
| WebInspector.KeyboardShortcut.Descriptor; |
| |
| /** |
| * @param {string|!WebInspector.KeyboardShortcut.Key} key |
| * @param {number=} modifiers |
| * @return {!WebInspector.KeyboardShortcut.Descriptor} |
| */ |
| WebInspector.KeyboardShortcut.makeDescriptor = function(key, modifiers) |
| { |
| return { |
| key: WebInspector.KeyboardShortcut.makeKey(typeof key === "string" ? key : key.code, modifiers), |
| name: WebInspector.KeyboardShortcut.shortcutToString(key, modifiers) |
| }; |
| } |
| |
| /** |
| * @param {string} shortcut |
| * @return {?WebInspector.KeyboardShortcut.Descriptor} |
| */ |
| WebInspector.KeyboardShortcut.makeDescriptorFromBindingShortcut = function(shortcut) |
| { |
| var parts = shortcut.split(/\+(?!$)/); |
| var modifiers = 0; |
| var keyString; |
| for (var i = 0; i < parts.length; ++i) { |
| if (typeof WebInspector.KeyboardShortcut.Modifiers[parts[i]] !== "undefined") { |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers[parts[i]]; |
| continue; |
| } |
| console.assert(i === parts.length - 1, "Only one key other than modifier is allowed in shortcut <" + shortcut + ">"); |
| keyString = parts[i]; |
| break; |
| } |
| console.assert(keyString, "Modifiers-only shortcuts are not allowed (encountered <" + shortcut + ">)"); |
| if (!keyString) |
| return null; |
| |
| var key = WebInspector.KeyboardShortcut.Keys[keyString] || WebInspector.KeyboardShortcut.KeyBindings[keyString]; |
| if (key && key.shiftKey) |
| modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift; |
| return WebInspector.KeyboardShortcut.makeDescriptor(key ? key : keyString, modifiers); |
| } |
| |
| /** |
| * @param {string|!WebInspector.KeyboardShortcut.Key} key |
| * @param {number=} modifiers |
| * @return {string} |
| */ |
| WebInspector.KeyboardShortcut.shortcutToString = function(key, modifiers) |
| { |
| return WebInspector.KeyboardShortcut._modifiersToString(modifiers) + WebInspector.KeyboardShortcut._keyName(key); |
| } |
| |
| /** |
| * @param {string|!WebInspector.KeyboardShortcut.Key} key |
| * @return {string} |
| */ |
| WebInspector.KeyboardShortcut._keyName = function(key) |
| { |
| if (typeof key === "string") |
| return key.toUpperCase(); |
| if (typeof key.name === "string") |
| return key.name; |
| return key.name[WebInspector.platform()] || key.name.other || ''; |
| } |
| |
| /** |
| * @param {number} keyCode |
| * @param {?number} modifiers |
| * @return {number} |
| */ |
| WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers = function(keyCode, modifiers) |
| { |
| return (keyCode & 255) | (modifiers << 8); |
| }; |
| |
| /** |
| * @param {number} key |
| * @return {!{keyCode: number, modifiers: number}} |
| */ |
| WebInspector.KeyboardShortcut.keyCodeAndModifiersFromKey = function(key) |
| { |
| return { keyCode: key & 255, modifiers: key >> 8 }; |
| } |
| |
| /** |
| * @param {number|undefined} modifiers |
| * @return {string} |
| */ |
| WebInspector.KeyboardShortcut._modifiersToString = function(modifiers) |
| { |
| var isMac = WebInspector.isMac(); |
| var m = WebInspector.KeyboardShortcut.Modifiers; |
| var modifierNames = new Map([ |
| [m.Ctrl, isMac ? "Ctrl\u2004" : "Ctrl\u200A+\u200A"], |
| [m.Alt, isMac ? "opt\u2004" : "Alt\u200A+\u200A"], |
| [m.Shift, isMac ? "\u21e7\u2004" : "Shift\u200A+\u200A"], |
| [m.Meta, isMac ? "\u2318\u2004" : "Win\u200A+\u200A"] |
| ]); |
| return [m.Meta, m.Ctrl, m.Alt, m.Shift].map(mapModifiers).join(""); |
| |
| /** |
| * @param {number} m |
| * @return {string} |
| */ |
| function mapModifiers(m) |
| { |
| return modifiers & m ? /** @type {string} */ (modifierNames.get(m)) : ""; |
| } |
| }; |
| |
| WebInspector.KeyboardShortcut.SelectAll = WebInspector.KeyboardShortcut.makeKey("a", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta); |