Replace commit/ack/frame protocol with simpler sync and frame callbacks
diff --git a/clients/dnd.c b/clients/dnd.c
index df4d8c5..9095672 100644
--- a/clients/dnd.c
+++ b/clients/dnd.c
@@ -183,8 +183,8 @@
 	cairo_destroy(cr);
 
 	window_copy_surface(dnd->window, &rectangle, surface);
-	window_commit(dnd->window, dnd->key);
 	cairo_surface_destroy(surface);
+	window_flush(dnd->window);
 }
 
 static void
diff --git a/clients/flower.c b/clients/flower.c
index 54d54f2..3a06bf9 100644
--- a/clients/flower.c
+++ b/clients/flower.c
@@ -98,21 +98,22 @@
 }
 
 struct flower {
+	struct display *display;
 	struct window *window;
 	int x, y, width, height;
 	int offset;
 };
 
 static void
-handle_frame(struct window *window,
-	     uint32_t frame, uint32_t timestamp, void *data)
+frame_callback(void *data, uint32_t time)
 {
 	struct flower *flower = data;
 
 	window_move(flower->window, 
-		    flower->x + cos((flower->offset + timestamp) / 400.0) * 400 - flower->width / 2,
-		    flower->y + sin((flower->offset + timestamp) / 320.0) * 300 - flower->height / 2);
-	window_commit(flower->window, 0);
+		    flower->x + cos((flower->offset + time) / 400.0) * 400 - flower->width / 2,
+		    flower->y + sin((flower->offset + time) / 320.0) * 300 - flower->height / 2);
+	wl_display_frame_callback(display_get_display(flower->display),
+				  frame_callback, flower);
 }
 
 int main(int argc, char *argv[])
@@ -128,6 +129,7 @@
 	flower.y = 384;
 	flower.width = 200;
 	flower.height = 200;
+	flower.display = d;
 	flower.window = window_create(d, "flower", flower.x, flower.y,
 				      flower.width, flower.height);
 
@@ -145,10 +147,11 @@
 
 	draw_stuff(s, flower.width, flower.height);
 	cairo_surface_flush(s);
+	window_flush(flower.window);
 
 	window_set_user_data(flower.window, &flower);
-	window_set_frame_handler(flower.window, handle_frame);
-	window_commit(flower.window, 0);
+	wl_display_frame_callback(display_get_display(d),
+				  frame_callback, &flower);
 
 	display_run(d);
 
diff --git a/clients/gears.c b/clients/gears.c
index 0426f20..f8c77ec 100644
--- a/clients/gears.c
+++ b/clients/gears.c
@@ -317,31 +317,21 @@
 }
 
 static void
-acknowledge_handler(struct window *window,
-		    uint32_t key, uint32_t frame,
-		    void *data)
+frame_callback(void *data, uint32_t time)
 {
 	struct gears *gears = data;
 
-	if (key == 10) {
-		if (gears->resized)
-			resize_window(gears);
-
-		draw_gears(gears);
-	}
-}
-
-static void
-frame_handler(struct window *window,
-	      uint32_t frame, uint32_t timestamp, void *data)
-{
-  	struct gears *gears = data;
-
 	window_copy_image(gears->window, &gears->rectangle, gears->image);
 
-	window_commit(gears->window, 10);
+	if (gears->resized)
+		resize_window(gears);
 
-	gears->angle = (GLfloat) (timestamp % 8192) * 360 / 8192.0;
+	draw_gears(gears);
+
+	gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
+
+	wl_display_frame_callback(display_get_display(gears->d),
+				  frame_callback, gears);
 }
 
 static struct gears *
@@ -417,13 +407,13 @@
 
 	resize_window(gears);
 	draw_gears(gears);
-	frame_handler(gears->window, 0, 0, gears);
 
 	window_set_user_data(gears->window, gears);
 	window_set_resize_handler(gears->window, resize_handler);
 	window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler);
