clients: Bring clients up to date
diff --git a/clients/dnd.c b/clients/dnd.c
index 802d766..f598e38 100644
--- a/clients/dnd.c
+++ b/clients/dnd.c
@@ -495,7 +495,8 @@
 	if (strcmp(interface, "wl_drag_offer") != 0)
 		return;
 
-	offer = wl_drag_offer_create(display_get_display(display), id, 1);
+	offer = wl_display_bind(display_get_display(display),
+				id, &wl_drag_offer_interface);
 
 	dnd_offer = malloc(sizeof *dnd_offer);
 	if (dnd_offer == NULL)
diff --git a/clients/gears.c b/clients/gears.c
index 3aaf8bb..d83a62c 100644
--- a/clients/gears.c
+++ b/clients/gears.c
@@ -295,16 +295,22 @@
 }
 
 static void
-frame_callback(struct wl_surface *surface, void *data, uint32_t time)
+frame_callback(void *data, struct wl_callback *callback, uint32_t time)
 {
+	static const struct wl_callback_listener listener = {
+		frame_callback
+	};
 	struct gears *gears = data;
 
 	gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
 
 	window_schedule_redraw(gears->window);
-	wl_display_frame_callback(display_get_display(gears->d),
-				  window_get_wl_surface(gears->window),
-				  frame_callback, gears);
+
+	if (callback)
+		wl_callback_destroy(callback);
+
+	callback = wl_surface_frame(window_get_wl_surface(gears->window));
+	wl_callback_add_listener(callback, &listener, gears);
 }
 
 static struct gears *
@@ -362,10 +368,7 @@
 	window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler);
 	window_set_redraw_handler(gears->window, redraw_handler);
 
-	draw_gears(gears);
-	wl_display_frame_callback(display_get_display(gears->d),
-				  window_get_wl_surface(gears->window),
-				  frame_callback, gears);
+	frame_callback(gears, NULL, 0);
 
 	return gears;
 }
diff --git a/clients/resizor.c b/clients/resizor.c
index 16287b3..899c152 100644
--- a/clients/resizor.c
+++ b/clients/resizor.c
@@ -49,8 +49,11 @@
 };
 
 static void
-frame_callback(struct wl_surface *surface, void *data, uint32_t time)
+frame_callback(void *data, struct wl_callback *callback, uint32_t time)
 {
+	static const struct wl_callback_listener listener = {
+		frame_callback
+	};
 	struct resizor *resizor = data;
 	double force, height;
 
@@ -75,6 +78,14 @@
 	window_set_child_size(resizor->window, resizor->width, height + 0.5);
 
 	window_schedule_redraw(resizor->window);
+
+	if (callback)
+		wl_callback_destroy(callback);
+
+	if (fabs(resizor->height.previous - resizor->height.target) > 0.1) {
+		callback = wl_surface_frame(window_get_wl_surface(resizor->window));
+		wl_callback_add_listener(callback, &listener, resizor);
+	}
 }
 
 static void
@@ -104,12 +115,6 @@
 	cairo_surface_destroy(surface);
 
 	window_flush(resizor->window);
-
-	if (fabs(resizor->height.previous - resizor->height.target) > 0.1) {
-		wl_display_frame_callback(display_get_display(resizor->display),
-					  window_get_wl_surface(resizor->window),
-					  frame_callback, resizor);
-	}
 }
 
 static void
@@ -141,11 +146,11 @@
 	switch (sym) {
 	case XK_Down:
 		resizor->height.target = 400;
-		frame_callback(window_get_wl_surface(window), resizor, 0);
+		frame_callback(resizor, NULL, 0);
 		break;
 	case XK_Up:
 		resizor->height.target = 200;
-		frame_callback(window_get_wl_surface(window), resizor, 0);
+		frame_callback(resizor, NULL, 0);
 		break;
 	}
 }
