From d8d98ca7e3cca77a700fc22b26b9107d683dd92e Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Fri, 23 Sep 2011 15:57:18 -0700 Subject: [PATCH] first pass at key bindings. just replicating keymaster for now. --- Cocoa/Classes/AtomApp.m | 1 - src/keybinder.coffee | 105 +++++++++++++++++++++----- vendor/keymaster.js | 159 ---------------------------------------- 3 files changed, 87 insertions(+), 178 deletions(-) delete mode 100644 vendor/keymaster.js diff --git a/Cocoa/Classes/AtomApp.m b/Cocoa/Classes/AtomApp.m index 0075c2963..b69d050d4 100644 --- a/Cocoa/Classes/AtomApp.m +++ b/Cocoa/Classes/AtomApp.m @@ -7,7 +7,6 @@ - (void)sendEvent:(NSEvent *)event { switch ([event type]) { case NSKeyDown: - case NSFlagsChanged: { BOOL handeled = NO; id controller = [[self keyWindow] windowController]; diff --git a/src/keybinder.coffee b/src/keybinder.coffee index dbe6b23fd..7ab22c612 100644 --- a/src/keybinder.coffee +++ b/src/keybinder.coffee @@ -1,26 +1,95 @@ _ = require 'underscore' -ace = require 'ace/ace' -canon = require 'pilot/canon' +modifierKeys = + '⇧': 16 + shift: 16 + alt: 18 + option: 18 + '⌥': 18 + control: 17 + ctrl: 17 + command: 91 + cmd: 91 + '⌘': 91 -key = require 'keymaster' +namedKeys = + backspace: 8 + tab: 9 + clear: 12 + enter: 13 + return: 13 + esc: 27 + escape: 27 + space: 32 + left: 37 + up: 38 + right: 39 + down: 40 + del: 46 + delete: 46 + home: 36 + end: 35 + pageup: 33 + pagedown: 34 + ',': 188 + '.': 190 + '/': 191 + '`': 192 + '-': 189 + '=': 187 + ';': 186 + '\'': 222 + '[': 219 + ']': 221 + '\\': 220 + +bindings = {} + +shortcutParser = (shortcut) -> + keys = shortcut.trim().split '-' + + modifiers = [] + key = null + + for k in keys + k = k.toLowerCase() + if modifierKeys[k] + modifiers.push modifierKeys[k] + else if key + throw "THIS KEYBINDING #{shortcut} specifies TWO keys, we don't handle that yet." + else if namedKeys[k] + key = namedKeys[k] + else if k.length > 1 + throw "THIS KEYBINDING #{shortcut} uses an unknown key #{k}." + else + key = k.charCodeAt 0 + + modifiers.concat(key).sort().join "-" exports.bindKey = (scope, shortcut, method) -> - key shortcut, -> - if _.isFunction method - method.apply scope - else - if scope[method] - scope[method]() - else - console.error "keymap: no '#{method}' method found" + callback = if _.isFunction method + -> method.apply scope + else if scope[method] + -> scope[method]() + else + console.error "keymap: no '#{method}' method found" + -> console.error "keymap: #{shortcut} failed to bind" - false + callbacks = bindings[shortcutParser shortcut] ?= [] + callbacks.push callback window.handleKeyEvent = (event) -> - false -# if (event.modifierFlags & OSX.NSCommandKeyMask) and event.keyCode == 50 -# console.log "Got Cmd-`" -# true -# else -# false + keys = [] + keys.push modifierKeys.command if event.modifierFlags & OSX.NSCommandKeyMask + keys.push modifierKeys.shift if event.modifierFlags & OSX.NSShiftKeyMask + keys.push modifierKeys.control if event.modifierFlags & OSX.NSControlKeyMask + keys.push modifierKeys.alt if event.modifierFlags & OSX.NSAlternateKeyMask + keys.push event.charactersIgnoringModifiers.charCodeAt 0 + + shortcut = keys.sort().join "-" + + callbacks = bindings[shortcut] + return false if not callbacks + + callback() for callback in callbacks + true diff --git a/vendor/keymaster.js b/vendor/keymaster.js deleted file mode 100644 index 29ebdccfd..000000000 --- a/vendor/keymaster.js +++ /dev/null @@ -1,159 +0,0 @@ -// keymaster.js -// (c) 2011 Thomas Fuchs -// keymaster.js may be freely distributed under the MIT license. - -;(function(global){ - var k, - _handlers = {}, - _mods = { 16: false, 18: false, 17: false, 91: false }, - _scope = 'all', - // modifier keys - _MODIFIERS = { - '⇧': 16, shift: 16, - option: 18, '⌥': 18, alt: 18, - ctrl: 17, control: 17, - command: 91, '⌘': 91 - }, - // special keys - _MAP = { - backspace: 8, tab: 9, clear: 12, - enter: 13, 'return': 13, - esc: 27, escape: 27, space: 32, - left: 37, up: 38, - right: 39, down: 40, - del: 46, 'delete': 46, - home: 36, end: 35, - pageup: 33, pagedown: 34, - ',': 188, '.': 190, '/': 191, - '`': 192, '-': 189, '=': 187, - ';': 186, '\'': 222, - '[': 219, ']': 221, '\\': 220 - }; - - for(k=1;k<20;k++) _MODIFIERS['f'+k] = 111+k; - - // IE doesn't support Array#indexOf, so have a simple replacement - function index(array, item){ - var i = array.length; - while(i--) if(array[i]===item) return i; - return -1; - } - - // handle keydown event - function dispatch(event){ - var key, tagName, handler, k, i, modifiersMatch; - tagName = (event.target || event.srcElement).tagName; - key = event.keyCode; - - // if a modifier key, set the key. property to true and return - if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko - if(key in _mods) { - _mods[key] = true; - // 'assignKey' from inside this closure is exported to window.key - for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true; - return; - } - - // ignore keypressed in any elements that support keyboard data input -// if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') return; - - // abort if no potentially matching shortcuts found - if (!(key in _handlers)) return; - - // for each potential shortcut - for (i = 0; i < _handlers[key].length; i++) { - handler = _handlers[key][i]; - - // see if it's in the current scope - if(handler.scope == _scope || handler.scope == 'all'){ - // check if modifiers match if any - modifiersMatch = handler.mods.length > 0; - for(k in _mods) - if((!_mods[k] && index(handler.mods, +k) > -1) || - (_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false; - // call the handler and stop the event if neccessary - if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){ - if(handler.method(event, handler)===false){ - if(event.preventDefault) event.preventDefault(); - else event.returnValue = false; - if(event.stopPropagation) event.stopPropagation(); - if(event.cancelBubble) event.cancelBubble = true; - } - } - } - } - }; - - // unset modifier keys on keyup - function clearModifier(event){ - var key = event.keyCode, k; - if(key == 93 || key == 224) key = 91; - if(key in _mods) { - _mods[key] = false; - for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false; - } - }; - // unset modifiers on blur - function clearModifiers(event){ - for(k in _MODIFIERS) assignKey[k] = false; - for(i in _mods) _mods[i] = false; - } - - // parse and assign shortcut - function assignKey(key, scope, method){ - var keys, mods, i, mi; - if (method === undefined) { - method = scope; - scope = 'all'; - } - key = key.replace(/\s/g,''); - keys = key.split(','); - - if((keys[keys.length-1])=='') - keys[keys.length-2] += ','; - // for each shortcut - for (i = 0; i < keys.length; i++) { - // set modifier keys if any - mods = []; - key = keys[i].split(/-|\+/); - if(key.length > 1){ - mods = key.slice(0,key.length-1); - for (mi = 0; mi < mods.length; mi++) - mods[mi] = _MODIFIERS[mods[mi].toLowerCase()]; - key = [key[key.length-1]]; - } - // convert to keycode and... - key = key[0] - key = _MAP[key] || key.toUpperCase().charCodeAt(0); - // ...store handler - if (!(key in _handlers)) _handlers[key] = []; - _handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods }); - } - }; - - // initialize key. to false - for(k in _MODIFIERS) assignKey[k] = false; - - // set current scope (default 'all') - function setScope(scope){ _scope = scope || 'all' }; - - // cross-browser events - function addEvent(object, event, method) { - if (object.addEventListener) - object.addEventListener(event, method, false); - else if(object.attachEvent) - object.attachEvent('on'+event, function(){ method(window.event) }); - }; - - // set the handlers globally on document - addEvent(document, 'keydown', dispatch); - addEvent(document, 'keyup', clearModifier); - addEvent(window, 'blur', clearModifiers, true); - - // set window.key and window.key.setScope - global.key = assignKey; - global.key.setScope = setScope; - - if(typeof module !== 'undefined') module.exports = global.key; - -})(this);