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