diff --git a/clients/screenshot.c b/clients/screenshot.c
index 82cf9cd..428befa 100644
--- a/clients/screenshot.c
+++ b/clients/screenshot.c
@@ -81,38 +81,19 @@
 	static int visual_count;
 
 	if (strcmp(interface, "wl_output") == 0) {
-		output = wl_output_create(display, id, 1);
+		output = wl_display_bind(display, id, &wl_output_interface);
 		wl_output_add_listener(output, &output_listener, NULL);
 	} else if (strcmp(interface, "wl_shm") == 0) {
-		shm = wl_shm_create(display, id, 1);
+		shm = wl_display_bind(display, id, &wl_shm_interface);
 	} else if (strcmp(interface, "wl_visual") == 0) {
 		if  (visual_count++ == 1)
-			visual = wl_visual_create(display, id, 1);
+			visual = wl_display_bind(display, id,
+						 &wl_visual_interface);
 	} else if (strcmp(interface, "screenshooter") == 0) {
-		screenshooter = screenshooter_create(display, id, 1);
+		screenshooter = wl_display_bind(display, id, &screenshooter_interface);
 	}
 }
 
-static void
-sync_callback(void *data)
-{
-   int *done = data;
-
-   *done = 1;
-}
-
-static void
-roundtrip(struct wl_display *display)
-{
-	int done;
-
-	done = 0;
-	wl_display_sync_callback(display, sync_callback, &done);
-	wl_display_iterate(display, WL_DISPLAY_WRITABLE);
-	while (!done)
-		wl_display_iterate(display, WL_DISPLAY_READABLE);
-}
-
 static struct wl_buffer *
 create_shm_buffer(int width, int height, void **data_out)
 {
@@ -183,7 +164,7 @@
 
 	wl_display_add_global_listener(display, handle_global, &screenshooter);
 	wl_display_iterate(display, WL_DISPLAY_READABLE);
-	roundtrip(display);
+	wl_display_roundtrip(display);
 	if (screenshooter == NULL) {
 		fprintf(stderr, "display doesn't support screenshooter\n");
 		return -1;
@@ -191,7 +172,7 @@
 
 	buffer = create_shm_buffer(output_width, output_height, &data);
 	screenshooter_shoot(screenshooter, output, buffer);
-	roundtrip(display);
+	wl_display_roundtrip(display);
 
 	write_png(output_width, output_height, data);
 
diff --git a/clients/smoke.c b/clients/smoke.c
index 5d3f2db..bae6e96 100644
--- a/clients/smoke.c
+++ b/clients/smoke.c
@@ -173,8 +173,11 @@
 }
 
 static void
-frame_callback(struct wl_surface *surface, void *data, uint32_t time)
+frame_callback(void *data, struct wl_callback *callback, uint32_t time)
 {
+	static const struct wl_callback_listener listener = {
+		frame_callback,
+	};
 	struct smoke *smoke = data;
 
 	diffuse(smoke, time / 30, smoke->b[0].u, smoke->b[1].u);
@@ -199,12 +202,15 @@
 
 	render(smoke);
 
+	if (callback)
+		wl_callback_destroy(callback);
+
 	display_surface_damage(smoke->display, smoke->surface,
 			       0, 0, smoke->width, smoke->height);
 	window_damage(smoke->window, 0, 0, smoke->width, smoke->height);
-	wl_display_frame_callback(display_get_display(smoke->display),
-				  window_get_wl_surface(smoke->window),
-				  frame_callback, smoke);
+
+	callback = wl_surface_frame(window_get_wl_surface(smoke->window));
+	wl_callback_add_listener(callback, &listener, smoke);
 }
 
 static int
@@ -290,10 +296,7 @@
 				  smoke_motion_handler);
 
 	window_set_user_data(smoke.window, &smoke);
-	wl_display_frame_callback(display_get_display(d),
-				  window_get_wl_surface(smoke.window),
-				  frame_callback, &smoke);
-
+	frame_callback(&smoke, NULL, 0);
 	display_run(d);
 
 	return 0;
diff --git a/clients/window.c b/clients/window.c
index 30a1179..eb1e64b 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -670,16 +670,21 @@
 window_attach_surface(struct window *window);
 
 static void
