[PATCH 2/3] Add support for client-side language bindings
Jason Ekstrand
jason at jlekstrand.net
Wed Jul 17 19:58:47 PDT 2013
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 at jlekstrand.net>
---
src/wayland-client.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++------
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 2887a40..b53ec69 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;
}
@@ -325,6 +328,41 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
return 0;
}
+/** 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
@@ -356,16 +394,45 @@ wl_proxy_add_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();
@@ -848,13 +915,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 216773a..b9cb3e1 100644
--- a/src/wayland-client.h
+++ b/src/wayland-client.h
@@ -122,12 +122,17 @@ 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);
void wl_proxy_destroy(struct wl_proxy *proxy);
int wl_proxy_add_listener(struct wl_proxy *proxy,
void (**implementation)(void), void *data);
+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);
--
1.8.3.1
More information about the wayland-devel
mailing list