Skip to content

Commit 7957d54

Browse files
committed
feat: added initial implementation of RobotKeyboard
1 parent 2dbd2ab commit 7957d54

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

  • fxgl/src/main/kotlin/com/almasb/fxgl/app/services

fxgl/src/main/kotlin/com/almasb/fxgl/app/services/OSService.kt

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.almasb.fxgl.logging.Logger
1313
import javafx.geometry.Point2D
1414
import javafx.geometry.Rectangle2D
1515
import javafx.scene.image.Image
16+
import javafx.scene.input.KeyCode
1617
import javafx.scene.input.MouseButton
1718
import javafx.scene.robot.Robot
1819
import java.util.Optional
@@ -31,6 +32,8 @@ class OSService : EngineService() {
3132

3233
val mouse: RobotMouse by lazy { RobotMouse(robot) }
3334

35+
val keyboard: RobotKeyboard by lazy { RobotKeyboard(robot) }
36+
3437
/**
3538
* @return a screenshot of the [region] in OS screen space, or an empty [Optional] if fails.
3639
*/
@@ -142,4 +145,104 @@ internal constructor(private val robot: Robot) {
142145
log.warning("Failed to move mouse", e)
143146
}
144147
}
148+
}
149+
150+
/**
151+
* An abstraction over an OS-level keyboard allowing to perform
152+
* actions outside the game window.
153+
*/
154+
class RobotKeyboard
155+
internal constructor(private val robot: Robot) {
156+
157+
/**
158+
* Types given [text] using OS keyboard.
159+
*/
160+
fun type(text: String) {
161+
text.forEach { type(it) }
162+
}
163+
164+
private fun type(ch: Char) {
165+
val key: KeyCode
166+
167+
var isShift = false
168+
169+
if (Character.isLetter(ch)) {
170+
key = KeyCode.valueOf(ch.uppercase())
171+
isShift = ch.isUpperCase()
172+
} else {
173+
key = when(ch) {
174+
' ' -> KeyCode.SPACE
175+
'?' -> {
176+
isShift = true
177+
KeyCode.SLASH
178+
}
179+
'!' -> {
180+
isShift = true
181+
KeyCode.DIGIT1
182+
}
183+
',' -> KeyCode.COMMA
184+
'.' -> KeyCode.PERIOD
185+
'_' -> {
186+
isShift = true
187+
KeyCode.MINUS
188+
}
189+
'-' -> KeyCode.MINUS
190+
'+' -> {
191+
isShift = true
192+
KeyCode.EQUALS
193+
}
194+
'*' -> {
195+
isShift = true
196+
KeyCode.DIGIT8
197+
}
198+
'/' -> KeyCode.SLASH
199+
'£' -> {
200+
isShift = true
201+
KeyCode.DIGIT3
202+
}
203+
'$' -> {
204+
isShift = true
205+
KeyCode.DIGIT4
206+
}
207+
'@' -> {
208+
isShift = true
209+
KeyCode.QUOTE
210+
}
211+
'%' -> {
212+
isShift = true
213+
KeyCode.DIGIT5
214+
}
215+
216+
else -> {
217+
log.warning("Cannot convert char to key: $ch")
218+
KeyCode.CONTROL
219+
}
220+
}
221+
}
222+
223+
if (isShift) {
224+
press(KeyCode.SHIFT)
225+
}
226+
227+
type(key)
228+
229+
if (isShift) {
230+
release(KeyCode.SHIFT)
231+
}
232+
}
233+
234+
/**
235+
* Types (presses, then releases) given [key] using OS keyboard.
236+
*/
237+
fun type(key: KeyCode) {
238+
robot.keyType(key)
239+
}
240+
241+
fun press(key: KeyCode) {
242+
robot.keyPress(key)
243+
}
244+
245+
fun release(key: KeyCode) {
246+
robot.keyRelease(key)
247+
}
145248
}

0 commit comments

Comments
 (0)