1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2011-2020 - Daniel De Matteis
3 *
4 * RetroArch is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with RetroArch.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include <stdint.h>
17 #include <string.h>
18
19 #include <poll.h>
20 #include <unistd.h>
21
22 #include <string/stdstring.h>
23
24 #include "wayland_common.h"
25
26 #include "../input_keymaps.h"
27 #include "../../frontend/frontend_driver.h"
28
keyboard_handle_keymap(void * data,struct wl_keyboard * keyboard,uint32_t format,int fd,uint32_t size)29 static void keyboard_handle_keymap(void* data,
30 struct wl_keyboard* keyboard,
31 uint32_t format,
32 int fd,
33 uint32_t size)
34 {
35 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
36 {
37 close(fd);
38 return;
39 }
40
41 #ifdef HAVE_XKBCOMMON
42 init_xkb(fd, size);
43 #endif
44 close(fd);
45 }
46
keyboard_handle_enter(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface,struct wl_array * keys)47 static void keyboard_handle_enter(void* data,
48 struct wl_keyboard* keyboard,
49 uint32_t serial,
50 struct wl_surface* surface,
51 struct wl_array* keys)
52 {
53 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
54 wl->input.keyboard_focus = true;
55 }
56
keyboard_handle_leave(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface)57 static void keyboard_handle_leave(void *data,
58 struct wl_keyboard *keyboard,
59 uint32_t serial,
60 struct wl_surface *surface)
61 {
62 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
63 wl->input.keyboard_focus = false;
64 }
65
keyboard_handle_key(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)66 static void keyboard_handle_key(void *data,
67 struct wl_keyboard *keyboard,
68 uint32_t serial,
69 uint32_t time,
70 uint32_t key,
71 uint32_t state)
72 {
73 int value = 1;
74 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
75 uint32_t keysym = key;
76
77 /* Handle 'duplicate' inputs that correspond
78 * to the same RETROK_* key */
79 switch (key)
80 {
81 case KEY_OK:
82 case KEY_SELECT:
83 keysym = KEY_ENTER;
84 case KEY_EXIT:
85 keysym = KEY_CLEAR;
86 default:
87 break;
88 }
89
90 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
91 {
92 BIT_SET(wl->input.key_state, keysym);
93 value = 1;
94 }
95 else if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
96 {
97 BIT_CLEAR(wl->input.key_state, keysym);
98 value = 0;
99 }
100
101 #ifdef HAVE_XKBCOMMON
102 if (handle_xkb(keysym, value) == 0)
103 return;
104 #endif
105 input_keyboard_event(value,
106 input_keymaps_translate_keysym_to_rk(keysym),
107 0, 0, RETRO_DEVICE_KEYBOARD);
108 }
109
keyboard_handle_modifiers(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t modsDepressed,uint32_t modsLatched,uint32_t modsLocked,uint32_t group)110 static void keyboard_handle_modifiers(void *data,
111 struct wl_keyboard *keyboard,
112 uint32_t serial,
113 uint32_t modsDepressed,
114 uint32_t modsLatched,
115 uint32_t modsLocked,
116 uint32_t group)
117 {
118 #ifdef HAVE_XKBCOMMON
119 handle_xkb_state_mask(modsDepressed, modsLatched, modsLocked, group);
120 #endif
121 }
122
keyboard_handle_repeat_info(void * data,struct wl_keyboard * wl_keyboard,int32_t rate,int32_t delay)123 void keyboard_handle_repeat_info(void *data,
124 struct wl_keyboard *wl_keyboard,
125 int32_t rate,
126 int32_t delay)
127 {
128 /* TODO: Seems like we'll need this to get
129 * repeat working. We'll have to do it on our own. */
130 }
131
gfx_ctx_wl_show_mouse(void * data,bool state)132 void gfx_ctx_wl_show_mouse(void *data, bool state)
133 {
134 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
135 if (!wl->wl_pointer)
136 return;
137
138 if (state)
139 {
140 struct wl_cursor_image *image = wl->cursor.default_cursor->images[0];
141 wl_pointer_set_cursor(wl->wl_pointer, wl->cursor.serial, wl->cursor.surface, image->hotspot_x, image->hotspot_y);
142 wl_surface_attach(wl->cursor.surface, wl_cursor_image_get_buffer(image), 0, 0);
143 wl_surface_damage(wl->cursor.surface, 0, 0, image->width, image->height);
144 wl_surface_commit(wl->cursor.surface);
145 }
146 else
147 wl_pointer_set_cursor(wl->wl_pointer, wl->cursor.serial, NULL, 0, 0);
148
149 wl->cursor.visible = state;
150 }
151
pointer_handle_enter(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface,wl_fixed_t sx,wl_fixed_t sy)152 static void pointer_handle_enter(void *data,
153 struct wl_pointer *pointer,
154 uint32_t serial,
155 struct wl_surface *surface,
156 wl_fixed_t sx,
157 wl_fixed_t sy)
158 {
159 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
160
161 wl->input.mouse.last_x = wl_fixed_to_int(sx * (wl_fixed_t)wl->buffer_scale);
162 wl->input.mouse.last_y = wl_fixed_to_int(sy * (wl_fixed_t)wl->buffer_scale);
163 wl->input.mouse.x = wl->input.mouse.last_x;
164 wl->input.mouse.y = wl->input.mouse.last_y;
165 wl->input.mouse.focus = true;
166 wl->cursor.serial = serial;
167
168 gfx_ctx_wl_show_mouse(data, wl->cursor.visible);
169 }
170
pointer_handle_leave(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface)171 static void pointer_handle_leave(void *data,
172 struct wl_pointer *pointer,
173 uint32_t serial,
174 struct wl_surface *surface)
175 {
176 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
177 wl->input.mouse.focus = false;
178 }
179
pointer_handle_motion(void * data,struct wl_pointer * pointer,uint32_t time,wl_fixed_t sx,wl_fixed_t sy)180 static void pointer_handle_motion(void *data,
181 struct wl_pointer *pointer,
182 uint32_t time,
183 wl_fixed_t sx,
184 wl_fixed_t sy)
185 {
186 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
187 wl->input.mouse.x = wl_fixed_to_int(
188 (wl_fixed_t)wl->buffer_scale * sx);
189 wl->input.mouse.y = wl_fixed_to_int(
190 (wl_fixed_t)wl->buffer_scale * sy);
191 }
192
pointer_handle_button(void * data,struct wl_pointer * wl_pointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)193 static void pointer_handle_button(void *data,
194 struct wl_pointer *wl_pointer,
195 uint32_t serial,
196 uint32_t time,
197 uint32_t button,
198 uint32_t state)
199 {
200 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
201
202 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
203 {
204 switch (button)
205 {
206 case BTN_LEFT:
207 wl->input.mouse.left = true;
208
209 if (BIT_GET(wl->input.key_state, KEY_LEFTALT))
210 {
211 if (wl->xdg_toplevel)
212 xdg_toplevel_move(wl->xdg_toplevel, wl->seat, serial);
213 else if (wl->zxdg_toplevel)
214 zxdg_toplevel_v6_move(wl->zxdg_toplevel, wl->seat, serial);
215 }
216 break;
217 case BTN_RIGHT:
218 wl->input.mouse.right = true;
219 break;
220 case BTN_MIDDLE:
221 wl->input.mouse.middle = true;
222 break;
223 }
224 }
225 else
226 {
227 switch (button)
228 {
229 case BTN_LEFT:
230 wl->input.mouse.left = false;
231 break;
232 case BTN_RIGHT:
233 wl->input.mouse.right = false;
234 break;
235 case BTN_MIDDLE:
236 wl->input.mouse.middle = false;
237 break;
238 }
239 }
240 }
241
pointer_handle_axis(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis,wl_fixed_t value)242 static void pointer_handle_axis(void *data,
243 struct wl_pointer *wl_pointer,
244 uint32_t time,
245 uint32_t axis,
246 wl_fixed_t value) { }
247
248 /* TODO: implement check for resize */
249
touch_handle_down(void * data,struct wl_touch * wl_touch,uint32_t serial,uint32_t time,struct wl_surface * surface,int32_t id,wl_fixed_t x,wl_fixed_t y)250 static void touch_handle_down(void *data,
251 struct wl_touch *wl_touch,
252 uint32_t serial,
253 uint32_t time,
254 struct wl_surface *surface,
255 int32_t id,
256 wl_fixed_t x,
257 wl_fixed_t y)
258 {
259 int i;
260 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
261
262 if (wl->num_active_touches < MAX_TOUCHES)
263 {
264 for (i = 0; i < MAX_TOUCHES; i++)
265 {
266 /* Use next empty slot */
267 if (!wl->active_touch_positions[i].active)
268 {
269 wl->active_touch_positions[wl->num_active_touches].active = true;
270 wl->active_touch_positions[wl->num_active_touches].id = id;
271 wl->active_touch_positions[wl->num_active_touches].x = (unsigned)
272 wl_fixed_to_int(x);
273 wl->active_touch_positions[wl->num_active_touches].y = (unsigned)
274 wl_fixed_to_int(y);
275 wl->num_active_touches++;
276 break;
277 }
278 }
279 }
280 }
281
reorder_touches(gfx_ctx_wayland_data_t * wl)282 static void reorder_touches(gfx_ctx_wayland_data_t *wl)
283 {
284 int i, j;
285 if (wl->num_active_touches == 0)
286 return;
287
288 for (i = 0; i < MAX_TOUCHES; i++)
289 {
290 if (!wl->active_touch_positions[i].active)
291 {
292 for (j=i+1; j<MAX_TOUCHES; j++)
293 {
294 if (wl->active_touch_positions[j].active)
295 {
296 wl->active_touch_positions[i].active =
297 wl->active_touch_positions[j].active;
298 wl->active_touch_positions[i].id =
299 wl->active_touch_positions[j].id;
300 wl->active_touch_positions[i].x = wl->active_touch_positions[j].x;
301 wl->active_touch_positions[i].y = wl->active_touch_positions[j].y;
302 wl->active_touch_positions[j].active = false;
303 wl->active_touch_positions[j].id = -1;
304 wl->active_touch_positions[j].x = (unsigned) 0;
305 wl->active_touch_positions[j].y = (unsigned) 0;
306 break;
307 }
308
309 if (j == MAX_TOUCHES)
310 return;
311 }
312 }
313 }
314 }
315
touch_handle_up(void * data,struct wl_touch * wl_touch,uint32_t serial,uint32_t time,int32_t id)316 static void touch_handle_up(void *data,
317 struct wl_touch *wl_touch,
318 uint32_t serial,
319 uint32_t time,
320 int32_t id)
321 {
322 int i;
323 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
324
325 for (i = 0; i < MAX_TOUCHES; i++)
326 {
327 if ( wl->active_touch_positions[i].active &&
328 wl->active_touch_positions[i].id == id)
329 {
330 wl->active_touch_positions[i].active = false;
331 wl->active_touch_positions[i].id = -1;
332 wl->active_touch_positions[i].x = (unsigned)0;
333 wl->active_touch_positions[i].y = (unsigned)0;
334 wl->num_active_touches--;
335 }
336 }
337 reorder_touches(wl);
338 }
339
touch_handle_motion(void * data,struct wl_touch * wl_touch,uint32_t time,int32_t id,wl_fixed_t x,wl_fixed_t y)340 static void touch_handle_motion(void *data,
341 struct wl_touch *wl_touch,
342 uint32_t time,
343 int32_t id,
344 wl_fixed_t x,
345 wl_fixed_t y)
346 {
347 int i;
348 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
349
350 for (i = 0; i < MAX_TOUCHES; i++)
351 {
352 if ( wl->active_touch_positions[i].active &&
353 wl->active_touch_positions[i].id == id)
354 {
355 wl->active_touch_positions[i].x = (unsigned) wl_fixed_to_int(x);
356 wl->active_touch_positions[i].y = (unsigned) wl_fixed_to_int(y);
357 }
358 }
359 }
360
touch_handle_frame(void * data,struct wl_touch * wl_touch)361 static void touch_handle_frame(void *data,
362 struct wl_touch *wl_touch) { }
363
touch_handle_cancel(void * data,struct wl_touch * wl_touch)364 static void touch_handle_cancel(void *data,
365 struct wl_touch *wl_touch)
366 {
367 /* If i understand the spec correctly we have to reset all touches here
368 * since they were not ment for us anyway */
369 int i;
370 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
371
372 for (i = 0; i < MAX_TOUCHES; i++)
373 {
374 wl->active_touch_positions[i].active = false;
375 wl->active_touch_positions[i].id = -1;
376 wl->active_touch_positions[i].x = (unsigned) 0;
377 wl->active_touch_positions[i].y = (unsigned) 0;
378 }
379
380 wl->num_active_touches = 0;
381 }
382
seat_handle_capabilities(void * data,struct wl_seat * seat,unsigned caps)383 static void seat_handle_capabilities(void *data,
384 struct wl_seat *seat, unsigned caps)
385 {
386 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
387
388 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl->wl_keyboard)
389 {
390 wl->wl_keyboard = wl_seat_get_keyboard(seat);
391 wl_keyboard_add_listener(wl->wl_keyboard, &keyboard_listener, wl);
392 }
393 else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl->wl_keyboard)
394 {
395 wl_keyboard_destroy(wl->wl_keyboard);
396 wl->wl_keyboard = NULL;
397 }
398 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl->wl_pointer)
399 {
400 wl->wl_pointer = wl_seat_get_pointer(seat);
401 wl_pointer_add_listener(wl->wl_pointer, &pointer_listener, wl);
402 }
403 else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl->wl_pointer)
404 {
405 wl_pointer_destroy(wl->wl_pointer);
406 wl->wl_pointer = NULL;
407 }
408 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wl->wl_touch)
409 {
410 wl->wl_touch = wl_seat_get_touch(seat);
411 wl_touch_add_listener(wl->wl_touch, &touch_listener, wl);
412 }
413 else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wl->wl_touch)
414 {
415 wl_touch_destroy(wl->wl_touch);
416 wl->wl_touch = NULL;
417 }
418
419 }
420
seat_handle_name(void * data,struct wl_seat * seat,const char * name)421 static void seat_handle_name(void *data,
422 struct wl_seat *seat, const char *name) { }
423
424 /* Surface callbacks. */
425
wl_surface_enter(void * data,struct wl_surface * wl_surface,struct wl_output * output)426 static void wl_surface_enter(void *data, struct wl_surface *wl_surface,
427 struct wl_output *output)
428 {
429 output_info_t *oi;
430 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
431
432 /* TODO: track all outputs the surface is on, pick highest scale */
433
434 wl_list_for_each(oi, &wl->all_outputs, link)
435 {
436 if (oi->output == output)
437 {
438 wl->current_output = oi;
439 wl->last_buffer_scale = wl->buffer_scale;
440 wl->buffer_scale = oi->scale;
441 break;
442 }
443 };
444 }
445
wl_nop(void * a,struct wl_surface * b,struct wl_output * c)446 static void wl_nop(void *a, struct wl_surface *b, struct wl_output *c) { }
447
448 /* Shell surface callbacks. */
xdg_shell_ping(void * data,struct xdg_wm_base * shell,uint32_t serial)449 static void xdg_shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
450 {
451 xdg_wm_base_pong(shell, serial);
452 }
453
handle_surface_config(void * data,struct xdg_surface * surface,uint32_t serial)454 static void handle_surface_config(void *data, struct xdg_surface *surface,
455 uint32_t serial)
456 {
457 xdg_surface_ack_configure(surface, serial);
458 }
459
zxdg_shell_ping(void * data,struct zxdg_shell_v6 * shell,uint32_t serial)460 static void zxdg_shell_ping(void *data,
461 struct zxdg_shell_v6 *shell, uint32_t serial)
462 {
463 zxdg_shell_v6_pong(shell, serial);
464 }
465
handle_zxdg_surface_config(void * data,struct zxdg_surface_v6 * surface,uint32_t serial)466 static void handle_zxdg_surface_config(void *data,
467 struct zxdg_surface_v6 *surface,
468 uint32_t serial)
469 {
470 zxdg_surface_v6_ack_configure(surface, serial);
471 }
472
handle_toplevel_close(void * data,struct xdg_toplevel * xdg_toplevel)473 void handle_toplevel_close(void *data,
474 struct xdg_toplevel *xdg_toplevel)
475 {
476 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
477 BIT_SET(wl->input.key_state, KEY_ESC);
478 }
479
handle_zxdg_toplevel_close(void * data,struct zxdg_toplevel_v6 * zxdg_toplevel)480 void handle_zxdg_toplevel_close(void *data,
481 struct zxdg_toplevel_v6 *zxdg_toplevel)
482 {
483 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
484 BIT_SET(wl->input.key_state, KEY_ESC);
485 }
486
display_handle_geometry(void * data,struct wl_output * output,int x,int y,int physical_width,int physical_height,int subpixel,const char * make,const char * model,int transform)487 static void display_handle_geometry(void *data,
488 struct wl_output *output,
489 int x, int y,
490 int physical_width, int physical_height,
491 int subpixel,
492 const char *make,
493 const char *model,
494 int transform)
495 {
496 output_info_t *oi = (output_info_t*)data;
497 oi->physical_width = physical_width;
498 oi->physical_height = physical_height;
499 }
500
display_handle_mode(void * data,struct wl_output * output,uint32_t flags,int width,int height,int refresh)501 static void display_handle_mode(void *data,
502 struct wl_output *output,
503 uint32_t flags,
504 int width,
505 int height,
506 int refresh)
507 {
508 (void)output;
509 (void)flags;
510
511 output_info_t *oi = (output_info_t*)data;
512 oi->width = width;
513 oi->height = height;
514 oi->refresh_rate = refresh;
515 }
516
display_handle_done(void * data,struct wl_output * output)517 static void display_handle_done(void *data,
518 struct wl_output *output) { }
519
display_handle_scale(void * data,struct wl_output * output,int32_t factor)520 static void display_handle_scale(void *data,
521 struct wl_output *output,
522 int32_t factor)
523 {
524 output_info_t *oi = (output_info_t*)data;
525 oi->scale = factor;
526 }
527
528 /* Registry callbacks. */
registry_handle_global(void * data,struct wl_registry * reg,uint32_t id,const char * interface,uint32_t version)529 static void registry_handle_global(void *data, struct wl_registry *reg,
530 uint32_t id, const char *interface, uint32_t version)
531 {
532 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
533
534 if (string_is_equal(interface, "wl_compositor"))
535 wl->compositor = (struct wl_compositor*)wl_registry_bind(reg,
536 id, &wl_compositor_interface, 3);
537 else if (string_is_equal(interface, "wl_output"))
538 {
539 output_info_t *oi = (output_info_t*)
540 calloc(1, sizeof(output_info_t));
541
542 oi->global_id = id;
543 oi->output = (struct wl_output*)wl_registry_bind(reg,
544 id, &wl_output_interface, 2);
545 wl_output_add_listener(oi->output, &output_listener, oi);
546 wl_list_insert(&wl->all_outputs, &oi->link);
547 wl_display_roundtrip(wl->input.dpy);
548 }
549 else if (string_is_equal(interface, "xdg_wm_base"))
550 wl->xdg_shell = (struct xdg_wm_base*)
551 wl_registry_bind(reg, id, &xdg_wm_base_interface, 1);
552 else if (string_is_equal(interface, "zxdg_shell_v6"))
553 wl->zxdg_shell = (struct zxdg_shell_v6*)
554 wl_registry_bind(reg, id, &zxdg_shell_v6_interface, 1);
555 else if (string_is_equal(interface, "wl_shm"))
556 wl->shm = (struct wl_shm*)wl_registry_bind(reg, id, &wl_shm_interface, 1);
557 else if (string_is_equal(interface, "wl_seat"))
558 {
559 wl->seat = (struct wl_seat*)wl_registry_bind(reg, id, &wl_seat_interface, 2);
560 wl_seat_add_listener(wl->seat, &seat_listener, wl);
561 }
562 else if (string_is_equal(interface, "zwp_idle_inhibit_manager_v1"))
563 wl->idle_inhibit_manager = (struct zwp_idle_inhibit_manager_v1*)wl_registry_bind(
564 reg, id, &zwp_idle_inhibit_manager_v1_interface, 1);
565 else if (string_is_equal(interface, "zxdg_decoration_manager_v1"))
566 wl->deco_manager = (struct zxdg_decoration_manager_v1*)wl_registry_bind(
567 reg, id, &zxdg_decoration_manager_v1_interface, 1);
568 }
569
registry_handle_global_remove(void * data,struct wl_registry * registry,uint32_t id)570 static void registry_handle_global_remove(void *data,
571 struct wl_registry *registry, uint32_t id)
572 {
573 output_info_t *oi, *tmp;
574 gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
575
576 wl_list_for_each_safe(oi, tmp, &wl->all_outputs, link)
577 {
578 if (oi->global_id == id)
579 {
580 wl_list_remove(&oi->link);
581 free(oi);
582 break;
583 }
584 }
585 }
586
587 const struct wl_registry_listener registry_listener = {
588 registry_handle_global,
589 registry_handle_global_remove,
590 };
591
592
593 const struct wl_output_listener output_listener = {
594 display_handle_geometry,
595 display_handle_mode,
596 display_handle_done,
597 display_handle_scale,
598 };
599
600 const struct zxdg_shell_v6_listener zxdg_shell_v6_listener = {
601 zxdg_shell_ping,
602 };
603
604 const struct zxdg_surface_v6_listener zxdg_surface_v6_listener = {
605 handle_zxdg_surface_config,
606 };
607
608 const struct xdg_wm_base_listener xdg_shell_listener = {
609 xdg_shell_ping,
610 };
611
612 const struct xdg_surface_listener xdg_surface_listener = {
613 handle_surface_config,
614 };
615
616 const struct wl_surface_listener wl_surface_listener = {
617 wl_surface_enter,
618 wl_nop,
619 };
620
621 const struct wl_seat_listener seat_listener = {
622 seat_handle_capabilities,
623 seat_handle_name,
624 };
625
626 const struct wl_touch_listener touch_listener = {
627 touch_handle_down,
628 touch_handle_up,
629 touch_handle_motion,
630 touch_handle_frame,
631 touch_handle_cancel,
632 };
633
634 const struct wl_keyboard_listener keyboard_listener = {
635 keyboard_handle_keymap,
636 keyboard_handle_enter,
637 keyboard_handle_leave,
638 keyboard_handle_key,
639 keyboard_handle_modifiers,
640 keyboard_handle_repeat_info
641 };
642
643 const struct wl_pointer_listener pointer_listener = {
644 pointer_handle_enter,
645 pointer_handle_leave,
646 pointer_handle_motion,
647 pointer_handle_button,
648 pointer_handle_axis,
649 };
650
flush_wayland_fd(void * data)651 void flush_wayland_fd(void *data)
652 {
653 struct pollfd fd = {0};
654 input_ctx_wayland_data_t *wl = (input_ctx_wayland_data_t*)data;
655
656 wl_display_dispatch_pending(wl->dpy);
657 wl_display_flush(wl->dpy);
658
659 fd.fd = wl->fd;
660 fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP;
661
662 if (poll(&fd, 1, 0) > 0)
663 {
664 if (fd.revents & (POLLERR | POLLHUP))
665 {
666 close(wl->fd);
667 frontend_driver_set_signal_handler_state(1);
668 }
669
670 if (fd.revents & POLLIN)
671 wl_display_dispatch(wl->dpy);
672 if (fd.revents & POLLOUT)
673 wl_display_flush(wl->dpy);
674 }
675 }
676