keyboard.monkey2 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. Namespace mojo.input
  2. #Import "native/keyinfo.h"
  3. #Import "native/keyinfo.cpp"
  4. Extern Private
  5. Struct bbKeyInfo
  6. Field name:Void Ptr
  7. Field scanCode:Int
  8. Field keyCode:Int
  9. End
  10. Global bbKeyInfos:bbKeyInfo Ptr
  11. Public
  12. #rem monkeydoc Global instance of the KeyboardDevice class.
  13. #end
  14. Const Keyboard:=New KeyboardDevice
  15. #rem monkeydoc The KeyboardDevice class.
  16. All method that take a `key` parameter can also be used with 'raw' keys.
  17. A raw key represents the physical location of a key on US keyboards. For example, `Key.Q|Key.Raw` indicates the key at the top left of the
  18. 'qwerty' keys regardless of the current keyboard layout.
  19. Please see the [[Key]] enum for more information on raw keys.
  20. To access the keyboard device, use the global [[Keyboard]] constant.
  21. The keyboard device should only used after a new [[app.AppInstance]] is created.
  22. #end
  23. Class KeyboardDevice Extends InputDevice
  24. #rem monkeydoc The current state of the modifier keys.
  25. #end
  26. Property Modifiers:Modifier()
  27. Return _modifiers
  28. End
  29. #rem monkeydoc Gets the name of a key.
  30. If `key` is a raw key, returns the name 'printed' on that key.
  31. if `key` is a virtual key
  32. #end
  33. Method KeyName:String( key:Key )
  34. If key & key.Raw key=TranslateKey( key )
  35. Return _names[key]
  36. End
  37. #rem monkeydoc Translates a key to/from a raw key.
  38. If `key` is a raw key, returns the corresponding virual key.
  39. If `key` is a virtual key, returns the corresponding raw key.
  40. #end
  41. Method TranslateKey:Key( key:Key )
  42. If key & Key.Raw
  43. #If __TARGET__="emscripten"
  44. Return key & ~Key.Raw
  45. #Else
  46. Local keyCode:=SDL_GetKeyFromScancode( Cast<SDL_Scancode>( _raw2scan[ key & ~Key.Raw ] ) )
  47. Return KeyCodeToKey( keyCode )
  48. #Endif
  49. Else
  50. Local scanCode:=_key2scan[key]
  51. Return _scan2raw[scanCode]
  52. Endif
  53. Return Key.None
  54. End
  55. #rem monkeydoc Checks the current up/down state of a key.
  56. Returns true if `key` is currently held down.
  57. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  58. @param key Key to check.
  59. #end
  60. Method KeyDown:Bool( key:Key )
  61. Local scode:=ScanCode( key )
  62. Return _down[scode]
  63. End
  64. #rem monkeydoc Checks if a key was pressed.
  65. Returns true if `key` was pressed since the last call to KeyPressed with the same key.
  66. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  67. @param key Key to check.
  68. #end
  69. Method KeyPressed:Bool( key:Key )
  70. Local scode:=ScanCode( key )
  71. Return _pressed[scode]
  72. End
  73. #rem monkeydoc Checks if a key was released.
  74. Returns true if `key` was released since the last call to KeyReleased with the same key.
  75. If `key` is a raw key, the state of the key as it is physically positioned on US keyboards is returned.
  76. @param key Key to check.
  77. #end
  78. Method KeyReleased:Bool( key:Key )
  79. Local scode:=ScanCode( key )
  80. Return _released[scode]
  81. End
  82. #rem monkeydoc @hidden
  83. #end
  84. Method KeyHit:Bool( key:Key )
  85. Return KeyPressed( key )
  86. End
  87. #rem monkeydoc Peeks at the next character in the character queue.
  88. #end
  89. Method PeekChar:Int()
  90. If _charPut=_charGet Return 0
  91. Return _charQueue[_charGet & CHAR_QUEUE_MASK]
  92. End
  93. #rem monkeydoc Gets the next character from the character queue.
  94. #end
  95. Method GetChar:Int()
  96. If _charPut=_charGet Return 0
  97. Local char:=_charQueue[_charGet & CHAR_QUEUE_MASK]
  98. _charGet+=1
  99. Return char
  100. End
  101. #rem monkeydoc Flushes the character queue.
  102. #end
  103. Method FlushChars()
  104. _charPut=0
  105. _charGet=0
  106. End
  107. '***** Internal *****
  108. #rem monkeydoc @hidden
  109. #end
  110. Method ScanCode:Int( key:Key )
  111. If key & Key.Raw Return _raw2scan[ key & ~Key.Raw ]
  112. Return _key2scan[ key ]
  113. End
  114. #rem monkeydoc @hidden
  115. #end
  116. Method KeyCodeToKey:Key( keyCode:Int )
  117. If (keyCode & $40000000) keyCode=(keyCode & ~$40000000)+$80
  118. Return Cast<Key>( keyCode )
  119. End
  120. #rem monkeydoc @hidden
  121. #end
  122. Method ScanCodeToRawKey:Key( scanCode:Int )
  123. Return _scan2raw[ scanCode ]
  124. End
  125. #rem monkeydoc @hidden
  126. #end
  127. Method Init()
  128. Local p:=bbKeyInfos
  129. While p->name
  130. Local name:=String.FromCString( p->name )
  131. Local scanCode:=p->scanCode
  132. Local keyCode:=p->keyCode
  133. Local key:=KeyCodeToKey( keyCode )
  134. _names[key]=name
  135. _raw2scan[key]=scanCode
  136. _scan2raw[scanCode]=key | Key.Raw
  137. #If __TARGET__="emscripten"
  138. _key2scan[key]=scanCode
  139. #Else
  140. _key2scan[key]=SDL_GetScancodeFromKey( Cast<SDL_Keycode>( keyCode ) )
  141. #Endif
  142. _scan2key[_key2scan[key]]=key
  143. p=p+1
  144. Wend
  145. End
  146. #rem monkeydoc @hidden
  147. #end
  148. Method Update()
  149. For Local key:=Eachin _pressedKeys
  150. _pressed[key]=False
  151. Next
  152. _pressedKeys.Clear()
  153. For Local key:=Eachin _releasedKeys
  154. _released[key]=False
  155. Next
  156. _releasedKeys.Clear()
  157. End
  158. #rem monkeydoc @hidden
  159. #end
  160. Method SendEvent( event:SDL_Event Ptr )
  161. Select event->type
  162. Case SDL_KEYDOWN
  163. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  164. Local scode:=kevent->keysym.scancode
  165. If Not _down[scode]
  166. _down[scode]=True
  167. _pressed[scode]=True
  168. _pressedKeys.Push( scode )
  169. Select kevent->keysym.sym
  170. Case $400000e0 _modifiers|=Modifier.LeftControl
  171. Case $400000e1 _modifiers|=Modifier.LeftShift
  172. Case $400000e2 _modifiers|=Modifier.LeftAlt
  173. Case $400000e3 _modifiers|=Modifier.LeftGui
  174. Case $400000e4 _modifiers|=Modifier.RightControl
  175. Case $400000e5 _modifiers|=Modifier.RightShift
  176. Case $400000e6 _modifiers|=Modifier.RightAlt
  177. Case $400000e7 _modifiers|=Modifier.RightGui
  178. End
  179. Endif
  180. Local char:=KeyToChar( _scan2key[scode] )
  181. If char PushChar( char )
  182. Case SDL_KEYUP
  183. Local kevent:=Cast<SDL_KeyboardEvent Ptr>( event )
  184. Local scode:=kevent->keysym.scancode
  185. If Not _down[scode] Return
  186. _down[scode]=False
  187. _released[scode]=True
  188. _releasedKeys.Push( scode )
  189. Select kevent->keysym.sym
  190. Case $400000e0 _modifiers&=~Modifier.LeftControl
  191. Case $400000e1 _modifiers&=~Modifier.LeftShift
  192. Case $400000e2 _modifiers&=~Modifier.LeftAlt
  193. Case $400000e3 _modifiers&=~Modifier.LeftGui
  194. Case $400000e4 _modifiers&=~Modifier.RightControl
  195. Case $400000e5 _modifiers&=~Modifier.RightShift
  196. Case $400000e6 _modifiers&=~Modifier.RightAlt
  197. Case $400000e7 _modifiers&=~Modifier.RightGui
  198. End
  199. Case SDL_TEXTINPUT
  200. Local tevent:=Cast<SDL_TextInputEvent Ptr>( event )
  201. Local char:=tevent->text[0]
  202. If char PushChar( char )
  203. End
  204. End
  205. Private
  206. Const CHAR_QUEUE_SIZE:=32
  207. Const CHAR_QUEUE_MASK:=31
  208. Field _modifiers:Modifier
  209. Field _down:=New Bool[512]
  210. Field _pressed:=New Bool[512]
  211. Field _released:=New Bool[512]
  212. Field _pressedKeys:=New IntStack
  213. Field _releasedKeys:=New IntStack
  214. Field _names:=New String[512]
  215. Field _raw2scan:=New Int[512] 'no translate
  216. Field _scan2raw:=New Key[512] 'no translate
  217. Field _key2scan:=New Int[512] 'translate
  218. Field _scan2key:=New Int[512] 'translate
  219. Field _charQueue:=New Int[CHAR_QUEUE_SIZE]
  220. Field _charPut:Int
  221. Field _charGet:Int
  222. Method New()
  223. End
  224. Function KeyToChar:Int( key:Int )
  225. Select key
  226. Case Key.Backspace,Key.Tab,Key.Enter,Key.Escape,Key.KeyDelete
  227. Return key
  228. Case Key.PageUp,Key.PageDown,Key.KeyEnd,Key.Home,Key.Left,Key.Up,Key.Right,Key.Down,Key.Insert
  229. Return key | $10000
  230. End
  231. Return 0
  232. End
  233. Method PushChar( char:Int )
  234. If _charPut-_charGet=CHAR_QUEUE_SIZE Return
  235. _charQueue[ _charPut & CHAR_QUEUE_MASK ]=char
  236. _charPut+=1
  237. End
  238. End