]> Pileus Git - wmpus/blob - sys-xwl.c
Some work on popups
[wmpus] / sys-xwl.c
1 /*
2  * Copyright (c) 2014-2015 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 <libevdev/libevdev.h>
25 #include <xkbcommon/xkbcommon.h>
26 #include <wayland-server.h>
27 #include <wayland-client.h>
28
29 #include <gtk/gtk.h>
30
31 #include "util.h"
32 #include "conf.h"
33 #include "sys.h"
34 #include "wm.h"
35
36 #include "xdg-shell-client-protocol.h"
37 #include "xdg-shell-server-protocol.h"
38 #include "gtk-shell-client-protocol.h"
39 #include "gtk-shell-server-protocol.h"
40
41 /* Window Managers calls */
42 void wm_update(void);
43
44 /* Wayland user data */
45 typedef struct {
46         uint8_t             *mem;
47         size_t               size;
48 } sys_pool_t;
49
50 typedef struct {
51         sys_pool_t          *pool;
52         uint8_t             *mem;
53         cairo_surface_t     *surface;
54 } sys_bdata_t;
55
56 typedef struct {
57         struct wl_client    *cli;
58         list_t              *ptrs;    // of struct wl_resource
59         list_t              *kbds;    // of struct wl_resource
60         list_t              *tchs;    // of struct wl_resource
61 } sys_cdata_t;
62
63 /* Internal structures */
64 struct win_sys {
65         struct wl_resource  *sfc;
66         struct wl_resource  *ssfc;
67         struct wl_resource  *xsfc;
68         struct wl_resource  *buf;
69         sys_cdata_t         *cdata;
70         int                  x,y;     // surface x,y
71         int                  wx,wy;   // window  x,y inside sfc
72         int                  ww,wh;   // window  w,h inside sfc
73 };
74
75 /* Global data */
76 static win_t                *root;
77 static win_t                *focus;
78 static list_t               *clients; // of sys_cdata_t
79 static list_t               *windows; // of win_t
80
81 static win_t                *cursor;
82 static double                cursor_x;
83 static double                cursor_y;
84 static double                cursor_dx;
85 static double                cursor_dy;
86
87 static GtkWidget            *screen;
88
89 static struct wl_resource   *output;
90 static struct wl_display    *display;
91 static struct wl_event_loop *events;
92
93 /********************
94  * Helper Functions *
95  ********************/
96
97 static int get_serial(void)
98 {
99         static int serial = 0;
100         return serial++;
101 }
102
103 static int get_time(void)
104 {
105         static uint64_t epoch;
106
107         struct timespec ts;
108         clock_gettime(CLOCK_REALTIME, &ts);
109
110         uint64_t now = (((uint64_t)ts.tv_sec ) * 1000)
111                      + (((uint64_t)ts.tv_nsec) / 1000000);
112
113         if (epoch == 0)
114                 epoch = now;
115
116         return (int)(now - epoch);
117 }
118
119 static win_t *find_win(int x, int y)
120 {
121         for (list_t *cur = windows; cur; cur = cur->prev) {
122                 win_t *win = cur->data;
123                 int l = win->x;
124                 int r = win->w + l;
125                 int t = win->y;
126                 int b = win->h + t;
127                 if (l <= x && x <= r && t <= y && y <= b)
128                         return win;
129         }
130         return NULL;
131 }
132
133 static sys_cdata_t *find_cdata(struct wl_client *cli)
134 {
135         // Search for existing client
136         for (list_t *cur = clients; cur; cur = cur->next) {
137                 sys_cdata_t *cdata = cur->data;
138                 if (cdata->cli == cli)
139                         return cdata;
140         }
141
142         // Not found, create new one
143         sys_cdata_t *cdata = new0(sys_cdata_t);
144         clients = list_insert(clients, cdata);
145         cdata->cli = cli;
146         return cdata;
147 }
148
149 /****************************
150  * Wayland Buffer Interface *
151  ****************************/
152 static void buffer_destroy(struct wl_client *cli, struct wl_resource *reso)
153 {
154         printf("buffer_destroy\n");
155 }
156
157 static struct wl_buffer_interface buffer_iface = {
158         .destroy  = buffer_destroy,
159 };
160
161 /***********************************
162  * Wayland Shared Memory Interface *
163  ***********************************/
164
165 /* Shm Pool */
166 static void pool_create_buffer(struct wl_client *cli, struct wl_resource *pool,
167                 uint32_t id, int32_t offset, int32_t width, int32_t height,
168                 int32_t stride, uint32_t format)
169 {
170         sys_bdata_t *bdata = new0(sys_bdata_t);
171         bdata->pool = wl_resource_get_user_data(pool);
172         bdata->mem  = bdata->pool->mem + offset;
173
174         printf("pool_create_buffer - %dx%d %p+%d : %d,%d,%d\n",
175                         width, height, bdata->pool->mem, offset, id, stride, format);
176
177         if (offset > bdata->pool->size || offset < 0)
178         {
179                 printf("\n\nerror\n\n");
180                 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_STRIDE,
181                                 "offset is too big or negative");
182                 return;
183         }
184
185         cairo_format_t cf =
186                 format == WL_SHM_FORMAT_ARGB8888 ? CAIRO_FORMAT_ARGB32 :
187                 format == WL_SHM_FORMAT_XRGB8888 ? CAIRO_FORMAT_RGB24  : CAIRO_FORMAT_INVALID;
188
189         bdata->surface = cairo_image_surface_create_for_data(bdata->mem, cf, width, height, stride);
190
191         struct wl_resource *res = wl_resource_create(cli, &wl_buffer_interface,
192                                         wl_resource_get_version(pool), id);
193         wl_resource_set_implementation(res, &buffer_iface, bdata, NULL);
194 }
195
196 static void pool_destroy(struct wl_client *cli, struct wl_resource *pool)
197 {
198         printf("pool_destroy\n");
199 }
200
201 static void pool_resize(struct wl_client *cli, struct wl_resource *pool,
202                 int32_t size)
203 {
204         printf("[   WMPUS   ] pool_resize - %d\n", size);
205         sys_pool_t *data = wl_resource_get_user_data(pool);
206         void *ptr = mremap(data->mem, data->size, size, MREMAP_MAYMOVE);
207         if (ptr == MAP_FAILED)
208         {
209                 printf("\n\nerror\n\n");
210                 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_FD,
211                                 "mremap failed: %s", strerror(errno));
212                 return;
213         }
214         data->mem  = ptr;
215         data->size = size;
216 }
217
218 static struct wl_shm_pool_interface pool_iface = {
219         .create_buffer = &pool_create_buffer,
220         .destroy       = &pool_destroy,
221         .resize        = &pool_resize,
222 };
223
224 /* Shm */
225 static void shm_create_pool(struct wl_client *cli, struct wl_resource *shm,
226                 uint32_t id, int32_t fd, int32_t size)
227 {
228         printf("shm_create_pool - #%d %d %d\n", id, fd, size);
229
230         sys_pool_t *data = new0(sys_pool_t);
231
232         struct wl_resource *res = wl_resource_create(cli, &wl_shm_pool_interface,
233                                         wl_resource_get_version(shm), id);
234         wl_resource_set_implementation(res, &pool_iface, data, NULL);
235
236         data->mem  = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
237         data->size = size;
238 }
239
240 static struct wl_shm_interface shm_iface = {
241         .create_pool = shm_create_pool,
242 };
243
244 /**************************
245  * Wayland Seat Interface *
246  **************************/
247
248 /* Pointer */
249 static void pointer_kill(struct wl_resource *ptr)
250 {
251         sys_cdata_t *cdata = wl_resource_get_user_data(ptr);
252         list_t *link = list_find(cdata->ptrs, ptr);
253         cdata->ptrs = list_remove(cdata->ptrs, link, 0);
254         if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
255                 list_t *clink = list_find(clients, cdata);
256                 clients = list_remove(clients, clink, 1);
257         }
258 }
259
260 static void pointer_set_cursor(struct wl_client *cli, struct wl_resource *ptr,
261                            uint32_t serial, struct wl_resource *sfc,
262                            int32_t hotspot_x, int32_t hotspot_y)
263 {
264         printf("pointer_set_cursor %d,%d\n", hotspot_x, hotspot_y);
265         win_t *win = wl_resource_get_user_data(sfc);
266         win->type = TYPE_CURSOR;
267         cursor_dx = hotspot_x;
268         cursor_dy = hotspot_y;
269         cursor    = win;
270 }
271
272 static void pointer_release(struct wl_client *cli, struct wl_resource *ptr)
273 {
274         printf("pointer_release\n");
275 }
276
277 static struct wl_pointer_interface pointer_iface = {
278         .set_cursor = pointer_set_cursor,
279         .release    = pointer_release,
280 };
281
282 /* Keyboard */
283 static void keyboard_kill(struct wl_resource *kbd)
284 {
285         sys_cdata_t *cdata = wl_resource_get_user_data(kbd);
286         list_t *link = list_find(cdata->kbds, kbd);
287         cdata->kbds = list_remove(cdata->kbds, link, 0);
288         if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
289                 list_t *clink = list_find(clients, cdata);
290                 clients = list_remove(clients, clink, 1);
291         }
292 }
293
294 static void keyboard_release(struct wl_client *cli, struct wl_resource *kbd)
295 {
296         printf("keyboard_release\n");
297 }
298
299 static struct wl_keyboard_interface keyboard_iface = {
300         .release = keyboard_release,
301 };
302
303 /* Touch */
304 static void touch_kill(struct wl_resource *tch)
305 {
306         sys_cdata_t *cdata = wl_resource_get_user_data(tch);
307         list_t *link = list_find(cdata->tchs, tch);
308         cdata->tchs = list_remove(cdata->tchs, link, 0);
309         if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
310                 list_t *clink = list_find(clients, cdata);
311                 clients = list_remove(clients, clink, 1);
312         }
313 }
314
315 static void touch_release(struct wl_client *cli, struct wl_resource *tch)
316 {
317         printf("touch_release\n");
318 }
319
320 static struct wl_touch_interface touch_iface = {
321         .release = touch_release,
322 };
323
324 /* Seat */
325 static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat,
326                 uint32_t id) {
327         sys_cdata_t *cdata = find_cdata(cli);
328         struct wl_resource *res = wl_resource_create(cli, &wl_pointer_interface, 3, id);
329         wl_resource_set_implementation(res, &pointer_iface, cdata, pointer_kill);
330         cdata->ptrs = list_insert(cdata->ptrs, res);
331         printf("seat_get_pointer - cli=%p cdata=%p ptr=%p\n", cli, cdata, res);
332 }
333
334 static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat,
335                 uint32_t id) {
336         sys_cdata_t *cdata = find_cdata(cli);
337         struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 4, id);
338         wl_resource_set_implementation(res, &keyboard_iface, cdata, keyboard_kill);
339
340         //map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
341         //xkb->context    = xkb_context_new(0);
342         //xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
343         //wl_keyboard_send_keymap(cli, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
344         //              keyboard->xkb.keymap.fd,
345         //              keyboard->xkb.keymap.size - 1);
346
347         cdata->kbds = list_insert(cdata->kbds, res);
348         printf("seat_get_keyboard - cli=%p cdata=%p kbd=%p\n", cli, cdata, res);
349 }
350
351 static void seat_get_touch(struct wl_client *cli, struct wl_resource *seat,
352                 uint32_t id) {
353         sys_cdata_t *cdata = find_cdata(cli);
354         struct wl_resource *res = wl_resource_create(cli, &wl_touch_interface, 3, id);
355         wl_resource_set_implementation(res, &touch_iface, cdata, touch_kill);
356         cdata->tchs = list_insert(cdata->tchs, res);
357         printf("seat_get_touch - cli=%p cdata=%p tch=%p\n", cli, cdata, res);
358 }
359
360 static struct wl_seat_interface seat_iface = {
361         .get_pointer  = &seat_get_pointer,
362         .get_keyboard = &seat_get_keyboard,
363         .get_touch    = &seat_get_touch,
364 };
365
366 /*****************************************
367  * Wayland Data Device Manager Interface *
368  *****************************************/
369
370 /* Data Offer */
371 static void doff_accept(struct wl_client *cli, struct wl_resource *doff,
372                uint32_t serial, const char *mime_type)
373 {
374         printf("doff_accept\n");
375 }
376
377 static void doff_receive(struct wl_client *cli, struct wl_resource *doff,
378                 const char *mime_type, int32_t fd)
379 {
380         printf("doff_receive\n");
381 }
382
383 static void doff_destroy(struct wl_client *cli, struct wl_resource *doff)
384 {
385         printf("doff_destroy\n");
386 }
387
388 static struct wl_data_offer_interface doff_iface = {
389         .accept  = doff_accept,
390         .receive = doff_receive,
391         .destroy = doff_destroy,
392 };
393
394 /* Data Source */
395 static void dsrc_offer(struct wl_client *cli, struct wl_resource *dsrc,
396               const char *mime_type)
397 {
398         (void)doff_iface;
399         printf("dsrc_offer\n");
400 }
401
402 static void dsrc_destroy(struct wl_client *cli, struct wl_resource *dsrc)
403 {
404         printf("dsrc_destroy\n");
405 }
406
407 static struct wl_data_source_interface dsrc_iface = {
408         .offer   = dsrc_offer,
409         .destroy = dsrc_destroy,
410 };
411
412 /* Data Device */
413 static void ddev_start_drag(struct wl_client *cli, struct wl_resource *dsrc,
414                    struct wl_resource *source, struct wl_resource *origin,
415                    struct wl_resource *icon, uint32_t serial)
416 {
417         printf("start_drag\n");
418 }
419
420 static void ddev_set_selection(struct wl_client *cli, struct wl_resource *dsrc,
421                       struct wl_resource *source, uint32_t serial)
422 {
423         printf("set_selection\n");
424 }
425
426 static struct wl_data_device_interface ddev_iface = {
427         .start_drag    = ddev_start_drag,
428         .set_selection = ddev_set_selection,
429 };
430
431 /* Data Device Manager */
432 static void ddm_create_data_source(struct wl_client *cli, struct wl_resource *ddm,
433                 uint32_t id)
434 {
435         printf("ddm_create_data_source\n");
436         struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
437         wl_resource_set_implementation(res, &dsrc_iface, NULL, NULL);
438 }
439
440 static void ddm_get_data_device(struct wl_client *cli, struct wl_resource *ddm,
441                 uint32_t id, struct wl_resource *seat)
442 {
443         printf("ddm_get_data_device\n");
444         struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
445         wl_resource_set_implementation(res, &ddev_iface, NULL, NULL);
446 }
447
448 static struct wl_data_device_manager_interface ddm_iface = {
449         .create_data_source = &ddm_create_data_source,
450         .get_data_device    = &ddm_get_data_device,
451 };
452
453 /**************************************
454  * Wayland Shell/Compositor Interface *
455  **************************************/
456
457 /* Surface */
458 static void surface_kill(struct wl_resource *sfc)
459 {
460         printf("surface_kill\n");
461         win_t  *win  = wl_resource_get_user_data(sfc);
462         list_t *link = list_find(windows, win);
463         free(win->sys);
464         free(win);
465         windows = list_remove(windows, link, 0);
466         gtk_widget_queue_draw(screen);
467 }
468
469 static void surface_destroy(struct wl_client *cli, struct wl_resource *sfc)
470 {
471         printf("surface_destroy\n");
472         surface_kill(sfc);
473 }
474
475 static void surface_attach(struct wl_client *cli, struct wl_resource *sfc,
476                 struct wl_resource *buf, int32_t x, int32_t y)
477 {
478         win_t       *win   = wl_resource_get_user_data(sfc);
479         sys_bdata_t *bdata = wl_resource_get_user_data(buf);
480         printf("surface_attach - %p - %d,%d\n", bdata->pool->mem, x, y);
481         win->sys->buf = buf;
482         win->sys->x   = x;
483         win->sys->y   = y;
484 }
485
486 static void surface_damage(struct wl_client *cli, struct wl_resource *sfc,
487                    int32_t x, int32_t y, int32_t width, int32_t height)
488 {
489         printf("surface_damage\n");
490 }
491
492 static void surface_frame(struct wl_client *cli, struct wl_resource *sfc,
493                 uint32_t id)
494 {
495         printf("surface_frame\n");
496         struct wl_resource *cb = wl_resource_create(cli, &wl_callback_interface, 1, id);
497         wl_resource_set_implementation(cb, NULL, NULL, NULL);
498         wl_callback_send_done(cb, get_time());
499 }
500
501 static void surface_set_opaque_region(struct wl_client *cli, struct wl_resource *sfc,
502                 struct wl_resource *reg)
503 {
504         printf("surface_set_opaque_region\n");
505 }
506
507 static void surface_set_input_region(struct wl_client *cli, struct wl_resource *sfc,
508                 struct wl_resource *reg)
509 {
510         printf("surface_set_input_region\n");
511 }
512
513 static void surface_commit(struct wl_client *cli, struct wl_resource *sfc)
514 {
515         printf("surface_commit\n");
516         gtk_widget_queue_draw(screen);
517 }
518
519 static void surface_set_buffer_transform(struct wl_client *cli, struct wl_resource *sfc,
520                 int32_t transform)
521 {
522         printf("surface_set_buffer_transform\n");
523 }
524
525 static void surface_set_buffer_scale(struct wl_client *cli, struct wl_resource *sfc,
526                 int32_t scale)
527 {
528         printf("surface_set_buffer_scale\n");
529 }
530
531 static struct wl_surface_interface surface_iface = {
532         .destroy              = surface_destroy,
533         .attach               = surface_attach,
534         .damage               = surface_damage,
535         .frame                = surface_frame,
536         .set_opaque_region    = surface_set_opaque_region,
537         .set_input_region     = surface_set_input_region,
538         .commit               = surface_commit,
539         .set_buffer_transform = surface_set_buffer_transform,
540         .set_buffer_scale     = surface_set_buffer_scale,
541 };
542
543 /* Region */
544 static void region_destroy(struct wl_client *cli, struct wl_resource *reg)
545 {
546         printf("region_destroy\n");
547 }
548
549 static void region_add(struct wl_client *cli, struct wl_resource *reg,
550                 int32_t x, int32_t y, int32_t width, int32_t height)
551 {
552         printf("region_add\n");
553 }
554
555 static void region_subtract(struct wl_client *cli, struct wl_resource *reg,
556                      int32_t x, int32_t y, int32_t width, int32_t height)
557 {
558         printf("region_subtract\n");
559 }
560
561 static struct wl_region_interface region_iface = {
562         .destroy  = region_destroy,
563         .add      = region_add,
564         .subtract = region_subtract,
565 };
566
567 /* Compositor */
568 static void comp_create_surface(struct wl_client *cli, struct wl_resource *comp,
569                 uint32_t id)
570 {
571         win_t *win = new0(win_t);
572         win->sys   = new0(win_sys_t);
573
574         struct wl_resource *res = wl_resource_create(cli, &wl_surface_interface, 3, id);
575         wl_resource_set_implementation(res, &surface_iface, win, surface_kill);
576         wl_surface_send_enter(res, output);
577
578         win->sys->sfc   = res;
579         win->sys->cdata = find_cdata(cli);
580
581         windows = list_insert(windows, win);
582
583         printf("comp_create_surface - cli=%p win=%p cdata=%p\n",
584                         cli, win, win->sys->cdata);
585 }
586
587 static void comp_create_region(struct wl_client *cli, struct wl_resource *comp,
588                 uint32_t id)
589 {
590         printf("comp_create_region\n");
591         struct wl_resource *res = wl_resource_create(cli, &wl_region_interface, 1, id);
592         wl_resource_set_implementation(res, &region_iface, NULL, NULL);
593 }
594
595 static struct wl_compositor_interface comp_iface = {
596         .create_surface = comp_create_surface,
597         .create_region  = comp_create_region,
598 };
599
600 /* Shell Surface */
601 static void ssurface_kill(struct wl_resource *ssfc)
602 {
603         win_t *win = wl_resource_get_user_data(ssfc);
604         printf("ssurface_kill - %p\n", win);
605         win->sys->ssfc = NULL;
606         if (!win->sys->xsfc)
607                 wm_remove(win);
608 }
609
610 static void ssurface_pong(struct wl_client *cli, struct wl_resource *ssfc,
611                 uint32_t serial)
612 {
613         printf("ssurface_pong\n");
614 }
615
616 static void ssurface_move(struct wl_client *cli, struct wl_resource *ssfc,
617                 struct wl_resource *seat, uint32_t serial)
618 {
619         printf("ssurface_move\n");
620 }
621
622 static void ssurface_resize(struct wl_client *cli, struct wl_resource *ssfc,
623                 struct wl_resource *seat, uint32_t serial, uint32_t edges)
624 {
625         printf("ssurface_resize\n");
626 }
627
628 static void ssurface_set_toplevel(struct wl_client *cli, struct wl_resource *ssfc)
629 {
630         printf("ssurface_set_toplevel\n");
631 }
632
633 static void ssurface_set_transient(struct wl_client *cli, struct wl_resource *ssfc,
634                 struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags)
635 {
636         printf("ssurface_set_transient\n");
637 }
638
639 static void ssurface_set_fullscreen(struct wl_client *cli, struct wl_resource *ssfc,
640                 uint32_t method, uint32_t framerate, struct wl_resource *out)
641 {
642         printf("ssurface_set_fullscreen\n");
643 }
644
645 static void ssurface_set_popup(struct wl_client *cli, struct wl_resource *ssfc,
646                 struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
647                 int32_t x, int32_t y, uint32_t flags)
648 {
649         printf("ssurface_set_popup\n");
650 }
651
652 static void ssurface_set_maximized(struct wl_client *cli, struct wl_resource *ssfc,
653                 struct wl_resource *out)
654 {
655         printf("ssurface_set_maximized\n");
656 }
657
658 static void ssurface_set_title(struct wl_client *cli, struct wl_resource *ssfc,
659                 const char *title)
660 {
661         printf("ssurface_set_title\n");
662 }
663
664 static void ssurface_set_class(struct wl_client *cli, struct wl_resource *ssfc,
665                 const char *class)
666 {
667         printf("ssurface_set_class\n");
668 }
669
670 static struct wl_shell_surface_interface ssurface_iface = {
671         .pong           = ssurface_pong,
672         .move           = ssurface_move,
673         .resize         = ssurface_resize,
674         .set_toplevel   = ssurface_set_toplevel,
675         .set_transient  = ssurface_set_transient,
676         .set_fullscreen = ssurface_set_fullscreen,
677         .set_popup      = ssurface_set_popup,
678         .set_maximized  = ssurface_set_maximized,
679         .set_title      = ssurface_set_title,
680         .set_class      = ssurface_set_class,
681 };
682
683 /* Shell */
684 static void shell_get_shell_surface(struct wl_client *cli, struct wl_resource *shell, uint32_t id,
685                               struct wl_resource *sfc) {
686         win_t *win = wl_resource_get_user_data(sfc);
687         printf("shell_get_shell_surface - %p\n", win);
688
689         struct wl_resource *res = wl_resource_create(cli, &wl_shell_surface_interface, 1, id);
690         wl_resource_set_implementation(res, &ssurface_iface, win, ssurface_kill);
691
692         win->type = TYPE_NORMAL;
693         win->sys->ssfc = res;
694         wm_insert(win);
695 }
696
697 static struct wl_shell_interface shell_iface = {
698         .get_shell_surface = shell_get_shell_surface,
699 };
700
701 /* XDG Popup */
702 static void xpopup_destroy(struct wl_client *cli, struct wl_resource *xpopup)
703 {
704         printf("xpopup_destroy\n");
705 }
706
707 static struct xdg_popup_interface xpopup_iface = {
708         .destroy = xpopup_destroy,
709 };
710
711 /* XDG Surface */
712 static void xsurface_kill(struct wl_resource *xsfc)
713 {
714         win_t *win = wl_resource_get_user_data(xsfc);
715         printf("xsurface_kill - %p\n", win);
716         win->sys->xsfc = NULL;
717         if (!win->sys->ssfc)
718                 wm_remove(win);
719 }
720
721 static void xsurface_destroy(struct wl_client *cli, struct wl_resource *xsfc)
722 {
723         printf("xsurface_destroy\n");
724 }
725
726 static void xsurface_set_parent(struct wl_client *cli, struct wl_resource *xsfc,
727                 struct wl_resource *parent)
728 {
729         win_t *win = wl_resource_get_user_data(xsfc);
730         printf("xsurface_set_parent - %p\n", win);
731         //win->type = TYPE_DIALOG;
732 }
733
734 static void xsurface_set_title(struct wl_client *cli, struct wl_resource *xsfc,
735                 const char *title)
736 {
737         printf("xsurface_set_title\n");
738 }
739
740 static void xsurface_set_app_id(struct wl_client *cli, struct wl_resource *xsfc,
741                 const char *app_id)
742 {
743         printf("xsurface_set_app_id\n");
744 }
745
746 static void xsurface_show_window_menu(struct wl_client *cli, struct wl_resource *xsfc,
747                 struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y)
748 {
749         printf("xsurface_show_window_menu\n");
750 }
751
752 static void xsurface_move(struct wl_client *cli, struct wl_resource *xsfc,
753                 struct wl_resource *seat, uint32_t serial)
754 {
755         printf("xsurface_move\n");
756 }
757
758 static void xsurface_resize(struct wl_client *cli, struct wl_resource *xsfc,
759                 struct wl_resource *seat, uint32_t serial, uint32_t edges)
760 {
761         printf("xsurface_resize\n");
762 }
763
764 static void xsurface_ack_configure(struct wl_client *cli, struct wl_resource *xsfc,
765                 uint32_t serial)
766 {
767         printf("xsurface_ack_configure\n");
768 }
769
770 static void xsurface_set_window_geometry(struct wl_client *cli, struct wl_resource *xsfc,
771                 int32_t x, int32_t y, int32_t width, int32_t height)
772 {
773         win_t *win = wl_resource_get_user_data(xsfc);
774         printf("xsurface_set_window_geometry - %p\n", win);
775         win->sys->wx = x;
776         win->sys->wy = y;
777         win->sys->ww = width;
778         win->sys->wh = height;
779 }
780
781 static void xsurface_set_maximized(struct wl_client *cli, struct wl_resource *xsfc)
782 {
783         printf("xsurface_set_maximized\n");
784 }
785
786 static void xsurface_unset_maximized(struct wl_client *cli, struct wl_resource *xsfc)
787 {
788         printf("xsurface_unset_maximized\n");
789 }
790
791 static void xsurface_set_fullscreen(struct wl_client *cli, struct wl_resource *xsfc,
792                 struct wl_resource *output)
793 {
794         printf("xsurface_set_fullscreen\n");
795 }
796
797 static void xsurface_unset_fullscreen(struct wl_client *cli, struct wl_resource *xsfc)
798 {
799         printf("xsurface_unset_fullscreen\n");
800 }
801
802 static void xsurface_set_minimized(struct wl_client *cli, struct wl_resource *xsfc)
803 {
804         printf("xsurface_set_minimized\n");
805 }
806
807 static struct xdg_surface_interface xsurface_iface = {
808         .destroy             = xsurface_destroy,
809         .set_parent          = xsurface_set_parent,
810         .set_title           = xsurface_set_title,
811         .set_app_id          = xsurface_set_app_id,
812         .show_window_menu    = xsurface_show_window_menu,
813         .move                = xsurface_move,
814         .resize              = xsurface_resize,
815         .ack_configure       = xsurface_ack_configure,
816         .set_window_geometry = xsurface_set_window_geometry,
817         .set_maximized       = xsurface_set_maximized,
818         .unset_maximized     = xsurface_unset_maximized,
819         .set_fullscreen      = xsurface_set_fullscreen,
820         .unset_fullscreen    = xsurface_unset_fullscreen,
821         .set_minimized       = xsurface_set_minimized,
822 };
823
824 /* XDG Shell */
825 static void xshell_use_unstable_version(struct wl_client *cli, struct wl_resource *xshell,
826                 int32_t version)
827 {
828         printf("xshell_use_unstable_version\n");
829 }
830
831 static void xshell_get_xdg_surface(struct wl_client *cli, struct wl_resource *xshell,
832                 uint32_t id, struct wl_resource *sfc)
833 {
834         win_t *win = wl_resource_get_user_data(sfc);
835         printf("xshell_get_xdg_surface - %p\n", win);
836
837         struct wl_resource *res = wl_resource_create(cli, &xdg_surface_interface, 1, id);
838         wl_resource_set_implementation(res, &xsurface_iface, win, xsurface_kill);
839
840         win->type = TYPE_NORMAL;
841         win->sys->xsfc = res;
842         wm_insert(win);
843 }
844
845 static void xshell_get_xdg_popup(struct wl_client *cli, struct wl_resource *xshell,
846                 uint32_t id, struct wl_resource *sfc, struct wl_resource *parent,
847                 struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y, uint32_t flags)
848 {
849         win_t *win = wl_resource_get_user_data(sfc);
850         printf("xshell_get_xdg_popup - %p @ %d,%d\n", win, x, y);
851
852         struct wl_resource *res = wl_resource_create(cli, &xdg_popup_interface, 1, id);
853         wl_resource_set_implementation(res, &xpopup_iface, win, NULL);
854
855         win_t *par  = wl_resource_get_user_data(parent);
856         win->type   = TYPE_POPUP;
857         win->parent = par;
858         win->x      = x;
859         win->y      = y;
860 }
861
862 static void xshell_pong(struct wl_client *cli, struct wl_resource *xshell,
863                 uint32_t serial)
864 {
865         printf("xshell_pong\n");
866 }
867
868 static struct xdg_shell_interface xshell_iface = {
869         .use_unstable_version = xshell_use_unstable_version,
870         .get_xdg_surface      = xshell_get_xdg_surface,
871         .get_xdg_popup        = xshell_get_xdg_popup,
872         .pong                 = xshell_pong,
873 };
874
875 /* GTK Surface */
876 static void gsurface_set_dbus_properties(struct wl_client *cli, struct wl_resource *gsfc,
877                             const char *application_id, const char *app_menu_path,
878                             const char *menubar_path, const char *window_object_path,
879                             const char *application_object_path, const char *unique_bus_name)
880 {
881         printf("gsurface_set_dbus_properties\n");
882 }
883
884 static struct gtk_surface_interface gsurface_iface = {
885         .set_dbus_properties = gsurface_set_dbus_properties,
886 };
887
888 /* GTK Shell */
889 static void gshell_get_gtk_surface(struct wl_client *cli, struct wl_resource *gshell,
890                 uint32_t id, struct wl_resource *sfc)
891 {
892         printf("gshell_get_gtk_surface\n");
893         struct wl_resource *res = wl_resource_create(cli, &gtk_surface_interface, 1, id);
894         wl_resource_set_implementation(res, &gsurface_iface, NULL, NULL);
895 }
896
897 static struct gtk_shell_interface gshell_iface = {
898         .get_gtk_surface = gshell_get_gtk_surface,
899 };
900
901 /*******************
902  * Wayland Globals *
903  *******************/
904
905 /* References */
906 static struct wl_global *ref_shm;
907 static struct wl_global *ref_output;
908 static struct wl_global *ref_seat;
909 static struct wl_global *ref_ddm;
910 static struct wl_global *ref_comp;
911 static struct wl_global *ref_shell;
912 static struct wl_global *ref_xshell;
913 static struct wl_global *ref_gshell;
914
915 /* Bind functions */
916 static void bind_shm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
917 {
918         printf("bind_shm\n");
919
920         if (version > 1)
921                 version = 1;
922
923         struct wl_resource *res = wl_resource_create(cli, &wl_shm_interface, version, id);
924         wl_resource_set_implementation(res, &shm_iface, NULL, NULL);
925
926         wl_shm_send_format(res, WL_SHM_FORMAT_XRGB8888);
927         wl_shm_send_format(res, WL_SHM_FORMAT_ARGB8888);
928 }
929
930 static void bind_output(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
931 {
932         printf("bind_output\n");
933
934         struct wl_resource *res = wl_resource_create(cli, &wl_output_interface, version, id);
935         output = res;
936
937         wl_output_send_geometry(res,
938                         0, 0, 330, 210,              // x/y (px), w/h (mm)
939                         WL_OUTPUT_SUBPIXEL_UNKNOWN,  // subpixel format
940                         "unknown", "unknown",        // make, model
941                         WL_OUTPUT_TRANSFORM_NORMAL); // rotatoin
942         wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 800,  600,  60);
943         wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1024, 768,  60);
944         wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1280, 1024, 60);
945         wl_output_send_done(res);
946 }
947
948 static void bind_seat(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
949 {
950         printf("bind_seat\n");
951
952         struct wl_resource *res = wl_resource_create(cli, &wl_seat_interface, version, id);
953         wl_resource_set_implementation(res, &seat_iface, NULL, NULL);
954
955         wl_seat_send_capabilities(res,
956                         WL_SEAT_CAPABILITY_KEYBOARD |
957                         WL_SEAT_CAPABILITY_POINTER);
958 }
959
960 static void bind_ddm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
961 {
962         printf("bind_ddm\n");
963
964         struct wl_resource *res = wl_resource_create(cli, &wl_data_device_manager_interface, version, id);
965         wl_resource_set_implementation(res, &ddm_iface, NULL, NULL);
966 }
967
968 static void bind_comp(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
969 {
970         printf("bind_comp\n");
971         struct wl_resource *res = wl_resource_create(cli, &wl_compositor_interface, version, id);
972         wl_resource_set_implementation(res, &comp_iface, NULL, NULL);
973 }
974
975 static void bind_shell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
976 {
977         printf("bind_shell\n");
978         struct wl_resource *res = wl_resource_create(cli, &wl_shell_interface, version, id);
979         wl_resource_set_implementation(res, &shell_iface, NULL, NULL);
980 }
981
982 static void bind_xshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
983 {
984         printf("bind_xshell\n");
985         struct wl_resource *res = wl_resource_create(cli, &xdg_shell_interface, version, id);
986         wl_resource_set_implementation(res, &xshell_iface, NULL, NULL);
987 }
988
989 static void bind_gshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
990 {
991         printf("bind_gshell\n");
992         struct wl_resource *res = wl_resource_create(cli, &gtk_shell_interface, version, id);
993         wl_resource_set_implementation(res, &gshell_iface, NULL, NULL);
994 }
995
996 /*****************
997  * Gtk Callbacks *
998  *****************/
999
1000 static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1001 {
1002         printf("on_destroy\n");
1003         sys_exit();
1004 }
1005
1006 static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1007 {
1008         /* Handle special keys */
1009         if (event->keyval == GDK_KEY_q)
1010                 sys_exit();
1011         if (event->keyval == GDK_KEY_t)
1012                 g_spawn_command_line_async("st-wl", NULL);
1013
1014         /* Send key to wayland */
1015         printf(g_ascii_isprint(event->keyval)
1016                 ? "on_key - win=%p cdata=%p '%c'\n"
1017                 : "on_key - win=%p cdata=%p 0x%X\n",
1018                 focus, focus?focus->sys->cdata:0, event->keyval);
1019         if (!focus || !focus->sys->cdata)
1020                 return FALSE;
1021         for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next) {
1022                 uint32_t serial = get_serial();
1023                 uint32_t stamp  = get_time();
1024                 uint32_t key    = event->hardware_keycode-8;
1025                 uint32_t state  = event->type == GDK_KEY_PRESS
1026                         ? WL_KEYBOARD_KEY_STATE_PRESSED
1027                         : WL_KEYBOARD_KEY_STATE_RELEASED;
1028                 wl_keyboard_send_key(cur->data, serial, stamp, key, state);
1029                 printf("    send -> %p tm=%d key=%d state=%d\n",
1030                                 cur->data, stamp, key, state);
1031         }
1032         return TRUE;
1033 }
1034
1035 static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
1036 {
1037         win_t *win = find_win(event->x, event->y);
1038         printf("on_button - win=%p cdata=%p\n",
1039                         win, win?win->sys->cdata:0);
1040         if (!win || !win->sys->cdata)
1041                 return FALSE;
1042         for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next) {
1043                 uint32_t serial = get_serial();
1044                 uint32_t stamp  = get_time();
1045                 uint32_t button = BTN_MOUSE+(event->button-1);
1046                 uint32_t state  = event->type == GDK_BUTTON_PRESS
1047                         ? WL_POINTER_BUTTON_STATE_PRESSED
1048                         : WL_POINTER_BUTTON_STATE_RELEASED;
1049                 wl_pointer_send_button(cur->data, serial, stamp, button, state);
1050                 printf("    send -> %p tm=%d btn=%d state=%d\n",
1051                                 cur->data, stamp, button, state);
1052         }
1053         return TRUE;
1054 }
1055
1056 static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
1057 {
1058         win_t *win = find_win(event->x, event->y);
1059         if (!win)
1060                 return FALSE;
1061
1062         /* Keys */
1063         static struct wl_array keys;
1064
1065         /* Queue draw event for cursor */
1066         gtk_widget_queue_draw(screen);
1067
1068         /* Save cursor position */
1069         cursor_x = event->x;
1070         cursor_y = event->y;
1071
1072         /* Create event */
1073         wl_fixed_t x = wl_fixed_from_double(event->x - win->x);
1074         wl_fixed_t y = wl_fixed_from_double(event->y - win->y);
1075
1076         /* No focus change */
1077         if (win == focus && win->sys->cdata) {
1078                 uint32_t t = get_time();
1079                 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next)
1080                         wl_pointer_send_motion(cur->data, t, x, y);
1081                 return TRUE;
1082         }
1083
1084         /* Send leave event */
1085         uint32_t s = get_serial();
1086         if  (focus && focus->sys->sfc && focus->sys->cdata) {
1087                 printf("on_move - leave win=%p\n", focus);
1088                 for (list_t *cur = focus->sys->cdata->ptrs; cur; cur = cur->next)
1089                         wl_pointer_send_leave(cur->data, s, focus->sys->sfc);
1090                 for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next)
1091                         wl_keyboard_send_leave(cur->data, s, focus->sys->sfc);
1092         }
1093         if  (win && win->sys->sfc && win->sys->cdata) {
1094                 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next) {
1095                         printf("on_move - enter win=%p ptr=%p\n", win, cur->data);
1096                         wl_pointer_send_enter(cur->data, s, win->sys->sfc, x, y);
1097                 }
1098                 for (list_t *cur = win->sys->cdata->kbds; cur; cur = cur->next) {
1099                         printf("on_move - enter win=%p kbd=%p\n", win, cur->data);
1100                         wl_keyboard_send_enter(cur->data, s, win->sys->sfc, &keys);
1101                 }
1102         }
1103         focus = win;
1104         return TRUE;
1105 }
1106
1107 static void on_size(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data)
1108 {
1109         printf("on_size - %dx%d\n", alloc->width, alloc->height);
1110         root->w = alloc->width;
1111         root->h = alloc->height;
1112 }
1113
1114 static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
1115 {
1116         printf("on_draw\n");
1117
1118         wm_update(); // Hacks for now
1119
1120         /* Draw windows bottom up */
1121         list_t *bottom = list_last(windows);
1122         for (list_t *cur = bottom; cur; cur = cur->prev) {
1123                 win_t       *win   = cur->data;
1124                 if (win->sys->buf == NULL)
1125                         continue;
1126                 if (win->type == TYPE_CURSOR)
1127                         continue;
1128                 sys_bdata_t *bdata = wl_resource_get_user_data(win->sys->buf);
1129                 int x = win->x;
1130                 int y = win->y;
1131                 if (win->type == TYPE_POPUP && win->parent) {
1132                         x += win->parent->x;
1133                         y += win->parent->y;
1134                 }
1135                 //if (win->sys->wx) x -= win->sys->wx;
1136                 //if (win->sys->wy) y -= win->sys->wy;
1137                 printf("    win = %p %dx%d @ %d,%d\n",
1138                                 win, win->w, win->h, x, y);
1139                 cairo_surface_mark_dirty(bdata->surface);
1140                 cairo_set_source_surface(cairo, bdata->surface, x, y);
1141                 cairo_paint(cairo);
1142                 //wl_buffer_send_release(win->sys->buf);
1143                 //win->sys->buf = 0;
1144         }
1145
1146         /* Draw cursor */
1147         if (cursor && cursor->sys->buf) {
1148                 int x = cursor_x, y = cursor_y;
1149                 sys_bdata_t *bdata = wl_resource_get_user_data(cursor->sys->buf);
1150                 cairo_surface_mark_dirty(bdata->surface);
1151                 cairo_set_source_surface(cairo, bdata->surface, x, y);
1152                 cairo_paint(cairo);
1153         }
1154
1155         return TRUE;
1156 }
1157
1158 static gboolean on_wayland(gpointer user_data)
1159 {
1160         // TODO - convert to polled execution
1161         wl_display_flush_clients(display);
1162         wl_event_loop_dispatch(events, 0);
1163         return TRUE;
1164 }
1165
1166 /********************
1167  * System functions *
1168  ********************/
1169 void sys_move(win_t *win, int x, int y, int w, int h)
1170 {
1171         static uint32_t        active;
1172         static struct wl_array states;
1173         if (!active) {
1174                 active = XDG_SURFACE_STATE_ACTIVATED;
1175                 wl_array_init(&states);
1176                 uint32_t *ptr = wl_array_add(&states, sizeof(active));
1177                 if (ptr)
1178                         *ptr = active;
1179         }
1180
1181         printf("sys_move: %p - %d,%d  %dx%d\n",
1182                         win, x, y, w, h);
1183
1184         if (win->x == x && win->y == y &&
1185             win->w == w && win->h == h)
1186                 return;
1187
1188         win->x = x;
1189         win->y = y;
1190         win->w = w;
1191         win->h = h;
1192
1193         if (win->sys->ssfc)
1194                 wl_shell_surface_send_configure(win->sys->ssfc,
1195                                 WL_SHELL_SURFACE_RESIZE_NONE, w, h);
1196
1197         if (win->sys->xsfc)
1198                 xdg_surface_send_configure(win->sys->xsfc,
1199                                 w, h, &states, get_serial());
1200 }
1201
1202 void sys_raise(win_t *win)
1203 {
1204         printf("sys_raise: %p\n", win);
1205 }
1206
1207 void sys_focus(win_t *win)
1208 {
1209         printf("sys_focus: %p\n", win);
1210 }
1211
1212 void sys_show(win_t *win, state_t state)
1213 {
1214         printf("sys_show: %p: %d\n", win, state);
1215 }
1216
1217 void sys_watch(win_t *win, event_t ev, mod_t mod)
1218 {
1219         printf("sys_watch: %p - %x %hhx\n",
1220                         win, ev, mod2int(mod));
1221 }
1222
1223 void sys_unwatch(win_t *win, event_t ev, mod_t mod)
1224 {
1225         printf("sys_unwatch: %p - %x %hhx\n",
1226                         win, ev, mod2int(mod));
1227 }
1228
1229 list_t *sys_info(win_t *win)
1230 {
1231         printf("sys_info: %p\n", win);
1232         return list_insert(NULL, win);
1233 }
1234
1235 win_t *sys_init(void)
1236 {
1237         printf("sys_init\n");
1238
1239         /* Create root window */
1240         root = new0(win_t);
1241         root->x = 0;
1242         root->y = 0;
1243         root->w = 800;
1244         root->h = 600;
1245
1246         /* Register log handler */
1247         wl_log_set_handler_server((wl_log_func_t)vprintf);
1248
1249         /* Open the display */
1250         if (!(display = wl_display_create()))
1251                 error("Unable to  create display");
1252         if (wl_display_add_socket(display, NULL) != 0)
1253                 error("Unable to add socket");
1254         if (!(events = wl_display_get_event_loop(display)))
1255                 error("Unable to get event loop");
1256
1257         /* Register interfaces */
1258         ref_shm    = wl_global_create(display, &wl_shm_interface,                 1, NULL, &bind_shm);
1259         ref_output = wl_global_create(display, &wl_output_interface,              2, NULL, &bind_output);
1260         ref_ddm    = wl_global_create(display, &wl_data_device_manager_interface, 1, NULL, &bind_ddm);
1261         ref_shell  = wl_global_create(display, &wl_shell_interface,               1, NULL, &bind_shell);
1262         ref_comp   = wl_global_create(display, &wl_compositor_interface,          3, NULL, &bind_comp);
1263         ref_seat   = wl_global_create(display, &wl_seat_interface,                4, NULL, &bind_seat);
1264         ref_xshell = wl_global_create(display, &xdg_shell_interface,              1, NULL, &bind_xshell);
1265         ref_gshell = wl_global_create(display, &gtk_shell_interface,              1, NULL, &bind_gshell);
1266
1267         /* Setup GTK display */
1268         gtk_init(&conf_argc, &conf_argv);
1269         screen = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1270         gtk_widget_add_events(screen,
1271                         GDK_KEY_PRESS_MASK |
1272                         GDK_BUTTON_PRESS_MASK |
1273                         GDK_BUTTON_RELEASE_MASK |
1274                         GDK_POINTER_MOTION_MASK);
1275         g_signal_connect(screen, "destroy",              G_CALLBACK(on_destroy), NULL);
1276         g_signal_connect(screen, "key-press-event",      G_CALLBACK(on_key),     NULL);
1277         g_signal_connect(screen, "key-release-event",    G_CALLBACK(on_key),     NULL);
1278         g_signal_connect(screen, "button-press-event",   G_CALLBACK(on_button),  NULL);
1279         g_signal_connect(screen, "button-release-event", G_CALLBACK(on_button),  NULL);
1280         g_signal_connect(screen, "motion-notify-event",  G_CALLBACK(on_move),    NULL);
1281         g_signal_connect(screen, "size-allocate",        G_CALLBACK(on_size),    NULL);
1282         g_signal_connect(screen, "draw",                 G_CALLBACK(on_draw),    NULL);
1283         g_timeout_add(1000/60, on_wayland, NULL);
1284         gtk_widget_show(screen);
1285
1286         return root;
1287 }
1288
1289 void sys_run(win_t *root)
1290 {
1291         printf("sys_run: %p\n", root);
1292         gtk_main();
1293 }
1294
1295 void sys_exit(void)
1296 {
1297         printf("sys_exit\n");
1298         gtk_main_quit();
1299 }
1300
1301 void sys_free(win_t *root)
1302 {
1303         printf("sys_free: %p\n", root);
1304 }
1305