main_linux.cpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084
  1. /*
  2. * Copyright (c) 2012-2026 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "config.h"
  6. #if CROWN_PLATFORM_LINUX
  7. #include "core/command_line.h"
  8. #include "core/containers/array.inl"
  9. #include "core/debug/callstack.h"
  10. #include "core/guid.h"
  11. #include "core/memory/globals.h"
  12. #include "core/memory/memory.inl"
  13. #include "core/option.inl"
  14. #include "core/os.h"
  15. #include "core/profiler.h"
  16. #include "core/thread/spsc_queue.inl"
  17. #include "core/thread/thread.h"
  18. #include "core/unit_tests.h"
  19. #include "device/device.h"
  20. #include "device/device_event_queue.inl"
  21. #include "device/display.h"
  22. #include "device/window.h"
  23. #include "resource/data_compiler.h"
  24. #include <fcntl.h> // O_RDONLY, ...
  25. #include <stdlib.h>
  26. #include <string.h> // memset
  27. #include <unistd.h> // close
  28. #include <X11/cursorfont.h>
  29. #include <X11/extensions/Xrandr.h>
  30. #include <X11/Xatom.h>
  31. #include <X11/XKBlib.h>
  32. #include <X11/Xlib.h>
  33. #include <X11/Xutil.h>
  34. #include <xkbcommon/xkbcommon.h>
  35. #include <xkbcommon/xkbcommon-compose.h>
  36. #include <sys/mman.h> // mmap
  37. #include <linux/input-event-codes.h>
  38. #define STB_SPRINTF_IMPLEMENTATION
  39. #define STB_SPRINTF_NOUNALIGNED
  40. #include <stb_sprintf.h>
  41. #include <signal.h>
  42. #include <errno.h>
  43. #include <stdio.h>
  44. struct wl_display;
  45. struct wl_proxy;
  46. struct wl_interface;
  47. #define WAYLAND_IMPORT() \
  48. DL_IMPORT_FUNC(wl_display_connect, struct wl_display *, (const char *name)); \
  49. DL_IMPORT_FUNC(wl_display_dispatch, int, (struct wl_display *)); \
  50. DL_IMPORT_FUNC(wl_display_roundtrip, int, (struct wl_display *)); \
  51. DL_IMPORT_FUNC(wl_proxy_add_listener, int, (struct wl_proxy *, void (**implementation)(void), void *)); \
  52. DL_IMPORT_FUNC(wl_proxy_get_version, uint32_t, (struct wl_proxy *)); \
  53. DL_IMPORT_FUNC(wl_proxy_marshal_flags, struct wl_proxy *, (struct wl_proxy *, uint32_t, const struct wl_interface *, uint32_t, uint32_t, ...)); \
  54. DL_IMPORT_FUNC(wl_display_dispatch_pending, int, (struct wl_display *)); \
  55. DL_IMPORT_FUNC(wl_display_get_fd, int, (struct wl_display *)); \
  56. DL_IMPORT_FUNC(wl_display_read_events, int, (struct wl_display *)); \
  57. DL_IMPORT_FUNC(wl_display_prepare_read, int, (struct wl_display *)); \
  58. DL_IMPORT_FUNC(wl_display_flush, int, (struct wl_display *));
  59. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  60. typedef return_type (*PROTO_ ## func_name)params; \
  61. extern PROTO_ ## func_name crown_ ## func_name
  62. extern "C"
  63. {
  64. WAYLAND_IMPORT();
  65. }
  66. #undef DL_IMPORT_FUNC
  67. #define wl_display_connect (*crown_wl_display_connect)
  68. #define wl_display_dispatch (*crown_wl_display_dispatch)
  69. #define wl_display_roundtrip (*crown_wl_display_roundtrip)
  70. #define wl_proxy_add_listener (*crown_wl_proxy_add_listener)
  71. #define wl_proxy_get_version (*crown_wl_proxy_get_version)
  72. #define wl_proxy_marshal_flags (*crown_wl_proxy_marshal_flags)
  73. #define wl_display_dispatch_pending (*crown_wl_display_dispatch_pending)
  74. #define wl_display_get_fd (*crown_wl_display_get_fd)
  75. #define wl_display_read_events (*crown_wl_display_read_events)
  76. #define wl_display_prepare_read (*crown_wl_display_prepare_read)
  77. #define wl_display_flush (*crown_wl_display_flush)
  78. #include "wayland/wayland-client-protocol.h"
  79. #include "wayland/wayland-client-protocol.c"
  80. #include "wayland/xdg-shell-client-protocol.h"
  81. #include "wayland/xdg-shell-client-protocol.c"
  82. #include "wayland/relative-pointer-unstable-v1-client-protocol.h"
  83. #include "wayland/relative-pointer-unstable-v1-client-protocol.c"
  84. #include "wayland/pointer-constraints-unstable-v1-client-protocol.h"
  85. #include "wayland/pointer-constraints-unstable-v1-client-protocol.c"
  86. namespace crown
  87. {
  88. static KeyboardButton::Enum x11_translate_key(KeySym x11_key)
  89. {
  90. switch (x11_key) {
  91. case XK_BackSpace: return KeyboardButton::BACKSPACE;
  92. case XK_Tab: return KeyboardButton::TAB;
  93. case XK_space: return KeyboardButton::SPACE;
  94. case XK_Escape: return KeyboardButton::ESCAPE;
  95. case XK_Return: return KeyboardButton::ENTER;
  96. case XK_F1: return KeyboardButton::F1;
  97. case XK_F2: return KeyboardButton::F2;
  98. case XK_F3: return KeyboardButton::F3;
  99. case XK_F4: return KeyboardButton::F4;
  100. case XK_F5: return KeyboardButton::F5;
  101. case XK_F6: return KeyboardButton::F6;
  102. case XK_F7: return KeyboardButton::F7;
  103. case XK_F8: return KeyboardButton::F8;
  104. case XK_F9: return KeyboardButton::F9;
  105. case XK_F10: return KeyboardButton::F10;
  106. case XK_F11: return KeyboardButton::F11;
  107. case XK_F12: return KeyboardButton::F12;
  108. case XK_Home: return KeyboardButton::HOME;
  109. case XK_Left: return KeyboardButton::LEFT;
  110. case XK_Up: return KeyboardButton::UP;
  111. case XK_Right: return KeyboardButton::RIGHT;
  112. case XK_Down: return KeyboardButton::DOWN;
  113. case XK_Page_Up: return KeyboardButton::PAGE_UP;
  114. case XK_Page_Down: return KeyboardButton::PAGE_DOWN;
  115. case XK_Insert: return KeyboardButton::INS;
  116. case XK_Delete: return KeyboardButton::DEL;
  117. case XK_End: return KeyboardButton::END;
  118. case XK_Shift_L: return KeyboardButton::SHIFT_LEFT;
  119. case XK_Shift_R: return KeyboardButton::SHIFT_RIGHT;
  120. case XK_Control_L: return KeyboardButton::CTRL_LEFT;
  121. case XK_Control_R: return KeyboardButton::CTRL_RIGHT;
  122. case XK_Caps_Lock: return KeyboardButton::CAPS_LOCK;
  123. case XK_Alt_L: return KeyboardButton::ALT_LEFT;
  124. case XK_Alt_R: return KeyboardButton::ALT_RIGHT;
  125. case XK_Super_L: return KeyboardButton::SUPER_LEFT;
  126. case XK_Super_R: return KeyboardButton::SUPER_RIGHT;
  127. case XK_Num_Lock: return KeyboardButton::NUM_LOCK;
  128. case XK_KP_Enter: return KeyboardButton::NUMPAD_ENTER;
  129. case XK_KP_Delete: return KeyboardButton::NUMPAD_DELETE;
  130. case XK_KP_Multiply: return KeyboardButton::NUMPAD_MULTIPLY;
  131. case XK_KP_Add: return KeyboardButton::NUMPAD_ADD;
  132. case XK_KP_Subtract: return KeyboardButton::NUMPAD_SUBTRACT;
  133. case XK_KP_Divide: return KeyboardButton::NUMPAD_DIVIDE;
  134. case XK_KP_Insert:
  135. case XK_KP_0: return KeyboardButton::NUMPAD_0;
  136. case XK_KP_End:
  137. case XK_KP_1: return KeyboardButton::NUMPAD_1;
  138. case XK_KP_Down:
  139. case XK_KP_2: return KeyboardButton::NUMPAD_2;
  140. case XK_KP_Page_Down: // or XK_KP_Next
  141. case XK_KP_3: return KeyboardButton::NUMPAD_3;
  142. case XK_KP_Left:
  143. case XK_KP_4: return KeyboardButton::NUMPAD_4;
  144. case XK_KP_Begin:
  145. case XK_KP_5: return KeyboardButton::NUMPAD_5;
  146. case XK_KP_Right:
  147. case XK_KP_6: return KeyboardButton::NUMPAD_6;
  148. case XK_KP_Home:
  149. case XK_KP_7: return KeyboardButton::NUMPAD_7;
  150. case XK_KP_Up:
  151. case XK_KP_8: return KeyboardButton::NUMPAD_8;
  152. case XK_KP_Page_Up: // or XK_KP_Prior
  153. case XK_KP_9: return KeyboardButton::NUMPAD_9;
  154. case '0': return KeyboardButton::NUMBER_0;
  155. case '1': return KeyboardButton::NUMBER_1;
  156. case '2': return KeyboardButton::NUMBER_2;
  157. case '3': return KeyboardButton::NUMBER_3;
  158. case '4': return KeyboardButton::NUMBER_4;
  159. case '5': return KeyboardButton::NUMBER_5;
  160. case '6': return KeyboardButton::NUMBER_6;
  161. case '7': return KeyboardButton::NUMBER_7;
  162. case '8': return KeyboardButton::NUMBER_8;
  163. case '9': return KeyboardButton::NUMBER_9;
  164. case 'a': return KeyboardButton::A;
  165. case 'b': return KeyboardButton::B;
  166. case 'c': return KeyboardButton::C;
  167. case 'd': return KeyboardButton::D;
  168. case 'e': return KeyboardButton::E;
  169. case 'f': return KeyboardButton::F;
  170. case 'g': return KeyboardButton::G;
  171. case 'h': return KeyboardButton::H;
  172. case 'i': return KeyboardButton::I;
  173. case 'j': return KeyboardButton::J;
  174. case 'k': return KeyboardButton::K;
  175. case 'l': return KeyboardButton::L;
  176. case 'm': return KeyboardButton::M;
  177. case 'n': return KeyboardButton::N;
  178. case 'o': return KeyboardButton::O;
  179. case 'p': return KeyboardButton::P;
  180. case 'q': return KeyboardButton::Q;
  181. case 'r': return KeyboardButton::R;
  182. case 's': return KeyboardButton::S;
  183. case 't': return KeyboardButton::T;
  184. case 'u': return KeyboardButton::U;
  185. case 'v': return KeyboardButton::V;
  186. case 'w': return KeyboardButton::W;
  187. case 'x': return KeyboardButton::X;
  188. case 'y': return KeyboardButton::Y;
  189. case 'z': return KeyboardButton::Z;
  190. default: return KeyboardButton::COUNT;
  191. }
  192. }
  193. static KeyboardButton::Enum evdev_translate_key(uint32_t key)
  194. {
  195. switch (key) {
  196. case KEY_BACKSPACE: return KeyboardButton::BACKSPACE;
  197. case KEY_TAB: return KeyboardButton::TAB;
  198. case KEY_SPACE: return KeyboardButton::SPACE;
  199. case KEY_ESC: return KeyboardButton::ESCAPE;
  200. case KEY_ENTER: return KeyboardButton::ENTER;
  201. case KEY_F1: return KeyboardButton::F1;
  202. case KEY_F2: return KeyboardButton::F2;
  203. case KEY_F3: return KeyboardButton::F3;
  204. case KEY_F4: return KeyboardButton::F4;
  205. case KEY_F5: return KeyboardButton::F5;
  206. case KEY_F6: return KeyboardButton::F6;
  207. case KEY_F7: return KeyboardButton::F7;
  208. case KEY_F8: return KeyboardButton::F8;
  209. case KEY_F9: return KeyboardButton::F9;
  210. case KEY_F10: return KeyboardButton::F10;
  211. case KEY_F11: return KeyboardButton::F11;
  212. case KEY_F12: return KeyboardButton::F12;
  213. case KEY_HOME: return KeyboardButton::HOME;
  214. case KEY_LEFT: return KeyboardButton::LEFT;
  215. case KEY_UP: return KeyboardButton::UP;
  216. case KEY_RIGHT: return KeyboardButton::RIGHT;
  217. case KEY_DOWN: return KeyboardButton::DOWN;
  218. case KEY_PAGEUP: return KeyboardButton::PAGE_UP;
  219. case KEY_PAGEDOWN: return KeyboardButton::PAGE_DOWN;
  220. case KEY_INSERT: return KeyboardButton::INS;
  221. case KEY_DELETE: return KeyboardButton::DEL;
  222. case KEY_END: return KeyboardButton::END;
  223. case KEY_LEFTSHIFT: return KeyboardButton::SHIFT_LEFT;
  224. case KEY_RIGHTSHIFT: return KeyboardButton::SHIFT_RIGHT;
  225. case KEY_LEFTCTRL: return KeyboardButton::CTRL_LEFT;
  226. case KEY_RIGHTCTRL: return KeyboardButton::CTRL_RIGHT;
  227. case KEY_CAPSLOCK: return KeyboardButton::CAPS_LOCK;
  228. case KEY_LEFTALT: return KeyboardButton::ALT_LEFT;
  229. case KEY_RIGHTALT: return KeyboardButton::ALT_RIGHT;
  230. case KEY_LEFTMETA: return KeyboardButton::SUPER_LEFT;
  231. case KEY_RIGHTMETA: return KeyboardButton::SUPER_RIGHT;
  232. case KEY_NUMLOCK: return KeyboardButton::NUM_LOCK;
  233. case KEY_KPENTER: return KeyboardButton::NUMPAD_ENTER;
  234. case KEY_KPDOT: return KeyboardButton::NUMPAD_DELETE;
  235. case KEY_KPASTERISK: return KeyboardButton::NUMPAD_MULTIPLY;
  236. case KEY_KPPLUS: return KeyboardButton::NUMPAD_ADD;
  237. case KEY_KPMINUS: return KeyboardButton::NUMPAD_SUBTRACT;
  238. case KEY_KPSLASH: return KeyboardButton::NUMPAD_DIVIDE;
  239. case KEY_KP0: return KeyboardButton::NUMPAD_0;
  240. case KEY_KP1: return KeyboardButton::NUMPAD_1;
  241. case KEY_KP2: return KeyboardButton::NUMPAD_2;
  242. case KEY_KP3: return KeyboardButton::NUMPAD_3;
  243. case KEY_KP4: return KeyboardButton::NUMPAD_4;
  244. case KEY_KP5: return KeyboardButton::NUMPAD_5;
  245. case KEY_KP6: return KeyboardButton::NUMPAD_6;
  246. case KEY_KP7: return KeyboardButton::NUMPAD_7;
  247. case KEY_KP8: return KeyboardButton::NUMPAD_8;
  248. case KEY_KP9: return KeyboardButton::NUMPAD_9;
  249. case KEY_0: return KeyboardButton::NUMBER_0;
  250. case KEY_1: return KeyboardButton::NUMBER_1;
  251. case KEY_2: return KeyboardButton::NUMBER_2;
  252. case KEY_3: return KeyboardButton::NUMBER_3;
  253. case KEY_4: return KeyboardButton::NUMBER_4;
  254. case KEY_5: return KeyboardButton::NUMBER_5;
  255. case KEY_6: return KeyboardButton::NUMBER_6;
  256. case KEY_7: return KeyboardButton::NUMBER_7;
  257. case KEY_8: return KeyboardButton::NUMBER_8;
  258. case KEY_9: return KeyboardButton::NUMBER_9;
  259. case KEY_A: return KeyboardButton::A;
  260. case KEY_B: return KeyboardButton::B;
  261. case KEY_C: return KeyboardButton::C;
  262. case KEY_D: return KeyboardButton::D;
  263. case KEY_E: return KeyboardButton::E;
  264. case KEY_F: return KeyboardButton::F;
  265. case KEY_G: return KeyboardButton::G;
  266. case KEY_H: return KeyboardButton::H;
  267. case KEY_I: return KeyboardButton::I;
  268. case KEY_J: return KeyboardButton::J;
  269. case KEY_K: return KeyboardButton::K;
  270. case KEY_L: return KeyboardButton::L;
  271. case KEY_M: return KeyboardButton::M;
  272. case KEY_N: return KeyboardButton::N;
  273. case KEY_O: return KeyboardButton::O;
  274. case KEY_P: return KeyboardButton::P;
  275. case KEY_Q: return KeyboardButton::Q;
  276. case KEY_R: return KeyboardButton::R;
  277. case KEY_S: return KeyboardButton::S;
  278. case KEY_T: return KeyboardButton::T;
  279. case KEY_U: return KeyboardButton::U;
  280. case KEY_V: return KeyboardButton::V;
  281. case KEY_W: return KeyboardButton::W;
  282. case KEY_X: return KeyboardButton::X;
  283. case KEY_Y: return KeyboardButton::Y;
  284. case KEY_Z: return KeyboardButton::Z;
  285. default: return KeyboardButton::COUNT;
  286. }
  287. }
  288. #define JS_EVENT_BUTTON 0x01 /* button pressed/released */
  289. #define JS_EVENT_AXIS 0x02 /* joystick moved */
  290. #define JS_EVENT_INIT 0x80 /* initial state of device */
  291. static u8 s_button[] =
  292. {
  293. JoypadButton::A,
  294. JoypadButton::B,
  295. JoypadButton::X,
  296. JoypadButton::Y,
  297. JoypadButton::SHOULDER_LEFT,
  298. JoypadButton::SHOULDER_RIGHT,
  299. JoypadButton::BACK,
  300. JoypadButton::START,
  301. JoypadButton::GUIDE,
  302. JoypadButton::THUMB_LEFT,
  303. JoypadButton::THUMB_RIGHT,
  304. JoypadButton::UP, // FIXME (reported as axis...)
  305. JoypadButton::DOWN,
  306. JoypadButton::LEFT,
  307. JoypadButton::RIGHT
  308. };
  309. struct JoypadEvent
  310. {
  311. u32 time; /* event timestamp in milliseconds */
  312. s16 value; /* value */
  313. u8 type; /* event type */
  314. u8 number; /* axis/button number */
  315. };
  316. struct Joypad
  317. {
  318. struct AxisData
  319. {
  320. s16 left[3];
  321. s16 right[3];
  322. };
  323. DeviceEventQueue *_queue;
  324. int _fd[CROWN_MAX_JOYPADS];
  325. AxisData _axis[CROWN_MAX_JOYPADS];
  326. explicit Joypad(DeviceEventQueue &queue)
  327. : _queue(&queue)
  328. {
  329. memset(&_fd, 0, sizeof(_fd));
  330. memset(&_axis, 0, sizeof(_axis));
  331. }
  332. void open()
  333. {
  334. char jspath[] = "/dev/input/jsX";
  335. char *num = strchr(jspath, 'X');
  336. for (u32 ii = 0; ii < CROWN_MAX_JOYPADS; ++ii) {
  337. *num = '0' + ii;
  338. _fd[ii] = ::open(jspath, O_RDONLY);
  339. _queue->push_status_event(InputDeviceType::JOYPAD, ii, _fd[ii] >= 0);
  340. }
  341. }
  342. void close()
  343. {
  344. for (u32 ii = 0; ii < CROWN_MAX_JOYPADS; ++ii) {
  345. if (_fd[ii] != -1) {
  346. ::close(_fd[ii]);
  347. _fd[ii] = -1;
  348. _queue->push_status_event(InputDeviceType::JOYPAD, ii, false);
  349. }
  350. }
  351. }
  352. void process_events(u32 joypad_id, const JoypadEvent *events, u32 num_events)
  353. {
  354. for (u32 ii = 0; ii < num_events; ++ii) {
  355. JoypadEvent ev = events[ii];
  356. switch (ev.type &= ~JS_EVENT_INIT) {
  357. case JS_EVENT_AXIS: {
  358. // Indices into axis.left/right respectively
  359. const u8 axis_idx[] = { 0, 1, 2, 0, 1, 2 };
  360. const u8 axis_map[] =
  361. {
  362. JoypadAxis::LEFT,
  363. JoypadAxis::LEFT,
  364. JoypadAxis::TRIGGER_LEFT,
  365. JoypadAxis::RIGHT,
  366. JoypadAxis::RIGHT,
  367. JoypadAxis::TRIGGER_RIGHT
  368. };
  369. // Remap triggers to [0, INT16_MAX]
  370. s16 value = ev.value;
  371. if (ev.number == 2 || ev.number == 5)
  372. value = (ev.value + INT16_MAX) >> 1;
  373. s16 *values = ev.number > 2 ? _axis[joypad_id].right : _axis[joypad_id].left;
  374. values[axis_idx[ev.number]] = value;
  375. if (ev.number == 2 || ev.number == 5) {
  376. _queue->push_axis_event(InputDeviceType::JOYPAD
  377. , joypad_id
  378. , axis_map[ev.number]
  379. , 0
  380. , 0
  381. , values[2]
  382. );
  383. } else if (ev.number < countof(axis_map)) {
  384. _queue->push_axis_event(InputDeviceType::JOYPAD
  385. , joypad_id
  386. , axis_map[ev.number]
  387. , values[0]
  388. , -values[1]
  389. , 0
  390. );
  391. }
  392. break;
  393. }
  394. case JS_EVENT_BUTTON:
  395. if (ev.number < countof(s_button)) {
  396. _queue->push_button_event(InputDeviceType::JOYPAD
  397. , joypad_id
  398. , s_button[ev.number]
  399. , ev.value == 1
  400. );
  401. }
  402. break;
  403. default:
  404. break;
  405. }
  406. }
  407. }
  408. int set_fds(fd_set *fdset, int max_fd)
  409. {
  410. for (int i = 0; i < CROWN_MAX_JOYPADS; ++i) {
  411. if (_fd[i] != -1) {
  412. FD_SET(_fd[i], fdset);
  413. max_fd = max(max_fd, _fd[i]);
  414. }
  415. }
  416. return max_fd;
  417. }
  418. void update(fd_set *fdset)
  419. {
  420. for (u8 ii = 0; ii < CROWN_MAX_JOYPADS; ++ii) {
  421. if (_fd[ii] == -1 || !FD_ISSET(_fd[ii], fdset))
  422. continue;
  423. // Read all events.
  424. JoypadEvent events[64];
  425. ssize_t num_bytes = read(_fd[ii], &events, sizeof(events));
  426. if (num_bytes > 0) {
  427. process_events(ii, events, num_bytes/ssize_t(sizeof(events[0])));
  428. } else {
  429. ::close(_fd[ii]);
  430. _fd[ii] = -1;
  431. _queue->push_status_event(InputDeviceType::JOYPAD, ii, false);
  432. }
  433. }
  434. }
  435. };
  436. static bool s_exit = false;
  437. static int exit_pipe[2];
  438. static bool push_event(const OsEvent &ev);
  439. #define X11_IMPORT() \
  440. DL_IMPORT_FUNC(XCloseDisplay, int, (::Display *)); \
  441. DL_IMPORT_FUNC(XCloseIM, Status, (XIM)); \
  442. DL_IMPORT_FUNC(XCreateBitmapFromData, Pixmap, (::Display *, Drawable, _Xconst char *, unsigned int, unsigned int)); \
  443. DL_IMPORT_FUNC(XCreateFontCursor, Cursor, (::Display *, unsigned int)); \
  444. DL_IMPORT_FUNC(XCreateIC, XIC, (XIM, ...)); \
  445. DL_IMPORT_FUNC(XCreatePixmapCursor, Cursor, (::Display *, Pixmap, Pixmap, XColor *, XColor *, unsigned int, unsigned int)); \
  446. DL_IMPORT_FUNC(XCreateWindow, ::Window, (::Display *, ::Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *)); \
  447. DL_IMPORT_FUNC(XDefineCursor, int, (::Display *, ::Window, Cursor)); \
  448. DL_IMPORT_FUNC(XDestroyIC, void, (XIC)); \
  449. DL_IMPORT_FUNC(XDestroyWindow, int, (::Display *, ::Window)); \
  450. DL_IMPORT_FUNC(XEventsQueued, int, (::Display *, int)); \
  451. DL_IMPORT_FUNC(XFetchName, int, (::Display *, ::Window, char **)); \
  452. DL_IMPORT_FUNC(XFlush, int, (::Display *)); \
  453. DL_IMPORT_FUNC(XFree, int, (void *)); \
  454. DL_IMPORT_FUNC(XFreeCursor, int, (::Display *, Cursor)); \
  455. DL_IMPORT_FUNC(XFreePixmap, int, (::Display *, Pixmap)); \
  456. DL_IMPORT_FUNC(XGetWindowAttributes, Status, (::Display *, ::Window, XWindowAttributes *)); \
  457. DL_IMPORT_FUNC(XGrabPointer, int, (::Display *, ::Window, Bool, unsigned int, int, int, ::Window, Cursor, Time)); \
  458. DL_IMPORT_FUNC(XIconifyWindow, Status, (::Display *, ::Window, int)); \
  459. DL_IMPORT_FUNC(XInitThreads, Status, (void)); \
  460. DL_IMPORT_FUNC(XInternAtom, Atom, (::Display *, _Xconst char *, Bool)); \
  461. DL_IMPORT_FUNC(XLookupKeysym, Status, (XKeyEvent *, int)); \
  462. DL_IMPORT_FUNC(XMapRaised, int, (::Display *, ::Window)); \
  463. DL_IMPORT_FUNC(XMoveWindow, int, (::Display *, ::Window, int, int)); \
  464. DL_IMPORT_FUNC(XNextEvent, int, (::Display *, XEvent *)); \
  465. DL_IMPORT_FUNC(XOpenDisplay, ::Display *, (_Xconst char *)); \
  466. DL_IMPORT_FUNC(XOpenIM, XIM, (::Display *, struct _XrmHashBucketRec *, char *, char *)); \
  467. DL_IMPORT_FUNC(XRefreshKeyboardMapping, int, (XMappingEvent *)); \
  468. DL_IMPORT_FUNC(XResizeWindow, int, (::Display *, ::Window, unsigned int, unsigned int)); \
  469. DL_IMPORT_FUNC(XSendEvent, Status, (::Display *, ::Window, Bool, long, XEvent *)); \
  470. DL_IMPORT_FUNC(XSetWMProtocols, Status, (::Display *, ::Window, Atom *, int)); \
  471. DL_IMPORT_FUNC(XStoreName, int, (::Display *, ::Window, _Xconst char *)); \
  472. DL_IMPORT_FUNC(XUngrabPointer, int, (::Display *, Time)); \
  473. DL_IMPORT_FUNC(XUnmapWindow, int, (::Display *, ::Window)); \
  474. DL_IMPORT_FUNC(XWarpPointer, int, (::Display *, ::Window, ::Window, int, int, unsigned int, unsigned int, int, int)); \
  475. DL_IMPORT_FUNC(XkbSetDetectableAutoRepeat, Bool, (::Display *, Bool, Bool *)); \
  476. DL_IMPORT_FUNC(Xutf8LookupString, int, (XIC, XKeyPressedEvent *, char *, int, KeySym *, Status *))
  477. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  478. typedef return_type (*PROTO_ ## func_name)params; \
  479. static PROTO_ ## func_name func_name
  480. X11_IMPORT();
  481. #undef DL_IMPORT_FUNC
  482. #define XRR_IMPORT() \
  483. DL_IMPORT_FUNC(XRRConfigCurrentConfiguration, SizeID, (XRRScreenConfiguration *, Rotation *)); \
  484. DL_IMPORT_FUNC(XRRConfigSizes, XRRScreenSize *, (XRRScreenConfiguration *, int *)); \
  485. DL_IMPORT_FUNC(XRRFreeScreenConfigInfo, void, (XRRScreenConfiguration *)); \
  486. DL_IMPORT_FUNC(XRRGetScreenInfo, XRRScreenConfiguration *, (::Display *, ::Window)); \
  487. DL_IMPORT_FUNC(XRRSetScreenConfig, Status, (::Display *, XRRScreenConfiguration *, Drawable, int, Rotation, Time))
  488. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  489. typedef return_type (*PROTO_ ## func_name)params; \
  490. static PROTO_ ## func_name func_name
  491. XRR_IMPORT();
  492. #undef DL_IMPORT_FUNC
  493. #define XKBCOMMON_IMPORT() \
  494. DL_IMPORT_FUNC(xkb_context_new, struct xkb_context *, (enum xkb_context_flags flags)); \
  495. DL_IMPORT_FUNC(xkb_keymap_new_from_string, struct xkb_keymap *, (struct xkb_context *context, const char *string, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags)); \
  496. DL_IMPORT_FUNC(xkb_keymap_unref, void, (struct xkb_keymap *keymap)); \
  497. DL_IMPORT_FUNC(xkb_state_key_get_one_sym, xkb_keysym_t, (struct xkb_state *state, xkb_keycode_t key)); \
  498. DL_IMPORT_FUNC(xkb_state_new, struct xkb_state *, (struct xkb_keymap *keymap)); \
  499. DL_IMPORT_FUNC(xkb_state_unref, void, (struct xkb_state *state)); \
  500. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  501. typedef return_type (*PROTO_ ## func_name)params; \
  502. static PROTO_ ## func_name func_name
  503. XKBCOMMON_IMPORT();
  504. #undef DL_IMPORT_FUNC
  505. static void registry_handle_global(void *data, wl_registry *registry, uint name, const char *iface, uint ver);
  506. static void registry_handle_global_remove(void *user_data, struct wl_registry *registry, uint32_t name);
  507. static const wl_registry_listener _wl_registry_listener =
  508. {
  509. registry_handle_global,
  510. registry_handle_global_remove
  511. };
  512. static void surface_handle_enter(void *user_data, struct wl_surface *surface, struct wl_output *output);
  513. static void surface_handle_leave(void *user_data, struct wl_surface *surface, struct wl_output *output);
  514. static const struct wl_surface_listener surface_listener =
  515. {
  516. surface_handle_enter,
  517. surface_handle_leave
  518. };
  519. static void xdg_toplevel_handle_configure(void *user_data, struct xdg_toplevel *toplevel, int32_t width, int32_t height, wl_array *states);
  520. static void xdg_toplevel_handle_close(void *user_data, struct xdg_toplevel *toplevel);
  521. static const struct xdg_toplevel_listener toplevel_listener =
  522. {
  523. xdg_toplevel_handle_configure,
  524. xdg_toplevel_handle_close
  525. };
  526. static void xdg_surface_handle_configure(void *user_data, struct xdg_surface *surface, uint32_t serial);
  527. static const xdg_surface_listener xdg_surface_listener =
  528. {
  529. xdg_surface_handle_configure,
  530. };
  531. struct WindowSystem
  532. {
  533. enum Enum
  534. {
  535. X11,
  536. WAYLAND,
  537. COUNT
  538. };
  539. };
  540. struct System
  541. {
  542. /// Returns the connection file descriptor or < 0 on error.
  543. virtual int init() = 0;
  544. ///
  545. virtual void shutdown() = 0;
  546. /// Call when events are pending on the connection.
  547. virtual void handle_events(fd_set *fdset) = 0;
  548. ///
  549. virtual int set_fds(fd_set *fdset, int max_fd) = 0;
  550. };
  551. struct SystemWayland : public System
  552. {
  553. void *wl_lib;
  554. wl_display *display;
  555. wl_registry *registry;
  556. wl_compositor *compositor;
  557. wl_seat *seat;
  558. xdg_wm_base *wm_base;
  559. wl_keyboard *keyboard;
  560. wl_pointer *pointer;
  561. zwp_relative_pointer_manager_v1 *relative_pointer_manager;
  562. zwp_relative_pointer_v1 *relative_pointer;
  563. zwp_pointer_constraints_v1 *pointer_constraints;
  564. zwp_locked_pointer_v1 *locked_pointer;
  565. CursorMode::Enum cursor_mode;
  566. struct wl_surface *surface;
  567. struct xdg_surface *xdg_surface;
  568. struct xdg_toplevel *xdg_toplevel;
  569. DeviceEventQueue *queue;
  570. int display_fd;
  571. struct
  572. {
  573. void *lib;
  574. struct xkb_context *context;
  575. struct xkb_keymap *keymap;
  576. struct xkb_state *state;
  577. } xkb;
  578. explicit SystemWayland(DeviceEventQueue &event_queue)
  579. : wl_lib(NULL)
  580. , display(NULL)
  581. , registry(NULL)
  582. , compositor(NULL)
  583. , seat(NULL)
  584. , wm_base(NULL)
  585. , keyboard(NULL)
  586. , pointer(NULL)
  587. , cursor_mode(CursorMode::NORMAL)
  588. , queue(&event_queue)
  589. , xdg_surface(NULL)
  590. , xdg_toplevel(NULL)
  591. , display_fd(-1)
  592. {
  593. }
  594. virtual ~SystemWayland()
  595. {
  596. }
  597. int init() override
  598. {
  599. wl_lib = os::library_open("libwayland-client.so");
  600. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  601. ::crown_ ## func_name = (PROTO_ ## func_name)os::library_symbol(wl_lib, # func_name); \
  602. CE_ENSURE(func_name != NULL);
  603. WAYLAND_IMPORT();
  604. #undef DL_IMPORT_FUNC
  605. for (int i = 0; i < countof(xdg_shell_types); ++i) {
  606. if (xdg_shell_types[i] == (void *)1)
  607. xdg_shell_types[i] = &wl_surface_interface;
  608. if (xdg_shell_types[i] == (void *)2)
  609. xdg_shell_types[i] = &wl_seat_interface;
  610. if (xdg_shell_types[i] == (void *)3)
  611. xdg_shell_types[i] = &wl_output_interface;
  612. }
  613. xkb.lib = os::library_open("libxkbcommon.so");
  614. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  615. func_name = (PROTO_ ## func_name)os::library_symbol(xkb.lib, # func_name); \
  616. CE_ENSURE(func_name != NULL);
  617. XKBCOMMON_IMPORT();
  618. #undef DL_IMPORT_FUNC
  619. xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
  620. CE_ASSERT(xkb.context != NULL, "xkb_context_new: error");
  621. display = wl_display_connect(NULL);
  622. CE_ASSERT(display != NULL, "wl_display_connect: error");
  623. display_fd = wl_display_get_fd(display);
  624. registry = wl_display_get_registry(display);
  625. wl_registry_add_listener(registry, &_wl_registry_listener, this);
  626. wl_display_roundtrip(display);
  627. CE_ENSURE(display != NULL);
  628. CE_ENSURE(compositor != NULL);
  629. CE_ENSURE(seat != NULL);
  630. CE_ENSURE(wm_base != NULL);
  631. return 0;
  632. }
  633. void shutdown()
  634. {
  635. if (relative_pointer_manager)
  636. zwp_relative_pointer_manager_v1_destroy(relative_pointer_manager);
  637. if (pointer_constraints)
  638. zwp_pointer_constraints_v1_destroy(pointer_constraints);
  639. os::library_close(xkb.lib);
  640. os::library_close(wl_lib);
  641. }
  642. void handle_events(fd_set *fdset) override
  643. {
  644. if (FD_ISSET(display_fd, fdset)) {
  645. if (wl_display_prepare_read(display) < 0) {
  646. wl_display_dispatch_pending(display);
  647. return;
  648. }
  649. if (wl_display_read_events(display) < 0)
  650. return; // Connection error.
  651. wl_display_dispatch(display);
  652. }
  653. }
  654. int set_fds(fd_set *fdset, int max_fd)
  655. {
  656. FD_SET(display_fd, fdset);
  657. return max(max_fd, max(display_fd, max_fd));
  658. }
  659. };
  660. static SystemWayland *_wl;
  661. static void keyboard_handle_keymap(void *user_data
  662. , wl_keyboard *keyboard
  663. , uint32_t format
  664. , int fd
  665. , uint32_t size
  666. )
  667. {
  668. SystemWayland *wl = (SystemWayland *)user_data;
  669. char *str = (char *)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
  670. if (str == MAP_FAILED) {
  671. close(fd);
  672. return;
  673. }
  674. wl->xkb.keymap = xkb_keymap_new_from_string(wl->xkb.context
  675. , str
  676. , XKB_KEYMAP_FORMAT_TEXT_V1
  677. , XKB_KEYMAP_COMPILE_NO_FLAGS
  678. );
  679. CE_ENSURE(wl->xkb.keymap != NULL);
  680. munmap(str, size);
  681. close(fd);
  682. wl->xkb.state = xkb_state_new(wl->xkb.keymap);
  683. if (!wl->xkb.state) {
  684. CE_FATAL("xkb_state_new: error");
  685. xkb_keymap_unref(wl->xkb.keymap);
  686. return;
  687. }
  688. xkb_keymap_unref(wl->xkb.keymap);
  689. xkb_state_unref(wl->xkb.state);
  690. }
  691. static void keyboard_handle_enter(void *user_data
  692. , struct wl_keyboard *keyboard
  693. , uint32_t serial
  694. , struct wl_surface *surface
  695. , struct wl_array *keys
  696. )
  697. {
  698. }
  699. static void keyboard_handle_leave(void *user_data
  700. , struct wl_keyboard *keyboard
  701. , uint32_t serial
  702. , struct wl_surface *surface
  703. )
  704. {
  705. }
  706. static void keyboard_handle_key(void *user_data
  707. , wl_keyboard *keyboard
  708. , uint32_t serial
  709. , uint32_t time
  710. , uint32_t key
  711. , uint32_t state
  712. )
  713. {
  714. SystemWayland *wl = (SystemWayland *)user_data;
  715. DeviceEventQueue &queue = *wl->queue;
  716. const KeyboardButton::Enum kb = evdev_translate_key(key);
  717. if (kb != KeyboardButton::COUNT) {
  718. queue.push_button_event(InputDeviceType::KEYBOARD
  719. , 0
  720. , kb
  721. , state == WL_KEYBOARD_KEY_STATE_PRESSED
  722. );
  723. }
  724. }
  725. static void keyboard_handle_modifiers(void *user_data
  726. , struct wl_keyboard *keyboard
  727. , uint32_t serial
  728. , uint32_t mods_depressed
  729. , uint32_t mods_latched
  730. , uint32_t mods_locked
  731. , uint32_t group
  732. )
  733. {
  734. }
  735. static const struct wl_keyboard_listener keyboard_listener =
  736. {
  737. keyboard_handle_keymap,
  738. keyboard_handle_enter,
  739. keyboard_handle_leave,
  740. keyboard_handle_key,
  741. keyboard_handle_modifiers,
  742. };
  743. static void pointer_handle_enter(void *user_data
  744. , struct wl_pointer *pointer
  745. , uint32_t serial
  746. , struct wl_surface *surface
  747. , wl_fixed_t surface_x
  748. , wl_fixed_t surface_y
  749. )
  750. {
  751. SystemWayland *wl = (SystemWayland *)user_data;
  752. const s32 mx = wl_fixed_to_int(surface_x);
  753. const s32 my = wl_fixed_to_int(surface_y);
  754. wl->queue->push_axis_event(InputDeviceType::MOUSE
  755. , 0
  756. , MouseAxis::CURSOR
  757. , (s16)mx
  758. , (s16)my
  759. , 0
  760. );
  761. }
  762. static void pointer_handle_leave(void *user_data
  763. , struct wl_pointer *pointer
  764. , uint32_t serial
  765. , struct wl_surface *surface
  766. )
  767. {
  768. }
  769. static void pointer_handle_motion(void *user_data
  770. , struct wl_pointer *pointer
  771. , uint32_t time
  772. , wl_fixed_t surface_x
  773. , wl_fixed_t surface_y
  774. )
  775. {
  776. SystemWayland *wl = (SystemWayland *)user_data;
  777. DeviceEventQueue &queue = *wl->queue;
  778. const s32 mx = wl_fixed_to_int(surface_x);
  779. const s32 my = wl_fixed_to_int(surface_y);
  780. queue.push_axis_event(InputDeviceType::MOUSE
  781. , 0
  782. , MouseAxis::CURSOR
  783. , (s16)mx
  784. , (s16)my
  785. , 0
  786. );
  787. }
  788. static void pointer_handle_button(void *user_data
  789. , struct wl_pointer *pointer
  790. , uint32_t serial
  791. , uint32_t time
  792. , uint32_t button
  793. , uint32_t state
  794. )
  795. {
  796. SystemWayland *wl = (SystemWayland *)user_data;
  797. DeviceEventQueue &queue = *wl->queue;
  798. MouseButton::Enum mb;
  799. switch (button) {
  800. case BTN_LEFT: mb = MouseButton::LEFT; break;
  801. case BTN_RIGHT: mb = MouseButton::RIGHT; break;
  802. case BTN_MIDDLE: mb = MouseButton::MIDDLE; break;
  803. default: mb = MouseButton::COUNT; break;
  804. }
  805. if (mb != MouseButton::COUNT) {
  806. queue.push_button_event(InputDeviceType::MOUSE
  807. , 0
  808. , mb
  809. , state == WL_POINTER_BUTTON_STATE_PRESSED
  810. );
  811. }
  812. }
  813. static void pointer_handle_axis(void *user_data
  814. , struct wl_pointer *pointer
  815. , uint32_t time
  816. , uint32_t axis
  817. , wl_fixed_t value
  818. )
  819. {
  820. }
  821. static const struct wl_pointer_listener pointer_listener =
  822. {
  823. pointer_handle_enter,
  824. pointer_handle_leave,
  825. pointer_handle_motion,
  826. pointer_handle_button,
  827. pointer_handle_axis,
  828. };
  829. static void relative_pointer_handle_relative_motion(void *user_data
  830. , struct zwp_relative_pointer_v1 *pointer
  831. , uint32_t time_hi
  832. , uint32_t time_lo
  833. , wl_fixed_t dx
  834. , wl_fixed_t dy
  835. , wl_fixed_t dx_unaccel
  836. , wl_fixed_t dy_unaccel
  837. )
  838. {
  839. SystemWayland *wl = (SystemWayland *)user_data;
  840. DeviceEventQueue &queue = *wl->queue;
  841. queue.push_axis_event(InputDeviceType::MOUSE
  842. , 0
  843. , MouseAxis::CURSOR_DELTA
  844. , wl_fixed_to_int(dx_unaccel)
  845. , wl_fixed_to_int(dy_unaccel)
  846. , 0
  847. );
  848. }
  849. static const struct zwp_relative_pointer_v1_listener relative_pointer_listener =
  850. {
  851. relative_pointer_handle_relative_motion
  852. };
  853. static void locked_pointer_handle_locked(void *data
  854. , struct zwp_locked_pointer_v1 *locked_pointer
  855. )
  856. {
  857. }
  858. static void locked_pointer_handle_unlocked(void *data
  859. , struct zwp_locked_pointer_v1 *locked_pointer
  860. )
  861. {
  862. }
  863. static const struct zwp_locked_pointer_v1_listener locked_pointer_listener =
  864. {
  865. locked_pointer_handle_locked,
  866. locked_pointer_handle_unlocked
  867. };
  868. static void seat_handle_capabilities(void *data, wl_seat *seat, uint32_t caps)
  869. {
  870. SystemWayland *wl = (SystemWayland *)data;
  871. if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
  872. wl->keyboard = wl_seat_get_keyboard(seat);
  873. wl_keyboard_add_listener(wl->keyboard, &keyboard_listener, wl);
  874. }
  875. if (caps & WL_SEAT_CAPABILITY_POINTER) {
  876. wl->pointer = wl_seat_get_pointer(seat);
  877. wl_pointer_add_listener(wl->pointer, &pointer_listener, wl);
  878. }
  879. }
  880. static void seat_handle_name(void *user_data
  881. , struct wl_seat *seat
  882. , const char *name
  883. )
  884. {
  885. }
  886. static const wl_seat_listener seat_listener =
  887. {
  888. seat_handle_capabilities,
  889. seat_handle_name,
  890. };
  891. static void wm_base_handle_ping(void *user_data, struct xdg_wm_base *wm_base, uint32_t serial)
  892. {
  893. xdg_wm_base_pong(wm_base, serial);
  894. }
  895. static const struct xdg_wm_base_listener wm_base_listener =
  896. {
  897. wm_base_handle_ping
  898. };
  899. static void registry_handle_global(void *data, wl_registry *registry, uint name, const char *iface, uint ver)
  900. {
  901. CE_UNUSED(ver);
  902. SystemWayland *wl = (SystemWayland *)data;
  903. if (strcmp(iface, wl_compositor_interface.name) == 0) {
  904. wl->compositor = (wl_compositor *)wl_registry_bind(registry, name, &wl_compositor_interface, 1);
  905. } else if (strcmp(iface, wl_seat_interface.name) == 0) {
  906. wl->seat = (wl_seat *)wl_registry_bind(registry, name, &wl_seat_interface, 1);
  907. wl_seat_add_listener(wl->seat, &seat_listener, wl);
  908. } else if (strcmp(iface, xdg_wm_base_interface.name) == 0) {
  909. wl->wm_base = (xdg_wm_base *)wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
  910. xdg_wm_base_add_listener(wl->wm_base, &wm_base_listener, wl);
  911. } else if (strcmp(iface, zwp_relative_pointer_manager_v1_interface.name) == 0) {
  912. wl->relative_pointer_manager = (zwp_relative_pointer_manager_v1 *)wl_registry_bind(registry, name, &zwp_relative_pointer_manager_v1_interface, 1);
  913. } else if (strcmp(iface, zwp_pointer_constraints_v1_interface.name) == 0) {
  914. wl->pointer_constraints = (zwp_pointer_constraints_v1 *)wl_registry_bind(registry, name, &zwp_pointer_constraints_v1_interface, 1);
  915. }
  916. }
  917. static void registry_handle_global_remove(void *user_data
  918. , struct wl_registry *registry
  919. , uint32_t name
  920. )
  921. {
  922. }
  923. static void surface_handle_enter(void *user_data
  924. , struct wl_surface *surface
  925. , struct wl_output *output
  926. )
  927. {
  928. }
  929. static void surface_handle_leave(void *user_data
  930. , struct wl_surface *surface
  931. , struct wl_output *output
  932. )
  933. {
  934. }
  935. static void xdg_surface_handle_configure(void *user_data
  936. , struct xdg_surface *surface
  937. , uint32_t serial
  938. )
  939. {
  940. CE_UNUSED(user_data);
  941. xdg_surface_ack_configure(surface, serial);
  942. }
  943. static void xdg_toplevel_handle_configure(void *user_data
  944. , struct xdg_toplevel *toplevel
  945. , int32_t width
  946. , int32_t height
  947. , wl_array *states
  948. )
  949. {
  950. SystemWayland *wl = (SystemWayland *)user_data;
  951. }
  952. static void xdg_toplevel_handle_close(void *user_data, struct xdg_toplevel *toplevel)
  953. {
  954. SystemWayland *wl = (SystemWayland *)user_data;
  955. DeviceEventQueue &queue = *wl->queue;
  956. queue.push_exit_event();
  957. }
  958. struct SystemX11 : public System
  959. {
  960. void *x11_lib;
  961. void *xrandr_lib;
  962. ::Display *display;
  963. int display_fd;
  964. Atom wm_delete_window;
  965. Atom net_wm_state;
  966. Atom net_wm_state_maximized_horz;
  967. Atom net_wm_state_maximized_vert;
  968. Atom net_wm_state_fullscreen;
  969. Cursor hidden_cursor;
  970. Cursor cursors[MouseCursor::COUNT];
  971. bool detectable_autorepeat;
  972. XRRScreenConfiguration *screen_config;
  973. ::Window window;
  974. Pixmap bitmap;
  975. XIM im;
  976. XIC ic;
  977. Rotation rr_old_rot;
  978. SizeID rr_old_sizeid;
  979. ::Window root_window;
  980. s16 mouse_last_x;
  981. s16 mouse_last_y;
  982. CursorMode::Enum cursor_mode;
  983. DeviceEventQueue &queue;
  984. explicit SystemX11(DeviceEventQueue &event_queue)
  985. : x11_lib(NULL)
  986. , xrandr_lib(NULL)
  987. , display(NULL)
  988. , display_fd(-1)
  989. , wm_delete_window(None)
  990. , net_wm_state(None)
  991. , net_wm_state_maximized_horz(None)
  992. , net_wm_state_maximized_vert(None)
  993. , net_wm_state_fullscreen(None)
  994. , hidden_cursor(None)
  995. , detectable_autorepeat(false)
  996. , screen_config(NULL)
  997. , window(None)
  998. , mouse_last_x(INT16_MAX)
  999. , mouse_last_y(INT16_MAX)
  1000. , cursor_mode(CursorMode::NORMAL)
  1001. , queue(event_queue)
  1002. {
  1003. }
  1004. virtual ~SystemX11()
  1005. {
  1006. }
  1007. int init() override
  1008. {
  1009. x11_lib = os::library_open("libX11.so.6");
  1010. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  1011. func_name = (PROTO_ ## func_name)os::library_symbol(x11_lib, # func_name); \
  1012. CE_ENSURE(func_name != NULL);
  1013. X11_IMPORT();
  1014. #undef DL_IMPORT_FUNC
  1015. xrandr_lib = os::library_open("libXrandr.so.2");
  1016. #define DL_IMPORT_FUNC(func_name, return_type, params) \
  1017. func_name = (PROTO_ ## func_name)os::library_symbol(xrandr_lib, # func_name); \
  1018. CE_ENSURE(func_name != NULL);
  1019. XRR_IMPORT();
  1020. #undef DL_IMPORT_FUNC
  1021. // http://tronche.com/gui/x/xlib/display/XInitThreads.html
  1022. Status xs = XInitThreads();
  1023. CE_ASSERT(xs != 0, "XInitThreads: error");
  1024. CE_UNUSED(xs);
  1025. display = XOpenDisplay(NULL);
  1026. CE_ASSERT(display != NULL, "XOpenDisplay: error");
  1027. display_fd = ConnectionNumber(display);
  1028. root_window = RootWindow(display, DefaultScreen(display));
  1029. // Do we have detectable autorepeat?
  1030. Bool detectable;
  1031. detectable_autorepeat = (bool)XkbSetDetectableAutoRepeat(display, true, &detectable);
  1032. wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
  1033. net_wm_state = XInternAtom(display, "_NET_WM_STATE", False);
  1034. net_wm_state_maximized_horz = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
  1035. net_wm_state_maximized_vert = XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
  1036. net_wm_state_fullscreen = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", False);
  1037. // Save screen configuration
  1038. screen_config = XRRGetScreenInfo(display, root_window);
  1039. rr_old_sizeid = XRRConfigCurrentConfiguration(screen_config, &rr_old_rot);
  1040. im = XOpenIM(display, NULL, NULL, NULL);
  1041. CE_ASSERT(im != NULL, "XOpenIM: error");
  1042. ic = XCreateIC(im
  1043. , XNInputStyle
  1044. , 0
  1045. | XIMPreeditNothing
  1046. | XIMStatusNothing
  1047. , XNClientWindow
  1048. , root_window
  1049. , NULL
  1050. );
  1051. CE_ASSERT(ic != NULL, "XCreateIC: error");
  1052. // Create hidden cursor
  1053. const char data[8] = { 0 };
  1054. XColor dummy;
  1055. bitmap = XCreateBitmapFromData(display, root_window, data, 8, 8);
  1056. hidden_cursor = XCreatePixmapCursor(display, bitmap, bitmap, &dummy, &dummy, 0, 0);
  1057. // Create standard cursors
  1058. cursors[MouseCursor::ARROW] = XCreateFontCursor(display, XC_top_left_arrow);
  1059. cursors[MouseCursor::HAND] = XCreateFontCursor(display, XC_hand2);
  1060. cursors[MouseCursor::TEXT_INPUT] = XCreateFontCursor(display, XC_xterm);
  1061. cursors[MouseCursor::CORNER_TOP_LEFT] = XCreateFontCursor(display, XC_top_left_corner);
  1062. cursors[MouseCursor::CORNER_TOP_RIGHT] = XCreateFontCursor(display, XC_top_right_corner);
  1063. cursors[MouseCursor::CORNER_BOTTOM_LEFT] = XCreateFontCursor(display, XC_bottom_left_corner);
  1064. cursors[MouseCursor::CORNER_BOTTOM_RIGHT] = XCreateFontCursor(display, XC_bottom_right_corner);
  1065. cursors[MouseCursor::SIZE_HORIZONTAL] = XCreateFontCursor(display, XC_sb_h_double_arrow);
  1066. cursors[MouseCursor::SIZE_VERTICAL] = XCreateFontCursor(display, XC_sb_v_double_arrow);
  1067. cursors[MouseCursor::WAIT] = XCreateFontCursor(display, XC_watch);
  1068. return 0;
  1069. }
  1070. void shutdown() override
  1071. {
  1072. // Free standard cursors.
  1073. for (s32 i = 0; i < countof(cursors); ++i)
  1074. XFreeCursor(display, cursors[i]);
  1075. // Free hidden cursor.
  1076. XFreeCursor(display, hidden_cursor);
  1077. XFreePixmap(display, bitmap);
  1078. XDestroyIC(ic);
  1079. XCloseIM(im);
  1080. // Restore previous screen configuration
  1081. Rotation rr_rot;
  1082. const SizeID rr_sizeid = XRRConfigCurrentConfiguration(screen_config, &rr_rot);
  1083. if (rr_rot != rr_old_rot || rr_sizeid != rr_old_sizeid) {
  1084. XRRSetScreenConfig(display
  1085. , screen_config
  1086. , root_window
  1087. , rr_old_sizeid
  1088. , rr_old_rot
  1089. , CurrentTime
  1090. );
  1091. }
  1092. XRRFreeScreenConfigInfo(screen_config);
  1093. XCloseDisplay(display);
  1094. os::library_close(xrandr_lib);
  1095. os::library_close(x11_lib);
  1096. }
  1097. void handle_events(fd_set *fdset) override
  1098. {
  1099. if (!FD_ISSET(display_fd, fdset))
  1100. return;
  1101. while (XEventsQueued(display, QueuedAfterFlush) > 0) {
  1102. XEvent event;
  1103. XNextEvent(display, &event);
  1104. switch (event.type) {
  1105. case EnterNotify:
  1106. mouse_last_x = (s16)event.xcrossing.x;
  1107. mouse_last_y = (s16)event.xcrossing.y;
  1108. queue.push_axis_event(InputDeviceType::MOUSE
  1109. , 0
  1110. , MouseAxis::CURSOR
  1111. , event.xcrossing.x
  1112. , event.xcrossing.y
  1113. , 0
  1114. );
  1115. break;
  1116. case ClientMessage:
  1117. if ((Atom)event.xclient.data.l[0] == wm_delete_window)
  1118. queue.push_exit_event();
  1119. break;
  1120. case ConfigureNotify:
  1121. queue.push_resolution_event(event.xconfigure.width
  1122. , event.xconfigure.height
  1123. );
  1124. break;
  1125. case ButtonPress:
  1126. case ButtonRelease: {
  1127. if (event.xbutton.button == Button4 || event.xbutton.button == Button5) {
  1128. queue.push_axis_event(InputDeviceType::MOUSE
  1129. , 0
  1130. , MouseAxis::WHEEL
  1131. , 0
  1132. , event.xbutton.button == Button4 ? 1 : -1
  1133. , 0
  1134. );
  1135. break;
  1136. }
  1137. MouseButton::Enum mb;
  1138. switch (event.xbutton.button) {
  1139. case Button1: mb = MouseButton::LEFT; break;
  1140. case Button2: mb = MouseButton::MIDDLE; break;
  1141. case Button3: mb = MouseButton::RIGHT; break;
  1142. default: mb = MouseButton::COUNT; break;
  1143. }
  1144. if (mb != MouseButton::COUNT) {
  1145. queue.push_button_event(InputDeviceType::MOUSE
  1146. , 0
  1147. , mb
  1148. , event.type == ButtonPress
  1149. );
  1150. }
  1151. break;
  1152. }
  1153. case MotionNotify: {
  1154. const s32 mx = event.xmotion.x;
  1155. const s32 my = event.xmotion.y;
  1156. s16 deltax = mx - mouse_last_x;
  1157. s16 deltay = my - mouse_last_y;
  1158. if (cursor_mode == CursorMode::DISABLED) {
  1159. XWindowAttributes window_attribs;
  1160. XGetWindowAttributes(display, window, &window_attribs);
  1161. unsigned width = window_attribs.width;
  1162. unsigned height = window_attribs.height;
  1163. if (mx != (s32)width/2 || my != (s32)height/2) {
  1164. queue.push_axis_event(InputDeviceType::MOUSE
  1165. , 0
  1166. , MouseAxis::CURSOR_DELTA
  1167. , deltax
  1168. , deltay
  1169. , 0
  1170. );
  1171. XWarpPointer(display
  1172. , None
  1173. , window
  1174. , 0
  1175. , 0
  1176. , 0
  1177. , 0
  1178. , width/2
  1179. , height/2
  1180. );
  1181. XFlush(display);
  1182. }
  1183. } else if (cursor_mode == CursorMode::NORMAL) {
  1184. queue.push_axis_event(InputDeviceType::MOUSE
  1185. , 0
  1186. , MouseAxis::CURSOR_DELTA
  1187. , deltax
  1188. , deltay
  1189. , 0
  1190. );
  1191. }
  1192. queue.push_axis_event(InputDeviceType::MOUSE
  1193. , 0
  1194. , MouseAxis::CURSOR
  1195. , (s16)mx
  1196. , (s16)my
  1197. , 0
  1198. );
  1199. mouse_last_x = (s16)mx;
  1200. mouse_last_y = (s16)my;
  1201. break;
  1202. }
  1203. case KeyPress:
  1204. case KeyRelease: {
  1205. KeySym keysym = XLookupKeysym(&event.xkey, 0);
  1206. KeyboardButton::Enum kb = x11_translate_key(keysym);
  1207. if (kb != KeyboardButton::COUNT) {
  1208. queue.push_button_event(InputDeviceType::KEYBOARD
  1209. , 0
  1210. , kb
  1211. , event.type == KeyPress
  1212. );
  1213. }
  1214. if (event.type == KeyPress) {
  1215. Status status = 0;
  1216. u8 utf8[4] = { 0 };
  1217. int len = Xutf8LookupString(ic
  1218. , &event.xkey
  1219. , (char *)utf8
  1220. , sizeof(utf8)
  1221. , NULL
  1222. , &status
  1223. );
  1224. if (status == XLookupChars || status == XLookupBoth) {
  1225. if (len)
  1226. queue.push_text_event(len, utf8);
  1227. }
  1228. }
  1229. break;
  1230. }
  1231. case KeymapNotify:
  1232. XRefreshKeyboardMapping(&event.xmapping);
  1233. break;
  1234. default:
  1235. break;
  1236. }
  1237. }
  1238. }
  1239. int set_fds(fd_set *fdset, int max_fd) override
  1240. {
  1241. FD_SET(display_fd, fdset);
  1242. return max(display_fd, max_fd);
  1243. }
  1244. };
  1245. static SystemX11 *_x11;
  1246. struct LinuxDevice
  1247. {
  1248. Allocator *_allocator;
  1249. DeviceOptions *_options;
  1250. SPSCQueue<OsEvent, CROWN_MAX_OS_EVENTS> _events;
  1251. DeviceEventQueue _queue;
  1252. Joypad _joypad;
  1253. System *_system;
  1254. WindowSystem::Enum window_system;
  1255. explicit LinuxDevice(Allocator &a)
  1256. : _allocator(&a)
  1257. , _events(a)
  1258. , _queue(push_event)
  1259. , _joypad(_queue)
  1260. , window_system(WindowSystem::COUNT)
  1261. {
  1262. }
  1263. int run(DeviceOptions *opts)
  1264. {
  1265. int init_ret = -1;
  1266. const char *display = NULL;
  1267. bool disable_wayland = true;
  1268. if (init_ret != 0 && !disable_wayland
  1269. && (display = getenv("WAYLAND_DISPLAY")) != NULL
  1270. && strlen32(display) != 0) {
  1271. _system = CE_NEW(*_allocator, SystemWayland)(_queue);
  1272. if ((init_ret = _system->init()) == 0) {
  1273. _wl = (SystemWayland *)_system;
  1274. window_system = WindowSystem::WAYLAND;
  1275. }
  1276. }
  1277. if (init_ret != 0
  1278. && (display = getenv("DISPLAY")) != NULL
  1279. && strlen32(display) != 0) {
  1280. _system = CE_NEW(*_allocator, SystemX11)(_queue);
  1281. if ((init_ret = _system->init()) == 0) {
  1282. _x11 = (SystemX11 *)_system;
  1283. window_system = WindowSystem::X11;
  1284. }
  1285. }
  1286. _options = opts;
  1287. int err = pipe(exit_pipe);
  1288. CE_ASSERT(err != -1, "pipe: errno = %d", errno);
  1289. CE_UNUSED(err);
  1290. // Start main thread
  1291. Thread main_thread;
  1292. main_thread.start([](void *user_data) {
  1293. int ec = crown::main_runtime(*((DeviceOptions *)user_data));
  1294. s_exit = true;
  1295. // Write something just to unlock the listening select().
  1296. write(exit_pipe[1], &s_exit, sizeof(s_exit));
  1297. return ec;
  1298. }
  1299. , opts
  1300. );
  1301. _joypad.open();
  1302. // Input events loop.
  1303. fd_set fdset;
  1304. while (!s_exit) {
  1305. FD_ZERO(&fdset);
  1306. FD_SET(exit_pipe[0], &fdset);
  1307. int maxfd = _system->set_fds(&fdset, exit_pipe[0]);
  1308. maxfd = _joypad.set_fds(&fdset, maxfd);
  1309. if (select(maxfd + 1, &fdset, NULL, NULL, NULL) <= 0)
  1310. continue;
  1311. if (FD_ISSET(exit_pipe[0], &fdset)) {
  1312. break;
  1313. } else {
  1314. _system->handle_events(&fdset);
  1315. _joypad.update(&fdset);
  1316. }
  1317. }
  1318. _joypad.close();
  1319. main_thread.stop();
  1320. _system->shutdown();
  1321. CE_DELETE(*_allocator, _system);
  1322. ::close(exit_pipe[0]);
  1323. ::close(exit_pipe[1]);
  1324. return main_thread.exit_code();
  1325. }
  1326. };
  1327. static LinuxDevice *s_linux_device;
  1328. struct WindowX11 : public Window
  1329. {
  1330. WindowX11()
  1331. {
  1332. }
  1333. void open(u16 x, u16 y, u16 width, u16 height, u32 parent) override
  1334. {
  1335. int screen = DefaultScreen(_x11->display);
  1336. ::Window root_window = RootWindow(_x11->display, screen);
  1337. ::Window parent_window = (parent == 0) ? root_window : (::Window)parent;
  1338. // Create main window
  1339. XSetWindowAttributes win_attribs;
  1340. win_attribs.background_pixmap = 0;
  1341. win_attribs.border_pixel = 0;
  1342. win_attribs.event_mask = FocusChangeMask
  1343. | StructureNotifyMask
  1344. ;
  1345. if (!parent) {
  1346. win_attribs.event_mask |= KeyPressMask
  1347. | KeyReleaseMask
  1348. | ButtonPressMask
  1349. | ButtonReleaseMask
  1350. | PointerMotionMask
  1351. | EnterWindowMask
  1352. ;
  1353. }
  1354. _x11->window = XCreateWindow(_x11->display
  1355. , parent_window
  1356. , x
  1357. , y
  1358. , width
  1359. , height
  1360. , 0
  1361. , CopyFromParent
  1362. , InputOutput
  1363. , CopyFromParent
  1364. , CWBorderPixel | CWEventMask
  1365. , &win_attribs
  1366. );
  1367. CE_ASSERT(_x11->window != None, "XCreateWindow: error");
  1368. XSetWMProtocols(_x11->display, _x11->window, &_x11->wm_delete_window, 1);
  1369. }
  1370. void close() override
  1371. {
  1372. XDestroyWindow(_x11->display, _x11->window);
  1373. }
  1374. void show() override
  1375. {
  1376. XMapRaised(_x11->display, _x11->window);
  1377. }
  1378. void hide() override
  1379. {
  1380. XUnmapWindow(_x11->display, _x11->window);
  1381. }
  1382. void resize(u16 width, u16 height) override
  1383. {
  1384. XResizeWindow(_x11->display, _x11->window, width, height);
  1385. XFlush(_x11->display);
  1386. }
  1387. void move(u16 x, u16 y) override
  1388. {
  1389. XMoveWindow(_x11->display, _x11->window, x, y);
  1390. }
  1391. void maximize_or_restore(bool maximize)
  1392. {
  1393. XEvent xev;
  1394. xev.type = ClientMessage;
  1395. xev.xclient.window = _x11->window;
  1396. xev.xclient.message_type = _x11->net_wm_state;
  1397. xev.xclient.format = 32;
  1398. xev.xclient.data.l[0] = maximize ? 1 : 0; // 0 = remove property, 1 = set property
  1399. xev.xclient.data.l[1] = _x11->net_wm_state_maximized_horz;
  1400. xev.xclient.data.l[2] = _x11->net_wm_state_maximized_vert;
  1401. XSendEvent(_x11->display
  1402. , DefaultRootWindow(_x11->display)
  1403. , False
  1404. , SubstructureNotifyMask | SubstructureRedirectMask
  1405. , &xev
  1406. );
  1407. }
  1408. void minimize() override
  1409. {
  1410. XIconifyWindow(_x11->display, _x11->window, DefaultScreen(_x11->display));
  1411. }
  1412. void maximize() override
  1413. {
  1414. maximize_or_restore(true);
  1415. }
  1416. void restore() override
  1417. {
  1418. maximize_or_restore(false);
  1419. }
  1420. const char *title() override
  1421. {
  1422. static char buf[512];
  1423. memset(buf, 0, sizeof(buf));
  1424. char *name;
  1425. XFetchName(_x11->display, _x11->window, &name);
  1426. strncpy(buf, name, sizeof(buf) - 1);
  1427. XFree(name);
  1428. return buf;
  1429. }
  1430. void set_title(const char *title) override
  1431. {
  1432. XStoreName(_x11->display, _x11->window, title);
  1433. }
  1434. void show_cursor(bool show) override
  1435. {
  1436. XDefineCursor(_x11->display
  1437. , _x11->window
  1438. , show ? None : _x11->hidden_cursor
  1439. );
  1440. }
  1441. void set_fullscreen(bool full) override
  1442. {
  1443. XEvent xev;
  1444. xev.xclient.type = ClientMessage;
  1445. xev.xclient.window = _x11->window;
  1446. xev.xclient.message_type = _x11->net_wm_state;
  1447. xev.xclient.format = 32;
  1448. xev.xclient.data.l[0] = full ? 1 : 0;
  1449. xev.xclient.data.l[1] = _x11->net_wm_state_fullscreen;
  1450. XSendEvent(_x11->display, DefaultRootWindow(_x11->display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
  1451. XFlush(_x11->display);
  1452. }
  1453. void set_cursor(MouseCursor::Enum cursor) override
  1454. {
  1455. XDefineCursor(_x11->display, _x11->window, _x11->cursors[cursor]);
  1456. }
  1457. void set_cursor_mode(CursorMode::Enum mode) override
  1458. {
  1459. if (mode == _x11->cursor_mode)
  1460. return;
  1461. _x11->cursor_mode = mode;
  1462. if (mode == CursorMode::DISABLED) {
  1463. XWindowAttributes window_attribs;
  1464. XGetWindowAttributes(_x11->display, _x11->window, &window_attribs);
  1465. unsigned width = window_attribs.width;
  1466. unsigned height = window_attribs.height;
  1467. _x11->mouse_last_x = width/2;
  1468. _x11->mouse_last_y = height/2;
  1469. XWarpPointer(_x11->display
  1470. , None
  1471. , _x11->window
  1472. , 0
  1473. , 0
  1474. , 0
  1475. , 0
  1476. , width/2
  1477. , height/2
  1478. );
  1479. XGrabPointer(_x11->display
  1480. , _x11->window
  1481. , True
  1482. , ButtonPressMask | ButtonReleaseMask | PointerMotionMask
  1483. , GrabModeAsync
  1484. , GrabModeAsync
  1485. , _x11->window
  1486. , _x11->hidden_cursor
  1487. , CurrentTime
  1488. );
  1489. XFlush(_x11->display);
  1490. } else if (mode == CursorMode::NORMAL) {
  1491. XUngrabPointer(_x11->display, CurrentTime);
  1492. XFlush(_x11->display);
  1493. }
  1494. }
  1495. void *native_handle() override
  1496. {
  1497. return (void *)(uintptr_t)_x11->window;
  1498. }
  1499. void *native_handle_type() override
  1500. {
  1501. return (void *)(uintptr_t)bgfx::NativeWindowHandleType::Default;
  1502. }
  1503. void *native_display() override
  1504. {
  1505. return _x11->display;
  1506. }
  1507. };
  1508. struct WindowWayland : public Window
  1509. {
  1510. WindowWayland()
  1511. {
  1512. }
  1513. void open(u16 x, u16 y, u16 width, u16 height, u32 parent) override
  1514. {
  1515. _wl->surface = wl_compositor_create_surface(_wl->compositor);
  1516. CE_ENSURE(_wl->surface != NULL);
  1517. wl_surface_add_listener(_wl->surface, &surface_listener, _wl);
  1518. }
  1519. void close() override
  1520. {
  1521. wl_surface_destroy(_wl->surface);
  1522. }
  1523. void show() override
  1524. {
  1525. get_toplevel_objects();
  1526. }
  1527. void hide() override
  1528. {
  1529. destroy_toplevel_objects();
  1530. }
  1531. void resize(u16 width, u16 height) override
  1532. {
  1533. }
  1534. void move(u16 x, u16 y) override
  1535. {
  1536. }
  1537. void maximize_or_restore(bool maximize)
  1538. {
  1539. }
  1540. void minimize() override
  1541. {
  1542. }
  1543. void maximize() override
  1544. {
  1545. maximize_or_restore(true);
  1546. }
  1547. void restore() override
  1548. {
  1549. maximize_or_restore(false);
  1550. }
  1551. const char *title() override
  1552. {
  1553. return "";
  1554. }
  1555. void set_title(const char *title) override
  1556. {
  1557. }
  1558. void show_cursor(bool show) override
  1559. {
  1560. }
  1561. void set_fullscreen(bool full) override
  1562. {
  1563. }
  1564. void set_cursor(MouseCursor::Enum cursor) override
  1565. {
  1566. }
  1567. void set_cursor_mode(CursorMode::Enum mode) override
  1568. {
  1569. if (mode == _wl->cursor_mode)
  1570. return;
  1571. _wl->cursor_mode = mode;
  1572. if (mode == CursorMode::DISABLED) {
  1573. if (!_wl->relative_pointer_manager)
  1574. return;
  1575. if (!_wl->pointer_constraints)
  1576. return;
  1577. _wl->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(_wl->relative_pointer_manager, _wl->pointer);
  1578. zwp_relative_pointer_v1_add_listener(_wl->relative_pointer, &relative_pointer_listener, _wl);
  1579. _wl->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(_wl->pointer_constraints
  1580. , _wl->surface
  1581. , _wl->pointer
  1582. , NULL
  1583. , ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT
  1584. );
  1585. zwp_locked_pointer_v1_add_listener(_wl->locked_pointer
  1586. , &locked_pointer_listener
  1587. , _wl
  1588. );
  1589. } else if (mode == CursorMode::NORMAL) {
  1590. zwp_relative_pointer_v1_destroy(_wl->relative_pointer);
  1591. _wl->relative_pointer = NULL;
  1592. zwp_locked_pointer_v1_destroy(_wl->locked_pointer);
  1593. _wl->locked_pointer = NULL;
  1594. }
  1595. }
  1596. void *native_handle() override
  1597. {
  1598. return (void *)(uintptr_t)_wl->surface;
  1599. }
  1600. void *native_handle_type() override
  1601. {
  1602. return (void *)(uintptr_t)bgfx::NativeWindowHandleType::Wayland;
  1603. }
  1604. void *native_display() override
  1605. {
  1606. return _wl->display;
  1607. }
  1608. void get_toplevel_objects()
  1609. {
  1610. if (_wl->xdg_surface == NULL) {
  1611. _wl->xdg_surface = xdg_wm_base_get_xdg_surface(_wl->wm_base, _wl->surface);
  1612. CE_ENSURE(_wl->xdg_surface != NULL);
  1613. xdg_surface_add_listener(_wl->xdg_surface, &xdg_surface_listener, _wl);
  1614. }
  1615. if (_wl->xdg_toplevel == NULL) {
  1616. _wl->xdg_toplevel = xdg_surface_get_toplevel(_wl->xdg_surface);
  1617. CE_ENSURE(_wl->xdg_toplevel != NULL);
  1618. xdg_toplevel_add_listener(_wl->xdg_toplevel, &toplevel_listener, _wl);
  1619. }
  1620. wl_surface_commit(_wl->surface);
  1621. wl_display_roundtrip(_wl->display);
  1622. }
  1623. void destroy_toplevel_objects()
  1624. {
  1625. if (_wl->xdg_toplevel) {
  1626. xdg_toplevel_destroy(_wl->xdg_toplevel);
  1627. _wl->xdg_toplevel = NULL;
  1628. }
  1629. if (_wl->xdg_surface) {
  1630. xdg_surface_destroy(_wl->xdg_surface);
  1631. _wl->xdg_surface = NULL;
  1632. }
  1633. wl_surface_attach(_wl->surface, NULL, 0, 0);
  1634. wl_surface_commit(_wl->surface);
  1635. wl_display_roundtrip(_wl->display);
  1636. }
  1637. };
  1638. namespace window
  1639. {
  1640. Window *create(Allocator &a)
  1641. {
  1642. if (s_linux_device->window_system == WindowSystem::X11)
  1643. return CE_NEW(a, WindowX11)();
  1644. else
  1645. return CE_NEW(a, WindowWayland)();
  1646. }
  1647. void destroy(Allocator &a, Window &w)
  1648. {
  1649. CE_DELETE(a, &w);
  1650. }
  1651. } // namespace window
  1652. struct DisplayXRandr : public Display
  1653. {
  1654. void modes(Array<DisplayMode> &modes) override
  1655. {
  1656. int num = 0;
  1657. XRRScreenSize *sizes = XRRConfigSizes(_x11->screen_config, &num);
  1658. if (!sizes)
  1659. return;
  1660. for (int i = 0; i < num; ++i) {
  1661. DisplayMode dm;
  1662. dm.id = (u32)i;
  1663. dm.width = sizes[i].width;
  1664. dm.height = sizes[i].height;
  1665. array::push_back(modes, dm);
  1666. }
  1667. }
  1668. void set_mode(u32 id) override
  1669. {
  1670. int num = 0;
  1671. XRRScreenSize *sizes = XRRConfigSizes(_x11->screen_config, &num);
  1672. if (!sizes || (int)id >= num)
  1673. return;
  1674. XRRSetScreenConfig(_x11->display
  1675. , _x11->screen_config
  1676. , RootWindow(_x11->display, DefaultScreen(_x11->display))
  1677. , (int)id
  1678. , RR_Rotate_0
  1679. , CurrentTime
  1680. );
  1681. }
  1682. };
  1683. struct DisplayWayland : public Display
  1684. {
  1685. void modes(Array<DisplayMode> &modes) override
  1686. {
  1687. }
  1688. void set_mode(u32 id) override
  1689. {
  1690. }
  1691. };
  1692. namespace display
  1693. {
  1694. Display *create(Allocator &a)
  1695. {
  1696. if (s_linux_device->window_system == WindowSystem::X11)
  1697. return CE_NEW(a, DisplayXRandr)();
  1698. else
  1699. return CE_NEW(a, DisplayWayland)();
  1700. }
  1701. void destroy(Allocator &a, Display &d)
  1702. {
  1703. CE_DELETE(a, &d);
  1704. }
  1705. } // namespace display
  1706. static bool push_event(const OsEvent &ev)
  1707. {
  1708. return s_linux_device->_events.push(ev);
  1709. }
  1710. bool next_event(OsEvent &ev)
  1711. {
  1712. return s_linux_device->_events.pop(ev);
  1713. }
  1714. struct InitGlobals
  1715. {
  1716. InitGlobals()
  1717. {
  1718. memory_globals::init();
  1719. profiler_globals::init();
  1720. guid_globals::init();
  1721. }
  1722. ~InitGlobals()
  1723. {
  1724. guid_globals::shutdown();
  1725. profiler_globals::shutdown();
  1726. memory_globals::shutdown();
  1727. }
  1728. };
  1729. void at_exit()
  1730. {
  1731. debug::callstack_shutdown();
  1732. }
  1733. } // namespace crown
  1734. int main(int argc, char **argv)
  1735. {
  1736. using namespace crown;
  1737. if (debug::callstack_init() != 0)
  1738. return EXIT_FAILURE;
  1739. if (atexit(at_exit) != 0) {
  1740. debug::callstack_shutdown();
  1741. return EXIT_FAILURE;
  1742. }
  1743. struct sigaction act;
  1744. // code-format off
  1745. act.sa_handler = [](int signum) {
  1746. switch (signum)
  1747. {
  1748. case SIGINT:
  1749. case SIGTERM:
  1750. if (device())
  1751. device()->quit();
  1752. break;
  1753. case SIGABRT:
  1754. case SIGBUS:
  1755. case SIGFPE:
  1756. case SIGILL:
  1757. case SIGPIPE:
  1758. case SIGSEGV:
  1759. case SIGSYS:
  1760. error::abort("Signal %d", signum);
  1761. break;
  1762. default:
  1763. error::abort("Unhandled signal %d", signum);
  1764. break;
  1765. }
  1766. };
  1767. // code-format on
  1768. sigemptyset(&act.sa_mask);
  1769. act.sa_flags = 0;
  1770. sigaction(SIGINT, &act, NULL);
  1771. sigaction(SIGTERM, &act, NULL);
  1772. sigaction(SIGABRT, &act, NULL);
  1773. sigaction(SIGBUS, &act, NULL);
  1774. sigaction(SIGFPE, &act, NULL);
  1775. sigaction(SIGILL, &act, NULL);
  1776. sigaction(SIGPIPE, &act, NULL);
  1777. sigaction(SIGSEGV, &act, NULL);
  1778. sigaction(SIGSYS, &act, NULL);
  1779. #if CROWN_BUILD_UNIT_TESTS
  1780. CommandLine cl(argc, (const char **)argv);
  1781. if (cl.has_option("run-unit-tests")) {
  1782. return main_unit_tests();
  1783. }
  1784. #endif
  1785. InitGlobals m;
  1786. CE_UNUSED(m);
  1787. DeviceOptions opts(default_allocator(), argc, (const char **)argv);
  1788. bool quit = false;
  1789. int ec = opts.parse(&quit);
  1790. if (quit)
  1791. return ec;
  1792. #if CROWN_CAN_COMPILE
  1793. if (ec == EXIT_SUCCESS && (opts._do_compile || opts._server)) {
  1794. ec = main_data_compiler(opts);
  1795. if (!opts._do_continue)
  1796. return ec;
  1797. }
  1798. #endif
  1799. if (ec == EXIT_SUCCESS) {
  1800. s_linux_device = CE_NEW(default_allocator(), LinuxDevice)(default_allocator());
  1801. ec = s_linux_device->run(&opts);
  1802. CE_DELETE(default_allocator(), s_linux_device);
  1803. }
  1804. return ec;
  1805. }
  1806. #endif // if CROWN_PLATFORM_LINUX