diff options
-rw-r--r-- | src/connection.c | 9 | ||||
-rw-r--r-- | src/wayland-private.h | 14 | ||||
-rw-r--r-- | src/wayland-server.c | 72 | ||||
-rw-r--r-- | src/wayland-server.h | 10 | ||||
-rw-r--r-- | src/wayland-util.h | 40 |
5 files changed, 120 insertions, 25 deletions
diff --git a/src/connection.c b/src/connection.c index 9bb850c..451b93e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -891,7 +891,6 @@ convert_arguments_to_ffi(const char *signature, uint32_t flags, } } - void wl_closure_invoke(struct wl_closure *closure, uint32_t flags, struct wl_object *target, uint32_t opcode, void *data) @@ -919,6 +918,14 @@ wl_closure_invoke(struct wl_closure *closure, uint32_t flags, ffi_call(&cif, implementation[opcode], NULL, ffi_args); } +void +wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher, + struct wl_object *target, uint32_t opcode) +{ + dispatcher(target->implementation, target, opcode, closure->message, + closure->args); +} + static int copy_fds_to_connection(struct wl_closure *closure, struct wl_connection *connection) diff --git a/src/wayland-private.h b/src/wayland-private.h index 7f8c12c..67e8783 100644 --- a/src/wayland-private.h +++ b/src/wayland-private.h @@ -97,17 +97,6 @@ int wl_connection_write(struct wl_connection *connection, const void *data, size int wl_connection_queue(struct wl_connection *connection, const void *data, size_t count); -union wl_argument { - int32_t i; - uint32_t u; - wl_fixed_t f; - const char *s; - struct wl_object *o; - uint32_t n; - struct wl_array *a; - int32_t h; -}; - struct wl_closure { int count; const struct wl_message *message; @@ -163,6 +152,9 @@ enum wl_closure_invoke_flag { void wl_closure_invoke(struct wl_closure *closure, uint32_t flags, struct wl_object *target, uint32_t opcode, void *data); +void +wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher, + struct wl_object *target, uint32_t opcode); int wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); int diff --git a/src/wayland-server.c b/src/wayland-server.c index 771309f..a1d69e5 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -114,21 +114,20 @@ struct wl_resource { struct wl_client *client; void *data; int version; + wl_dispatcher_func_t dispatcher; }; static int wl_debug = 0; WL_EXPORT void -wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...) +wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode, + union wl_argument *args) { struct wl_closure *closure; struct wl_object *object = &resource->object; - va_list ap; - va_start(ap, opcode); - closure = wl_closure_vmarshal(object, opcode, ap, - &object->interface->events[opcode]); - va_end(ap); + closure = wl_closure_marshal(object, opcode, args, + &object->interface->events[opcode]); if (closure == NULL) { resource->client->error = 1; @@ -144,19 +143,32 @@ 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, ...) +wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...) { - struct wl_closure *closure; + union wl_argument args[WL_CLOSURE_MAX_ARGS]; struct wl_object *object = &resource->object; va_list ap; va_start(ap, opcode); - closure = wl_closure_vmarshal(object, opcode, ap, - &object->interface->events[opcode]); + wl_argument_from_va_list(object->interface->events[opcode].signature, + args, WL_CLOSURE_MAX_ARGS, ap); va_end(ap); + wl_resource_post_event_array(resource, opcode, args); +} + + +WL_EXPORT void +wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode, + union wl_argument *args) +{ + struct wl_closure *closure; + struct wl_object *object = &resource->object; + + closure = wl_closure_marshal(object, opcode, args, + &object->interface->events[opcode]); + if (closure == NULL) { resource->client->error = 1; return; @@ -172,6 +184,21 @@ wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...) } WL_EXPORT void +wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...) +{ + union wl_argument args[WL_CLOSURE_MAX_ARGS]; + struct wl_object *object = &resource->object; + va_list ap; + + va_start(ap, opcode); + wl_argument_from_va_list(object->interface->events[opcode].signature, + args, WL_CLOSURE_MAX_ARGS, ap); + va_end(ap); + + wl_resource_queue_event_array(resource, opcode, args); +} + +WL_EXPORT void wl_resource_post_error(struct wl_resource *resource, uint32_t code, const char *msg, ...) { @@ -300,8 +327,14 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) if (wl_debug) wl_closure_print(closure, object, false); - wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, object, - opcode, client); + if ((resource_flags & WL_MAP_ENTRY_LEGACY) || + resource->dispatcher == NULL) { + wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, + object, opcode, client); + } else { + wl_closure_dispatch(closure, resource->dispatcher, + object, opcode); + } wl_closure_destroy(closure); @@ -1032,8 +1065,20 @@ wl_resource_set_implementation(struct wl_resource *resource, resource->object.implementation = implementation; resource->data = data; resource->destroy = destroy; + resource->dispatcher = NULL; } +WL_EXPORT void +wl_resource_set_dispatcher(struct wl_resource *resource, + wl_dispatcher_func_t dispatcher, + const void *implementation, + void *data, wl_resource_destroy_func_t destroy) +{ + resource->dispatcher = dispatcher; + resource->object.implementation = implementation; + resource->data = data; + resource->destroy = destroy; +} WL_EXPORT struct wl_resource * wl_resource_create(struct wl_client *client, @@ -1059,6 +1104,7 @@ wl_resource_create(struct wl_client *client, resource->client = client; resource->data = NULL; resource->version = version; + resource->dispatcher = NULL; if (wl_map_insert_at(&client->objects, 0, resource->object.id, resource) < 0) { wl_resource_post_error(client->display_resource, diff --git a/src/wayland-server.h b/src/wayland-server.h index e5e0ed8..d77050d 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -241,8 +241,12 @@ wl_display_remove_global(struct wl_display *display, */ void wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...); +void wl_resource_post_event_array(struct wl_resource *resource, + uint32_t opcode, union wl_argument *args); void wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...); +void wl_resource_queue_event_array(struct wl_resource *resource, + uint32_t opcode, union wl_argument *args); /* msg is a printf format string, variable args are its args. */ void wl_resource_post_error(struct wl_resource *resource, @@ -264,6 +268,12 @@ wl_resource_set_implementation(struct wl_resource *resource, const void *implementation, void *data, wl_resource_destroy_func_t destroy); +void +wl_resource_set_dispatcher(struct wl_resource *resource, + wl_dispatcher_func_t dispatcher, + const void *implementation, + void *data, + wl_resource_destroy_func_t destroy); void wl_resource_destroy(struct wl_resource *resource); diff --git a/src/wayland-util.h b/src/wayland-util.h index 53d3282..e5e4e25 100644 --- a/src/wayland-util.h +++ b/src/wayland-util.h @@ -199,6 +199,46 @@ static inline wl_fixed_t wl_fixed_from_int(int i) return i * 256; } +/** + * \brief A union representing all of the basic data types that can be passed + * along the wayland wire format. + * + * This union represents all of the basic data types that can be passed in the + * wayland wire format. It is used by dispatchers and runtime-friendly + * versions of the event and request marshaling functions. + */ +union wl_argument { + int32_t i; /**< signed integer */ + uint32_t u; /**< unsigned integer */ + wl_fixed_t f; /**< fixed point */ + const char *s; /**< string */ + struct wl_object *o; /**< object */ + uint32_t n; /**< new_id */ + struct wl_array *a; /**< array */ + int32_t h; /**< file descriptor */ +}; + +/** + * \brief A function pointer type for a dispatcher. + * + * A dispatcher is a function that handles the emitting of callbacks in client + * code. For programs directly using the C library, this is done by using + * libffi to call function pointers. When binding to languages other than C, + * dispatchers provide a way to abstract the function calling process to be + * friendlier to other function calling systems. + * + * A dispatcher takes five arguments: The first is the dispatcher-specific + * implementation data associated with the target object. The second is the + * object on which the callback is being invoked (either wl_proxy or + * wl_resource). The third and fourth arguments are the opcode the wl_messsage + * structure corresponding to the callback being emitted. The final argument + * is an array of arguments recieved from the other process via the wire + * protocol. + */ +typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t, + const struct wl_message *, + union wl_argument *); + typedef void (*wl_log_func_t)(const char *, va_list); #ifdef __cplusplus |