Skip to content

Commit f76f0ec

Browse files
committed
Continue keyboard audit
1 parent 34c4138 commit f76f0ec

File tree

9 files changed

+671
-606
lines changed

9 files changed

+671
-606
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright © 2023 Dustin Collins (Strega's Gate)
3+
* All Rights Reserved.
4+
*
5+
* http://stregasgate.com
6+
*/
7+
8+
public final class CharacterStream {
9+
public internal(set) var string: String
10+
public var cursor: String.Index
11+
12+
public init() {
13+
let emptyString = ""
14+
string = emptyString
15+
cursor = emptyString.startIndex
16+
}
17+
18+
internal func insert(_ character: Character?, as key: KeyboardKey) {
19+
@_transparent
20+
func insertCharacter(_ character: Character) {
21+
self.string.insert(character, at: cursor)
22+
self.cursor = string.index(after: cursor)
23+
}
24+
@_transparent
25+
func moveLeft() {
26+
if cursor > string.startIndex {
27+
let index = string.index(before: cursor)
28+
cursor = index
29+
}
30+
}
31+
@_transparent
32+
func moveRight() {
33+
if cursor < string.endIndex {
34+
let index = string.index(after: cursor)
35+
cursor = index
36+
}
37+
}
38+
switch key {
39+
case .character(_, _):
40+
if let character {
41+
insertCharacter(character)
42+
}
43+
case .tab:
44+
insertCharacter("\t")
45+
case .enter(_):
46+
insertCharacter("\n")
47+
case .space:
48+
insertCharacter(" ")
49+
case .backspace:
50+
moveLeft()
51+
if cursor >= string.startIndex, string.isEmpty == false {
52+
string.remove(at: cursor)
53+
}
54+
case .delete:
55+
guard cursor < string.endIndex else {return}
56+
string.remove(at: cursor)
57+
case .left:
58+
moveLeft()
59+
case .right:
60+
moveRight()
61+
default:
62+
break
63+
}
64+
}
65+
66+
/// Clear the string
67+
public func erase() {
68+
string.removeAll(keepingCapacity: true)
69+
cursor = string.startIndex
70+
}
71+
public func startCapture() {
72+
Task { @MainActor in
73+
Game.shared.hid.keyboard.insertStream(self)
74+
}
75+
}
76+
public func stopCapture() {
77+
Task { @MainActor in
78+
Game.shared.hid.keyboard.removeStream(self)
79+
}
80+
}
81+
deinit {
82+
stopCapture()
83+
}
84+
}
85+
86+
internal extension Keyboard {
87+
struct WeakCharacterStream: Hashable {
88+
let id: ObjectIdentifier
89+
weak var stream: CharacterStream? = nil
90+
init(stream: CharacterStream) {
91+
self.id = ObjectIdentifier(stream)
92+
self.stream = stream
93+
}
94+
static func ==(lhs: Self, rhs: Self) -> Bool {
95+
return lhs.id == rhs.id
96+
}
97+
func hash(into hasher: inout Hasher) {
98+
hasher.combine(id)
99+
}
100+
}
101+
102+
func insertStream(_ stream: CharacterStream) {
103+
let wrapper = Keyboard.WeakCharacterStream(stream: stream)
104+
self.activeStreams.insert(wrapper)
105+
}
106+
107+
func removeStream(_ stream: CharacterStream) {
108+
let wrapper = Keyboard.WeakCharacterStream(stream: stream)
109+
self.activeStreams.remove(wrapper)
110+
}
111+
112+
func updateStreams(with key: KeyboardKey, character: Character?) -> Bool {
113+
var handled: Bool = false
114+
for wrapper in activeStreams {
115+
if let stream = wrapper.stream {
116+
stream.insert(character, as: key)
117+
handled = true
118+
}
119+
}
120+
return handled
121+
}
122+
}

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

Lines changed: 2 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import GameMath
2323
if case let .character(character1, origin1) = keyboardKey {
2424
if case let .character(character2, origin2) = key {
2525
guard character1 == character2 else {return false}
26-
if origin1 == nil || origin2 == nil {
26+
if origin1 == .fromAnywhere || origin2 == .fromAnywhere {
2727
return true
2828
}
2929
return origin1 == origin2
@@ -32,7 +32,7 @@ import GameMath
3232
}
3333
if case let .enter(origin1) = keyboardKey {
3434
if case let .enter(origin2) = key {
35-
if origin1 == nil || origin2 == nil {
35+
if origin1 == .fromAnywhere || origin2 == .fromAnywhere {
3636
return true
3737
}
3838
return origin1 == origin2
@@ -54,121 +54,7 @@ import GameMath
5454
}
5555
}
5656

57-
public final class CharacterStream {
58-
public internal(set) var string: String
59-
public var cursor: String.Index
60-
61-
public init() {
62-
let emptyString = ""
63-
string = emptyString
64-
cursor = emptyString.startIndex
65-
}
66-
67-
internal func insert(_ character: Character?, as key: KeyboardKey) {
68-
@_transparent
69-
func insertCharacter(_ character: Character) {
70-
self.string.insert(character, at: cursor)
71-
self.cursor = string.index(after: cursor)
72-
}
73-
@_transparent
74-
func moveLeft() {
75-
if cursor > string.startIndex {
76-
let index = string.index(before: cursor)
77-
cursor = index
78-
}
79-
}
80-
@_transparent
81-
func moveRight() {
82-
if cursor < string.endIndex {
83-
let index = string.index(after: cursor)
84-
cursor = index
85-
}
86-
}
87-
switch key {
88-
case .character(_, _):
89-
if let character {
90-
insertCharacter(character)
91-
}
92-
case .tab:
93-
insertCharacter("\t")
94-
case .enter(_):
95-
insertCharacter("\n")
96-
case .space:
97-
insertCharacter(" ")
98-
case .backspace:
99-
moveLeft()
100-
if cursor >= string.startIndex, string.isEmpty == false {
101-
string.remove(at: cursor)
102-
}
103-
case .delete:
104-
guard cursor < string.endIndex else {return}
105-
string.remove(at: cursor)
106-
case .left:
107-
moveLeft()
108-
case .right:
109-
moveRight()
110-
default:
111-
break
112-
}
113-
}
114-
115-
/// Clear the string
116-
public func erase() {
117-
string.removeAll(keepingCapacity: true)
118-
cursor = string.startIndex
119-
}
120-
public func startCapture() {
121-
Task { @MainActor in
122-
Game.shared.hid.keyboard.insertStream(self)
123-
}
124-
}
125-
public func stopCapture() {
126-
Task { @MainActor in
127-
Game.shared.hid.keyboard.removeStream(self)
128-
}
129-
}
130-
deinit {
131-
stopCapture()
132-
}
133-
}
13457

135-
internal extension Keyboard {
136-
struct WeakCharacterStream: Hashable {
137-
let id: ObjectIdentifier
138-
weak var stream: CharacterStream? = nil
139-
init(stream: CharacterStream) {
140-
self.id = ObjectIdentifier(stream)
141-
self.stream = stream
142-
}
143-
static func ==(lhs: Self, rhs: Self) -> Bool {
144-
return lhs.id == rhs.id
145-
}
146-
func hash(into hasher: inout Hasher) {
147-
hasher.combine(id)
148-
}
149-
}
150-
151-
func insertStream(_ stream: CharacterStream) {
152-
let wrapper = Keyboard.WeakCharacterStream(stream: stream)
153-
self.activeStreams.insert(wrapper)
154-
}
155-
156-
func removeStream(_ stream: CharacterStream) {
157-
let wrapper = Keyboard.WeakCharacterStream(stream: stream)
158-
self.activeStreams.remove(wrapper)
159-
}
160-
161-
func updateStreams(with key: KeyboardKey, character: Character?) -> Bool {
162-
var handled: Bool = false
163-
for wrapper in activeStreams {
164-
if let stream = wrapper.stream {
165-
stream.insert(character, as: key)
166-
handled = true
167-
}
168-
}
169-
return handled
170-
}
171-
}
17258

17359
public extension Keyboard {
17460
@MainActor final class ButtonState: CustomStringConvertible {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright © 2023 Dustin Collins (Strega's Gate)
3+
* All Rights Reserved.
4+
*
5+
* http://stregasgate.com
6+
*/
7+
8+
public enum KeyboardEvent {
9+
case keyDown
10+
case keyUp
11+
case toggle
12+
}

0 commit comments

Comments
 (0)