mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Add support for client-side language bindings
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@jlekstrand.net>
This commit is contained in:
parent
c44090908d
commit
eb947e9408
2 changed files with 86 additions and 9 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -344,6 +347,41 @@ wl_proxy_get_listener(struct wl_proxy *proxy)
|
|||
return proxy->object.implementation;
|
||||
}
|
||||
|
||||
/** 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
|
||||
|
|
@ -375,15 +413,44 @@ wl_proxy_get_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;
|
||||
|
||||
va_start(ap, 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);
|
||||
|
||||
va_start(ap, opcode);
|
||||
closure = wl_closure_vmarshal(&proxy->object, opcode, ap,
|
||||
&proxy->object.interface->methods[opcode]);
|
||||
va_end(ap);
|
||||
closure = wl_closure_marshal(&proxy->object, opcode, args,
|
||||
&proxy->object.interface->methods[opcode]);
|
||||
|
||||
if (closure == NULL) {
|
||||
fprintf(stderr, "Error marshalling request\n");
|
||||
|
|
@ -867,13 +934,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);
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ 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);
|
||||
|
||||
|
|
@ -129,6 +131,9 @@ void wl_proxy_destroy(struct wl_proxy *proxy);
|
|||
int wl_proxy_add_listener(struct wl_proxy *proxy,
|
||||
void (**implementation)(void), void *data);
|
||||
const void *wl_proxy_get_listener(struct wl_proxy *proxy);
|
||||
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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue