diff options
author | Jason Ekstrand <jason@jlekstrand.net> | 2013-07-17 21:58:47 -0500 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2013-08-19 16:23:08 -0700 |
commit | eb947e9408c149041c4c8e1c80ef9ebea049f477 (patch) | |
tree | 4fb9aebd45758a70e85941bbc52a7cc5b7965587 | |
parent | c44090908db1c4f1b0e87bda2e4fdaa6bc15c0d1 (diff) |
Add support for client-side language bindings
This commit adds support for language bindings on the client half of the
library. The idea is the same as for server-side dispatchers.
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
-rw-r--r-- | src/wayland-client.c | 90 | ||||
-rw-r--r-- | src/wayland-client.h | 5 |
2 files changed, 86 insertions, 9 deletions
diff --git a/src/wayland-client.c b/src/wayland-client.c index 3ff3629..04d988b 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -59,6 +59,7 @@ struct wl_proxy { uint32_t flags; int refcount; void *user_data; + wl_dispatcher_func_t dispatcher; }; struct wl_global { @@ -224,6 +225,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface) proxy->object.interface = interface; proxy->object.implementation = NULL; + proxy->dispatcher = NULL; proxy->display = display; proxy->queue = factory->queue; proxy->flags = 0; @@ -251,6 +253,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory, proxy->object.interface = interface; proxy->object.implementation = NULL; proxy->object.id = id; + proxy->dispatcher = NULL; proxy->display = display; proxy->queue = factory->queue; proxy->flags = 0; @@ -314,7 +317,7 @@ 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->dispatcher) { fprintf(stderr, "proxy already has listener\n"); return -1; } @@ -344,6 +347,41 @@ wl_proxy_get_listener(struct wl_proxy *proxy) return proxy->object.implementation; } +/** Set a proxy's listener (with dispatcher) + * + * \param proxy The proxy object + * \param dispatcher The dispatcher to be used for this proxy + * \param implementation The dispatcher-specific listener implementation + * \param data User data to be associated with the proxy + * \return 0 on success or -1 on failure + * + * Set proxy's listener to use \c dispatcher_func as its dispatcher and \c + * dispatcher_data as its dispatcher-specific implementation and its user data + * to \c data. If a listener has already been set, this function + * fails and nothing is changed. + * + * The exact details of dispatcher_data depend on the dispatcher used. This + * function is intended to be used by language bindings, not user code. + * + * \memberof wl_proxy + */ +WL_EXPORT int +wl_proxy_add_dispatcher(struct wl_proxy *proxy, + wl_dispatcher_func_t dispatcher, + const void *implementation, void *data) +{ + if (proxy->object.implementation || proxy->dispatcher) { + fprintf(stderr, "proxy already has listener\n"); + return -1; + } + + proxy->object.implementation = implementation; + proxy->dispatcher = dispatcher; + proxy->user_data = data; + + return 0; +} + /** Prepare a request to be sent to the compositor * * \param proxy The proxy object @@ -375,16 +413,45 @@ wl_proxy_get_listener(struct wl_proxy *proxy) WL_EXPORT void wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) { - struct wl_closure *closure; + union wl_argument args[WL_CLOSURE_MAX_ARGS]; va_list ap; - pthread_mutex_lock(&proxy->display->mutex); - va_start(ap, opcode); - closure = wl_closure_vmarshal(&proxy->object, opcode, ap, - &proxy->object.interface->methods[opcode]); + wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature, + args, WL_CLOSURE_MAX_ARGS, ap); va_end(ap); + wl_proxy_marshal_array(proxy, opcode, args); +} + +/** Prepare a request to be sent to the compositor + * + * \param proxy The proxy object + * \param opcode Opcode of the request to be sent + * \param args Extra arguments for the given request + * + * Translates the request given by opcode and the extra arguments into the + * wire format and write it to the connection buffer. This version takes an + * array of the union type wl_argument. + * + * \note This is intended to be used by language bindings and not in + * non-generated code. + * + * \sa wl_proxy_marshal() + * + * \memberof wl_proxy + */ +WL_EXPORT void +wl_proxy_marshal_array(struct wl_proxy *proxy, uint32_t opcode, + union wl_argument *args) +{ + struct wl_closure *closure; + + pthread_mutex_lock(&proxy->display->mutex); + + closure = wl_closure_marshal(&proxy->object, opcode, args, + &proxy->object.interface->methods[opcode]); + if (closure == NULL) { fprintf(stderr, "Error marshalling request\n"); abort(); @@ -867,13 +934,18 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue) pthread_mutex_unlock(&display->mutex); - if (proxy->object.implementation) { + if (proxy->dispatcher) { + if (wl_debug) + wl_closure_print(closure, &proxy->object, false); + + wl_closure_dispatch(closure, proxy->dispatcher, + &proxy->object, opcode); + } else if (proxy->object.implementation) { if (wl_debug) wl_closure_print(closure, &proxy->object, false); wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT, - &proxy->object, opcode, - proxy->user_data); + &proxy->object, opcode, proxy->user_data); } wl_closure_destroy(closure); diff --git a/src/wayland-client.h b/src/wayland-client.h index 32ed373..cf92174 100644 --- a/src/wayland-client.h +++ b/src/wayland-client.h @@ -122,6 +122,8 @@ struct wl_event_queue; void wl_event_queue_destroy(struct wl_event_queue *queue); void wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...); +void wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode, + union wl_argument *args); struct wl_proxy *wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface); @@ -129,6 +131,9 @@ void wl_proxy_destroy(struct wl_proxy *proxy); int wl_proxy_add_listener(struct wl_proxy *proxy, void (**implementation)(void), void *data); const void *wl_proxy_get_listener(struct wl_proxy *proxy); +int wl_proxy_add_dispatcher(struct wl_proxy *proxy, + wl_dispatcher_func_t dispatcher_func, + const void * dispatcher_data, void *data); void wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data); void *wl_proxy_get_user_data(struct wl_proxy *proxy); uint32_t wl_proxy_get_id(struct wl_proxy *proxy); |