-	window_set_acknowledge_handler(gears->window, acknowledge_handler);
-	window_set_frame_handler(gears->window, frame_handler);
+
+	wl_display_frame_callback(display_get_display(gears->d),
+				  frame_callback, gears);
 
 	return gears;
 }
diff --git a/clients/image.c b/clients/image.c
index fa23520..b359a94 100644
--- a/clients/image.c
+++ b/clients/image.c
@@ -176,7 +176,7 @@
 	g_object_unref(pb);
 
 	window_copy_surface(image->window, &rectangle, surface);
-	window_commit(image->window, image->key);
+	window_flush(image->window);
 	cairo_surface_destroy(surface);
 }
 
diff --git a/clients/terminal.c b/clients/terminal.c
index 1bb496d..c841ef2 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -215,7 +215,7 @@
 
 	window_draw(terminal->window);
 	terminal_draw_contents(terminal);
-	window_commit(terminal->window, 0);
+	window_flush(terminal->window);
 }
 
 static void
diff --git a/clients/view.c b/clients/view.c
index 0c8ce5a..ace838d 100644
--- a/clients/view.c
+++ b/clients/view.c
@@ -101,8 +101,7 @@
 	poppler_page_render(page, cr);
 	cairo_destroy(cr);
 	g_object_unref(G_OBJECT(page));
-
-	window_commit(view->window, 0);
+	window_flush(view->window);
 }
 
 static void
diff --git a/clients/window.c b/clients/window.c
index 5a2f247..0aa319d 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -98,8 +98,6 @@
 	window_key_handler_t key_handler;
 	window_button_handler_t button_handler;
 	window_keyboard_focus_handler_t keyboard_focus_handler;
-	window_acknowledge_handler_t acknowledge_handler;
-	window_frame_handler_t frame_handler;
 	window_motion_handler_t motion_handler;
 
 	void *user_data;
@@ -331,6 +329,21 @@
 	return cairo_surface_reference(surface);
 }
 
+
+static void
+window_attach_surface(struct window *window);
+
+static void
+free_surface(void *data)
+{
+	struct window *window = data;
+
+	cairo_surface_destroy(window->pending_surface);
+	window->pending_surface = NULL;
+	if (window->cairo_surface)
+		window_attach_surface(window);
+}
+
 static void
 window_attach_surface(struct window *window)
 {
@@ -353,17 +366,14 @@
 		       window->allocation.width,
 		       window->allocation.height);
 
-	wl_compositor_commit(window->display->compositor, 0);
+	wl_display_sync_callback(display->display, free_surface, window);
 }
 
 void
-window_commit(struct window *window, uint32_t key)
+window_flush(struct window *window)
 {
-	if (window->cairo_surface) {
-		window_attach_surface(window);
-	} else {
-		wl_compositor_commit(window->display->compositor, key);
-	}
+       if (window->cairo_surface)
+	       window_attach_surface(window);
 }
 
 static void
@@ -848,6 +858,10 @@
 
 	cairo_paint (cr);
 	cairo_destroy (cr);
+
+	wl_surface_damage(window->surface,
+			  rectangle->x, rectangle->y,
+			  rectangle->width, rectangle->height);
 }
 
 static gboolean
@@ -934,20 +948,6 @@
 }
 
 void
-window_set_acknowledge_handler(struct window *window,
-			       window_acknowledge_handler_t handler)
-{
-	window->acknowledge_handler = handler;
-}
-
-void
-window_set_frame_handler(struct window *window,
-			 window_frame_handler_t handler)
-{
-	window->frame_handler = handler;
-}
-
-void
 window_set_motion_handler(struct window *window,
 			  window_motion_handler_t handler)
 {
@@ -1023,48 +1023,6 @@
 };
 
 static void
