diff --git a/KeyType/Collection/Custom.swift b/KeyType/Collection/Custom.swift index f283964..3d04630 100644 --- a/KeyType/Collection/Custom.swift +++ b/KeyType/Collection/Custom.swift @@ -12,7 +12,7 @@ let Custom = [ // To launch Alfred faster Remap(Key.shiftR.without.shift, to: Key.SPACE.with.option), // Left to 'a' becomes escape - Remap(Key.ctrlR.without.ctrl, to: Key.ESCAPE.alone), + Remap(Key.ctrlR.without.ctrl, to: Key.ESCAPE), // To launch OmniFocus faster Remap(Key.shiftL.without.shift, to: Key.SPACE.with.shift.command.option), ] diff --git a/KeyType/Collection/Emacs.swift b/KeyType/Collection/Emacs.swift index 97b8970..56a074e 100644 --- a/KeyType/Collection/Emacs.swift +++ b/KeyType/Collection/Emacs.swift @@ -8,13 +8,12 @@ import Foundation -let Emacs = [ - [Key.ctrlL.without.ctrl, Key.ESCAPE.alone], - [Key.J.with.ctrl, Key.RETURN.alone], - [Key.M.with.ctrl, Key.RETURN.alone], - [Key.F.with.ctrl, Key.RIGHT_ARROW.alone], - [Key.B.with.ctrl, Key.LEFT_ARROW.alone], - [Key.N.with.ctrl, Key.DOWN_ARROW.alone], - [Key.P.with.ctrl, Key.UP_ARROW.alone], - [Key.H.with.ctrl, Key.DELETE.alone], -].map { Remap($0[0], to: $0[1]) } +let EmacsLike = [ + Remap(Key.J.with.ctrl, to: .returnKey), + Remap(Key.M.with.ctrl, to: .returnKey), + Remap(Key.F.with.ctrl, to: .rightArrow), + Remap(Key.B.with.ctrl, to: .leftArrow), + Remap(Key.N.with.ctrl, to: .downArrow), + Remap(Key.P.with.ctrl, to: .upArrow), + Remap(Key.H.with.ctrl, to: .delete), +] diff --git a/KeyType/Collection/KanaEisu.swift b/KeyType/Collection/KanaEisu.swift index 661f4ae..d7f0167 100644 --- a/KeyType/Collection/KanaEisu.swift +++ b/KeyType/Collection/KanaEisu.swift @@ -9,6 +9,6 @@ import Foundation let KanaEisu: KeyMapCollection = [ - Remap(Key.commandL.without.command, to: Key.EISU.alone), - Remap(Key.commandR.without.command, to: Key.KANA.alone), + Remap(Key.commandL.without.command, to: Key.EISU), + Remap(Key.commandR.without.command, to: Key.KANA), ] diff --git a/KeyType/EventConverter.swift b/KeyType/EventConverter.swift index bf631b8..3fb6a17 100644 --- a/KeyType/EventConverter.swift +++ b/KeyType/EventConverter.swift @@ -35,7 +35,7 @@ class EventConverter { } for remap in candidateRemaps { - if eventKeyCombination.isCompatible(with: remap) { + if eventKeyCombination.canTrigger(remap.input) { event.keyCode = remap.outputKeyCode event.flags = remap.renderEventFlag(for: event) return event diff --git a/KeyType/Key/Key.swift b/KeyType/Key/Key.swift index 58bcd4d..1894e0f 100644 --- a/KeyType/Key/Key.swift +++ b/KeyType/Key/Key.swift @@ -45,7 +45,7 @@ enum Key: UInt16 { case SQUARE_BRA = 33 case I = 34 case P = 35 - case RETURN = 36 + case returnKey = 36 case L = 37 case J = 38 case QUOTE = 39 @@ -60,7 +60,7 @@ enum Key: UInt16 { case TAB = 48 case SPACE = 49 case BACKQUOTE = 50 - case DELETE = 51 + case delete = 51 case ENTER_POWERBOOK = 52 case ESCAPE = 53 case commandR = 54 @@ -123,10 +123,10 @@ enum Key: UInt16 { case F2 = 120 case PG_DOWN = 121 case F1 = 122 - case LEFT_ARROW = 123 - case RIGHT_ARROW = 124 - case DOWN_ARROW = 125 - case UP_ARROW = 126 + case leftArrow = 123 + case rightArrow = 124 + case downArrow = 125 + case upArrow = 126 case PC_POWER = 127 case GERMAN_PC_LESS_THAN = 128 case DASHBOARD = 130 diff --git a/KeyType/Key/KeyCombination.swift b/KeyType/Key/KeyCombination.swift index a94afd6..aba238e 100644 --- a/KeyType/Key/KeyCombination.swift +++ b/KeyType/Key/KeyCombination.swift @@ -10,17 +10,13 @@ import Cocoa class KeyCombination { let keyCode: CGKeyCode - var flags = CGEventFlags() + private(set) var withFlags = CGEventFlags() private var withoutFlags = CGEventFlags() private var addToWithFlag = true - var withoutModifier: CGEventFlags { - return withoutFlags - } - init(fromEvent: CGEvent) { keyCode = fromEvent.keyCode - flags = fromEvent.flags + withFlags = fromEvent.flags } init(_ key: Key) { @@ -29,7 +25,7 @@ class KeyCombination { private func addMask(_ mask: CGEventFlags) -> KeyCombination { if addToWithFlag { - flags.insert(mask) + withFlags.insert(mask) } else { withoutFlags.insert(mask) } @@ -52,33 +48,14 @@ class KeyCombination { return addMask(.maskAlternate) } - private func setModeExAddition() { - addToWithFlag = false - } - var without: KeyCombination { - setModeExAddition() + addToWithFlag = false return self } - var label: String { - guard let key = Key(rawValue: keyCode) else { return flagString } - return flagString + String(describing: key) - } - - private var flagString: String { - var flagString = "" - if has(modifier: .maskSecondaryFn) { flagString += "(fn)" } - if has(modifier: .maskAlphaShift) { flagString += "⇪" } - if has(modifier: .maskCommand) { flagString += "⌘" } - if has(modifier: .maskShift) { flagString += "⇧" } - if has(modifier: .maskControl) { flagString += "⌃" } - if has(modifier: .maskAlternate) { flagString += "⌥" } - return flagString - } - - private func has(modifier key: CGEventFlags) -> Bool { - return flags.contains(key) + var with: KeyCombination { + addToWithFlag = true + return self } func postEvent() { @@ -87,15 +64,14 @@ class KeyCombination { let keyDownEvent = CGEvent(keyboardEventSource: nil, virtualKey: keyCode, keyDown: true)! let keyUpEvent = CGEvent(keyboardEventSource: nil, virtualKey: keyCode, keyDown: false)! - keyDownEvent.flags = flags + keyDownEvent.flags = withFlags keyUpEvent.flags = CGEventFlags() keyDownEvent.post(tap: loc) keyUpEvent.post(tap: loc) } - func isCompatible(with mapping: Remap) -> Bool { - let cmb = mapping.input + func canTrigger(_ cmb: KeyCombination) -> Bool { if cmb.has(modifier: .maskCommand), !has(modifier: .maskCommand) { return false } if cmb.has(modifier: .maskShift), !has(modifier: .maskShift) { return false } if cmb.has(modifier: .maskControl), !has(modifier: .maskControl) { return false } @@ -103,6 +79,33 @@ class KeyCombination { if cmb.has(modifier: .maskSecondaryFn), !has(modifier: .maskSecondaryFn) { return false } if cmb.has(modifier: .maskAlphaShift), !has(modifier: .maskAlphaShift) { return false } - return mapping.hasAnyModToAvoid(flags) + return cmb.hasAnyModToAvoid(withFlags) + } + + private func hasAnyModToAvoid(_ flags: CGEventFlags) -> Bool { + return flags.rawValue & withoutFlags.rawValue == 0 + } + + private func has(modifier key: CGEventFlags) -> Bool { + return withFlags.contains(key) + } +} + +// Debug +extension KeyCombination { + var label: String { + guard let key = Key(rawValue: keyCode) else { return flagString } + return flagString + String(describing: key) + } + + private var flagString: String { + var flagString = "" + if has(modifier: .maskSecondaryFn) { flagString += "(fn)" } + if has(modifier: .maskAlphaShift) { flagString += "⇪" } + if has(modifier: .maskCommand) { flagString += "⌘" } + if has(modifier: .maskShift) { flagString += "⇧" } + if has(modifier: .maskControl) { flagString += "⌃" } + if has(modifier: .maskAlternate) { flagString += "⌥" } + return flagString } } diff --git a/KeyType/Key/Remap.swift b/KeyType/Key/Remap.swift index 9466b35..772a48b 100644 --- a/KeyType/Key/Remap.swift +++ b/KeyType/Key/Remap.swift @@ -18,12 +18,13 @@ class Remap: NSObject { self.output = output } - func renderEventFlag(for event: CGEvent) -> CGEventFlags { - let rawValue = (event.flags.rawValue & ~input.flags.rawValue) | output.flags.rawValue - return CGEventFlags(rawValue: rawValue) + init(_ from: KeyCombination, to output: Key) { + input = from + self.output = output.alone } - func hasAnyModToAvoid(_ flags: CGEventFlags) -> Bool { - return flags.rawValue & input.withoutModifier.rawValue == 0 + func renderEventFlag(for event: CGEvent) -> CGEventFlags { + let rawValue = (event.flags.rawValue & ~input.withFlags.rawValue) | output.withFlags.rawValue + return CGEventFlags(rawValue: rawValue) } } diff --git a/KeyType/KeyEventWatcher.swift b/KeyType/KeyEventWatcher.swift index 726815e..970be1a 100644 --- a/KeyType/KeyEventWatcher.swift +++ b/KeyType/KeyEventWatcher.swift @@ -11,7 +11,7 @@ import Cocoa class KeyEventWatcher { private var keyCode: CGKeyCode? private let bundleId = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String - private let config = EventConverter(LRDvorak + KanaEisu + Emacs + Custom) + private let config = EventConverter(LRDvorak + KanaEisu + EmacsLike + Custom) private var eventMaskToWatch: CGEventMask { let eventTypeList: [CGEventType] = [ diff --git a/KeyTypeTests/KeyCombinationTests.swift b/KeyTypeTests/KeyCombinationTests.swift index 780ea5d..32c1d77 100644 --- a/KeyTypeTests/KeyCombinationTests.swift +++ b/KeyTypeTests/KeyCombinationTests.swift @@ -18,6 +18,10 @@ class KeyCombinationTests: XCTestCase { XCTAssert(convert(KanaEisu, key: Key.commandR)?.keyCode == Key.KANA.rawValue) } + func testChain() { + XCTAssertFalse(Key.commandR.without.command.withFlags.contains(.maskCommand)) + } + private func convert(_ collection: KeyMapCollection, key: Key) -> CGEvent? { let converter = EventConverter(collection) let event = CGEvent(