| /* |
| * Copyright © 2008-2012 Kristian Høgsberg |
| * Copyright © 2010-2012 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sublicense, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the |
| * next paragraph) shall be included in all copies or substantial |
| * portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| */ |
| |
| #define _GNU_SOURCE |
| |
| #include <stdlib.h> |
| #include <stdint.h> |
| #include <stddef.h> |
| #include <stdio.h> |
| #include <stdbool.h> |
| #include <errno.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| #include <ctype.h> |
| #include <assert.h> |
| #include <fcntl.h> |
| #include <poll.h> |
| #include <pthread.h> |
| |
| #include "wayland-util.h" |
| #include "wayland-os.h" |
| #include "wayland-client.h" |
| #include "wayland-private.h" |
| |
| /** \cond */ |
| |
| enum wl_proxy_flag { |
| WL_PROXY_FLAG_ID_DELETED = (1 << 0), |
| WL_PROXY_FLAG_DESTROYED = (1 << 1), |
| WL_PROXY_FLAG_WRAPPER = (1 << 2), |
| }; |
| |
| struct wl_proxy { |
| struct wl_object object; |
| struct wl_display *display; |
| struct wl_event_queue *queue; |
| uint32_t flags; |
| int refcount; |
| void *user_data; |
| wl_dispatcher_func_t dispatcher; |
| uint32_t version; |
| }; |
| |
| struct wl_global { |
| uint32_t id; |
| char *interface; |
| uint32_t version; |
| struct wl_list link; |
| }; |
| |
| struct wl_event_queue { |
| struct wl_list event_list; |
| struct wl_display *display; |
| }; |
| |
| struct wl_display { |
| struct wl_proxy proxy; |
| struct wl_connection *connection; |
| |
| /* errno of the last wl_display error */ |
| int last_error; |
| |
| /* When display gets an error event from some object, it stores |
| * information about it here, so that client can get this |
| * information afterwards */ |
| struct { |
| /* Code of the error. It can be compared to |
| * the interface's errors enumeration. */ |
| uint32_t code; |
| /* interface (protocol) in which the error occurred */ |
| const struct wl_interface *interface; |
| /* id of the proxy that caused the error. There's no warranty |
| * that the proxy is still valid. It's up to client how it will |
| * use it */ |
| uint32_t id; |
| } protocol_error; |
| int fd; |
| struct wl_map objects; |
| struct wl_event_queue display_queue; |
| struct wl_event_queue default_queue; |
| pthread_mutex_t mutex; |
| |
| int reader_count; |
| uint32_t read_serial; |
| pthread_cond_t reader_cond; |
| }; |
| |
| /** \endcond */ |
| |
| static int debug_client = 0; |
| |
| /** |
| * This helper function wakes up all threads that are |
| * waiting for display->reader_cond (i. e. when reading is done, |
| * canceled, or an error occurred) |
| * |
| * NOTE: must be called with display->mutex locked |
| */ |
| static void |
| display_wakeup_threads(struct wl_display *display) |
| { |
| /* Thread can get sleeping only in read_events(). If we're |
| * waking it up, it means that the read completed or was |
| * canceled, so we must increase the read_serial. |
| * This prevents from indefinite sleeping in read_events(). |
| */ |
| ++display->read_serial; |
| |
| pthread_cond_broadcast(&display->reader_cond); |
| } |
| |
| /** |
| * This function is called for local errors (no memory, server hung up) |
| * |
| * \param display |
| * \param error error value (EINVAL, EFAULT, ...) |
| * |
| * \note this function is called with display mutex locked |
| */ |
| static void |
| display_fatal_error(struct wl_display *display, int error) |
| { |
| if (display->last_error) |
| return; |
| |
| if (!error) |
| error = EFAULT; |
| |
| display->last_error = error; |
| |
| display_wakeup_threads(display); |
| } |
| |
| /** |
| * This function is called for error events |
| * and indicates that in some object an error occurred. |
| * The difference between this function and display_fatal_error() |
| * is that this one handles errors that will come by wire, |
| * whereas display_fatal_error() is called for local errors. |
| * |
| * \param display |
| * \param code error code |
| * \param id id of the object that generated the error |
| * \param intf protocol interface |
| */ |
| static void |
| display_protocol_error(struct wl_display *display, uint32_t code, |
| uint32_t id, const struct wl_interface *intf) |
| { |
| int err; |
| |
| if (display->last_error) |
| return; |
| |
| /* set correct errno */ |
| if (intf && wl_interface_equal(intf, &wl_display_interface)) { |
| switch (code) { |
| case WL_DISPLAY_ERROR_INVALID_OBJECT: |
| case WL_DISPLAY_ERROR_INVALID_METHOD: |
| err = EINVAL; |
| break; |
| case WL_DISPLAY_ERROR_NO_MEMORY: |
| err = ENOMEM; |
| break; |
| default: |
| err = EFAULT; |
| } |
| } else { |
| err = EPROTO; |
| } |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| display->last_error = err; |
| |
| display->protocol_error.code = code; |
| display->protocol_error.id = id; |
| display->protocol_error.interface = intf; |
| |
| /* |
| * here it is not necessary to wake up threads like in |
| * display_fatal_error, because this function is called from |
| * an event handler and that means that read_events() is done |
| * and woke up all threads. Since wl_display_prepare_read() |
| * fails when there are events in the queue, no threads |
| * can sleep in read_events() during dispatching |
| * (and therefore during calling this function), so this is safe. |
| */ |
| |
| pthread_mutex_unlock(&display->mutex); |
| } |
| |
| static void |
| wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display) |
| { |
| wl_list_init(&queue->event_list); |
| queue->display = display; |
| } |
| |
| static void |
| decrease_closure_args_refcount(struct wl_closure *closure) |
| { |
| const char *signature; |
| struct argument_details arg; |
| int i, count; |
| struct wl_proxy *proxy; |
| |
| signature = closure->message->signature; |
| count = arg_count_for_signature(signature); |
| for (i = 0; i < count; i++) { |
| signature = get_next_argument(signature, &arg); |
| switch (arg.type) { |
| case 'n': |
| case 'o': |
| proxy = (struct wl_proxy *) closure->args[i].o; |
| if (proxy) { |
| if (proxy->flags & WL_PROXY_FLAG_DESTROYED) |
| closure->args[i].o = NULL; |
| |
| proxy->refcount--; |
| if (!proxy->refcount) |
| free(proxy); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| static void |
| wl_event_queue_release(struct wl_event_queue *queue) |
| { |
| struct wl_closure *closure; |
| struct wl_proxy *proxy; |
| bool proxy_destroyed; |
| |
| while (!wl_list_empty(&queue->event_list)) { |
| closure = container_of(queue->event_list.next, |
| struct wl_closure, link); |
| wl_list_remove(&closure->link); |
| |
| decrease_closure_args_refcount(closure); |
| |
| proxy = closure->proxy; |
| proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED); |
| |
| proxy->refcount--; |
| if (proxy_destroyed && !proxy->refcount) |
| free(proxy); |
| |
| wl_closure_destroy(closure); |
| } |
| } |
| |
| /** Destroy an event queue |
| * |
| * \param queue The event queue to be destroyed |
| * |
| * Destroy the given event queue. Any pending event on that queue is |
| * discarded. |
| * |
| * The \ref wl_display object used to create the queue should not be |
| * destroyed until all event queues created with it are destroyed with |
| * this function. |
| * |
| * \memberof wl_event_queue |
| */ |
| WL_EXPORT void |
| wl_event_queue_destroy(struct wl_event_queue *queue) |
| { |
| struct wl_display *display = queue->display; |
| |
| pthread_mutex_lock(&display->mutex); |
| wl_event_queue_release(queue); |
| free(queue); |
| pthread_mutex_unlock(&display->mutex); |
| } |
| |
| /** Create a new event queue for this display |
| * |
| * \param display The display context object |
| * \return A new event queue associated with this display or NULL on |
| * failure. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT struct wl_event_queue * |
| wl_display_create_queue(struct wl_display *display) |
| { |
| struct wl_event_queue *queue; |
| |
| queue = malloc(sizeof *queue); |
| if (queue == NULL) |
| return NULL; |
| |
| wl_event_queue_init(queue, display); |
| |
| return queue; |
| } |
| |
| static struct wl_proxy * |
| proxy_create(struct wl_proxy *factory, const struct wl_interface *interface, |
| uint32_t version) |
| { |
| struct wl_proxy *proxy; |
| struct wl_display *display = factory->display; |
| |
| proxy = zalloc(sizeof *proxy); |
| if (proxy == NULL) |
| return NULL; |
| |
| proxy->object.interface = interface; |
| proxy->display = display; |
| proxy->queue = factory->queue; |
| proxy->refcount = 1; |
| proxy->version = version; |
| |
| proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy); |
| |
| return proxy; |
| } |
| |
| /** Create a proxy object with a given interface |
| * |
| * \param factory Factory proxy object |
| * \param interface Interface the proxy object should use |
| * \return A newly allocated proxy object or NULL on failure |
| * |
| * This function creates a new proxy object with the supplied interface. The |
| * proxy object will have an id assigned from the client id space. The id |
| * should be created on the compositor side by sending an appropriate request |
| * with \ref wl_proxy_marshal(). |
| * |
| * The proxy will inherit the display and event queue of the factory object. |
| * |
| * \note This should not normally be used by non-generated code. |
| * |
| * \sa wl_display, wl_event_queue, wl_proxy_marshal() |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT struct wl_proxy * |
| wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface) |
| { |
| struct wl_display *display = factory->display; |
| struct wl_proxy *proxy; |
| |
| pthread_mutex_lock(&display->mutex); |
| proxy = proxy_create(factory, interface, factory->version); |
| pthread_mutex_unlock(&display->mutex); |
| |
| return proxy; |
| } |
| |
| /* The caller should hold the display lock */ |
| static struct wl_proxy * |
| wl_proxy_create_for_id(struct wl_proxy *factory, |
| uint32_t id, const struct wl_interface *interface) |
| { |
| struct wl_proxy *proxy; |
| struct wl_display *display = factory->display; |
| |
| proxy = zalloc(sizeof *proxy); |
| if (proxy == NULL) |
| return NULL; |
| |
| proxy->object.interface = interface; |
| proxy->object.id = id; |
| proxy->display = display; |
| proxy->queue = factory->queue; |
| proxy->refcount = 1; |
| proxy->version = factory->version; |
| |
| wl_map_insert_at(&display->objects, 0, id, proxy); |
| |
| return proxy; |
| } |
| |
| static void |
| proxy_destroy(struct wl_proxy *proxy) |
| { |
| if (proxy->flags & WL_PROXY_FLAG_ID_DELETED) |
| wl_map_remove(&proxy->display->objects, proxy->object.id); |
| else if (proxy->object.id < WL_SERVER_ID_START) |
| wl_map_insert_at(&proxy->display->objects, 0, |
| proxy->object.id, WL_ZOMBIE_OBJECT); |
| else |
| wl_map_insert_at(&proxy->display->objects, 0, |
| proxy->object.id, NULL); |
| |
| |
| proxy->flags |= WL_PROXY_FLAG_DESTROYED; |
| |
| proxy->refcount--; |
| if (!proxy->refcount) |
| free(proxy); |
| } |
| |
| /** Destroy a proxy object |
| * |
| * \param proxy The proxy to be destroyed |
| * |
| * \c proxy must not be a proxy wrapper. |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT void |
| wl_proxy_destroy(struct wl_proxy *proxy) |
| { |
| struct wl_display *display = proxy->display; |
| |
| if (proxy->flags & WL_PROXY_FLAG_WRAPPER) |
| wl_abort("Tried to destroy wrapper with wl_proxy_destroy()\n"); |
| |
| pthread_mutex_lock(&display->mutex); |
| proxy_destroy(proxy); |
| pthread_mutex_unlock(&display->mutex); |
| } |
| |
| /** Set a proxy's listener |
| * |
| * \param proxy The proxy object |
| * \param implementation The listener to be added to proxy |
| * \param data User data to be associated with the proxy |
| * \return 0 on success or -1 on failure |
| * |
| * Set proxy's listener to \c implementation and its user data to |
| * \c data. If a listener has already been set, this function |
| * fails and nothing is changed. |
| * |
| * \c implementation is a vector of function pointers. For an opcode |
| * \c n, \c implementation[n] should point to the handler of \c n for |
| * the given object. |
| * |
| * \c proxy must not be a proxy wrapper. |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT int |
| wl_proxy_add_listener(struct wl_proxy *proxy, |
| void (**implementation)(void), void *data) |
| { |
| if (proxy->flags & WL_PROXY_FLAG_WRAPPER) |
| wl_abort("Proxy %p is a wrapper\n", proxy); |
| |
| if (proxy->object.implementation || proxy->dispatcher) { |
| wl_log("proxy %p already has listener\n", proxy); |
| return -1; |
| } |
| |
| proxy->object.implementation = implementation; |
| proxy->user_data = data; |
| |
| return 0; |
| } |
| |
| /** Get a proxy's listener |
| * |
| * \param proxy The proxy object |
| * \return The address of the proxy's listener or NULL if no listener is set |
| * |
| * Gets the address to the proxy's listener; which is the listener set with |
| * \ref wl_proxy_add_listener. |
| * |
| * This function is useful in clients with multiple listeners on the same |
| * interface to allow the identification of which code to execute. |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT const void * |
| 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. |
| * |
| * \c proxy must not be a proxy wrapper. |
| * |
| * \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->flags & WL_PROXY_FLAG_WRAPPER) |
| wl_abort("Proxy %p is a wrapper\n", proxy); |
| |
| if (proxy->object.implementation || proxy->dispatcher) { |
| wl_log("proxy %p already has listener\n", proxy); |
| return -1; |
| } |
| |
| proxy->object.implementation = implementation; |
| proxy->dispatcher = dispatcher; |
| proxy->user_data = data; |
| |
| return 0; |
| } |
| |
| static struct wl_proxy * |
| create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message, |
| union wl_argument *args, |
| const struct wl_interface *interface, uint32_t version) |
| { |
| int i, count; |
| const char *signature; |
| struct argument_details arg; |
| struct wl_proxy *new_proxy = NULL; |
| |
| signature = message->signature; |
| count = arg_count_for_signature(signature); |
| for (i = 0; i < count; i++) { |
| signature = get_next_argument(signature, &arg); |
| |
| switch (arg.type) { |
| case 'n': |
| new_proxy = proxy_create(proxy, interface, version); |
| if (new_proxy == NULL) |
| return NULL; |
| |
| args[i].o = &new_proxy->object; |
| break; |
| } |
| } |
| |
| return new_proxy; |
| } |
| |
| /** 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 |
| * \param interface The interface to use for the new proxy |
| * |
| * This function translates a request given an opcode, an interface and a |
| * wl_argument array to the wire format and writes it to the connection |
| * buffer. |
| * |
| * For new-id arguments, this function will allocate a new wl_proxy |
| * and send the ID to the server. The new wl_proxy will be returned |
| * on success or NULL on error with errno set accordingly. The newly |
| * created proxy will inherit their version from their parent. |
| * |
| * \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 struct wl_proxy * |
| wl_proxy_marshal_array_constructor(struct wl_proxy *proxy, |
| uint32_t opcode, union wl_argument *args, |
| const struct wl_interface *interface) |
| { |
| return wl_proxy_marshal_array_constructor_versioned(proxy, opcode, |
| args, interface, |
| proxy->version); |
| } |
| |
| |
| /** 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 |
| * \param interface The interface to use for the new proxy |
| * \param version The protocol object version for the new proxy |
| * |
| * 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. |
| * |
| * For new-id arguments, this function will allocate a new wl_proxy |
| * and send the ID to the server. The new wl_proxy will be returned |
| * on success or NULL on error with errno set accordingly. The newly |
| * created proxy will have the version specified. |
| * |
| * \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 struct wl_proxy * |
| wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy, |
| uint32_t opcode, |
| union wl_argument *args, |
| const struct wl_interface *interface, |
| uint32_t version) |
| { |
| struct wl_closure *closure; |
| struct wl_proxy *new_proxy = NULL; |
| const struct wl_message *message; |
| |
| pthread_mutex_lock(&proxy->display->mutex); |
| |
| message = &proxy->object.interface->methods[opcode]; |
| if (interface) { |
| new_proxy = create_outgoing_proxy(proxy, message, |
| args, interface, |
| version); |
| if (new_proxy == NULL) |
| goto err_unlock; |
| } |
| |
| closure = wl_closure_marshal(&proxy->object, opcode, args, message); |
| if (closure == NULL) |
| wl_abort("Error marshalling request: %s\n", strerror(errno)); |
| |
| if (debug_client) |
| wl_closure_print(closure, &proxy->object, true); |
| |
| if (wl_closure_send(closure, proxy->display->connection)) |
| wl_abort("Error sending request: %s\n", strerror(errno)); |
| |
| wl_closure_destroy(closure); |
| |
| err_unlock: |
| pthread_mutex_unlock(&proxy->display->mutex); |
| |
| return new_proxy; |
| } |
| |
| |
| /** Prepare a request to be sent to the compositor |
| * |
| * \param proxy The proxy object |
| * \param opcode Opcode of the request to be sent |
| * \param ... Extra arguments for the given request |
| * |
| * This function is similar to wl_proxy_marshal_constructor(), except |
| * it doesn't create proxies for new-id arguments. |
| * |
| * \note This should not normally be used by non-generated code. |
| * |
| * \sa wl_proxy_create() |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT void |
| wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) |
| { |
| 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_constructor(proxy, opcode, args, NULL); |
| } |
| |
| /** Prepare a request to be sent to the compositor |
| * |
| * \param proxy The proxy object |
| * \param opcode Opcode of the request to be sent |
| * \param interface The interface to use for the new proxy |
| * \param ... Extra arguments for the given request |
| * \return A new wl_proxy for the new_id argument or NULL on error |
| * |
| * This function translates a request given an opcode, an interface and extra |
| * arguments to the wire format and writes it to the connection buffer. The |
| * types of the extra arguments must correspond to the argument types of the |
| * method associated with the opcode in the interface. |
| * |
| * For new-id arguments, this function will allocate a new wl_proxy |
| * and send the ID to the server. The new wl_proxy will be returned |
| * on success or NULL on error with errno set accordingly. The newly |
| * created proxy will inherit their version from their parent. |
| * |
| * \note This should not normally be used by non-generated code. |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT struct wl_proxy * |
| wl_proxy_marshal_constructor(struct wl_proxy *proxy, uint32_t opcode, |
| const struct wl_interface *interface, ...) |
| { |
| union wl_argument args[WL_CLOSURE_MAX_ARGS]; |
| va_list ap; |
| |
| va_start(ap, interface); |
| wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature, |
| args, WL_CLOSURE_MAX_ARGS, ap); |
| va_end(ap); |
| |
| return wl_proxy_marshal_array_constructor(proxy, opcode, |
| args, interface); |
| } |
| |
| |
| /** Prepare a request to be sent to the compositor |
| * |
| * \param proxy The proxy object |
| * \param opcode Opcode of the request to be sent |
| * \param interface The interface to use for the new proxy |
| * \param version The protocol object version of the new proxy |
| * \param ... Extra arguments for the given request |
| * \return A new wl_proxy for the new_id argument or NULL on error |
| * |
| * Translates the request given by opcode and the extra arguments into the |
| * wire format and write it to the connection buffer. |
| * |
| * For new-id arguments, this function will allocate a new wl_proxy |
| * and send the ID to the server. The new wl_proxy will be returned |
| * on success or NULL on error with errno set accordingly. The newly |
| * created proxy will have the version specified. |
| * |
| * \note This should not normally be used by non-generated code. |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT struct wl_proxy * |
| wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, uint32_t opcode, |
| const struct wl_interface *interface, |
| uint32_t version, ...) |
| { |
| union wl_argument args[WL_CLOSURE_MAX_ARGS]; |
| va_list ap; |
| |
| va_start(ap, version); |
| wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature, |
| args, WL_CLOSURE_MAX_ARGS, ap); |
| va_end(ap); |
| |
| return wl_proxy_marshal_array_constructor_versioned(proxy, opcode, |
| args, interface, |
| version); |
| } |
| |
| /** 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 |
| * |
| * This function is similar to wl_proxy_marshal_array_constructor(), except |
| * it doesn't create proxies for new-id arguments. |
| * |
| * \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) |
| { |
| wl_proxy_marshal_array_constructor(proxy, opcode, args, NULL); |
| } |
| |
| static void |
| display_handle_error(void *data, |
| struct wl_display *display, void *object, |
| uint32_t code, const char *message) |
| { |
| struct wl_proxy *proxy = object; |
| uint32_t object_id; |
| const struct wl_interface *interface; |
| |
| if (proxy) { |
| wl_log("%s@%u: error %d: %s\n", |
| proxy->object.interface->name, |
| proxy->object.id, |
| code, message); |
| |
| object_id = proxy->object.id; |
| interface = proxy->object.interface; |
| } else { |
| wl_log("[destroyed object]: error %d: %s\n", |
| code, message); |
| |
| object_id = 0; |
| interface = NULL; |
| } |
| |
| display_protocol_error(display, code, object_id, interface); |
| } |
| |
| static void |
| display_handle_delete_id(void *data, struct wl_display *display, uint32_t id) |
| { |
| struct wl_proxy *proxy; |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| proxy = wl_map_lookup(&display->objects, id); |
| |
| if (!proxy) |
| wl_log("error: received delete_id for unknown id (%u)\n", id); |
| |
| if (proxy && proxy != WL_ZOMBIE_OBJECT) |
| proxy->flags |= WL_PROXY_FLAG_ID_DELETED; |
| else |
| wl_map_remove(&display->objects, id); |
| |
| pthread_mutex_unlock(&display->mutex); |
| } |
| |
| static const struct wl_display_listener display_listener = { |
| display_handle_error, |
| display_handle_delete_id |
| }; |
| |
| static int |
| connect_to_socket(const char *name) |
| { |
| struct sockaddr_un addr; |
| socklen_t size; |
| const char *runtime_dir; |
| int name_size, fd; |
| |
| runtime_dir = getenv("XDG_RUNTIME_DIR"); |
| if (!runtime_dir) { |
| wl_log("error: XDG_RUNTIME_DIR not set in the environment.\n"); |
| /* to prevent programs reporting |
| * "failed to create display: Success" */ |
| errno = ENOENT; |
| return -1; |
| } |
| |
| if (name == NULL) |
| name = getenv("WAYLAND_DISPLAY"); |
| if (name == NULL) |
| name = "wayland-0"; |
| |
| fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0); |
| if (fd < 0) |
| return -1; |
| |
| memset(&addr, 0, sizeof addr); |
| addr.sun_family = AF_LOCAL; |
| name_size = |
| snprintf(addr.sun_path, sizeof addr.sun_path, |
| "%s/%s", runtime_dir, name) + 1; |
| |
| assert(name_size > 0); |
| if (name_size > (int)sizeof addr.sun_path) { |
| wl_log("error: socket path \"%s/%s\" plus null terminator" |
| " exceeds 108 bytes\n", runtime_dir, name); |
| close(fd); |
| /* to prevent programs reporting |
| * "failed to add socket: Success" */ |
| errno = ENAMETOOLONG; |
| return -1; |
| }; |
| |
| size = offsetof (struct sockaddr_un, sun_path) + name_size; |
| |
| if (connect(fd, (struct sockaddr *) &addr, size) < 0) { |
| close(fd); |
| return -1; |
| } |
| |
| return fd; |
| } |
| |
| /** Connect to Wayland display on an already open fd |
| * |
| * \param fd The fd to use for the connection |
| * \return A \ref wl_display object or \c NULL on failure |
| * |
| * The wl_display takes ownership of the fd and will close it when the |
| * display is destroyed. The fd will also be closed in case of |
| * failure. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT struct wl_display * |
| wl_display_connect_to_fd(int fd) |
| { |
| struct wl_display *display; |
| const char *debug; |
| |
| debug = getenv("WAYLAND_DEBUG"); |
| if (debug && (strstr(debug, "client") || strstr(debug, "1"))) |
| debug_client = 1; |
| |
| display = zalloc(sizeof *display); |
| if (display == NULL) { |
| close(fd); |
| return NULL; |
| } |
| |
| display->fd = fd; |
| wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE); |
| wl_event_queue_init(&display->default_queue, display); |
| wl_event_queue_init(&display->display_queue, display); |
| pthread_mutex_init(&display->mutex, NULL); |
| pthread_cond_init(&display->reader_cond, NULL); |
| display->reader_count = 0; |
| |
| wl_map_insert_new(&display->objects, 0, NULL); |
| |
| display->proxy.object.interface = &wl_display_interface; |
| display->proxy.object.id = |
| wl_map_insert_new(&display->objects, 0, display); |
| display->proxy.display = display; |
| display->proxy.object.implementation = (void(**)(void)) &display_listener; |
| display->proxy.user_data = display; |
| display->proxy.queue = &display->default_queue; |
| display->proxy.flags = 0; |
| display->proxy.refcount = 1; |
| |
| /* We set this version to 0 for backwards compatibility. |
| * |
| * If a client is using old versions of protocol headers, |
| * it will use unversioned API to create proxies. Those |
| * proxies will inherit this 0. |
| * |
| * A client could be passing these proxies into library |
| * code newer than the headers that checks proxy |
| * versions. When the proxy version is reported as 0 |
| * the library will know that it can't reliably determine |
| * the proxy version, and should do whatever fallback is |
| * required. |
| * |
| * This trick forces wl_display to always report 0, but |
| * since it's a special object that we can't bind |
| * specific versions of anyway, this should be fine. |
| */ |
| display->proxy.version = 0; |
| |
| display->connection = wl_connection_create(display->fd); |
| if (display->connection == NULL) |
| goto err_connection; |
| |
| return display; |
| |
| err_connection: |
| pthread_mutex_destroy(&display->mutex); |
| pthread_cond_destroy(&display->reader_cond); |
| wl_map_release(&display->objects); |
| close(display->fd); |
| free(display); |
| |
| return NULL; |
| } |
| |
| /** Connect to a Wayland display |
| * |
| * \param name Name of the Wayland display to connect to |
| * \return A \ref wl_display object or \c NULL on failure |
| * |
| * Connect to the Wayland display named \c name. If \c name is \c NULL, |
| * its value will be replaced with the WAYLAND_DISPLAY environment |
| * variable if it is set, otherwise display "wayland-0" will be used. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT struct wl_display * |
| wl_display_connect(const char *name) |
| { |
| char *connection, *end; |
| int flags, fd; |
| |
| connection = getenv("WAYLAND_SOCKET"); |
| if (connection) { |
| int prev_errno = errno; |
| errno = 0; |
| fd = strtol(connection, &end, 10); |
| if (errno != 0 || connection == end || *end != '\0') |
| return NULL; |
| errno = prev_errno; |
| |
| flags = fcntl(fd, F_GETFD); |
| if (flags != -1) |
| fcntl(fd, F_SETFD, flags | FD_CLOEXEC); |
| unsetenv("WAYLAND_SOCKET"); |
| } else { |
| fd = connect_to_socket(name); |
| if (fd < 0) |
| return NULL; |
| } |
| |
| return wl_display_connect_to_fd(fd); |
| } |
| |
| /** Close a connection to a Wayland display |
| * |
| * \param display The display context object |
| * |
| * Close the connection to \c display and free all resources associated |
| * with it. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT void |
| wl_display_disconnect(struct wl_display *display) |
| { |
| wl_connection_destroy(display->connection); |
| wl_map_release(&display->objects); |
| wl_event_queue_release(&display->default_queue); |
| wl_event_queue_release(&display->display_queue); |
| pthread_mutex_destroy(&display->mutex); |
| pthread_cond_destroy(&display->reader_cond); |
| close(display->fd); |
| |
| free(display); |
| } |
| |
| /** Get a display context's file descriptor |
| * |
| * \param display The display context object |
| * \return Display object file descriptor |
| * |
| * Return the file descriptor associated with a display so it can be |
| * integrated into the client's main loop. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_get_fd(struct wl_display *display) |
| { |
| return display->fd; |
| } |
| |
| static void |
| sync_callback(void *data, struct wl_callback *callback, uint32_t serial) |
| { |
| int *done = data; |
| |
| *done = 1; |
| wl_callback_destroy(callback); |
| } |
| |
| static const struct wl_callback_listener sync_listener = { |
| sync_callback |
| }; |
| |
| /** Block until all pending request are processed by the server |
| * |
| * \param display The display context object |
| * \param queue The queue on which to run the roundtrip |
| * \return The number of dispatched events on success or -1 on failure |
| * |
| * This function blocks until the server has processed all currently issued |
| * requests by sending a request to the display server and waiting for a |
| * reply before returning. |
| * |
| * This function uses wl_display_dispatch_queue() internally. It is not allowed |
| * to call this function while the thread is being prepared for reading events, |
| * and doing so will cause a dead lock. |
| * |
| * \note This function may dispatch other events being received on the given |
| * queue. |
| * |
| * \sa wl_display_roundtrip() |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *queue) |
| { |
| struct wl_display *display_wrapper; |
| struct wl_callback *callback; |
| int done, ret = 0; |
| |
| done = 0; |
| |
| display_wrapper = wl_proxy_create_wrapper(display); |
| if (!display_wrapper) |
| return -1; |
| |
| wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue); |
| callback = wl_display_sync(display_wrapper); |
| wl_proxy_wrapper_destroy(display_wrapper); |
| |
| if (callback == NULL) |
| return -1; |
| |
| wl_callback_add_listener(callback, &sync_listener, &done); |
| while (!done && ret >= 0) |
| ret = wl_display_dispatch_queue(display, queue); |
| |
| if (ret == -1 && !done) |
| wl_callback_destroy(callback); |
| |
| return ret; |
| } |
| |
| /** Block until all pending request are processed by the server |
| * |
| * \param display The display context object |
| * \return The number of dispatched events on success or -1 on failure |
| * |
| * This function blocks until the server has processed all currently issued |
| * requests by sending a request to the display server and waiting for a reply |
| * before returning. |
| * |
| * This function uses wl_display_dispatch_queue() internally. It is not allowed |
| * to call this function while the thread is being prepared for reading events, |
| * and doing so will cause a dead lock. |
| * |
| * \note This function may dispatch other events being received on the default |
| * queue. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_roundtrip(struct wl_display *display) |
| { |
| return wl_display_roundtrip_queue(display, &display->default_queue); |
| } |
| |
| static int |
| create_proxies(struct wl_proxy *sender, struct wl_closure *closure) |
| { |
| struct wl_proxy *proxy; |
| const char *signature; |
| struct argument_details arg; |
| uint32_t id; |
| int i; |
| int count; |
| |
| signature = closure->message->signature; |
| count = arg_count_for_signature(signature); |
| for (i = 0; i < count; i++) { |
| signature = get_next_argument(signature, &arg); |
| switch (arg.type) { |
| case 'n': |
| id = closure->args[i].n; |
| if (id == 0) { |
| closure->args[i].o = NULL; |
| break; |
| } |
| proxy = wl_proxy_create_for_id(sender, id, |
| closure->message->types[i]); |
| if (proxy == NULL) |
| return -1; |
| closure->args[i].o = (struct wl_object *)proxy; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static void |
| increase_closure_args_refcount(struct wl_closure *closure) |
| { |
| const char *signature; |
| struct argument_details arg; |
| int i, count; |
| struct wl_proxy *proxy; |
| |
| signature = closure->message->signature; |
| count = arg_count_for_signature(signature); |
| for (i = 0; i < count; i++) { |
| signature = get_next_argument(signature, &arg); |
| switch (arg.type) { |
| case 'n': |
| case 'o': |
| proxy = (struct wl_proxy *) closure->args[i].o; |
| if (proxy) |
| proxy->refcount++; |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| static int |
| queue_event(struct wl_display *display, int len) |
| { |
| uint32_t p[2], id; |
| int opcode, size; |
| struct wl_proxy *proxy; |
| struct wl_closure *closure; |
| const struct wl_message *message; |
| struct wl_event_queue *queue; |
| |
| wl_connection_copy(display->connection, p, sizeof p); |
| id = p[0]; |
| opcode = p[1] & 0xffff; |
| size = p[1] >> 16; |
| if (len < size) |
| return 0; |
| |
| proxy = wl_map_lookup(&display->objects, id); |
| if (proxy == WL_ZOMBIE_OBJECT) { |
| wl_connection_consume(display->connection, size); |
| return size; |
| } else if (proxy == NULL) { |
| wl_connection_consume(display->connection, size); |
| return size; |
| } |
| |
| message = &proxy->object.interface->events[opcode]; |
| closure = wl_connection_demarshal(display->connection, size, |
| &display->objects, message); |
| if (!closure) |
| return -1; |
| |
| if (create_proxies(proxy, closure) < 0) { |
| wl_closure_destroy(closure); |
| return -1; |
| } |
| |
| if (wl_closure_lookup_objects(closure, &display->objects) != 0) { |
| wl_closure_destroy(closure); |
| return -1; |
| } |
| |
| increase_closure_args_refcount(closure); |
| proxy->refcount++; |
| closure->proxy = proxy; |
| |
| if (proxy == &display->proxy) |
| queue = &display->display_queue; |
| else |
| queue = proxy->queue; |
| |
| wl_list_insert(queue->event_list.prev, &closure->link); |
| |
| return size; |
| } |
| |
| static void |
| dispatch_event(struct wl_display *display, struct wl_event_queue *queue) |
| { |
| struct wl_closure *closure; |
| struct wl_proxy *proxy; |
| int opcode; |
| bool proxy_destroyed; |
| |
| closure = container_of(queue->event_list.next, |
| struct wl_closure, link); |
| wl_list_remove(&closure->link); |
| opcode = closure->opcode; |
| |
| /* Verify that the receiving object is still valid by checking if has |
| * been destroyed by the application. */ |
| |
| decrease_closure_args_refcount(closure); |
| proxy = closure->proxy; |
| proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED); |
| |
| proxy->refcount--; |
| if (proxy_destroyed) { |
| if (!proxy->refcount) |
| free(proxy); |
| |
| wl_closure_destroy(closure); |
| return; |
| } |
| |
| pthread_mutex_unlock(&display->mutex); |
| |
| if (proxy->dispatcher) { |
| if (debug_client) |
| wl_closure_print(closure, &proxy->object, false); |
| |
| wl_closure_dispatch(closure, proxy->dispatcher, |
| &proxy->object, opcode); |
| } else if (proxy->object.implementation) { |
| if (debug_client) |
| wl_closure_print(closure, &proxy->object, false); |
| |
| wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT, |
| &proxy->object, opcode, proxy->user_data); |
| } |
| |
| wl_closure_destroy(closure); |
| |
| pthread_mutex_lock(&display->mutex); |
| } |
| |
| static int |
| read_events(struct wl_display *display) |
| { |
| int total, rem, size; |
| uint32_t serial; |
| |
| display->reader_count--; |
| if (display->reader_count == 0) { |
| total = wl_connection_read(display->connection); |
| if (total == -1) { |
| if (errno == EAGAIN) { |
| /* we must wake up threads whenever |
| * the reader_count dropped to 0 */ |
| display_wakeup_threads(display); |
| |
| return 0; |
| } |
| |
| display_fatal_error(display, errno); |
| return -1; |
| } else if (total == 0) { |
| /* The compositor has closed the socket. This |
| * should be considered an error so we'll fake |
| * an errno */ |
| errno = EPIPE; |
| display_fatal_error(display, errno); |
| return -1; |
| } |
| |
| for (rem = total; rem >= 8; rem -= size) { |
| size = queue_event(display, rem); |
| if (size == -1) { |
| display_fatal_error(display, errno); |
| return -1; |
| } else if (size == 0) { |
| break; |
| } |
| } |
| |
| display_wakeup_threads(display); |
| } else { |
| serial = display->read_serial; |
| while (display->read_serial == serial) |
| pthread_cond_wait(&display->reader_cond, |
| &display->mutex); |
| |
| if (display->last_error) { |
| errno = display->last_error; |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static void |
| cancel_read(struct wl_display *display) |
| { |
| display->reader_count--; |
| if (display->reader_count == 0) |
| display_wakeup_threads(display); |
| } |
| |
| /** Read events from display file descriptor |
| * |
| * \param display The display context object |
| * \return 0 on success or -1 on error. In case of error errno will |
| * be set accordingly |
| * |
| * Calling this function will result in data available on the display file |
| * descriptor being read and read events will be queued on their corresponding |
| * event queues. |
| * |
| * Before calling this function, depending on what thread it is to be called |
| * from, wl_display_prepare_read_queue() or wl_display_prepare_read() needs to |
| * be called. See wl_display_prepare_read_queue() for more details. |
| * |
| * When being called at a point where other threads have been prepared to read |
| * (using wl_display_prepare_read_queue() or wl_display_prepare_read()) this |
| * function will sleep until all other prepared threads have either been |
| * cancelled (using wl_display_cancel_read()) or them self entered this |
| * function. The last thread that calls this function will then read and queue |
| * events on their corresponding event queues, and finally wake up all other |
| * wl_display_read_events() calls causing them to return. |
| * |
| * If a thread cancels a read preparation when all other threads that have |
| * prepared to read has either called wl_display_cancel_read() or |
| * wl_display_read_events(), all reader threads will return without having read |
| * any data. |
| * |
| * To dispatch events that may have been queued, call |
| * wl_display_dispatch_pending() or wl_display_dispatch_queue_pending(). |
| * |
| * \sa wl_display_prepare_read(), wl_display_cancel_read(), |
| * wl_display_dispatch_pending(), wl_display_dispatch() |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_read_events(struct wl_display *display) |
| { |
| int ret; |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| if (display->last_error) { |
| cancel_read(display); |
| pthread_mutex_unlock(&display->mutex); |
| |
| errno = display->last_error; |
| return -1; |
| } |
| |
| ret = read_events(display); |
| |
| pthread_mutex_unlock(&display->mutex); |
| |
| return ret; |
| } |
| |
| static int |
| dispatch_queue(struct wl_display *display, struct wl_event_queue *queue) |
| { |
| int count; |
| |
| if (display->last_error) |
| goto err; |
| |
| count = 0; |
| while (!wl_list_empty(&display->display_queue.event_list)) { |
| dispatch_event(display, &display->display_queue); |
| if (display->last_error) |
| goto err; |
| count++; |
| } |
| |
| while (!wl_list_empty(&queue->event_list)) { |
| dispatch_event(display, queue); |
| if (display->last_error) |
| goto err; |
| count++; |
| } |
| |
| return count; |
| |
| err: |
| errno = display->last_error; |
| |
| return -1; |
| } |
| |
| /** Prepare to read events from the display's file descriptor to a queue |
| * |
| * \param display The display context object |
| * \param queue The event queue to use |
| * \return 0 on success or -1 if event queue was not empty |
| * |
| * This function (or wl_display_prepare_read()) must be called before reading |
| * from the file descriptor using wl_display_read_events(). Calling |
| * wl_display_prepare_read_queue() announces the calling thread's intention to |
| * read and ensures that until the thread is ready to read and calls |
| * wl_display_read_events(), no other thread will read from the file descriptor. |
| * This only succeeds if the event queue is empty, and if not -1 is returned and |
| * errno set to EAGAIN. |
| * |
| * If a thread successfully calls wl_display_prepare_read_queue(), it must |
| * either call wl_display_read_events() when it's ready or cancel the read |
| * intention by calling wl_display_cancel_read(). |
| * |
| * Use this function before polling on the display fd or integrate the fd into a |
| * toolkit event loop in a race-free way. A correct usage would be (with most |
| * error checking left out): |
| * |
| * \code |
| * while (wl_display_prepare_read_queue(display, queue) != 0) |
| * wl_display_dispatch_queue_pending(display, queue); |
| * wl_display_flush(display); |
| * |
| * ret = poll(fds, nfds, -1); |
| * if (has_error(ret)) |
| * wl_display_cancel_read(display); |
| * else |
| * wl_display_read_events(display); |
| * |
| * wl_display_dispatch_queue_pending(display, queue); |
| * \endcode |
| * |
| * Here we call wl_display_prepare_read_queue(), which ensures that between |
| * returning from that call and eventually calling wl_display_read_events(), no |
| * other thread will read from the fd and queue events in our queue. If the call |
| * to wl_display_prepare_read_queue() fails, we dispatch the pending events and |
| * try again until we're successful. |
| * |
| * The wl_display_prepare_read_queue() function doesn't acquire exclusive access |
| * to the display's fd. It only registers that the thread calling this function |
| * has intention to read from fd. When all registered readers call |
| * wl_display_read_events(), only one (at random) eventually reads and queues |
| * the events and the others are sleeping meanwhile. This way we avoid races and |
| * still can read from more threads. |
| * |
| * \sa wl_display_cancel_read(), wl_display_read_events(), |
| * wl_display_prepare_read() |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_prepare_read_queue(struct wl_display *display, |
| struct wl_event_queue *queue) |
| { |
| int ret; |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| if (!wl_list_empty(&queue->event_list)) { |
| errno = EAGAIN; |
| ret = -1; |
| } else { |
| display->reader_count++; |
| ret = 0; |
| } |
| |
| pthread_mutex_unlock(&display->mutex); |
| |
| return ret; |
| } |
| |
| /** Prepare to read events from the display's file descriptor |
| * |
| * \param display The display context object |
| * \return 0 on success or -1 if event queue was not empty |
| * |
| * This function does the same thing as wl_display_prepare_read_queue() |
| * with the default queue passed as the queue. |
| * |
| * \sa wl_display_prepare_read_queue |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_prepare_read(struct wl_display *display) |
| { |
| return wl_display_prepare_read_queue(display, &display->default_queue); |
| } |
| |
| /** Cancel read intention on display's fd |
| * |
| * \param display The display context object |
| * |
| * After a thread successfully called wl_display_prepare_read() it must |
| * either call wl_display_read_events() or wl_display_cancel_read(). |
| * If the threads do not follow this rule it will lead to deadlock. |
| * |
| * \sa wl_display_prepare_read(), wl_display_read_events() |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT void |
| wl_display_cancel_read(struct wl_display *display) |
| { |
| pthread_mutex_lock(&display->mutex); |
| |
| cancel_read(display); |
| |
| pthread_mutex_unlock(&display->mutex); |
| } |
| |
| static int |
| wl_display_poll(struct wl_display *display, short int events) |
| { |
| int ret; |
| struct pollfd pfd[1]; |
| |
| pfd[0].fd = display->fd; |
| pfd[0].events = events; |
| do { |
| ret = poll(pfd, 1, -1); |
| } while (ret == -1 && errno == EINTR); |
| |
| return ret; |
| } |
| |
| /** Dispatch events in an event queue |
| * |
| * \param display The display context object |
| * \param queue The event queue to dispatch |
| * \return The number of dispatched events on success or -1 on failure |
| * |
| * Dispatch events on the given event queue. |
| * |
| * If the given event queue is empty, this function blocks until there are |
| * events to be read from the display fd. Events are read and queued on |
| * the appropriate event queues. Finally, events on given event queue are |
| * dispatched. On failure -1 is returned and errno set appropriately. |
| * |
| * In a multi threaded environment, do not manually wait using poll() (or |
| * equivalent) before calling this function, as doing so might cause a dead |
| * lock. If external reliance on poll() (or equivalent) is required, see |
| * wl_display_prepare_read_queue() of how to do so. |
| * |
| * This function is thread safe as long as it dispatches the right queue on the |
| * right thread. It is also compatible with the multi thread event reading |
| * preparation API (see wl_display_prepare_read_queue()), and uses the |
| * equivalent functionality internally. It is not allowed to call this function |
| * while the thread is being prepared for reading events, and doing so will |
| * cause a dead lock. |
| * |
| * It can be used as a helper function to ease the procedure of reading and |
| * dispatching events. |
| * |
| * \note Since Wayland 1.5 the display has an extra queue |
| * for its own events (i. e. delete_id). This queue is dispatched always, |
| * no matter what queue we passed as an argument to this function. |
| * That means that this function can return non-0 value even when it |
| * haven't dispatched any event for the given queue. |
| * |
| * \sa wl_display_dispatch(), wl_display_dispatch_pending(), |
| * wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue() |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_dispatch_queue(struct wl_display *display, |
| struct wl_event_queue *queue) |
| { |
| int ret; |
| |
| if (wl_display_prepare_read_queue(display, queue) == -1) |
| return wl_display_dispatch_queue_pending(display, queue); |
| |
| while (true) { |
| ret = wl_display_flush(display); |
| |
| if (ret != -1 || errno != EAGAIN) |
| break; |
| |
| if (wl_display_poll(display, POLLOUT) == -1) { |
| wl_display_cancel_read(display); |
| return -1; |
| } |
| } |
| |
| /* Don't stop if flushing hits an EPIPE; continue so we can read any |
| * protocol error that may have triggered it. */ |
| if (ret < 0 && errno != EPIPE) { |
| wl_display_cancel_read(display); |
| return -1; |
| } |
| |
| if (wl_display_poll(display, POLLIN) == -1) { |
| wl_display_cancel_read(display); |
| return -1; |
| } |
| |
| if (wl_display_read_events(display) == -1) |
| return -1; |
| |
| return wl_display_dispatch_queue_pending(display, queue); |
| } |
| |
| /** Dispatch pending events in an event queue |
| * |
| * \param display The display context object |
| * \param queue The event queue to dispatch |
| * \return The number of dispatched events on success or -1 on failure |
| * |
| * Dispatch all incoming events for objects assigned to the given |
| * event queue. On failure -1 is returned and errno set appropriately. |
| * If there are no events queued, this function returns immediately. |
| * |
| * \memberof wl_display |
| * \since 1.0.2 |
| */ |
| WL_EXPORT int |
| wl_display_dispatch_queue_pending(struct wl_display *display, |
| struct wl_event_queue *queue) |
| { |
| int ret; |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| ret = dispatch_queue(display, queue); |
| |
| pthread_mutex_unlock(&display->mutex); |
| |
| return ret; |
| } |
| |
| /** Process incoming events |
| * |
| * \param display The display context object |
| * \return The number of dispatched events on success or -1 on failure |
| * |
| * Dispatch events on the default event queue. |
| * |
| * If the default event queue is empty, this function blocks until there are |
| * events to be read from the display fd. Events are read and queued on |
| * the appropriate event queues. Finally, events on the default event queue |
| * are dispatched. On failure -1 is returned and errno set appropriately. |
| * |
| * In a multi threaded environment, do not manually wait using poll() (or |
| * equivalent) before calling this function, as doing so might cause a dead |
| * lock. If external reliance on poll() (or equivalent) is required, see |
| * wl_display_prepare_read_queue() of how to do so. |
| * |
| * This function is thread safe as long as it dispatches the right queue on the |
| * right thread. It is also compatible with the multi thread event reading |
| * preparation API (see wl_display_prepare_read_queue()), and uses the |
| * equivalent functionality internally. It is not allowed to call this function |
| * while the thread is being prepared for reading events, and doing so will |
| * cause a dead lock. |
| * |
| * \note It is not possible to check if there are events on the queue |
| * or not. For dispatching default queue events without blocking, see \ref |
| * wl_display_dispatch_pending(). |
| * |
| * \sa wl_display_dispatch_pending(), wl_display_dispatch_queue(), |
| * wl_display_read_events() |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_dispatch(struct wl_display *display) |
| { |
| return wl_display_dispatch_queue(display, &display->default_queue); |
| } |
| |
| /** Dispatch default queue events without reading from the display fd |
| * |
| * \param display The display context object |
| * \return The number of dispatched events or -1 on failure |
| * |
| * This function dispatches events on the main event queue. It does not |
| * attempt to read the display fd and simply returns zero if the main |
| * queue is empty, i.e., it doesn't block. |
| * |
| * \sa wl_display_dispatch(), wl_display_dispatch_queue(), |
| * wl_display_flush() |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_dispatch_pending(struct wl_display *display) |
| { |
| return wl_display_dispatch_queue_pending(display, |
| &display->default_queue); |
| } |
| |
| /** Retrieve the last error that occurred on a display |
| * |
| * \param display The display context object |
| * \return The last error that occurred on \c display or 0 if no error occurred |
| * |
| * Return the last error that occurred on the display. This may be an error sent |
| * by the server or caused by the local client. |
| * |
| * \note Errors are \b fatal. If this function returns non-zero the display |
| * can no longer be used. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_get_error(struct wl_display *display) |
| { |
| int ret; |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| ret = display->last_error; |
| |
| pthread_mutex_unlock(&display->mutex); |
| |
| return ret; |
| } |
| |
| /** Retrieves the information about a protocol error: |
| * |
| * \param display The Wayland display |
| * \param interface if not NULL, stores the interface where the error occurred, |
| * or NULL, if unknown. |
| * \param id if not NULL, stores the object id that generated |
| * the error, or 0, if the object id is unknown. There's no |
| * guarantee the object is still valid; the client must know |
| * if it deleted the object. |
| * \return The error code as defined in the interface specification. |
| * |
| * \code |
| * int err = wl_display_get_error(display); |
| * |
| * if (err == EPROTO) { |
| * code = wl_display_get_protocol_error(display, &interface, &id); |
| * handle_error(code, interface, id); |
| * } |
| * |
| * ... |
| * \endcode |
| * \memberof wl_display |
| */ |
| WL_EXPORT uint32_t |
| wl_display_get_protocol_error(struct wl_display *display, |
| const struct wl_interface **interface, |
| uint32_t *id) |
| { |
| uint32_t ret; |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| ret = display->protocol_error.code; |
| |
| if (interface) |
| *interface = display->protocol_error.interface; |
| if (id) |
| *id = display->protocol_error.id; |
| |
| pthread_mutex_unlock(&display->mutex); |
| |
| return ret; |
| } |
| |
| |
| /** Send all buffered requests on the display to the server |
| * |
| * \param display The display context object |
| * \return The number of bytes sent on success or -1 on failure |
| * |
| * Send all buffered data on the client side to the server. Clients should |
| * always call this function before blocking on input from the display fd. |
| * On success, the number of bytes sent to the server is returned. On |
| * failure, this function returns -1 and errno is set appropriately. |
| * |
| * wl_display_flush() never blocks. It will write as much data as |
| * possible, but if all data could not be written, errno will be set |
| * to EAGAIN and -1 returned. In that case, use poll on the display |
| * file descriptor to wait for it to become writable again. |
| * |
| * \memberof wl_display |
| */ |
| WL_EXPORT int |
| wl_display_flush(struct wl_display *display) |
| { |
| int ret; |
| |
| pthread_mutex_lock(&display->mutex); |
| |
| if (display->last_error) { |
| errno = display->last_error; |
| ret = -1; |
| } else { |
| /* We don't make EPIPE a fatal error here, so that we may try to |
| * read events after the failed flush. When the compositor sends |
| * an error it will close the socket, and if we make EPIPE fatal |
| * here we don't get a chance to process the error. */ |
| ret = wl_connection_flush(display->connection); |
| if (ret < 0 && errno != EAGAIN && errno != EPIPE) |
| display_fatal_error(display, errno); |
| } |
| |
| pthread_mutex_unlock(&display->mutex); |
| |
| return ret; |
| } |
| |
| /** Set the user data associated with a proxy |
| * |
| * \param proxy The proxy object |
| * \param user_data The data to be associated with proxy |
| * |
| * Set the user data associated with \c proxy. When events for this |
| * proxy are received, \c user_data will be supplied to its listener. |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT void |
| wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data) |
| { |
| proxy->user_data = user_data; |
| } |
| |
| /** Get the user data associated with a proxy |
| * |
| * \param proxy The proxy object |
| * \return The user data associated with proxy |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT void * |
| wl_proxy_get_user_data(struct wl_proxy *proxy) |
| { |
| return proxy->user_data; |
| } |
| |
| /** Get the protocol object version of a proxy object |
| * |
| * \param proxy The proxy object |
| * \return The protocol object version of the proxy or 0 |
| * |
| * Gets the protocol object version of a proxy object, or 0 |
| * if the proxy was created with unversioned API. |
| * |
| * A returned value of 0 means that no version information is |
| * available, so the caller must make safe assumptions about |
| * the object's real version. |
| * |
| * wl_display's version will always return 0. |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT uint32_t |
| wl_proxy_get_version(struct wl_proxy *proxy) |
| { |
| return proxy->version; |
| } |
| |
| /** Get the id of a proxy object |
| * |
| * \param proxy The proxy object |
| * \return The id the object associated with the proxy |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT uint32_t |
| wl_proxy_get_id(struct wl_proxy *proxy) |
| { |
| return proxy->object.id; |
| } |
| |
| /** Get the interface name (class) of a proxy object |
| * |
| * \param proxy The proxy object |
| * \return The interface name of the object associated with the proxy |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT const char * |
| wl_proxy_get_class(struct wl_proxy *proxy) |
| { |
| return proxy->object.interface->name; |
| } |
| |
| /** Assign a proxy to an event queue |
| * |
| * \param proxy The proxy object |
| * \param queue The event queue that will handle this proxy or NULL |
| * |
| * Assign proxy to event queue. Events coming from \c proxy will be |
| * queued in \c queue from now. If queue is NULL, then the display's |
| * default queue is set to the proxy. |
| * |
| * \note By default, the queue set in proxy is the one inherited from parent. |
| * |
| * \sa wl_display_dispatch_queue() |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT void |
| wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue) |
| { |
| if (queue) |
| proxy->queue = queue; |
| else |
| proxy->queue = &proxy->display->default_queue; |
| } |
| |
| /** Create a proxy wrapper for making queue assignments thread-safe |
| * |
| * \param proxy The proxy object to be wrapped |
| * \return A proxy wrapper for the given proxy or NULL on failure |
| * |
| * A proxy wrapper is type of 'struct wl_proxy' instance that can be used when |
| * sending requests instead of using the original proxy. A proxy wrapper does |
| * not have an implementation or dispatcher, and events received on the |
| * object is still emitted on the original proxy. Trying to set an |
| * implementation or dispatcher will have no effect but result in a warning |
| * being logged. |
| * |
| * Setting the proxy queue of the proxy wrapper will make new objects created |
| * using the proxy wrapper use the set proxy queue. |
| * Even though there is no implementation nor dispatcher, the proxy queue can |
| * be changed. This will affect the default queue of new objects created by |
| * requests sent via the proxy wrapper. |
| * |
| * A proxy wrapper can only be destroyed using wl_proxy_wrapper_destroy(). |
| * |
| * A proxy wrapper must be destroyed before the proxy it was created from. |
| * |
| * If a user reads and dispatches events on more than one thread, it is |
| * necessary to use a proxy wrapper when sending requests on objects when the |
| * intention is that a newly created proxy is to use a proxy queue different |
| * from the proxy the request was sent on, as creating the new proxy and then |
| * setting the queue is not thread safe. |
| * |
| * For example, a module that runs using its own proxy queue that needs to |
| * do display roundtrip must wrap the wl_display proxy object before sending |
| * the wl_display.sync request. For example: |
| * |
| * \code |
| * |
| * struct wl_event_queue *queue = ...; |
| * struct wl_display *wrapped_display; |
| * struct wl_callback *callback; |
| * |
| * wrapped_display = wl_proxy_create_wrapper(display); |
| * wl_proxy_set_queue((struct wl_proxy *) wrapped_display, queue); |
| * callback = wl_display_sync(wrapped_display); |
| * wl_proxy_wrapper_destroy(wrapped_display); |
| * wl_callback_add_listener(callback, ...); |
| * |
| * \endcode |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT void * |
| wl_proxy_create_wrapper(void *proxy) |
| { |
| struct wl_proxy *wrapped_proxy = proxy; |
| struct wl_proxy *wrapper; |
| |
| wrapper = zalloc(sizeof *wrapper); |
| if (!wrapper) |
| return NULL; |
| |
| pthread_mutex_lock(&wrapped_proxy->display->mutex); |
| |
| wrapper->object.interface = wrapped_proxy->object.interface; |
| wrapper->object.id = wrapped_proxy->object.id; |
| wrapper->version = wrapped_proxy->version; |
| wrapper->display = wrapped_proxy->display; |
| wrapper->queue = wrapped_proxy->queue; |
| wrapper->flags = WL_PROXY_FLAG_WRAPPER; |
| wrapper->refcount = 1; |
| |
| pthread_mutex_unlock(&wrapped_proxy->display->mutex); |
| |
| return wrapper; |
| } |
| |
| /** Destroy a proxy wrapper |
| * \param proxy_wrapper The proxy wrapper to be destroyed |
| * |
| * \memberof wl_proxy |
| */ |
| WL_EXPORT void |
| wl_proxy_wrapper_destroy(void *proxy_wrapper) |
| { |
| struct wl_proxy *wrapper = proxy_wrapper; |
| |
| if (!(wrapper->flags & WL_PROXY_FLAG_WRAPPER)) |
| wl_abort("Tried to destroy non-wrapper proxy with " |
| "wl_proxy_wrapper_destroy\n"); |
| |
| assert(wrapper->refcount == 1); |
| |
| free(wrapper); |
| } |
| |
| WL_EXPORT void |
| wl_log_set_handler_client(wl_log_func_t handler) |
| { |
| wl_log_handler = handler; |
| } |