fix: trust native global shortcut registration

This commit is contained in:
Valdemar Lorenzen
2026-10-16 13:59:54 +02:00
parent 6725be8ad5
commit c8b2e8e0c5
3 changed files with 3 additions and 25 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ Cancelling recording, changing destination, or leaving the recorder restores sav
For Command-Space, select **Applications** and choose **Use ⌘Space**. If it conflicts with Spotlight, Input Sources, or another app, change that binding in System Settings first. Conjure never changes macOS shortcuts for you. Shortcuts work while Conjure is running; they do not start a quit app or require Accessibility permission. For Command-Space, select **Applications** and choose **Use ⌘Space**. If it conflicts with Spotlight, Input Sources, or another app, change that binding in System Settings first. Conjure never changes macOS shortcuts for you. Shortcuts work while Conjure is running; they do not start a quit app or require Accessibility permission.
On macOS 27, [Siri AI uses Command-Shift-Space to select a window for screen capture](https://support.apple.com/en-is/guide/mac-help/iphmk4p88mkuky/mac). That system reservation can conflict even though it is not listed under Spotlight or Input Sources. Use another binding unless you have freed the Siri shortcut. Conjure lets macOS decide whether a global shortcut can be registered, rather than rejecting it solely because it appears in the system shortcut table. A registered shortcut can still compete with system behavior; if it does, change the conflicting system shortcut or choose another binding.
Install Conjure in `/Applications`, then enable **Launch at login** in Settings to start it in the background. If macOS requires approval, use **Open Login Items Settings…** to grant it. Install Conjure in `/Applications`, then enable **Launch at login** in Settings to start it in the background. If macOS requires approval, use **Open Login Items Settings…** to grant it.
-24
View File
@@ -89,36 +89,14 @@ public final class GlobalShortcut {
if let registration { if let registration {
try registration.activate(candidate) try registration.activate(candidate)
} else { } else {
try Self.rejectSystemConflict(candidate)
try native.register(candidate) try native.register(candidate)
} }
isRegistered = true isRegistered = true
} }
private static func rejectSystemConflict(_ candidate: KeyboardShortcut) throws {
var copied: Unmanaged<CFArray>?
let status = CopySymbolicHotKeys(&copied)
let result = copied?.takeRetainedValue()
guard status == noErr, let result else {
throw ShortcutError.native(operation: "read macOS keyboard shortcuts", status: status)
}
let hotKeys = result as NSArray
for case let record as NSDictionary in hotKeys {
guard let enabled = record[kHISymbolicHotKeyEnabled] as? NSNumber, enabled.boolValue,
let code = record[kHISymbolicHotKeyCode] as? NSNumber,
let modifiers = record[kHISymbolicHotKeyModifiers] as? NSNumber else { continue }
let relevantModifiers = UInt32(cmdKey | optionKey | controlKey | shiftKey)
if code.uint16Value == candidate.keyCode,
modifiers.uint32Value & relevantModifiers == candidate.carbonModifiers {
throw ShortcutError.systemConflict(candidate.displayName)
}
}
}
} }
enum ShortcutError: LocalizedError { enum ShortcutError: LocalizedError {
case invalidSavedShortcut case invalidSavedShortcut
case systemConflict(String)
case inAppConflict(shortcut: String, action: String) case inAppConflict(shortcut: String, action: String)
case duplicate(shortcut: String, destination: String) case duplicate(shortcut: String, destination: String)
case native(operation: String, status: OSStatus) case native(operation: String, status: OSStatus)
@@ -127,8 +105,6 @@ enum ShortcutError: LocalizedError {
switch self { switch self {
case .invalidSavedShortcut: case .invalidSavedShortcut:
return "The saved shortcut is invalid. Choose a new shortcut or clear it in Conjure Settings." return "The saved shortcut is invalid. Choose a new shortcut or clear it in Conjure Settings."
case .systemConflict(let shortcut):
return "\(shortcut) is already an enabled macOS shortcut. Check System Settings → Keyboard → Keyboard Shortcuts, including Spotlight and Input Sources. On macOS 27, Command-Shift-Space is also reserved for Siri AI screen capture. Choose another shortcut or change the system binding; Conjure will not change your system settings."
case .inAppConflict(let shortcut, let action): case .inAppConflict(let shortcut, let action):
return "\(shortcut) is already used by Conjure for \(action). Choose another shortcut." return "\(shortcut) is already used by Conjure for \(action). Choose another shortcut."
case .duplicate(let shortcut, let destination): case .duplicate(let shortcut, let destination):
+2
View File
@@ -1,2 +1,4 @@
- [ ] conjure should pop up quicker when launching than it currently does.
- [ ] conjure emoji selector should have an extra action (default) that both copies and tries to paste the selected emoji into the application that was focused when the conjure window was spawned.
- [ ] add a notes app inspired by raycast notes - [ ] add a notes app inspired by raycast notes
- [ ] improve on the conjure translation command - [ ] improve on the conjure translation command