-display_handle_acknowledge(void *data,
-			   struct wl_compositor *compositor,
-			   uint32_t key, uint32_t frame)
-{
-	struct display *d = data;
-	struct window *window;
-		
-	/* The acknowledge event means that the server processed our
-	 * last commit request and we can now safely free the old
-	 * window buffer if we resized and render the next frame into
-	 * our back buffer.. */
-	wl_list_for_each(window, &d->window_list, link) {
-		cairo_surface_destroy(window->pending_surface);
-		window->pending_surface = NULL;
-		if (window->cairo_surface)
-			window_attach_surface(window);
-		if (window->acknowledge_handler)
-			(*window->acknowledge_handler)(window, key, frame, window->user_data);
-	}
-}
-
-static void
-display_handle_frame(void *data,
-		     struct wl_compositor *compositor,
-		     uint32_t frame, uint32_t timestamp)
-{
-	struct display *d = data;
-	struct window *window;
-
-	wl_list_for_each(window, &d->window_list, link) {
-		if (window->frame_handler)
-			(*window->frame_handler)(window, frame,
-						 timestamp, window->user_data);
-	}
-}
-
-static const struct wl_compositor_listener compositor_listener = {
-	display_handle_acknowledge,
-	display_handle_frame,
-};
-
-static void
 display_handle_geometry(void *data,
 			struct wl_output *output,
 			int32_t width, int32_t height)
@@ -1111,8 +1069,6 @@
 
 	if (strcmp(interface, "compositor") == 0) {
 		d->compositor = wl_compositor_create(display, id);
-		wl_compositor_add_listener(d->compositor,
-					   &compositor_listener, d);
 	} else if (strcmp(interface, "output") == 0) {
 		d->output = wl_output_create(display, id);
 		wl_output_add_listener(d->output, &output_listener, d);
@@ -1290,6 +1246,12 @@
 	return d;
 }
 
+struct wl_display *
+display_get_display(struct display *display)
+{
+	return display->display;
+}
+
 struct wl_compositor *
 display_get_compositor(struct display *display)
 {
diff --git a/clients/window.h b/clients/window.h
index 1b4285f..343d536 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -38,6 +38,9 @@
 struct display *
 display_create(int *argc, char **argv[], const GOptionEntry *option_entries);
 
+struct wl_display *
+display_get_display(struct display *display);
+
 struct wl_compositor *
 display_get_compositor(struct display *display);
 
@@ -96,7 +99,6 @@
 typedef void (*window_resize_handler_t)(struct window *window, void *data);
 typedef void (*window_redraw_handler_t)(struct window *window, void *data);
 typedef void (*window_frame_handler_t)(struct window *window, uint32_t frame, uint32_t timestamp, void *data);
-typedef void (*window_acknowledge_handler_t)(struct window *window, uint32_t key, uint32_t frame, void *data);
 typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t unicode,
 				     uint32_t state, uint32_t modifiers, void *data);
 typedef void (*window_keyboard_focus_handler_t)(struct window *window,
@@ -121,8 +123,6 @@
 void
 window_draw(struct window *window);
 void
-window_commit(struct window *window, uint32_t key);
-void
 window_get_child_rectangle(struct window *window,
 			   struct rectangle *rectangle);
 void
@@ -147,6 +147,9 @@
 		    cairo_surface_t *surface);
 
 void
+window_flush(struct window *window);
+
+void
 window_set_fullscreen(struct window *window, int fullscreen);
 
 void
@@ -168,9 +171,6 @@
 void
 window_set_frame_handler(struct window *window,
 			 window_frame_handler_t handler);
-void
-window_set_acknowledge_handler(struct window *window,
-			       window_acknowledge_handler_t handler);
 
 void
 window_set_key_handler(struct window *window,
@@ -189,10 +189,6 @@
 				  window_keyboard_focus_handler_t handler);
 
 void
-window_set_acknowledge_handler(struct window *window,
-			       window_acknowledge_handler_t handler);
-
-void
 window_set_frame_handler(struct window *window,
 			 window_frame_handler_t handler);
 
