summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2011-07-29 19:51:22 -0700
committerKristian Høgsberg <krh@bitplanet.net>2011-08-27 12:06:10 -0400
commit0af17ed98c8f8112c0d43ccbf90367f543846143 (patch)
tree93a6c58aa836286850b3cdebde9f1e3427cfeb7b
parent1648109c84a5e96fd28a29a276a668050dd6c881 (diff)
Use a callback object instead of ad-hoc lists for sync and frame events
So obvious in retrospect. The object system can do all the work for us and keep track of pending calls as regular objects and we don't need to abuse the resource system to get them cleaned up on client exit. We don't need the custom key management or (broken) lookup, we just sue object IDs. And last but not least, anybody can receive the callback, not just display listeners.
-rw-r--r--protocol/wayland.xml31
-rw-r--r--src/wayland-client.c107
-rw-r--r--src/wayland-client.h12
-rw-r--r--src/wayland-server.c69
4 files changed, 43 insertions, 176 deletions
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 92377c4..f1dd78e 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -42,16 +42,7 @@
The key argument can be used to correlate between multiple
sync invocations. -->
<request name="sync">
- <arg name="key" type="uint"/>
- </request>
-
- <!-- Request notification when the next frame is displayed.
- Useful for throttling redrawing operations, and driving
- animations. The notification will only be posted for one
- frame unless requested again. -->
- <request name="frame">
- <arg name="surface" type="object" interface="wl_surface"/>
- <arg name="key" type="uint"/>
+ <arg name="callback" type="new_id" interface="wl_callback"/>
</request>
<!-- A fatal error has occurred. -->
@@ -92,19 +83,14 @@
<event name="range">
<arg name="base" type="uint"/>
</event>
+ </interface>
- <!-- A reply to the frame or sync request. The key is the one
- used in the request. time is in millisecond units, and
- denotes the time when the frame was posted on the
- display. time can be used to estimate frame rate, determine
- how much to advance animations and compensate for jitter. -->
- <event name="key">
- <arg name="key" type="uint"/>
+ <interface name="wl_callback" version="1">
+ <event name="done">
<arg name="time" type="uint"/>
</event>
</interface>
-
<!-- A compositor. This object is a global. The compositor is in
charge of combining the contents of multiple surfaces into one
displayable output. -->
@@ -423,6 +409,15 @@
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</request>
+
+ <!-- Request notification when the next frame is displayed.
+ Useful for throttling redrawing operations, and driving
+ animations. The notification will only be posted for one
+ frame unless requested again. -->
+ <request name="frame">
+ <arg name="callback" type="new_id" interface="wl_callback"/>
+ </request>
+
</interface>
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 9d1f66b..a7b118b 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -51,21 +51,6 @@ struct wl_proxy {
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_surface *surface;
- struct wl_list link;
-};
-
struct wl_global {
uint32_t id;
char *interface;
@@ -88,9 +73,6 @@ struct wl_display {
wl_display_global_func_t global_handler;
void *global_handler_data;
-
- struct wl_list sync_list, frame_list;
- uint32_t key;
};
static int wl_debug = 0;
@@ -278,42 +260,11 @@ display_handle_range(void *data,
display->next_range = range;
}
-static void
-display_handle_key(void *data,
- struct wl_display *display, uint32_t key, uint32_t time)
-{
- struct wl_sync_handler *sync_handler;
- struct wl_frame_handler *frame_handler;
-
- sync_handler = container_of(display->sync_list.next,
- struct wl_sync_handler, link);
- if (!wl_list_empty(&display->sync_list) && sync_handler->key == key) {
- wl_list_remove(&sync_handler->link);
- sync_handler->func(sync_handler->data);
- free(sync_handler);
- return;
- }
-
- frame_handler = container_of(display->frame_list. next,
- struct wl_frame_handler, link);
- if (!wl_list_empty(&display->frame_list) &&
- frame_handler->key == key) {
- wl_list_remove(&frame_handler->link);
- frame_handler->func(frame_handler->surface,
- frame_handler->data, time);
- free(frame_handler);
- return;
- }
-
- fprintf(stderr, "unsolicited sync event, client gone?\n");
-}
-
static const struct wl_display_listener display_listener = {
display_handle_error,
display_handle_global,
display_handle_global_remove,
display_handle_range,
- display_handle_key
};
static int
@@ -402,9 +353,6 @@ wl_display_connect(const char *name)
display->proxy.object.id = 1;
display->proxy.display = display;
- wl_list_init(&display->sync_list);
- wl_list_init(&display->frame_list);
-
display->proxy.object.implementation =
(void(**)(void)) &display_listener;
display->proxy.user_data = display;
@@ -455,46 +403,31 @@ wl_display_get_fd(struct wl_display *display,
return display->fd;
}
-WL_EXPORT int
-wl_display_sync_callback(struct wl_display *display,
- wl_display_sync_func_t func, void *data)
+static void
+sync_callback(void *data, struct wl_callback *callback, uint32_t time)
{
- struct wl_sync_handler *handler;
-
- handler = malloc(sizeof *handler);
- if (handler == NULL)
- return -1;
+ int *done = data;
- 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;
+ *done = 1;
+ wl_callback_destroy(callback);
}
-WL_EXPORT int
-wl_display_frame_callback(struct wl_display *display,
- struct wl_surface *surface,
- 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;
- handler->surface = surface;
-
- wl_list_insert(display->frame_list.prev, &handler->link);
- wl_display_frame(display, handler->surface, handler->key);
+static const struct wl_callback_listener sync_listener = {
+ sync_callback
+};
- return 0;
+WL_EXPORT void
+wl_display_roundtrip(struct wl_display *display)
+{
+ struct wl_callback *callback;
+ int done;
+
+ done = 0;
+ callback = wl_display_sync(display);
+ wl_callback_add_listener(callback, &sync_listener, &done);
+ wl_display_flush(display);
+ while (!done)
+ wl_display_iterate(display, WL_DISPLAY_READABLE);
}
static void
diff --git a/src/wayland-client.h b/src/wayland-client.h
index 385dc16..b00b0ae 100644
--- a/src/wayland-client.h
+++ b/src/wayland-client.h
@@ -50,9 +50,7 @@ void *wl_proxy_get_user_data(struct wl_proxy *proxy);
#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)(struct wl_surface *surface,
- void *data, uint32_t time);
+typedef void (*wl_callback_func_t)(void *data, uint32_t time);
struct wl_display *wl_display_connect(const char *name);
void wl_display_destroy(struct wl_display *display);
@@ -61,11 +59,7 @@ int wl_display_get_fd(struct wl_display *display,
uint32_t wl_display_allocate_id(struct wl_display *display);
void wl_display_iterate(struct wl_display *display, uint32_t mask);
void wl_display_flush(struct wl_display *display);
-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,
- struct wl_surface *surface,
- wl_display_frame_func_t func, void *data);
+void wl_display_roundtrip(struct wl_display *display);
struct wl_global_listener;
typedef void (*wl_display_global_func_t)(struct wl_display *display,
@@ -79,7 +73,7 @@ wl_display_remove_global_listener(struct wl_display *display,
struct wl_global_listener *
wl_display_add_global_listener(struct wl_display *display,
wl_display_global_func_t handler, void *data);
-WL_EXPORT uint32_t
+uint32_t
wl_display_get_global(struct wl_display *display,
const char *interface, uint32_t version);
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 2019cb4..c6ec2f1 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -69,7 +69,7 @@ struct wl_display {
struct wl_hash_table *objects;
int run;
- struct wl_list frame_list;
+ struct wl_list callback_list;
uint32_t client_id_range;
uint32_t id;
@@ -78,14 +78,6 @@ struct wl_display {
struct wl_list client_list;
};
-struct wl_frame_listener {
- struct wl_resource resource;
- struct wl_client *client;
- uint32_t key;
- struct wl_surface *surface;
- struct wl_list link;
-};
-
struct wl_global {
struct wl_object *object;
wl_global_bind_func_t func;
@@ -531,51 +523,19 @@ display_bind(struct wl_client *client,
static void
display_sync(struct wl_client *client,
- struct wl_display *display, uint32_t key)
-{
- wl_client_post_event(client, &display->object, WL_DISPLAY_KEY, key, 0);
-}
-
-static void
-destroy_frame_listener(struct wl_resource *resource, struct wl_client *client)
+ struct wl_display *display, uint32_t id)
{
- 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,
- struct wl_surface *surface,
- uint32_t key)
-{
- struct wl_frame_listener *listener;
+ struct wl_object object;
- listener = malloc(sizeof *listener);
- if (listener == NULL) {
- wl_client_post_no_memory(client);
- return;
- }
+ object.interface = &wl_callback_interface;
+ object.id = id;
- /* The listener is a resource so we destroy it when the client
- * goes away. */
- listener->resource.destroy = destroy_frame_listener;
- listener->resource.object.id = 0;
- listener->client = client;
- listener->key = key;
- listener->surface = surface;
- wl_list_init(&listener->resource.destroy_listener_list);
- wl_list_insert(client->resource_list.prev, &listener->resource.link);
- wl_list_insert(display->frame_list.prev, &listener->link);
+ wl_client_post_event(client, &object, WL_CALLBACK_DONE, 0);
}
struct wl_display_interface display_interface = {
display_bind,
display_sync,
- display_frame
};
@@ -606,7 +566,7 @@ wl_display_create(void)
return NULL;
}
- wl_list_init(&display->frame_list);
+ wl_list_init(&display->callback_list);
wl_list_init(&display->global_list);
wl_list_init(&display->socket_list);
wl_list_init(&display->client_list);
@@ -698,21 +658,6 @@ wl_display_remove_global(struct wl_display *display,
return 0;
}
-WL_EXPORT void
-wl_display_post_frame(struct wl_display *display, struct wl_surface *surface,
- uint32_t time)
-{
- struct wl_frame_listener *listener, *next;
-
- wl_list_for_each_safe(listener, next, &display->frame_list, link) {
- if (listener->surface != surface)
- continue;
- wl_client_post_event(listener->client, &display->object,
- WL_DISPLAY_KEY, listener->key, time);
- wl_resource_destroy(&listener->resource, listener->client, 0);
- }
-}
-
WL_EXPORT struct wl_event_loop *
wl_display_get_event_loop(struct wl_display *display)
{