SDL2Keyboard.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. using Ryujinx.Common.Configuration.Hid;
  2. using Ryujinx.Common.Configuration.Hid.Keyboard;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Numerics;
  6. using System.Runtime.CompilerServices;
  7. using static SDL2.SDL;
  8. using ConfigKey = Ryujinx.Common.Configuration.Hid.Key;
  9. namespace Ryujinx.Input.SDL2
  10. {
  11. class SDL2Keyboard : IKeyboard
  12. {
  13. private readonly record struct ButtonMappingEntry(GamepadButtonInputId To, Key From)
  14. {
  15. public bool IsValid => To is not GamepadButtonInputId.Unbound && From is not Key.Unbound;
  16. }
  17. private readonly object _userMappingLock = new();
  18. #pragma warning disable IDE0052 // Remove unread private member
  19. private readonly SDL2KeyboardDriver _driver;
  20. #pragma warning restore IDE0052
  21. private StandardKeyboardInputConfig _configuration;
  22. private readonly List<ButtonMappingEntry> _buttonsUserMapping;
  23. private static readonly SDL_Keycode[] _keysDriverMapping = new SDL_Keycode[(int)Key.Count]
  24. {
  25. // INVALID
  26. SDL_Keycode.SDLK_0,
  27. // Presented as modifiers, so invalid here.
  28. SDL_Keycode.SDLK_0,
  29. SDL_Keycode.SDLK_0,
  30. SDL_Keycode.SDLK_0,
  31. SDL_Keycode.SDLK_0,
  32. SDL_Keycode.SDLK_0,
  33. SDL_Keycode.SDLK_0,
  34. SDL_Keycode.SDLK_0,
  35. SDL_Keycode.SDLK_0,
  36. SDL_Keycode.SDLK_0,
  37. SDL_Keycode.SDLK_F1,
  38. SDL_Keycode.SDLK_F2,
  39. SDL_Keycode.SDLK_F3,
  40. SDL_Keycode.SDLK_F4,
  41. SDL_Keycode.SDLK_F5,
  42. SDL_Keycode.SDLK_F6,
  43. SDL_Keycode.SDLK_F7,
  44. SDL_Keycode.SDLK_F8,
  45. SDL_Keycode.SDLK_F9,
  46. SDL_Keycode.SDLK_F10,
  47. SDL_Keycode.SDLK_F11,
  48. SDL_Keycode.SDLK_F12,
  49. SDL_Keycode.SDLK_F13,
  50. SDL_Keycode.SDLK_F14,
  51. SDL_Keycode.SDLK_F15,
  52. SDL_Keycode.SDLK_F16,
  53. SDL_Keycode.SDLK_F17,
  54. SDL_Keycode.SDLK_F18,
  55. SDL_Keycode.SDLK_F19,
  56. SDL_Keycode.SDLK_F20,
  57. SDL_Keycode.SDLK_F21,
  58. SDL_Keycode.SDLK_F22,
  59. SDL_Keycode.SDLK_F23,
  60. SDL_Keycode.SDLK_F24,
  61. SDL_Keycode.SDLK_0,
  62. SDL_Keycode.SDLK_0,
  63. SDL_Keycode.SDLK_0,
  64. SDL_Keycode.SDLK_0,
  65. SDL_Keycode.SDLK_0,
  66. SDL_Keycode.SDLK_0,
  67. SDL_Keycode.SDLK_0,
  68. SDL_Keycode.SDLK_0,
  69. SDL_Keycode.SDLK_0,
  70. SDL_Keycode.SDLK_0,
  71. SDL_Keycode.SDLK_0,
  72. SDL_Keycode.SDLK_UP,
  73. SDL_Keycode.SDLK_DOWN,
  74. SDL_Keycode.SDLK_LEFT,
  75. SDL_Keycode.SDLK_RIGHT,
  76. SDL_Keycode.SDLK_RETURN,
  77. SDL_Keycode.SDLK_ESCAPE,
  78. SDL_Keycode.SDLK_SPACE,
  79. SDL_Keycode.SDLK_TAB,
  80. SDL_Keycode.SDLK_BACKSPACE,
  81. SDL_Keycode.SDLK_INSERT,
  82. SDL_Keycode.SDLK_DELETE,
  83. SDL_Keycode.SDLK_PAGEUP,
  84. SDL_Keycode.SDLK_PAGEDOWN,
  85. SDL_Keycode.SDLK_HOME,
  86. SDL_Keycode.SDLK_END,
  87. SDL_Keycode.SDLK_CAPSLOCK,
  88. SDL_Keycode.SDLK_SCROLLLOCK,
  89. SDL_Keycode.SDLK_PRINTSCREEN,
  90. SDL_Keycode.SDLK_PAUSE,
  91. SDL_Keycode.SDLK_NUMLOCKCLEAR,
  92. SDL_Keycode.SDLK_CLEAR,
  93. SDL_Keycode.SDLK_KP_0,
  94. SDL_Keycode.SDLK_KP_1,
  95. SDL_Keycode.SDLK_KP_2,
  96. SDL_Keycode.SDLK_KP_3,
  97. SDL_Keycode.SDLK_KP_4,
  98. SDL_Keycode.SDLK_KP_5,
  99. SDL_Keycode.SDLK_KP_6,
  100. SDL_Keycode.SDLK_KP_7,
  101. SDL_Keycode.SDLK_KP_8,
  102. SDL_Keycode.SDLK_KP_9,
  103. SDL_Keycode.SDLK_KP_DIVIDE,
  104. SDL_Keycode.SDLK_KP_MULTIPLY,
  105. SDL_Keycode.SDLK_KP_MINUS,
  106. SDL_Keycode.SDLK_KP_PLUS,
  107. SDL_Keycode.SDLK_KP_DECIMAL,
  108. SDL_Keycode.SDLK_KP_ENTER,
  109. SDL_Keycode.SDLK_a,
  110. SDL_Keycode.SDLK_b,
  111. SDL_Keycode.SDLK_c,
  112. SDL_Keycode.SDLK_d,
  113. SDL_Keycode.SDLK_e,
  114. SDL_Keycode.SDLK_f,
  115. SDL_Keycode.SDLK_g,
  116. SDL_Keycode.SDLK_h,
  117. SDL_Keycode.SDLK_i,
  118. SDL_Keycode.SDLK_j,
  119. SDL_Keycode.SDLK_k,
  120. SDL_Keycode.SDLK_l,
  121. SDL_Keycode.SDLK_m,
  122. SDL_Keycode.SDLK_n,
  123. SDL_Keycode.SDLK_o,
  124. SDL_Keycode.SDLK_p,
  125. SDL_Keycode.SDLK_q,
  126. SDL_Keycode.SDLK_r,
  127. SDL_Keycode.SDLK_s,
  128. SDL_Keycode.SDLK_t,
  129. SDL_Keycode.SDLK_u,
  130. SDL_Keycode.SDLK_v,
  131. SDL_Keycode.SDLK_w,
  132. SDL_Keycode.SDLK_x,
  133. SDL_Keycode.SDLK_y,
  134. SDL_Keycode.SDLK_z,
  135. SDL_Keycode.SDLK_0,
  136. SDL_Keycode.SDLK_1,
  137. SDL_Keycode.SDLK_2,
  138. SDL_Keycode.SDLK_3,
  139. SDL_Keycode.SDLK_4,
  140. SDL_Keycode.SDLK_5,
  141. SDL_Keycode.SDLK_6,
  142. SDL_Keycode.SDLK_7,
  143. SDL_Keycode.SDLK_8,
  144. SDL_Keycode.SDLK_9,
  145. SDL_Keycode.SDLK_BACKQUOTE,
  146. SDL_Keycode.SDLK_BACKQUOTE,
  147. SDL_Keycode.SDLK_MINUS,
  148. SDL_Keycode.SDLK_PLUS,
  149. SDL_Keycode.SDLK_LEFTBRACKET,
  150. SDL_Keycode.SDLK_RIGHTBRACKET,
  151. SDL_Keycode.SDLK_SEMICOLON,
  152. SDL_Keycode.SDLK_QUOTE,
  153. SDL_Keycode.SDLK_COMMA,
  154. SDL_Keycode.SDLK_PERIOD,
  155. SDL_Keycode.SDLK_SLASH,
  156. SDL_Keycode.SDLK_BACKSLASH,
  157. // Invalids
  158. SDL_Keycode.SDLK_0,
  159. };
  160. public SDL2Keyboard(SDL2KeyboardDriver driver, string id, string name)
  161. {
  162. _driver = driver;
  163. Id = id;
  164. Name = name;
  165. _buttonsUserMapping = new List<ButtonMappingEntry>();
  166. }
  167. private bool HasConfiguration => _configuration != null;
  168. public string Id { get; }
  169. public string Name { get; }
  170. public bool IsConnected => true;
  171. public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
  172. public void Dispose()
  173. {
  174. // No operations
  175. }
  176. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  177. private static int ToSDL2Scancode(Key key)
  178. {
  179. if (key >= Key.Unknown && key <= Key.Menu)
  180. {
  181. return -1;
  182. }
  183. return (int)SDL_GetScancodeFromKey(_keysDriverMapping[(int)key]);
  184. }
  185. private static SDL_Keymod GetKeyboardModifierMask(Key key)
  186. {
  187. return key switch
  188. {
  189. Key.ShiftLeft => SDL_Keymod.KMOD_LSHIFT,
  190. Key.ShiftRight => SDL_Keymod.KMOD_RSHIFT,
  191. Key.ControlLeft => SDL_Keymod.KMOD_LCTRL,
  192. Key.ControlRight => SDL_Keymod.KMOD_RCTRL,
  193. Key.AltLeft => SDL_Keymod.KMOD_LALT,
  194. Key.AltRight => SDL_Keymod.KMOD_RALT,
  195. Key.WinLeft => SDL_Keymod.KMOD_LGUI,
  196. Key.WinRight => SDL_Keymod.KMOD_RGUI,
  197. // NOTE: Menu key isn't supported by SDL2.
  198. _ => SDL_Keymod.KMOD_NONE,
  199. };
  200. }
  201. public KeyboardStateSnapshot GetKeyboardStateSnapshot()
  202. {
  203. ReadOnlySpan<byte> rawKeyboardState;
  204. SDL_Keymod rawKeyboardModifierState = SDL_GetModState();
  205. unsafe
  206. {
  207. nint statePtr = SDL_GetKeyboardState(out int numKeys);
  208. rawKeyboardState = new ReadOnlySpan<byte>((byte*)statePtr, numKeys);
  209. }
  210. bool[] keysState = new bool[(int)Key.Count];
  211. for (Key key = 0; key < Key.Count; key++)
  212. {
  213. int index = ToSDL2Scancode(key);
  214. if (index == -1)
  215. {
  216. SDL_Keymod modifierMask = GetKeyboardModifierMask(key);
  217. if (modifierMask == SDL_Keymod.KMOD_NONE)
  218. {
  219. continue;
  220. }
  221. keysState[(int)key] = (rawKeyboardModifierState & modifierMask) == modifierMask;
  222. }
  223. else
  224. {
  225. keysState[(int)key] = rawKeyboardState[index] == 1;
  226. }
  227. }
  228. return new KeyboardStateSnapshot(keysState);
  229. }
  230. private static float ConvertRawStickValue(short value)
  231. {
  232. const float ConvertRate = 1.0f / (short.MaxValue + 0.5f);
  233. return value * ConvertRate;
  234. }
  235. private static (short, short) GetStickValues(ref KeyboardStateSnapshot snapshot, JoyconConfigKeyboardStick<ConfigKey> stickConfig)
  236. {
  237. short stickX = 0;
  238. short stickY = 0;
  239. if (snapshot.IsPressed((Key)stickConfig.StickUp))
  240. {
  241. stickY += 1;
  242. }
  243. if (snapshot.IsPressed((Key)stickConfig.StickDown))
  244. {
  245. stickY -= 1;
  246. }
  247. if (snapshot.IsPressed((Key)stickConfig.StickRight))
  248. {
  249. stickX += 1;
  250. }
  251. if (snapshot.IsPressed((Key)stickConfig.StickLeft))
  252. {
  253. stickX -= 1;
  254. }
  255. Vector2 stick = Vector2.Normalize(new Vector2(stickX, stickY));
  256. return ((short)(stick.X * short.MaxValue), (short)(stick.Y * short.MaxValue));
  257. }
  258. public GamepadStateSnapshot GetMappedStateSnapshot()
  259. {
  260. KeyboardStateSnapshot rawState = GetKeyboardStateSnapshot();
  261. GamepadStateSnapshot result = default;
  262. lock (_userMappingLock)
  263. {
  264. if (!HasConfiguration)
  265. {
  266. return result;
  267. }
  268. foreach (ButtonMappingEntry entry in _buttonsUserMapping)
  269. {
  270. if (entry.From == Key.Unknown || entry.From == Key.Unbound || entry.To == GamepadButtonInputId.Unbound)
  271. {
  272. continue;
  273. }
  274. // Do not touch state of button already pressed
  275. if (!result.IsPressed(entry.To))
  276. {
  277. result.SetPressed(entry.To, rawState.IsPressed(entry.From));
  278. }
  279. }
  280. (short leftStickX, short leftStickY) = GetStickValues(ref rawState, _configuration.LeftJoyconStick);
  281. (short rightStickX, short rightStickY) = GetStickValues(ref rawState, _configuration.RightJoyconStick);
  282. result.SetStick(StickInputId.Left, ConvertRawStickValue(leftStickX), ConvertRawStickValue(leftStickY));
  283. result.SetStick(StickInputId.Right, ConvertRawStickValue(rightStickX), ConvertRawStickValue(rightStickY));
  284. }
  285. return result;
  286. }
  287. public GamepadStateSnapshot GetStateSnapshot()
  288. {
  289. throw new NotSupportedException();
  290. }
  291. public (float, float) GetStick(StickInputId inputId)
  292. {
  293. throw new NotSupportedException();
  294. }
  295. public bool IsPressed(GamepadButtonInputId inputId)
  296. {
  297. throw new NotSupportedException();
  298. }
  299. public bool IsPressed(Key key)
  300. {
  301. // We only implement GetKeyboardStateSnapshot.
  302. throw new NotSupportedException();
  303. }
  304. public void SetConfiguration(InputConfig configuration)
  305. {
  306. lock (_userMappingLock)
  307. {
  308. _configuration = (StandardKeyboardInputConfig)configuration;
  309. // First clear the buttons mapping
  310. _buttonsUserMapping.Clear();
  311. // Then configure left joycon
  312. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
  313. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
  314. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
  315. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadLeft, (Key)_configuration.LeftJoycon.DpadLeft));
  316. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadRight, (Key)_configuration.LeftJoycon.DpadRight));
  317. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Minus, (Key)_configuration.LeftJoycon.ButtonMinus));
  318. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftShoulder, (Key)_configuration.LeftJoycon.ButtonL));
  319. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftTrigger, (Key)_configuration.LeftJoycon.ButtonZl));
  320. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, (Key)_configuration.LeftJoycon.ButtonSr));
  321. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
  322. // Finally configure right joycon
  323. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
  324. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
  325. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
  326. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.X, (Key)_configuration.RightJoycon.ButtonX));
  327. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Y, (Key)_configuration.RightJoycon.ButtonY));
  328. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Plus, (Key)_configuration.RightJoycon.ButtonPlus));
  329. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightShoulder, (Key)_configuration.RightJoycon.ButtonR));
  330. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (Key)_configuration.RightJoycon.ButtonZr));
  331. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, (Key)_configuration.RightJoycon.ButtonSr));
  332. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (Key)_configuration.RightJoycon.ButtonSl));
  333. }
  334. }
  335. public void SetTriggerThreshold(float triggerThreshold)
  336. {
  337. // No operations
  338. }
  339. public void Rumble(float lowFrequency, float highFrequency, uint durationMs)
  340. {
  341. // No operations
  342. }
  343. public Vector3 GetMotionData(MotionInputId inputId)
  344. {
  345. // No operations
  346. return Vector3.Zero;
  347. }
  348. }
  349. }