KeyboardLinux.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. }