KeyboardLinux.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2024 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Input/Linux/KeyboardLinux.h>
  6. #include <Renderer/Renderer.h>
  7. KeyboardLinux::~KeyboardLinux()
  8. {
  9. Shutdown();
  10. }
  11. bool KeyboardLinux::Initialize(Renderer *inRenderer)
  12. {
  13. mRenderer = inRenderer;
  14. inRenderer->SetEventListener([this](const XEvent &inEvent) { HandleEvent(inEvent); });
  15. return true;
  16. }
  17. void KeyboardLinux::Shutdown()
  18. {
  19. if (mRenderer != nullptr)
  20. {
  21. mRenderer->SetEventListener({});
  22. mRenderer = nullptr;
  23. }
  24. }
  25. void KeyboardLinux::Poll()
  26. {
  27. // Reset the keys pressed
  28. memset(mKeysPressed, 0, sizeof(mKeysPressed));
  29. Display *display = mRenderer->GetDisplay();
  30. // Get pressed keys
  31. char keymap[32];
  32. XQueryKeymap(display, keymap);
  33. for (int i = 0; i < 32; ++i)
  34. {
  35. // Iterate 8 bits at a time
  36. uint keycode = i << 3;
  37. uint32 value = uint8(keymap[i]);
  38. while (value != 0)
  39. {
  40. // Get the next bit
  41. uint lz = CountTrailingZeros(value);
  42. keycode += lz;
  43. // Convert to key
  44. KeySym keysym = XkbKeycodeToKeysym(display, keycode, 0, 0);
  45. EKey key = ToKey(keysym);
  46. if (key != EKey::Unknown)
  47. mKeysPressed[(int)key] = true;
  48. // Skip this bit
  49. keycode++;
  50. value >>= lz + 1;
  51. }
  52. }
  53. // Make the pending buffer the active buffer
  54. mKeyBuffer = mPendingKeyBuffer;
  55. mPendingKeyBuffer.clear();
  56. }
  57. EKey KeyboardLinux::GetFirstKey()
  58. {
  59. mCurrentKey = 0;
  60. return GetNextKey();
  61. }
  62. EKey KeyboardLinux::GetNextKey()
  63. {
  64. if (mCurrentKey < mKeyBuffer.size())
  65. return mKeyBuffer[mCurrentKey++];
  66. return EKey::Invalid;
  67. }
  68. void KeyboardLinux::HandleEvent(const XEvent &inEvent)
  69. {
  70. // If this is a key press event and the buffer is not yet full
  71. if (inEvent.type == KeyPress && mPendingKeyBuffer.size() < mPendingKeyBuffer.capacity())
  72. {
  73. // Convert to key
  74. KeySym keysym = XkbKeycodeToKeysym(mRenderer->GetDisplay(), inEvent.xkey.keycode, 0, 0);
  75. EKey key = ToKey(keysym);
  76. if (key != EKey::Unknown)
  77. mPendingKeyBuffer.push_back(key);
  78. }
  79. }
  80. EKey KeyboardLinux::ToKey(int inValue) const
  81. {
  82. switch (inValue)
  83. {
  84. case XK_a: return EKey::A;
  85. case XK_b: return EKey::B;
  86. case XK_c: return EKey::C;
  87. case XK_d: return EKey::D;
  88. case XK_e: return EKey::E;
  89. case XK_f: return EKey::F;
  90. case XK_g: return EKey::G;
  91. case XK_h: return EKey::H;
  92. case XK_i: return EKey::I;
  93. case XK_j: return EKey::J;
  94. case XK_k: return EKey::K;
  95. case XK_l: return EKey::L;
  96. case XK_m: return EKey::M;
  97. case XK_n: return EKey::N;
  98. case XK_o: return EKey::O;
  99. case XK_p: return EKey::P;
  100. case XK_q: return EKey::Q;
  101. case XK_r: return EKey::R;
  102. case XK_s: return EKey::S;
  103. case XK_t: return EKey::T;
  104. case XK_u: return EKey::U;
  105. case XK_v: return EKey::V;
  106. case XK_w: return EKey::W;
  107. case XK_x: return EKey::X;
  108. case XK_y: return EKey::Y;
  109. case XK_z: return EKey::Z;
  110. case XK_0: return EKey::Num0;
  111. case XK_1: return EKey::Num1;
  112. case XK_2: return EKey::Num2;
  113. case XK_3: return EKey::Num3;
  114. case XK_4: return EKey::Num4;
  115. case XK_5: return EKey::Num5;
  116. case XK_6: return EKey::Num6;
  117. case XK_7: return EKey::Num7;
  118. case XK_8: return EKey::Num8;
  119. case XK_9: return EKey::Num9;
  120. case XK_space: return EKey::Space;
  121. case XK_comma: return EKey::Comma;
  122. case XK_period: return EKey::Period;
  123. case XK_Escape: return EKey::Escape;
  124. case XK_Shift_L: return EKey::LShift;
  125. case XK_Shift_R: return EKey::RShift;
  126. case XK_Control_L: return EKey::LControl;
  127. case XK_Control_R: return EKey::RControl;
  128. case XK_Alt_L: return EKey::LAlt;
  129. case XK_Alt_R: return EKey::RAlt;
  130. case XK_Left: return EKey::Left;
  131. case XK_Right: return EKey::Right;
  132. case XK_Up: return EKey::Up;
  133. case XK_Down: return EKey::Down;
  134. case XK_Return: return EKey::Return;
  135. default: return EKey::Unknown;
  136. }
  137. }
  138. int KeyboardLinux::FromKey(EKey inKey) const
  139. {
  140. switch (inKey)
  141. {
  142. case EKey::A: return XK_a;
  143. case EKey::B: return XK_b;
  144. case EKey::C: return XK_c;
  145. case EKey::D: return XK_d;
  146. case EKey::E: return XK_e;
  147. case EKey::F: return XK_f;
  148. case EKey::G: return XK_g;
  149. case EKey::H: return XK_h;
  150. case EKey::I: return XK_i;
  151. case EKey::J: return XK_j;
  152. case EKey::K: return XK_k;
  153. case EKey::L: return XK_l;
  154. case EKey::M: return XK_m;
  155. case EKey::N: return XK_n;
  156. case EKey::O: return XK_o;
  157. case EKey::P: return XK_p;
  158. case EKey::Q: return XK_q;
  159. case EKey::R: return XK_r;
  160. case EKey::S: return XK_s;
  161. case EKey::T: return XK_t;
  162. case EKey::U: return XK_u;
  163. case EKey::V: return XK_v;
  164. case EKey::W: return XK_w;
  165. case EKey::X: return XK_x;
  166. case EKey::Y: return XK_y;
  167. case EKey::Z: return XK_z;
  168. case EKey::Num0: return XK_0;
  169. case EKey::Num1: return XK_1;
  170. case EKey::Num2: return XK_2;
  171. case EKey::Num3: return XK_3;
  172. case EKey::Num4: return XK_4;
  173. case EKey::Num5: return XK_5;
  174. case EKey::Num6: return XK_6;
  175. case EKey::Num7: return XK_7;
  176. case EKey::Num8: return XK_8;
  177. case EKey::Num9: return XK_9;
  178. case EKey::Space: return XK_space;
  179. case EKey::Comma: return XK_comma;
  180. case EKey::Period: return XK_period;
  181. case EKey::Escape: return XK_Escape;
  182. case EKey::LShift: return XK_Shift_L;
  183. case EKey::RShift: return XK_Shift_R;
  184. case EKey::LControl: return XK_Control_L;
  185. case EKey::RControl: return XK_Control_R;
  186. case EKey::LAlt: return XK_Alt_L;
  187. case EKey::RAlt: return XK_Alt_R;
  188. case EKey::Left: return XK_Left;
  189. case EKey::Right: return XK_Right;
  190. case EKey::Up: return XK_Up;
  191. case EKey::Down: return XK_Down;
  192. case EKey::Return: return XK_Return;
  193. case EKey::Invalid:
  194. case EKey::Unknown:
  195. default:
  196. return 0;
  197. }
  198. }