diff --git a/compositor.c b/compositor.c
index 175e5a7..a805f8c 100644
--- a/compositor.c
+++ b/compositor.c
@@ -349,12 +349,8 @@
 void
 wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs)
 {
-	wl_display_post_frame(compositor->wl_display,
-			      &compositor->base,
-			      compositor->current_frame, msecs);
-
+	wl_display_post_frame(compositor->wl_display, msecs);
 	wl_event_source_timer_update(compositor->timer_source, 5);
-	compositor->current_frame++;
 }
 
 static void
@@ -426,6 +422,7 @@
 	glBindTexture(GL_TEXTURE_2D, es->texture);
 	glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image);
 	es->visual = buffer->visual;
+	wlsc_compositor_schedule_repaint(es->compositor);
 }
 
 static void
@@ -441,6 +438,7 @@
 	es->height = height;
 
 	wlsc_surface_update_matrix(es);
+	wlsc_compositor_schedule_repaint(es->compositor);
 }
 
 static void
@@ -448,7 +446,9 @@
 	       struct wl_surface *surface,
 	       int32_t x, int32_t y, int32_t width, int32_t height)
 {
-	/* FIXME: This need to take a damage region, of course. */
+	struct wlsc_surface *es = (struct wlsc_surface *) surface;
+
+	wlsc_compositor_schedule_repaint(es->compositor);
 }
 
 const static struct wl_surface_interface surface_interface = {
@@ -640,19 +640,8 @@
 	wl_client_add_resource(client, &surface->base.base);
 }
 
-static void
-compositor_commit(struct wl_client *client,
-		  struct wl_compositor *compositor, uint32_t key)
-{
-	struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
-
-	wlsc_compositor_schedule_repaint(ec);
-	wl_client_send_acknowledge(client, compositor, key, ec->current_frame);
-}
-
 const static struct wl_compositor_interface compositor_interface = {
 	compositor_create_surface,
-	compositor_commit
 };
 
 static void
diff --git a/compositor.h b/compositor.h
index 097cdc6..2cbdf8e 100644
--- a/compositor.h
+++ b/compositor.h
@@ -154,7 +154,6 @@
 	int repaint_needed;
 	int repaint_on_timeout;
 	struct timespec previous_swap;
-	uint32_t current_frame;
 
 	uint32_t focus;
 
diff --git a/protocol.xml b/protocol.xml
index 0f2bd98..9da4b49 100644
--- a/protocol.xml
+++ b/protocol.xml
@@ -1,6 +1,14 @@
 <protocol>
 
   <interface name="display" version="1">
+    <request name="sync">
+      <arg name="key" type="uint"/>
+    </request>
+
+    <request name="frame">
+      <arg name="key" type="uint"/>
+    </request>
+
     <event name="invalid_object">
       <arg name="object_id" type="uint"/>
     </event>
@@ -21,26 +29,21 @@
     <event name="range">
       <arg name="base" type="uint"/>
     </event>
+
+    <event name="sync">
+      <arg name="key" type="uint"/>
+    </event>
+
+    <event name="frame">
+      <arg name="key" type="uint"/>
+      <arg name="time" type="uint"/>
+    </event>
   </interface>
 
   <interface name="compositor" version="1">
     <request name="create_surface">
       <arg name="id" type="new_id" interface="surface"/>
     </request>
-
-    <request name="commit">
-      <arg name="key" type="uint"/>
-    </request>
-
-    <event name="acknowledge">
-      <arg name="key" type="uint"/>
-      <arg name="frame" type="uint"/>
-    </event>
-
-    <event name="frame">
-      <arg name="frame" type="uint"/>
-      <arg name="timestamp" type="uint"/>
-    </event>
   </interface>
 
   <interface name="drm" version="1">
