How to handle keyDown in NSResponder

Issue #760

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import AppKit
import Omnia

class MyWindow: NSWindow {
override func keyDown(with event: NSEvent) {
super.keyDown(with: event)

if isKey(NSDeleteCharacter, event: event) {
NotificationCenter.default.post(Notification(name: .didKeyboardDeleteItem))
} else if isKey(NSUpArrowFunctionKey, event: event) {
print("up")
} else if isKey(NSDownArrowFunctionKey, event: event) {
print("down")
} else if isKey(NSLeftArrowFunctionKey, event: event) {
print("left")
} else if isKey(NSRightArrowFunctionKey, event: event) {
print("right")
}
}

private func isKey(_ key: Int, event: NSEvent) -> Bool {
if let scalar = UnicodeScalar(key) {
return event.characters == String(scalar)
} else {
return false
}
}
}

Another way is to listen to

1
2
3
4
5
6
NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in
if handled(with: $0) {
return nil
}
return event
}

Or create our own inspector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class MyWindow: NSWindow {
override func keyDown(with event: NSEvent) {
if !EventService.shared.inspect(event) {
super.keyDown(with: event)
}
}

override var canBecomeKey: Bool { true }
override var canBecomeMain: Bool { true }
override var acceptsFirstResponder: Bool { true }
override func becomeFirstResponder() -> Bool { true }
}

import AppKit
import Omnia
import KeyboardShortcuts

final class EventService {
static let shared = EventService()

private var combos: [Combo] = []
private let debouncer = Debouncer(delay: 0.1)

func register(_ combo: Combo) {
combos.append(combo)
}

func inspect(_ event: NSEvent) -> Bool {
for combo in combos {
if combo.match(event) {
self.debouncer.run {
combo.action()
}
return true
}
}

return false
}
}

extension EventService {
struct Combo {
let modifier: NSEvent.ModifierFlags?
let keyCode: KeyboardShortcuts.Key
let action: () -> Void

func match(_ event: NSEvent) -> Bool {
if let modifier = modifier,
!event.modifierFlags.contains(modifier) {
return false
}

if event.keyCode != keyCode.rawValue {
return false
}

return true
}
}
}

Updated at 2021-01-25 20:05:08

Comments