-free_surface(void *data)
+free_surface(void *data, struct wl_callback *callback, uint32_t time)
 {
 	struct window *window = data;
 
+	wl_callback_destroy(callback);
 	cairo_surface_destroy(window->pending_surface);
 	window->pending_surface = NULL;
 	if (window->cairo_surface)
 		window_attach_surface(window);
 }
 
+static const struct wl_callback_listener free_surface_listener = {
+	free_surface
+};
+
 static void
 window_get_resize_dx_dy(struct window *window, int *x, int *y)
 {
@@ -702,6 +707,7 @@
 {
 	struct display *display = window->display;
 	struct wl_buffer *buffer;
+	struct wl_callback *cb;
 #ifdef HAVE_CAIRO_EGL
 	struct egl_window_surface_data *data;
 #endif
@@ -735,8 +741,8 @@
 
 		wl_surface_attach(window->surface, buffer, x, y);
 		window->server_allocation = window->allocation;
-		wl_display_sync_callback(display->display, free_surface,
-					 window);
+		cb = wl_display_sync(display->display);
+		wl_callback_add_listener(cb, &free_surface_listener, window);
 		break;
 	default:
 		return;
@@ -1575,14 +1581,16 @@
 
 	switch (token) {
 	case WL_COMPOSITOR_VISUAL_ARGB32:
-		d->argb_visual = wl_visual_create(d->display, id, 1);
+		d->argb_visual =
+			wl_display_bind(d->display, id, &wl_visual_interface);
 		break;
 	case WL_COMPOSITOR_VISUAL_PREMULTIPLIED_ARGB32:
 		d->premultiplied_argb_visual =
-			wl_visual_create(d->display, id, 1);
+			wl_display_bind(d->display, id, &wl_visual_interface);
 		break;
 	case WL_COMPOSITOR_VISUAL_XRGB32:
-		d->rgb_visual = wl_visual_create(d->display, id, 1);
+		d->rgb_visual =
+			wl_display_bind(d->display, id, &wl_visual_interface);
 		break;
 	}
 }
@@ -1637,7 +1645,8 @@
 
 	memset(input, 0, sizeof *input);
 	input->display = d;
-	input->input_device = wl_input_device_create(d->display, id, 1);
+	input->input_device =
+		wl_display_bind(d->display, id, &wl_input_device_interface);
 	input->pointer_focus = NULL;
 	input->keyboard_focus = NULL;
 	wl_list_insert(d->input_list.prev, &input->link);
@@ -1744,7 +1753,8 @@
 	if (offer == NULL)
 		return;
 
-	offer->offer = wl_selection_offer_create(d->display, id, 1);
+	offer->offer =
+		wl_display_bind(d->display, id, &wl_selection_offer_interface);
 	offer->display = d;
 	wl_array_init(&offer->types);
 	offer->input = NULL;
@@ -1760,19 +1770,20 @@
 	struct display *d = data;
 
 	if (strcmp(interface, "wl_compositor") == 0) {
-		d->compositor = wl_compositor_create(display, id, 1);
+		d->compositor =
+			wl_display_bind(display, id, &wl_compositor_interface);
 		wl_compositor_add_listener(d->compositor,
 					   &compositor_listener, d);
 	} else if (strcmp(interface, "wl_output") == 0) {
-		d->output = wl_output_create(display, id, 1);
+		d->output = wl_display_bind(display, id, &wl_output_interface);
 		wl_output_add_listener(d->output, &output_listener, d);
 	} else if (strcmp(interface, "wl_input_device") == 0) {
 		display_add_input(d, id);
 	} else if (strcmp(interface, "wl_shell") == 0) {
-		d->shell = wl_shell_create(display, id, 1);
+		d->shell = wl_display_bind(display, id, &wl_shell_interface);
 		wl_shell_add_listener(d->shell, &shell_listener, d);
 	} else if (strcmp(interface, "wl_shm") == 0) {
-		d->shm = wl_shm_create(display, id, 1);
+		d->shm = wl_display_bind(display, id, &wl_shm_interface);
 	} else if (strcmp(interface, "wl_selection_offer") == 0) {
 		add_selection_offer(d, id);
 	} else if (d->global_handler) {