diff --git a/wayland-client.c b/wayland-client.c
index dd0500f..2d731b0 100644
--- a/wayland-client.c
+++ b/wayland-client.c
@@ -59,6 +59,20 @@
 	void *user_data;
 };
 
+struct wl_sync_handler {
+	wl_display_sync_func_t func;
+	uint32_t key;
+	void *data;
+	struct wl_list link;
+};
+
+struct wl_frame_handler {
+	wl_display_frame_func_t func;
+	uint32_t key;
+	void *data;
+	struct wl_list link;
+};
+
 struct wl_display {
 	struct wl_proxy proxy;
 	struct wl_connection *connection;
@@ -78,6 +92,9 @@
 
 	wl_display_global_func_t global_handler;
 	void *global_handler_data;
+
+	struct wl_list sync_list, frame_list;
+	uint32_t key;
 };
 
 static int
@@ -270,12 +287,49 @@
 	display->next_range = range;
 }
 
+static void
+display_handle_sync(void *data, struct wl_display *display, uint32_t key)
+{
+	struct wl_sync_handler *handler;
+
+	handler = container_of(display->sync_list.next,
+			       struct wl_sync_handler, link);
+	if (handler->key != key) {
+		fprintf(stderr, "unsolicited sync event, client gone?\n");
+		return;
+	}
+
+	wl_list_remove(&handler->link);
+	handler->func(handler->data);
+	free(handler);
+}
+
+static void
+display_handle_frame(void *data,
+		     struct wl_display *display, uint32_t key, uint32_t time)
+{
+	struct wl_frame_handler *handler;
+
+	handler = container_of(display->frame_list. next,
+			       struct wl_frame_handler, link);
+	if (handler->key != key) {
+		fprintf(stderr, "unsolicited frame event, client gone?\n");
+		return;
+	}
+
+	wl_list_remove(&handler->link);
+	handler->func(handler->data, time);
+	free(handler);
+}
+
 static const struct wl_display_listener display_listener = {
 	display_handle_invalid_object,
 	display_handle_invalid_method,
 	display_handle_no_memory,
 	display_handle_global,
-	display_handle_range
+	display_handle_range,
+	display_handle_sync,
+	display_handle_frame
 };
 
 WL_EXPORT struct wl_display *
@@ -315,6 +369,9 @@
 	display->proxy.display = display;
 	wl_list_init(&display->proxy.listener_list);
 
+	wl_list_init(&display->sync_list);
+	wl_list_init(&display->frame_list);
+
 	display->listener.implementation = (void(**)(void)) &display_listener;
 	wl_list_insert(display->proxy.listener_list.prev, &display->listener.link);
 
@@ -345,6 +402,46 @@
 	return display->fd;
 }
 
+WL_EXPORT int
+wl_display_sync_callback(struct wl_display *display,
+			 wl_display_sync_func_t func, void *data)
+{
+	struct wl_sync_handler *handler;
+
+	handler = malloc(sizeof *handler);
+	if (handler == NULL)
+		return -1;
+
+	handler->func = func;
+	handler->key = display->key++;
+	handler->data = data;
+
+	wl_list_insert(display->sync_list.prev, &handler->link);
+	wl_display_sync(display, handler->key);
+
+	return 0;
+}
+
+WL_EXPORT int
+wl_display_frame_callback(struct wl_display *display,
+			  wl_display_frame_func_t func, void *data)
+{
+	struct wl_frame_handler *handler;
+
+	handler = malloc(sizeof *handler);
+	if (handler == NULL)
+		return -1;
+
+	handler->func = func;
+	handler->key = display->key++;
+	handler->data = data;
+
+	wl_list_insert(display->frame_list.prev, &handler->link);
+	wl_display_frame(display, handler->key);
+
+	return 0;
+}
+
 static void
 handle_event(struct wl_display *display,
 	     uint32_t id, uint32_t opcode, uint32_t size)
