summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connection.c9
-rw-r--r--src/wayland-private.h14
-rw-r--r--src/wayland-server.c72
-rw-r--r--src/wayland-server.h10
-rw-r--r--src/wayland-util.h40
5 files changed, 120 insertions, 25 deletions
diff --git a/src/connection.c b/src/connection.c
index 9bb850c..451b93e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -891,7 +891,6 @@ 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)
@@ -919,6 +918,14 @@ wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
ffi_call(&cif, implementation[opcode], NULL, ffi_args);
}
+void
+wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
+ struct wl_object *target, uint32_t opcode)
+{
+ dispatcher(target->implementation, target, opcode, closure->message,
+ closure->args);
+}
+
static int
copy_fds_to_connection(struct wl_closure *closure,
struct wl_connection *connection)
diff --git a/src/wayland-private.h b/src/wayland-private.h
index 7f8c12c..67e8783 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -97,17 +97,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;
@@ -163,6 +152,9 @@ enum wl_closure_invoke_flag {
void
wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
struct wl_object *target, uint32_t opcode, void *data);
+void
+wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
+ struct wl_object *target, uint32_t opcode);
int
wl_closure_send(struct wl_closure *closure, struct wl_connection *connection);
int
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 771309f..a1d69e5 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -114,21 +114,20 @@ struct wl_resource {
struct wl_client *client;
void *data;
int version;
+ wl_dispatcher_func_t dispatcher;
};
static int wl_debug = 0;
WL_EXPORT void
-wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
+wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
+ union wl_argument *args)
{
struct wl_closure *closure;
struct wl_object *object = &resource->object;
- va_list ap;
- va_start(ap, opcode);
- closure = wl_closure_vmarshal(object, opcode, ap,
- &object->interface->events[opcode]);
- va_end(ap);
+ closure = wl_closure_marshal(object, opcode, args,
+ &object->interface->events[opcode]);
if (closure == NULL) {
resource->client->error = 1;
@@ -144,19 +143,32 @@ wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
wl_closure_destroy(closure);
}
-
WL_EXPORT void
-wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
+wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
{
- struct wl_closure *closure;
+ union wl_argument args[WL_CLOSURE_MAX_ARGS];
struct wl_object *object = &resource->object;
va_list ap;
va_start(ap, opcode);
- closure = wl_closure_vmarshal(object, opcode, ap,
- &object->interface->events[opcode]);
+ wl_argument_from_va_list(object->interface->events[opcode].signature,
+ args, WL_CLOSURE_MAX_ARGS, ap);
va_end(ap);
+ wl_resource_post_event_array(resource, opcode, args);
+}
+
+
+WL_EXPORT void
+wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode,
+ union wl_argument *args)
+{
+ struct wl_closure *closure;
+ struct wl_object *object = &resource->object;
+
+ closure = wl_closure_marshal(object, opcode, args,
+ &object->interface->events[opcode]);
+
if (closure == NULL) {
resource->client->error = 1;
return;
@@ -172,6 +184,21 @@ wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
}
WL_EXPORT void
+wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
+{
+ union wl_argument args[WL_CLOSURE_MAX_ARGS];
+ struct wl_object *object = &resource->object;
+ va_list ap;
+
+ va_start(ap, opcode);
+ wl_argument_from_va_list(object->interface->events[opcode].signature,
+ args, WL_CLOSURE_MAX_ARGS, ap);
+ va_end(ap);
+
+ wl_resource_queue_event_array(resource, opcode, args);
+}
+
+WL_EXPORT void
wl_resource_post_error(struct wl_resource *resource,
uint32_t code, const char *msg, ...)
{
@@ -300,8 +327,14 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
if (wl_debug)
wl_closure_print(closure, object, false);
- wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, object,
- opcode, client);
+ if ((resource_flags & WL_MAP_ENTRY_LEGACY) ||
+ resource->dispatcher == NULL) {
+ wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER,
+ object, opcode, client);
+ } else {
+ wl_closure_dispatch(closure, resource->dispatcher,
+ object, opcode);
+ }
wl_closure_destroy(closure);
@@ -1032,8 +1065,20 @@ wl_resource_set_implementation(struct wl_resource *resource,
resource->object.implementation = implementation;
resource->data = data;
resource->destroy = destroy;
+ resource->dispatcher = NULL;
}
+WL_EXPORT void
+wl_resource_set_dispatcher(struct wl_resource *resource,
+ wl_dispatcher_func_t dispatcher,
+ const void *implementation,
+ void *data, wl_resource_destroy_func_t destroy)
+{
+ resource->dispatcher = dispatcher;
+ resource->object.implementation = implementation;
+ resource->data = data;
+ resource->destroy = destroy;
+}
WL_EXPORT struct wl_resource *
wl_resource_create(struct wl_client *client,
@@ -1059,6 +1104,7 @@ wl_resource_create(struct wl_client *client,
resource->client = client;
resource->data = NULL;
resource->version = version;
+ resource->dispatcher = NULL;
if (wl_map_insert_at(&client->objects, 0, resource->object.id, resource) < 0) {
wl_resource_post_error(client->display_resource,
diff --git a/src/wayland-server.h b/src/wayland-server.h
index e5e0ed8..d77050d 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -241,8 +241,12 @@ wl_display_remove_global(struct wl_display *display,
*/
void wl_resource_post_event(struct wl_resource *resource,
uint32_t opcode, ...);
+void wl_resource_post_event_array(struct wl_resource *resource,
+ uint32_t opcode, union wl_argument *args);
void wl_resource_queue_event(struct wl_resource *resource,
uint32_t opcode, ...);
+void wl_resource_queue_event_array(struct wl_resource *resource,
+ uint32_t opcode, union wl_argument *args);
/* msg is a printf format string, variable args are its args. */
void wl_resource_post_error(struct wl_resource *resource,
@@ -264,6 +268,12 @@ wl_resource_set_implementation(struct wl_resource *resource,
const void *implementation,
void *data,
wl_resource_destroy_func_t destroy);
+void
+wl_resource_set_dispatcher(struct wl_resource *resource,
+ wl_dispatcher_func_t dispatcher,
+ const void *implementation,
+ void *data,
+ wl_resource_destroy_func_t destroy);
void
wl_resource_destroy(struct wl_resource *resource);
diff --git a/src/wayland-util.h b/src/wayland-util.h
index 53d3282..e5e4e25 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -199,6 +199,46 @@ static inline wl_fixed_t wl_fixed_from_int(int i)
return i * 256;
}
+/**
+ * \brief A union representing all of the basic data types that can be passed
+ * along the wayland wire format.
+ *
+ * This union represents all of the basic data types that can be passed in the
+ * wayland wire format. It is used by dispatchers and runtime-friendly
+ * versions of the event and request marshaling functions.
+ */
+union wl_argument {
+ int32_t i; /**< signed integer */
+ uint32_t u; /**< unsigned integer */
+ wl_fixed_t f; /**< fixed point */
+ const char *s; /**< string */
+ struct wl_object *o; /**< object */
+ uint32_t n; /**< new_id */
+ struct wl_array *a; /**< array */
+ int32_t h; /**< file descriptor */
+};
+
+/**
+ * \brief A function pointer type for a dispatcher.
+ *
+ * A dispatcher is a function that handles the emitting of callbacks in client
+ * code. For programs directly using the C library, this is done by using
+ * libffi to call function pointers. When binding to languages other than C,
+ * dispatchers provide a way to abstract the function calling process to be
+ * friendlier to other function calling systems.
+ *
+ * A dispatcher takes five arguments: The first is the dispatcher-specific
+ * implementation data associated with the target object. The second is the
+ * object on which the callback is being invoked (either wl_proxy or
+ * wl_resource). The third and fourth arguments are the opcode the wl_messsage
+ * structure corresponding to the callback being emitted. The final argument
+ * is an array of arguments recieved from the other process via the wire
+ * protocol.
+ */
+typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t,
+ const struct wl_message *,
+ union wl_argument *);
+
typedef void (*wl_log_func_t)(const char *, va_list);
#ifdef __cplusplus