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
}
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[])
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);
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);
}
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);
+ window_copy_image(gears->window, &gears->rectangle, gears->image);
- draw_gears(gears);
- }
-}
+ if (gears->resized)
+ resize_window(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);
+ draw_gears(gears);
- window_commit(gears->window, 10);
+ gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
- gears->angle = (GLfloat) (timestamp % 8192) * 360 / 8192.0;
+ wl_display_frame_callback(display_get_display(gears->d),
+ frame_callback, gears);
}
static struct gears *
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;
}
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);
}
window_draw(terminal->window);
terminal_draw_contents(terminal);
- window_commit(terminal->window, 0);
+ window_flush(terminal->window);
}
static void
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
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;
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)
{
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
cairo_paint (cr);
cairo_destroy (cr);
+
+ wl_surface_damage(window->surface,
+ rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
}
static gboolean
}
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)
{
};
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)
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);
return d;
}
+struct wl_display *
+display_get_display(struct display *display)
+{
+ return display->display;
+}
+
struct wl_compositor *
display_get_compositor(struct display *display)
{
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);
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,
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
cairo_surface_t *surface);
void
+window_flush(struct window *window);
+
+void
window_set_fullscreen(struct window *window, int fullscreen);
void
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,
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);
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
glBindTexture(GL_TEXTURE_2D, es->texture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image);
es->visual = buffer->visual;
+ wlsc_compositor_schedule_repaint(es->compositor);
}
static void
es->height = height;
wlsc_surface_update_matrix(es);
+ wlsc_compositor_schedule_repaint(es->compositor);
}
static void
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 = {
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
int repaint_needed;
int repaint_on_timeout;
struct timespec previous_swap;
- uint32_t current_frame;
uint32_t focus;
<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>
<event name="range">
<arg name="base" 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">
+ <event name="sync">
<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"/>
+ <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>
+ </interface>
+
<interface name="drm" version="1">
<!-- dri2 auth and create buffer -->
<request name="authenticate">
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;
wl_display_global_func_t global_handler;
void *global_handler_data;
+
+ struct wl_list sync_list, frame_list;
+ uint32_t key;
};
static int
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 *
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);
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)
#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);
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,
struct wl_event_source *source;
struct wl_display *display;
struct wl_list resource_list;
- struct wl_list link;
uint32_t id_count;
};
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;
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);
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);
}
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,
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)
{
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
}
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 *
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,