[PATCH wayland 2/2] Add support for client-side language bindings

Jason Ekstrand jason at jlekstrand.net
Mon Apr 8 07:30:58 PDT 2013


This commit adds support for language bindings on the client half of the
library.  The idea is the same as for the server-side dispatchers, only simpler
because of better API isolation of wl_proxy.

Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
---
 src/wayland-client.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++-----
 src/wayland-client.h |  5 +++
 2 files changed, 88 insertions(+), 9 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 7847370..cba6910 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -47,11 +47,12 @@
 
 enum wl_proxy_flag {
 	WL_PROXY_FLAG_ID_DELETED = (1 << 0),
-	WL_PROXY_FLAG_DESTROYED = (1 << 1)
+	WL_PROXY_FLAG_DESTROYED = (1 << 1),
 };
 
 struct wl_proxy {
 	struct wl_object object;
+	struct wl_dispatcher dispatcher;
 	struct wl_display *display;
 	struct wl_event_queue *queue;
 	uint32_t flags;
@@ -220,6 +221,8 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
 
 	proxy->object.interface = interface;
 	proxy->object.implementation = NULL;
+	proxy->dispatcher.dispatcher = NULL;
+	proxy->dispatcher.data = NULL;
 	proxy->display = display;
 	proxy->queue = factory->queue;
 	proxy->flags = 0;
@@ -248,6 +251,8 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
 	proxy->object.interface = interface;
 	proxy->object.implementation = NULL;
 	proxy->object.id = id;
+	proxy->dispatcher.dispatcher = NULL;
+	proxy->dispatcher.data = NULL;
 	proxy->display = display;
 	proxy->queue = factory->queue;
 	proxy->flags = 0;
@@ -311,7 +316,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.dispatcher) {
 		fprintf(stderr, "proxy already has listener\n");
 		return -1;
 	}
@@ -322,6 +327,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_func The dispatcher to be used for this listener
+ * \param dispatcher_data The dispatcher-specific listener data be added to proxy
+ * \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_dispatched_listener(struct wl_proxy *proxy,
+				 wl_dispatcher_func_t dispatcher_func,
+				 const void * dispatcher_data, void *data)
+{
+	if (proxy->object.implementation || proxy->dispatcher.dispatcher) {
+		fprintf(stderr, "proxy already has listener\n");
+		return -1;
+	}
+
+	proxy->dispatcher.dispatcher = dispatcher_func;
+	proxy->dispatcher.data = dispatcher_data;
+	proxy->user_data = data;
+
+	return 0;
+}
+
 /** Prepare a request to be sent to the compositor
  *
  * \param proxy The proxy object
@@ -353,16 +393,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_a(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_a(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();
@@ -841,8 +910,13 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
 			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);
+	} else if (proxy->dispatcher.dispatcher) {
+		if (wl_debug)
+			wl_closure_print(closure, &proxy->object, false);
+
+		wl_closure_dispatch(closure, &proxy->dispatcher,
+				    &proxy->object, opcode);
 	}
 
 	wl_closure_destroy(closure);
diff --git a/src/wayland-client.h b/src/wayland-client.h
index 578fa7e..1660df7 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_a(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_dispatched_listener(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.1.4



More information about the wayland-devel mailing list