Skip to content

Commit b3dca8c

Browse files
committed
Audit Linux keyboard
1 parent f76f0ec commit b3dca8c

File tree

7 files changed

+662
-373
lines changed

7 files changed

+662
-373
lines changed

Sources/GateEngine/System/HID/Keyboard/Keyboard.swift

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,115 @@ import GameMath
1515

1616
internal var activeStreams: Set<WeakCharacterStream> = []
1717

18-
public func button(_ keyboardKey: KeyboardKey) -> ButtonState {
18+
/**
19+
Gets a ``ButtonState`` associcated with the physical key.
20+
21+
When requesting a key represents multiple buttons, such as with `.character("1", .anyVariation)`, the `ButtonState` returned will be one of the represented physical keys.
22+
If you keep a reference to the ``ButtonState`` you will only be checking that physical button. Request a new ``ButtonState`` each time to ensure any variation of the ``KeyboardKey`` is returned.
23+
24+
When requesting with a physical ``KeyboardKey``, like `.shift(.leftSide)`, it is okay to keep a reference to the ``ButtonState``.
25+
26+
- parameter keybordKey: A ``KeyboardKey`` that represents a physical keyboard button.
27+
- note: Non-physical keys are keys which have no physical button, like `.control(.anything)` or `.character("0", .anyVariation)`
28+
- returns: A ``ButtonState``, or `nil` if the key is not a physical key.
29+
*/
30+
public func button(_ keyboardKey: KeyboardKey) -> ButtonState? {
1931
if let exactMatch = buttons[keyboardKey] {
2032
return exactMatch
2133
}
2234
if let existing = buttons.first(where: { (key: KeyboardKey, value: ButtonState) in
2335
if case let .character(character1, origin1) = keyboardKey {
2436
if case let .character(character2, origin2) = key {
2537
guard character1 == character2 else {return false}
26-
if origin1 == .fromAnywhere || origin2 == .fromAnywhere {
27-
return true
38+
if origin1 == origin2 || origin1 == .anyVariation {
39+
return value.isPressed
2840
}
29-
return origin1 == origin2
3041
}
3142
return false
3243
}
3344
if case let .enter(origin1) = keyboardKey {
3445
if case let .enter(origin2) = key {
35-
if origin1 == .fromAnywhere || origin2 == .fromAnywhere {
36-
return true
46+
if origin1 == origin2 || origin1 == .anyVariation {
47+
return value.isPressed
48+
}
49+
}
50+
return false
51+
}
52+
if case let .shift(alignment1) = keyboardKey {
53+
if case let .shift(alignment2) = key {
54+
if alignment1 == .anyVariation || alignment2 == .anyVariation {
55+
return value.isPressed
56+
}
57+
}
58+
return false
59+
}
60+
if case let .control(alignment1) = keyboardKey {
61+
if case let .control(alignment2) = key {
62+
if alignment1 == .anyVariation || alignment2 == .anyVariation {
63+
return value.isPressed
64+
}
65+
}
66+
return false
67+
}
68+
if case let .alt(alignment1) = keyboardKey {
69+
if case let .alt(alignment2) = key {
70+
if alignment1 == .anyVariation || alignment2 == .anyVariation {
71+
return value.isPressed
72+
}
73+
}
74+
return false
75+
}
76+
if case let .host(alignment1) = keyboardKey {
77+
if case let .host(alignment2) = key {
78+
if alignment1 == .anyVariation || alignment2 == .anyVariation {
79+
return value.isPressed
3780
}
38-
return origin1 == origin2
3981
}
4082
return false
4183
}
4284
return false
4385
}) {
4486
return existing.value
4587
}
46-
let button = ButtonState(keyboard: self, key: keyboardKey)
47-
buttons[keyboardKey] = button
48-
return button
88+
switch keyboardKey {
89+
// Non-physical keys can't have a button
90+
case .shift(.anyVariation), .alt(.anyVariation), .host(.anyVariation),
91+
.control(.anyVariation), .enter(.anyVariation),
92+
.character(_, .anyVariation), .unhandledPlatformKeyCode(_, _):
93+
return nil
94+
default:
95+
let button = ButtonState(keyboard: self, key: keyboardKey)
96+
buttons[keyboardKey] = button
97+
return button
98+
}
4999
}
50100

101+
/// All currently pressed keyboard keys
51102
@inlinable @inline(__always)
52103
public func pressedButtons() -> [KeyboardKey:ButtonState] {
53104
return buttons.filter({$0.value.isPressed})
54105
}
106+
107+
108+
internal func _button(_ keyboardKey: KeyboardKey) -> ButtonState {
109+
#if GATEENGINE_DEBUG_HID
110+
switch keyboardKey {
111+
// Non-physical keys can't have a button
112+
case .shift(.anyVariation), .alt(.anyVariation), .host(.anyVariation),
113+
.control(.anyVariation), .enter(.anyVariation),
114+
.character(_, .anyVariation), .unhandledPlatformKeyCode(_, _):
115+
assertionFailure("pass physical keys only")
116+
default:
117+
break
118+
}
119+
#endif
120+
if let exactMatch = buttons[keyboardKey] {
121+
return exactMatch
122+
}
123+
let button = ButtonState(keyboard: self, key: keyboardKey)
124+
buttons[keyboardKey] = button
125+
return button
126+
}
55127
}
56128

57129

@@ -65,28 +137,56 @@ public extension Keyboard {
65137
internal var currentRecipt: UInt8 = 0
66138

67139
nonisolated public var description: String {
68-
if case .unhandledPlatformKeyCode(let keyCode, let character) = key {
140+
switch key {
141+
case .unhandledPlatformKeyCode(let keyCode, let character):
69142
let keyCodeString: String
70143
if let keyCode {
71144
keyCodeString = "\(keyCode)"
72145
}else{
73146
keyCodeString = "nil"
74147
}
75148
var characterString: String
76-
if let character, character.isEmpty == false {
149+
if let character{
77150
switch character {
78151
case "\r":
79152
characterString = "\\r"
80153
case "\n":
81154
characterString = "\\n"
82155
default:
83-
characterString = character
156+
characterString = String(character)
84157
}
85158
}else{
86159
characterString = "nil"
87160
}
88161
return "unhandledPlatformKeyCode(\(keyCodeString), \(characterString))"
162+
case .character(let character, _):
163+
return "\(character)"
164+
case .function(let index):
165+
return "F\(index)"
166+
case .enter(.standard):
167+
return "Enter"
168+
case .enter(.numberPad):
169+
return "Enter(NumPad)"
170+
case .alt(.leftSide):
171+
return "Left Alt"
172+
case .alt(.rightSide):
173+
return "Right Alt"
174+
case .host(.leftSide):
175+
return "Left Host"
176+
case .host(.rightSide):
177+
return "Right Host"
178+
case .control(.leftSide):
179+
return "Left Control"
180+
case .control(.rightSide):
181+
return "Right Control"
182+
case .shift(.leftSide):
183+
return "Left Shift"
184+
case .shift(.rightSide):
185+
return "Right Shift"
186+
default:
187+
break
89188
}
189+
90190
return "\(key)"
91191
}
92192

@@ -140,19 +240,20 @@ extension Keyboard {
140240
switch event {
141241
case .keyDown:
142242
if isRepeat == false {
143-
self.button(key).isPressed = true
243+
self._button(key).isPressed = true
144244
self.modifiers = modifiers
145245
}
146246
_ = self.updateStreams(with: key, character: character)
147247
case .keyUp:
148-
self.button(key).isPressed = false
248+
self._button(key).isPressed = false
149249
self.modifiers = modifiers
150250
case .toggle:
151251
if isRepeat == false {
152-
if self.button(key).isPressed == false {
153-
self.button(key).isPressed = true
252+
let button = self._button(key)
253+
if button.isPressed == false {
254+
button.isPressed = true
154255
}else{
155-
self.button(key).isPressed = false
256+
button.isPressed = false
156257
}
157258
}
158259
}

Sources/GateEngine/System/HID/Keyboard/KeyboardKey.swift

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ public enum KeyboardKey: Hashable {
5555

5656
public enum KeyOrigin {
5757
// Any part of the keyboard
58-
case fromAnywhere
58+
case anyVariation
5959
// The main keyboard area
60-
case fromMain
60+
case standard
6161
// The numeric key pad area
62-
case fromNumberPad
62+
case numberPad
6363
}
6464
/**
6565
The primary (not shift) symbol on the face of a physical key.
@@ -68,7 +68,7 @@ public enum KeyboardKey: Hashable {
6868
- note: `character` is in qwerty layout. If you use another layoit for devlopment you can use the following function to translate:
6969
``KeyboardKey.qwerty(_,_)``, ``KeyboardKey.qwertz(_,_)``, ``KeyboardKey.azerty(_,_)``
7070
*/
71-
case character(_ character: Character, _ origin: KeyOrigin = .fromAnywhere)
71+
case character(_ character: Character, _ origin: KeyOrigin = .anyVariation)
7272

7373
/// The backspace or delete key
7474
case backspace
@@ -91,15 +91,15 @@ public enum KeyboardKey: Hashable {
9191
- parameter int: A key code represented as an Int
9292
- parameter string: A key represented as a String
9393
*/
94-
case unhandledPlatformKeyCode(_ int: Int?, _ string: String?)
94+
case unhandledPlatformKeyCode(_ int: Int?, _ string: Character?)
9595

9696
public enum Alignment {
9797
// Any key
98-
case anything
98+
case anyVariation
9999
// On the left of the space bar
100-
case left
100+
case leftSide
101101
// On the right of the space bar
102-
case right
102+
case rightSide
103103
}
104104
case alt(_ alignment: Alignment)
105105
case host(_ alignment: Alignment)
@@ -139,8 +139,8 @@ extension KeyboardKey {
139139
- parameter origin: The location of the key on the keyboard. `nil` means any instance of the key.
140140
- note: If you are solo and use qwerty, this function can be omitted as the unerlying representation is already \"qwerty\".
141141
*/
142-
@_transparent
143-
public static func qwerty(_ character: Character, origin: KeyOrigin = .fromAnywhere) -> Self {
142+
@inlinable @inline(__always) @_transparent
143+
public static func qwerty(_ character: Character, origin: KeyOrigin = .anyVariation) -> Self {
144144
return .character(character, origin)
145145
}
146146

@@ -153,7 +153,8 @@ extension KeyboardKey {
153153
- parameter character: The character on your keyboard, assuming your keyboard layout is \"qwertz\".
154154
- parameter origin: The location of the key on the keyboard. `nil` means any instance of the key.
155155
*/
156-
public static func qwertz(_ character: Character, origin: KeyOrigin = .fromAnywhere) -> Self {
156+
@inlinable @inline(__always)
157+
public static func qwertz(_ character: Character, origin: KeyOrigin = .anyVariation) -> Self {
157158
switch character {
158159
case "<":
159160
return .character("`", origin)
@@ -198,7 +199,8 @@ extension KeyboardKey {
198199
- parameter character: The character on your keyboard, assuming your keyboard layout is \"azerty\".
199200
- parameter origin: The location of the key on the keyboard. `nil` means any instance of the key.
200201
*/
201-
public static func azerty(_ character: Character, origin: KeyOrigin = .fromAnywhere) -> Self {
202+
@inlinable @inline(__always)
203+
public static func azerty(_ character: Character, origin: KeyOrigin = .anyVariation) -> Self {
202204
switch character {
203205
case "<":
204206
return .character("`", origin)

0 commit comments

Comments
 (0)