diff --git a/wayland-client.h b/wayland-client.h
index 68e5936..4fcb00b 100644
--- a/wayland-client.h
+++ b/wayland-client.h
@@ -34,6 +34,8 @@
 #define WL_DISPLAY_WRITABLE 0x02
 
 typedef int (*wl_display_update_func_t)(uint32_t mask, void *data);
+typedef void (*wl_display_sync_func_t)(void *data);
+typedef void (*wl_display_frame_func_t)(void *data, uint32_t time);
 
 struct wl_display *wl_display_create(const char *name, size_t name_size);
 void wl_display_destroy(struct wl_display *display);
@@ -41,6 +43,10 @@
 		      wl_display_update_func_t update, void *data);
 uint32_t wl_display_allocate_id(struct wl_display *display);
 void wl_display_iterate(struct wl_display *display, uint32_t mask);
+int wl_display_sync_callback(struct wl_display *display,
+			     wl_display_sync_func_t func, void *data);
+int wl_display_frame_callback(struct wl_display *display,
+			      wl_display_frame_func_t func, void *data);
 
 struct wl_global_listener;
 typedef void (*wl_display_global_func_t)(struct wl_display *display,
diff --git a/wayland-server.c b/wayland-server.c
index 1c91353..db8bf74 100644
--- a/wayland-server.c
+++ b/wayland-server.c
@@ -43,7 +43,6 @@
 	struct wl_event_source *source;
 	struct wl_display *display;
 	struct wl_list resource_list;
-	struct wl_list link;
 	uint32_t id_count;
 };
 
@@ -52,13 +51,20 @@
 	struct wl_event_loop *loop;
 	struct wl_hash_table *objects;
 
-	struct wl_list pending_frame_list;
+	struct wl_list frame_list;
 	uint32_t client_id_range;
 	uint32_t id;
 
 	struct wl_list global_list;
 };
 
+struct wl_frame_listener {
+	struct wl_resource resource;
+	struct wl_client *client;
+	uint32_t key;
+	struct wl_list link;
+};
+
 struct wl_global {
 	struct wl_object *object;
 	wl_client_connect_func_t func;
@@ -200,7 +206,6 @@
 		wl_connection_create(fd, wl_client_connection_update, client);
 
 	wl_list_init(&client->resource_list);
-	wl_list_init(&client->link);
 
 	wl_display_post_range(display, client);
 
@@ -257,7 +262,8 @@
 	struct wl_display *display = client->display;
 
 	wl_list_remove(&resource->link);
-	wl_hash_table_remove(display->objects, resource->base.id);
+	if (resource->base.id > 0)
+		wl_hash_table_remove(display->objects, resource->base.id);
 	resource->destroy(resource, client);
 }
 
@@ -268,30 +274,14 @@
 
 	printf("disconnect from client %p\n", client);
 
-	wl_list_remove(&client->link);
-
-	wl_list_for_each_safe(resource, tmp, &client->resource_list, link) {
-		wl_list_remove(&resource->link);
-		resource->destroy(resource, client);
-	}
+	wl_list_for_each_safe(resource, tmp, &client->resource_list, link)
+		wl_resource_destroy(resource, client);
 
 	wl_event_source_remove(client->source);
 	wl_connection_destroy(client->connection);
 	free(client);
 }
 
-WL_EXPORT void
-wl_client_send_acknowledge(struct wl_client *client,
-			   struct wl_compositor *compositor,
-			   uint32_t key, uint32_t frame)
-{
-	wl_list_remove(&client->link);
-	wl_list_insert(client->display->pending_frame_list.prev,
-		       &client->link);
-	wl_client_post_event(client, &compositor->base,
-			     WL_COMPOSITOR_ACKNOWLEDGE, key, frame);
-}
-
 WL_EXPORT int
 wl_display_set_compositor(struct wl_display *display,
 			  struct wl_compositor *compositor,
@@ -307,6 +297,51 @@
 	return 0;
 }
 
