]> Pileus Git - wmpus/commitdiff
Add home grown wayland protocol wlsimple
authorAndy Spencer <andy753421@gmail.com>
Sat, 28 Mar 2015 21:47:41 +0000 (21:47 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sat, 28 Mar 2015 22:57:06 +0000 (22:57 +0000)
makefile
sys-gwl.c [new file with mode: 0644]
wayland.c [new file with mode: 0644]
wayland.h [new file with mode: 0644]
wayland.sh [new file with mode: 0755]

index caceac9e8de918f6ef00c6b0088efea6ea209d8f..fdcf5bb7cb4e5c23918a96955600baa86dab11b3 100644 (file)
--- a/makefile
+++ b/makefile
@@ -10,6 +10,14 @@ CFLAGS    ?= -g -Wall
 PREFIX    ?= /usr/local
 MANPREFIX ?= ${PREFIX}/share/man
 
+ifeq ($(SYS),gwl)
+GCC       ?= gcc
+PROG      ?= wmpus
+
+sys-gwl.o: CFLAGS  += $(shell pkg-config --cflags gtk+-3.0) -I.
+wmpus:     LDFLAGS += $(shell pkg-config --libs   gtk+-3.0)
+endif
+
 ifeq ($(SYS),x11)
 GCC       ?= gcc
 PROG      ?= wmpus
diff --git a/sys-gwl.c b/sys-gwl.c
new file mode 100644 (file)
index 0000000..f1bad98
--- /dev/null
+++ b/sys-gwl.c
@@ -0,0 +1,1001 @@
+/*
+ * Copyright (c) 2014-2015 Andy Spencer <andy753421@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include <wayland.h>
+
+#include <gtk/gtk.h>
+
+#include "util.h"
+#include "conf.h"
+#include "sys.h"
+#include "wm.h"
+
+/* Internal structures */
+struct win_sys {
+       win_t *win;
+};
+
+typedef struct {
+       uint8_t *mem;
+       size_t   size;
+} sys_pool_t;
+
+typedef struct {
+       sys_pool_t      *pool;
+       uint8_t         *mem;
+       cairo_surface_t *surface;
+} sys_buf_t;
+
+struct wl_resource *output;
+
+sys_pool_t *gdata[10];
+int         gidx;
+
+/* Global data */
+static int         server;
+static int         client;
+static wl_msg_t   *message[WL_MESSAGE_MAX];
+static GtkWidget  *window;
+static sys_buf_t  *buffer;
+
+/*****************
+ * Gtk Callbacks *
+ *****************/
+
+static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+       printf("on_destroy\n");
+       sys_exit();
+}
+
+static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+{
+       printf(g_ascii_isprint(event->keyval)
+               ? "on_key: '%c'\n"
+               : "on_key: 0x%X\n",
+               event->keyval);
+       if (event->keyval == GDK_KEY_q)
+               sys_exit();
+       if (event->keyval == GDK_KEY_t)
+               g_spawn_command_line_async("st-wl", NULL);
+       return TRUE;
+}
+
+static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+       printf("on_button\n");
+       return TRUE;
+}
+
+static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
+{
+       //printf("on_motion\n");
+       return TRUE;
+}
+
+static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
+{
+       printf("on_draw\n");
+
+       if (buffer) {
+               cairo_surface_mark_dirty(buffer->surface);
+               cairo_set_source_surface(cairo, buffer->surface, 10, 10);
+               cairo_paint(cairo);
+       }
+
+       cairo_set_source_rgb(cairo, 1, 1, 1);
+       cairo_arc(cairo, 150, 150, 50, 0, 2*G_PI);
+       cairo_fill(cairo);
+
+       return TRUE;
+}
+
+static gboolean on_wayland(gpointer user_data)
+{
+       struct sockaddr_un addr;
+       socklen_t len = sizeof(addr);
+
+       if (server && client == 0) {
+               if ((client = accept4(server, addr, &len, SOCK_CLOEXEC)) < 0)
+                       error("accept failed");
+       }
+
+       if (client > 0) {
+               wl_header_t head = {};
+               int len = read(client, head, sizeof(head), 1);
+               read(client, buf, sizeof(header, count);
+       }
+
+       return TRUE;
+}
+
+/*********************
+ * Wayland Callbacks *
+ *********************/
+
+#if 0
+static void new_window(void)
+{
+       printf("new_window\n");
+}
+
+static void new_screen(void)
+{
+       printf("new_screen\n");
+}
+#endif
+
+/****************************
+ * Wayland Buffer Interface *
+ ****************************/
+static void buffer_destroy(struct wl_client *cli, struct wl_resource *reso)
+{
+       printf("buffer_destroy\n");
+}
+
+static struct wl_buffer_interface buffer_iface = {
+        .destroy  = buffer_destroy,
+};
+
+/***********************************
+ * Wayland Shared Memory Interface *
+ ***********************************/
+
+/* Shm Pool */
+static void pool_create_buffer(struct wl_client *cli, struct wl_resource *pool,
+               uint32_t id, int32_t offset, int32_t width, int32_t height,
+               int32_t stride, uint32_t format)
+{
+       sys_buf_t  *buf  = new0(sys_buf_t);
+       buf->pool = wl_resource_get_user_data(pool);
+       buf->mem  = buf->pool->mem + offset;
+
+       printf("pool_create_buffer - %dx%d %p+%d : %d,%d,%d\n",
+                       width, height, buf->pool->mem, offset, id, stride, format);
+
+       if (offset > buf->pool->size || offset < 0)
+       {
+               printf("\n\nerror\n\n");
+               wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_STRIDE,
+                               "offset is too big or negative");
+               return;
+       }
+
+       cairo_format_t cf =
+               format == WL_SHM_FORMAT_ARGB8888 ? CAIRO_FORMAT_ARGB32 :
+               format == WL_SHM_FORMAT_XRGB8888 ? CAIRO_FORMAT_RGB24  : CAIRO_FORMAT_INVALID;
+
+       buf->surface = cairo_image_surface_create_for_data(buf->mem, cf, width, height, stride);
+
+       struct wl_resource *res = wl_resource_create(cli, &wl_buffer_interface,
+                                        wl_resource_get_version(pool), id);
+       wl_resource_set_implementation(res, &buffer_iface, buf, NULL);
+}
+
+static void pool_destroy(struct wl_client *cli, struct wl_resource *pool)
+{
+       printf("pool_destroy\n");
+}
+
+static void pool_resize(struct wl_client *cli, struct wl_resource *pool,
+               int32_t size)
+{
+       printf("[   WMPUS   ] pool_resize - %d\n", size);
+       sys_pool_t *data = wl_resource_get_user_data(pool);
+       void *ptr = mremap(data->mem, data->size, size, MREMAP_MAYMOVE);
+       if (ptr == MAP_FAILED)
+       {
+               printf("\n\nerror\n\n");
+               wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_FD,
+                               "mremap failed: %s", strerror(errno));
+               return;
+       }
+       data->mem  = ptr;
+       data->size = size;
+       gdata[gidx++] = data;
+}
+
+static struct wl_shm_pool_interface pool_iface = {
+       .create_buffer = &pool_create_buffer,
+       .destroy       = &pool_destroy,
+       .resize        = &pool_resize,
+};
+
+/* Shm */
+static void shm_create_pool(struct wl_client *cli, struct wl_resource *shm,
+               uint32_t id, int32_t fd, int32_t size)
+{
+       printf("shm_create_pool - #%d %d %d\n", id, fd, size);
+
+       sys_pool_t *data = new0(sys_pool_t);
+
+       struct wl_resource *res = wl_resource_create(cli, &wl_shm_pool_interface,
+                                        wl_resource_get_version(shm), id);
+       wl_resource_set_implementation(res, &pool_iface, data, NULL);
+
+       data->mem  = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+       data->size = size;
+       gdata[gidx++] = data;
+}
+
+static struct wl_shm_interface shm_iface = {
+       .create_pool = shm_create_pool,
+};
+
+/**************************
+ * Wayland Seat Interface *
+ **************************/
+
+/* Pointer */
+static void pointer_set_cursor(struct wl_client *cli, struct wl_resource *ptr,
+                          uint32_t serial,
+                          struct wl_resource *surface,
+                          int32_t hotspot_x,
+                          int32_t hotspot_y)
+{
+       printf("pointer_set_cursor\n");
+}
+
+static void pointer_release(struct wl_client *cli, struct wl_resource *ptr)
+{
+       printf("pointer_release\n");
+}
+
+static struct wl_pointer_interface pointer_iface = {
+        .set_cursor = pointer_set_cursor,
+        .release    = pointer_release,
+};
+
+/* Keyboard */
+static void keyboard_release(struct wl_client *cli, struct wl_resource *kbd)
+{
+       printf("keyboard_release\n");
+}
+
+static struct wl_keyboard_interface keyboard_iface = {
+        .release = keyboard_release,
+};
+
+/* Touch */
+static void touch_release(struct wl_client *cli, struct wl_resource *tch)
+{
+       printf("touch_release\n");
+}
+
+static struct wl_touch_interface touch_iface = {
+        .release = touch_release,
+};
+
+/* Seat */
+static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat,
+               uint32_t id) {
+       printf("seat_get_pointer\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_pointer_interface, 3, id);
+       wl_resource_set_implementation(res, &pointer_iface, NULL, NULL);
+}
+
+static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat,
+               uint32_t id) {
+       printf("seat_get_keyboard\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 4, id);
+       wl_resource_set_implementation(res, &keyboard_iface, NULL, NULL);
+}
+
+static void seat_get_touch(struct wl_client *cli, struct wl_resource *seat,
+               uint32_t id) {
+       printf("seat_get_touch\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_touch_interface, 3, id);
+       wl_resource_set_implementation(res, &touch_iface, NULL, NULL);
+}
+
+static struct wl_seat_interface seat_iface = {
+       .get_pointer  = &seat_get_pointer,
+       .get_keyboard = &seat_get_keyboard,
+        .get_touch    = &seat_get_touch,
+};
+
+/*****************************************
+ * Wayland Data Device Manager Interface *
+ *****************************************/
+
+/* Data Offer */
+static void doff_accept(struct wl_client *cli, struct wl_resource *res,
+              uint32_t serial, const char *mime_type)
+{
+       printf("doff_accept\n");
+}
+
+static void doff_receive(struct wl_client *cli, struct wl_resource *res,
+               const char *mime_type, int32_t fd)
+{
+       printf("doff_receive\n");
+}
+
+static void doff_destroy(struct wl_client *cli, struct wl_resource *res)
+{
+       printf("doff_destroy\n");
+}
+
+static struct wl_data_offer_interface doff_iface = {
+        .accept  = doff_accept,
+        .receive = doff_receive,
+        .destroy = doff_destroy,
+};
+
+/* Data Source */
+static void dsrc_offer(struct wl_client *cli, struct wl_resource *res,
+             const char *mime_type)
+{
+       (void)doff_iface;
+       printf("dsrc_offer\n");
+}
+
+static void dsrc_destroy(struct wl_client *cli, struct wl_resource *res)
+{
+       printf("dsrc_destroy\n");
+}
+
+static struct wl_data_source_interface dsrc_iface = {
+        .offer   = dsrc_offer,
+        .destroy = dsrc_destroy,
+};
+
+/* Data Device */
+static void ddev_start_drag(struct wl_client *cli, struct wl_resource *res,
+                  struct wl_resource *source, struct wl_resource *origin,
+                  struct wl_resource *icon, uint32_t serial)
+{
+       printf("start_drag\n");
+}
+
+static void ddev_set_selection(struct wl_client *cli, struct wl_resource *res,
+                     struct wl_resource *source, uint32_t serial)
+{
+       printf("set_selection\n");
+}
+
+static struct wl_data_device_interface ddev_iface = {
+        .start_drag    = ddev_start_drag,
+        .set_selection = ddev_set_selection,
+};
+
+/* Data Device Manager */
+static void ddm_create_data_source(struct wl_client *cli, struct wl_resource *ddm,
+               uint32_t id)
+{
+       printf("ddm_create_data_source\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
+       wl_resource_set_implementation(res, &dsrc_iface, NULL, NULL);
+}
+
+static void ddm_get_data_device(struct wl_client *cli, struct wl_resource *ddm,
+               uint32_t id, struct wl_resource *seat)
+{
+       printf("ddm_get_data_device\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
+       wl_resource_set_implementation(res, &ddev_iface, NULL, NULL);
+}
+
+static struct wl_data_device_manager_interface ddm_iface = {
+       .create_data_source = &ddm_create_data_source,
+       .get_data_device    = &ddm_get_data_device,
+};
+
+/**************************************
+ * Wayland Shell/Compositor Interface *
+ **************************************/
+
+/* Callback */
+static void frame_callback(struct wl_resource *res)
+{
+       printf("frame_callback\n");
+}
+
+/* Surface */
+static void surface_destroy(struct wl_client *cli, struct wl_resource *res)
+{
+       printf("surface_destroy\n");
+}
+
+static void surface_attach(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *buf, int32_t x, int32_t y)
+{
+       sys_buf_t *data = wl_resource_get_user_data(buf);
+       printf("surface_attach - %p\n", data->pool->mem);
+       buffer = data;
+}
+
+static void surface_damage(struct wl_client *cli, struct wl_resource *res,
+                   int32_t x, int32_t y, int32_t width, int32_t height)
+{
+       printf("surface_damage\n");
+}
+
+static void surface_frame(struct wl_client *cli, struct wl_resource *res,
+               uint32_t id)
+{
+       printf("surface_frame\n");
+       struct wl_resource *cb = wl_resource_create(cli, &wl_callback_interface, 1, id);
+       wl_resource_set_implementation(cb, NULL, NULL, &frame_callback);
+        wl_callback_send_done(cb, time(NULL));
+}
+
+static void surface_set_opaque_region(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *reg)
+{
+       printf("surface_set_opaque_region\n");
+}
+
+static void surface_set_input_region(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *reg)
+{
+       printf("surface_set_input_region\n");
+}
+
+static void surface_commit(struct wl_client *cli, struct wl_resource *res)
+{
+       printf("surface_commit\n");
+       gtk_widget_queue_draw(window);
+}
+
+static void surface_set_buffer_transform(struct wl_client *cli, struct wl_resource *res,
+               int32_t transform)
+{
+       printf("surface_set_buffer_transform\n");
+}
+
+static void surface_set_buffer_scale(struct wl_client *cli, struct wl_resource *res,
+               int32_t scale)
+{
+       printf("surface_set_buffer_scale\n");
+}
+
+static struct wl_surface_interface surface_iface = {
+        .destroy              = surface_destroy,
+        .attach               = surface_attach,
+        .damage               = surface_damage,
+        .frame                = surface_frame,
+        .set_opaque_region    = surface_set_opaque_region,
+        .set_input_region     = surface_set_input_region,
+        .commit               = surface_commit,
+        .set_buffer_transform = surface_set_buffer_transform,
+        .set_buffer_scale     = surface_set_buffer_scale,
+};
+
+/* Region */
+static void region_destroy(struct wl_client *cli, struct wl_resource *res)
+{
+       printf("region_destroy\n");
+}
+
+static void region_add(struct wl_client *cli, struct wl_resource *res,
+                int32_t x, int32_t y, int32_t width, int32_t height)
+{
+       printf("region_add\n");
+}
+
+static void region_subtract(struct wl_client *cli, struct wl_resource *res,
+                     int32_t x, int32_t y, int32_t width, int32_t height)
+{
+       printf("region_subtract\n");
+}
+
+static struct wl_region_interface region_iface = {
+        .destroy  = region_destroy,
+        .add      = region_add,
+        .subtract = region_subtract,
+};
+
+/* Compositor */
+static void comp_create_surface(struct wl_client *cli, struct wl_resource *comp,
+               uint32_t id)
+{
+       printf("comp_create_surface\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_surface_interface, 3, id);
+       wl_resource_set_implementation(res, &surface_iface, NULL, NULL);
+       wl_surface_send_enter(res, output);
+}
+
+static void comp_create_region(struct wl_client *cli, struct wl_resource *comp,
+               uint32_t id)
+{
+       printf("comp_create_region\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_region_interface, 1, id);
+       wl_resource_set_implementation(res, &region_iface, NULL, NULL);
+}
+
+static struct wl_compositor_interface comp_iface = {
+       .create_surface = comp_create_surface,
+       .create_region  = comp_create_region,
+};
+
+/* Shell Surface */
+static void ssurface_pong(struct wl_client *cli, struct wl_resource *res,
+               uint32_t serial)
+{
+       printf("ssurface_pong\n");
+}
+
+static void ssurface_move(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *seat, uint32_t serial)
+{
+       printf("ssurface_move\n");
+}
+
+static void ssurface_resize(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *seat, uint32_t serial, uint32_t edges)
+{
+       printf("ssurface_resize\n");
+}
+
+static void ssurface_set_toplevel(struct wl_client *cli, struct wl_resource *res)
+{
+       printf("ssurface_set_toplevel\n");
+}
+
+static void ssurface_set_transient(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags)
+{
+       printf("ssurface_set_transient\n");
+}
+
+static void ssurface_set_fullscreen(struct wl_client *cli, struct wl_resource *res,
+               uint32_t method, uint32_t framerate, struct wl_resource *out)
+{
+       printf("ssurface_set_fullscreen\n");
+}
+
+static void ssurface_set_popup(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
+               int32_t x, int32_t y, uint32_t flags)
+{
+       printf("ssurface_set_popup\n");
+}
+
+static void ssurface_set_maximized(struct wl_client *cli, struct wl_resource *res,
+               struct wl_resource *out)
+{
+       printf("ssurface_set_maximized\n");
+}
+
+static void ssurface_set_title(struct wl_client *cli, struct wl_resource *res,
+               const char *title)
+{
+       printf("ssurface_set_title\n");
+}
+
+static void ssurface_set_class(struct wl_client *cli, struct wl_resource *res,
+               const char *class)
+{
+       printf("ssurface_set_class\n");
+}
+
+static struct wl_shell_surface_interface ssurface_iface = {
+        .pong           = ssurface_pong,
+        .move           = ssurface_move,
+        .resize         = ssurface_resize,
+        .set_toplevel   = ssurface_set_toplevel,
+        .set_transient  = ssurface_set_transient,
+        .set_fullscreen = ssurface_set_fullscreen,
+        .set_popup      = ssurface_set_popup,
+        .set_maximized  = ssurface_set_maximized,
+        .set_title      = ssurface_set_title,
+        .set_class      = ssurface_set_class,
+};
+
+/* Shell */
+static void shell_get_shell_surface(struct wl_client *cli, struct wl_resource *shell, uint32_t id,
+                              struct wl_resource *sfc) {
+       printf("shell_get_shell_surface\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_shell_surface_interface, 1, id);
+       wl_resource_set_implementation(res, &ssurface_iface, NULL, NULL);
+}
+
+static struct wl_shell_interface shell_iface = {
+       .get_shell_surface = shell_get_shell_surface,
+};
+
+/* XDG Popup */
+static void xpopup_destroy(struct wl_client *cli, struct wl_resource *xpopup)
+{
+       printf("xpopup_destroy\n");
+}
+
+static struct xdg_popup_interface xpopup_iface = {
+       .destroy = xpopup_destroy,
+};
+
+/* XDG Surface */
+static void xsurface_destroy(struct wl_client *cli, struct wl_resource *xsfc)
+{
+       printf("xsurface_destroy\n");
+}
+
+static void xsurface_set_parent(struct wl_client *cli, struct wl_resource *xsfc,
+               struct wl_resource *parent)
+{
+       printf("xsurface_set_parent\n");
+}
+
+static void xsurface_set_title(struct wl_client *cli, struct wl_resource *xsfc,
+               const char *title)
+{
+       printf("xsurface_set_title\n");
+}
+
+static void xsurface_set_app_id(struct wl_client *cli, struct wl_resource *xsfc,
+               const char *app_id)
+{
+       printf("xsurface_set_app_id\n");
+}
+
+static void xsurface_show_window_menu(struct wl_client *cli, struct wl_resource *xsfc,
+               struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y)
+{
+       printf("xsurface_show_window_menu\n");
+}
+
+static void xsurface_move(struct wl_client *cli, struct wl_resource *xsfc,
+               struct wl_resource *seat, uint32_t serial)
+{
+       printf("xsurface_move\n");
+}
+
+static void xsurface_resize(struct wl_client *cli, struct wl_resource *xsfc,
+               struct wl_resource *seat, uint32_t serial, uint32_t edges)
+{
+       printf("xsurface_resize\n");
+}
+
+static void xsurface_ack_configure(struct wl_client *cli, struct wl_resource *xsfc,
+               uint32_t serial)
+{
+       printf("xsurface_ack_configure\n");
+}
+
+static void xsurface_set_window_geometry(struct wl_client *cli, struct wl_resource *xsfc,
+               int32_t x, int32_t y, int32_t width, int32_t height)
+{
+       printf("xsurface_set_window_geometry\n");
+}
+
+static void xsurface_set_maximized(struct wl_client *cli, struct wl_resource *xsfc)
+{
+       printf("xsurface_set_maximized\n");
+}
+
+static void xsurface_unset_maximized(struct wl_client *cli, struct wl_resource *xsfc)
+{
+       printf("xsurface_unset_maximized\n");
+}
+
+static void xsurface_set_fullscreen(struct wl_client *cli, struct wl_resource *xsfc,
+               struct wl_resource *output)
+{
+       printf("xsurface_set_fullscreen\n");
+}
+
+static void xsurface_unset_fullscreen(struct wl_client *cli, struct wl_resource *xsfc)
+{
+       printf("xsurface_unset_fullscreen\n");
+}
+
+static void xsurface_set_minimized(struct wl_client *cli, struct wl_resource *xsfc)
+{
+       printf("xsurface_set_minimized\n");
+}
+
+static struct xdg_surface_interface xsurface_iface = {
+       .destroy             = xsurface_destroy,
+       .set_parent          = xsurface_set_parent,
+       .set_title           = xsurface_set_title,
+       .set_app_id          = xsurface_set_app_id,
+       .show_window_menu    = xsurface_show_window_menu,
+       .move                = xsurface_move,
+       .resize              = xsurface_resize,
+       .ack_configure       = xsurface_ack_configure,
+       .set_window_geometry = xsurface_set_window_geometry,
+       .set_maximized       = xsurface_set_maximized,
+       .unset_maximized     = xsurface_unset_maximized,
+       .set_fullscreen      = xsurface_set_fullscreen,
+       .unset_fullscreen    = xsurface_unset_fullscreen,
+       .set_minimized       = xsurface_set_minimized,
+};
+
+/* XDG Shell */
+static void xshell_use_unstable_version(struct wl_client *cli, struct wl_resource *gshell,
+               int32_t version)
+{
+       printf("xshell_use_unstable_version\n");
+}
+
+static void xshell_get_xdg_surface(struct wl_client *cli, struct wl_resource *gshell,
+               uint32_t id, struct wl_resource *surface)
+{
+       printf("xshell_get_xdg_surface\n");
+       struct wl_resource *res = wl_resource_create(cli, &xdg_surface_interface, 1, id);
+       wl_resource_set_implementation(res, &xsurface_iface, NULL, NULL);
+}
+
+static void xshell_get_xdg_popup(struct wl_client *cli, struct wl_resource *gshell,
+               uint32_t id, struct wl_resource *surface, struct wl_resource *parent,
+               struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y, uint32_t flags)
+{
+       printf("xshell_get_xdg_popup\n");
+       struct wl_resource *res = wl_resource_create(cli, &xdg_popup_interface, 1, id);
+       wl_resource_set_implementation(res, &xpopup_iface, NULL, NULL);
+}
+
+static void xshell_pong(struct wl_client *cli, struct wl_resource *gshell,
+               uint32_t serial)
+{
+       printf("xshell_pong\n");
+}
+
+static struct xdg_shell_interface xshell_iface = {
+       .use_unstable_version = xshell_use_unstable_version,
+       .get_xdg_surface      = xshell_get_xdg_surface,
+       .get_xdg_popup        = xshell_get_xdg_popup,
+       .pong                 = xshell_pong,
+};
+
+/* GTK Surface */
+static void gsurface_set_dbus_properties(struct wl_client *cli, struct wl_resource *gsfc,
+                           const char *application_id, const char *app_menu_path,
+                           const char *menubar_path, const char *window_object_path,
+                           const char *application_object_path, const char *unique_bus_name)
+{
+       printf("gsurface_set_dbus_properties\n");
+}
+
+static struct gtk_surface_interface gsurface_iface = {
+       .set_dbus_properties = gsurface_set_dbus_properties,
+};
+
+/* GTK Shell */
+static void gshell_get_gtk_surface(struct wl_client *cli, struct wl_resource *gshell,
+               uint32_t id, struct wl_resource *sfc)
+{
+       printf("gshell_get_gtk_surface\n");
+       struct wl_resource *res = wl_resource_create(cli, &gtk_surface_interface, 1, id);
+       wl_resource_set_implementation(res, &gsurface_iface, NULL, NULL);
+}
+
+static struct gtk_shell_interface gshell_iface = {
+       .get_gtk_surface = gshell_get_gtk_surface,
+};
+
+/*******************
+ * Wayland Globals *
+ *******************/
+
+/* References */
+static struct wl_global *ref_shm;
+static struct wl_global *ref_output;
+static struct wl_global *ref_seat;
+static struct wl_global *ref_ddm;
+static struct wl_global *ref_comp;
+static struct wl_global *ref_shell;
+static struct wl_global *ref_xshell;
+static struct wl_global *ref_gshell;
+
+/* Bind functions */
+static void bind_shm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_shm\n");
+
+       if (version > 1)
+               version = 1;
+
+       struct wl_resource *res = wl_resource_create(cli, &wl_shm_interface, version, id);
+       wl_resource_set_implementation(res, &shm_iface, NULL, NULL);
+
+       wl_shm_send_format(res, WL_SHM_FORMAT_XRGB8888);
+       wl_shm_send_format(res, WL_SHM_FORMAT_ARGB8888);
+}
+
+static void bind_output(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_output\n");
+
+       struct wl_resource *res = wl_resource_create(cli, &wl_output_interface, version, id);
+       output = res;
+
+       wl_output_send_geometry(res,
+                       0, 0, 330, 210,              // x/y (px), w/h (mm)
+                       WL_OUTPUT_SUBPIXEL_UNKNOWN,  // subpixel format
+                       "unknown", "unknown",        // make, model
+                       WL_OUTPUT_TRANSFORM_NORMAL); // rotatoin
+       //wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 800,  600,  60);
+       //wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1024, 768,  60);
+       wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1280, 1024, 60);
+       //wl_output_send_done(res);
+}
+
+static void bind_seat(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_seat\n");
+
+       struct wl_resource *res = wl_resource_create(cli, &wl_seat_interface, version, id);
+       wl_resource_set_implementation(res, &seat_iface, NULL, NULL);
+
+       wl_seat_send_capabilities(res,
+                       WL_SEAT_CAPABILITY_KEYBOARD |
+                       WL_SEAT_CAPABILITY_POINTER);
+}
+
+static void bind_ddm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_ddm\n");
+
+       struct wl_resource *res = wl_resource_create(cli, &wl_data_device_manager_interface, version, id);
+       wl_resource_set_implementation(res, &ddm_iface, NULL, NULL);
+}
+
+static void bind_comp(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_comp\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_compositor_interface, version, id);
+       wl_resource_set_implementation(res, &comp_iface, NULL, NULL);
+}
+
+static void bind_shell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_shell\n");
+       struct wl_resource *res = wl_resource_create(cli, &wl_shell_interface, version, id);
+       wl_resource_set_implementation(res, &shell_iface, NULL, NULL);
+}
+
+static void bind_xshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_xshell\n");
+       struct wl_resource *res = wl_resource_create(cli, &xdg_shell_interface, version, id);
+       wl_resource_set_implementation(res, &xshell_iface, NULL, NULL);
+}
+
+static void bind_gshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
+{
+       printf("bind_gshell\n");
+       struct wl_resource *res = wl_resource_create(cli, &gtk_shell_interface, version, id);
+       wl_resource_set_implementation(res, &gshell_iface, NULL, NULL);
+}
+
+/********************
+ * System functions *
+ ********************/
+void sys_move(win_t *win, int x, int y, int w, int h)
+{
+       printf("sys_move: %p - %d,%d  %dx%d\n",
+                       win, x, y, w, h);
+}
+
+void sys_raise(win_t *win)
+{
+       printf("sys_raise: %p\n", win);
+}
+
+void sys_focus(win_t *win)
+{
+       printf("sys_focus: %p\n", win);
+}
+
+void sys_show(win_t *win, state_t state)
+{
+       printf("sys_show: %p: %d\n", win, state);
+}
+
+void sys_watch(win_t *win, event_t ev, mod_t mod)
+{
+       printf("sys_watch: %p - %x %hhx\n",
+                       win, ev, mod2int(mod));
+}
+
+void sys_unwatch(win_t *win, event_t ev, mod_t mod)
+{
+       printf("sys_unwatch: %p - %x %hhx\n",
+                       win, ev, mod2int(mod));
+}
+
+list_t *sys_info(win_t *win)
+{
+       printf("sys_info: %p\n", win);
+       return list_insert(NULL, win);
+}
+
+win_t *sys_init(void)
+{
+       printf("sys_init\n");
+
+       /* Determine Runtime Directory */
+       char *runtime = NULL;
+       if (display == NULL)
+               display = getenv("XDG_RUNTIME_DIR");
+       if (display == NULL)
+               error("No XDG Runtime Directory");
+
+       /* Determine Display Socket */
+       char *display = NULL;
+       if (display == NULL)
+               display = getenv("WAYLAND_DISPLAY");
+       if (display == NULL)
+               display = "wayland-0";
+
+       /* Open socket */
+       struct sockaddr_un addr = { .sun_family = AF_LOCAL; };
+       if (strlen(runtime) + 1 + strlen(display) + 1 >= sizeof(addr.sun_path))
+               error("Socket path too long");
+       if (snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", runtime, display) <= 0)
+               error("snprint failed");
+       if ((server = socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0)) < 0)
+               error("socket() failed");
+       if ((bind(server, addr, size) < 0)
+               error("bind() failed");
+       if ((listen(server, 1) < 0)
+               error("listen() failed");
+
+       /* Register interfaces */
+       ref_shm    = wl_global_create(display, &wl_shm_interface,                 1, NULL, &bind_shm);
+       ref_output = wl_global_create(display, &wl_output_interface,              2, NULL, &bind_output);
+       ref_ddm    = wl_global_create(display, &wl_data_device_manager_interface, 1, NULL, &bind_ddm);
+       ref_shell  = wl_global_create(display, &wl_shell_interface,               1, NULL, &bind_shell);
+       ref_comp   = wl_global_create(display, &wl_compositor_interface,          3, NULL, &bind_comp);
+       ref_seat   = wl_global_create(display, &wl_seat_interface,                4, NULL, &bind_seat);
+       ref_xshell = wl_global_create(display, &xdg_shell_interface,              1, NULL, &bind_xshell);
+       ref_gshell = wl_global_create(display, &gtk_shell_interface,              1, NULL, &bind_gshell);
+
+       /* Setup GTK display */
+       gtk_init(&conf_argc, &conf_argv);
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       gtk_widget_add_events(window,
+                       GDK_KEY_PRESS_MASK |
+                       GDK_BUTTON_PRESS_MASK |
+                       GDK_BUTTON_RELEASE_MASK |
+                       GDK_POINTER_MOTION_MASK);
+       g_signal_connect(window, "destroy",             G_CALLBACK(on_destroy), NULL);
+       g_signal_connect(window, "key-press-event",     G_CALLBACK(on_key),     NULL);
+       g_signal_connect(window, "button-press-event",  G_CALLBACK(on_button),  NULL);
+       g_signal_connect(window, "motion-notify-event", G_CALLBACK(on_move),    NULL);
+       g_signal_connect(window, "draw",                G_CALLBACK(on_draw),    NULL);
+       g_timeout_add(1000/60, on_wayland, NULL);
+       gtk_widget_show(window);
+
+       return new0(win_t);
+}
+
+void sys_run(win_t *root)
+{
+       printf("sys_run: %p\n", root);
+       gtk_main();
+}
+
+void sys_exit(void)
+{
+       printf("sys_exit\n");
+       gtk_main_quit();
+}
+
+void sys_free(win_t *root)
+{
+       printf("sys_free: %p\n", root);
+}
+
diff --git a/wayland.c b/wayland.c
new file mode 100644 (file)
index 0000000..91f6b3b
--- /dev/null
+++ b/wayland.c
@@ -0,0 +1,115 @@
+#define WL_DEFINE_TABLES
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "wayland.h"
+
+int warn(char *msg);
+
+/* Test */
+typedef int (*callback_t)(void *obj, uint16_t op, void *data);
+
+typedef struct
+{
+       uint32_t       max;
+       wl_header_t    head;
+       wl_request_t   req;
+       wl_event_t     evt;
+       void          *data;
+} msg_t;
+
+typedef struct
+{
+       uint32_t       id;
+       callback_t     func;
+       wl_interface_t iface;
+} obj_t;
+
+int step(int fd, msg_t *msg)
+{
+       obj_t *obj = NULL;
+
+       // Read header
+       int hlen = sizeof(msg->head);
+       if (read(fd, &msg->head, hlen) < hlen)
+               warn("short head read");
+
+       // Read header info
+       int id  = msg->head.id;
+       int len = msg->head.len;
+       int op  = msg->head.op;
+
+       // Allocate data
+       if (len > msg->max) {
+               msg->max  = len;
+               msg->data = realloc(msg->data, len);
+               if (!msg->data)
+                       warn("no memory");
+       }
+
+       // Read body
+       if (read(fd, msg->data, len) < len)
+               warn("short data read");
+
+       // Find Object
+       (void)id;
+       (void)obj;
+       int        iface = obj->iface;
+       callback_t func  = obj->func;
+
+       // No parsing needed
+       if (!wl_rarray[iface] || !wl_rarray[iface][op])
+               return func(obj, op, msg->data);
+
+       // Parse body
+       const char *info = wl_rarray[iface][op];
+       uint32_t *sptr = (uint32_t*) msg->data;
+       uint32_t *dptr = (uint32_t*)&msg->req;
+       for (int i = 0; info[i]; i++) {
+               switch (info[i]) {
+                       case WL_ARRAY_NONE:
+                               *dptr++       = *sptr++;  // data
+                               break;
+                       case WL_ARRAY_STRING:
+                               *dptr++       = *sptr++;  // length
+                               *(void**)dptr =  sptr;    // pointer
+                               dptr += (((len/4)+1)/4);
+                               sptr += (sizeof(void*)/4);
+                               break;
+                       case WL_ARRAY_ARRAY:
+                               *dptr++       = *sptr++;  // length
+                               *(void**)dptr =  sptr;    // pointer
+                               dptr += ((((len-1)/4)+1)/4);
+                               sptr += (sizeof(void*)/4);
+                               break;
+                       case WL_ARRAY_FD:
+                               // todo
+                               break;
+               }
+       }
+       return func(obj, op, &msg->req);
+}
+
+int main(int argc, char **argv)
+{
+       int    fd  = 0;
+       msg_t  msg = {};
+
+       while (1) {
+               // Find file descriptor
+               //if (!select(fd))
+               //      warn("error in select");;
+
+               // Process request
+               if (!step(fd, &msg))
+                       warn("error stepping");
+       }
+}
+
+int main()
+{
+       wl_init();
+       while ((msg = wl_run())) {
+               switch msg(
+       }
+}
diff --git a/wayland.h b/wayland.h
new file mode 100644 (file)
index 0000000..0caba1e
--- /dev/null
+++ b/wayland.h
@@ -0,0 +1,1041 @@
+#ifndef WAYLAND_H
+#define WAYLAND_H
+
+#include <stdint.h>
+
+/***********************************************************
+ * Common Types
+ ***********************************************************/
+
+#define WL_MESSAGE_LEN 4096
+
+typedef struct {
+       uint32_t id;
+       uint32_t len : 16;
+       uint32_t op  : 16;
+} wl_header_t;
+
+typedef struct {
+       uint32_t len;
+       char    *str;
+} wl_string_t;
+
+typedef struct {
+       uint32_t len;
+       void    *data;
+} wl_array_t;
+
+typedef struct {
+       uint32_t num  : 24;
+       uint32_t frac : 8;
+} wl_fixed_t;
+
+/***********************************************************
+ * Interfaces
+ ***********************************************************/
+
+/* Interface Versions */
+#define WL_DISPLAY_VERSION               1
+#define WL_REGISTRY_VERSION              1
+#define WL_CALLBACK_VERSION              1
+#define WL_COMPOSITOR_VERSION            3
+#define WL_SHM_POOL_VERSION              1
+#define WL_SHM_VERSION                   1
+#define WL_BUFFER_VERSION                1
+#define WL_DATA_OFFER_VERSION            1
+#define WL_DATA_SOURCE_VERSION           1
+#define WL_DATA_DEVICE_VERSION           1
+#define WL_DATA_DEVICE_MANAGER_VERSION   1
+#define WL_SHELL_VERSION                 1
+#define WL_SHELL_SURFACE_VERSION         1
+#define WL_SURFACE_VERSION               3
+#define WL_SEAT_VERSION                  4
+#define WL_POINTER_VERSION               3
+#define WL_KEYBOARD_VERSION              4
+#define WL_TOUCH_VERSION                 3
+#define WL_OUTPUT_VERSION                2
+#define WL_REGION_VERSION                1
+#define WL_SUBCOMPOSITOR_VERSION         1
+#define WL_SUBSURFACE_VERSION            1
+
+/* Interface IDs */
+typedef enum {
+       WL_DISPLAY                     = 0,
+       WL_REGISTRY                    = 1,
+       WL_CALLBACK                    = 2,
+       WL_COMPOSITOR                  = 3,
+       WL_SHM_POOL                    = 4,
+       WL_SHM                         = 5,
+       WL_BUFFER                      = 6,
+       WL_DATA_OFFER                  = 7,
+       WL_DATA_SOURCE                 = 8,
+       WL_DATA_DEVICE                 = 9,
+       WL_DATA_DEVICE_MANAGER         = 10,
+       WL_SHELL                       = 11,
+       WL_SHELL_SURFACE               = 12,
+       WL_SURFACE                     = 13,
+       WL_SEAT                        = 14,
+       WL_POINTER                     = 15,
+       WL_KEYBOARD                    = 16,
+       WL_TOUCH                       = 17,
+       WL_OUTPUT                      = 18,
+       WL_REGION                      = 19,
+       WL_SUBCOMPOSITOR               = 20,
+       WL_SUBSURFACE                  = 21,
+       WL_NUM_INTERFACES              = 22,
+} wl_interface_t;
+
+/***********************************************************
+ * Interface WL_DISPLAY
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_DISPLAY_SYNC                = 0,
+       WL_DISPLAY_GET_REGISTRY        = 1,
+       WL_NUM_DISPLAY_REQUESTS        = 2,
+} wl_display_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_DISPLAY_ERROR               = 0,
+       WL_DISPLAY_DELETE_ID           = 1,
+       WL_NUM_DISPLAY_EVENTS          = 2,
+} wl_display_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    callback;
+} wl_display_sync_t;
+
+typedef struct {
+       uint32_t    registry;
+} wl_display_get_registry_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    object_id;
+       uint32_t    code;
+       wl_string_t message;
+} wl_display_error_t;
+
+typedef struct {
+       uint32_t    id;
+} wl_display_delete_id_t;
+
+/***********************************************************
+ * Interface WL_REGISTRY
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_REGISTRY_BIND               = 0,
+       WL_NUM_REGISTRY_REQUESTS       = 1,
+} wl_registry_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_REGISTRY_GLOBAL             = 0,
+       WL_REGISTRY_GLOBAL_REMOVE      = 1,
+       WL_NUM_REGISTRY_EVENTS         = 2,
+} wl_registry_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    name;
+       uint32_t    id;
+} wl_registry_bind_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    name;
+       wl_string_t interface;
+       uint32_t    version;
+} wl_registry_global_t;
+
+typedef struct {
+       uint32_t    name;
+} wl_registry_global_remove_t;
+
+/***********************************************************
+ * Interface WL_CALLBACK
+ ***********************************************************/
+
+/* Event IDs */
+typedef enum {
+       WL_CALLBACK_DONE               = 0,
+       WL_NUM_CALLBACK_EVENTS         = 1,
+} wl_callback_event_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    callback_data;
+} wl_callback_done_t;
+
+/***********************************************************
+ * Interface WL_COMPOSITOR
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_COMPOSITOR_CREATE_SURFACE   = 0,
+       WL_COMPOSITOR_CREATE_REGION    = 1,
+       WL_NUM_COMPOSITOR_REQUESTS     = 2,
+} wl_compositor_request_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    id;
+} wl_compositor_create_surface_t;
+
+typedef struct {
+       uint32_t    id;
+} wl_compositor_create_region_t;
+
+/***********************************************************
+ * Interface WL_SHM_POOL
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SHM_POOL_CREATE_BUFFER      = 0,
+       WL_SHM_POOL_DESTROY            = 1,
+       WL_SHM_POOL_RESIZE             = 2,
+       WL_NUM_SHM_POOL_REQUESTS       = 3,
+} wl_shm_pool_request_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    id;
+       int32_t     offset;
+       int32_t     width;
+       int32_t     height;
+       int32_t     stride;
+       uint32_t    format;
+} wl_shm_pool_create_buffer_t;
+
+typedef struct {
+       int32_t     size;
+} wl_shm_pool_resize_t;
+
+/***********************************************************
+ * Interface WL_SHM
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SHM_CREATE_POOL             = 0,
+       WL_NUM_SHM_REQUESTS            = 1,
+} wl_shm_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_SHM_FORMAT                  = 0,
+       WL_NUM_SHM_EVENTS              = 1,
+} wl_shm_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    id;
+       int32_t     size;
+} wl_shm_create_pool_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    format;
+} wl_shm_format_t;
+
+/***********************************************************
+ * Interface WL_BUFFER
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_BUFFER_DESTROY              = 0,
+       WL_NUM_BUFFER_REQUESTS         = 1,
+} wl_buffer_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_BUFFER_RELEASE              = 0,
+       WL_NUM_BUFFER_EVENTS           = 1,
+} wl_buffer_event_t;
+
+/***********************************************************
+ * Interface WL_DATA_OFFER
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_DATA_OFFER_ACCEPT           = 0,
+       WL_DATA_OFFER_RECEIVE          = 1,
+       WL_DATA_OFFER_DESTROY          = 2,
+       WL_NUM_DATA_OFFER_REQUESTS     = 3,
+} wl_data_offer_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_DATA_OFFER_OFFER            = 0,
+       WL_NUM_DATA_OFFER_EVENTS       = 1,
+} wl_data_offer_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    serial;
+       wl_string_t mime_type;
+} wl_data_offer_accept_t;
+
+typedef struct {
+       wl_string_t mime_type;
+} wl_data_offer_receive_t;
+
+/* Events Messages */
+typedef struct {
+       wl_string_t mime_type;
+} wl_data_offer_offer_t;
+
+/***********************************************************
+ * Interface WL_DATA_SOURCE
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_DATA_SOURCE_OFFER           = 0,
+       WL_DATA_SOURCE_DESTROY         = 1,
+       WL_NUM_DATA_SOURCE_REQUESTS    = 2,
+} wl_data_source_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_DATA_SOURCE_TARGET          = 0,
+       WL_DATA_SOURCE_SEND            = 1,
+       WL_DATA_SOURCE_CANCELLED       = 2,
+       WL_NUM_DATA_SOURCE_EVENTS      = 3,
+} wl_data_source_event_t;
+
+/* Requests Messages */
+typedef struct {
+       wl_string_t mime_type;
+} wl_data_source_offer_t;
+
+/* Events Messages */
+typedef struct {
+       wl_string_t mime_type;
+} wl_data_source_target_t;
+
+typedef struct {
+       wl_string_t mime_type;
+} wl_data_source_send_t;
+
+/***********************************************************
+ * Interface WL_DATA_DEVICE
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_DATA_DEVICE_START_DRAG      = 0,
+       WL_DATA_DEVICE_SET_SELECTION   = 1,
+       WL_NUM_DATA_DEVICE_REQUESTS    = 2,
+} wl_data_device_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_DATA_DEVICE_DATA_OFFER      = 0,
+       WL_DATA_DEVICE_ENTER           = 1,
+       WL_DATA_DEVICE_LEAVE           = 2,
+       WL_DATA_DEVICE_MOTION          = 3,
+       WL_DATA_DEVICE_DROP            = 4,
+       WL_DATA_DEVICE_SELECTION       = 5,
+       WL_NUM_DATA_DEVICE_EVENTS      = 6,
+} wl_data_device_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    source;
+       uint32_t    origin;
+       uint32_t    icon;
+       uint32_t    serial;
+} wl_data_device_start_drag_t;
+
+typedef struct {
+       uint32_t    source;
+       uint32_t    serial;
+} wl_data_device_set_selection_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    id;
+} wl_data_device_data_offer_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    surface;
+       wl_fixed_t  x;
+       wl_fixed_t  y;
+       uint32_t    id;
+} wl_data_device_enter_t;
+
+typedef struct {
+       uint32_t    time;
+       wl_fixed_t  x;
+       wl_fixed_t  y;
+} wl_data_device_motion_t;
+
+typedef struct {
+       uint32_t    id;
+} wl_data_device_selection_t;
+
+/***********************************************************
+ * Interface WL_DATA_DEVICE_MANAGER
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE = 0,
+       WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE = 1,
+       WL_NUM_DATA_DEVICE_MANAGER_REQUESTS = 2,
+} wl_data_device_manager_request_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    id;
+} wl_data_device_manager_create_data_source_t;
+
+typedef struct {
+       uint32_t    id;
+       uint32_t    seat;
+} wl_data_device_manager_get_data_device_t;
+
+/***********************************************************
+ * Interface WL_SHELL
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SHELL_GET_SHELL_SURFACE     = 0,
+       WL_NUM_SHELL_REQUESTS          = 1,
+} wl_shell_request_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    id;
+       uint32_t    surface;
+} wl_shell_get_shell_surface_t;
+
+/***********************************************************
+ * Interface WL_SHELL_SURFACE
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SHELL_SURFACE_PONG          = 0,
+       WL_SHELL_SURFACE_MOVE          = 1,
+       WL_SHELL_SURFACE_RESIZE        = 2,
+       WL_SHELL_SURFACE_SET_TOPLEVEL  = 3,
+       WL_SHELL_SURFACE_SET_TRANSIENT = 4,
+       WL_SHELL_SURFACE_SET_FULLSCREEN = 5,
+       WL_SHELL_SURFACE_SET_POPUP     = 6,
+       WL_SHELL_SURFACE_SET_MAXIMIZED = 7,
+       WL_SHELL_SURFACE_SET_TITLE     = 8,
+       WL_SHELL_SURFACE_SET_CLASS     = 9,
+       WL_NUM_SHELL_SURFACE_REQUESTS  = 10,
+} wl_shell_surface_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_SHELL_SURFACE_PING          = 0,
+       WL_SHELL_SURFACE_CONFIGURE     = 1,
+       WL_SHELL_SURFACE_POPUP_DONE    = 2,
+       WL_NUM_SHELL_SURFACE_EVENTS    = 3,
+} wl_shell_surface_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    serial;
+} wl_shell_surface_pong_t;
+
+typedef struct {
+       uint32_t    seat;
+       uint32_t    serial;
+} wl_shell_surface_move_t;
+
+typedef struct {
+       uint32_t    seat;
+       uint32_t    serial;
+       uint32_t    edges;
+} wl_shell_surface_resize_t;
+
+typedef struct {
+       uint32_t    parent;
+       int32_t     x;
+       int32_t     y;
+       uint32_t    flags;
+} wl_shell_surface_set_transient_t;
+
+typedef struct {
+       uint32_t    method;
+       uint32_t    framerate;
+       uint32_t    output;
+} wl_shell_surface_set_fullscreen_t;
+
+typedef struct {
+       uint32_t    seat;
+       uint32_t    serial;
+       uint32_t    parent;
+       int32_t     x;
+       int32_t     y;
+       uint32_t    flags;
+} wl_shell_surface_set_popup_t;
+
+typedef struct {
+       uint32_t    output;
+} wl_shell_surface_set_maximized_t;
+
+typedef struct {
+       wl_string_t title;
+} wl_shell_surface_set_title_t;
+
+typedef struct {
+       wl_string_t class_;
+} wl_shell_surface_set_class_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    serial;
+} wl_shell_surface_ping_t;
+
+typedef struct {
+       uint32_t    edges;
+       int32_t     width;
+       int32_t     height;
+} wl_shell_surface_configure_t;
+
+/***********************************************************
+ * Interface WL_SURFACE
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SURFACE_DESTROY             = 0,
+       WL_SURFACE_ATTACH              = 1,
+       WL_SURFACE_DAMAGE              = 2,
+       WL_SURFACE_FRAME               = 3,
+       WL_SURFACE_SET_OPAQUE_REGION   = 4,
+       WL_SURFACE_SET_INPUT_REGION    = 5,
+       WL_SURFACE_COMMIT              = 6,
+       WL_SURFACE_SET_BUFFER_TRANSFORM = 7,
+       WL_SURFACE_SET_BUFFER_SCALE    = 8,
+       WL_NUM_SURFACE_REQUESTS        = 9,
+} wl_surface_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_SURFACE_ENTER               = 0,
+       WL_SURFACE_LEAVE               = 1,
+       WL_NUM_SURFACE_EVENTS          = 2,
+} wl_surface_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    buffer;
+       int32_t     x;
+       int32_t     y;
+} wl_surface_attach_t;
+
+typedef struct {
+       int32_t     x;
+       int32_t     y;
+       int32_t     width;
+       int32_t     height;
+} wl_surface_damage_t;
+
+typedef struct {
+       uint32_t    callback;
+} wl_surface_frame_t;
+
+typedef struct {
+       uint32_t    region;
+} wl_surface_set_opaque_region_t;
+
+typedef struct {
+       uint32_t    region;
+} wl_surface_set_input_region_t;
+
+typedef struct {
+       int32_t     transform;
+} wl_surface_set_buffer_transform_t;
+
+typedef struct {
+       int32_t     scale;
+} wl_surface_set_buffer_scale_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    output;
+} wl_surface_enter_t;
+
+typedef struct {
+       uint32_t    output;
+} wl_surface_leave_t;
+
+/***********************************************************
+ * Interface WL_SEAT
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SEAT_GET_POINTER            = 0,
+       WL_SEAT_GET_KEYBOARD           = 1,
+       WL_SEAT_GET_TOUCH              = 2,
+       WL_NUM_SEAT_REQUESTS           = 3,
+} wl_seat_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_SEAT_CAPABILITIES           = 0,
+       WL_SEAT_NAME                   = 1,
+       WL_NUM_SEAT_EVENTS             = 2,
+} wl_seat_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    id;
+} wl_seat_get_pointer_t;
+
+typedef struct {
+       uint32_t    id;
+} wl_seat_get_keyboard_t;
+
+typedef struct {
+       uint32_t    id;
+} wl_seat_get_touch_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    capabilities;
+} wl_seat_capabilities_t;
+
+typedef struct {
+       wl_string_t name;
+} wl_seat_name_t;
+
+/***********************************************************
+ * Interface WL_POINTER
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_POINTER_SET_CURSOR          = 0,
+       WL_POINTER_RELEASE             = 1,
+       WL_NUM_POINTER_REQUESTS        = 2,
+} wl_pointer_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_POINTER_ENTER               = 0,
+       WL_POINTER_LEAVE               = 1,
+       WL_POINTER_MOTION              = 2,
+       WL_POINTER_BUTTON              = 3,
+       WL_POINTER_AXIS                = 4,
+       WL_NUM_POINTER_EVENTS          = 5,
+} wl_pointer_event_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    serial;
+       uint32_t    surface;
+       int32_t     hotspot_x;
+       int32_t     hotspot_y;
+} wl_pointer_set_cursor_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    serial;
+       uint32_t    surface;
+       wl_fixed_t  surface_x;
+       wl_fixed_t  surface_y;
+} wl_pointer_enter_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    surface;
+} wl_pointer_leave_t;
+
+typedef struct {
+       uint32_t    time;
+       wl_fixed_t  surface_x;
+       wl_fixed_t  surface_y;
+} wl_pointer_motion_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    time;
+       uint32_t    button;
+       uint32_t    state;
+} wl_pointer_button_t;
+
+typedef struct {
+       uint32_t    time;
+       uint32_t    axis;
+       wl_fixed_t  value;
+} wl_pointer_axis_t;
+
+/***********************************************************
+ * Interface WL_KEYBOARD
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_KEYBOARD_RELEASE            = 0,
+       WL_NUM_KEYBOARD_REQUESTS       = 1,
+} wl_keyboard_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_KEYBOARD_KEYMAP             = 0,
+       WL_KEYBOARD_ENTER              = 1,
+       WL_KEYBOARD_LEAVE              = 2,
+       WL_KEYBOARD_KEY                = 3,
+       WL_KEYBOARD_MODIFIERS          = 4,
+       WL_KEYBOARD_REPEAT_INFO        = 5,
+       WL_NUM_KEYBOARD_EVENTS         = 6,
+} wl_keyboard_event_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    format;
+       uint32_t    size;
+} wl_keyboard_keymap_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    surface;
+       wl_array_t  keys;
+} wl_keyboard_enter_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    surface;
+} wl_keyboard_leave_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    time;
+       uint32_t    key;
+       uint32_t    state;
+} wl_keyboard_key_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    mods_depressed;
+       uint32_t    mods_latched;
+       uint32_t    mods_locked;
+       uint32_t    group;
+} wl_keyboard_modifiers_t;
+
+typedef struct {
+       int32_t     rate;
+       int32_t     delay;
+} wl_keyboard_repeat_info_t;
+
+/***********************************************************
+ * Interface WL_TOUCH
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_TOUCH_RELEASE               = 0,
+       WL_NUM_TOUCH_REQUESTS          = 1,
+} wl_touch_request_t;
+
+/* Event IDs */
+typedef enum {
+       WL_TOUCH_DOWN                  = 0,
+       WL_TOUCH_UP                    = 1,
+       WL_TOUCH_MOTION                = 2,
+       WL_TOUCH_FRAME                 = 3,
+       WL_TOUCH_CANCEL                = 4,
+       WL_NUM_TOUCH_EVENTS            = 5,
+} wl_touch_event_t;
+
+/* Events Messages */
+typedef struct {
+       uint32_t    serial;
+       uint32_t    time;
+       uint32_t    surface;
+       int32_t     id;
+       wl_fixed_t  x;
+       wl_fixed_t  y;
+} wl_touch_down_t;
+
+typedef struct {
+       uint32_t    serial;
+       uint32_t    time;
+       int32_t     id;
+} wl_touch_up_t;
+
+typedef struct {
+       uint32_t    time;
+       int32_t     id;
+       wl_fixed_t  x;
+       wl_fixed_t  y;
+} wl_touch_motion_t;
+
+/***********************************************************
+ * Interface WL_OUTPUT
+ ***********************************************************/
+
+/* Event IDs */
+typedef enum {
+       WL_OUTPUT_GEOMETRY             = 0,
+       WL_OUTPUT_MODE                 = 1,
+       WL_OUTPUT_DONE                 = 2,
+       WL_OUTPUT_SCALE                = 3,
+       WL_NUM_OUTPUT_EVENTS           = 4,
+} wl_output_event_t;
+
+/* Events Messages */
+typedef struct {
+       int32_t     x;
+       int32_t     y;
+       int32_t     physical_width;
+       int32_t     physical_height;
+       int32_t     subpixel;
+       wl_string_t make;
+       wl_string_t model;
+       int32_t     transform;
+} wl_output_geometry_t;
+
+typedef struct {
+       uint32_t    flags;
+       int32_t     width;
+       int32_t     height;
+       int32_t     refresh;
+} wl_output_mode_t;
+
+typedef struct {
+       int32_t     factor;
+} wl_output_scale_t;
+
+/***********************************************************
+ * Interface WL_REGION
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_REGION_DESTROY              = 0,
+       WL_REGION_ADD                  = 1,
+       WL_REGION_SUBTRACT             = 2,
+       WL_NUM_REGION_REQUESTS         = 3,
+} wl_region_request_t;
+
+/* Requests Messages */
+typedef struct {
+       int32_t     x;
+       int32_t     y;
+       int32_t     width;
+       int32_t     height;
+} wl_region_add_t;
+
+typedef struct {
+       int32_t     x;
+       int32_t     y;
+       int32_t     width;
+       int32_t     height;
+} wl_region_subtract_t;
+
+/***********************************************************
+ * Interface WL_SUBCOMPOSITOR
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SUBCOMPOSITOR_DESTROY       = 0,
+       WL_SUBCOMPOSITOR_GET_SUBSURFACE = 1,
+       WL_NUM_SUBCOMPOSITOR_REQUESTS  = 2,
+} wl_subcompositor_request_t;
+
+/* Requests Messages */
+typedef struct {
+       uint32_t    id;
+       uint32_t    surface;
+       uint32_t    parent;
+} wl_subcompositor_get_subsurface_t;
+
+/***********************************************************
+ * Interface WL_SUBSURFACE
+ ***********************************************************/
+
+/* Request IDs */
+typedef enum {
+       WL_SUBSURFACE_DESTROY          = 0,
+       WL_SUBSURFACE_SET_POSITION     = 1,
+       WL_SUBSURFACE_PLACE_ABOVE      = 2,
+       WL_SUBSURFACE_PLACE_BELOW      = 3,
+       WL_SUBSURFACE_SET_SYNC         = 4,
+       WL_SUBSURFACE_SET_DESYNC       = 5,
+       WL_NUM_SUBSURFACE_REQUESTS     = 6,
+} wl_subsurface_request_t;
+
+/* Requests Messages */
+typedef struct {
+       int32_t     x;
+       int32_t     y;
+} wl_subsurface_set_position_t;
+
+typedef struct {
+       uint32_t    sibling;
+} wl_subsurface_place_above_t;
+
+typedef struct {
+       uint32_t    sibling;
+} wl_subsurface_place_below_t;
+
+/* Union messages */
+typedef union {
+       wl_display_sync_t                                  wl_display_sync;
+       wl_display_get_registry_t                          wl_display_get_registry;
+       wl_registry_bind_t                                 wl_registry_bind;
+       wl_compositor_create_surface_t                     wl_compositor_create_surface;
+       wl_compositor_create_region_t                      wl_compositor_create_region;
+       wl_shm_pool_create_buffer_t                        wl_shm_pool_create_buffer;
+       wl_shm_pool_resize_t                               wl_shm_pool_resize;
+       wl_shm_create_pool_t                               wl_shm_create_pool;
+       wl_data_offer_accept_t                             wl_data_offer_accept;
+       wl_data_offer_receive_t                            wl_data_offer_receive;
+       wl_data_source_offer_t                             wl_data_source_offer;
+       wl_data_device_start_drag_t                        wl_data_device_start_drag;
+       wl_data_device_set_selection_t                     wl_data_device_set_selection;
+       wl_data_device_manager_create_data_source_t        wl_data_device_manager_create_data_source;
+       wl_data_device_manager_get_data_device_t           wl_data_device_manager_get_data_device;
+       wl_shell_get_shell_surface_t                       wl_shell_get_shell_surface;
+       wl_shell_surface_pong_t                            wl_shell_surface_pong;
+       wl_shell_surface_move_t                            wl_shell_surface_move;
+       wl_shell_surface_resize_t                          wl_shell_surface_resize;
+       wl_shell_surface_set_transient_t                   wl_shell_surface_set_transient;
+       wl_shell_surface_set_fullscreen_t                  wl_shell_surface_set_fullscreen;
+       wl_shell_surface_set_popup_t                       wl_shell_surface_set_popup;
+       wl_shell_surface_set_maximized_t                   wl_shell_surface_set_maximized;
+       wl_shell_surface_set_title_t                       wl_shell_surface_set_title;
+       wl_shell_surface_set_class_t                       wl_shell_surface_set_class;
+       wl_surface_attach_t                                wl_surface_attach;
+       wl_surface_damage_t                                wl_surface_damage;
+       wl_surface_frame_t                                 wl_surface_frame;
+       wl_surface_set_opaque_region_t                     wl_surface_set_opaque_region;
+       wl_surface_set_input_region_t                      wl_surface_set_input_region;
+       wl_surface_set_buffer_transform_t                  wl_surface_set_buffer_transform;
+       wl_surface_set_buffer_scale_t                      wl_surface_set_buffer_scale;
+       wl_seat_get_pointer_t                              wl_seat_get_pointer;
+       wl_seat_get_keyboard_t                             wl_seat_get_keyboard;
+       wl_seat_get_touch_t                                wl_seat_get_touch;
+       wl_pointer_set_cursor_t                            wl_pointer_set_cursor;
+       wl_region_add_t                                    wl_region_add;
+       wl_region_subtract_t                               wl_region_subtract;
+       wl_subcompositor_get_subsurface_t                  wl_subcompositor_get_subsurface;
+       wl_subsurface_set_position_t                       wl_subsurface_set_position;
+       wl_subsurface_place_above_t                        wl_subsurface_place_above;
+       wl_subsurface_place_below_t                        wl_subsurface_place_below;
+} wl_request_t;
+
+typedef union {
+       wl_display_error_t                                 wl_display_error;
+       wl_display_delete_id_t                             wl_display_delete_id;
+       wl_registry_global_t                               wl_registry_global;
+       wl_registry_global_remove_t                        wl_registry_global_remove;
+       wl_callback_done_t                                 wl_callback_done;
+       wl_shm_format_t                                    wl_shm_format;
+       wl_data_offer_offer_t                              wl_data_offer_offer;
+       wl_data_source_target_t                            wl_data_source_target;
+       wl_data_source_send_t                              wl_data_source_send;
+       wl_data_device_data_offer_t                        wl_data_device_data_offer;
+       wl_data_device_enter_t                             wl_data_device_enter;
+       wl_data_device_motion_t                            wl_data_device_motion;
+       wl_data_device_selection_t                         wl_data_device_selection;
+       wl_shell_surface_ping_t                            wl_shell_surface_ping;
+       wl_shell_surface_configure_t                       wl_shell_surface_configure;
+       wl_surface_enter_t                                 wl_surface_enter;
+       wl_surface_leave_t                                 wl_surface_leave;
+       wl_seat_capabilities_t                             wl_seat_capabilities;
+       wl_seat_name_t                                     wl_seat_name;
+       wl_pointer_enter_t                                 wl_pointer_enter;
+       wl_pointer_leave_t                                 wl_pointer_leave;
+       wl_pointer_motion_t                                wl_pointer_motion;
+       wl_pointer_button_t                                wl_pointer_button;
+       wl_pointer_axis_t                                  wl_pointer_axis;
+       wl_keyboard_keymap_t                               wl_keyboard_keymap;
+       wl_keyboard_enter_t                                wl_keyboard_enter;
+       wl_keyboard_leave_t                                wl_keyboard_leave;
+       wl_keyboard_key_t                                  wl_keyboard_key;
+       wl_keyboard_modifiers_t                            wl_keyboard_modifiers;
+       wl_keyboard_repeat_info_t                          wl_keyboard_repeat_info;
+       wl_touch_down_t                                    wl_touch_down;
+       wl_touch_up_t                                      wl_touch_up;
+       wl_touch_motion_t                                  wl_touch_motion;
+       wl_output_geometry_t                               wl_output_geometry;
+       wl_output_mode_t                                   wl_output_mode;
+       wl_output_scale_t                                  wl_output_scale;
+} wl_event_t;
+
+/***********************************************************
+ * Arrays and Strings
+ ***********************************************************/
+
+/* Constants */
+#define WL_ARRAY_NONE   '-'
+#define WL_ARRAY_STRING 's'
+#define WL_ARRAY_ARRAY  'a'
+#define WL_ARRAY_FD     'f'
+
+extern const char **wl_rarray[WL_NUM_INTERFACES];
+extern const char **wl_earray[WL_NUM_INTERFACES];
+
+/* Request Array */
+#ifdef WL_DEFINE_TABLES
+const char **wl_rarray[WL_NUM_INTERFACES] = {
+       [WL_SHM] (const char *[WL_NUM_SHM_REQUESTS]) {
+               [WL_SHM_CREATE_POOL]           "-f-",
+       },
+       [WL_DATA_OFFER] (const char *[WL_NUM_DATA_OFFER_REQUESTS]) {
+               [WL_DATA_OFFER_ACCEPT]         "-s",
+               [WL_DATA_OFFER_RECEIVE]        "sf",
+       },
+       [WL_DATA_SOURCE] (const char *[WL_NUM_DATA_SOURCE_REQUESTS]) {
+               [WL_DATA_SOURCE_OFFER]         "s",
+       },
+       [WL_SHELL_SURFACE] (const char *[WL_NUM_SHELL_SURFACE_REQUESTS]) {
+               [WL_SHELL_SURFACE_SET_TITLE]   "s",
+               [WL_SHELL_SURFACE_SET_CLASS]   "s",
+       },
+};
+#endif
+
+/* Event Array */
+#ifdef WL_DEFINE_TABLES
+const char **wl_earray[WL_NUM_INTERFACES] = {
+       [WL_DISPLAY] (const char *[WL_NUM_DISPLAY_EVENTS]) {
+               [WL_DISPLAY_ERROR]             "--s",
+       },
+       [WL_REGISTRY] (const char *[WL_NUM_REGISTRY_EVENTS]) {
+               [WL_REGISTRY_GLOBAL]           "-s-",
+       },
+       [WL_DATA_OFFER] (const char *[WL_NUM_DATA_OFFER_EVENTS]) {
+               [WL_DATA_OFFER_OFFER]          "s",
+       },
+       [WL_DATA_SOURCE] (const char *[WL_NUM_DATA_SOURCE_EVENTS]) {
+               [WL_DATA_SOURCE_TARGET]        "s",
+               [WL_DATA_SOURCE_SEND]          "sf",
+       },
+       [WL_SEAT] (const char *[WL_NUM_SEAT_EVENTS]) {
+               [WL_SEAT_NAME]                 "s",
+       },
+       [WL_KEYBOARD] (const char *[WL_NUM_KEYBOARD_EVENTS]) {
+               [WL_KEYBOARD_KEYMAP]           "-f-",
+               [WL_KEYBOARD_ENTER]            "--a",
+       },
+       [WL_OUTPUT] (const char *[WL_NUM_OUTPUT_EVENTS]) {
+               [WL_OUTPUT_GEOMETRY]           "-----ss-",
+       },
+};
+#endif
+
+#endif
diff --git a/wayland.sh b/wayland.sh
new file mode 100755 (executable)
index 0000000..0a8f9d0
--- /dev/null
@@ -0,0 +1,265 @@
+#!/bin/bash
+
+# Formatting helpers
+function comment {
+       echo "/* $* */"
+}
+
+function banner {
+       echo "/***********************************************************"
+       echo " * $1"                                                  
+       echo " ***********************************************************/"
+}
+
+function enum {
+       printf "\t%-30s = %s,\n" "$(upper $1)" "$2"
+}
+
+function upper {
+       echo $1 | tr 'a-z' 'A-Z'
+}
+
+# XPath Helpers
+function xpath {
+       xmllint --xpath $1 wayland.xml
+}
+
+function xpathv {
+       xpath $1 | sed -r 's/\w+="([^"]+)"/\1/g'
+}
+
+function exists {
+       xpath "$1" > /dev/null 2>&1
+}
+
+function isarray {
+       exists "$1/arg[@type='string']|$1/arg[@type='array']|$1/arg[@type='fd']"
+}
+
+# Message helpers
+function msg_field {
+       case $1 in
+               int)    echo -e "\tint32_t     $2;"  ;;
+               uint)   echo -e "\tuint32_t    $2;"  ;;
+               new_id) echo -e "\tuint32_t    $2;"  ;;
+               object) echo -e "\tuint32_t    $2;"  ;;
+               fixed)  echo -e "\twl_fixed_t  $2;"  ;;
+               array)  echo -e "\twl_array_t  $2;"  ;;
+               string) echo -e "\twl_string_t $2;"  ;;
+               fd)     ;;
+       esac
+}
+
+function msg_array {
+       for t in $(xpathv "$1"); do
+               case $t in
+                       array)  echo -n "a" ;;
+                       string) echo -n "s" ;;
+                       fd)     echo -n "f" ;;
+                       *)      echo -n "-" ;;
+               esac
+       done
+}
+
+# Interface functions
+function print_iface_vers {
+       local vers
+       for i in $IFACES; do
+               vers=$(xpath "string(/protocol/interface[@name='$i']/@version)")
+               printf "#define %-32s %s\n" "$(upper ${i}_version)" "$vers"
+       done
+}
+
+function print_iface_enum {
+       local cnt
+       cnt=0
+       for i in $IFACES; do
+               enum "${i}" $((cnt++))
+       done
+       enum "wl_num_interfaces" $((cnt++))
+}
+
+# Enumeration functions
+function print_enums {
+       local base k v
+       base="/protocol/interface[@name='$i']/enum"
+       if exists "$base"; then
+               comment $1
+               for e in $(xpathv "$base/@name"); do
+                       echo "typedef enum {"
+                       for n in $(xpathv "$base[@name='$e']/entry/@name"); do
+                               k="$base[@name='$e']/entry[@name='$n']/@value"
+                               v=$(xpath "string($k)")
+                               printf "\t%-40s = %s,\n" \
+                                       "$(upper "${i}_${e}_${n}")" "$v"
+                       done
+                       echo "} ${i}_${e};"
+                       echo
+               done
+       fi
+}
+
+# Message functions
+function print_msg_ids {
+       local cnt base
+       cnt=0
+       base="/protocol/interface[@name='$IFACE']/$2"
+       if exists "$base"; then
+               comment $1
+               echo "typedef enum {"
+               for r in $(xpathv "$base/@name"); do
+                       enum "${IFACE}_${r}" $((cnt++))
+               done
+               enum "${IFACE/wl/wl_num}_${2}s" $((cnt++))
+               echo "} ${IFACE}_${2}_t;"
+               echo
+       fi
+}
+
+function print_msg_defs {
+       local base msgs args k t
+       base="/protocol/interface[@name='$IFACE']/$2"
+       if exists "$base/arg"; then
+               comment $1
+               msgs=$(xpathv "$base/@name")
+               for m in $msgs; do
+                       if exists "$base[@name='$m']/arg"; then
+                               echo "typedef struct {"
+                               args=$(xpathv "$base[@name='$m']/arg/@name")
+                               for a in $args; do
+                                       k="$base[@name='$m']/arg[@name='$a']/@type"
+                                       t=$(xpath "string($k)")
+                                       msg_field "$t" "$a"
+                               done
+                               echo "} ${IFACE}_${m}_t;"
+                               echo
+                       fi
+               done
+       fi
+}
+
+function print_msg_union {
+       local base t n
+       for IFACE in $IFACES; do
+               base="/protocol/interface[@name='$IFACE']/$1"
+               if exists "$base"; then
+                       for r in $(xpathv "$base/@name"); do
+                               if exists "$base[@name='$r']/arg"; then
+                                       t="${IFACE}_${r}_t"
+                                       n="${IFACE}_${r/wl_/}"
+                                       printf '\t%-50s %s;\n' "$t" "$n"
+                               fi
+                       done
+               fi
+       done
+}
+
+function print_msg_table {
+       local base size idx str
+       for IFACE in $IFACES; do
+               base="/protocol/interface[@name='$IFACE']/$1"
+               size="$(upper "${IFACE/wl/wl_num}_${1}s")"
+               if isarray "$base"; then
+                       echo -e "\t[$(upper $IFACE)] (const char *[$size]) {"
+                       for r in $(xpathv "$base/@name"); do
+                               if isarray "$base[@name='$r']"; then
+                                       idx="$(upper "${IFACE}_${r}")"
+                                       str="$(msg_array "$base[@name='$r']/arg/@type")"
+                                       printf '\t\t%-30s "%s",\n' "[$idx]" "$str"
+                               fi
+                       done
+                       echo -e "\t},"
+               fi
+       done
+}
+
+# Main
+IFACES=$(xpathv "/protocol/interface/@name")
+
+cat <<EOF
+#ifndef WAYLAND_H
+#define WAYLAND_H
+
+#include <stdint.h>
+
+$(banner "Common Types")
+
+#define WL_MESSAGE_LEN 4096
+
+typedef struct {
+       uint32_t id;
+       uint32_t len : 16;
+       uint32_t op  : 16;
+} wl_header_t;
+
+typedef struct {
+       uint32_t len;
+       char    *str;
+} wl_string_t;
+
+typedef struct {
+       uint32_t len;
+       void    *data;
+} wl_array_t;
+
+typedef struct {
+       uint32_t num  : 24;
+       uint32_t frac : 8;
+} wl_fixed_t;
+
+$(banner "Interfaces")
+
+/* Interface Versions */
+$(print_iface_vers)
+
+/* Interface IDs */
+typedef enum {
+$(print_iface_enum)
+} wl_interface_t;
+
+$(for IFACE in $IFACES; do
+       banner "Interface $(upper $IFACE)"
+       echo
+       print_msg_ids  "Request IDs"       request
+       print_msg_ids  "Event IDs"         event
+       print_enums    "Enumerations"      
+       print_msg_defs "Requests Messages" request
+       print_msg_defs "Events Messages"   event
+done)
+
+/* Union messages */
+typedef union {
+$(print_msg_union request)
+} wl_request_t;
+
+typedef union {
+$(print_msg_union event)
+} wl_event_t;
+
+$(banner "Arrays and Strings")
+
+/* Constants */
+#define WL_ARRAY_NONE   '-'
+#define WL_ARRAY_STRING 's'
+#define WL_ARRAY_ARRAY  'a'
+#define WL_ARRAY_FD     'f'
+
+extern const char **wl_rarray[WL_NUM_INTERFACES];
+extern const char **wl_earray[WL_NUM_INTERFACES];
+
+/* Request Array */
+#ifdef WL_DEFINE_TABLES
+const char **wl_rarray[WL_NUM_INTERFACES] = {
+$(print_msg_table request)
+};
+#endif
+
+/* Event Array */
+#ifdef WL_DEFINE_TABLES
+const char **wl_earray[WL_NUM_INTERFACES] = {
+$(print_msg_table event)
+};
+#endif
+
+#endif
+EOF