mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-04 13:29:51 -05:00
Add support for server-side language bindings
This commit adds support for server-side languages bindings. This is done in two ways: 1. Adding a wl_resource_set_dispatcher function that corresponds to wl_resource_set_interface. The only difference between the two functions is that the new version takes a dispatcher along with the implementation, data, and destructor. This allows for runtime calling of native language functions for callbacks instead of having to generate function pointers. 2. Adding versions of wl_resource_post_event and wl_resource_queue_event that take an array of wl_argument instead of a variable argument list. This allows for easier run-time argument conversion and removes the need for libffi-based calling of variadic functions. Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
parent
6b8eef962f
commit
c44090908d
5 changed files with 120 additions and 25 deletions
|
|
@ -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;
|
||||
|
|
@ -171,6 +183,21 @@ wl_resource_queue_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, ...)
|
||||
{
|
||||
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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue