summaryrefslogtreecommitdiffstats
path: root/Sources
diff options
context:
space:
mode:
Diffstat (limited to 'Sources')
-rw-r--r--Sources/DDHotKey/DDHotKey.swift6
-rw-r--r--Sources/DDHotKey/DDHotKeyCenter.swift8
-rw-r--r--Sources/DDHotKey/DDHotKeyTextField.swift124
3 files changed, 131 insertions, 7 deletions
diff --git a/Sources/DDHotKey/DDHotKey.swift b/Sources/DDHotKey/DDHotKey.swift
index 0f3c93e..e8523bf 100644
--- a/Sources/DDHotKey/DDHotKey.swift
+++ b/Sources/DDHotKey/DDHotKey.swift
@@ -15,9 +15,9 @@ public class DDHotKey {
internal let uuid = UUID()
internal let keyCode: CGKeyCode
internal let modifiers: NSEvent.ModifierFlags
- internal let handler: (NSEvent) -> Void
+ public var handler: ((NSEvent) -> Void)?
- public init(keyCode: CGKeyCode, modifiers: NSEvent.ModifierFlags, handler: @escaping (NSEvent) -> Void) {
+ public init(keyCode: CGKeyCode, modifiers: NSEvent.ModifierFlags, handler: ((NSEvent) -> Void)? = nil) {
self.keyCode = keyCode
self.modifiers = modifiers
self.handler = handler
@@ -32,7 +32,7 @@ public class DDHotKey {
}
internal func invoke(with event: NSEvent) {
- handler(event)
+ handler?(event)
}
}
diff --git a/Sources/DDHotKey/DDHotKeyCenter.swift b/Sources/DDHotKey/DDHotKeyCenter.swift
index 84a456d..9625890 100644
--- a/Sources/DDHotKey/DDHotKeyCenter.swift
+++ b/Sources/DDHotKey/DDHotKeyCenter.swift
@@ -14,13 +14,13 @@ public class DDHotKeyCenter {
case alreadyRegistered
case tooManyHotKeys
case conflictsWithExistingHotKey(DDHotKey)
- case unableToRegisterHotKey(OSStatus)
+ case cannotRegisterHotKey(OSStatus)
}
public enum UnregistrationError: Error {
case notRegistered
case unknownHotKey
- case unableToUnregisterHotKey(OSStatus)
+ case cannotUnregisterHotKey(OSStatus)
}
public static let shared = DDHotKeyCenter()
@@ -72,7 +72,7 @@ public class DDHotKeyCenter {
let error = RegisterEventHotKey(UInt32(hotKey.keyCode), flags, hotKeyID, GetEventDispatcherTarget(), 0, &hotKeyRef)
if error != noErr {
- throw RegistrationError.unableToRegisterHotKey(error)
+ throw RegistrationError.cannotRegisterHotKey(error)
}
hotKey.hotKeyRef = hotKeyRef
@@ -94,7 +94,7 @@ public class DDHotKeyCenter {
let status = UnregisterEventHotKey(ref)
guard status == noErr else {
- throw UnregistrationError.unableToUnregisterHotKey(status)
+ throw UnregistrationError.cannotUnregisterHotKey(status)
}
registered.removeValue(forKey: hotKey.uuid)
diff --git a/Sources/DDHotKey/DDHotKeyTextField.swift b/Sources/DDHotKey/DDHotKeyTextField.swift
new file mode 100644
index 0000000..8c71408
--- /dev/null
+++ b/Sources/DDHotKey/DDHotKeyTextField.swift
@@ -0,0 +1,124 @@
+//
+// DDHotKeyTextField.swift
+//
+//
+// Created by Dave DeLong on 12/8/19.
+//
+
+#if canImport(AppKit)
+
+import AppKit
+import Carbon
+
+fileprivate let DDFieldEditor: DDHotKeyTextFieldEditor = {
+ let editor = DDHotKeyTextFieldEditor(frame: NSRect(x: 0, y: 0, width: 100, height: 32))
+ editor.isFieldEditor = true
+ return editor
+}()
+
+open class DDHotKeyTextField: NSTextField {
+
+ open override class var cellClass: AnyClass? {
+ get { return DDHotKeyTextFieldCell.self }
+ set { super.cellClass = DDHotKeyTextFieldCell.self }
+ }
+
+ public var hotKey: DDHotKey? {
+ didSet {
+ super.stringValue = ""
+ }
+ }
+
+ open override var stringValue: String {
+ get {
+ print("DDHotKeyTextField.stringValue is not what you want. Use DDHotKeyTextField.hotKey instead.")
+ return super.stringValue
+ }
+ set {
+ print("DDHotKeyTextField.stringValue is not what you want. Use DDHotKeyTextField.hotKey instead.")
+ super.stringValue = newValue
+ }
+ }
+
+}
+
+private class DDHotKeyTextFieldCell: NSTextFieldCell {
+
+ override func fieldEditor(for controlView: NSView) -> NSTextView? {
+ guard let hkField = controlView as? DDHotKeyTextField else { return nil }
+
+ let editor = DDFieldEditor
+ editor.insertionPointColor = editor.backgroundColor
+ editor.hotKeyField = hkField
+ return editor
+ }
+
+}
+
+fileprivate class DDHotKeyTextFieldEditor: NSTextView {
+ private var hasSeenKeyDown: Bool = false
+ private var globalMonitor: Any?
+ private var originalHotKey: DDHotKey?
+
+ weak var hotKeyField: DDHotKeyTextField? {
+ didSet {
+ originalHotKey = hotKeyField?.hotKey
+ }
+ }
+
+ override func becomeFirstResponder() -> Bool {
+ guard super.becomeFirstResponder() else { return false }
+
+ hasSeenKeyDown = false
+ globalMonitor = NSEvent.addLocalMonitorForEvents(matching: [.keyDown, .flagsChanged], handler: self.processHotKeyEvent(_:))
+
+ return true
+ }
+
+ override func resignFirstResponder() -> Bool {
+ guard super.resignFirstResponder() else { return false }
+ hasSeenKeyDown = false
+ hotKeyField = nil
+ if let m = globalMonitor {
+ NSEvent.removeMonitor(m)
+ globalMonitor = nil
+ }
+ return true
+ }
+
+ private func processHotKeyEvent(_ event: NSEvent) -> NSEvent? {
+ let flags = event.modifierFlags
+ let hasModifier = flags.contains(.command) || flags.contains(.option) || flags.contains(.control) || flags.contains(.shift) || flags.contains(.function)
+
+ if event.type == .keyDown {
+ hasSeenKeyDown = true
+ let char = event.charactersIgnoringModifiers?.first
+
+ if hasModifier == false && (char?.isNewline == true || event.keyCode == Int16(kVK_Escape)) {
+ if event.keyCode == Int16(kVK_Escape) {
+ hotKeyField?.hotKey = originalHotKey
+
+ let str = stringFrom(keyCode: event.keyCode, modifiers: flags)
+ textStorage?.mutableString.setString(str.uppercased())
+ }
+
+ hotKeyField?.sendAction(hotKeyField?.action, to: hotKeyField?.target)
+ window?.makeFirstResponder(nil)
+ }
+ }
+
+ if hasModifier && (event.type == .keyDown || (event.type == .flagsChanged && hasSeenKeyDown == false)) {
+
+ hotKeyField?.hotKey = DDHotKey(keyCode: event.keyCode, modifiers: flags, handler: originalHotKey?.handler)
+
+ let str = stringFrom(keyCode: event.keyCode, modifiers: flags)
+ textStorage?.mutableString.setString(str.uppercased())
+ hotKeyField?.sendAction(hotKeyField?.action, to: hotKeyField?.target)
+ }
+
+ return nil
+ }
+
+}
+
+#endif