@@ -13,6 +13,7 @@ import com.almasb.fxgl.logging.Logger
1313import javafx.geometry.Point2D
1414import javafx.geometry.Rectangle2D
1515import javafx.scene.image.Image
16+ import javafx.scene.input.KeyCode
1617import javafx.scene.input.MouseButton
1718import javafx.scene.robot.Robot
1819import 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