[PATCH wayland 3/6] Add a dispatcher field to wl_object.

Jason Ekstrand jason at jlekstrand.net
Fri Mar 8 20:28:13 PST 2013


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 <jason at jlekstrand.net>
---
 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



More information about the wayland-devel mailing list