input_android.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright 2016 Hajime Hoshi
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package ebitenmobileview
  15. import (
  16. "encoding/hex"
  17. "hash/crc32"
  18. "unicode"
  19. "github.com/hajimehoshi/ebiten/v2/internal/gamepad"
  20. "github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
  21. "github.com/hajimehoshi/ebiten/v2/internal/ui"
  22. )
  23. // https://developer.android.com/reference/android/view/KeyEvent
  24. const (
  25. keycodeButtonA = 0x00000060
  26. keycodeButtonB = 0x00000061
  27. keycodeButtonC = 0x00000062
  28. keycodeButtonX = 0x00000063
  29. keycodeButtonY = 0x00000064
  30. keycodeButtonZ = 0x00000065
  31. keycodeButtonL1 = 0x00000066
  32. keycodeButtonR1 = 0x00000067
  33. keycodeButtonL2 = 0x00000068
  34. keycodeButtonR2 = 0x00000069
  35. keycodeButtonThumbl = 0x0000006a
  36. keycodeButtonThumbr = 0x0000006b
  37. keycodeButtonStart = 0x0000006c
  38. keycodeButtonSelect = 0x0000006d
  39. keycodeButtonMode = 0x0000006e
  40. keycodeButton1 = 0x000000bc
  41. keycodeButton2 = 0x000000bd
  42. keycodeButton3 = 0x000000be
  43. keycodeButton4 = 0x000000bf
  44. keycodeButton5 = 0x000000c0
  45. keycodeButton6 = 0x000000c1
  46. keycodeButton7 = 0x000000c2
  47. keycodeButton8 = 0x000000c3
  48. keycodeButton9 = 0x000000c4
  49. keycodeButton10 = 0x000000c5
  50. keycodeButton11 = 0x000000c6
  51. keycodeButton12 = 0x000000c7
  52. keycodeButton13 = 0x000000c8
  53. keycodeButton14 = 0x000000c9
  54. keycodeButton15 = 0x000000ca
  55. keycodeButton16 = 0x000000cb
  56. keycodeDpadUp = 0x00000013
  57. keycodeDpadDown = 0x00000014
  58. keycodeDpadLeft = 0x00000015
  59. keycodeDpadRight = 0x00000016
  60. keycodeDpadCenter = 0x00000017
  61. keycodeBack = 0x00000004
  62. keycodeMenu = 0x00000052
  63. )
  64. // https://developer.android.com/reference/android/view/InputDevice
  65. const (
  66. sourceKeyboard = 0x00000101
  67. sourceGamepad = 0x00000401
  68. sourceJoystick = 0x01000010
  69. )
  70. // See https://github.com/libsdl-org/SDL/blob/47f2373dc13b66c48bf4024fcdab53cd0bdd59bb/src/joystick/android/SDL_sysjoystick.c#L71-L172
  71. // TODO: This exceeds gamepad.SDLControllerButtonMax. Is that OK?
  72. var androidKeyToSDL = map[int]int{
  73. keycodeButtonA: gamepaddb.SDLControllerButtonA,
  74. keycodeButtonB: gamepaddb.SDLControllerButtonB,
  75. keycodeButtonX: gamepaddb.SDLControllerButtonX,
  76. keycodeButtonY: gamepaddb.SDLControllerButtonY,
  77. keycodeButtonL1: gamepaddb.SDLControllerButtonLeftShoulder,
  78. keycodeButtonR1: gamepaddb.SDLControllerButtonRightShoulder,
  79. keycodeButtonThumbl: gamepaddb.SDLControllerButtonLeftStick,
  80. keycodeButtonThumbr: gamepaddb.SDLControllerButtonRightStick,
  81. keycodeMenu: gamepaddb.SDLControllerButtonStart,
  82. keycodeButtonStart: gamepaddb.SDLControllerButtonStart,
  83. keycodeBack: gamepaddb.SDLControllerButtonBack,
  84. keycodeButtonSelect: gamepaddb.SDLControllerButtonBack,
  85. keycodeButtonMode: gamepaddb.SDLControllerButtonGuide,
  86. keycodeButtonL2: 15,
  87. keycodeButtonR2: 16,
  88. keycodeButtonC: 17,
  89. keycodeButtonZ: 18,
  90. keycodeDpadUp: gamepaddb.SDLControllerButtonDpadUp,
  91. keycodeDpadDown: gamepaddb.SDLControllerButtonDpadDown,
  92. keycodeDpadLeft: gamepaddb.SDLControllerButtonDpadLeft,
  93. keycodeDpadRight: gamepaddb.SDLControllerButtonDpadRight,
  94. keycodeDpadCenter: gamepaddb.SDLControllerButtonA,
  95. keycodeButton1: 20,
  96. keycodeButton2: 21,
  97. keycodeButton3: 22,
  98. keycodeButton4: 23,
  99. keycodeButton5: 24,
  100. keycodeButton6: 25,
  101. keycodeButton7: 26,
  102. keycodeButton8: 27,
  103. keycodeButton9: 28,
  104. keycodeButton10: 29,
  105. keycodeButton11: 30,
  106. keycodeButton12: 31,
  107. keycodeButton13: 32,
  108. keycodeButton14: 33,
  109. keycodeButton15: 34,
  110. keycodeButton16: 35,
  111. }
  112. func UpdateTouchesOnAndroid(action int, id int, x, y int) {
  113. switch action {
  114. case 0x00, 0x05, 0x02: // ACTION_DOWN, ACTION_POINTER_DOWN, ACTION_MOVE
  115. touches[ui.TouchID(id)] = position{x, y}
  116. updateInput(nil)
  117. case 0x01, 0x06: // ACTION_UP, ACTION_POINTER_UP
  118. delete(touches, ui.TouchID(id))
  119. updateInput(nil)
  120. }
  121. }
  122. func OnKeyDownOnAndroid(keyCode int, unicodeChar int, source int, deviceID int) {
  123. switch {
  124. case source&sourceGamepad == sourceGamepad:
  125. // A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
  126. if button, ok := androidKeyToSDL[keyCode]; ok {
  127. gamepad.UpdateAndroidGamepadButton(deviceID, gamepad.Button(button), true)
  128. }
  129. case source&sourceJoystick == sourceJoystick:
  130. // DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
  131. case source&sourceKeyboard == sourceKeyboard:
  132. if key, ok := androidKeyToUIKey[keyCode]; ok {
  133. keys[key] = struct{}{}
  134. }
  135. var runes []rune
  136. if r := rune(unicodeChar); r != 0 && unicode.IsPrint(r) {
  137. runes = []rune{r}
  138. }
  139. updateInput(runes)
  140. }
  141. }
  142. func OnKeyUpOnAndroid(keyCode int, source int, deviceID int) {
  143. switch {
  144. case source&sourceGamepad == sourceGamepad:
  145. // A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
  146. if button, ok := androidKeyToSDL[keyCode]; ok {
  147. gamepad.UpdateAndroidGamepadButton(deviceID, gamepad.Button(button), false)
  148. }
  149. case source&sourceJoystick == sourceJoystick:
  150. // DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
  151. case source&sourceKeyboard == sourceKeyboard:
  152. if key, ok := androidKeyToUIKey[keyCode]; ok {
  153. delete(keys, key)
  154. }
  155. updateInput(nil)
  156. }
  157. }
  158. func OnGamepadAxisChanged(deviceID int, axisID int, value float32) {
  159. gamepad.UpdateAndroidGamepadAxis(deviceID, axisID, float64(value))
  160. }
  161. func OnGamepadHatChanged(deviceID int, hatID int, xValue, yValue int) {
  162. gamepad.UpdateAndroidGamepadHat(deviceID, hatID, xValue, yValue)
  163. }
  164. func OnGamepadAdded(deviceID int, name string, axisCount int, hatCount int, descriptor string, vendorID int, productID int, buttonMask int, axisMask int) {
  165. // This emulates the implementation of Android_AddJoystick.
  166. // https://github.com/libsdl-org/SDL/blob/0e9560aea22818884921e5e5064953257bfe7fa7/src/joystick/android/SDL_sysjoystick.c#L386
  167. const SDL_HARDWARE_BUS_BLUETOOTH = 0x05
  168. var sdlid [16]byte
  169. sdlid[0] = byte(SDL_HARDWARE_BUS_BLUETOOTH)
  170. sdlid[1] = byte(SDL_HARDWARE_BUS_BLUETOOTH >> 8)
  171. if vendorID != 0 && productID != 0 {
  172. sdlid[4] = byte(vendorID)
  173. sdlid[5] = byte(vendorID >> 8)
  174. sdlid[8] = byte(productID)
  175. sdlid[9] = byte(productID >> 8)
  176. } else {
  177. crc := crc32.ChecksumIEEE(([]byte)(descriptor))
  178. copy(sdlid[4:8], ([]byte)(descriptor))
  179. sdlid[8] = byte(crc)
  180. sdlid[9] = byte(crc >> 8)
  181. sdlid[10] = byte(crc >> 16)
  182. sdlid[11] = byte(crc >> 24)
  183. }
  184. sdlid[12] = byte(buttonMask)
  185. sdlid[13] = byte(buttonMask >> 8)
  186. sdlid[14] = byte(axisMask)
  187. sdlid[15] = byte(axisMask >> 8)
  188. gamepad.AddAndroidGamepad(deviceID, name, hex.EncodeToString(sdlid[:]), axisCount, hatCount)
  189. }
  190. func OnInputDeviceRemoved(deviceID int) {
  191. gamepad.RemoveAndroidGamepad(deviceID)
  192. }