InputX11.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #include "anki/input/Input.h"
  2. #include "anki/core/Logger.h"
  3. #include "anki/input/InputX11.h"
  4. #if ANKI_WINDOW_BACKEND_GLXX11
  5. # include "anki/core/NativeWindowGlxX11.h"
  6. #elif ANKI_WINDOW_BACKEND_EGLX11
  7. # include "anki/core/NativeWindowEglX11.h"
  8. #else
  9. # error "See file"
  10. #endif
  11. #include <X11/XKBlib.h>
  12. #include <cstring>
  13. #define DEBUG_EVENTS 0
  14. #if DEBUG_EVENTS
  15. # define DBG_LOGI(x_) ANKI_LOGI(x_)
  16. #else
  17. # define DBG_LOGI(x_) ((void)0)
  18. #endif
  19. // Undef stupid X11 defines
  20. #undef Bool
  21. namespace anki {
  22. //==============================================================================
  23. struct X11KeyCodeToAnki
  24. {
  25. U32 x;
  26. KeyCode ak;
  27. };
  28. static const X11KeyCodeToAnki x2a[] = {
  29. {XK_Return, KC_RETURN},
  30. {XK_Escape, KC_ESCAPE},
  31. {XK_BackSpace, KC_BACKSPACE},
  32. {XK_Tab, KC_TAB},
  33. {XK_space, KC_SPACE},
  34. {XK_exclam, KC_EXCLAIM},
  35. {XK_quotedbl, KC_QUOTEDBL},
  36. {XK_numbersign, KC_HASH},
  37. {XK_percent, KC_PERCENT},
  38. {XK_dollar, KC_DOLLAR},
  39. {XK_ampersand, KC_AMPERSAND},
  40. {XK_apostrophe, KC_QUOTE},
  41. {XK_parenleft, KC_LEFTPAREN},
  42. {XK_parenright, KC_RIGHTPAREN},
  43. {XK_asterisk, KC_ASTERISK},
  44. {XK_plus, KC_PLUS},
  45. {XK_comma, KC_COMMA},
  46. {XK_minus, KC_MINUS},
  47. {XK_period, KC_PERIOD},
  48. {XK_slash, KC_SLASH},
  49. {XK_0, KC_0},
  50. {XK_1, KC_1},
  51. {XK_2, KC_2},
  52. {XK_3, KC_3},
  53. {XK_4, KC_4},
  54. {XK_5, KC_5},
  55. {XK_6, KC_6},
  56. {XK_7, KC_7},
  57. {XK_8, KC_8},
  58. {XK_9, KC_9},
  59. {XK_colon, KC_COLON},
  60. {XK_semicolon, KC_SEMICOLON},
  61. {XK_less, KC_LESS},
  62. {XK_equal, KC_EQUALS},
  63. {XK_greater, KC_GREATER},
  64. {XK_question, KC_QUESTION},
  65. {XK_at, KC_AT},
  66. {XK_bracketleft, KC_LEFTBRACKET},
  67. {XK_backslash, KC_BACKSLASH},
  68. {XK_bracketright, KC_RIGHTBRACKET},
  69. /*{XK_caret, KC_CARET},*/
  70. {XK_underscore, KC_UNDERSCORE},
  71. {XK_grave, KC_BACKQUOTE},
  72. {XK_a, KC_A},
  73. {XK_b, KC_B},
  74. {XK_c, KC_C},
  75. {XK_d, KC_D},
  76. {XK_e, KC_E},
  77. {XK_f, KC_F},
  78. {XK_g, KC_G},
  79. {XK_h, KC_H},
  80. {XK_i, KC_I},
  81. {XK_j, KC_J},
  82. {XK_k, KC_K},
  83. {XK_l, KC_L},
  84. {XK_m, KC_M},
  85. {XK_n, KC_N},
  86. {XK_o, KC_O},
  87. {XK_p, KC_P},
  88. {XK_q, KC_Q},
  89. {XK_r, KC_R},
  90. {XK_s, KC_S},
  91. {XK_t, KC_T},
  92. {XK_u, KC_U},
  93. {XK_v, KC_V},
  94. {XK_w, KC_W},
  95. {XK_x, KC_X},
  96. {XK_y, KC_Y},
  97. {XK_z, KC_Z},
  98. {XK_Delete, KC_DELETE},
  99. {XK_F1, KC_F1},
  100. {XK_F2, KC_F2},
  101. {XK_F3, KC_F3},
  102. {XK_F4, KC_F4},
  103. {XK_F5, KC_F5},
  104. {XK_F6, KC_F6},
  105. {XK_F7, KC_F7},
  106. {XK_F8, KC_F8},
  107. {XK_F9, KC_F9},
  108. {XK_F10, KC_F10},
  109. {XK_F11, KC_F11},
  110. {XK_F12, KC_F12},
  111. {XK_Up, KC_UP},
  112. {XK_Down, KC_DOWN},
  113. {XK_Left, KC_LEFT},
  114. {XK_Right, KC_RIGHT}
  115. };
  116. #define XKEYCODE2ANKI(k_) impl->nativeKeyToAnki[k_ & 0xFF]
  117. //==============================================================================
  118. static Bool eventsPending(Display* display)
  119. {
  120. XFlush(display);
  121. if(XEventsQueued(display, QueuedAlready))
  122. {
  123. return true;
  124. }
  125. static struct timeval zero_time;
  126. int x11_fd;
  127. fd_set fdset;
  128. x11_fd = ConnectionNumber(display);
  129. FD_ZERO(&fdset);
  130. FD_SET(x11_fd, &fdset);
  131. if(select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1)
  132. {
  133. return XPending(display);
  134. }
  135. return false;
  136. }
  137. //==============================================================================
  138. Input::~Input()
  139. {}
  140. //==============================================================================
  141. void Input::init(NativeWindow* nativeWindow_)
  142. {
  143. ANKI_ASSERT(nativeWindow == nullptr);
  144. nativeWindow = nativeWindow_;
  145. NativeWindowImpl& nwin = nativeWindow->getNative();
  146. XSelectInput(nwin.xDisplay, nwin.xWindow,
  147. ExposureMask | ButtonPressMask | KeyPressMask | KeyReleaseMask
  148. | PointerMotionMask | FocusChangeMask | EnterWindowMask
  149. | LeaveWindowMask);
  150. // Init native
  151. impl.reset(new InputImpl);
  152. memset(
  153. &impl->nativeKeyToAnki[0], sizeof(impl->nativeKeyToAnki), KC_UNKNOWN);
  154. for(const X11KeyCodeToAnki& a : x2a)
  155. {
  156. // Convert X11 keycode to something else
  157. U32 somethingElse = a.x & 0xFF;
  158. impl->nativeKeyToAnki[somethingElse] = a.ak;
  159. }
  160. reset();
  161. }
  162. //==============================================================================
  163. void Input::handleEvents()
  164. {
  165. ANKI_ASSERT(nativeWindow != nullptr);
  166. // add the times a key is being pressed
  167. for(auto& k : keys)
  168. {
  169. if(k)
  170. {
  171. ++k;
  172. }
  173. }
  174. for(auto& k : mouseBtns)
  175. {
  176. if(k)
  177. {
  178. ++k;
  179. }
  180. }
  181. NativeWindowImpl& win = nativeWindow->getNative();
  182. Display* disp = win.xDisplay;
  183. //DBG_LOGI("----------------------");
  184. while(eventsPending(disp))
  185. {
  186. XEvent event;
  187. ::KeyCode keycode = 0;
  188. KeySym keysym;
  189. XNextEvent(disp, &event);
  190. skipXNextEvent:
  191. switch(event.type)
  192. {
  193. case KeyPress:
  194. keysym = XLookupKeysym(&event.xkey, 0);
  195. keycode = event.xkey.keycode;
  196. keys[XKEYCODE2ANKI(keysym)] = 1;
  197. DBG_LOGI("Key pressed: 0x" << std::hex << (U32)keysym);
  198. break;
  199. case KeyRelease:
  200. keycode = event.xkey.keycode;
  201. keysym = XLookupKeysym(&event.xkey, 0);
  202. if(eventsPending(disp))
  203. {
  204. XEvent event1;
  205. XNextEvent(disp, &event1);
  206. if(event1.type == KeyPress && event1.xkey.keycode == keycode)
  207. {
  208. // Repeat
  209. //DBG_LOGI("Key autorepeat: 0x" << std::hex << (U32)keysym);
  210. //++keys[XKEYCODE2ANKI(keysym)];
  211. }
  212. else
  213. {
  214. DBG_LOGI("Key released: 0x" << std::hex << (U32)keysym);
  215. keys[XKEYCODE2ANKI(keysym)] = 0;
  216. event = event1;
  217. goto skipXNextEvent;
  218. }
  219. }
  220. else
  221. {
  222. DBG_LOGI("Key released #2: 0x" << std::hex << (U32)keysym);
  223. keys[XKEYCODE2ANKI(keysym)] = 0;
  224. }
  225. break;
  226. case MotionNotify:
  227. mousePosNdc.x() =
  228. (F32)event.xmotion.x / nativeWindow->getWidth() * 2.0 - 1.0;
  229. mousePosNdc.y() =
  230. -((F32)event.xmotion.y / nativeWindow->getHeight() * 2.0 - 1.0);
  231. DBG_LOGI("MotionNotify: " << event.xmotion.x << " "
  232. << event.xmotion.y << " (" << mousePosNdc << ")");
  233. break;
  234. case EnterNotify:
  235. DBG_LOGI("EnterNotify: ");
  236. break;
  237. case LeaveNotify:
  238. DBG_LOGI("LeaveNotify: ");
  239. break;
  240. default:
  241. DBG_LOGI("Unknown X event");
  242. break;
  243. }
  244. }
  245. // Lock mouse
  246. if(lockCurs)
  247. {
  248. moveCursor(Vec2(0.0));
  249. }
  250. }
  251. //==============================================================================
  252. void Input::moveCursor(const Vec2& pos)
  253. {
  254. DBG_LOGI("Moving to: " << pos.x() << " " << pos.y());
  255. if(pos != mousePosNdc)
  256. {
  257. NativeWindowImpl& nwi = nativeWindow->getNative();
  258. XWarpPointer(nwi.xDisplay, None, nwi.xWindow, 0, 0, 0, 0,
  259. (F32)nativeWindow->getWidth() * (pos.x() / 2.0 + 0.5),
  260. (F32)nativeWindow->getHeight() * (-pos.y() / 2.0 + 0.5));
  261. XSync(nwi.xDisplay, False);
  262. }
  263. }
  264. //==============================================================================
  265. void Input::hideCursor(Bool hide)
  266. {
  267. Display* dis = nativeWindow->getNative().xDisplay;
  268. Window win = nativeWindow->getNative().xWindow;
  269. if(impl->emptyCursor == None)
  270. {
  271. char data[1] = {0};
  272. XColor color;
  273. Pixmap pixmap;
  274. color.red = color.green = color.blue = 0;
  275. pixmap = XCreateBitmapFromData(dis, DefaultRootWindow(dis), data, 1, 1);
  276. if(pixmap)
  277. {
  278. impl->emptyCursor = XCreatePixmapCursor(dis, pixmap, pixmap,
  279. &color, &color, 0, 0);
  280. XFreePixmap(dis, pixmap);
  281. }
  282. }
  283. XDefineCursor(dis, win, impl->emptyCursor);
  284. XFlush(dis);
  285. }
  286. } // end namespace anki