Update to new fd and wl_registry APIs

This commit updates the clients and the wayland compositor backend to
use the new wl_registry mechanism and the thread safe fd API.
diff --git a/clients/window.c b/clients/window.c
index b19c579..8ea453d 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
 #include <math.h>
 #include <assert.h>
 #include <time.h>
@@ -69,8 +70,16 @@
 
 struct shm_pool;
 
+struct global {
+	uint32_t name;
+	char *interface;
+	uint32_t version;
+	struct wl_list link;
+};
+
 struct display {
 	struct wl_display *display;
+	struct wl_registry *registry;
 	struct wl_compositor *compositor;
 	struct wl_shell *shell;
 	struct wl_shm *shm;
@@ -85,7 +94,6 @@
 
 	int display_fd;
 	uint32_t display_fd_events;
-	uint32_t mask;
 	struct task display_task;
 
 	int epoll_fd;
@@ -93,6 +101,7 @@
 
 	int running;
 
+	struct wl_list global_list;
 	struct wl_list window_list;
 	struct wl_list input_list;
 	struct wl_list output_list;
@@ -107,6 +116,7 @@
 	PFNEGLDESTROYIMAGEKHRPROC destroy_image;
 
 	display_output_handler_t output_configure_handler;
+	display_global_handler_t global_handler;
 
 	void *user_data;
 
@@ -3495,7 +3505,7 @@
 	memset(output, 0, sizeof *output);
 	output->display = d;
 	output->output =
-		wl_display_bind(d->display, id, &wl_output_interface);
+		wl_registry_bind(d->registry, id, &wl_output_interface, 1);
 	wl_list_insert(d->output_list.prev, &output->link);
 
 	wl_output_add_listener(output->output, &output_listener, output);
@@ -3513,6 +3523,22 @@
 }
 
 void
+display_set_global_handler(struct display *display,
+			   display_global_handler_t handler)
+{
+	struct global *global;
+
+	display->global_handler = handler;
+	if (!handler)
+		return;
+
+	wl_list_for_each(global, &display->global_list, link)
+		display->global_handler(display,
+					global->name, global->interface,
+					global->version, display->user_data);
+}
+
+void
 display_set_output_configure_handler(struct display *display,
 				     display_output_handler_t handler)
 {
@@ -3590,7 +3616,7 @@
 
 	memset(input, 0, sizeof *input);
 	input->display = d;
-	input->seat = wl_display_bind(d->display, id, &wl_seat_interface);
+	input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
 	input->pointer_focus = NULL;
 	input->keyboard_focus = NULL;
 	wl_list_insert(d->input_list.prev, &input->link);
@@ -3640,7 +3666,8 @@
 init_workspace_manager(struct display *d, uint32_t id)
 {
 	d->workspace_manager =
-		wl_display_bind(d->display, id, &workspace_manager_interface);
+		wl_registry_bind(d->registry, id,
+				 &workspace_manager_interface, 1);
 	if (d->workspace_manager != NULL)
 		workspace_manager_add_listener(d->workspace_manager,
 					       &workspace_manager_listener,
@@ -3648,35 +3675,57 @@
 }
 
 static void
-display_handle_global(struct wl_display *display, uint32_t id,
-		      const char *interface, uint32_t version, void *data)
+registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
+		       const char *interface, uint32_t version)
 {
 	struct display *d = data;
+	struct global *global;
+
+	global = malloc(sizeof *global);
+	global->name = id;
+	global->interface = strdup(interface);
+	global->version = version;
+	wl_list_insert(d->global_list.prev, &global->link);
 
 	if (strcmp(interface, "wl_compositor") == 0) {
-		d->compositor =
-			wl_display_bind(display, id, &wl_compositor_interface);
+		d->compositor = wl_registry_bind(registry, id,
+						 &wl_compositor_interface, 1);
 	} else if (strcmp(interface, "wl_output") == 0) {
 		display_add_output(d, id);
 	} else if (strcmp(interface, "wl_seat") == 0) {
 		display_add_input(d, id);
 	} else if (strcmp(interface, "wl_shell") == 0) {
-		d->shell = wl_display_bind(display, id, &wl_shell_interface);
+		d->shell = wl_registry_bind(registry,
+					    id, &wl_shell_interface, 1);
 	} else if (strcmp(interface, "wl_shm") == 0) {
-		d->shm = wl_display_bind(display, id, &wl_shm_interface);
+		d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
 	} else if (strcmp(interface, "wl_data_device_manager") == 0) {
 		d->data_device_manager =
-			wl_display_bind(display, id,
-					&wl_data_device_manager_interface);
+			wl_registry_bind(registry, id,
+					 &wl_data_device_manager_interface, 1);
 	} else if (strcmp(interface, "text_cursor_position") == 0) {
 		d->text_cursor_position =
-			wl_display_bind(display, id,
-					&text_cursor_position_interface);
+			wl_registry_bind(registry, id,
+					 &text_cursor_position_interface, 1);
 	} else if (strcmp(interface, "workspace_manager") == 0) {
 		init_workspace_manager(d, id);
 	}
+
+	if (d->global_handler)
+		d->global_handler(d, id, interface, version, d->user_data);
 }
 
+void *
+display_bind(struct display *display, uint32_t name,
+	     const struct wl_interface *interface, uint32_t version)
+{
+	return wl_registry_bind(display->registry, name, interface, version);
+}
+
+static const struct wl_registry_listener registry_listener = {
+	registry_handle_global
+};
+
 #ifdef HAVE_CAIRO_EGL
 static int
 init_egl(struct display *d)
@@ -3767,21 +3816,13 @@
 }
 #endif
 
