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