You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1417 lines
42 KiB

  1. #include "wayland.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <poll.h>
  7. #include <fcntl.h>
  8. #include <sys/timerfd.h>
  9. #include <sys/epoll.h>
  10. #include <wayland-client.h>
  11. #include <wayland-cursor.h>
  12. #include <xdg-shell.h>
  13. #include <xkbcommon/xkbcommon-compose.h>
  14. #include <tllist.h>
  15. #include <xdg-output-unstable-v1.h>
  16. #include <xdg-decoration-unstable-v1.h>
  17. #define LOG_MODULE "wayland"
  18. #define LOG_ENABLE_DBG 0
  19. #include "log.h"
  20. #include "config.h"
  21. #include "terminal.h"
  22. #include "input.h"
  23. #include "render.h"
  24. #include "selection.h"
  25. #include "util.h"
  26. #include "xmalloc.h"
  27. static void
  28. csd_instantiate(struct wl_window *win)
  29. {
  30. struct wayland *wayl = win->term->wl;
  31. assert(wayl != NULL);
  32. for (size_t i = 0; i < ALEN(win->csd.surface); i++) {
  33. assert(win->csd.surface[i] == NULL);
  34. assert(win->csd.sub_surface[i] == NULL);
  35. win->csd.surface[i] = wl_compositor_create_surface(wayl->compositor);
  36. struct wl_surface *parent = i < CSD_SURF_MINIMIZE
  37. ? win->surface : win->csd.surface[CSD_SURF_TITLE];
  38. win->csd.sub_surface[i] = wl_subcompositor_get_subsurface(
  39. wayl->sub_compositor, win->csd.surface[i], parent);
  40. wl_subsurface_set_sync(win->csd.sub_surface[i]);
  41. wl_surface_set_user_data(win->csd.surface[i], win);
  42. wl_surface_commit(win->csd.surface[i]);
  43. }
  44. }
  45. static void
  46. csd_destroy(struct wl_window *win)
  47. {
  48. for (size_t i = 0; i < ALEN(win->csd.surface); i++) {
  49. if (win->csd.sub_surface[i] != NULL)
  50. wl_subsurface_destroy(win->csd.sub_surface[i]);
  51. if (win->csd.surface[i] != NULL)
  52. wl_surface_destroy(win->csd.surface[i]);
  53. win->csd.surface[i] = NULL;
  54. win->csd.sub_surface[i] = NULL;
  55. }
  56. }
  57. static void
  58. seat_add_data_device(struct seat *seat)
  59. {
  60. if (seat->wayl->data_device_manager == NULL)
  61. return;
  62. if (seat->data_device != NULL) {
  63. /* TODO: destroy old device + clipboard data? */
  64. return;
  65. }
  66. struct wl_data_device *data_device = wl_data_device_manager_get_data_device(
  67. seat->wayl->data_device_manager, seat->wl_seat);
  68. if (data_device == NULL)
  69. return;
  70. seat->data_device = data_device;
  71. wl_data_device_add_listener(data_device, &data_device_listener, seat);
  72. }
  73. static void
  74. seat_add_primary_selection(struct seat *seat)
  75. {
  76. if (seat->wayl->primary_selection_device_manager == NULL)
  77. return;
  78. if (seat->primary_selection_device != NULL)
  79. return;
  80. struct zwp_primary_selection_device_v1 *primary_selection_device
  81. = zwp_primary_selection_device_manager_v1_get_device(
  82. seat->wayl->primary_selection_device_manager, seat->wl_seat);
  83. if (primary_selection_device == NULL)
  84. return;
  85. seat->primary_selection_device = primary_selection_device;
  86. zwp_primary_selection_device_v1_add_listener(
  87. primary_selection_device, &primary_selection_device_listener, seat);
  88. }
  89. static void
  90. seat_destroy(struct seat *seat)
  91. {
  92. if (seat == NULL)
  93. return;
  94. tll_foreach(seat->kbd.bindings.key, it)
  95. tll_free(it->item.bind.key_codes);
  96. tll_free(seat->kbd.bindings.key);
  97. tll_foreach(seat->kbd.bindings.search, it)
  98. tll_free(it->item.bind.key_codes);
  99. tll_free(seat->kbd.bindings.search);
  100. tll_free(seat->mouse.bindings);
  101. if (seat->kbd.xkb_compose_state != NULL)
  102. xkb_compose_state_unref(seat->kbd.xkb_compose_state);
  103. if (seat->kbd.xkb_compose_table != NULL)
  104. xkb_compose_table_unref(seat->kbd.xkb_compose_table);
  105. if (seat->kbd.xkb_keymap != NULL)
  106. xkb_keymap_unref(seat->kbd.xkb_keymap);
  107. if (seat->kbd.xkb_state != NULL)
  108. xkb_state_unref(seat->kbd.xkb_state);
  109. if (seat->kbd.xkb != NULL)
  110. xkb_context_unref(seat->kbd.xkb);
  111. if (seat->kbd.repeat.fd >= 0)
  112. fdm_del(seat->wayl->fdm, seat->kbd.repeat.fd);
  113. if (seat->pointer.theme != NULL)
  114. wl_cursor_theme_destroy(seat->pointer.theme);
  115. if (seat->pointer.surface != NULL)
  116. wl_surface_destroy(seat->pointer.surface);
  117. if (seat->pointer.xcursor_callback != NULL)
  118. wl_callback_destroy(seat->pointer.xcursor_callback);
  119. if (seat->clipboard.data_source != NULL)
  120. wl_data_source_destroy(seat->clipboard.data_source);
  121. if (seat->clipboard.data_offer != NULL)
  122. wl_data_offer_destroy(seat->clipboard.data_offer);
  123. if (seat->primary.data_source != NULL)
  124. zwp_primary_selection_source_v1_destroy(seat->primary.data_source);
  125. if (seat->primary.data_offer != NULL)
  126. zwp_primary_selection_offer_v1_destroy(seat->primary.data_offer);
  127. if (seat->primary_selection_device != NULL)
  128. zwp_primary_selection_device_v1_destroy(seat->primary_selection_device);
  129. if (seat->data_device != NULL)
  130. wl_data_device_destroy(seat->data_device);
  131. if (seat->wl_keyboard != NULL)
  132. wl_keyboard_destroy(seat->wl_keyboard);
  133. if (seat->wl_pointer != NULL)
  134. wl_pointer_destroy(seat->wl_pointer);
  135. if (seat->wl_seat != NULL)
  136. wl_seat_destroy(seat->wl_seat);
  137. free(seat->clipboard.text);
  138. free(seat->primary.text);
  139. free(seat->name);
  140. }
  141. static void
  142. shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
  143. {
  144. struct wayland *wayl = data;
  145. if (format == WL_SHM_FORMAT_ARGB8888)
  146. wayl->have_argb8888 = true;
  147. }
  148. static const struct wl_shm_listener shm_listener = {
  149. .format = &shm_format,
  150. };
  151. static void
  152. xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
  153. {
  154. LOG_DBG("wm base ping");
  155. xdg_wm_base_pong(shell, serial);
  156. }
  157. static const struct xdg_wm_base_listener xdg_wm_base_listener = {
  158. .ping = &xdg_wm_base_ping,
  159. };
  160. static void
  161. seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
  162. enum wl_seat_capability caps)
  163. {
  164. struct seat *seat = data;
  165. assert(seat->wl_seat == wl_seat);
  166. LOG_DBG("%s: keyboard=%s, pointer=%s", seat->name,
  167. (caps & WL_SEAT_CAPABILITY_KEYBOARD) ? "yes" : "no",
  168. (caps & WL_SEAT_CAPABILITY_POINTER) ? "yes" : "no");
  169. if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
  170. if (seat->wl_keyboard == NULL) {
  171. seat->wl_keyboard = wl_seat_get_keyboard(wl_seat);
  172. wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, seat);
  173. }
  174. } else {
  175. if (seat->wl_keyboard != NULL) {
  176. wl_keyboard_release(seat->wl_keyboard);
  177. seat->wl_keyboard = NULL;
  178. }
  179. }
  180. if (caps & WL_SEAT_CAPABILITY_POINTER) {
  181. if (seat->wl_pointer == NULL) {
  182. assert(seat->pointer.surface == NULL);
  183. seat->pointer.surface = wl_compositor_create_surface(seat->wayl->compositor);
  184. if (seat->pointer.surface == NULL) {
  185. LOG_ERR("%s: failed to create pointer surface", seat->name);
  186. return;
  187. }
  188. seat->wl_pointer = wl_seat_get_pointer(wl_seat);
  189. wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
  190. }
  191. } else {
  192. if (seat->wl_pointer != NULL) {
  193. wl_pointer_release(seat->wl_pointer);
  194. wl_surface_destroy(seat->pointer.surface);
  195. if (seat->pointer.theme != NULL)
  196. wl_cursor_theme_destroy(seat->pointer.theme);
  197. seat->wl_pointer = NULL;
  198. seat->pointer.surface = NULL;
  199. seat->pointer.theme = NULL;
  200. seat->pointer.cursor = NULL;
  201. }
  202. }
  203. }
  204. static void
  205. seat_handle_name(void *data, struct wl_seat *wl_seat, const char *name)
  206. {
  207. struct seat *seat = data;
  208. free(seat->name);
  209. seat->name = xstrdup(name);
  210. }
  211. static const struct wl_seat_listener seat_listener = {
  212. .capabilities = seat_handle_capabilities,
  213. .name = seat_handle_name,
  214. };
  215. static void
  216. update_term_for_output_change(struct terminal *term)
  217. {
  218. if (tll_length(term->window->on_outputs) == 0)
  219. return;
  220. render_resize(term, term->width / term->scale, term->height / term->scale);
  221. term_font_dpi_changed(term);
  222. term_font_subpixel_changed(term);
  223. }
  224. static void
  225. update_terms_on_monitor(struct monitor *mon)
  226. {
  227. struct wayland *wayl = mon->wayl;
  228. tll_foreach(wayl->terms, it) {
  229. struct terminal *term = it->item;
  230. tll_foreach(term->window->on_outputs, it2) {
  231. if (it2->item == mon) {
  232. update_term_for_output_change(term);
  233. break;
  234. }
  235. }
  236. }
  237. }
  238. static void
  239. output_update_ppi(struct monitor *mon)
  240. {
  241. if (mon->dim.mm.width == 0 || mon->dim.mm.height == 0)
  242. return;
  243. int x_inches = mon->dim.mm.width * 0.03937008;
  244. int y_inches = mon->dim.mm.height * 0.03937008;
  245. mon->ppi.real.x = mon->dim.px_real.width / x_inches;
  246. mon->ppi.real.y = mon->dim.px_real.height / y_inches;
  247. mon->ppi.scaled.x = mon->dim.px_scaled.width / x_inches;
  248. mon->ppi.scaled.y = mon->dim.px_scaled.height / y_inches;
  249. float px_diag = sqrt(
  250. pow(mon->dim.px_scaled.width, 2) +
  251. pow(mon->dim.px_scaled.height, 2));
  252. mon->dpi = px_diag / mon->inch * mon->scale;
  253. }
  254. static void
  255. output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y,
  256. int32_t physical_width, int32_t physical_height,
  257. int32_t subpixel, const char *make, const char *model,
  258. int32_t transform)
  259. {
  260. struct monitor *mon = data;
  261. mon->dim.mm.width = physical_width;
  262. mon->dim.mm.height = physical_height;
  263. mon->inch = sqrt(pow(mon->dim.mm.width, 2) + pow(mon->dim.mm.height, 2)) * 0.03937008;
  264. mon->make = make != NULL ? xstrdup(make) : NULL;
  265. mon->model = model != NULL ? xstrdup(model) : NULL;
  266. mon->subpixel = subpixel;
  267. output_update_ppi(mon);
  268. }
  269. static void
  270. output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
  271. int32_t width, int32_t height, int32_t refresh)
  272. {
  273. if ((flags & WL_OUTPUT_MODE_CURRENT) == 0)
  274. return;
  275. struct monitor *mon = data;
  276. mon->refresh = (float)refresh / 1000;
  277. mon->dim.px_real.width = width;
  278. mon->dim.px_real.height = height;
  279. output_update_ppi(mon);
  280. }
  281. static void
  282. output_done(void *data, struct wl_output *wl_output)
  283. {
  284. struct monitor *mon = data;
  285. update_terms_on_monitor(mon);
  286. }
  287. static void
  288. output_scale(void *data, struct wl_output *wl_output, int32_t factor)
  289. {
  290. struct monitor *mon = data;
  291. mon->scale = factor;
  292. output_update_ppi(mon);
  293. }
  294. static const struct wl_output_listener output_listener = {
  295. .geometry = &output_geometry,
  296. .mode = &output_mode,
  297. .done = &output_done,
  298. .scale = &output_scale,
  299. };
  300. static void
  301. xdg_output_handle_logical_position(
  302. void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y)
  303. {
  304. struct monitor *mon = data;
  305. mon->x = x;
  306. mon->y = y;
  307. }
  308. static void
  309. xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
  310. int32_t width, int32_t height)
  311. {
  312. struct monitor *mon = data;
  313. mon->dim.px_scaled.width = width;
  314. mon->dim.px_scaled.height = height;
  315. output_update_ppi(mon);
  316. }
  317. static void
  318. xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
  319. {
  320. }
  321. static void
  322. xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
  323. const char *name)
  324. {
  325. struct monitor *mon = data;
  326. mon->name = name != NULL ? xstrdup(name) : NULL;
  327. }
  328. static void
  329. xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output,
  330. const char *description)
  331. {
  332. struct monitor *mon = data;
  333. mon->description = description != NULL ? xstrdup(description) : NULL;
  334. }
  335. static const struct zxdg_output_v1_listener xdg_output_listener = {
  336. .logical_position = xdg_output_handle_logical_position,
  337. .logical_size = xdg_output_handle_logical_size,
  338. .done = xdg_output_handle_done,
  339. .name = xdg_output_handle_name,
  340. .description = xdg_output_handle_description,
  341. };
  342. static void
  343. clock_id(void *data, struct wp_presentation *wp_presentation, uint32_t clk_id)
  344. {
  345. struct wayland *wayl = data;
  346. wayl->presentation_clock_id = clk_id;
  347. LOG_DBG("presentation clock ID: %u", clk_id);
  348. }
  349. static const struct wp_presentation_listener presentation_listener = {
  350. .clock_id = &clock_id,
  351. };
  352. static bool
  353. verify_iface_version(const char *iface, uint32_t version, uint32_t wanted)
  354. {
  355. if (version >= wanted)
  356. return true;
  357. LOG_ERR("%s: need interface version %u, but compositor only implements %u",
  358. iface, wanted, version);
  359. return false;
  360. }
  361. static void
  362. surface_enter(void *data, struct wl_surface *wl_surface,
  363. struct wl_output *wl_output)
  364. {
  365. struct wl_window *win = data;
  366. struct terminal *term = win->term;
  367. tll_foreach(term->wl->monitors, it) {
  368. if (it->item.output == wl_output) {
  369. LOG_DBG("mapped on %s", it->item.name);
  370. tll_push_back(term->window->on_outputs, &it->item);
  371. update_term_for_output_change(term);
  372. return;
  373. }
  374. }
  375. LOG_ERR("mapped on unknown output");
  376. }
  377. static void
  378. surface_leave(void *data, struct wl_surface *wl_surface,
  379. struct wl_output *wl_output)
  380. {
  381. struct wl_window *win = data;
  382. struct terminal *term = win->term;
  383. tll_foreach(term->window->on_outputs, it) {
  384. if (it->item->output != wl_output)
  385. continue;
  386. LOG_DBG("unmapped from %s", it->item->name);
  387. tll_remove(term->window->on_outputs, it);
  388. update_term_for_output_change(term);
  389. return;
  390. }
  391. LOG_ERR("unmapped from unknown output");
  392. }
  393. static const struct wl_surface_listener surface_listener = {
  394. .enter = &surface_enter,
  395. .leave = &surface_leave,
  396. };
  397. static void
  398. xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
  399. int32_t width, int32_t height, struct wl_array *states)
  400. {
  401. bool is_activated = false;
  402. bool is_fullscreen = false;
  403. bool is_maximized = false;
  404. #if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
  405. char state_str[2048];
  406. int state_chars = 0;
  407. static const char *const strings[] = {
  408. [XDG_TOPLEVEL_STATE_MAXIMIZED] = "maximized",
  409. [XDG_TOPLEVEL_STATE_FULLSCREEN] = "fullscreen",
  410. [XDG_TOPLEVEL_STATE_RESIZING] = "resizing",
  411. [XDG_TOPLEVEL_STATE_ACTIVATED] = "activated",
  412. [XDG_TOPLEVEL_STATE_TILED_LEFT] = "tiled:left",
  413. [XDG_TOPLEVEL_STATE_TILED_RIGHT] = "tiled:right",
  414. [XDG_TOPLEVEL_STATE_TILED_TOP] = "tiled:top",
  415. [XDG_TOPLEVEL_STATE_TILED_BOTTOM] = "tiled:bottom",
  416. };
  417. #endif
  418. enum xdg_toplevel_state *state;
  419. wl_array_for_each(state, states) {
  420. switch (*state) {
  421. case XDG_TOPLEVEL_STATE_ACTIVATED: is_activated = true; break;
  422. case XDG_TOPLEVEL_STATE_FULLSCREEN: is_fullscreen = true; break;
  423. case XDG_TOPLEVEL_STATE_MAXIMIZED: is_maximized = true; break;
  424. case XDG_TOPLEVEL_STATE_RESIZING:
  425. case XDG_TOPLEVEL_STATE_TILED_LEFT:
  426. case XDG_TOPLEVEL_STATE_TILED_RIGHT:
  427. case XDG_TOPLEVEL_STATE_TILED_TOP:
  428. case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
  429. /* Ignored */
  430. break;
  431. }
  432. #if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
  433. if (*state >= XDG_TOPLEVEL_STATE_MAXIMIZED &&
  434. *state <= XDG_TOPLEVEL_STATE_TILED_BOTTOM)
  435. {
  436. state_chars += snprintf(
  437. &state_str[state_chars], sizeof(state_str) - state_chars,
  438. "%s, ", strings[*state]);
  439. }
  440. #endif
  441. }
  442. #if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
  443. if (state_chars > 2)
  444. state_str[state_chars - 2] = '\0';
  445. else
  446. state_str[0] = '\0';
  447. LOG_DBG("xdg-toplevel: configure: size=%dx%d, states=%s",
  448. width, height, state_str);
  449. #endif
  450. /*
  451. * Changes done here are ignored until the configure event has
  452. * been ack:ed in xdg_surface_configure().
  453. *
  454. * So, just store the config data and apply it later, in
  455. * xdg_surface_configure() after we've ack:ed the event.
  456. */
  457. struct wl_window *win = data;
  458. if (!is_fullscreen && win->use_csd == CSD_YES && width > 0 && height > 0) {
  459. /*
  460. * We include the CSD title bar in our window geometry. Thus,
  461. * the height we call render_resize() with must be adjusted,
  462. * since it expects the size to refer to the main grid only.
  463. */
  464. height -= win->term->conf->csd.title_height;
  465. }
  466. win->configure.is_activated = is_activated;
  467. win->configure.is_fullscreen = is_fullscreen;
  468. win->configure.is_maximized = is_maximized;
  469. win->configure.width = width;
  470. win->configure.height = height;
  471. }
  472. static void
  473. xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
  474. {
  475. struct wl_window *win = data;
  476. struct terminal *term = win->term;
  477. LOG_DBG("xdg-toplevel: close");
  478. term_shutdown(term);
  479. }
  480. static const struct xdg_toplevel_listener xdg_toplevel_listener = {
  481. .configure = &xdg_toplevel_configure,
  482. .close = &xdg_toplevel_close,
  483. };
  484. static void
  485. xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
  486. uint32_t serial)
  487. {
  488. LOG_DBG("xdg-surface: configure");
  489. struct wl_window *win = data;
  490. struct terminal *term = win->term;
  491. bool wasnt_configured = !win->is_configured;
  492. win->is_configured = true;
  493. win->is_maximized = win->configure.is_maximized;
  494. if (win->is_fullscreen != win->configure.is_fullscreen && win->use_csd == CSD_YES) {
  495. if (win->configure.is_fullscreen)
  496. csd_destroy(win);
  497. else
  498. csd_instantiate(win);
  499. }
  500. win->is_fullscreen = win->configure.is_fullscreen;
  501. xdg_surface_ack_configure(xdg_surface, serial);
  502. /* TODO: check with GNOME and tiling - presumably that didn't work
  503. * unless we presented a *new* buffer, hence we used to do a force
  504. * resize here */
  505. bool resized = render_resize(term, win->configure.width, win->configure.height);
  506. if (win->configure.is_activated)
  507. term_visual_focus_in(term);
  508. else
  509. term_visual_focus_out(term);
  510. /* TODO: remove - shouldn't be necessary with render_resize_force() */
  511. if (!resized) {
  512. /*
  513. * If we didn't resize, we won't be committing a new surface
  514. * anytime soon. Some compositors require a commit in
  515. * combination with an ack - make them happy.
  516. */
  517. wl_surface_commit(win->surface);
  518. }
  519. if (wasnt_configured)
  520. term_window_configured(term);
  521. }
  522. static const struct xdg_surface_listener xdg_surface_listener = {
  523. .configure = &xdg_surface_configure,
  524. };
  525. static void
  526. xdg_toplevel_decoration_configure(void *data,
  527. struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1,
  528. uint32_t mode)
  529. {
  530. struct wl_window *win = data;
  531. assert(win->term->conf->csd.preferred != CONF_CSD_PREFER_NONE);
  532. switch (mode) {
  533. case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:
  534. LOG_INFO("using CSD decorations");
  535. win->use_csd = CSD_YES;
  536. csd_instantiate(win);
  537. break;
  538. case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:
  539. LOG_INFO("using SSD decorations");
  540. win->use_csd = CSD_NO;
  541. csd_destroy(win);
  542. break;
  543. default:
  544. LOG_ERR("unimplemented: unknown XDG toplevel decoration mode: %u", mode);
  545. break;
  546. }
  547. if (win->is_configured && win->use_csd == CSD_YES) {
  548. struct terminal *term = win->term;
  549. int scale = term->scale;
  550. int width = term->width / scale;
  551. int height = term->height / scale;
  552. /* Take CSD title bar into account */
  553. height -= term->conf->csd.title_height;
  554. render_resize_force(term, width, height);
  555. }
  556. }
  557. static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = {
  558. .configure = &xdg_toplevel_decoration_configure,
  559. };
  560. static bool
  561. fdm_repeat(struct fdm *fdm, int fd, int events, void *data)
  562. {
  563. if (events & EPOLLHUP)
  564. return false;
  565. struct seat *seat = data;
  566. uint64_t expiration_count;
  567. ssize_t ret = read(
  568. seat->kbd.repeat.fd, &expiration_count, sizeof(expiration_count));
  569. if (ret < 0) {
  570. if (errno == EAGAIN)
  571. return true;
  572. LOG_ERRNO("failed to read repeat key from repeat timer fd");
  573. return false;
  574. }
  575. seat->kbd.repeat.dont_re_repeat = true;
  576. for (size_t i = 0; i < expiration_count; i++)
  577. input_repeat(seat, seat->kbd.repeat.key);
  578. seat->kbd.repeat.dont_re_repeat = false;
  579. return true;
  580. }
  581. static void
  582. handle_global(void *data, struct wl_registry *registry,
  583. uint32_t name, const char *interface, uint32_t version)
  584. {
  585. LOG_DBG("global: 0x%08x, interface=%s, version=%u", name, interface, version);
  586. struct wayland *wayl = data;
  587. if (strcmp(interface, wl_compositor_interface.name) == 0) {
  588. const uint32_t required = 4;
  589. if (!verify_iface_version(interface, version, required))
  590. return;
  591. wayl->compositor = wl_registry_bind(
  592. wayl->registry, name, &wl_compositor_interface, required);
  593. }
  594. else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
  595. const uint32_t required = 1;
  596. if (!verify_iface_version(interface, version, required))
  597. return;
  598. wayl->sub_compositor = wl_registry_bind(
  599. wayl->registry, name, &wl_subcompositor_interface, required);
  600. }
  601. else if (strcmp(interface, wl_shm_interface.name) == 0) {
  602. const uint32_t required = 1;
  603. if (!verify_iface_version(interface, version, required))
  604. return;
  605. wayl->shm = wl_registry_bind(
  606. wayl->registry, name, &wl_shm_interface, required);
  607. wl_shm_add_listener(wayl->shm, &shm_listener, wayl);
  608. }
  609. else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
  610. const uint32_t required = 1;
  611. if (!verify_iface_version(interface, version, required))
  612. return;
  613. wayl->shell = wl_registry_bind(
  614. wayl->registry, name, &xdg_wm_base_interface, required);
  615. xdg_wm_base_add_listener(wayl->shell, &xdg_wm_base_listener, wayl);
  616. }
  617. else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
  618. const uint32_t required = 1;
  619. if (!verify_iface_version(interface, version, required))
  620. return;
  621. wayl->xdg_decoration_manager = wl_registry_bind(
  622. wayl->registry, name, &zxdg_decoration_manager_v1_interface, required);
  623. }
  624. else if (strcmp(interface, wl_seat_interface.name) == 0) {
  625. const uint32_t required = 5;
  626. if (!verify_iface_version(interface, version, required))
  627. return;
  628. int repeat_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
  629. if (repeat_fd == -1) {
  630. LOG_ERRNO("failed to create keyboard repeat timer FD");
  631. return;
  632. }
  633. struct wl_seat *wl_seat = wl_registry_bind(
  634. wayl->registry, name, &wl_seat_interface, required);
  635. tll_push_back(wayl->seats, ((struct seat){
  636. .wayl = wayl,
  637. .wl_seat = wl_seat,
  638. .wl_name = name,
  639. .kbd = {
  640. .repeat = {
  641. .fd = repeat_fd,
  642. },
  643. }}));
  644. struct seat *seat = &tll_back(wayl->seats);
  645. if (!fdm_add(wayl->fdm, repeat_fd, EPOLLIN, &fdm_repeat, seat)) {
  646. close(repeat_fd);
  647. seat->kbd.repeat.fd = -1;
  648. seat_destroy(seat);
  649. return;
  650. }
  651. seat_add_data_device(seat);
  652. seat_add_primary_selection(seat);
  653. wl_seat_add_listener(wl_seat, &seat_listener, seat);
  654. }
  655. else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
  656. const uint32_t required = 1;
  657. if (!verify_iface_version(interface, version, required))
  658. return;
  659. wayl->xdg_output_manager = wl_registry_bind(
  660. wayl->registry, name, &zxdg_output_manager_v1_interface,
  661. min(version, 2));
  662. tll_foreach(wayl->monitors, it) {
  663. struct monitor *mon = &it->item;
  664. mon->xdg = zxdg_output_manager_v1_get_xdg_output(
  665. wayl->xdg_output_manager, mon->output);
  666. zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon);
  667. }
  668. }
  669. else if (strcmp(interface, wl_output_interface.name) == 0) {
  670. const uint32_t required = 2;
  671. if (!verify_iface_version(interface, version, required))
  672. return;
  673. struct wl_output *output = wl_registry_bind(
  674. wayl->registry, name, &wl_output_interface, required);
  675. tll_push_back(
  676. wayl->monitors,
  677. ((struct monitor){.wayl = wayl, .output = output, .wl_name = name}));
  678. struct monitor *mon = &tll_back(wayl->monitors);
  679. wl_output_add_listener(output, &output_listener, mon);
  680. if (wayl->xdg_output_manager != NULL) {
  681. mon->xdg = zxdg_output_manager_v1_get_xdg_output(
  682. wayl->xdg_output_manager, mon->output);
  683. zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon);
  684. }
  685. }
  686. else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
  687. const uint32_t required = 1;
  688. if (!verify_iface_version(interface, version, required))
  689. return;
  690. wayl->data_device_manager = wl_registry_bind(
  691. wayl->registry, name, &wl_data_device_manager_interface, required);
  692. tll_foreach(wayl->seats, it)
  693. seat_add_data_device(&it->item);
  694. }
  695. else if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
  696. const uint32_t required = 1;
  697. if (!verify_iface_version(interface, version, required))
  698. return;
  699. wayl->primary_selection_device_manager = wl_registry_bind(
  700. wayl->registry, name,
  701. &zwp_primary_selection_device_manager_v1_interface, required);
  702. tll_foreach(wayl->seats, it)
  703. seat_add_primary_selection(&it->item);
  704. }
  705. else if (strcmp(interface, wp_presentation_interface.name) == 0) {
  706. if (wayl->conf->presentation_timings) {
  707. const uint32_t required = 1;
  708. if (!verify_iface_version(interface, version, required))
  709. return;
  710. wayl->presentation = wl_registry_bind(
  711. wayl->registry, name, &wp_presentation_interface, required);
  712. wp_presentation_add_listener(
  713. wayl->presentation, &presentation_listener, wayl);
  714. }
  715. }
  716. }
  717. static void
  718. monitor_destroy(struct monitor *mon)
  719. {
  720. if (mon->xdg != NULL)
  721. zxdg_output_v1_destroy(mon->xdg);
  722. if (mon->output != NULL)
  723. wl_output_destroy(mon->output);
  724. free(mon->make);
  725. free(mon->model);
  726. free(mon->name);
  727. free(mon->description);
  728. }
  729. static void
  730. handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
  731. {
  732. LOG_DBG("global removed: 0x%08x", name);
  733. struct wayland *wayl = data;
  734. /* Check if this is an output */
  735. tll_foreach(wayl->monitors, it) {
  736. struct monitor *mon = &it->item;
  737. if (mon->wl_name != name)
  738. continue;
  739. LOG_INFO("monitor unplugged: %s", mon->name);
  740. /*
  741. * Update all terminals that are mapped here. On Sway 1.4,
  742. * surfaces are *not* unmapped before the output is removed
  743. */
  744. tll_foreach(wayl->terms, t)
  745. surface_leave(t->item->window, NULL /* wl_surface - unused */, mon->output);
  746. monitor_destroy(mon);
  747. tll_remove(wayl->monitors, it);
  748. return;
  749. }
  750. /* A seat? */
  751. tll_foreach(wayl->seats, it) {
  752. struct seat *seat = &it->item;
  753. if (seat->wl_name != name)
  754. continue;
  755. LOG_INFO("seat destroyed: %s", seat->name);
  756. if (seat->kbd_focus != NULL) {
  757. LOG_WARN("compositor destroyed seat '%s' "
  758. "without sending a keyboard leave event",
  759. seat->name);
  760. if (seat->wl_keyboard != NULL)
  761. keyboard_listener.leave(
  762. seat, seat->wl_keyboard, -1, seat->kbd_focus->window->surface);
  763. }
  764. if (seat->mouse_focus != NULL) {
  765. LOG_WARN("compositor destroyed seat '%s' "
  766. "without sending a pointer leave event",
  767. seat->name);
  768. if (seat->wl_pointer != NULL)
  769. pointer_listener.leave(
  770. seat, seat->wl_pointer, -1, seat->mouse_focus->window->surface);
  771. }
  772. seat_destroy(seat);
  773. tll_remove(wayl->seats, it);
  774. return;
  775. }
  776. LOG_WARN("unknown global removed: 0x%08x", name);
  777. }
  778. static const struct wl_registry_listener registry_listener = {
  779. .global = &handle_global,
  780. .global_remove = &handle_global_remove,
  781. };
  782. static void
  783. fdm_hook(struct fdm *fdm, void *data)
  784. {
  785. struct wayland *wayl = data;
  786. wayl_flush(wayl);
  787. }
  788. static bool
  789. fdm_wayl(struct fdm *fdm, int fd, int events, void *data)
  790. {
  791. struct wayland *wayl = data;
  792. int event_count = 0;
  793. if (events & EPOLLIN) {
  794. if (wl_display_read_events(wayl->display) < 0) {
  795. LOG_ERRNO("failed to read events from the Wayland socket");
  796. return false;
  797. }
  798. while (wl_display_prepare_read(wayl->display) != 0)
  799. wl_display_dispatch_pending(wayl->display);
  800. }
  801. if (events & EPOLLHUP) {
  802. LOG_WARN("disconnected from Wayland");
  803. wl_display_cancel_read(wayl->display);
  804. return false;
  805. }
  806. return event_count != -1;
  807. }
  808. struct wayland *
  809. wayl_init(const struct config *conf, struct fdm *fdm)
  810. {
  811. struct wayland *wayl = calloc(1, sizeof(*wayl));
  812. if (unlikely(wayl == NULL)) {
  813. LOG_ERRNO("calloc() failed");
  814. return NULL;
  815. }
  816. wayl->conf = conf;
  817. wayl->fdm = fdm;
  818. wayl->fd = -1;
  819. if (!fdm_hook_add(fdm, &fdm_hook, wayl, FDM_HOOK_PRIORITY_LOW)) {
  820. LOG_ERR("failed to add FDM hook");
  821. goto out;
  822. }
  823. wayl->display = wl_display_connect(NULL);
  824. if (wayl->display == NULL) {
  825. LOG_ERR("failed to connect to wayland; no compositor running?");
  826. goto out;
  827. }
  828. wayl->registry = wl_display_get_registry(wayl->display);
  829. if (wayl->registry == NULL) {
  830. LOG_ERR("failed to get wayland registry");
  831. goto out;
  832. }
  833. wl_registry_add_listener(wayl->registry, &registry_listener, wayl);
  834. wl_display_roundtrip(wayl->display);
  835. if (wayl->compositor == NULL) {
  836. LOG_ERR("no compositor");
  837. goto out;
  838. }
  839. if (wayl->sub_compositor == NULL) {
  840. LOG_ERR("no sub compositor");
  841. goto out;
  842. }
  843. if (wayl->shm == NULL) {
  844. LOG_ERR("no shared memory buffers interface");
  845. goto out;
  846. }
  847. if (wayl->shell == NULL) {
  848. LOG_ERR("no XDG shell interface");
  849. goto out;
  850. }
  851. if (wayl->data_device_manager == NULL) {
  852. LOG_ERR("no clipboard available "
  853. "(wl_data_device_manager not implemented by server)");
  854. goto out;
  855. }
  856. if (wayl->primary_selection_device_manager == NULL)
  857. LOG_WARN("no primary selection available");
  858. if (conf->presentation_timings && wayl->presentation == NULL) {
  859. LOG_ERR("presentation time interface not implemented by compositor");
  860. goto out;
  861. }
  862. /* Trigger listeners registered when handling globals */
  863. wl_display_roundtrip(wayl->display);
  864. if (!wayl->have_argb8888) {
  865. LOG_ERR("compositor does not support ARGB surfaces");
  866. goto out;
  867. }
  868. tll_foreach(wayl->monitors, it) {
  869. LOG_INFO(
  870. "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical), DPI=%.2f",
  871. it->item.name, it->item.dim.px_real.width, it->item.dim.px_real.height,
  872. it->item.x, it->item.y, (int)round(it->item.refresh),
  873. it->item.model != NULL ? it->item.model : it->item.description,
  874. it->item.inch, it->item.scale,
  875. it->item.ppi.real.x, it->item.ppi.real.y,
  876. it->item.ppi.scaled.x, it->item.ppi.scaled.y,
  877. it->item.dpi);
  878. }
  879. wayl->fd = wl_display_get_fd(wayl->display);
  880. if (fcntl(wayl->fd, F_SETFL, fcntl(wayl->fd, F_GETFL) | O_NONBLOCK) < 0) {
  881. LOG_ERRNO("failed to make Wayland socket non-blocking");
  882. goto out;
  883. }
  884. if (!fdm_add(fdm, wayl->fd, EPOLLIN, &fdm_wayl, wayl))
  885. goto out;
  886. if (wl_display_prepare_read(wayl->display) != 0) {
  887. LOG_ERRNO("failed to prepare for reading wayland events");
  888. goto out;
  889. }
  890. return wayl;
  891. out:
  892. if (wayl != NULL)
  893. wayl_destroy(wayl);
  894. return NULL;
  895. }
  896. void
  897. wayl_destroy(struct wayland *wayl)
  898. {
  899. if (wayl == NULL)
  900. return;
  901. tll_foreach(wayl->terms, it) {
  902. static bool have_warned = false;
  903. if (!have_warned) {
  904. have_warned = true;
  905. LOG_WARN("there are terminals still running");
  906. term_destroy(it->item);
  907. }
  908. }
  909. tll_free(wayl->terms);
  910. fdm_hook_del(wayl->fdm, &fdm_hook, FDM_HOOK_PRIORITY_LOW);
  911. tll_foreach(wayl->monitors, it)
  912. monitor_destroy(&it->item);
  913. tll_free(wayl->monitors);
  914. tll_foreach(wayl->seats, it)
  915. seat_destroy(&it->item);
  916. tll_free(wayl->seats);
  917. if (wayl->xdg_output_manager != NULL)
  918. zxdg_output_manager_v1_destroy(wayl->xdg_output_manager);
  919. if (wayl->shell != NULL)
  920. xdg_wm_base_destroy(wayl->shell);
  921. if (wayl->xdg_decoration_manager != NULL)
  922. zxdg_decoration_manager_v1_destroy(wayl->xdg_decoration_manager);
  923. if (wayl->presentation != NULL)
  924. wp_presentation_destroy(wayl->presentation);
  925. if (wayl->data_device_manager != NULL)
  926. wl_data_device_manager_destroy(wayl->data_device_manager);
  927. if (wayl->primary_selection_device_manager != NULL)
  928. zwp_primary_selection_device_manager_v1_destroy(wayl->primary_selection_device_manager);
  929. if (wayl->shm != NULL)
  930. wl_shm_destroy(wayl->shm);
  931. if (wayl->sub_compositor != NULL)
  932. wl_subcompositor_destroy(wayl->sub_compositor);
  933. if (wayl->compositor != NULL)
  934. wl_compositor_destroy(wayl->compositor);
  935. if (wayl->registry != NULL)
  936. wl_registry_destroy(wayl->registry);
  937. if (wayl->fd != -1)
  938. fdm_del_no_close(wayl->fdm, wayl->fd);
  939. if (wayl->display != NULL)
  940. wl_display_disconnect(wayl->display);
  941. free(wayl);
  942. }
  943. struct wl_window *
  944. wayl_win_init(struct terminal *term)
  945. {
  946. struct wayland *wayl = term->wl;
  947. const struct config *conf = term->conf;
  948. struct wl_window *win = calloc(1, sizeof(*win));
  949. if (unlikely(win == NULL)) {
  950. LOG_ERRNO("calloc() failed");
  951. return NULL;
  952. }
  953. win->term = term;
  954. win->use_csd = CSD_UNKNOWN;
  955. win->csd.move_timeout_fd = -1;
  956. win->surface = wl_compositor_create_surface(wayl->compositor);
  957. if (win->surface == NULL) {
  958. LOG_ERR("failed to create wayland surface");
  959. goto out;
  960. }
  961. if (term->colors.alpha == 0xffff) {
  962. struct wl_region *region = wl_compositor_create_region(
  963. term->wl->compositor);
  964. if (region != NULL) {
  965. wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
  966. wl_surface_set_opaque_region(win->surface, region);
  967. wl_region_destroy(region);
  968. }
  969. }
  970. wl_surface_add_listener(win->surface, &surface_listener, win);
  971. win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface);
  972. xdg_surface_add_listener(win->xdg_surface, &xdg_surface_listener, win);
  973. win->xdg_toplevel = xdg_surface_get_toplevel(win->xdg_surface);
  974. xdg_toplevel_add_listener(win->xdg_toplevel, &xdg_toplevel_listener, win);
  975. xdg_toplevel_set_app_id(win->xdg_toplevel, conf->app_id);
  976. if (conf->csd.preferred == CONF_CSD_PREFER_NONE) {
  977. /* User specifically do *not* want decorations */
  978. win->use_csd = CSD_NO;
  979. LOG_INFO("window decorations disabled by user");
  980. } else if (wayl->xdg_decoration_manager != NULL) {
  981. win->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
  982. wayl->xdg_decoration_manager, win->xdg_toplevel);
  983. LOG_INFO("requesting %s decorations",
  984. conf->csd.preferred == CONF_CSD_PREFER_SERVER ? "SSD" : "CSD");
  985. zxdg_toplevel_decoration_v1_set_mode(
  986. win->xdg_toplevel_decoration,
  987. (conf->csd.preferred == CONF_CSD_PREFER_SERVER
  988. ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
  989. : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE));
  990. zxdg_toplevel_decoration_v1_add_listener(
  991. win->xdg_toplevel_decoration, &xdg_toplevel_decoration_listener, win);
  992. } else {
  993. /* No decoration manager - thus we *must* draw our own decorations */
  994. win->use_csd = CSD_YES;
  995. csd_instantiate(win);
  996. LOG_WARN("no decoration manager available - using CSDs unconditionally");
  997. }
  998. wl_surface_commit(win->surface);
  999. if (conf->tweak.render_timer_osd) {
  1000. win->render_timer_surface = wl_compositor_create_surface(wayl->compositor);
  1001. if (win->render_timer_surface == NULL) {
  1002. LOG_ERR("failed to create render timer surface");
  1003. goto out;
  1004. }
  1005. win->render_timer_sub_surface = wl_subcompositor_get_subsurface(
  1006. wayl->sub_compositor, win->render_timer_surface, win->surface);
  1007. wl_subsurface_set_sync(win->render_timer_sub_surface);
  1008. wl_surface_set_user_data(win->render_timer_surface, win);
  1009. wl_surface_commit(win->render_timer_surface);
  1010. }
  1011. return win;
  1012. out:
  1013. if (win != NULL)
  1014. wayl_win_destroy(win);
  1015. return NULL;
  1016. }
  1017. void
  1018. wayl_win_destroy(struct wl_window *win)
  1019. {
  1020. if (win == NULL)
  1021. return;
  1022. if (win->csd.move_timeout_fd != -1)
  1023. close(win->csd.move_timeout_fd);
  1024. /*
  1025. * First, unmap all surfaces to trigger things like
  1026. * keyboard_leave() and wl_pointer_leave().
  1027. *
  1028. * This ensures we remove all references to *this* window from the
  1029. * global wayland struct (since it no longer has neither keyboard
  1030. * nor mouse focus).
  1031. */
  1032. if (win->render_timer_surface != NULL) {
  1033. wl_surface_attach(win->render_timer_surface, NULL, 0, 0);
  1034. wl_surface_commit(win->render_timer_surface);
  1035. }
  1036. if (win->scrollback_indicator_surface != NULL) {
  1037. wl_surface_attach(win->scrollback_indicator_surface, NULL, 0, 0);
  1038. wl_surface_commit(win->scrollback_indicator_surface);
  1039. }
  1040. /* Scrollback search */
  1041. if (win->search_surface != NULL) {
  1042. wl_surface_attach(win->search_surface, NULL, 0, 0);
  1043. wl_surface_commit(win->search_surface);
  1044. }
  1045. /* CSD */
  1046. for (size_t i = 0; i < ALEN(win->csd.surface); i++) {
  1047. if (win->csd.surface[i] != NULL) {
  1048. wl_surface_attach(win->csd.surface[i], NULL, 0, 0);
  1049. wl_surface_commit(win->csd.surface[i]);
  1050. }
  1051. }
  1052. wayl_roundtrip(win->term->wl);
  1053. /* Main window */
  1054. wl_surface_attach(win->surface, NULL, 0, 0);
  1055. wl_surface_commit(win->surface);
  1056. wayl_roundtrip(win->term->wl);
  1057. tll_free(win->on_outputs);
  1058. csd_destroy(win);
  1059. if (win->render_timer_sub_surface != NULL)
  1060. wl_subsurface_destroy(win->render_timer_sub_surface);
  1061. if (win->render_timer_surface != NULL)
  1062. wl_surface_destroy(win->render_timer_surface);
  1063. if (win->scrollback_indicator_sub_surface != NULL)
  1064. wl_subsurface_destroy(win->scrollback_indicator_sub_surface);
  1065. if (win->scrollback_indicator_surface != NULL)
  1066. wl_surface_destroy(win->scrollback_indicator_surface);
  1067. if (win->search_sub_surface != NULL)
  1068. wl_subsurface_destroy(win->search_sub_surface);
  1069. if (win->search_surface != NULL)
  1070. wl_surface_destroy(win->search_surface);
  1071. if (win->frame_callback != NULL)
  1072. wl_callback_destroy(win->frame_callback);
  1073. if (win->xdg_toplevel_decoration != NULL)
  1074. zxdg_toplevel_decoration_v1_destroy(win->xdg_toplevel_decoration);
  1075. if (win->xdg_toplevel != NULL)
  1076. xdg_toplevel_destroy(win->xdg_toplevel);
  1077. if (win->xdg_surface != NULL)
  1078. xdg_surface_destroy(win->xdg_surface);
  1079. if (win->surface != NULL)
  1080. wl_surface_destroy(win->surface);
  1081. wayl_roundtrip(win->term->wl);
  1082. free(win);
  1083. }
  1084. bool
  1085. wayl_reload_xcursor_theme(struct seat *seat, int new_scale)
  1086. {
  1087. if (seat->pointer.theme != NULL && seat->pointer.scale == new_scale) {
  1088. /* We already have a theme loaded, and the scale hasn't changed */
  1089. return true;
  1090. }
  1091. if (seat->pointer.theme != NULL) {
  1092. assert(seat->pointer.scale != new_scale);
  1093. wl_cursor_theme_destroy(seat->pointer.theme);
  1094. seat->pointer.theme = NULL;
  1095. seat->pointer.cursor = NULL;
  1096. }
  1097. const char *xcursor_theme = getenv("XCURSOR_THEME");
  1098. int xcursor_size = 24;
  1099. {
  1100. const char *env_cursor_size = getenv("XCURSOR_SIZE");
  1101. if (env_cursor_size != NULL) {
  1102. unsigned size;
  1103. if (sscanf(env_cursor_size, "%u", &size) == 1)
  1104. xcursor_size = size;
  1105. }
  1106. }
  1107. LOG_INFO("cursor theme: %s, size: %u, scale: %d",
  1108. xcursor_theme, xcursor_size, new_scale);
  1109. seat->pointer.theme = wl_cursor_theme_load(
  1110. xcursor_theme, xcursor_size * new_scale, seat->wayl->shm);
  1111. if (seat->pointer.theme == NULL) {
  1112. LOG_ERR("failed to load cursor theme");
  1113. return false;
  1114. }
  1115. seat->pointer.scale = new_scale;
  1116. return true;
  1117. }
  1118. void
  1119. wayl_flush(struct wayland *wayl)
  1120. {
  1121. while (true) {
  1122. int r = wl_display_flush(wayl->display);
  1123. if (r >= 0) {
  1124. /* Most likely code path - the flush succeed */
  1125. return;
  1126. }
  1127. if (errno == EINTR) {
  1128. /* Unlikely */
  1129. continue;
  1130. }
  1131. if (errno != EAGAIN) {
  1132. LOG_ERRNO("failed to flush wayland socket");
  1133. return;
  1134. }
  1135. /* Socket buffer is full - need to wait for it to become
  1136. writeable again */
  1137. assert(errno == EAGAIN);
  1138. while (true) {
  1139. struct pollfd fds[] = {{.fd = wayl->fd, .events = POLLOUT}};
  1140. r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1);
  1141. if (r < 0) {
  1142. if (errno == EINTR)
  1143. continue;
  1144. LOG_ERRNO("failed to poll");
  1145. return;
  1146. }
  1147. if (fds[0].revents & POLLHUP)
  1148. return;
  1149. assert(fds[0].revents & POLLOUT);
  1150. break;
  1151. }
  1152. }
  1153. }
  1154. void
  1155. wayl_roundtrip(struct wayland *wayl)
  1156. {
  1157. wl_display_cancel_read(wayl->display);
  1158. wl_display_roundtrip(wayl->display);
  1159. /* I suspect the roundtrip above clears the pending queue, and
  1160. * that prepare_read() will always succeed in the first call. But,
  1161. * better safe than sorry... */
  1162. while (wl_display_prepare_read(wayl->display) != 0)
  1163. wl_display_dispatch_pending(wayl->display);
  1164. wayl_flush(wayl);
  1165. }