This commit adds support for custom dispatchers via a new dispatcher field in wl_object. If the dispatcher field is set to null, the default libffi-based dispatcher will be used.
Signed-off-by: Jason Ekstrand <[email protected]> --- src/connection.c | 52 ++++++++++++++++++++++++++++++++++++++++++++------- src/wayland-client.c | 8 ++++++-- src/wayland-private.h | 11 ----------- src/wayland-server.h | 1 + src/wayland-util.h | 33 +++++++++++++++++++++++++++++++- 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/src/connection.c b/src/connection.c index 816392d..7e25b44 100644 --- a/src/connection.c +++ b/src/connection.c @@ -859,10 +859,10 @@ 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) +static void +ffi_dispatch_closure(struct wl_object * target, uint32_t flags, uint32_t opcode, + const struct wl_message *message, void *data, + union wl_argument *args) { int count; ffi_cif cif; @@ -870,15 +870,15 @@ wl_closure_invoke(struct wl_closure *closure, uint32_t flags, void * ffi_args[WL_CLOSURE_MAX_ARGS + 2]; void (* const *implementation)(void); - count = arg_count_for_signature(closure->message->signature); + count = arg_count_for_signature(message->signature); ffi_types[0] = &ffi_type_pointer; ffi_args[0] = &data; ffi_types[1] = &ffi_type_pointer; ffi_args[1] = ⌖ - convert_arguments_to_ffi(closure->message->signature, flags, closure->args, - count, ffi_types + 2, ffi_args + 2); + convert_arguments_to_ffi(message->signature, flags, args, count, + ffi_types + 2, ffi_args + 2); ffi_prep_cif(&cif, FFI_DEFAULT_ABI, count + 2, &ffi_type_void, ffi_types); @@ -887,6 +887,44 @@ wl_closure_invoke(struct wl_closure *closure, uint32_t flags, ffi_call(&cif, implementation[opcode], NULL, ffi_args); } +void +wl_object_default_client_dispatcher(struct wl_object * target, uint32_t opcode, + const struct wl_message *message, + void *data, union wl_argument *args) +{ + ffi_dispatch_closure(target, WL_CLOSURE_INVOKE_CLIENT, opcode, + message, data, args); +} + +void +wl_object_default_server_dispatcher(struct wl_object * target, uint32_t opcode, + const struct wl_message *message, + void *data, union wl_argument *args) +{ + ffi_dispatch_closure(target, WL_CLOSURE_INVOKE_SERVER, opcode, + message, data, args); +} + +void +wl_closure_invoke(struct wl_closure *closure, uint32_t flags, + struct wl_object *target, uint32_t opcode, void *data) +{ + if (target->dispatcher) { + (*target->dispatcher)(target, opcode, closure->message, + data, closure->args); + } else { + if (flags & WL_CLOSURE_INVOKE_CLIENT) { + wl_object_default_client_dispatcher(target, opcode, + closure->message, + data, closure->args); + } else { + wl_object_default_server_dispatcher(target, opcode, + closure->message, + data, closure->args); + } + } +} + static int copy_fds_to_connection(struct wl_closure *closure, struct wl_connection *connection) diff --git a/src/wayland-client.c b/src/wayland-client.c index 5b3f5dc..1b52e32 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -220,6 +220,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface) proxy->object.interface = interface; proxy->object.implementation = NULL; + proxy->object.dispatcher = NULL; proxy->display = display; proxy->queue = factory->queue; proxy->flags = 0; @@ -247,6 +248,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory, proxy->object.interface = interface; proxy->object.implementation = NULL; + proxy->object.dispatcher = NULL; proxy->object.id = id; proxy->display = display; proxy->queue = factory->queue; @@ -311,12 +313,13 @@ WL_EXPORT int wl_proxy_add_listener(struct wl_proxy *proxy, void (**implementation)(void), void *data) { - if (proxy->object.implementation) { + if (proxy->object.implementation || proxy->object.dispatcher) { fprintf(stderr, "proxy already has listener\n"); return -1; } proxy->object.implementation = implementation; + proxy->object.dispatcher = NULL; proxy->user_data = data; return 0; @@ -527,6 +530,7 @@ wl_display_connect_to_fd(int fd) WL_MAP_CLIENT_SIDE, display); display->proxy.display = display; display->proxy.object.implementation = (void(**)(void)) &display_listener; + display->proxy.object.dispatcher = NULL; display->proxy.user_data = display; display->proxy.queue = &display->queue; display->proxy.flags = 0; @@ -833,7 +837,7 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue) pthread_mutex_unlock(&display->mutex); - if (proxy->object.implementation) { + if (proxy->object.implementation || proxy->object.dispatcher) { if (wl_debug) wl_closure_print(closure, &proxy->object, false); diff --git a/src/wayland-private.h b/src/wayland-private.h index 3669ba9..c3b6724 100644 --- a/src/wayland-private.h +++ b/src/wayland-private.h @@ -75,17 +75,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; diff --git a/src/wayland-server.h b/src/wayland-server.h index 38b8303..b720f32 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -198,6 +198,7 @@ wl_resource_init(struct wl_resource *resource, resource->object.id = id; resource->object.interface = interface; resource->object.implementation = implementation; + resource->object.dispatcher = NULL; wl_signal_init(&resource->destroy_signal); diff --git a/src/wayland-util.h b/src/wayland-util.h index 257a5d1..b15a53f 100644 --- a/src/wayland-util.h +++ b/src/wayland-util.h @@ -1,5 +1,6 @@ /* * Copyright © 2008 Kristian Høgsberg + * Copyright © 2013 Jason Ekstrand * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -54,12 +55,31 @@ struct wl_interface { const struct wl_message *events; }; +struct wl_object; +union wl_argument; + +typedef void (*wl_object_dispatcher_func_t)(struct wl_object *, uint32_t, + const struct wl_message *, + void *, union wl_argument *); + struct wl_object { const struct wl_interface *interface; - void (* const * implementation)(void); + const void *implementation; uint32_t id; + + /* Added since Wayland version 1.0 */ + wl_object_dispatcher_func_t dispatcher; }; +void +wl_object_default_client_dispatcher(struct wl_object * target, uint32_t opcode, + const struct wl_message *message, + void *data, union wl_argument *args); +void +wl_object_default_server_dispatcher(struct wl_object * target, uint32_t opcode, + const struct wl_message *message, + void *data, union wl_argument *args); + /** * wl_list - linked list * @@ -198,6 +218,17 @@ static inline wl_fixed_t wl_fixed_from_int(int i) return i * 256; } +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; +}; + typedef void (*wl_log_func_t)(const char *, va_list); #ifdef __cplusplus -- 1.8.1.4 _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
