1 /**
2  *   MIT/X11 License
3  *   Modified  (c) 2017 Quentin “Sardem FF7” Glidic
4  *
5  *   Permission is hereby granted, free of charge, to any person obtaining
6  *   a copy of this software and associated documentation files (the
7  *   "Software"), to deal in the Software without restriction, including
8  *   without limitation the rights to use, copy, modify, merge, publish,
9  *   distribute, sublicense, and/or sell copies of the Software, and to
10  *   permit persons to whom the Software is furnished to do so, subject to
11  *   the following conditions:
12  *
13  *   The above copyright notice and this permission notice shall be
14  *   included in all copies or substantial portions of the Software.
15  *
16  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  *   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  *   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  *   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  *   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  *   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #define G_LOG_DOMAIN    "Wayland"
26 #pragma GCC diagnostic ignored "-Wunused-variable"
27 #pragma GCC diagnostic ignored "-Wunused-parameter"
28 
29 #include <config.h>
30 #include <sys/mman.h>
31 #include <sys/types.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <locale.h>
36 #include <linux/input-event-codes.h>
37 
38 #include <glib.h>
39 #include <glib/gstdio.h>
40 #include <cairo.h>
41 #include <wayland-client.h>
42 #include <wayland-cursor.h>
43 #include <xcb/xkb.h>
44 #include <libgwater-wayland.h>
45 #include <xkbcommon/xkbcommon.h>
46 #include <xkbcommon/xkbcommon-compose.h>
47 
48 #include <nkutils-bindings.h>
49 
50 #include "keyb.h"
51 #include "view.h"
52 
53 #include "wayland-internal.h"
54 #include "display.h"
55 #include "display-internal.h"
56 
57 #include "wlr-layer-shell-unstable-v1-protocol.h"
58 
59 typedef struct _display_buffer_pool wayland_buffer_pool;
60 typedef struct
61 {
62     wayland_stuff    *context;
63     uint32_t         global_name;
64     struct wl_output *output;
65     int32_t          scale;
66 } wayland_output;
67 
68 typedef struct
69 {
70     wayland_buffer_pool *pool;
71     struct wl_buffer    *buffer;
72     uint8_t             *data;
73     gboolean            released;
74 } wayland_buffer;
75 
76 struct _display_buffer_pool
77 {
78     wayland_stuff  *context;
79     uint8_t        *data;
80     size_t         size;
81     int32_t        width;
82     int32_t        height;
83     gboolean       to_free;
84     wayland_buffer *buffers;
85 };
86 
87 static wayland_stuff               wayland_;
88 wayland_stuff                      *wayland = &wayland_;
89 static const cairo_user_data_key_t wayland_cairo_surface_user_data;
90 
91 static void
wayland_buffer_cleanup(wayland_buffer_pool * self)92 wayland_buffer_cleanup ( wayland_buffer_pool *self )
93 {
94     if ( !self->to_free ) {
95         return;
96     }
97 
98     size_t i, count = 0;
99     for ( i = 0; i < wayland->buffer_count; ++i ) {
100         if ( ( self->buffers[i].released ) && ( self->buffers[i].buffer != NULL ) ) {
101             wl_buffer_destroy ( self->buffers[i].buffer );
102             self->buffers[i].buffer = NULL;
103         }
104         if ( self->buffers[i].buffer == NULL ) {
105             ++count;
106         }
107     }
108 
109     if ( count < wayland->buffer_count ) {
110         return;
111     }
112 
113     munmap ( self->data, self->size );
114     g_free ( self );
115 }
116 
117 static void
wayland_buffer_release(void * data,struct wl_buffer * buffer)118 wayland_buffer_release ( void *data, struct wl_buffer *buffer )
119 {
120     wayland_buffer_pool *self = data;
121 
122     size_t              i;
123     for ( i = 0; i < wayland->buffer_count; ++i ) {
124         if ( self->buffers[i].buffer == buffer ) {
125             self->buffers[i].released = TRUE;
126         }
127     }
128 
129     wayland_buffer_cleanup ( self );
130 }
131 
132 static const struct wl_buffer_listener wayland_buffer_listener = {
133     wayland_buffer_release
134 };
135 
136 wayland_buffer_pool *
display_buffer_pool_new(gint width,gint height)137 display_buffer_pool_new ( gint width, gint height )
138 {
139     struct wl_shm_pool *wl_pool;
140     struct wl_buffer   *buffer;
141     int                fd;
142     uint8_t            *data;
143     width  *= wayland->scale;
144     height *= wayland->scale;
145     int32_t stride;
146     size_t  size;
147     size_t  pool_size;
148 
149     stride    = cairo_format_stride_for_width ( CAIRO_FORMAT_ARGB32, width );
150     size      = stride * height;
151     pool_size = size * wayland->buffer_count;
152 
153     gchar filename[PATH_MAX];
154     g_snprintf ( filename, PATH_MAX, "%s/rofi-wayland-surface", g_get_user_runtime_dir () );
155     fd = g_open ( filename, O_CREAT | O_RDWR, 0 );
156     g_unlink ( filename );
157     if ( fd < 0 ) {
158         g_warning ( "creating a buffer file for %zu B failed: %s", pool_size, g_strerror ( errno ) );
159         return NULL;
160     }
161     if ( fcntl ( fd, F_SETFD, FD_CLOEXEC ) < 0 ) {
162         g_close ( fd, NULL );
163         return NULL;
164     }
165     if ( ftruncate ( fd, pool_size ) < 0 ) {
166         g_close ( fd, NULL );
167         return NULL;
168     }
169 
170     data = mmap ( NULL, pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
171     if ( data == MAP_FAILED ) {
172         g_warning ( "mmap of size %zu failed: %s", pool_size, g_strerror ( errno ) );
173         close ( fd );
174         return NULL;
175     }
176 
177     wayland_buffer_pool *pool;
178     pool = g_new0 ( wayland_buffer_pool, 1 );
179 
180     pool->width  = width;
181     pool->height = height;
182 
183     pool->buffers = g_new0 ( wayland_buffer, wayland->buffer_count );
184 
185     wl_pool = wl_shm_create_pool ( wayland->shm, fd, pool_size );
186     size_t i;
187     for ( i = 0; i < wayland->buffer_count; ++i ) {
188         pool->buffers[i].pool     = pool;
189         pool->buffers[i].buffer   = wl_shm_pool_create_buffer ( wl_pool, size * i, width, height, stride, WL_SHM_FORMAT_ARGB8888 );
190         pool->buffers[i].data     = data + size * i;
191         pool->buffers[i].released = TRUE;
192         wl_buffer_add_listener ( pool->buffers[i].buffer, &wayland_buffer_listener, pool );
193     }
194     wl_shm_pool_destroy ( wl_pool );
195     close ( fd );
196 
197     return pool;
198 }
199 
200 void
display_buffer_pool_free(wayland_buffer_pool * self)201 display_buffer_pool_free ( wayland_buffer_pool *self )
202 {
203     self->to_free = TRUE;
204     wayland_buffer_cleanup ( self );
205 }
206 
207 static void
wayland_surface_protocol_enter(void * data,struct wl_surface * wl_surface,struct wl_output * wl_output)208 wayland_surface_protocol_enter ( void *data, struct wl_surface *wl_surface, struct wl_output *wl_output )
209 {
210     wayland_output *output;
211 
212     output = g_hash_table_lookup ( wayland->outputs, wl_output );
213     if ( output == NULL ) {
214         return;
215     }
216 
217     wl_surface_set_buffer_scale ( wl_surface, output->scale );
218 
219     if ( wayland->scale != output->scale ) {
220         wayland->scale = output->scale;
221 
222         // create new buffers with the correct scaled size
223         rofi_view_pool_refresh ( );
224 
225         RofiViewState *state = rofi_view_get_active ( );
226         if ( state != NULL ) {
227             rofi_view_set_size ( state, -1, -1 );
228         }
229     }
230 }
231 
232 static void
wayland_surface_protocol_leave(void * data,struct wl_surface * wl_surface,struct wl_output * wl_output)233 wayland_surface_protocol_leave ( void *data, struct wl_surface *wl_surface, struct wl_output *wl_output )
234 {
235 }
236 
237 static const struct wl_surface_listener wayland_surface_interface = {
238     .enter = wayland_surface_protocol_enter,
239     .leave = wayland_surface_protocol_leave,
240 };
241 
242 static void wayland_frame_callback ( void *data, struct wl_callback *callback, uint32_t time );
243 
244 static const struct wl_callback_listener wayland_frame_wl_callback_listener = {
245     .done = wayland_frame_callback,
246 };
247 
248 cairo_surface_t *
display_buffer_pool_get_next_buffer(wayland_buffer_pool * pool)249 display_buffer_pool_get_next_buffer ( wayland_buffer_pool *pool )
250 {
251     wayland_buffer *buffer = NULL;
252     size_t         i;
253     for ( i = 0; ( buffer == NULL ) && ( i < wayland->buffer_count ); ++i ) {
254         buffer = pool->buffers + i;
255         if ( !buffer->released ) {
256             buffer = NULL;
257         }
258     }
259     if ( buffer == NULL ) {
260         return NULL;
261     }
262 
263     cairo_surface_t *surface;
264 
265     surface = cairo_image_surface_create_for_data ( buffer->data, CAIRO_FORMAT_ARGB32, pool->width, pool->height, cairo_format_stride_for_width ( CAIRO_FORMAT_ARGB32, pool->width ) );
266     cairo_surface_set_user_data ( surface, &wayland_cairo_surface_user_data, buffer, NULL );
267     return surface;
268 }
269 
270 void
display_surface_commit(cairo_surface_t * surface)271 display_surface_commit ( cairo_surface_t *surface )
272 {
273     if ( surface == NULL ) {
274         return;
275     }
276 
277     wayland_buffer      *buffer = cairo_surface_get_user_data ( surface, &wayland_cairo_surface_user_data );
278     wayland_buffer_pool *pool   = buffer->pool;
279 
280     cairo_surface_destroy ( surface );
281 
282     wl_surface_damage ( wayland->surface, 0, 0, pool->width, pool->height );
283     wl_surface_attach ( wayland->surface, buffer->buffer, 0, 0 );
284     // FIXME: hidpi
285     wl_surface_set_buffer_scale ( wayland->surface, wayland->scale );
286     buffer->released = FALSE;
287 
288     wl_surface_commit ( wayland->surface );
289 }
290 
291 static void
wayland_frame_callback(void * data,struct wl_callback * callback,uint32_t timestamp)292 wayland_frame_callback ( void *data, struct wl_callback *callback, uint32_t timestamp )
293 {
294     if ( wayland->frame_cb != NULL ) {
295         wl_callback_destroy ( wayland->frame_cb );
296         rofi_view_frame_callback ();
297     }
298     wayland->frame_cb = wl_surface_frame ( wayland->surface );
299     wl_callback_add_listener ( wayland->frame_cb, &wayland_frame_wl_callback_listener, wayland );
300 }
301 
302 static void
wayland_keyboard_keymap(void * data,struct wl_keyboard * keyboard,enum wl_keyboard_keymap_format format,int32_t fd,uint32_t size)303 wayland_keyboard_keymap ( void *data, struct wl_keyboard *keyboard, enum wl_keyboard_keymap_format format, int32_t fd, uint32_t size )
304 {
305     wayland_seat *self = data;
306 
307     if ( format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 ) {
308         close ( fd );
309         return;
310     }
311 
312     char *str = mmap ( NULL, size, PROT_READ, MAP_SHARED, fd, 0 );
313     if ( str == MAP_FAILED ) {
314         close ( fd );
315         return;
316     }
317 
318     struct xkb_keymap *keymap = xkb_keymap_new_from_string ( nk_bindings_seat_get_context ( wayland->bindings_seat ), str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS );
319     if ( keymap == NULL ) {
320         fprintf ( stderr, "Failed to get Keymap for current keyboard device.\n" );
321         return;
322     }
323     struct xkb_state *state = xkb_state_new ( keymap );
324     if ( state == NULL ) {
325         fprintf ( stderr, "Failed to get state object for current keyboard device.\n" );
326         return;
327     }
328 
329     nk_bindings_seat_update_keymap ( wayland->bindings_seat, keymap, state );
330 }
331 
332 static void
wayland_keyboard_enter(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface,struct wl_array * keys)333 wayland_keyboard_enter ( void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys )
334 {
335     wayland_seat *self = data;
336 
337     wayland->last_seat = self;
338     self->serial       = serial;
339 
340     uint32_t *key, *kend;
341     for ( key = keys->data, kend = key + keys->size / sizeof ( *key ); key < kend; ++key ) {
342         nk_bindings_seat_handle_key ( wayland->bindings_seat, NULL, *key + 8, NK_BINDINGS_KEY_STATE_PRESSED );
343     }
344 }
345 
346 static void
wayland_keyboard_leave(void * data,struct wl_keyboard * keyboard,uint32_t serial,struct wl_surface * surface)347 wayland_keyboard_leave ( void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface )
348 {
349     wayland_seat *self = data;
350     // TODO?
351 }
352 
353 static gboolean
wayland_key_repeat(void * data)354 wayland_key_repeat ( void *data )
355 {
356     wayland_seat *self = data;
357 
358     if ( self->repeat.key == 0 ) {
359         self->repeat.source = NULL;
360         return G_SOURCE_REMOVE;
361     }
362 
363     char          *text = nk_bindings_seat_handle_key ( wayland->bindings_seat, NULL, self->repeat.key, NK_BINDINGS_KEY_STATE_PRESS );
364 
365     RofiViewState *state = rofi_view_get_active ( );
366     if ( state == NULL ) {
367         return G_SOURCE_REMOVE;
368     }
369 
370     if ( text != NULL ) {
371         rofi_view_handle_text ( state, text );
372     }
373 
374     rofi_view_maybe_update ( state );
375 
376     return G_SOURCE_CONTINUE;
377 }
378 
379 static gboolean
wayland_key_repeat_delay(void * data)380 wayland_key_repeat_delay ( void *data )
381 {
382     wayland_seat *self = data;
383 
384     if ( self->repeat.key == 0 ) {
385         return FALSE;
386     }
387 
388     char          *text = nk_bindings_seat_handle_key ( wayland->bindings_seat, NULL, self->repeat.key, NK_BINDINGS_KEY_STATE_PRESS );
389 
390     RofiViewState *state = rofi_view_get_active ( );
391     if ( state == NULL ) {
392         return G_SOURCE_REMOVE;
393     }
394 
395     if ( text != NULL ) {
396         rofi_view_handle_text ( state, text );
397     }
398 
399     guint source_id = g_timeout_add ( self->repeat.rate, wayland_key_repeat, data );
400     self->repeat.source = g_main_context_find_source_by_id ( NULL, source_id );
401 
402     rofi_view_maybe_update ( state );
403 
404     return G_SOURCE_REMOVE;
405 }
406 
407 static void
wayland_keyboard_key(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t time,uint32_t key,enum wl_keyboard_key_state kstate)408 wayland_keyboard_key ( void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, enum wl_keyboard_key_state kstate )
409 {
410     RofiViewState *state = rofi_view_get_active ( );
411     wayland_seat  *self  = data;
412 
413     gchar         *text;
414 
415     wayland->last_seat = self;
416     self->serial       = serial;
417 
418     xkb_keycode_t keycode = key + 8;
419     if ( kstate == WL_KEYBOARD_KEY_STATE_RELEASED ) {
420         if ( keycode == self->repeat.key ) {
421             self->repeat.key = 0;
422             if ( self->repeat.source != NULL ) {
423                 g_source_destroy ( self->repeat.source );
424                 self->repeat.source = NULL;
425             }
426         }
427         nk_bindings_seat_handle_key ( wayland->bindings_seat, NULL, keycode, NK_BINDINGS_KEY_STATE_RELEASE );
428     }
429     else if ( kstate == WL_KEYBOARD_KEY_STATE_PRESSED ) {
430         char *text = nk_bindings_seat_handle_key ( wayland->bindings_seat, NULL, keycode, NK_BINDINGS_KEY_STATE_PRESS );
431 
432         if ( self->repeat.source != NULL ) {
433             g_source_destroy ( self->repeat.source );
434             self->repeat.source = NULL;
435         }
436 
437         if ( state != NULL ) {
438             if ( text != NULL ) {
439                 rofi_view_handle_text ( state, text );
440             }
441             self->repeat.key = keycode;
442             guint source_id = g_timeout_add ( self->repeat.delay, wayland_key_repeat_delay, data );
443             self->repeat.source = g_main_context_find_source_by_id ( NULL, source_id );
444         }
445     }
446 
447     if ( state != NULL ) {
448         rofi_view_maybe_update ( state );
449     }
450 }
451 
452 static void
wayland_keyboard_modifiers(void * data,struct wl_keyboard * keyboard,uint32_t serial,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)453 wayland_keyboard_modifiers ( void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group )
454 {
455     wayland_seat *self = data;
456     nk_bindings_seat_update_mask ( wayland->bindings_seat, NULL, mods_depressed, mods_latched, mods_locked, 0, 0, 0 );
457 
458     RofiViewState *state = rofi_view_get_active ( );
459     if ( state != NULL ) {
460         rofi_view_maybe_update ( state );
461     }
462 }
463 
464 static void
wayland_keyboard_repeat_info(void * data,struct wl_keyboard * keyboard,int32_t rate,int32_t delay)465 wayland_keyboard_repeat_info ( void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay )
466 {
467     wayland_seat *self = data;
468     self->repeat.key   = 0;
469     self->repeat.rate  = rate;
470     self->repeat.delay = delay;
471     if ( self->repeat.source != NULL ) {
472         g_source_destroy ( self->repeat.source );
473         self->repeat.source = NULL;
474     }
475 }
476 
477 static const struct wl_keyboard_listener wayland_keyboard_listener = {
478     .keymap      = wayland_keyboard_keymap,
479     .enter       = wayland_keyboard_enter,
480     .leave       = wayland_keyboard_leave,
481     .key         = wayland_keyboard_key,
482     .modifiers   = wayland_keyboard_modifiers,
483     .repeat_info = wayland_keyboard_repeat_info,
484 };
485 
486 static void
wayland_cursor_set_image(int i)487 wayland_cursor_set_image ( int i )
488 {
489     struct wl_buffer       *buffer;
490     struct wl_cursor_image *image;
491     image = wayland->cursor.cursor->images[i];
492 
493     wayland->cursor.image = image;
494     buffer                = wl_cursor_image_get_buffer ( wayland->cursor.image );
495     wl_surface_attach ( wayland->cursor.surface, buffer, 0, 0 );
496     wl_surface_damage ( wayland->cursor.surface, 0, 0, wayland->cursor.image->width, wayland->cursor.image->height );
497     wl_surface_commit ( wayland->cursor.surface );
498 }
499 
500 static void wayland_cursor_frame_callback ( void *data, struct wl_callback *callback, uint32_t time );
501 
502 static const struct wl_callback_listener wayland_cursor_frame_wl_callback_listener = {
503     .done = wayland_cursor_frame_callback,
504 };
505 
506 static void
wayland_cursor_frame_callback(void * data,struct wl_callback * callback,uint32_t time)507 wayland_cursor_frame_callback ( void *data, struct wl_callback *callback, uint32_t time )
508 {
509     int i;
510 
511     if ( wayland->cursor.frame_cb != NULL ) {
512         wl_callback_destroy ( wayland->cursor.frame_cb );
513     }
514     wayland->cursor.frame_cb = wl_surface_frame ( wayland->cursor.surface );
515     wl_callback_add_listener ( wayland->cursor.frame_cb, &wayland_cursor_frame_wl_callback_listener, wayland );
516 
517     i = wl_cursor_frame ( wayland->cursor.cursor, time );
518     wayland_cursor_set_image ( i );
519 }
520 
521 static void
wayland_pointer_send_events(wayland_seat * self)522 wayland_pointer_send_events ( wayland_seat *self )
523 {
524     RofiViewState *state = rofi_view_get_active ();
525 
526     if ( state == NULL ) {
527         return;
528     }
529 
530     if ( self->motion.x > -1 || self->motion.y > -1 ) {
531         rofi_view_handle_mouse_motion ( state, self->motion.x, self->motion.y );
532         self->motion.x = -1;
533         self->motion.y = -1;
534     }
535 
536     NkBindingsMouseButton button = -1;
537     switch ( self->button.button )
538     {
539     case BTN_LEFT:
540         button = NK_BINDINGS_MOUSE_BUTTON_PRIMARY;
541         break;
542     case BTN_RIGHT:
543         button = NK_BINDINGS_MOUSE_BUTTON_SECONDARY;
544         break;
545     case BTN_MIDDLE:
546         button = NK_BINDINGS_MOUSE_BUTTON_MIDDLE;
547         break;
548     }
549 
550     if ( self->button.button >= 0 ) {
551         if ( self->button.pressed ) {
552             rofi_view_handle_mouse_motion ( state, self->button.x, self->button.y );
553             nk_bindings_seat_handle_button ( wayland->bindings_seat, NULL, button, NK_BINDINGS_BUTTON_STATE_PRESS, self->button.time );
554         }
555         else {
556             nk_bindings_seat_handle_button ( wayland->bindings_seat, NULL, button, NK_BINDINGS_BUTTON_STATE_RELEASE, self->button.time );
557         }
558         self->button.button = 0;
559     }
560 
561     if ( self->wheel.vertical != 0 ) {
562         nk_bindings_seat_handle_scroll ( wayland->bindings_seat, NULL, NK_BINDINGS_SCROLL_AXIS_VERTICAL, self->wheel.vertical );
563         self->wheel.vertical = 0;
564     }
565 
566     if ( self->wheel.horizontal != 0 ) {
567         nk_bindings_seat_handle_scroll ( wayland->bindings_seat, NULL, NK_BINDINGS_SCROLL_AXIS_HORIZONTAL, self->wheel.horizontal );
568         self->wheel.horizontal = 0;
569     }
570 
571     rofi_view_maybe_update ( state );
572 }
573 
574 static void
wayland_pointer_enter(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface,wl_fixed_t x,wl_fixed_t y)575 wayland_pointer_enter ( void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y )
576 {
577     wayland_seat *self = data;
578 
579     if ( wayland->cursor.surface == NULL ) {
580         return;
581     }
582 
583     if ( wayland->cursor.cursor->image_count < 2 ) {
584         wayland_cursor_set_image ( 0 );
585     }
586     else{
587         wayland_cursor_frame_callback ( wayland, wayland->cursor.frame_cb, 0 );
588     }
589 
590     wl_pointer_set_cursor ( self->pointer, serial, wayland->cursor.surface, wayland->cursor.image->hotspot_x, wayland->cursor.image->hotspot_y );
591 }
592 
593 static void
wayland_pointer_leave(void * data,struct wl_pointer * pointer,uint32_t serial,struct wl_surface * surface)594 wayland_pointer_leave ( void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface )
595 {
596     wayland_seat *self = data;
597 
598     if ( wayland->cursor.frame_cb != NULL ) {
599         wl_callback_destroy ( wayland->cursor.frame_cb );
600     }
601 }
602 
603 static void
wayland_pointer_motion(void * data,struct wl_pointer * pointer,uint32_t time,wl_fixed_t x,wl_fixed_t y)604 wayland_pointer_motion ( void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y )
605 {
606     wayland_seat *self = data;
607 
608     self->button.x    = wl_fixed_to_int ( x );
609     self->button.y    = wl_fixed_to_int ( y );
610     self->motion.x    = wl_fixed_to_int ( x );
611     self->motion.y    = wl_fixed_to_int ( y );
612     self->motion.time = time;
613 
614     if ( wl_pointer_get_version ( self->pointer ) >= WL_POINTER_FRAME_SINCE_VERSION ) {
615         return;
616     }
617 
618     wayland_pointer_send_events ( self );
619 }
620 
621 static void
wayland_pointer_button(void * data,struct wl_pointer * pointer,uint32_t serial,uint32_t time,uint32_t button,enum wl_pointer_button_state state)622 wayland_pointer_button ( void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, enum wl_pointer_button_state state )
623 {
624     wayland_seat *self = data;
625 
626     wayland->last_seat = self;
627     self->serial       = serial;
628 
629     self->button.time    = time;
630     self->button.pressed = ( state == WL_POINTER_BUTTON_STATE_PRESSED );
631     self->button.button  = button;
632 
633     wayland_pointer_send_events ( self );
634 }
635 
636 static void
wayland_pointer_axis(void * data,struct wl_pointer * pointer,uint32_t time,enum wl_pointer_axis axis,wl_fixed_t value)637 wayland_pointer_axis ( void *data, struct wl_pointer *pointer, uint32_t time, enum wl_pointer_axis axis, wl_fixed_t value )
638 {
639     wayland_seat *self = data;
640 
641     switch ( axis )
642     {
643     case WL_POINTER_AXIS_VERTICAL_SCROLL:
644         self->wheel.vertical += (gint) ( wl_fixed_to_double ( value ) / 10. );
645         break;
646     case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
647         self->wheel.horizontal += (gint) ( wl_fixed_to_double ( value ) / 10. );
648         break;
649     }
650 
651     wayland_pointer_send_events ( self );
652 }
653 
654 static void
wayland_pointer_frame(void * data,struct wl_pointer * pointer)655 wayland_pointer_frame ( void *data, struct wl_pointer *pointer )
656 {
657     wayland_seat *self = data;
658     wayland_pointer_send_events ( self );
659 }
660 
661 static void
wayland_pointer_axis_source(void * data,struct wl_pointer * pointer,enum wl_pointer_axis_source axis_source)662 wayland_pointer_axis_source ( void *data, struct wl_pointer *pointer, enum wl_pointer_axis_source axis_source )
663 {
664 }
665 
666 static void
wayland_pointer_axis_stop(void * data,struct wl_pointer * pointer,uint32_t time,enum wl_pointer_axis axis)667 wayland_pointer_axis_stop ( void *data, struct wl_pointer *pointer, uint32_t time, enum wl_pointer_axis axis )
668 {
669 }
670 
671 static void
wayland_pointer_axis_discrete(void * data,struct wl_pointer * pointer,enum wl_pointer_axis axis,int32_t discrete)672 wayland_pointer_axis_discrete ( void *data, struct wl_pointer *pointer, enum wl_pointer_axis axis, int32_t discrete )
673 {
674     wayland_seat *self = data;
675 
676     switch ( axis )
677     {
678     case WL_POINTER_AXIS_VERTICAL_SCROLL:
679         self->wheel.vertical += discrete;
680         break;
681     case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
682         self->wheel.horizontal += discrete;
683         break;
684     }
685 }
686 
687 static const struct wl_pointer_listener wayland_pointer_listener = {
688     .enter         = wayland_pointer_enter,
689     .leave         = wayland_pointer_leave,
690     .motion        = wayland_pointer_motion,
691     .button        = wayland_pointer_button,
692     .axis          = wayland_pointer_axis,
693     .frame         = wayland_pointer_frame,
694     .axis_source   = wayland_pointer_axis_source,
695     .axis_stop     = wayland_pointer_axis_stop,
696     .axis_discrete = wayland_pointer_axis_discrete,
697 };
698 
699 static void
wayland_keyboard_release(wayland_seat * self)700 wayland_keyboard_release ( wayland_seat *self )
701 {
702     if ( self->keyboard == NULL ) {
703         return;
704     }
705 
706     if ( wl_keyboard_get_version ( self->keyboard ) >= WL_KEYBOARD_RELEASE_SINCE_VERSION ) {
707         wl_keyboard_release ( self->keyboard );
708     }
709     else{
710         wl_keyboard_destroy ( self->keyboard );
711     }
712 
713     self->repeat.key = 0;
714     if ( self->repeat.source != NULL ) {
715         g_source_destroy ( self->repeat.source );
716         self->repeat.source = NULL;
717     }
718 
719     self->keyboard = NULL;
720 }
721 
722 static void
wayland_pointer_release(wayland_seat * self)723 wayland_pointer_release ( wayland_seat *self )
724 {
725     if ( self->pointer == NULL ) {
726         return;
727     }
728 
729     if ( wl_pointer_get_version ( self->pointer ) >= WL_POINTER_RELEASE_SINCE_VERSION ) {
730         wl_pointer_release ( self->pointer );
731     }
732     else{
733         wl_pointer_destroy ( self->pointer );
734     }
735 
736     self->pointer = NULL;
737 }
738 
739 static void
wayland_seat_release(wayland_seat * self)740 wayland_seat_release ( wayland_seat *self )
741 {
742     wayland_keyboard_release ( self );
743     wayland_pointer_release ( self );
744 
745     if ( wl_seat_get_version ( self->seat ) >= WL_SEAT_RELEASE_SINCE_VERSION ) {
746         wl_seat_release ( self->seat );
747     }
748     else{
749         wl_seat_destroy ( self->seat );
750     }
751 
752     g_hash_table_remove ( wayland->seats, self->seat );
753 
754     g_free ( self );
755 }
756 
757 static void
wayland_seat_capabilities(void * data,struct wl_seat * seat,uint32_t capabilities)758 wayland_seat_capabilities ( void *data, struct wl_seat *seat, uint32_t capabilities )
759 {
760     wayland_seat *self = data;
761 
762     if ( ( capabilities & WL_SEAT_CAPABILITY_KEYBOARD ) && ( self->keyboard == NULL ) ) {
763         self->keyboard = wl_seat_get_keyboard ( self->seat );
764         wl_keyboard_add_listener ( self->keyboard, &wayland_keyboard_listener, self );
765     }
766     else if ( ( !( capabilities & WL_SEAT_CAPABILITY_POINTER ) ) && ( self->keyboard != NULL ) ) {
767         wayland_keyboard_release ( self );
768     }
769 
770     if ( ( capabilities & WL_SEAT_CAPABILITY_POINTER ) && ( self->pointer == NULL ) ) {
771         self->pointer = wl_seat_get_pointer ( self->seat );
772         wl_pointer_add_listener ( self->pointer, &wayland_pointer_listener, self );
773     }
774     else if ( ( !( capabilities & WL_SEAT_CAPABILITY_POINTER ) ) && ( self->pointer != NULL ) ) {
775         wayland_pointer_release ( self );
776     }
777 }
778 
779 static void
wayland_seat_name(void * data,struct wl_seat * seat,const char * name)780 wayland_seat_name ( void *data, struct wl_seat *seat, const char *name )
781 {
782     wayland_seat *self = data;
783 
784     if ( self->name != NULL ) {
785         g_hash_table_remove ( wayland->seats_by_name, self->name );
786     }
787     self->name = g_strdup ( name );
788     g_hash_table_insert ( wayland->seats_by_name, self->name, self );
789 }
790 
791 static const struct wl_seat_listener wayland_seat_listener = {
792     .capabilities = wayland_seat_capabilities,
793     .name         = wayland_seat_name,
794 };
795 
796 static void
wayland_output_release(wayland_output * self)797 wayland_output_release ( wayland_output *self )
798 {
799     if ( wl_output_get_version ( self->output ) >= WL_OUTPUT_RELEASE_SINCE_VERSION ) {
800         wl_output_release ( self->output );
801     }
802     else{
803         wl_output_destroy ( self->output );
804     }
805 
806     g_hash_table_remove ( wayland->outputs, self->output );
807 
808     g_free ( self );
809 }
810 
811 static void
wayland_output_done(void * data,struct wl_output * output)812 wayland_output_done ( void *data, struct wl_output *output )
813 {
814 }
815 
816 static void
wayland_output_geometry(void * data,struct wl_output * output,int32_t x,int32_t y,int32_t width,int32_t height,int32_t subpixel,const char * make,const char * model,int32_t transform)817 wayland_output_geometry ( void *data, struct wl_output *output, int32_t x, int32_t y, int32_t width, int32_t height, int32_t subpixel, const char *make, const char *model, int32_t transform )
818 {
819 }
820 
821 static void
wayland_output_mode(void * data,struct wl_output * output,enum wl_output_mode flags,int32_t width,int32_t height,int32_t refresh)822 wayland_output_mode ( void *data, struct wl_output *output, enum wl_output_mode flags, int32_t width, int32_t height, int32_t refresh )
823 {
824 }
825 
826 static void
wayland_output_scale(void * data,struct wl_output * output,int32_t scale)827 wayland_output_scale ( void *data, struct wl_output *output, int32_t scale )
828 {
829     wayland_output *self = data;
830 
831     self->scale = scale;
832 }
833 
834 static const struct wl_output_listener wayland_output_listener = {
835     .geometry = wayland_output_geometry,
836     .mode     = wayland_output_mode,
837     .scale    = wayland_output_scale,
838     .done     = wayland_output_done,
839 };
840 
841 static const char * const              wayland_cursor_names[] = {
842     "left_ptr",
843     "default",
844     "top_left_arrow",
845     "left-arrow",
846     NULL
847 };
848 
849 static void
wayland_registry_handle_global(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)850 wayland_registry_handle_global ( void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version )
851 {
852     if ( g_strcmp0 ( interface, wl_compositor_interface.name ) == 0 ) {
853         wayland->global_names[WAYLAND_GLOBAL_COMPOSITOR] = name;
854         wayland->compositor                              = wl_registry_bind ( registry, name, &wl_compositor_interface, MIN ( version, WL_COMPOSITOR_INTERFACE_VERSION ) );
855     }
856     else if ( g_strcmp0 ( interface, zwlr_layer_shell_v1_interface.name ) == 0 ) {
857         wayland->global_names[WAYLAND_GLOBAL_LAYER_SHELL] = name;
858         wayland->layer_shell                              = wl_registry_bind ( registry, name, &zwlr_layer_shell_v1_interface, MIN ( version, WL_LAYER_SHELL_INTERFACE_VERSION ) );
859     }
860     else if ( g_strcmp0 ( interface, wl_shm_interface.name ) == 0 ) {
861         wayland->global_names[WAYLAND_GLOBAL_SHM] = name;
862         wayland->shm                              = wl_registry_bind ( registry, name, &wl_shm_interface, MIN ( version, WL_SHM_INTERFACE_VERSION ) );
863     }
864     else if ( g_strcmp0 ( interface, wl_seat_interface.name ) == 0 ) {
865         wayland_seat *seat = g_new0 ( wayland_seat, 1 );
866         seat->context     = wayland;
867         seat->global_name = name;
868         seat->seat        = wl_registry_bind ( registry, name, &wl_seat_interface, MIN ( version, WL_SEAT_INTERFACE_VERSION ) );
869         g_hash_table_insert ( wayland->seats, seat->seat, seat );
870 
871         wl_seat_add_listener ( seat->seat, &wayland_seat_listener, seat );
872     }
873     else if ( g_strcmp0 ( interface, wl_output_interface.name ) == 0 ) {
874         wayland_output *output = g_new0 ( wayland_output, 1 );
875         output->context     = wayland;
876         output->global_name = name;
877         output->output      = wl_registry_bind ( registry, name, &wl_output_interface, MIN ( version, WL_OUTPUT_INTERFACE_VERSION ) );
878         output->scale       = 1;
879 
880         g_hash_table_insert ( wayland->outputs, output->output, output );
881 
882         wl_output_add_listener ( output->output, &wayland_output_listener, output );
883     }
884 }
885 
886 static void
wayland_registry_handle_global_remove(void * data,struct wl_registry * registry,uint32_t name)887 wayland_registry_handle_global_remove ( void *data, struct wl_registry *registry, uint32_t name )
888 {
889     wayland_global_name i;
890     for ( i = 0; i < _WAYLAND_GLOBAL_SIZE; ++i ) {
891         if ( wayland->global_names[i] != name ) {
892             continue;
893         }
894         wayland->global_names[i] = 0;
895 
896         switch ( i )
897         {
898         case WAYLAND_GLOBAL_COMPOSITOR:
899             wl_compositor_destroy ( wayland->compositor );
900             wayland->compositor = NULL;
901             break;
902         case WAYLAND_GLOBAL_LAYER_SHELL:
903             zwlr_layer_shell_v1_destroy ( wayland->layer_shell );
904             wayland->layer_shell = NULL;
905             break;
906         case WAYLAND_GLOBAL_SHM:
907             wl_shm_destroy ( wayland->shm );
908             wayland->shm = NULL;
909             break;
910         case _WAYLAND_GLOBAL_SIZE:
911             g_assert_not_reached ();
912         }
913         return;
914     }
915     if ( ( wayland->cursor.theme != NULL ) && ( ( wayland->compositor == NULL ) || ( wayland->shm == NULL ) ) ) {
916         if ( wayland->cursor.frame_cb != NULL ) {
917             wl_callback_destroy ( wayland->cursor.frame_cb );
918         }
919         wayland->cursor.frame_cb = NULL;
920 
921         wl_surface_destroy ( wayland->cursor.surface );
922         wl_cursor_theme_destroy ( wayland->cursor.theme );
923         wayland->cursor.surface = NULL;
924         wayland->cursor.image   = NULL;
925         wayland->cursor.cursor  = NULL;
926         wayland->cursor.theme   = NULL;
927     }
928 
929     GHashTableIter iter;
930 
931     wayland_seat   *seat;
932     g_hash_table_iter_init ( &iter, wayland->seats );
933     while ( g_hash_table_iter_next ( &iter, NULL, (gpointer *) &seat ) ) {
934         if ( seat->global_name != name ) {
935             continue;
936         }
937 
938         g_hash_table_iter_remove ( &iter );
939         wayland_seat_release ( seat );
940         return;
941     }
942 
943     wayland_output *output;
944     g_hash_table_iter_init ( &iter, wayland->outputs );
945     while ( g_hash_table_iter_next ( &iter, NULL, (gpointer *) &output ) ) {
946         if ( output->global_name != name ) {
947             continue;
948         }
949 
950         g_hash_table_iter_remove ( &iter );
951         wayland_output_release ( output );
952         return;
953     }
954 }
955 
956 static const struct wl_registry_listener wayland_registry_listener = {
957     .global        = wayland_registry_handle_global,
958     .global_remove = wayland_registry_handle_global_remove,
959 };
960 
wayland_layer_shell_surface_configure(void * data,struct zwlr_layer_surface_v1 * surface,uint32_t serial,uint32_t width,uint32_t height)961 static void wayland_layer_shell_surface_configure ( void *data,
962                                                     struct zwlr_layer_surface_v1 *surface,
963                                                     uint32_t serial,
964                                                     uint32_t width,
965                                                     uint32_t height )
966 {
967     wayland->layer_width  = width;
968     wayland->layer_height = height;
969     zwlr_layer_surface_v1_ack_configure ( surface, serial );
970 }
971 
wayland_layer_shell_surface_closed(void * data,struct zwlr_layer_surface_v1 * surface)972 static void wayland_layer_shell_surface_closed ( void *data,
973                                                  struct zwlr_layer_surface_v1 *surface )
974 {
975     zwlr_layer_surface_v1_destroy ( surface );
976     wl_surface_destroy ( wayland->surface );
977     wayland->surface = NULL;
978 }
979 
980 static const struct zwlr_layer_surface_v1_listener wayland_layer_shell_surface_listener = {
981     .configure = wayland_layer_shell_surface_configure,
982     .closed    = wayland_layer_shell_surface_closed,
983 };
984 
985 static gboolean
wayland_error(gpointer user_data)986 wayland_error ( gpointer user_data )
987 {
988     g_main_loop_quit ( wayland->main_loop );
989     return G_SOURCE_REMOVE;
990 }
991 
992 static gboolean
wayland_display_setup(GMainLoop * main_loop,NkBindings * bindings)993 wayland_display_setup ( GMainLoop *main_loop, NkBindings *bindings )
994 {
995     wayland->main_loop = main_loop;
996 
997     char *display = ( char *) g_getenv ( "WAYLAND_DISPLAY" );
998     wayland->main_loop_source = g_water_wayland_source_new ( NULL, display );
999     if ( wayland->main_loop_source == NULL ) {
1000         g_warning ( "Could not connect to the Wayland compositor" );
1001         return FALSE;
1002     }
1003 
1004     g_water_wayland_source_set_error_callback ( wayland->main_loop_source, wayland_error, NULL, NULL );
1005 
1006     wayland->buffer_count = 3;
1007     wayland->scale        = 1;
1008 
1009     wayland->outputs       = g_hash_table_new ( g_direct_hash, g_direct_equal );
1010     wayland->seats         = g_hash_table_new ( g_direct_hash, g_direct_equal );
1011     wayland->seats_by_name = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL );
1012 
1013     wayland->display  = g_water_wayland_source_get_display ( wayland->main_loop_source );
1014     wayland->registry = wl_display_get_registry ( wayland->display );
1015     wl_registry_add_listener ( wayland->registry, &wayland_registry_listener, NULL );
1016     wl_display_roundtrip ( wayland->display );
1017 
1018     if ( wayland->compositor == NULL || wayland->shm == NULL || g_hash_table_size ( wayland->outputs ) == 0 || g_hash_table_size ( wayland->seats ) == 0 ) {
1019         g_error ( "Could not connect to wayland compositor" );
1020         return FALSE;
1021     }
1022     if ( wayland->layer_shell == NULL ) {
1023         g_error ( "Rofi on wayland requires support for the layer shell protocol" );
1024         return FALSE;
1025     }
1026 
1027     wayland->cursor.theme = wl_cursor_theme_load ( wayland->cursor.theme_name, 32, wayland->shm );
1028     if ( wayland->cursor.theme != NULL ) {
1029         const char * const *cname = (const char * const *) wayland->cursor.name;
1030         for ( cname = ( cname != NULL ) ? cname : wayland_cursor_names; ( wayland->cursor.cursor == NULL ) && ( *cname != NULL ); ++cname ) {
1031             wayland->cursor.cursor = wl_cursor_theme_get_cursor ( wayland->cursor.theme, *cname );
1032         }
1033         if ( wayland->cursor.cursor == NULL ) {
1034             wl_cursor_theme_destroy ( wayland->cursor.theme );
1035             wayland->cursor.theme = NULL;
1036         }
1037         else{
1038             wayland->cursor.surface = wl_compositor_create_surface ( wayland->compositor );
1039         }
1040     }
1041 
1042     wayland->surface = wl_compositor_create_surface ( wayland->compositor );
1043 
1044     wayland->bindings_seat = nk_bindings_seat_new ( bindings, XKB_CONTEXT_NO_FLAGS );
1045 
1046     wayland->wlr_surface = zwlr_layer_shell_v1_get_layer_surface ( wayland->layer_shell, wayland->surface, NULL, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "rofi" );
1047 
1048     // Set size zero and anchor on all corners to get the usable screen size
1049     // see https://github.com/swaywm/wlroots/pull/2422
1050     zwlr_layer_surface_v1_set_anchor ( wayland->wlr_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT );
1051     zwlr_layer_surface_v1_set_size ( wayland->wlr_surface, 0, 0 );
1052     zwlr_layer_surface_v1_set_keyboard_interactivity ( wayland->wlr_surface, 1 );
1053     zwlr_layer_surface_v1_add_listener ( wayland->wlr_surface, &wayland_layer_shell_surface_listener, NULL );
1054 
1055     wl_surface_add_listener ( wayland->surface, &wayland_surface_interface, wayland );
1056     wl_surface_commit ( wayland->surface );
1057     wl_display_roundtrip ( wayland->display );
1058     wayland_frame_callback ( wayland, wayland->frame_cb, 0 );
1059 
1060     return TRUE;
1061 }
1062 
1063 static gboolean
wayland_display_late_setup(void)1064 wayland_display_late_setup ( void )
1065 {
1066     return TRUE;
1067 }
1068 
1069 gboolean
display_get_surface_dimensions(int * width,int * height)1070 display_get_surface_dimensions ( int *width, int *height )
1071 {
1072     if ( wayland->layer_width != 0 ) {
1073         if ( width != NULL ) {
1074             *width = wayland->layer_width;
1075         }
1076         if ( height != NULL ) {
1077             *height = wayland->layer_height;
1078         }
1079         return TRUE;
1080     }
1081     return FALSE;
1082 }
1083 
1084 void
display_set_surface_dimensions(int width,int height,int loc)1085 display_set_surface_dimensions ( int width, int height, int loc )
1086 {
1087     wayland->layer_width  = width;
1088     wayland->layer_height = height;
1089     zwlr_layer_surface_v1_set_size ( wayland->wlr_surface, width, height );
1090 
1091     uint32_t wlr_anchor = 0;
1092     switch ( loc )
1093     {
1094     case WL_NORTH_WEST:
1095         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1096         break;
1097     case WL_NORTH:
1098         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1099         break;
1100     case WL_NORTH_EAST:
1101         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1102         break;
1103     case WL_EAST:
1104         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
1105         break;
1106     case WL_SOUTH_EAST:
1107         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
1108         break;
1109     case WL_SOUTH:
1110         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
1111         break;
1112     case WL_SOUTH_WEST:
1113         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
1114         break;
1115     case WL_WEST:
1116         wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
1117         break;
1118     case WL_CENTER:
1119     default:
1120         break;
1121     }
1122 
1123     if ( height == 0 ) {
1124         wlr_anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1125     }
1126     if ( width == 0 ) {
1127         wlr_anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
1128     }
1129 
1130     zwlr_layer_surface_v1_set_anchor ( wayland->wlr_surface, wlr_anchor );
1131 }
1132 
1133 static void
wayland_display_early_cleanup(void)1134 wayland_display_early_cleanup ( void )
1135 {
1136 }
1137 
1138 static void
wayland_display_cleanup(void)1139 wayland_display_cleanup ( void )
1140 {
1141     if ( wayland->main_loop_source == NULL ) {
1142         return;
1143     }
1144 
1145     if ( wayland->surface != NULL ) {
1146         wl_surface_destroy ( wayland->surface );
1147     }
1148 
1149     nk_bindings_seat_free ( wayland->bindings_seat );
1150     g_hash_table_unref ( wayland->seats_by_name );
1151     g_hash_table_unref ( wayland->seats );
1152     g_hash_table_unref ( wayland->outputs );
1153     wl_registry_destroy ( wayland->registry );
1154     wl_display_flush ( wayland->display );
1155     g_water_wayland_source_free ( wayland->main_loop_source );
1156 }
1157 
1158 static void
wayland_display_dump_monitor_layout(void)1159 wayland_display_dump_monitor_layout ( void )
1160 {
1161 }
1162 
1163 static void
wayland_display_startup_notification(RofiHelperExecuteContext * context,GSpawnChildSetupFunc * child_setup,gpointer * user_data)1164 wayland_display_startup_notification ( RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data )
1165 {
1166 }
1167 
wayland_display_monitor_active(workarea * mon)1168 static int wayland_display_monitor_active ( workarea *mon )
1169 {
1170     // TODO: do something?
1171     return FALSE;
1172 }
1173 
wayland_display_view_proxy(void)1174 static const struct _view_proxy* wayland_display_view_proxy ( void )
1175 {
1176     return wayland_view_proxy;
1177 }
1178 
wayland_display_scale(void)1179 static guint wayland_display_scale ( void )
1180 {
1181     return wayland->scale;
1182 }
1183 
1184 static display_proxy  display_ = {
1185     .setup                = wayland_display_setup,
1186     .late_setup           = wayland_display_late_setup,
1187     .early_cleanup        = wayland_display_early_cleanup,
1188     .cleanup              = wayland_display_cleanup,
1189     .dump_monitor_layout  = wayland_display_dump_monitor_layout,
1190     .startup_notification = wayland_display_startup_notification,
1191     .monitor_active       = wayland_display_monitor_active,
1192     .scale                = wayland_display_scale,
1193 
1194     .view                 = wayland_display_view_proxy,
1195 };
1196 
1197 display_proxy * const wayland_proxy = &display_;
1198