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