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