wl_init.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. //========================================================================
  2. // GLFW 3.4 Wayland - www.glfw.org
  3. //------------------------------------------------------------------------
  4. // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
  5. //
  6. // This software is provided 'as-is', without any express or implied
  7. // warranty. In no event will the authors be held liable for any damages
  8. // arising from the use of this software.
  9. //
  10. // Permission is granted to anyone to use this software for any purpose,
  11. // including commercial applications, and to alter it and redistribute it
  12. // freely, subject to the following restrictions:
  13. //
  14. // 1. The origin of this software must not be misrepresented; you must not
  15. // claim that you wrote the original software. If you use this software
  16. // in a product, an acknowledgment in the product documentation would
  17. // be appreciated but is not required.
  18. //
  19. // 2. Altered source versions must be plainly marked as such, and must not
  20. // be misrepresented as being the original software.
  21. //
  22. // 3. This notice may not be removed or altered from any source
  23. // distribution.
  24. //
  25. //========================================================================
  26. // It is fine to use C99 in this file because it will not be built with VS
  27. //========================================================================
  28. #define _GNU_SOURCE
  29. #include "internal.h"
  30. #include "backend_utils.h"
  31. #include "wl_client_side_decorations.h"
  32. #include "linux_desktop_settings.h"
  33. #include "../kitty/monotonic.h"
  34. #include "wl_text_input.h"
  35. #include "wayland-text-input-unstable-v3-client-protocol.h"
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <sys/mman.h>
  40. #include <unistd.h>
  41. #include <fcntl.h>
  42. #include <sys/socket.h>
  43. #include <wayland-client.h>
  44. #include <stdio.h>
  45. // errno.h needed for BSD code paths
  46. #include <errno.h>
  47. // Needed for the BTN_* defines
  48. #ifdef __has_include
  49. #if __has_include(<linux/input.h>)
  50. #include <linux/input.h>
  51. #elif __has_include(<dev/evdev/input.h>)
  52. #include <dev/evdev/input.h>
  53. #endif
  54. #else
  55. #include <linux/input.h>
  56. #endif
  57. #define debug debug_rendering
  58. #define x window->wl.allCursorPosX
  59. #define y window->wl.allCursorPosY
  60. static _GLFWwindow*
  61. get_window_from_surface(struct wl_surface* surface) {
  62. if (!surface) return NULL;
  63. _GLFWwindow *ans = wl_surface_get_user_data(surface);
  64. if (ans) {
  65. const _GLFWwindow *w = _glfw.windowListHead;
  66. while (w) {
  67. if (w == ans) return ans;
  68. w = w->next;
  69. }
  70. }
  71. return NULL;
  72. }
  73. static void
  74. pointerHandleEnter(
  75. void* data UNUSED, struct wl_pointer* pointer UNUSED, uint32_t serial, struct wl_surface* surface,
  76. wl_fixed_t sx, wl_fixed_t sy
  77. ) {
  78. _GLFWwindow* window = get_window_from_surface(surface);
  79. if (!window) return;
  80. _glfw.wl.serial = serial; _glfw.wl.input_serial = serial; _glfw.wl.pointer_serial = serial; _glfw.wl.pointer_enter_serial = serial;
  81. _glfw.wl.pointerFocus = window;
  82. window->wl.allCursorPosX = wl_fixed_to_double(sx);
  83. window->wl.allCursorPosY = wl_fixed_to_double(sy);
  84. if (surface != window->wl.surface) {
  85. csd_handle_pointer_event(window, -2, -2, surface);
  86. } else {
  87. window->wl.decorations.focus = CENTRAL_WINDOW;
  88. window->wl.hovered = true;
  89. window->wl.cursorPosX = x;
  90. window->wl.cursorPosY = y;
  91. _glfwPlatformSetCursor(window, window->wl.currentCursor);
  92. _glfwInputCursorEnter(window, true);
  93. }
  94. }
  95. static void
  96. pointerHandleLeave(void* data UNUSED, struct wl_pointer* pointer UNUSED, uint32_t serial, struct wl_surface* surface) {
  97. _GLFWwindow* window = _glfw.wl.pointerFocus;
  98. if (!window) return;
  99. _glfw.wl.serial = serial;
  100. _glfw.wl.pointerFocus = NULL;
  101. if (window->wl.surface == surface) {
  102. window->wl.hovered = false;
  103. _glfwInputCursorEnter(window, false);
  104. _glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
  105. } else csd_handle_pointer_event(window, -3, -3, surface);
  106. }
  107. static void
  108. pointerHandleMotion(void* data UNUSED, struct wl_pointer* pointer UNUSED, uint32_t time UNUSED, wl_fixed_t sx, wl_fixed_t sy) {
  109. _GLFWwindow* window = _glfw.wl.pointerFocus;
  110. if (!window || window->cursorMode == GLFW_CURSOR_DISABLED) return;
  111. window->wl.allCursorPosX = wl_fixed_to_double(sx);
  112. window->wl.allCursorPosY = wl_fixed_to_double(sy);
  113. if (window->wl.decorations.focus != CENTRAL_WINDOW) {
  114. csd_handle_pointer_event(window, -1, -1, NULL);
  115. } else {
  116. window->wl.cursorPosX = x;
  117. window->wl.cursorPosY = y;
  118. _glfwInputCursorPos(window, x, y);
  119. _glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
  120. }
  121. }
  122. static void pointerHandleButton(void* data UNUSED,
  123. struct wl_pointer* pointer UNUSED,
  124. uint32_t serial,
  125. uint32_t time UNUSED,
  126. uint32_t button,
  127. uint32_t state)
  128. {
  129. _glfw.wl.serial = serial; _glfw.wl.input_serial = serial; _glfw.wl.pointer_serial = serial;
  130. _GLFWwindow* window = _glfw.wl.pointerFocus;
  131. if (!window) return;
  132. if (window->wl.decorations.focus != CENTRAL_WINDOW) {
  133. csd_handle_pointer_event(window, button, state, NULL);
  134. return;
  135. }
  136. /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
  137. * codes. */
  138. int glfwButton = button - BTN_LEFT;
  139. _glfwInputMouseClick(
  140. window, glfwButton, state == WL_POINTER_BUTTON_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE, _glfw.wl.xkb.states.modifiers);
  141. }
  142. #undef x
  143. #undef y
  144. #define info (window->wl.pointer_curr_axis_info)
  145. static void
  146. pointer_handle_axis_common(enum _GLFWWaylandAxisEvent type, uint32_t axis, wl_fixed_t value) {
  147. _GLFWwindow* window = _glfw.wl.pointerFocus;
  148. if (!window || window->wl.decorations.focus != CENTRAL_WINDOW) return;
  149. float fval = (float) wl_fixed_to_double(value);
  150. #define CASE(type, type_const, axis, fval) \
  151. case type_const: \
  152. if (info.type.axis##_axis_type == AXIS_EVENT_UNKNOWN) { \
  153. info.type.axis##_axis_type = type_const; info.type.axis = 0.f; } \
  154. info.type.axis += fval; break;
  155. if (window) {
  156. switch ((enum wl_pointer_axis)axis) {
  157. case WL_POINTER_AXIS_VERTICAL_SCROLL:
  158. switch (type) {
  159. case AXIS_EVENT_UNKNOWN: break;
  160. CASE(discrete, AXIS_EVENT_DISCRETE, y, -fval); // wheel event
  161. CASE(discrete, AXIS_EVENT_VALUE120, y, -fval); // wheel event higher res than plain discrete
  162. CASE(continuous, AXIS_EVENT_CONTINUOUS, y, -fval); // touchpad, etc. high res
  163. }
  164. break;
  165. case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
  166. switch (type) {
  167. case AXIS_EVENT_UNKNOWN: break;
  168. CASE(discrete, AXIS_EVENT_DISCRETE, x, fval); // wheel event
  169. CASE(discrete, AXIS_EVENT_VALUE120, x, fval); // wheel event higher res than plain discrete
  170. CASE(continuous, AXIS_EVENT_CONTINUOUS, x, fval); // touchpad, etc. high res
  171. }
  172. break;
  173. }
  174. }
  175. #undef CASE
  176. }
  177. static void
  178. pointer_handle_axis(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t time, uint32_t axis, wl_fixed_t value) {
  179. _GLFWwindow* window = _glfw.wl.pointerFocus;
  180. if (!window) return;
  181. if (!info.timestamp_ns) info.timestamp_ns = ms_to_monotonic_t(time);
  182. pointer_handle_axis_common(AXIS_EVENT_CONTINUOUS, axis, value);
  183. }
  184. static void
  185. pointer_handle_frame(void *data UNUSED, struct wl_pointer *pointer UNUSED) {
  186. _GLFWwindow* window = _glfw.wl.pointerFocus;
  187. if (!window) return;
  188. float x = 0, y = 0;
  189. int highres = 0;
  190. if (info.discrete.y_axis_type != AXIS_EVENT_UNKNOWN) {
  191. y = info.discrete.y;
  192. if (info.discrete.y_axis_type == AXIS_EVENT_VALUE120) y /= 120.f;
  193. } else if (info.continuous.y_axis_type != AXIS_EVENT_UNKNOWN) {
  194. highres = 1;
  195. y = info.continuous.y;
  196. }
  197. if (info.discrete.x_axis_type != AXIS_EVENT_UNKNOWN) {
  198. x = info.discrete.x;
  199. if (info.discrete.x_axis_type == AXIS_EVENT_VALUE120) x /= 120.f;
  200. } else if (info.continuous.x_axis_type != AXIS_EVENT_UNKNOWN) {
  201. highres = 1;
  202. x = info.continuous.x;
  203. }
  204. /* clear pointer_curr_axis_info for next frame */
  205. memset(&info, 0, sizeof(info));
  206. if (x != 0.0f || y != 0.0f) {
  207. float scale = (float)_glfwWaylandWindowScale(window);
  208. y *= scale; x *= scale;
  209. _glfwInputScroll(window, -x, y, highres, _glfw.wl.xkb.states.modifiers);
  210. }
  211. }
  212. static void
  213. pointer_handle_axis_source(void* data UNUSED, struct wl_pointer* pointer UNUSED, uint32_t source UNUSED) { }
  214. static void
  215. pointer_handle_axis_stop(void *data UNUSED, struct wl_pointer *wl_pointer UNUSED, uint32_t time UNUSED, uint32_t axis UNUSED) { }
  216. static void
  217. pointer_handle_axis_discrete(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t axis, int32_t discrete) {
  218. pointer_handle_axis_common(AXIS_EVENT_DISCRETE, axis, wl_fixed_from_int(discrete));
  219. }
  220. static void
  221. pointer_handle_axis_value120(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t axis, int32_t value120) {
  222. pointer_handle_axis_common(AXIS_EVENT_VALUE120, axis, wl_fixed_from_int(value120));
  223. }
  224. static void
  225. pointer_handle_axis_relative_direction(void *data UNUSED, struct wl_pointer *pointer UNUSED, uint32_t axis UNUSED, uint32_t axis_relative_direction UNUSED) { }
  226. #undef info
  227. static const struct wl_pointer_listener pointerListener = {
  228. .enter = pointerHandleEnter,
  229. .leave = pointerHandleLeave,
  230. .motion = pointerHandleMotion,
  231. .button = pointerHandleButton,
  232. .axis = pointer_handle_axis,
  233. .frame = pointer_handle_frame,
  234. .axis_source = pointer_handle_axis_source,
  235. .axis_stop = pointer_handle_axis_stop,
  236. .axis_discrete = pointer_handle_axis_discrete,
  237. #ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
  238. .axis_value120 = pointer_handle_axis_value120,
  239. #endif
  240. #ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
  241. .axis_relative_direction = pointer_handle_axis_relative_direction,
  242. #endif
  243. };
  244. static void keyboardHandleKeymap(void* data UNUSED,
  245. struct wl_keyboard* keyboard UNUSED,
  246. uint32_t format,
  247. int fd,
  248. uint32_t size)
  249. {
  250. char* mapStr;
  251. if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
  252. {
  253. _glfwInputError(GLFW_PLATFORM_ERROR, "Unknown keymap format: %u", format);
  254. close(fd);
  255. return;
  256. }
  257. mapStr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
  258. if (mapStr == MAP_FAILED) {
  259. close(fd);
  260. _glfwInputError(GLFW_PLATFORM_ERROR, "Mapping of keymap file descriptor failed: %u", format);
  261. return;
  262. }
  263. glfw_xkb_compile_keymap(&_glfw.wl.xkb, mapStr);
  264. munmap(mapStr, size);
  265. close(fd);
  266. }
  267. static void keyboardHandleEnter(void* data UNUSED,
  268. struct wl_keyboard* keyboard UNUSED,
  269. uint32_t serial,
  270. struct wl_surface* surface,
  271. struct wl_array* keys)
  272. {
  273. _GLFWwindow* window = get_window_from_surface(surface);
  274. if (!window) return;
  275. _glfw.wl.serial = serial; _glfw.wl.input_serial = serial; _glfw.wl.keyboard_enter_serial = serial;
  276. _glfw.wl.keyboardFocusId = window->id;
  277. _glfwInputWindowFocus(window, true);
  278. uint32_t* key;
  279. if (keys && _glfw.wl.keyRepeatInfo.key) {
  280. wl_array_for_each(key, keys) {
  281. if (*key == _glfw.wl.keyRepeatInfo.key) {
  282. toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
  283. break;
  284. }
  285. }
  286. }
  287. }
  288. static void keyboardHandleLeave(void* data UNUSED,
  289. struct wl_keyboard* keyboard UNUSED,
  290. uint32_t serial,
  291. struct wl_surface* surface UNUSED)
  292. {
  293. _GLFWwindow* window = _glfwWindowForId(_glfw.wl.keyboardFocusId);
  294. if (!window)
  295. return;
  296. _glfw.wl.serial = serial;
  297. _glfw.wl.keyboardFocusId = 0;
  298. _glfwInputWindowFocus(window, false);
  299. toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 0);
  300. }
  301. static void
  302. dispatchPendingKeyRepeats(id_type timer_id UNUSED, void *data UNUSED) {
  303. if (_glfw.wl.keyRepeatInfo.keyboardFocusId != _glfw.wl.keyboardFocusId || _glfw.wl.keyboardRepeatRate == 0) return;
  304. _GLFWwindow* window = _glfwWindowForId(_glfw.wl.keyboardFocusId);
  305. if (!window) return;
  306. glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, _glfw.wl.keyRepeatInfo.key, GLFW_REPEAT);
  307. changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, (s_to_monotonic_t(1ll) / (monotonic_t)_glfw.wl.keyboardRepeatRate));
  308. toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
  309. }
  310. static void keyboardHandleKey(void* data UNUSED,
  311. struct wl_keyboard* keyboard UNUSED,
  312. uint32_t serial,
  313. uint32_t time UNUSED,
  314. uint32_t key,
  315. uint32_t state)
  316. {
  317. _GLFWwindow* window = _glfwWindowForId(_glfw.wl.keyboardFocusId);
  318. if (!window)
  319. return;
  320. int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
  321. _glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
  322. glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
  323. if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key))
  324. {
  325. _glfw.wl.keyRepeatInfo.key = key;
  326. _glfw.wl.keyRepeatInfo.keyboardFocusId = window->id;
  327. changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, _glfw.wl.keyboardRepeatDelay);
  328. toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
  329. } else if (action == GLFW_RELEASE && key == _glfw.wl.keyRepeatInfo.key) {
  330. _glfw.wl.keyRepeatInfo.key = 0;
  331. toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 0);
  332. }
  333. }
  334. static void keyboardHandleModifiers(void* data UNUSED,
  335. struct wl_keyboard* keyboard UNUSED,
  336. uint32_t serial,
  337. uint32_t modsDepressed,
  338. uint32_t modsLatched,
  339. uint32_t modsLocked,
  340. uint32_t group)
  341. {
  342. _glfw.wl.serial = serial; _glfw.wl.input_serial = serial;
  343. glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group);
  344. }
  345. static void keyboardHandleRepeatInfo(void* data UNUSED,
  346. struct wl_keyboard* keyboard,
  347. int32_t rate,
  348. int32_t delay)
  349. {
  350. if (keyboard != _glfw.wl.keyboard)
  351. return;
  352. _glfw.wl.keyboardRepeatRate = rate;
  353. _glfw.wl.keyboardRepeatDelay = ms_to_monotonic_t(delay);
  354. }
  355. static const struct wl_keyboard_listener keyboardListener = {
  356. keyboardHandleKeymap,
  357. keyboardHandleEnter,
  358. keyboardHandleLeave,
  359. keyboardHandleKey,
  360. keyboardHandleModifiers,
  361. keyboardHandleRepeatInfo,
  362. };
  363. static void seatHandleCapabilities(void* data UNUSED,
  364. struct wl_seat* seat,
  365. enum wl_seat_capability caps)
  366. {
  367. if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
  368. {
  369. _glfw.wl.pointer = wl_seat_get_pointer(seat);
  370. wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
  371. if (_glfw.wl.wp_cursor_shape_manager_v1) {
  372. if (_glfw.wl.wp_cursor_shape_device_v1) wp_cursor_shape_device_v1_destroy(_glfw.wl.wp_cursor_shape_device_v1);
  373. _glfw.wl.wp_cursor_shape_device_v1 = NULL;
  374. _glfw.wl.wp_cursor_shape_device_v1 = wp_cursor_shape_manager_v1_get_pointer(_glfw.wl.wp_cursor_shape_manager_v1, _glfw.wl.pointer);
  375. }
  376. }
  377. else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
  378. {
  379. if (_glfw.wl.wp_cursor_shape_device_v1) wp_cursor_shape_device_v1_destroy(_glfw.wl.wp_cursor_shape_device_v1);
  380. _glfw.wl.wp_cursor_shape_device_v1 = NULL;
  381. wl_pointer_destroy(_glfw.wl.pointer);
  382. _glfw.wl.pointer = NULL;
  383. if (_glfw.wl.cursorAnimationTimer) toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 0);
  384. }
  385. if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
  386. {
  387. _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
  388. wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
  389. }
  390. else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
  391. {
  392. wl_keyboard_destroy(_glfw.wl.keyboard);
  393. _glfw.wl.keyboard = NULL;
  394. _glfw.wl.keyboardFocusId = 0;
  395. if (_glfw.wl.keyRepeatInfo.keyRepeatTimer) toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 0);
  396. }
  397. }
  398. static void seatHandleName(void* data UNUSED,
  399. struct wl_seat* seat UNUSED,
  400. const char* name UNUSED)
  401. {
  402. }
  403. static const struct wl_seat_listener seatListener = {
  404. seatHandleCapabilities,
  405. seatHandleName,
  406. };
  407. static void wmBaseHandlePing(void* data UNUSED,
  408. struct xdg_wm_base* wmBase,
  409. uint32_t serial)
  410. {
  411. xdg_wm_base_pong(wmBase, serial);
  412. }
  413. static const struct xdg_wm_base_listener wmBaseListener = {
  414. wmBaseHandlePing
  415. };
  416. static void registryHandleGlobal(void* data UNUSED,
  417. struct wl_registry* registry,
  418. uint32_t name,
  419. const char* interface,
  420. uint32_t version)
  421. {
  422. #define is(x) strcmp(interface, x##_interface.name) == 0
  423. if (is(wl_compositor))
  424. {
  425. #ifdef WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION
  426. _glfw.wl.compositorVersion = MIN(WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION, (int)version);
  427. _glfw.wl.has_preferred_buffer_scale = _glfw.wl.compositorVersion >= WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION;
  428. #else
  429. _glfw.wl.compositorVersion = MIN(3, (int)version);
  430. #endif
  431. _glfw.wl.compositor = wl_registry_bind(registry, name, &wl_compositor_interface, _glfw.wl.compositorVersion);
  432. }
  433. else if (is(wl_subcompositor))
  434. {
  435. _glfw.wl.subcompositor =
  436. wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
  437. }
  438. else if (is(wl_shm))
  439. {
  440. _glfw.wl.shm =
  441. wl_registry_bind(registry, name, &wl_shm_interface, 1);
  442. }
  443. else if (is(wl_output))
  444. {
  445. _glfwAddOutputWayland(name, version);
  446. }
  447. else if (is(wl_seat))
  448. {
  449. if (!_glfw.wl.seat)
  450. {
  451. #ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
  452. _glfw.wl.seatVersion = MIN(WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION, (int)version);
  453. #elif defined(WL_POINTER_AXIS_VALUE120_SINCE_VERSION)
  454. _glfw.wl.seatVersion = MIN(WL_POINTER_AXIS_VALUE120_SINCE_VERSION, (int)version);
  455. #else
  456. _glfw.wl.seatVersion = MIN(WL_POINTER_AXIS_DISCRETE_SINCE_VERSION, version);
  457. #endif
  458. _glfw.wl.seat =
  459. wl_registry_bind(registry, name, &wl_seat_interface,
  460. _glfw.wl.seatVersion);
  461. wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
  462. }
  463. if (_glfw.wl.seat) {
  464. if (_glfw.wl.dataDeviceManager && !_glfw.wl.dataDevice) _glfwSetupWaylandDataDevice();
  465. if (_glfw.wl.primarySelectionDeviceManager && !_glfw.wl.primarySelectionDevice) {
  466. _glfwSetupWaylandPrimarySelectionDevice();
  467. }
  468. }
  469. }
  470. else if (is(xdg_wm_base))
  471. {
  472. _glfw.wl.xdg_wm_base_version = 1;
  473. #ifdef XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION
  474. _glfw.wl.xdg_wm_base_version = MIN(XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION, (int)version);
  475. #elif defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
  476. _glfw.wl.xdg_wm_base_version = MIN(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION, (int)version);
  477. #endif
  478. _glfw.wl.wmBase = wl_registry_bind(registry, name, &xdg_wm_base_interface, _glfw.wl.xdg_wm_base_version);
  479. xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
  480. }
  481. else if (is(zxdg_decoration_manager_v1))
  482. {
  483. _glfw.wl.decorationManager =
  484. wl_registry_bind(registry, name,
  485. &zxdg_decoration_manager_v1_interface, 1);
  486. }
  487. else if (is(zwp_relative_pointer_manager_v1))
  488. {
  489. _glfw.wl.relativePointerManager =
  490. wl_registry_bind(registry, name,
  491. &zwp_relative_pointer_manager_v1_interface,
  492. 1);
  493. }
  494. else if (is(zwp_pointer_constraints_v1))
  495. {
  496. _glfw.wl.pointerConstraints =
  497. wl_registry_bind(registry, name,
  498. &zwp_pointer_constraints_v1_interface,
  499. 1);
  500. }
  501. else if (is(zwp_text_input_manager_v3))
  502. {
  503. _glfwWaylandBindTextInput(registry, name);
  504. }
  505. else if (is(wl_data_device_manager))
  506. {
  507. _glfw.wl.dataDeviceManager =
  508. wl_registry_bind(registry, name,
  509. &wl_data_device_manager_interface,
  510. 1);
  511. if (_glfw.wl.seat && _glfw.wl.dataDeviceManager && !_glfw.wl.dataDevice) {
  512. _glfwSetupWaylandDataDevice();
  513. }
  514. }
  515. else if (is(zwp_primary_selection_device_manager_v1))
  516. {
  517. _glfw.wl.primarySelectionDeviceManager =
  518. wl_registry_bind(registry, name,
  519. &zwp_primary_selection_device_manager_v1_interface,
  520. 1);
  521. if (_glfw.wl.seat && _glfw.wl.primarySelectionDeviceManager && !_glfw.wl.primarySelectionDevice) {
  522. _glfwSetupWaylandPrimarySelectionDevice();
  523. }
  524. }
  525. else if (is(wp_single_pixel_buffer_manager_v1)) {
  526. _glfw.wl.wp_single_pixel_buffer_manager_v1 = wl_registry_bind(registry, name, &wp_single_pixel_buffer_manager_v1_interface, 1);
  527. }
  528. else if (is(xdg_activation_v1)) {
  529. _glfw.wl.xdg_activation_v1 = wl_registry_bind(registry, name, &xdg_activation_v1_interface, 1);
  530. }
  531. else if (is(wp_cursor_shape_manager_v1)) {
  532. _glfw.wl.wp_cursor_shape_manager_v1 = wl_registry_bind(registry, name, &wp_cursor_shape_manager_v1_interface, 1);
  533. }
  534. else if (is(wp_fractional_scale_manager_v1)) {
  535. _glfw.wl.wp_fractional_scale_manager_v1 = wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, 1);
  536. }
  537. else if (is(wp_viewporter)) {
  538. _glfw.wl.wp_viewporter = wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
  539. }
  540. else if (is(org_kde_kwin_blur_manager)) {
  541. _glfw.wl.org_kde_kwin_blur_manager = wl_registry_bind(registry, name, &org_kde_kwin_blur_manager_interface, 1);
  542. }
  543. else if (is(zwlr_layer_shell_v1)) {
  544. if (version >= 4) {
  545. _glfw.wl.zwlr_layer_shell_v1_version = version;
  546. _glfw.wl.zwlr_layer_shell_v1 = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, version);
  547. }
  548. }
  549. #undef is
  550. }
  551. static void registryHandleGlobalRemove(void *data UNUSED,
  552. struct wl_registry *registry UNUSED,
  553. uint32_t name)
  554. {
  555. _GLFWmonitor* monitor;
  556. for (int i = 0; i < _glfw.monitorCount; ++i)
  557. {
  558. monitor = _glfw.monitors[i];
  559. if (monitor->wl.name == name)
  560. {
  561. for (_GLFWwindow *window = _glfw.windowListHead; window; window = window->next) {
  562. for (int m = window->wl.monitorsCount - 1; m >= 0; m--) {
  563. if (window->wl.monitors[m] == monitor) {
  564. remove_i_from_array(window->wl.monitors, m, window->wl.monitorsCount);
  565. }
  566. }
  567. }
  568. _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
  569. return;
  570. }
  571. }
  572. }
  573. static const struct wl_registry_listener registryListener = {
  574. registryHandleGlobal,
  575. registryHandleGlobalRemove
  576. };
  577. GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(void) {
  578. return glfw_current_system_color_theme();
  579. }
  580. static pid_t
  581. get_socket_peer_pid(int fd) {
  582. (void)fd;
  583. #ifdef __linux__
  584. struct ucred ucred;
  585. socklen_t len = sizeof(struct ucred);
  586. return (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) ? -1 : ucred.pid;
  587. #elif defined(LOCAL_PEERCRED) && defined(XUCRED_VERSION)
  588. struct xucred peercred;
  589. socklen_t peercredlen = sizeof(peercred);
  590. return (getsockopt(c->fd, LOCAL_PEERCRED, 1, (void *)&peercred, &peercredlen) == 0 && peercred.cr_version == XUCRED_VERSION) ? peercred.cr_pid : -1;
  591. #elif defined(LOCAL_PEERPID)
  592. pid_t pid;
  593. socklen_t pid_size = sizeof(pid);
  594. return getsockopt(client, SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size) == -1 ? -1 : pid;
  595. #else
  596. errno = ENOSYS;
  597. return -1;
  598. #endif
  599. }
  600. GLFWAPI pid_t glfwWaylandCompositorPID(void) {
  601. if (!_glfw.wl.display) return -1;
  602. int fd = wl_display_get_fd(_glfw.wl.display);
  603. if (fd < 0) return -1;
  604. return get_socket_peer_pid(fd);
  605. }
  606. //////////////////////////////////////////////////////////////////////////
  607. ////// GLFW platform API //////
  608. //////////////////////////////////////////////////////////////////////////
  609. static const char*
  610. get_compositor_missing_capabilities(void) {
  611. #define C(title, x) if (!_glfw.wl.x) p += snprintf(buf, sizeof(buf) - (p - buf), "%s", #title);
  612. static char buf[256];
  613. char *p = buf;
  614. *p = 0;
  615. C(viewporter, wp_viewporter); C(fractional_scale, wp_fractional_scale_manager_v1);
  616. C(blur, org_kde_kwin_blur_manager); C(server_side_decorations, decorationManager);
  617. C(cursor_shape, wp_cursor_shape_manager_v1); C(layer_shell, zwlr_layer_shell_v1);
  618. C(single_pixel_buffer, wp_single_pixel_buffer_manager_v1); C(preferred_scale, has_preferred_buffer_scale);
  619. #undef C
  620. return buf;
  621. }
  622. GLFWAPI const char* glfwWaylandMissingCapabilities(void) { return get_compositor_missing_capabilities(); }
  623. int _glfwPlatformInit(void)
  624. {
  625. int i;
  626. _GLFWmonitor* monitor;
  627. _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
  628. if (!_glfw.wl.cursor.handle)
  629. {
  630. _glfwInputError(GLFW_PLATFORM_ERROR,
  631. "Wayland: Failed to open libwayland-cursor");
  632. return false;
  633. }
  634. glfw_dlsym(_glfw.wl.cursor.theme_load, _glfw.wl.cursor.handle, "wl_cursor_theme_load");
  635. glfw_dlsym(_glfw.wl.cursor.theme_destroy, _glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
  636. glfw_dlsym(_glfw.wl.cursor.theme_get_cursor, _glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
  637. glfw_dlsym(_glfw.wl.cursor.image_get_buffer, _glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
  638. _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
  639. if (!_glfw.wl.egl.handle)
  640. {
  641. _glfwInputError(GLFW_PLATFORM_ERROR,
  642. "Wayland: Failed to open libwayland-egl");
  643. return false;
  644. }
  645. glfw_dlsym(_glfw.wl.egl.window_create, _glfw.wl.egl.handle, "wl_egl_window_create");
  646. glfw_dlsym(_glfw.wl.egl.window_destroy, _glfw.wl.egl.handle, "wl_egl_window_destroy");
  647. glfw_dlsym(_glfw.wl.egl.window_resize, _glfw.wl.egl.handle, "wl_egl_window_resize");
  648. _glfw.wl.display = wl_display_connect(NULL);
  649. if (!_glfw.wl.display)
  650. {
  651. _glfwInputError(GLFW_PLATFORM_ERROR,
  652. "Wayland: Failed to connect to display");
  653. return false;
  654. }
  655. if (!initPollData(&_glfw.wl.eventLoopData, wl_display_get_fd(_glfw.wl.display))) {
  656. _glfwInputError(GLFW_PLATFORM_ERROR,
  657. "Wayland: Failed to initialize event loop data");
  658. }
  659. glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData);
  660. glfw_initialize_desktop_settings();
  661. _glfw.wl.keyRepeatInfo.keyRepeatTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-key-repeat", ms_to_monotonic_t(500ll), 0, true, dispatchPendingKeyRepeats, NULL, NULL);
  662. _glfw.wl.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", ms_to_monotonic_t(500ll), 0, true, animateCursorImage, NULL, NULL);
  663. _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
  664. wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
  665. if (!glfw_xkb_create_context(&_glfw.wl.xkb)) return false;
  666. // Sync so we got all registry objects
  667. wl_display_roundtrip(_glfw.wl.display);
  668. _glfwWaylandInitTextInput();
  669. // Sync so we got all initial output events
  670. wl_display_roundtrip(_glfw.wl.display);
  671. for (i = 0; i < _glfw.monitorCount; ++i)
  672. {
  673. monitor = _glfw.monitors[i];
  674. if (monitor->widthMM <= 0 || monitor->heightMM <= 0)
  675. {
  676. // If Wayland does not provide a physical size, assume the default 96 DPI
  677. monitor->widthMM = (int) (monitor->modes[monitor->wl.currentMode].width * 25.4f / 96.f);
  678. monitor->heightMM = (int) (monitor->modes[monitor->wl.currentMode].height * 25.4f / 96.f);
  679. }
  680. }
  681. if (!_glfw.wl.wmBase)
  682. {
  683. _glfwInputError(GLFW_PLATFORM_ERROR,
  684. "Wayland: Failed to find xdg-shell in your compositor");
  685. return false;
  686. }
  687. if (_glfw.wl.shm)
  688. {
  689. _glfw.wl.cursorSurface =
  690. wl_compositor_create_surface(_glfw.wl.compositor);
  691. }
  692. else
  693. {
  694. _glfwInputError(GLFW_PLATFORM_ERROR,
  695. "Wayland: Failed to find Wayland SHM");
  696. return false;
  697. }
  698. if (_glfw.hints.init.debugRendering) {
  699. const char *mc = get_compositor_missing_capabilities();
  700. if (mc && mc[0]) debug("Compositor missing capabilities: %s\n", mc);
  701. }
  702. return true;
  703. }
  704. void _glfwPlatformTerminate(void)
  705. {
  706. if (_glfw.wl.activation_requests.array) {
  707. for (size_t i=0; i < _glfw.wl.activation_requests.sz; i++) {
  708. glfw_wl_xdg_activation_request *r = _glfw.wl.activation_requests.array + i;
  709. if (r->callback) r->callback(NULL, NULL, r->callback_data);
  710. xdg_activation_token_v1_destroy(r->token);
  711. }
  712. free(_glfw.wl.activation_requests.array);
  713. }
  714. _glfwTerminateEGL();
  715. if (_glfw.wl.egl.handle)
  716. {
  717. _glfw_dlclose(_glfw.wl.egl.handle);
  718. _glfw.wl.egl.handle = NULL;
  719. }
  720. glfw_xkb_release(&_glfw.wl.xkb);
  721. glfw_dbus_terminate(&_glfw.wl.dbus);
  722. glfw_wlc_destroy();
  723. if (_glfw.wl.cursor.handle)
  724. {
  725. _glfw_dlclose(_glfw.wl.cursor.handle);
  726. _glfw.wl.cursor.handle = NULL;
  727. }
  728. if (_glfw.wl.cursorSurface)
  729. wl_surface_destroy(_glfw.wl.cursorSurface);
  730. if (_glfw.wl.subcompositor)
  731. wl_subcompositor_destroy(_glfw.wl.subcompositor);
  732. if (_glfw.wl.compositor)
  733. wl_compositor_destroy(_glfw.wl.compositor);
  734. if (_glfw.wl.shm)
  735. wl_shm_destroy(_glfw.wl.shm);
  736. if (_glfw.wl.decorationManager)
  737. zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
  738. if (_glfw.wl.wmBase)
  739. xdg_wm_base_destroy(_glfw.wl.wmBase);
  740. if (_glfw.wl.pointer)
  741. wl_pointer_destroy(_glfw.wl.pointer);
  742. if (_glfw.wl.keyboard)
  743. wl_keyboard_destroy(_glfw.wl.keyboard);
  744. if (_glfw.wl.seat)
  745. wl_seat_destroy(_glfw.wl.seat);
  746. if (_glfw.wl.relativePointerManager)
  747. zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
  748. if (_glfw.wl.pointerConstraints)
  749. zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
  750. _glfwWaylandDestroyTextInput();
  751. if (_glfw.wl.dataSourceForClipboard)
  752. wl_data_source_destroy(_glfw.wl.dataSourceForClipboard);
  753. if (_glfw.wl.dataSourceForPrimarySelection)
  754. zwp_primary_selection_source_v1_destroy(_glfw.wl.dataSourceForPrimarySelection);
  755. for (size_t doi=0; doi < arraysz(_glfw.wl.dataOffers); doi++) {
  756. if (_glfw.wl.dataOffers[doi].id) {
  757. destroy_data_offer(&_glfw.wl.dataOffers[doi]);
  758. }
  759. }
  760. if (_glfw.wl.dataDevice)
  761. wl_data_device_destroy(_glfw.wl.dataDevice);
  762. if (_glfw.wl.dataDeviceManager)
  763. wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
  764. if (_glfw.wl.primarySelectionDevice)
  765. zwp_primary_selection_device_v1_destroy(_glfw.wl.primarySelectionDevice);
  766. if (_glfw.wl.primarySelectionDeviceManager)
  767. zwp_primary_selection_device_manager_v1_destroy(_glfw.wl.primarySelectionDeviceManager);
  768. if (_glfw.wl.xdg_activation_v1)
  769. xdg_activation_v1_destroy(_glfw.wl.xdg_activation_v1);
  770. if (_glfw.wl.wp_single_pixel_buffer_manager_v1)
  771. wp_single_pixel_buffer_manager_v1_destroy(_glfw.wl.wp_single_pixel_buffer_manager_v1);
  772. if (_glfw.wl.wp_cursor_shape_manager_v1)
  773. wp_cursor_shape_manager_v1_destroy(_glfw.wl.wp_cursor_shape_manager_v1);
  774. if (_glfw.wl.wp_viewporter)
  775. wp_viewporter_destroy(_glfw.wl.wp_viewporter);
  776. if (_glfw.wl.wp_fractional_scale_manager_v1)
  777. wp_fractional_scale_manager_v1_destroy(_glfw.wl.wp_fractional_scale_manager_v1);
  778. if (_glfw.wl.org_kde_kwin_blur_manager)
  779. org_kde_kwin_blur_manager_destroy(_glfw.wl.org_kde_kwin_blur_manager);
  780. if (_glfw.wl.zwlr_layer_shell_v1)
  781. zwlr_layer_shell_v1_destroy(_glfw.wl.zwlr_layer_shell_v1);
  782. if (_glfw.wl.registry)
  783. wl_registry_destroy(_glfw.wl.registry);
  784. if (_glfw.wl.display)
  785. {
  786. wl_display_flush(_glfw.wl.display);
  787. wl_display_disconnect(_glfw.wl.display);
  788. }
  789. finalizePollData(&_glfw.wl.eventLoopData);
  790. }
  791. #define GLFW_LOOP_BACKEND wl
  792. #include "main_loop.h"
  793. const char* _glfwPlatformGetVersionString(void)
  794. {
  795. (void)keep_going;
  796. return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa"
  797. #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
  798. " clock_gettime"
  799. #else
  800. " gettimeofday"
  801. #endif
  802. " evdev"
  803. #if defined(_GLFW_BUILD_DLL)
  804. " shared"
  805. #endif
  806. ;
  807. }