diff --git a/src/connection.c b/src/connection.c index 4230f7d..5a7ec2e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -65,6 +65,7 @@ struct wl_connection { void *data; wl_connection_update_func_t update; struct wl_closure receive_closure, send_closure; + int write_signalled; }; union wl_value { @@ -285,10 +286,13 @@ wl_connection_data(struct wl_connection *connection, uint32_t mask) close_fds(&connection->fds_out); connection->out.tail += len; - if (connection->out.tail == connection->out.head) + if (connection->out.tail == connection->out.head && + connection->write_signalled) { connection->update(connection, WL_CONNECTION_READABLE, connection->data); + connection->write_signalled = 0; + } } if (mask & WL_CONNECTION_READABLE) { @@ -334,11 +338,24 @@ wl_connection_write(struct wl_connection *connection, wl_buffer_put(&connection->out, data, count); - if (connection->out.head - connection->out.tail == count) + if (!connection->write_signalled) { connection->update(connection, WL_CONNECTION_READABLE | WL_CONNECTION_WRITABLE, connection->data); + connection->write_signalled = 1; + } +} + +static void +wl_connection_queue(struct wl_connection *connection, + const void *data, size_t count) +{ + if (connection->out.head - connection->out.tail + + count > ARRAY_LENGTH(connection->out.data)) + wl_connection_data(connection, WL_CONNECTION_WRITABLE); + + wl_buffer_put(&connection->out, data, count); } static int @@ -703,6 +720,15 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection) wl_connection_write(connection, closure->start, size); } +void +wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection) +{ + uint32_t size; + + size = closure->start[1] >> 16; + wl_connection_queue(connection, closure->start, size); +} + void wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) { diff --git a/src/connection.h b/src/connection.h index 1c733ff..4f7c928 100644 --- a/src/connection.h +++ b/src/connection.h @@ -61,6 +61,8 @@ wl_closure_invoke(struct wl_closure *closure, void wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); void +wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection); +void wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send); void wl_closure_destroy(struct wl_closure *closure); diff --git a/src/wayland-client.c b/src/wayland-client.c index 8f3e106..5845698 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -469,10 +469,6 @@ wl_display_iterate(struct wl_display *display, uint32_t mask) len = wl_connection_data(display->connection, mask); - if (wl_debug && (mask & WL_DISPLAY_READABLE)) - fprintf(stderr, - "[-----------] wakeup, read %d bytes\n", len); - while (len > 0) { if (len < sizeof p) break; diff --git a/src/wayland-server.c b/src/wayland-server.c index 0004c15..f3d8050 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -108,6 +108,28 @@ wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...) wl_closure_destroy(closure); } + +WL_EXPORT void +wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...) +{ + struct wl_closure *closure; + struct wl_object *object = &resource->object; + va_list ap; + + va_start(ap, opcode); + closure = wl_connection_vmarshal(resource->client->connection, + object, opcode, ap, + &object->interface->events[opcode]); + va_end(ap); + + wl_closure_queue(closure, resource->client->connection); + + if (wl_debug) + wl_closure_print(closure, object, true); + + wl_closure_destroy(closure); +} + WL_EXPORT void wl_resource_post_error(struct wl_resource *resource, uint32_t code, const char *msg, ...) @@ -314,8 +336,8 @@ wl_resource_destroy(struct wl_resource *resource, uint32_t time) { struct wl_client *client = resource->client; - wl_resource_post_event(resource->client->display_resource, - WL_DISPLAY_DELETE_ID, resource->object.id); + wl_resource_queue_event(resource->client->display_resource, + WL_DISPLAY_DELETE_ID, resource->object.id); wl_map_insert_at(&client->objects, resource->object.id, NULL); destroy_resource(resource, &time); } diff --git a/src/wayland-server.h b/src/wayland-server.h index 9f5e8c3..ead95cc 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -216,6 +216,8 @@ struct wl_selection { void wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...); +void wl_resource_queue_event(struct wl_resource *resource, + uint32_t opcode, ...); void wl_resource_post_error(struct wl_resource *resource, uint32_t code, const char *msg, ...); void wl_resource_post_no_memory(struct wl_resource *resource);