+static void
+display_sync(struct wl_client *client,
+	       struct wl_display *display, uint32_t key)
+{
+	wl_client_post_event(client, &display->base, WL_DISPLAY_SYNC, key);
+}
+
+static void
+destroy_frame_listener(struct wl_resource *resource, struct wl_client *client)
+{
+	struct wl_frame_listener *listener =
+		container_of(resource, struct wl_frame_listener, resource);
+
+	wl_list_remove(&listener->link);
+	free(listener);
+}
+
+static void
+display_frame(struct wl_client *client,
+	      struct wl_display *display, uint32_t key)
+{
+	struct wl_frame_listener *listener;
+
+	listener = malloc(sizeof *listener);
+	if (listener == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	/* The listener is a resource so we destroy it when the client
+	 * goes away. */
+	listener->resource.destroy = destroy_frame_listener;
+	listener->resource.base.id = 0;
+	listener->client = client;
+	listener->key = key;
+	wl_list_insert(client->resource_list.prev, &listener->resource.link);
+	wl_list_insert(display->frame_list.prev, &listener->link);
+}
+
+struct wl_display_interface display_interface = {
+	display_sync,
+	display_frame
+};
+
+
 WL_EXPORT struct wl_display *
 wl_display_create(void)
 {
@@ -328,22 +363,22 @@
 		return NULL;
 	}
 
-	wl_list_init(&display->pending_frame_list);
+	wl_list_init(&display->frame_list);
 	wl_list_init(&display->global_list);
 
 	display->client_id_range = 256; /* Gah, arbitrary... */
 
 	display->id = 1;
 	display->base.interface = &wl_display_interface;
-	display->base.implementation = NULL;
+	display->base.implementation = (void (**)(void)) &display_interface;
 	wl_display_add_object(display, &display->base);
 	if (wl_display_add_global(display, &display->base, NULL)) {
 		wl_event_loop_destroy(display->loop);
 		free(display);
 		return NULL;
-	}		
+	}
 
-	return display;		
+	return display;
 }
 
 WL_EXPORT void
@@ -388,18 +423,15 @@
 }
 
 WL_EXPORT void
-wl_display_post_frame(struct wl_display *display,
-		      struct wl_compositor *compositor,
-		      uint32_t frame, uint32_t msecs)
+wl_display_post_frame(struct wl_display *display, uint32_t time)
 {
-	struct wl_client *client;
+	struct wl_frame_listener *listener, *next;
 
-	wl_list_for_each(client, &display->pending_frame_list, link)
-		wl_client_post_event(client, &compositor->base,
-				     WL_COMPOSITOR_FRAME, frame, msecs);
-
-	wl_list_remove(&display->pending_frame_list);
-	wl_list_init(&display->pending_frame_list);
+	wl_list_for_each_safe(listener, next, &display->frame_list, link) {
+		wl_client_post_event(listener->client, &display->base,
+				     WL_DISPLAY_FRAME, listener->key, time);
+		wl_resource_destroy(&listener->resource, listener->client);
+	}
 }
 
 WL_EXPORT struct wl_event_loop *
diff --git a/wayland-server.h b/wayland-server.h
index 5bd4b75..bb99cb8 100644
--- a/wayland-server.h
+++ b/wayland-server.h
@@ -159,14 +159,7 @@
 			  const struct wl_compositor_interface *implementation);
 
 void
-wl_client_send_acknowledge(struct wl_client *client,
-			   struct wl_compositor *compositor,
-			   uint32_t key, uint32_t frame);
-
-void
-wl_display_post_frame(struct wl_display *display,
-		      struct wl_compositor *compositor,
-		      uint32_t frame, uint32_t msecs);
+wl_display_post_frame(struct wl_display *display, uint32_t msecs);
 
 void
 wl_client_add_resource(struct wl_client *client,