mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05: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;
 | 
						uint32_t flags;
 | 
				
			||||||
	int refcount;
 | 
						int refcount;
 | 
				
			||||||
	void *user_data;
 | 
						void *user_data;
 | 
				
			||||||
 | 
						wl_dispatcher_func_t dispatcher;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_global {
 | 
					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.interface = interface;
 | 
				
			||||||
	proxy->object.implementation = NULL;
 | 
						proxy->object.implementation = NULL;
 | 
				
			||||||
 | 
						proxy->dispatcher = NULL;
 | 
				
			||||||
	proxy->display = display;
 | 
						proxy->display = display;
 | 
				
			||||||
	proxy->queue = factory->queue;
 | 
						proxy->queue = factory->queue;
 | 
				
			||||||
	proxy->flags = 0;
 | 
						proxy->flags = 0;
 | 
				
			||||||
| 
						 | 
					@ -251,6 +253,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
 | 
				
			||||||
	proxy->object.interface = interface;
 | 
						proxy->object.interface = interface;
 | 
				
			||||||
	proxy->object.implementation = NULL;
 | 
						proxy->object.implementation = NULL;
 | 
				
			||||||
	proxy->object.id = id;
 | 
						proxy->object.id = id;
 | 
				
			||||||
 | 
						proxy->dispatcher = NULL;
 | 
				
			||||||
	proxy->display = display;
 | 
						proxy->display = display;
 | 
				
			||||||
	proxy->queue = factory->queue;
 | 
						proxy->queue = factory->queue;
 | 
				
			||||||
	proxy->flags = 0;
 | 
						proxy->flags = 0;
 | 
				
			||||||
| 
						 | 
					@ -314,7 +317,7 @@ WL_EXPORT int
 | 
				
			||||||
wl_proxy_add_listener(struct wl_proxy *proxy,
 | 
					wl_proxy_add_listener(struct wl_proxy *proxy,
 | 
				
			||||||
		      void (**implementation)(void), void *data)
 | 
							      void (**implementation)(void), void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (proxy->object.implementation) {
 | 
						if (proxy->object.implementation || proxy->dispatcher) {
 | 
				
			||||||
		fprintf(stderr, "proxy already has listener\n");
 | 
							fprintf(stderr, "proxy already has listener\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -344,6 +347,41 @@ wl_proxy_get_listener(struct wl_proxy *proxy)
 | 
				
			||||||
	return proxy->object.implementation;
 | 
						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
 | 
					/** Prepare a request to be sent to the compositor
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param proxy The proxy object
 | 
					 * \param proxy The proxy object
 | 
				
			||||||
| 
						 | 
					@ -375,15 +413,44 @@ wl_proxy_get_listener(struct wl_proxy *proxy)
 | 
				
			||||||
WL_EXPORT void
 | 
					WL_EXPORT void
 | 
				
			||||||
wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
 | 
					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_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);
 | 
						pthread_mutex_lock(&proxy->display->mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	va_start(ap, opcode);
 | 
						closure = wl_closure_marshal(&proxy->object, opcode, args,
 | 
				
			||||||
	closure = wl_closure_vmarshal(&proxy->object, opcode, ap,
 | 
					 | 
				
			||||||
				     &proxy->object.interface->methods[opcode]);
 | 
									     &proxy->object.interface->methods[opcode]);
 | 
				
			||||||
	va_end(ap);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (closure == NULL) {
 | 
						if (closure == NULL) {
 | 
				
			||||||
		fprintf(stderr, "Error marshalling request\n");
 | 
							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);
 | 
						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)
 | 
							if (wl_debug)
 | 
				
			||||||
			wl_closure_print(closure, &proxy->object, false);
 | 
								wl_closure_print(closure, &proxy->object, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
 | 
							wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
 | 
				
			||||||
				  &proxy->object, opcode,
 | 
									  &proxy->object, opcode, proxy->user_data);
 | 
				
			||||||
				  proxy->user_data);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_closure_destroy(closure);
 | 
						wl_closure_destroy(closure);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,6 +122,8 @@ struct wl_event_queue;
 | 
				
			||||||
void wl_event_queue_destroy(struct wl_event_queue *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(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,
 | 
					struct wl_proxy *wl_proxy_create(struct wl_proxy *factory,
 | 
				
			||||||
				 const struct wl_interface *interface);
 | 
									 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,
 | 
					int wl_proxy_add_listener(struct wl_proxy *proxy,
 | 
				
			||||||
			  void (**implementation)(void), void *data);
 | 
								  void (**implementation)(void), void *data);
 | 
				
			||||||
const void *wl_proxy_get_listener(struct wl_proxy *proxy);
 | 
					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_set_user_data(struct wl_proxy *proxy, void *user_data);
 | 
				
			||||||
void *wl_proxy_get_user_data(struct wl_proxy *proxy);
 | 
					void *wl_proxy_get_user_data(struct wl_proxy *proxy);
 | 
				
			||||||
uint32_t wl_proxy_get_id(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