-static int
-event_mask_update(uint32_t mask, void *data)
-{
-	struct display *d = data;
-
-	d->mask = mask;
-
-	return 0;
-}
-
 static void
 handle_display_data(struct task *task, uint32_t events)
 {
 	struct display *display =
 		container_of(task, struct display, display_task);
+	struct epoll_event ep;
+	int ret;
 
 	display->display_fd_events = events;
 
@@ -3790,7 +3831,21 @@
 		return;
 	}
 
-	wl_display_iterate(display->display, display->mask);
+	if (events & EPOLLIN)
+		wl_display_dispatch(display->display);
+
+	if (events & EPOLLOUT) {
+		ret = wl_display_flush(display->display);
+		if (ret == 0) {
+			ep.events = EPOLLIN | EPOLLERR | EPOLLHUP;
+			ep.data.ptr = &display->display_task;
+			epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD,
+				  display->display_fd, &ep);
+		} else if (ret == -1 && errno != EAGAIN) {
+			display_exit(display);
+			return;
+		}
+	}
 }
 
 struct display *
@@ -3811,7 +3866,7 @@
 	}
 
 	d->epoll_fd = os_epoll_create_cloexec();
-	d->display_fd = wl_display_get_fd(d->display, event_mask_update, d);
+	d->display_fd = wl_display_get_fd(d->display);
 	d->display_task.run = handle_display_data;
 	display_watch_fd(d, d->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP,
 			 &d->display_task);
@@ -3819,6 +3874,7 @@
 	wl_list_init(&d->deferred_list);
 	wl_list_init(&d->input_list);
 	wl_list_init(&d->output_list);
+	wl_list_init(&d->global_list);
 
 	d->xkb_context = xkb_context_new(0);
 	if (d->xkb_context == NULL) {
@@ -3829,12 +3885,9 @@
 	d->workspace = 0;
 	d->workspace_count = 1;
 
-	/* Set up listener so we'll catch all events. */
-	wl_display_add_global_listener(d->display,
-				       display_handle_global, d);
-
-	/* Process connection events. */
-	wl_display_iterate(d->display, WL_DISPLAY_READABLE);
+	d->registry = wl_display_get_registry(d->display);
+	wl_registry_add_listener(d->registry, &registry_listener, d);
+	wl_display_dispatch(d->display);
 #ifdef HAVE_CAIRO_EGL
 	if (init_egl(d) < 0)
 		return NULL;
@@ -4052,12 +4105,10 @@
 {
 	struct task *task;
 	struct epoll_event ep[16];
-	int i, count;
+	int i, count, ret;
 
 	display->running = 1;
 	while (1) {
-		wl_display_flush(display->display);
-
 		while (!wl_list_empty(&display->deferred_list)) {
 			task = container_of(display->deferred_list.prev,
 					    struct task, link);
@@ -4068,7 +4119,17 @@
 		if (!display->running)
 			break;
 
-		wl_display_flush(display->display);
+		ret = wl_display_flush(display->display);
+		if (ret < 0 && errno == EAGAIN) {
+			ep[0].events =
+				EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP;
+			ep[0].data.ptr = &display->display_task;
+
+			epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD,
+				  display->display_fd, &ep[0]);
+		} else if (ret < 0) {
+			break;
+		}
 
 		count = epoll_wait(display->epoll_fd,
 				   ep, ARRAY_LENGTH(ep), -1);