Use the new wl_callback interface
diff --git a/compositor/compositor.c b/compositor/compositor.c
index bf31220..34bd366 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -897,26 +897,31 @@
fade_output(output, ec->fade.spring.current, &total_damage);
}
+struct wlsc_frame_callback {
+ struct wl_resource resource;
+ struct wl_client *client;
+ struct wl_list link;
+};
+
static void
repaint(void *data, int msecs)
{
struct wlsc_output *output = data;
struct wlsc_compositor *compositor = output->compositor;
- struct wlsc_surface *es;
struct wlsc_animation *animation, *next;
+ struct wlsc_frame_callback *cb, *cnext;
wlsc_output_repaint(output);
output->repaint_needed = 0;
output->repaint_scheduled = 1;
output->present(output);
- /* FIXME: Keep the surfaces in an per-output list. */
- wl_list_for_each(es, &compositor->surface_list, link) {
- if (es->output == output) {
- wl_display_post_frame(compositor->wl_display,
- &es->surface, msecs);
- }
+ wl_list_for_each_safe(cb, cnext, &output->frame_callback_list, link) {
+ wl_client_post_event(cb->client, &cb->resource.object,
+ WL_CALLBACK_DONE, msecs);
+ wl_resource_destroy(&cb->resource, cb->client, 0);
}
+ wl_list_init(&output->frame_callback_list);
wl_list_for_each_safe(animation, next,
&compositor->animation_list, link)
@@ -1052,10 +1057,39 @@
wlsc_surface_damage_rectangle(es, x, y, width, height);
}
+static void
+destroy_frame_callback(struct wl_resource *resource, struct wl_client *client)
+{
+ free(resource);
+}
+
+static void
+surface_frame(struct wl_client *client,
+ struct wl_surface *surface, uint32_t callback)
+{
+ struct wlsc_frame_callback *cb;
+ struct wlsc_surface *es = (struct wlsc_surface *) surface;
+
+ cb = malloc(sizeof *cb);
+ if (cb == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ cb->resource.object.interface = &wl_callback_interface;
+ cb->resource.object.id = callback;
+ cb->resource.destroy = destroy_frame_callback;
+ wl_list_insert(es->output->frame_callback_list.prev, &cb->link);
+ cb->client = client;
+
+ wl_client_add_resource(client, &cb->resource);
+}
+
const static struct wl_surface_interface surface_interface = {
surface_destroy,
surface_attach,
- surface_damage
+ surface_damage,
+ surface_frame
};
static void
@@ -1820,6 +1854,7 @@
output->scanout_buffer_destroy_listener.func =
output_handle_scanout_buffer_destroy;
wl_list_init(&output->scanout_buffer_destroy_listener.link);
+ wl_list_init(&output->frame_callback_list);
output->object.interface = &wl_output_interface;
wl_display_add_object(c->wl_display, &output->object);