entry_x11.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /*
  2. * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "entry_p.h"
  6. #if ENTRY_CONFIG_USE_NATIVE && (BX_PLATFORM_BSD || BX_PLATFORM_LINUX || BX_PLATFORM_RPI)
  7. #define XK_MISCELLANY
  8. #define XK_LATIN1
  9. #include <X11/keysymdef.h>
  10. #include <X11/Xlib.h> // will include X11 which #defines None... Don't mess with order of includes.
  11. #include <bgfx/bgfxplatform.h>
  12. #undef None
  13. #include <bx/thread.h>
  14. #include <bx/os.h>
  15. #include <bx/handlealloc.h>
  16. #include <string.h> // memset
  17. #include <string>
  18. #include <fcntl.h>
  19. namespace entry
  20. {
  21. #define JS_EVENT_BUTTON 0x01 /* button pressed/released */
  22. #define JS_EVENT_AXIS 0x02 /* joystick moved */
  23. #define JS_EVENT_INIT 0x80 /* initial state of device */
  24. struct JoystickEvent
  25. {
  26. uint32_t time; /* event timestamp in milliseconds */
  27. int16_t value; /* value */
  28. uint8_t type; /* event type */
  29. uint8_t number; /* axis/button number */
  30. };
  31. static Key::Enum s_translateButton[] =
  32. {
  33. Key::GamepadA,
  34. Key::GamepadB,
  35. Key::GamepadX,
  36. Key::GamepadY,
  37. Key::GamepadShoulderL,
  38. Key::GamepadShoulderR,
  39. Key::GamepadBack,
  40. Key::GamepadStart,
  41. Key::GamepadGuide,
  42. Key::GamepadThumbL,
  43. Key::GamepadThumbR,
  44. };
  45. static GamepadAxis::Enum s_translateAxis[] =
  46. {
  47. GamepadAxis::LeftX,
  48. GamepadAxis::LeftY,
  49. GamepadAxis::LeftZ,
  50. GamepadAxis::RightX,
  51. GamepadAxis::RightY,
  52. GamepadAxis::RightZ,
  53. };
  54. struct AxisDpadRemap
  55. {
  56. Key::Enum first;
  57. Key::Enum second;
  58. };
  59. static AxisDpadRemap s_axisDpad[] =
  60. {
  61. { Key::GamepadLeft, Key::GamepadRight },
  62. { Key::GamepadUp, Key::GamepadDown },
  63. { Key::None, Key::None },
  64. { Key::GamepadLeft, Key::GamepadRight },
  65. { Key::GamepadUp, Key::GamepadDown },
  66. { Key::None, Key::None },
  67. };
  68. BX_STATIC_ASSERT(BX_COUNTOF(s_translateAxis) == BX_COUNTOF(s_axisDpad) );
  69. struct Joystick
  70. {
  71. Joystick()
  72. : m_fd(-1)
  73. {
  74. }
  75. void init()
  76. {
  77. m_fd = open("/dev/input/js0", O_RDONLY | O_NONBLOCK);
  78. memset(m_value, 0, sizeof(m_value) );
  79. // Deadzone values from xinput.h
  80. m_deadzone[GamepadAxis::LeftX ] =
  81. m_deadzone[GamepadAxis::LeftY ] = 7849;
  82. m_deadzone[GamepadAxis::RightX] =
  83. m_deadzone[GamepadAxis::RightY] = 8689;
  84. m_deadzone[GamepadAxis::LeftZ ] =
  85. m_deadzone[GamepadAxis::RightZ] = 30;
  86. }
  87. void shutdown()
  88. {
  89. if (-1 != m_fd)
  90. {
  91. close(m_fd);
  92. }
  93. }
  94. bool filter(GamepadAxis::Enum _axis, int32_t* _value)
  95. {
  96. const int32_t old = m_value[_axis];
  97. const int32_t deadzone = m_deadzone[_axis];
  98. int32_t value = *_value;
  99. value = value > deadzone || value < -deadzone ? value : 0;
  100. m_value[_axis] = value;
  101. *_value = value;
  102. return old != value;
  103. }
  104. bool update(EventQueue& _eventQueue)
  105. {
  106. if (-1 == m_fd)
  107. {
  108. return false;
  109. }
  110. JoystickEvent event;
  111. int32_t bytes = read(m_fd, &event, sizeof(JoystickEvent) );
  112. if (bytes != sizeof(JoystickEvent) )
  113. {
  114. return false;
  115. }
  116. WindowHandle defaultWindow = { 0 };
  117. GamepadHandle handle = { 0 };
  118. if (event.type & JS_EVENT_BUTTON)
  119. {
  120. if (event.number < BX_COUNTOF(s_translateButton) )
  121. {
  122. _eventQueue.postKeyEvent(defaultWindow, s_translateButton[event.number], 0, 0 != event.value);
  123. }
  124. }
  125. else if (event.type & JS_EVENT_AXIS)
  126. {
  127. if (event.number < BX_COUNTOF(s_translateAxis) )
  128. {
  129. GamepadAxis::Enum axis = s_translateAxis[event.number];
  130. int32_t value = event.value;
  131. if (filter(axis, &value) )
  132. {
  133. _eventQueue.postAxisEvent(defaultWindow, handle, axis, value);
  134. if (Key::None != s_axisDpad[axis].first)
  135. {
  136. if (m_value[axis] == 0)
  137. {
  138. _eventQueue.postKeyEvent(defaultWindow, s_axisDpad[axis].first, 0, false);
  139. _eventQueue.postKeyEvent(defaultWindow, s_axisDpad[axis].second, 0, false);
  140. }
  141. else
  142. {
  143. _eventQueue.postKeyEvent(defaultWindow
  144. , 0 > m_value[axis] ? s_axisDpad[axis].first : s_axisDpad[axis].second
  145. , 0
  146. , true
  147. );
  148. }
  149. }
  150. }
  151. }
  152. }
  153. return true;
  154. }
  155. int m_fd;
  156. int32_t m_value[GamepadAxis::Count];
  157. int32_t m_deadzone[GamepadAxis::Count];
  158. };
  159. static Joystick s_joystick;
  160. static uint8_t s_translateKey[512];
  161. static void initTranslateKey(uint16_t _xk, Key::Enum _key)
  162. {
  163. _xk += 256;
  164. BX_CHECK(_xk < BX_COUNTOF(s_translateKey), "Out of bounds %d.", _xk);
  165. s_translateKey[_xk&0x1ff] = (uint8_t)_key;
  166. }
  167. Key::Enum fromXk(uint16_t _xk)
  168. {
  169. _xk += 256;
  170. return 512 > _xk ? (Key::Enum)s_translateKey[_xk] : Key::None;
  171. }
  172. struct MainThreadEntry
  173. {
  174. int m_argc;
  175. char** m_argv;
  176. static int32_t threadFunc(void* _userData);
  177. };
  178. struct Msg
  179. {
  180. Msg()
  181. : m_x(0)
  182. , m_y(0)
  183. , m_width(0)
  184. , m_height(0)
  185. , m_flags(0)
  186. {
  187. }
  188. int32_t m_x;
  189. int32_t m_y;
  190. uint32_t m_width;
  191. uint32_t m_height;
  192. uint32_t m_flags;
  193. std::string m_title;
  194. };
  195. struct Context
  196. {
  197. Context()
  198. : m_modifiers(Modifier::None)
  199. , m_exit(false)
  200. {
  201. memset(s_translateKey, 0, sizeof(s_translateKey) );
  202. initTranslateKey(XK_Escape, Key::Esc);
  203. initTranslateKey(XK_Return, Key::Return);
  204. initTranslateKey(XK_Tab, Key::Tab);
  205. initTranslateKey(XK_BackSpace, Key::Backspace);
  206. initTranslateKey(XK_space, Key::Space);
  207. initTranslateKey(XK_Up, Key::Up);
  208. initTranslateKey(XK_Down, Key::Down);
  209. initTranslateKey(XK_Left, Key::Left);
  210. initTranslateKey(XK_Right, Key::Right);
  211. initTranslateKey(XK_Insert, Key::Insert);
  212. initTranslateKey(XK_Delete, Key::Delete);
  213. initTranslateKey(XK_Home, Key::Home);
  214. initTranslateKey(XK_KP_End, Key::End);
  215. initTranslateKey(XK_Page_Up, Key::PageUp);
  216. initTranslateKey(XK_Page_Down, Key::PageDown);
  217. initTranslateKey(XK_Print, Key::Print);
  218. initTranslateKey(XK_equal, Key::Plus);
  219. initTranslateKey(XK_minus, Key::Minus);
  220. initTranslateKey(XK_bracketleft, Key::LeftBracket);
  221. initTranslateKey(XK_bracketright, Key::RightBracket);
  222. initTranslateKey(XK_semicolon, Key::Semicolon);
  223. initTranslateKey(XK_apostrophe, Key::Quote);
  224. initTranslateKey(XK_comma, Key::Comma);
  225. initTranslateKey(XK_period, Key::Period);
  226. initTranslateKey(XK_slash, Key::Slash);
  227. initTranslateKey(XK_backslash, Key::Backslash);
  228. initTranslateKey(XK_grave, Key::Tilde);
  229. initTranslateKey(XK_F1, Key::F1);
  230. initTranslateKey(XK_F2, Key::F2);
  231. initTranslateKey(XK_F3, Key::F3);
  232. initTranslateKey(XK_F4, Key::F4);
  233. initTranslateKey(XK_F5, Key::F5);
  234. initTranslateKey(XK_F6, Key::F6);
  235. initTranslateKey(XK_F7, Key::F7);
  236. initTranslateKey(XK_F8, Key::F8);
  237. initTranslateKey(XK_F9, Key::F9);
  238. initTranslateKey(XK_F10, Key::F10);
  239. initTranslateKey(XK_F11, Key::F11);
  240. initTranslateKey(XK_F12, Key::F12);
  241. initTranslateKey(XK_KP_Insert, Key::NumPad0);
  242. initTranslateKey(XK_KP_End, Key::NumPad1);
  243. initTranslateKey(XK_KP_Down, Key::NumPad2);
  244. initTranslateKey(XK_KP_Page_Down, Key::NumPad3);
  245. initTranslateKey(XK_KP_Left, Key::NumPad4);
  246. initTranslateKey(XK_KP_Begin, Key::NumPad5);
  247. initTranslateKey(XK_KP_Right, Key::NumPad6);
  248. initTranslateKey(XK_KP_Home, Key::NumPad7);
  249. initTranslateKey(XK_KP_Up, Key::NumPad8);
  250. initTranslateKey(XK_KP_Page_Up, Key::NumPad9);
  251. initTranslateKey('0', Key::Key0);
  252. initTranslateKey('1', Key::Key1);
  253. initTranslateKey('2', Key::Key2);
  254. initTranslateKey('3', Key::Key3);
  255. initTranslateKey('4', Key::Key4);
  256. initTranslateKey('5', Key::Key5);
  257. initTranslateKey('6', Key::Key6);
  258. initTranslateKey('7', Key::Key7);
  259. initTranslateKey('8', Key::Key8);
  260. initTranslateKey('9', Key::Key9);
  261. initTranslateKey('a', Key::KeyA);
  262. initTranslateKey('b', Key::KeyB);
  263. initTranslateKey('c', Key::KeyC);
  264. initTranslateKey('d', Key::KeyD);
  265. initTranslateKey('e', Key::KeyE);
  266. initTranslateKey('f', Key::KeyF);
  267. initTranslateKey('g', Key::KeyG);
  268. initTranslateKey('h', Key::KeyH);
  269. initTranslateKey('i', Key::KeyI);
  270. initTranslateKey('j', Key::KeyJ);
  271. initTranslateKey('k', Key::KeyK);
  272. initTranslateKey('l', Key::KeyL);
  273. initTranslateKey('m', Key::KeyM);
  274. initTranslateKey('n', Key::KeyN);
  275. initTranslateKey('o', Key::KeyO);
  276. initTranslateKey('p', Key::KeyP);
  277. initTranslateKey('q', Key::KeyQ);
  278. initTranslateKey('r', Key::KeyR);
  279. initTranslateKey('s', Key::KeyS);
  280. initTranslateKey('t', Key::KeyT);
  281. initTranslateKey('u', Key::KeyU);
  282. initTranslateKey('v', Key::KeyV);
  283. initTranslateKey('w', Key::KeyW);
  284. initTranslateKey('x', Key::KeyX);
  285. initTranslateKey('y', Key::KeyY);
  286. initTranslateKey('z', Key::KeyZ);
  287. m_mx = 0;
  288. m_my = 0;
  289. m_mz = 0;
  290. }
  291. int32_t run(int _argc, char** _argv)
  292. {
  293. XInitThreads();
  294. m_display = XOpenDisplay(0);
  295. int32_t screen = DefaultScreen(m_display);
  296. m_depth = DefaultDepth(m_display, screen);
  297. m_visual = DefaultVisual(m_display, screen);
  298. m_root = RootWindow(m_display, screen);
  299. memset(&m_windowAttrs, 0, sizeof(m_windowAttrs) );
  300. m_windowAttrs.background_pixmap = 0;
  301. m_windowAttrs.border_pixel = 0;
  302. m_windowAttrs.event_mask = 0
  303. | ButtonPressMask
  304. | ButtonReleaseMask
  305. | ExposureMask
  306. | KeyPressMask
  307. | KeyReleaseMask
  308. | PointerMotionMask
  309. | StructureNotifyMask
  310. ;
  311. m_windowAlloc.alloc();
  312. m_window[0] = XCreateWindow(m_display
  313. , m_root
  314. , 0, 0
  315. , 1, 1, 0
  316. , m_depth
  317. , InputOutput
  318. , m_visual
  319. , CWBorderPixel|CWEventMask
  320. , &m_windowAttrs
  321. );
  322. // Clear window to black.
  323. XSetWindowAttributes attr;
  324. memset(&attr, 0, sizeof(attr) );
  325. XChangeWindowAttributes(m_display, m_window[0], CWBackPixel, &attr);
  326. const char* wmDeleteWindowName = "WM_DELETE_WINDOW";
  327. Atom wmDeleteWindow;
  328. XInternAtoms(m_display, (char **)&wmDeleteWindowName, 1, False, &wmDeleteWindow);
  329. XSetWMProtocols(m_display, m_window[0], &wmDeleteWindow, 1);
  330. XMapWindow(m_display, m_window[0]);
  331. XStoreName(m_display, m_window[0], "BGFX");
  332. XIM im;
  333. im = XOpenIM(m_display, NULL, NULL, NULL);
  334. XIC ic;
  335. ic = XCreateIC(im
  336. , XNInputStyle
  337. , 0
  338. | XIMPreeditNothing
  339. | XIMStatusNothing
  340. , XNClientWindow
  341. , m_window[0]
  342. , NULL
  343. );
  344. //
  345. bgfx::x11SetDisplayWindow(m_display, m_window[0]);
  346. MainThreadEntry mte;
  347. mte.m_argc = _argc;
  348. mte.m_argv = _argv;
  349. bx::Thread thread;
  350. thread.init(mte.threadFunc, &mte);
  351. WindowHandle defaultWindow = { 0 };
  352. m_eventQueue.postSizeEvent(defaultWindow, 1, 1);
  353. s_joystick.init();
  354. while (!m_exit)
  355. {
  356. bool joystick = s_joystick.update(m_eventQueue);
  357. bool xpending = XPending(m_display);
  358. if (!xpending)
  359. {
  360. bx::sleep(joystick ? 8 : 16);
  361. }
  362. else
  363. {
  364. XEvent event;
  365. XNextEvent(m_display, &event);
  366. switch (event.type)
  367. {
  368. case Expose:
  369. break;
  370. case ClientMessage:
  371. if ( (Atom)event.xclient.data.l[0] == wmDeleteWindow)
  372. {
  373. m_eventQueue.postExitEvent();
  374. }
  375. break;
  376. case ButtonPress:
  377. case ButtonRelease:
  378. {
  379. const XButtonEvent& xbutton = event.xbutton;
  380. MouseButton::Enum mb = MouseButton::None;
  381. switch (xbutton.button)
  382. {
  383. case Button1: mb = MouseButton::Left; break;
  384. case Button2: mb = MouseButton::Middle; break;
  385. case Button3: mb = MouseButton::Right; break;
  386. case Button4: ++m_mz; break;
  387. case Button5: --m_mz; break;
  388. }
  389. WindowHandle handle = findHandle(xbutton.window);
  390. if (MouseButton::None != mb)
  391. {
  392. m_eventQueue.postMouseEvent(handle
  393. , xbutton.x
  394. , xbutton.y
  395. , 0
  396. , mb
  397. , event.type == ButtonPress
  398. );
  399. }
  400. else
  401. {
  402. m_eventQueue.postMouseEvent(handle
  403. , m_mx
  404. , m_my
  405. , m_mz
  406. );
  407. }
  408. }
  409. break;
  410. case MotionNotify:
  411. {
  412. const XMotionEvent& xmotion = event.xmotion;
  413. WindowHandle handle = findHandle(xmotion.window);
  414. m_mx = xmotion.x;
  415. m_my = xmotion.y;
  416. m_eventQueue.postMouseEvent(handle
  417. , m_mx
  418. , m_my
  419. , m_mz
  420. );
  421. }
  422. break;
  423. case KeyPress:
  424. case KeyRelease:
  425. {
  426. XKeyEvent& xkey = event.xkey;
  427. KeySym keysym = XLookupKeysym(&xkey, 0);
  428. switch (keysym)
  429. {
  430. case XK_Meta_L: setModifier(Modifier::LeftMeta, KeyPress == event.type); break;
  431. case XK_Meta_R: setModifier(Modifier::RightMeta, KeyPress == event.type); break;
  432. case XK_Control_L: setModifier(Modifier::LeftCtrl, KeyPress == event.type); break;
  433. case XK_Control_R: setModifier(Modifier::RightCtrl, KeyPress == event.type); break;
  434. case XK_Shift_L: setModifier(Modifier::LeftShift, KeyPress == event.type); break;
  435. case XK_Shift_R: setModifier(Modifier::RightShift, KeyPress == event.type); break;
  436. case XK_Alt_L: setModifier(Modifier::LeftAlt, KeyPress == event.type); break;
  437. case XK_Alt_R: setModifier(Modifier::RightAlt, KeyPress == event.type); break;
  438. default:
  439. {
  440. WindowHandle handle = findHandle(xkey.window);
  441. if (KeyPress == event.type)
  442. {
  443. Status status = 0;
  444. uint8_t utf8[4];
  445. int len = Xutf8LookupString(ic, &xkey, (char*)utf8, sizeof(utf8), &keysym, &status);
  446. switch (status)
  447. {
  448. case XLookupChars:
  449. case XLookupBoth:
  450. if (0 != len)
  451. {
  452. m_eventQueue.postCharEvent(handle, len, utf8);
  453. }
  454. break;
  455. default:
  456. break;
  457. }
  458. }
  459. Key::Enum key = fromXk(keysym);
  460. if (Key::None != key)
  461. {
  462. m_eventQueue.postKeyEvent(handle, key, m_modifiers, KeyPress == event.type);
  463. }
  464. }
  465. break;
  466. }
  467. }
  468. break;
  469. case ConfigureNotify:
  470. {
  471. const XConfigureEvent& xev = event.xconfigure;
  472. WindowHandle handle = findHandle(xev.window);
  473. if (isValid(handle) )
  474. {
  475. m_eventQueue.postSizeEvent(handle, xev.width, xev.height);
  476. }
  477. }
  478. break;
  479. }
  480. }
  481. }
  482. thread.shutdown();
  483. s_joystick.shutdown();
  484. XDestroyIC(ic);
  485. XCloseIM(im);
  486. XUnmapWindow(m_display, m_window[0]);
  487. XDestroyWindow(m_display, m_window[0]);
  488. return thread.getExitCode();
  489. }
  490. void setModifier(Modifier::Enum _modifier, bool _set)
  491. {
  492. m_modifiers &= ~_modifier;
  493. m_modifiers |= _set ? _modifier : 0;
  494. }
  495. void createWindow(WindowHandle _handle, Msg* msg)
  496. {
  497. Window window = XCreateWindow(m_display
  498. , m_root
  499. , msg->m_x
  500. , msg->m_y
  501. , msg->m_width
  502. , msg->m_height
  503. , 0
  504. , m_depth
  505. , InputOutput
  506. , m_visual
  507. , CWBorderPixel|CWEventMask
  508. , &m_windowAttrs
  509. );
  510. m_window[_handle.idx] = window;
  511. // Clear window to black.
  512. XSetWindowAttributes attr;
  513. memset(&attr, 0, sizeof(attr) );
  514. XChangeWindowAttributes(m_display, window, CWBackPixel, &attr);
  515. const char* wmDeleteWindowName = "WM_DELETE_WINDOW";
  516. Atom wmDeleteWindow;
  517. XInternAtoms(m_display, (char **)&wmDeleteWindowName, 1, False, &wmDeleteWindow);
  518. XSetWMProtocols(m_display, window, &wmDeleteWindow, 1);
  519. XMapWindow(m_display, window);
  520. XStoreName(m_display, window, msg->m_title.c_str() );
  521. m_eventQueue.postSizeEvent(_handle, msg->m_width, msg->m_height);
  522. union cast
  523. {
  524. void* p;
  525. ::Window w;
  526. };
  527. cast c;
  528. c.w = window;
  529. m_eventQueue.postWindowEvent(_handle, c.p);
  530. delete msg;
  531. }
  532. WindowHandle findHandle(Window _window)
  533. {
  534. bx::LwMutexScope scope(m_lock);
  535. for (uint32_t ii = 0, num = m_windowAlloc.getNumHandles(); ii < num; ++ii)
  536. {
  537. uint16_t idx = m_windowAlloc.getHandleAt(ii);
  538. if (_window == m_window[idx])
  539. {
  540. WindowHandle handle = { idx };
  541. return handle;
  542. }
  543. }
  544. WindowHandle invalid = { UINT16_MAX };
  545. return invalid;
  546. }
  547. uint8_t m_modifiers;
  548. bool m_exit;
  549. int32_t m_mx;
  550. int32_t m_my;
  551. int32_t m_mz;
  552. EventQueue m_eventQueue;
  553. bx::LwMutex m_lock;
  554. bx::HandleAllocT<ENTRY_CONFIG_MAX_WINDOWS> m_windowAlloc;
  555. int32_t m_depth;
  556. Visual* m_visual;
  557. Window m_root;
  558. XSetWindowAttributes m_windowAttrs;
  559. Display* m_display;
  560. Window m_window[ENTRY_CONFIG_MAX_WINDOWS];
  561. uint32_t m_flags[ENTRY_CONFIG_MAX_WINDOWS];
  562. };
  563. static Context s_ctx;
  564. int32_t MainThreadEntry::threadFunc(void* _userData)
  565. {
  566. MainThreadEntry* self = (MainThreadEntry*)_userData;
  567. int32_t result = main(self->m_argc, self->m_argv);
  568. s_ctx.m_exit = true;
  569. return result;
  570. }
  571. const Event* poll()
  572. {
  573. return s_ctx.m_eventQueue.poll();
  574. }
  575. const Event* poll(WindowHandle _handle)
  576. {
  577. return s_ctx.m_eventQueue.poll(_handle);
  578. }
  579. void release(const Event* _event)
  580. {
  581. s_ctx.m_eventQueue.release(_event);
  582. }
  583. WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title)
  584. {
  585. bx::LwMutexScope scope(s_ctx.m_lock);
  586. WindowHandle handle = { s_ctx.m_windowAlloc.alloc() };
  587. if (isValid(handle) )
  588. {
  589. Msg* msg = new Msg;
  590. msg->m_x = _x;
  591. msg->m_y = _y;
  592. msg->m_width = _width;
  593. msg->m_height = _height;
  594. msg->m_title = _title;
  595. msg->m_flags = _flags;
  596. s_ctx.createWindow(handle, msg);
  597. }
  598. return handle;
  599. }
  600. void destroyWindow(WindowHandle _handle)
  601. {
  602. if (isValid(_handle) )
  603. {
  604. s_ctx.m_eventQueue.postWindowEvent(_handle, NULL);
  605. XUnmapWindow(s_ctx.m_display, s_ctx.m_window[_handle.idx]);
  606. XDestroyWindow(s_ctx.m_display, s_ctx.m_window[_handle.idx]);
  607. bx::LwMutexScope scope(s_ctx.m_lock);
  608. s_ctx.m_windowAlloc.free(_handle.idx);
  609. }
  610. }
  611. void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y)
  612. {
  613. Display* display = s_ctx.m_display;
  614. Window window = s_ctx.m_window[_handle.idx];
  615. XMoveWindow(display, window, _x, _y);
  616. }
  617. void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height)
  618. {
  619. Display* display = s_ctx.m_display;
  620. Window window = s_ctx.m_window[_handle.idx];
  621. XResizeWindow(display, window, int32_t(_width), int32_t(_height) );
  622. }
  623. void setWindowTitle(WindowHandle _handle, const char* _title)
  624. {
  625. Display* display = s_ctx.m_display;
  626. Window window = s_ctx.m_window[_handle.idx];
  627. XStoreName(display, window, _title);
  628. }
  629. void toggleWindowFrame(WindowHandle _handle)
  630. {
  631. BX_UNUSED(_handle);
  632. }
  633. void toggleFullscreen(WindowHandle _handle)
  634. {
  635. BX_UNUSED(_handle);
  636. }
  637. void setMouseLock(WindowHandle _handle, bool _lock)
  638. {
  639. BX_UNUSED(_handle, _lock);
  640. }
  641. } // namespace entry
  642. int main(int _argc, char** _argv)
  643. {
  644. using namespace entry;
  645. return s_ctx.run(_argc, _argv);
  646. }
  647. #endif // ENTRY_CONFIG_USE_NATIVE && (BX_PLATFORM_BSD || BX_PLATFORM_LINUX || BX_PLATFORM_RPI)