Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Sources/KeyboardShortcuts/HotKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ final class HotKeyCenter {
return nil
}

private var globalEventMonitor: AnyObject?

var mode: Mode = .normal {
didSet {
guard mode != oldValue else {
Expand Down Expand Up @@ -219,6 +221,7 @@ final class HotKeyCenter {
}

hotKeys.removeValue(forKey: hotKey.id)
updateEventHandler()
}

private func pause(_ hotKey: HotKey) {
Expand Down Expand Up @@ -324,6 +327,38 @@ final class HotKeyCenter {

setHotKeyEventHandlingEnabled(shouldHandleHotKeys)
setRawKeyEventHandlingEnabled(shouldHandleRawKeys)
setGlobalOptionKeyMonitorEnabled(mode == .normal && hasOptionOnlyShortcuts)
}

/**
Returns true if any registered shortcut uses Option as the only modifier (no Command or Control).
Such shortcuts are prone to being intercepted by the IME layer before Carbon receives them.
*/
private var hasOptionOnlyShortcuts: Bool {
hotKeys.values.compactMap(\.value).contains { hotKey in
let modifiers = NSEvent.ModifierFlags(carbon: hotKey.carbonModifiers)
return modifiers.contains(.option)
&& !modifiers.contains(.command)
&& !modifiers.contains(.control)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a more appropriate check would be:

modifiers == [.option]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

}
}
Comment on lines +333 to +342

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't work if a user has also shortcuts with different modifiers. It would be best to combine both the current solution and the new one, I guess.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe your application is more important and should run globally.
I removed all the hotkeys I found while setting up the workspace.


private func setGlobalOptionKeyMonitorEnabled(_ isEnabled: Bool) {
if isEnabled, globalEventMonitor == nil {
globalEventMonitor = NSEvent.addGlobalMonitorForEvents(matching: [.keyDown, .keyUp]) { [weak self] event in
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires accessibility access, so it's a no-go. From docs:

Key-related events may only be monitored if accessibility is enabled or if your application is trusted for accessibility access (see AXIsProcessTrusted()).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many apps use accessibility API. How about making it optional? Clients could decide wheter they want to use this API or not.

guard
let self,
let eventRef = OpaquePointer(event.eventRef)
else {
return
}

_ = handleRawKeyEvent(eventRef)
}
} else if !isEnabled, let monitor = globalEventMonitor {
NSEvent.removeMonitor(monitor)
globalEventMonitor = nil
}
}

private func setHotKeyEventHandlingEnabled(_ isEnabled: Bool) {
Expand Down