]> Pileus Git - wmpus/blob - sys-xwl.c
01d43b47c5e06bdd5e3287c92a4ecd45976e4779
[wmpus] / sys-xwl.c
1 /*
2  * Copyright (c) 2014, Andy Spencer <andy753421@gmail.com>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  */
15
16 #define _GNU_SOURCE
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <sys/mman.h>
23
24 #include <xkbcommon/xkbcommon.h>
25 #include <wayland-server.h>
26 #include <wayland-client.h>
27
28 #include <gtk/gtk.h>
29
30 #include "util.h"
31 #include "conf.h"
32 #include "sys.h"
33 #include "wm.h"
34
35 /* Internal structures */
36 struct win_sys {
37         win_t *win;
38 };
39
40 typedef struct {
41         uint8_t *mem;
42         size_t   size;
43 } sys_pool_t;
44
45 typedef struct {
46         sys_pool_t      *pool;
47         uint8_t         *mem;
48         cairo_surface_t *surface;
49 } sys_buf_t;
50
51 struct wl_resource *output;
52
53 sys_pool_t *gdata[10];
54 int         gidx;
55
56 /* Global data */
57 static struct wl_display    *display;
58 static struct wl_event_loop *events;
59
60 static GtkWidget            *window;
61 static sys_buf_t            *buffer;
62
63 /*****************
64  * Gtk Callbacks *
65  *****************/
66
67 static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
68 {
69         printf("on_destroy\n");
70         sys_exit();
71 }
72
73 static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
74 {
75         printf(g_ascii_isprint(event->keyval)
76                 ? "on_key: '%c'\n"
77                 : "on_key: 0x%X\n",
78                 event->keyval);
79         if (event->keyval == GDK_KEY_q)
80                 sys_exit();
81         if (event->keyval == GDK_KEY_t)
82                 g_spawn_command_line_async("st-wl", NULL);
83         return TRUE;
84 }
85
86 static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
87 {
88         printf("on_button\n");
89         return TRUE;
90 }
91
92 static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
93 {
94         //printf("on_motion\n");
95         return TRUE;
96 }
97
98 static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
99 {
100         printf("on_draw\n");
101
102         if (buffer) {
103                 cairo_surface_mark_dirty(buffer->surface);
104                 cairo_set_source_surface(cairo, buffer->surface, 10, 10);
105                 cairo_paint(cairo);
106         }
107
108         cairo_set_source_rgb(cairo, 1, 1, 1);
109         cairo_arc(cairo, 150, 150, 50, 0, 2*G_PI);
110         cairo_fill(cairo);
111
112         //int gi = 0, mi;
113         //FILE *fd = fopen("/tmp/mem.txt", "w+");
114         //for (gi = 0; gi < 10; gi++) {
115         //      mi = 0;
116         //      while (gdata[gi] && (mi+32) < gdata[gi]->size) {
117         //              fprintf(fd, "%d %p %08x: ", gi, gdata[gi]->mem, mi);
118         //              for (int i = 0; i < 16; mi++, i += 2)
119         //                      fprintf(fd, "%02hhx%02hhx ",
120         //                              gdata[gi]->mem[mi+0],
121         //                              gdata[gi]->mem[mi+1]);
122         //              fprintf(fd, "\n");
123         //      }
124         //      fprintf(fd, "\n");
125         //}
126         //printf("\n");
127         //fclose(fd);
128
129         return TRUE;
130 }
131
132 static gboolean on_wayland(gpointer user_data)
133 {
134         // TODO - convert to polled execution
135         wl_display_flush_clients(display);
136         wl_event_loop_dispatch(events, 0);
137         return TRUE;
138 }
139
140 /*********************
141  * Wayland Callbacks *
142  *********************/
143
144 #if 0
145 static void new_window(void)
146 {
147         printf("new_window\n");
148 }
149
150 static void new_screen(void)
151 {
152         printf("new_screen\n");
153 }
154 #endif
155
156 /****************************
157  * Wayland Buffer Interface *
158  ****************************/
159 static struct wl_buffer_interface buffer_iface = {
160         .destroy  = NULL,
161 };
162
163 /***********************************
164  * Wayland Shared Memory Interface *
165  ***********************************/
166
167 /* Shm Pool */
168 static void pool_create_buffer(struct wl_client *cli, struct wl_resource *pool,
169                 uint32_t id, int32_t offset, int32_t width, int32_t height,
170                 int32_t stride, uint32_t format)
171 {
172         sys_buf_t  *buf  = new0(sys_buf_t);
173         buf->pool = wl_resource_get_user_data(pool);
174         buf->mem  = buf->pool->mem + offset;
175
176         printf("pool_create_buffer - %dx%d %p+%d : %d,%d,%d\n",
177                         width, height, buf->pool->mem, offset, id, stride, format);
178
179         if (offset > buf->pool->size || offset < 0)
180         {
181                 printf("\n\nerror\n\n");
182                 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_STRIDE,
183                                 "offset is too big or negative");
184                 return;
185         }
186
187         cairo_format_t cf =
188                 format == WL_SHM_FORMAT_ARGB8888 ? CAIRO_FORMAT_ARGB32 :
189                 format == WL_SHM_FORMAT_XRGB8888 ? CAIRO_FORMAT_RGB24  : CAIRO_FORMAT_INVALID;
190
191         buf->surface = cairo_image_surface_create_for_data(buf->mem, cf, width, height, stride);
192
193         struct wl_resource *res = wl_resource_create(cli, &wl_buffer_interface,
194                                         wl_resource_get_version(pool), id);
195         wl_resource_set_implementation(res, &buffer_iface, buf, NULL);
196 }
197
198 static void pool_destroy(struct wl_client *cli, struct wl_resource *pool)
199 {
200         printf("pool_destroy\n");
201 }
202
203 static void pool_resize(struct wl_client *cli, struct wl_resource *pool,
204                 int32_t size)
205 {
206         printf("[   WMPUS   ] pool_resize - %d\n", size);
207         sys_pool_t *data = wl_resource_get_user_data(pool);
208         void *ptr = mremap(data->mem, data->size, size, MREMAP_MAYMOVE);
209         if (ptr == MAP_FAILED)
210         {
211                 printf("\n\nerror\n\n");
212                 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_FD,
213                                 "mremap failed: %s", strerror(errno));
214                 return;
215         }
216         data->mem  = ptr;
217         data->size = size;
218         gdata[gidx++] = data;
219 }
220
221 static struct wl_shm_pool_interface pool_iface = {
222         .create_buffer = &pool_create_buffer,
223         .destroy       = &pool_destroy,
224         .resize        = &pool_resize,
225 };
226
227 /* Shm */
228 static void shm_create_pool(struct wl_client *cli, struct wl_resource *shm,
229                 uint32_t id, int32_t fd, int32_t size)
230 {
231         printf("shm_create_pool - #%d %d %d\n", id, fd, size);
232
233         sys_pool_t *data = new0(sys_pool_t);
234
235         struct wl_resource *res = wl_resource_create(cli, &wl_shm_pool_interface,
236                                         wl_resource_get_version(shm), id);
237         wl_resource_set_implementation(res, &pool_iface, data, NULL);
238
239         data->mem  = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
240         data->size = size;
241         gdata[gidx++] = data;
242 }
243
244 static struct wl_shm_interface shm_iface = {
245         .create_pool = shm_create_pool,
246 };
247
248 /**************************
249  * Wayland Seat Interface *
250  **************************/
251
252 /* Pointer */
253 static struct wl_pointer_interface pointer_iface = {
254         .set_cursor = NULL,
255         .release    = NULL,
256 };
257
258 /* Keyboard */
259 static struct wl_keyboard_interface keyboard_iface = {
260         .release    = NULL,
261 };
262
263 /* Touch */
264 static struct wl_touch_interface touch_iface = {
265         .release    = NULL,
266 };
267
268 /* Seat */
269 static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat,
270                 uint32_t id) {
271         printf("seat_get_pointer\n");
272         struct wl_resource *res = wl_resource_create(cli, &wl_pointer_interface, 3, id);
273         wl_resource_set_implementation(res, &pointer_iface, NULL, NULL);
274 }
275
276 static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat,
277                 uint32_t id) {
278         printf("seat_get_keyboard\n");
279         struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 3, id);
280         wl_resource_set_implementation(res, &keyboard_iface, NULL, NULL);
281 }
282
283 static void seat_get_touch(struct wl_client *cli, struct wl_resource *seat,
284                 uint32_t id) {
285         printf("seat_get_touch\n");
286         struct wl_resource *res = wl_resource_create(cli, &wl_touch_interface, 3, id);
287         wl_resource_set_implementation(res, &touch_iface, NULL, NULL);
288 }
289
290 static struct wl_seat_interface seat_iface = {
291         .get_pointer  = &seat_get_pointer,
292         .get_keyboard = &seat_get_keyboard,
293         .get_touch    = &seat_get_touch,
294 };
295
296 /*****************************************
297  * Wayland Data Device Manager Interface *
298  *****************************************/
299
300 /* Data Offer */
301 static struct wl_data_offer_interface doff_iface = {
302         .accept        = NULL,
303         .receive       = NULL,
304         .destroy       = NULL,
305 };
306
307 /* Data Source */
308 static struct wl_data_source_interface dsrc_iface = {
309         .offer         = NULL,
310         .destroy       = NULL,
311 };
312
313 /* Data Device */
314 static struct wl_data_device_interface ddev_iface = {
315         .start_drag    = NULL,
316         .set_selection = NULL,
317 };
318
319 /* Data Device Manager */
320 static void ddm_create_data_source(struct wl_client *cli, struct wl_resource *ddm,
321                 uint32_t id)
322 {
323         printf("ddm_create_data_source\n");
324         struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
325         wl_resource_set_implementation(res, &dsrc_iface, NULL, NULL);
326 }
327
328 static void ddm_get_data_device(struct wl_client *cli, struct wl_resource *ddm,
329                 uint32_t id, struct wl_resource *seat)
330 {
331         printf("ddm_get_data_device\n");
332         struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
333         wl_resource_set_implementation(res, &ddev_iface, NULL, NULL);
334 }
335
336 static struct wl_data_device_manager_interface ddm_iface = {
337         .create_data_source = &ddm_create_data_source,
338         .get_data_device    = &ddm_get_data_device,
339 };
340
341 /**************************************
342  * Wayland Shell/Compositor Interface *
343  **************************************/
344
345 /* Callback */
346 static void frame_callback(struct wl_resource *res)
347 {
348         printf("frame_callback\n");
349 }
350
351 /* Surface */
352 static void surface_destroy(struct wl_client *cli, struct wl_resource *res)
353 {
354         printf("surface_destroy\n");
355 }
356
357 static void surface_attach(struct wl_client *cli, struct wl_resource *res,
358                 struct wl_resource *buf, int32_t x, int32_t y)
359 {
360         sys_buf_t *data = wl_resource_get_user_data(buf);
361         printf("surface_attach - %p\n", data->pool->mem);
362         buffer = data;
363 }
364
365 static void surface_damage(struct wl_client *cli, struct wl_resource *res,
366                    int32_t x, int32_t y, int32_t width, int32_t height)
367 {
368         printf("surface_damage\n");
369 }
370
371 static void surface_frame(struct wl_client *cli, struct wl_resource *res,
372                 uint32_t id)
373 {
374         printf("surface_frame\n");
375         struct wl_resource *cb = wl_resource_create(cli, &wl_callback_interface, 1, id);
376         wl_resource_set_implementation(cb, NULL, NULL, &frame_callback);
377         wl_callback_send_done(cb, time(NULL));
378 }
379
380 static void surface_set_opaque_region(struct wl_client *cli, struct wl_resource *res,
381                 struct wl_resource *reg)
382 {
383         printf("surface_set_opaque_region\n");
384 }
385
386 static void surface_set_input_region(struct wl_client *cli, struct wl_resource *res,
387                 struct wl_resource *reg)
388 {
389         printf("surface_set_input_region\n");
390 }
391
392 static void surface_commit(struct wl_client *cli, struct wl_resource *res)
393 {
394         printf("surface_commit\n");
395         gtk_widget_queue_draw(window);
396 }
397
398 static void surface_set_buffer_transform(struct wl_client *cli, struct wl_resource *res,
399                 int32_t transform)
400 {
401         printf("surface_set_buffer_transform\n");
402 }
403
404 static void surface_set_buffer_scale(struct wl_client *cli, struct wl_resource *res,
405                 int32_t scale)
406 {
407         printf("surface_set_buffer_scale\n");
408 }
409
410 static struct wl_surface_interface surface_iface = {
411         .destroy              = surface_destroy,
412         .attach               = surface_attach,
413         .damage               = surface_damage,
414         .frame                = surface_frame,
415         .set_opaque_region    = surface_set_opaque_region,
416         .set_input_region     = surface_set_input_region,
417         .commit               = surface_commit,
418         .set_buffer_transform = surface_set_buffer_transform,
419         .set_buffer_scale     = surface_set_buffer_scale,
420 };
421
422 /* Region */
423 static void region_destroy(struct wl_client *cli, struct wl_resource *res)
424 {
425         printf("region_destroy\n");
426 }
427
428 static void region_add(struct wl_client *cli, struct wl_resource *res,
429                 int32_t x, int32_t y, int32_t width, int32_t height)
430 {
431         printf("region_add\n");
432 }
433
434 static void region_subtract(struct wl_client *cli, struct wl_resource *res,
435                      int32_t x, int32_t y, int32_t width, int32_t height)
436 {
437         printf("region_subtract\n");
438 }
439
440 static struct wl_region_interface region_iface = {
441         .destroy  = region_destroy,
442         .add      = region_add,
443         .subtract = region_subtract,
444 };
445
446 /* Compositor */
447 static void comp_create_surface(struct wl_client *cli, struct wl_resource *comp,
448                 uint32_t id)
449 {
450         printf("comp_create_surface\n");
451         struct wl_resource *res = wl_resource_create(cli, &wl_surface_interface, 3, id);
452         wl_resource_set_implementation(res, &surface_iface, NULL, NULL);
453         wl_surface_send_enter(res, output);
454 }
455
456 static void comp_create_region(struct wl_client *cli, struct wl_resource *comp,
457                 uint32_t id)
458 {
459         printf("comp_create_region\n");
460         struct wl_resource *res = wl_resource_create(cli, &wl_region_interface, 1, id);
461         wl_resource_set_implementation(res, &region_iface, NULL, NULL);
462 }
463
464 static struct wl_compositor_interface comp_iface = {
465         .create_surface = comp_create_surface,
466         .create_region  = comp_create_region,
467 };
468
469 /* Shell Surface */
470 static void ssurface_pong(struct wl_client *cli, struct wl_resource *res,
471                 uint32_t serial)
472 {
473         printf("ssurface_pong\n");
474 }
475
476 static void ssurface_move(struct wl_client *cli, struct wl_resource *res,
477                 struct wl_resource *seat, uint32_t serial)
478 {
479         printf("ssurface_move\n");
480 }
481
482 static void ssurface_resize(struct wl_client *cli, struct wl_resource *res,
483                 struct wl_resource *seat, uint32_t serial, uint32_t edges)
484 {
485         printf("ssurface_resize\n");
486 }
487
488 static void ssurface_set_toplevel(struct wl_client *cli, struct wl_resource *res)
489 {
490         printf("ssurface_set_toplevel\n");
491 }
492
493 static void ssurface_set_transient(struct wl_client *cli, struct wl_resource *res,
494                 struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags)
495 {
496         printf("ssurface_set_transient\n");
497 }
498
499 static void ssurface_set_fullscreen(struct wl_client *cli, struct wl_resource *res,
500                 uint32_t method, uint32_t framerate, struct wl_resource *out)
501 {
502         printf("ssurface_set_fullscreen\n");
503 }
504
505 static void ssurface_set_popup(struct wl_client *cli, struct wl_resource *res,
506                 struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
507                 int32_t x, int32_t y, uint32_t flags)
508 {
509         printf("ssurface_set_popup\n");
510 }
511
512 static void ssurface_set_maximized(struct wl_client *cli, struct wl_resource *res,
513                 struct wl_resource *out)
514 {
515         printf("ssurface_set_maximized\n");
516 }
517
518 static void ssurface_set_title(struct wl_client *cli, struct wl_resource *res,
519                 const char *title)
520 {
521         printf("ssurface_set_title\n");
522 }
523
524 static void ssurface_set_class(struct wl_client *cli, struct wl_resource *res,
525                 const char *class)
526 {
527         printf("ssurface_set_class\n");
528 }
529
530 static struct wl_shell_surface_interface ssurface_iface = {
531         .pong           = ssurface_pong,
532         .move           = ssurface_move,
533         .resize         = ssurface_resize,
534         .set_toplevel   = ssurface_set_toplevel,
535         .set_transient  = ssurface_set_transient,
536         .set_fullscreen = ssurface_set_fullscreen,
537         .set_popup      = ssurface_set_popup,
538         .set_maximized  = ssurface_set_maximized,
539         .set_title      = ssurface_set_title,
540         .set_class      = ssurface_set_class,
541 };
542
543 /* Shell */
544 static void shell_get_shell_surface(struct wl_client *cli, struct wl_resource *shell, uint32_t id,
545                               struct wl_resource *sfc) {
546         printf("shell_get_shell_surface\n");
547         struct wl_resource *res = wl_resource_create(cli, &wl_shell_surface_interface, 1, id);
548         wl_resource_set_implementation(res, &ssurface_iface, NULL, NULL);
549 }
550
551 static struct wl_shell_interface shell_iface = {
552         .get_shell_surface = shell_get_shell_surface,
553 };
554
555 /*******************
556  * Wayland Globals *
557  *******************/
558
559 /* References */
560 static struct wl_global *ref_shm;
561 static struct wl_global *ref_output;
562 static struct wl_global *ref_seat;
563 static struct wl_global *ref_ddm;
564 static struct wl_global *ref_comp;
565 static struct wl_global *ref_shell;
566
567 /* Bind functions */
568 static void bind_shm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
569 {
570         printf("bind_shm\n");
571
572         if (version > 1)
573                 version = 1;
574
575         struct wl_resource *res = wl_resource_create(cli, &wl_shm_interface, version, id);
576         wl_resource_set_implementation(res, &shm_iface, NULL, NULL);
577
578         wl_shm_send_format(res, WL_SHM_FORMAT_XRGB8888);
579         wl_shm_send_format(res, WL_SHM_FORMAT_ARGB8888);
580 }
581
582 static void bind_output(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
583 {
584         printf("bind_output\n");
585
586         struct wl_resource *res = wl_resource_create(cli, &wl_output_interface, version, id);
587         output = res;
588
589         wl_output_send_geometry(res,
590                         0, 0, 330, 210,              // x/y (px), w/h (mm)
591                         WL_OUTPUT_SUBPIXEL_UNKNOWN,  // subpixel format
592                         "unknown", "unknown",        // make, model
593                         WL_OUTPUT_TRANSFORM_NORMAL); // rotatoin
594         //wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 800,  600,  60);
595         //wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1024, 768,  60);
596         wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1280, 1024, 60);
597         //wl_output_send_done(res);
598 }
599
600 static void bind_seat(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
601 {
602         printf("bind_seat\n");
603
604         struct wl_resource *res = wl_resource_create(cli, &wl_seat_interface, version, id);
605         wl_resource_set_implementation(res, &seat_iface, NULL, NULL);
606
607         wl_seat_send_capabilities(res,
608                         WL_SEAT_CAPABILITY_KEYBOARD |
609                         WL_SEAT_CAPABILITY_POINTER);
610 }
611
612 static void bind_ddm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
613 {
614         printf("bind_ddm\n");
615
616         struct wl_resource *res = wl_resource_create(cli, &wl_data_device_manager_interface, version, id);
617         wl_resource_set_implementation(res, &ddm_iface, NULL, NULL);
618 }
619
620 static void bind_comp(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
621 {
622         printf("bind_comp\n");
623         struct wl_resource *res = wl_resource_create(cli, &wl_compositor_interface, version, id);
624         wl_resource_set_implementation(res, &comp_iface, NULL, NULL);
625 }
626
627 static void bind_shell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
628 {
629         printf("bind_shell\n");
630         struct wl_resource *res = wl_resource_create(cli, &wl_shell_interface, version, id);
631         wl_resource_set_implementation(res, &shell_iface, NULL, NULL);
632 }
633
634 /********************
635  * System functions *
636  ********************/
637 void sys_move(win_t *win, int x, int y, int w, int h)
638 {
639         printf("sys_move: %p - %d,%d  %dx%d\n",
640                         win, x, y, w, h);
641 }
642
643 void sys_raise(win_t *win)
644 {
645         printf("sys_raise: %p\n", win);
646 }
647
648 void sys_focus(win_t *win)
649 {
650         printf("sys_focus: %p\n", win);
651 }
652
653 void sys_show(win_t *win, state_t state)
654 {
655         printf("sys_show: %p: %d\n", win, state);
656 }
657
658 void sys_watch(win_t *win, event_t ev, mod_t mod)
659 {
660         printf("sys_watch: %p - %x %hhx\n",
661                         win, ev, mod2int(mod));
662 }
663
664 void sys_unwatch(win_t *win, event_t ev, mod_t mod)
665 {
666         printf("sys_unwatch: %p - %x %hhx\n",
667                         win, ev, mod2int(mod));
668 }
669
670 list_t *sys_info(win_t *win)
671 {
672         printf("sys_info: %p\n", win);
673         return list_insert(NULL, win);
674 }
675
676 win_t *sys_init(void)
677 {
678         printf("sys_init\n");
679
680         /* Register log handler */
681         wl_log_set_handler_server((wl_log_func_t)vprintf);
682
683         /* Open the display */
684         if (!(display = wl_display_create()))
685                 error("Unable to  create display");
686         if (wl_display_add_socket(display, NULL) != 0)
687                 error("Unable to add socket");
688         if (!(events = wl_display_get_event_loop(display)))
689                 error("Unable to get event loop");
690
691         /* Register interfaces */
692         ref_shm    = wl_global_create(display, &wl_shm_interface,                 1, NULL, &bind_shm);
693         ref_output = wl_global_create(display, &wl_output_interface,              2, NULL, &bind_output);
694         ref_ddm    = wl_global_create(display, &wl_data_device_manager_interface, 1, NULL, &bind_ddm);
695         ref_shell  = wl_global_create(display, &wl_shell_interface,               1, NULL, &bind_shell);
696         ref_comp   = wl_global_create(display, &wl_compositor_interface,          3, NULL, &bind_comp);
697         ref_seat   = wl_global_create(display, &wl_seat_interface,                3, NULL, &bind_seat);
698
699         /* Setup GTK display */
700         gtk_init(&conf_argc, &conf_argv);
701         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
702         gtk_widget_add_events(window,
703                         GDK_KEY_PRESS_MASK |
704                         GDK_BUTTON_PRESS_MASK |
705                         GDK_BUTTON_RELEASE_MASK |
706                         GDK_POINTER_MOTION_MASK);
707         g_signal_connect(window, "destroy",             G_CALLBACK(on_destroy), NULL);
708         g_signal_connect(window, "key-press-event",     G_CALLBACK(on_key),     NULL);
709         g_signal_connect(window, "button-press-event",  G_CALLBACK(on_button),  NULL);
710         g_signal_connect(window, "motion-notify-event", G_CALLBACK(on_move),    NULL);
711         g_signal_connect(window, "draw",                G_CALLBACK(on_draw),    NULL);
712         g_timeout_add(1000/60, on_wayland, NULL);
713         gtk_widget_show(window);
714
715         return new0(win_t);
716 }
717
718 void sys_run(win_t *root)
719 {
720         printf("sys_run: %p\n", root);
721         gtk_main();
722 }
723
724 void sys_exit(void)
725 {
726         printf("sys_exit\n");
727         gtk_main_quit();
728 }
729
730 void sys_free(win_t *root)
731 {
732         printf("sys_free: %p\n", root);
733 }
734