Bunch of new stuff: simple compositor, cairo+gem use in client, events.
diff --git a/client.c b/client.c
index 8312be8..d01ed2c 100644
--- a/client.c
+++ b/client.c
@@ -1,109 +1,135 @@
-#include <stdlib.h>
 #include <stdint.h>
-#include <stddef.h>
 #include <stdio.h>
-#include <errno.h>
+#include <stdlib.h>
 #include <string.h>
+#include <i915_drm.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
 #include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <ctype.h>
+#include <math.h>
+#include <cairo.h>
 
+#include "wayland-client.h"
+
+static const char gem_device[] = "/dev/dri/card0";
 static const char socket_name[] = "\0wayland";
 
-struct method {
-	const char *name;
-	uint32_t opcode;
-};
-
-static const struct method display_methods[] = {
-	{ "get_interface", 0 },
-	{ "create_surface", 1 },
-	{ NULL }
-};
-
-static const struct method surface_methods[] = {
-	{ "get_interface", 0 },
-	{ "post", 1 },
-	{ NULL }
-};
-
-struct interface {
-	const char *name;
-	const struct method *methods;
-};
-
-static const struct interface interfaces[] = {
-	{ "display", display_methods },
-	{ "surface", surface_methods },
-	{ NULL },
-};
-
-int send_request(int sock, const char *buffer, int buffer_len)
+static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
 {
-	const struct method *methods;
-	char interface[32], method[32];
-	uint32_t request[3], id, new_id;
-	int i;
+	struct drm_i915_gem_create create;
+	struct drm_gem_flink flink;
+	struct drm_i915_gem_pwrite pwrite;
+	int32_t width, height, stride;
 
-	if (sscanf(buffer, "%d/%32[^:]:%32s %d\n",
-		   &id, interface, method, &new_id) != 4) {
-		printf("invalid input, expected <id>/<interface>:<method>\n");
-		return -1;
+	width = cairo_image_surface_get_width(surface);
+	height = cairo_image_surface_get_height(surface);
+	stride = cairo_image_surface_get_stride(surface);
+
+	memset(&create, 0, sizeof(create));
+	create.size = height * stride;
+
+	if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
+		fprintf(stderr, "gem create failed: %m\n");
+		return 0;
 	}
 
-	printf("got object id %d, interface \"%s\", name \"%s\"\n",
-	       id, interface, method);
-
-	for (i = 0; interfaces[i].name != NULL; i++) {
-		if (strcmp(interfaces[i].name, interface) == 0)
-			break;
-	}
-	if (interfaces[i].name == NULL) {
-		printf("unknown interface \"%s\"\n", interface);
-		return -1;
+	pwrite.handle = create.handle;
+	pwrite.offset = 0;
+	pwrite.size = height * stride;
+	pwrite.data_ptr = (uint64_t) (uintptr_t)
+		cairo_image_surface_get_data(surface);
+	if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
+		fprintf(stderr, "gem pwrite failed: %m\n");
+		return 0;
 	}
 
-	methods = interfaces[i].methods;
-	for (i = 0; methods[i].name != NULL; i++) {
-		if (strcmp(methods[i].name, method) == 0)
-			break;
+	flink.handle = create.handle;
+	if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
+		fprintf(stderr, "gem flink failed: %m\n");
+		return 0;
 	}
 
-	if (methods[i].name == NULL) {
-		printf("unknown request \"%s\"\n", method);
-		return -1;
+#if 0
+	/* We need to hold on to the handle until the server has received
+	 * the attach request... we probably need a confirmation event.
+	 * I guess the breadcrumb idea will suffice. */
+	struct drm_gem_close close;
+	close.handle = create.handle;
+	if (ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) {
+		fprintf(stderr, "gem close failed: %m\n");
+		return 0;
 	}
+#endif
 
-	request[0] = id;
-	request[1] = methods[i].opcode;
-	request[2] = new_id;
+	return flink.name;
+}
 
-	return write(sock, request, sizeof request);
+static void *
+draw_stuff(int width, int height)
+{
+	cairo_surface_t *surface;
+	cairo_t *cr;
+
+	surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
+					     width, height);
+
+	cr = cairo_create(surface);
+
+	cairo_arc(cr, width / 2, height / 2, width / 2 - 10, 0, 2 * M_PI);
+	cairo_set_source_rgb(cr, 1, 0, 0);
+	cairo_fill_preserve(cr);
+	cairo_set_source_rgb(cr, 1, 1, 0);
+	cairo_stroke(cr);
+
+	cairo_arc(cr, width / 2, height / 2, width / 4 - 10, 0, 2 * M_PI);
+	cairo_set_source_rgb(cr, 0, 0, 1);
+	cairo_fill_preserve(cr);
+	cairo_set_source_rgb(cr, 1, 1, 0);
+	cairo_stroke(cr);
+
+	cairo_destroy(cr);
+
+	return surface;
 }
 
 int main(int argc, char *argv[])
 {
-	struct sockaddr_un name;
-	socklen_t size;
-	int sock, len;
-	char buffer[256];
+	struct wl_connection *connection;
+	struct wl_display *display;
+	struct wl_surface *surface;
+	int width = 300, height = 300, fd;
+	uint32_t name;
+	cairo_surface_t *s;
 
-	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
-	if (sock < 0)
+	fd = open(gem_device, O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "drm open failed: %m\n");
 		return -1;
+	}
 
-	name.sun_family = AF_LOCAL;
-	memcpy(name.sun_path, socket_name, sizeof socket_name);
-
-	size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
-
-	if (connect (sock, (struct sockaddr *) &name, size) < 0)
+	connection = wl_connection_create(socket_name);
+	if (connection == NULL) {
+		fprintf(stderr, "failed to create connection: %m\n");
 		return -1;
+	}
 
-	while (len = read(STDIN_FILENO, buffer, sizeof buffer), len > 0)
-		if (send_request(sock, buffer, len) < 0)
-			break;
+	display = wl_connection_get_display(connection);
+
+	surface = wl_display_create_surface(display);
+
+	s = draw_stuff(width, height);
+	name = name_cairo_surface(fd, s);
+
+	wl_surface_attach(surface, name, width, height,
+			  cairo_image_surface_get_stride(s));
+
+	if (wl_connection_flush(connection) < 0) {
+		fprintf(stderr, "flush error: %m\n");
+		return -1;
+	}
+
+	while (1)
+		wl_connection_iterate(connection);
 
 	return 0;
 }