Skip to content

Commit a6db708

Browse files
Support decoding keyboardHIDUsage from AppKit function key codes
1 parent e1cb256 commit a6db708

4 files changed

Lines changed: 113 additions & 35 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
# KeyCodes
1010

11-
Versions of `UIKey`, `UIKeyboardHIDUsage`, and `UIKeyModifierFlags` that work with AppKit's `NSEvent`. No need for Carbon.HIToolbox. Aside from being a nicer API to work with, these versions should make it possible to more easily write source-compatible AppKit/UIKit keyboard handling code. Yes, this is basically a gigantic switch statement.
11+
Versions of `UIKey`, `UIKeyboardHIDUsage`, and `UIKeyModifierFlags` that work with AppKit's `NSEvent`. No need for Carbon.HIToolbox or using the `NS*FunctionKey` codes. Aside from being a nicer API to work with, these versions should make it possible to more easily write source-compatible AppKit/UIKit keyboard handling code. Yes, this is basically a gigantic switch statement.
1212

1313
These structures are particularly helpful for writing tests. Constructing `NSEvent` instances by hand is a pain.
1414

@@ -47,7 +47,7 @@ func withKeyCodes(_ event: NSEvent) {
4747

4848
```swift
4949
dependencies: [
50-
.package(url: "https://github.com/ChimeHQ/KeyCodes", from: "0.1.1")
50+
.package(url: "https://github.com/ChimeHQ/KeyCodes", from: "1.0.3")
5151
]
5252
```
5353

Sources/KeyCodes/NSEvent+Key.swift

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,13 @@ extension NSEvent {
118118
case kVK_ANSI_9:
119119
return .keyboard9
120120

121-
case kVK_LeftArrow:
121+
case kVK_LeftArrow, NSLeftArrowFunctionKey:
122122
return .keyboardLeftArrow
123-
case kVK_RightArrow:
123+
case kVK_RightArrow, NSRightArrowFunctionKey:
124124
return .keyboardRightArrow
125-
case kVK_UpArrow:
125+
case kVK_UpArrow, NSUpArrowFunctionKey:
126126
return .keyboardUpArrow
127-
case kVK_DownArrow:
127+
case kVK_DownArrow, NSDownArrowFunctionKey:
128128
return .keyboardDownArrow
129129

130130
case kVK_ANSI_Equal:
@@ -181,64 +181,64 @@ extension NSEvent {
181181
case kVK_ANSI_Keypad9:
182182
return .keypad9
183183

184-
case kVK_F1:
184+
case kVK_F1, NSF1FunctionKey:
185185
return .keyboardF1
186-
case kVK_F2:
186+
case kVK_F2, NSF2FunctionKey:
187187
return .keyboardF2
188-
case kVK_F3:
188+
case kVK_F3, NSF3FunctionKey:
189189
return .keyboardF3
190-
case kVK_F4:
190+
case kVK_F4, NSF4FunctionKey:
191191
return .keyboardF4
192-
case kVK_F5:
192+
case kVK_F5, NSF5FunctionKey:
193193
return .keyboardF5
194-
case kVK_F6:
194+
case kVK_F6, NSF6FunctionKey:
195195
return .keyboardF6
196-
case kVK_F7:
196+
case kVK_F7, NSF7FunctionKey:
197197
return .keyboardF7
198-
case kVK_F8:
198+
case kVK_F8, NSF8FunctionKey:
199199
return .keyboardF8
200-
case kVK_F9:
200+
case kVK_F9, NSF9FunctionKey:
201201
return .keyboardF9
202-
case kVK_F10:
202+
case kVK_F10, NSF10FunctionKey:
203203
return .keyboardF10
204-
case kVK_F11:
204+
case kVK_F11, NSF11FunctionKey:
205205
return .keyboardF11
206-
case kVK_F12:
206+
case kVK_F12, NSF12FunctionKey:
207207
return .keyboardF12
208-
case kVK_F13:
208+
case kVK_F13, NSF13FunctionKey:
209209
return .keyboardF13
210-
case kVK_F14:
210+
case kVK_F14, NSF14FunctionKey:
211211
return .keyboardF14
212-
case kVK_F15:
212+
case kVK_F15, NSF15FunctionKey:
213213
return .keyboardF15
214-
case kVK_F16:
214+
case kVK_F16, NSF16FunctionKey:
215215
return .keyboardF16
216-
case kVK_F17:
216+
case kVK_F17, NSF17FunctionKey:
217217
return .keyboardF17
218-
case kVK_F18:
218+
case kVK_F18, NSF18FunctionKey:
219219
return .keyboardF18
220-
case kVK_F19:
220+
case kVK_F19, NSF19FunctionKey:
221221
return .keyboardF19
222-
case kVK_F20:
222+
case kVK_F20, NSF20FunctionKey:
223223
return .keyboardF20
224224

225-
case kVK_PageUp:
225+
case kVK_PageUp, NSPageUpFunctionKey:
226226
return .keyboardPageUp
227-
case kVK_PageDown:
227+
case kVK_PageDown, NSPageDownFunctionKey:
228228
return .keyboardPageDown
229-
case kVK_Home:
229+
case kVK_Home, NSHomeFunctionKey:
230230
return .keyboardHome
231-
case kVK_End:
231+
case kVK_End, NSEndFunctionKey:
232232
return .keyboardEnd
233-
case kVK_Help:
233+
case kVK_Help, NSHelpFunctionKey:
234234
return .keyboardHelp
235235
case kVK_Return:
236236
return .keyboardReturn
237237
case kVK_Tab:
238238
return .keyboardTab
239239
case kVK_Space:
240240
return .keyboardSpacebar
241-
case kVK_Delete:
241+
case kVK_Delete, NSDeleteFunctionKey:
242242
return .keyboardDeleteOrBackspace
243243
case kVK_ForwardDelete:
244244
return .keyboardDeleteForward
@@ -249,6 +249,17 @@ extension NSEvent {
249249
case kVK_VolumeDown:
250250
return .keyboardVolumeDown
251251

252+
case NSPrintScreenFunctionKey:
253+
return .keyboardPrintScreen
254+
case NSUndoFunctionKey:
255+
return .keyboardUndo
256+
case NSFindFunctionKey:
257+
return .keyboardFind
258+
case NSSelectFunctionKey:
259+
return .keyboardSelect
260+
case NSMenuFunctionKey:
261+
return .keyboardMenu
262+
252263
default:
253264
return nil
254265
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
extension Character {
2-
init?(utf16CodePoint: UInt16) {
2+
/// Creates a character representing the a single UTF-16 code point.
3+
public init?(utf16CodePoint: UInt16) {
34
guard let scalar = Unicode.Scalar(utf16CodePoint) else {
45
return nil
56
}
@@ -9,11 +10,12 @@ extension Character {
910
}
1011

1112
extension String {
12-
init?(utf16CodePoint: UInt16) {
13+
/// Creates a string containing a single UTF-16 code point.
14+
public init?(utf16CodePoint: UInt16) {
1315
guard let char = Character(utf16CodePoint: utf16CodePoint) else {
1416
return nil
1517
}
1618

1719
self.init(char)
1820
}
19-
}
21+
}

Tests/KeyCodesTests/NSEventTests.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Testing
12
import XCTest
23
import KeyCodes
34

@@ -29,4 +30,68 @@ final class NSEventTests: XCTestCase {
2930
XCTAssertEqual(event.keyModifierFlags, [.command])
3031
}
3132
}
33+
34+
extension NSEvent {
35+
static func keyEvent(withUTF6CodePointKeyCode: Int) -> NSEvent? {
36+
let char = UInt16(withUTF6CodePointKeyCode)
37+
guard let string = String(utf16CodePoint: char) else {
38+
return nil
39+
}
40+
41+
return NSEvent.keyEvent(
42+
with: .keyDown,
43+
location: .zero,
44+
modifierFlags: [],
45+
timestamp: 0,
46+
windowNumber: 0,
47+
context: nil,
48+
characters: string,
49+
charactersIgnoringModifiers: string,
50+
isARepeat: false,
51+
keyCode: char
52+
)
53+
}
54+
}
55+
56+
struct TestingNSEventTests {
57+
@Test func functionKeyMapping() throws {
58+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSUpArrowFunctionKey)?.keyboardHIDUsage == .keyboardUpArrow)
59+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSDownArrowFunctionKey)?.keyboardHIDUsage == .keyboardDownArrow)
60+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSLeftArrowFunctionKey)?.keyboardHIDUsage == .keyboardLeftArrow)
61+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSRightArrowFunctionKey)?.keyboardHIDUsage == .keyboardRightArrow)
62+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSHomeFunctionKey)?.keyboardHIDUsage == .keyboardHome)
63+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSDeleteFunctionKey)?.keyboardHIDUsage == .keyboardDeleteOrBackspace)
64+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSPageUpFunctionKey)?.keyboardHIDUsage == .keyboardPageUp)
65+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSPageDownFunctionKey)?.keyboardHIDUsage == .keyboardPageDown)
66+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSPrintScreenFunctionKey)?.keyboardHIDUsage == .keyboardPrintScreen)
67+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSUndoFunctionKey)?.keyboardHIDUsage == .keyboardUndo)
68+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSHelpFunctionKey)?.keyboardHIDUsage == .keyboardHelp)
69+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSFindFunctionKey)?.keyboardHIDUsage == .keyboardFind)
70+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSSelectFunctionKey)?.keyboardHIDUsage == .keyboardSelect)
71+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSMenuFunctionKey)?.keyboardHIDUsage == .keyboardMenu)
72+
73+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF1FunctionKey)?.keyboardHIDUsage == .keyboardF1)
74+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF2FunctionKey)?.keyboardHIDUsage == .keyboardF2)
75+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF3FunctionKey)?.keyboardHIDUsage == .keyboardF3)
76+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF4FunctionKey)?.keyboardHIDUsage == .keyboardF4)
77+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF5FunctionKey)?.keyboardHIDUsage == .keyboardF5)
78+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF6FunctionKey)?.keyboardHIDUsage == .keyboardF6)
79+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF7FunctionKey)?.keyboardHIDUsage == .keyboardF7)
80+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF8FunctionKey)?.keyboardHIDUsage == .keyboardF8)
81+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF9FunctionKey)?.keyboardHIDUsage == .keyboardF9)
82+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF10FunctionKey)?.keyboardHIDUsage == .keyboardF10)
83+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF11FunctionKey)?.keyboardHIDUsage == .keyboardF11)
84+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF12FunctionKey)?.keyboardHIDUsage == .keyboardF12)
85+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF13FunctionKey)?.keyboardHIDUsage == .keyboardF13)
86+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF14FunctionKey)?.keyboardHIDUsage == .keyboardF14)
87+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF15FunctionKey)?.keyboardHIDUsage == .keyboardF15)
88+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF16FunctionKey)?.keyboardHIDUsage == .keyboardF16)
89+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF17FunctionKey)?.keyboardHIDUsage == .keyboardF17)
90+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF18FunctionKey)?.keyboardHIDUsage == .keyboardF18)
91+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF19FunctionKey)?.keyboardHIDUsage == .keyboardF19)
92+
#expect(NSEvent.keyEvent(withUTF6CodePointKeyCode: NSF20FunctionKey)?.keyboardHIDUsage == .keyboardF20)
93+
94+
}
95+
}
96+
3297
#endif

0 commit comments

Comments
 (0)