@@ -24,25 +24,12 @@ class KeyboardEvents {
2424 static var hotKeyReleasedEventHandler : EventHandlerRef ?
2525 static var localMonitor : Any !
2626
27- static func addGlobalShortcut( _ controlId: String , _ shortcut: Shortcut ) {
28- addGlobalHandlerIfNeeded ( shortcut)
29- registerHotKeyIfNeeded ( controlId, shortcut)
30- }
31-
32- static func removeGlobalShortcut( _ controlId: String , _ shortcut: Shortcut ) {
33- unregisterHotKeyIfNeeded ( controlId, shortcut)
34- removeHandlerIfNeeded ( )
35- }
36-
37- private static func unregisterHotKeyIfNeeded( _ controlId: String , _ shortcut: Shortcut ) {
38- if shortcut. keyCode != . none {
39- UnregisterEventHotKey ( eventHotKeyRefs [ controlId] !)
40- eventHotKeyRefs [ controlId] = nil
41- }
42- }
43-
44- static func registerHotKeyIfNeeded( _ controlId: String , _ shortcut: Shortcut ) {
45- if shortcut. keyCode != . none {
27+ static func addGlobalShortcutIfNeeded( _ controlId: String , _ shortcut: Shortcut , checkEnabled: Bool = true , checkAnyModifierSide: Bool = true ) {
28+ if
29+ shortcut. keyCode != . none, eventHotKeyRefs [ controlId] == nil ,
30+ !checkEnabled || !App. app. globalShortcutsAreDisabled,
31+ !checkAnyModifierSide || Preferences . shortcutModifierSide [ Preferences . nameToIndex ( controlId) ] == . any
32+ {
4633 let id = globalShortcutsIds [ controlId] !
4734 let hotkeyId = EventHotKeyID ( signature: signature, id: UInt32 ( id) )
4835 let key = shortcut. carbonKeyCode
@@ -54,12 +41,22 @@ class KeyboardEvents {
5441 }
5542 }
5643
44+ static func removeGlobalShortcutIfNeeded( _ controlId: String , _ shortcut: Shortcut ) {
45+ if shortcut. keyCode != . none, eventHotKeyRefs [ controlId] != nil {
46+ UnregisterEventHotKey ( eventHotKeyRefs [ controlId] !)
47+ eventHotKeyRefs [ controlId] = nil
48+ }
49+ }
50+
5751 static func toggleGlobalShortcuts( _ shouldDisable: Bool ) {
5852 if shouldDisable != App . app. globalShortcutsAreDisabled {
59- let fn = shouldDisable ? unregisterHotKeyIfNeeded : registerHotKeyIfNeeded
6053 for shortcutId in globalShortcutsIds. keys {
6154 if let shortcut = ControlsTab . shortcuts [ shortcutId] ? . shortcut {
62- fn ( shortcutId, shortcut)
55+ if shouldDisable {
56+ removeGlobalShortcutIfNeeded ( shortcutId, shortcut)
57+ } else {
58+ addGlobalShortcutIfNeeded ( shortcutId, shortcut, checkEnabled: false )
59+ }
6360 }
6461 }
6562 debugPrint ( " toggleGlobalShortcuts " , shouldDisable)
@@ -69,15 +66,33 @@ class KeyboardEvents {
6966
7067 static func addEventHandlers( ) {
7168 addLocalMonitorForKeyDownAndKeyUp ( )
69+ addGlobalHandler ( )
7270 addCgEventTapForModifierFlags ( )
7371 }
7472
7573 private static func addLocalMonitorForKeyDownAndKeyUp( ) {
7674 localMonitor = NSEvent . addLocalMonitorForEvents ( matching: [ . keyDown, . keyUp] ) { ( event: NSEvent ) in
77- let someShortcutTriggered = handleEvent ( nil , nil , event. type == . keyDown ? UInt32 ( event. keyCode) : nil , cocoaToCarbonFlags ( event. modifierFlags) , event. type == . keyDown ? event. isARepeat : false )
75+ let someShortcutTriggered = handleEvent ( nil , nil , event. type == . keyDown ? UInt32 ( event. keyCode) : nil , cocoaToCarbonFlags ( event. modifierFlags) , event. type == . keyDown ? event. isARepeat : false , . local )
7876 return someShortcutTriggered ? nil : event
7977 }
8078 }
79+
80+ private static func addGlobalHandler( ) {
81+ var hotKeyPressedEventTypes = [ EventTypeSpec ( eventClass: OSType ( kEventClassKeyboard) , eventKind: OSType ( kEventHotKeyPressed) ) ]
82+ InstallEventHandler ( shortcutEventTarget, { ( _: EventHandlerCallRef ? , event: EventRef ? , _: UnsafeMutableRawPointer ? ) -> OSStatus in
83+ var id = EventHotKeyID ( )
84+ GetEventParameter ( event, EventParamName ( kEventParamDirectObject) , EventParamType ( typeEventHotKeyID) , nil , MemoryLayout< EventHotKeyID> . size, nil , & id)
85+ handleEvent ( id, . down, nil , nil , false , . global)
86+ return noErr
87+ } , hotKeyPressedEventTypes. count, & hotKeyPressedEventTypes, nil , & hotKeyPressedEventHandler)
88+ var hotKeyReleasedEventTypes = [ EventTypeSpec ( eventClass: OSType ( kEventClassKeyboard) , eventKind: OSType ( kEventHotKeyReleased) ) ]
89+ InstallEventHandler ( shortcutEventTarget, { ( _: EventHandlerCallRef ? , event: EventRef ? , _: UnsafeMutableRawPointer ? ) -> OSStatus in
90+ var id = EventHotKeyID ( )
91+ GetEventParameter ( event, EventParamName ( kEventParamDirectObject) , EventParamType ( typeEventHotKeyID) , nil , MemoryLayout< EventHotKeyID> . size, nil , & id)
92+ handleEvent ( id, . up, nil , nil , false , . global)
93+ return noErr
94+ } , hotKeyReleasedEventTypes. count, & hotKeyReleasedEventTypes, nil , & hotKeyReleasedEventHandler)
95+ }
8196
8297 private static func addCgEventTapForModifierFlags( ) {
8398 let eventMask = [ CGEventType . flagsChanged ] . reduce ( CGEventMask ( 0 ) , { $0 | ( 1 << $1. rawValue) } )
@@ -97,45 +112,59 @@ class KeyboardEvents {
97112 App . app. restart ( )
98113 }
99114 }
115+ }
100116
101- private static func addGlobalHandlerIfNeeded( _ shortcut: Shortcut ) {
102- if shortcut. keyCode != . none && hotKeyPressedEventHandler == nil {
103- var eventTypes = [ EventTypeSpec ( eventClass: OSType ( kEventClassKeyboard) , eventKind: OSType ( kEventHotKeyPressed) ) ]
104- InstallEventHandler ( shortcutEventTarget, { ( _: EventHandlerCallRef ? , event: EventRef ? , _: UnsafeMutableRawPointer ? ) -> OSStatus in
105- var id = EventHotKeyID ( )
106- GetEventParameter ( event, EventParamName ( kEventParamDirectObject) , EventParamType ( typeEventHotKeyID) , nil , MemoryLayout< EventHotKeyID> . size, nil , & id)
107- handleEvent ( id, . down, nil , nil , false )
108- return noErr
109- } , eventTypes. count, & eventTypes, nil , & hotKeyPressedEventHandler)
117+ fileprivate func handleShortcutModifierSide( _ modifiers: NSEvent . ModifierFlags ) {
118+ let sideModifiers : [ ( any: NSEvent . ModifierFlags , left : NSEvent . ModifierFlags , right : NSEvent . ModifierFlags ) ] = [
119+ ( . shift, . leftShift, . rightShift) ,
120+ ( . control, . leftControl, . rightControl) ,
121+ ( . option, . leftOption, . rightOption) ,
122+ ( . command, . leftCommand, . rightCommand)
123+ ]
124+ var removeShortcuts = [ ( id: String, shortcut: Shortcut) ] ( )
125+ var addShortcuts = [ ( id: String, shortcut: Shortcut) ] ( )
126+ for shortcutIndex in 0 ... 4 {
127+ let shortcutModifierSide = Preferences . shortcutModifierSide [ shortcutIndex]
128+ guard shortcutModifierSide != . any else {
129+ continue
110130 }
111- if shortcut. keyCode != . none && hotKeyReleasedEventHandler == nil {
112- var eventTypes = [ EventTypeSpec ( eventClass: OSType ( kEventClassKeyboard) , eventKind: OSType ( kEventHotKeyReleased) ) ]
113- InstallEventHandler ( shortcutEventTarget, { ( _: EventHandlerCallRef ? , event: EventRef ? , _: UnsafeMutableRawPointer ? ) -> OSStatus in
114- var id = EventHotKeyID ( )
115- GetEventParameter ( event, EventParamName ( kEventParamDirectObject) , EventParamType ( typeEventHotKeyID) , nil , MemoryLayout< EventHotKeyID> . size, nil , & id)
116- handleEvent ( id, . up, nil , nil , false )
117- return noErr
118- } , eventTypes. count, & eventTypes, nil , & hotKeyReleasedEventHandler)
131+ let holdShortcutId = Preferences . indexToName ( " holdShortcut " , shortcutIndex)
132+ let nextWindowShortcutId = Preferences . indexToName ( " nextWindowShortcut " , shortcutIndex)
133+ guard
134+ let holdShortcut = ControlsTab . shortcuts [ holdShortcutId] ? . shortcut,
135+ let nextWindowShortcut = ControlsTab . shortcuts [ nextWindowShortcutId] ? . shortcut
136+ else {
137+ continue
119138 }
120- }
121-
122- private static func removeHandlerIfNeeded( ) {
123- let globalShortcuts = ControlsTab . shortcuts. values. filter { $0. scope == . global }
124- if let hotKeyPressedEventHandler_ = hotKeyPressedEventHandler, let hotKeyReleasedEventHandler_ = hotKeyReleasedEventHandler,
125- ( globalShortcuts. allSatisfy { $0. shortcut. keyCode == . none } ) {
126- RemoveEventHandler ( hotKeyPressedEventHandler_)
127- hotKeyPressedEventHandler = nil
128- RemoveEventHandler ( hotKeyReleasedEventHandler_)
129- hotKeyReleasedEventHandler = nil
139+ if
140+ ( sideModifiers. filter {
141+ holdShortcut. modifierFlags. contains ( $0. any)
142+ } . allSatisfy {
143+ modifiers. contains ( shortcutModifierSide == . left ? $0. left : $0. right) &&
144+ !modifiers. contains ( shortcutModifierSide == . left ? $0. right : $0. left)
145+ } )
146+ {
147+ addShortcuts. append ( ( nextWindowShortcutId, nextWindowShortcut) )
148+ } else {
149+ if App . app. shortcutIndex == shortcutIndex && App . app. appIsBeingUsed {
150+ App . app. hideUi ( )
151+ }
152+ removeShortcuts. append ( ( nextWindowShortcutId, nextWindowShortcut) )
130153 }
131154 }
155+ removeShortcuts. forEach {
156+ KeyboardEvents . removeGlobalShortcutIfNeeded ( $0. id, $0. shortcut)
157+ }
158+ addShortcuts. forEach {
159+ KeyboardEvents . addGlobalShortcutIfNeeded ( $0. id, $0. shortcut, checkAnyModifierSide: false )
160+ }
132161}
133162
134163@discardableResult
135- fileprivate func handleEvent( _ id: EventHotKeyID ? , _ shortcutState: ShortcutState ? , _ keyCode: UInt32 ? , _ modifiers: UInt32 ? , _ isARepeat: Bool ) -> Bool {
164+ fileprivate func handleEvent( _ id: EventHotKeyID ? , _ shortcutState: ShortcutState ? , _ keyCode: UInt32 ? , _ modifiers: UInt32 ? , _ isARepeat: Bool , _ shortcutScope : ShortcutScope ) -> Bool {
136165 var someShortcutTriggered = false
137166 for shortcut in ControlsTab . shortcuts. values {
138- if shortcut. matches ( id, shortcutState, keyCode, modifiers, isARepeat) && shortcut. shouldTrigger ( ) {
167+ if shortcut. matches ( id, shortcutState, keyCode, modifiers, isARepeat, shortcutScope ) && shortcut. shouldTrigger ( ) {
139168 shortcut. executeAction ( isARepeat)
140169 someShortcutTriggered = true
141170 }
@@ -145,8 +174,9 @@ fileprivate func handleEvent(_ id: EventHotKeyID?, _ shortcutState: ShortcutStat
145174
146175fileprivate func cgEventFlagsChangedHandler( proxy: CGEventTapProxy , type: CGEventType , cgEvent: CGEvent , userInfo: UnsafeMutableRawPointer ? ) -> Unmanaged < CGEvent > ? {
147176 if type == . flagsChanged {
148- let modifiers = cocoaToCarbonFlags ( NSEvent . ModifierFlags ( rawValue: UInt ( cgEvent. flags. rawValue) ) )
149- handleEvent ( nil , nil , nil , modifiers, false )
177+ let modifiers = NSEvent . ModifierFlags ( rawValue: UInt ( cgEvent. flags. rawValue) )
178+ handleShortcutModifierSide ( modifiers)
179+ handleEvent ( nil , nil , nil , cocoaToCarbonFlags ( modifiers) , false , . global)
150180 } else if ( type == . tapDisabledByUserInput || type == . tapDisabledByTimeout) {
151181 CGEvent . tapEnable ( tap: eventTap!, enable: true )
152182 }
0 commit comments