mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-10-29 05:40:16 -04:00 
			
		
		
		
	Compare commits
	
		
			5 commits
		
	
	
		
			c15497bde8
			...
			a9d13ecd4d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | a9d13ecd4d | ||
|   | d81525a235 | ||
|   | 4673ef7e9c | ||
|   | 77730f10a0 | ||
|   | 0853304bc9 | 
					 8 changed files with 249 additions and 12 deletions
				
			
		|  | @ -46,6 +46,7 @@ have_funcs = [ | |||
| 	'memfd_create', | ||||
| 	'mremap', | ||||
| 	'strndup', | ||||
| 	'gettid', | ||||
| ] | ||||
| foreach f: have_funcs | ||||
| 	config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f)) | ||||
|  |  | |||
|  | @ -518,7 +518,7 @@ | |||
|     </event> | ||||
|   </interface> | ||||
| 
 | ||||
|   <interface name="wl_data_offer" version="3"> | ||||
|   <interface name="wl_data_offer" version="4"> | ||||
|     <description summary="offer to transfer data"> | ||||
|       A wl_data_offer represents a piece of data offered for transfer | ||||
|       by another client (the source client).  It is used by the | ||||
|  | @ -711,7 +711,7 @@ | |||
|     </event> | ||||
|   </interface> | ||||
| 
 | ||||
|   <interface name="wl_data_source" version="3"> | ||||
|   <interface name="wl_data_source" version="4"> | ||||
|     <description summary="offer to transfer data"> | ||||
|       The wl_data_source object is the source side of a wl_data_offer. | ||||
|       It is created by the source client in a data transfer and | ||||
|  | @ -866,7 +866,7 @@ | |||
|     </event> | ||||
|   </interface> | ||||
| 
 | ||||
|   <interface name="wl_data_device" version="3"> | ||||
|   <interface name="wl_data_device" version="4"> | ||||
|     <description summary="data transfer device"> | ||||
|       There is one wl_data_device per seat which can be obtained | ||||
|       from the global wl_data_device_manager singleton. | ||||
|  | @ -1006,13 +1006,12 @@ | |||
| 	data_device.data_offer and the data_offer.offer events are | ||||
| 	sent out immediately before this event to introduce the data | ||||
| 	offer object.  The selection event is sent to a client | ||||
| 	immediately before receiving keyboard focus and when a new | ||||
| 	selection is set while the client has keyboard focus.  The | ||||
| 	immediately before receiving data device focus and when a new | ||||
| 	selection is set while the client has data device focus.  The | ||||
| 	data_offer is valid until a new data_offer or NULL is received | ||||
| 	or until the client loses keyboard focus.  Switching surface with | ||||
| 	keyboard focus within the same client doesn't mean a new selection | ||||
| 	will be sent.  The client must destroy the previous selection | ||||
| 	data_offer, if any, upon receiving this event. | ||||
| 	or until the client loses data device focus. The client must | ||||
| 	destroy the previous selection data_offer, if any, upon receiving | ||||
| 	this event. | ||||
|       </description> | ||||
|       <arg name="id" type="object" interface="wl_data_offer" allow-null="true" | ||||
| 	   summary="selection data_offer object"/> | ||||
|  | @ -1025,9 +1024,33 @@ | |||
| 	This request destroys the data device. | ||||
|       </description> | ||||
|     </request> | ||||
| 
 | ||||
|     <!-- Version 4 additions --> | ||||
| 
 | ||||
|     <event name="enter" since="4"> | ||||
|       <description summary="focus gained"> | ||||
| 	Notification that this seat's data device has gained focus. | ||||
| 
 | ||||
| 	The compositor must send the wl_data_device.selection event before this | ||||
| 	event. | ||||
| 
 | ||||
| 	Before version 4, data device focus was indicated by keyboard focus. | ||||
| 	Switching surface with keyboard focus within the same client didn't mean | ||||
| 	a new selection event was sent. | ||||
|       </description> | ||||
|     </event> | ||||
| 
 | ||||
|     <event name="leave" since="4"> | ||||
|       <description summary="focus lost"> | ||||
| 	Notification that this seat's data device has lost focus. | ||||
| 
 | ||||
| 	The client will stop receiving selection events until the next enter | ||||
| 	event. | ||||
|       </description> | ||||
|     </event> | ||||
|   </interface> | ||||
| 
 | ||||
|   <interface name="wl_data_device_manager" version="3"> | ||||
|   <interface name="wl_data_device_manager" version="4"> | ||||
|     <description summary="data transfer interface"> | ||||
|       The wl_data_device_manager is a singleton global object that | ||||
|       provides access to inter-client data transfer mechanisms such as | ||||
|  |  | |||
|  | @ -26,6 +26,8 @@ | |||
| 
 | ||||
| #define _GNU_SOURCE | ||||
| 
 | ||||
| #include "../config.h" | ||||
| 
 | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
|  | @ -1491,11 +1493,56 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection) | |||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| wl_check_env_token(const char *env, const char *token) | ||||
| { | ||||
| 	const char *ptr = env; | ||||
| 	size_t token_len; | ||||
| 
 | ||||
| 	if (env == NULL) | ||||
| 		return false; | ||||
| 
 | ||||
| 	token_len = strlen(token); | ||||
| 
 | ||||
| 	// Scan the string for comma-separated tokens and look for a match.
 | ||||
| 	while (true) { | ||||
| 		const char *end; | ||||
| 		size_t len; | ||||
| 
 | ||||
| 		// Skip over any leading separators.
 | ||||
| 		while (*ptr == ',') | ||||
| 			ptr++; | ||||
| 
 | ||||
| 		if (*ptr == '\x00') | ||||
| 			return false; | ||||
| 
 | ||||
| 		end = strchr(ptr + 1, ','); | ||||
| 
 | ||||
| 		// If there isn't another separarator, then the rest of the string
 | ||||
| 		// is one token.
 | ||||
| 		if (end == NULL) | ||||
| 			return (strcmp(ptr, token) == 0); | ||||
| 
 | ||||
| 		len = end - ptr; | ||||
| 		if (len == token_len && memcmp(ptr, token, len) == 0) { | ||||
| 			return true; | ||||
| 		} | ||||
| 
 | ||||
| 		// Skip to the next token.
 | ||||
| 		ptr += len; | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| wl_closure_print(struct wl_closure *closure, struct wl_object *target, | ||||
| 		 int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg), | ||||
| 		 const char *queue_name, int color) | ||||
| { | ||||
| #if defined(HAVE_GETTID) | ||||
| 	static int include_tid = -1; | ||||
| #endif // defined(HAVE_GETTID)
 | ||||
| 	int i; | ||||
| 	struct argument_details arg; | ||||
| 	const char *signature = closure->message->signature; | ||||
|  | @ -1516,6 +1563,18 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, | |||
| 		color ? WL_DEBUG_COLOR_GREEN : "", | ||||
| 		time / 1000, time % 1000); | ||||
| 
 | ||||
| #if defined(HAVE_GETTID) | ||||
| 	if (include_tid < 0) { | ||||
| 		include_tid = wl_check_env_token(getenv("WAYLAND_DEBUG"), "thread_id"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (include_tid) { | ||||
| 		fprintf(f, "%sTID#%d ", | ||||
| 			color ? WL_DEBUG_COLOR_CYAN : "", | ||||
| 			(int) gettid()); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	if (queue_name) { | ||||
| 		fprintf(f, "%s{%s} ", | ||||
| 			color ? WL_DEBUG_COLOR_YELLOW : "", | ||||
|  |  | |||
|  | @ -268,9 +268,16 @@ int | |||
| wl_display_dispatch_queue_pending(struct wl_display *display, | ||||
| 				  struct wl_event_queue *queue); | ||||
| 
 | ||||
| int | ||||
| wl_display_dispatch_queue_pending_single(struct wl_display *display, | ||||
| 					 struct wl_event_queue *queue); | ||||
| 
 | ||||
| int | ||||
| wl_display_dispatch_pending(struct wl_display *display); | ||||
| 
 | ||||
| int | ||||
| wl_display_dispatch_pending_single(struct wl_display *display); | ||||
| 
 | ||||
| int | ||||
| wl_display_get_error(struct wl_display *display); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1236,7 +1236,7 @@ wl_display_connect_to_fd(int fd) | |||
| 	no_color = getenv("NO_COLOR"); | ||||
| 	force_color = getenv("FORCE_COLOR"); | ||||
| 	debug = getenv("WAYLAND_DEBUG"); | ||||
| 	if (debug && (strstr(debug, "client") || strstr(debug, "1"))) { | ||||
| 	if (debug && (wl_check_env_token(debug, "client") || wl_check_env_token(debug, "1"))) { | ||||
| 		debug_client = 1; | ||||
| 		if (isatty(fileno(stderr))) | ||||
| 			debug_color = 1; | ||||
|  | @ -1882,6 +1882,34 @@ err: | |||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| dispatch_queue_single(struct wl_display *display, struct wl_event_queue *queue) | ||||
| { | ||||
| 	if (display->last_error) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	while (!wl_list_empty(&display->display_queue.event_list)) { | ||||
| 		dispatch_event(display, &display->display_queue); | ||||
| 		if (display->last_error) | ||||
| 			goto err; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!wl_list_empty(&queue->event_list)) { | ||||
| 		dispatch_event(display, queue); | ||||
| 		if (display->last_error) | ||||
| 			goto err; | ||||
| 		return 1; | ||||
| 	} else { | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 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 | ||||
|  | @ -2212,6 +2240,34 @@ wl_display_dispatch_queue_pending(struct wl_display *display, | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /** Dispatch at most one pending event in an event queue
 | ||||
|  * | ||||
|  * \param display The display context object | ||||
|  * \param queue The event queue to dispatch | ||||
|  * \return The number of dispatched events (0 or 1) on success or -1 on failure | ||||
|  * | ||||
|  * Dispatch at most one pending event 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.25.0 | ||||
|  */ | ||||
| WL_EXPORT int | ||||
| wl_display_dispatch_queue_pending_single(struct wl_display *display, | ||||
| 					 struct wl_event_queue *queue) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	pthread_mutex_lock(&display->mutex); | ||||
| 
 | ||||
| 	ret = dispatch_queue_single(display, queue); | ||||
| 
 | ||||
| 	pthread_mutex_unlock(&display->mutex); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /** Process incoming events
 | ||||
|  * | ||||
|  * \param display The display context object | ||||
|  | @ -2272,6 +2328,25 @@ wl_display_dispatch_pending(struct wl_display *display) | |||
| 						 &display->default_queue); | ||||
| } | ||||
| 
 | ||||
| /** Dispatch at most one pending event in the default event queue.
 | ||||
|  * | ||||
|  * \param display The display context object | ||||
|  * \return The number of dispatched events (0 or 1) on success or -1 on failure | ||||
|  * | ||||
|  * Dispatch at most one pending event for objects assigned to the default | ||||
|  * 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.25.0 | ||||
|  */ | ||||
| WL_EXPORT int | ||||
| wl_display_dispatch_pending_single(struct wl_display *display) | ||||
| { | ||||
| 	return wl_display_dispatch_queue_pending_single(display, | ||||
| 			                             &display->default_queue); | ||||
| } | ||||
| 
 | ||||
| /** Retrieve the last error that occurred on a display
 | ||||
|  * | ||||
|  * \param display The display context object | ||||
|  |  | |||
|  | @ -237,6 +237,9 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); | |||
| int | ||||
| wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection); | ||||
| 
 | ||||
| bool | ||||
| wl_check_env_token(const char *env, const char *token); | ||||
| 
 | ||||
| void | ||||
| wl_closure_print(struct wl_closure *closure, | ||||
| 		 struct wl_object *target, int send, int discarded, | ||||
|  |  | |||
|  | @ -1198,7 +1198,7 @@ wl_display_create(void) | |||
| 	no_color = getenv("NO_COLOR"); | ||||
| 	force_color = getenv("FORCE_COLOR"); | ||||
| 	debug = getenv("WAYLAND_DEBUG"); | ||||
| 	if (debug && (strstr(debug, "server") || strstr(debug, "1"))) { | ||||
| 	if (debug && (wl_check_env_token(debug, "server") || wl_check_env_token(debug, "1"))) { | ||||
| 		debug_server = 1; | ||||
| 		if (isatty(fileno(stderr))) | ||||
| 			debug_color = 1; | ||||
|  |  | |||
|  | @ -1695,6 +1695,75 @@ TEST(global_remove) | |||
| 	display_destroy(d); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| dispatch_single_read_events(struct wl_display *d) | ||||
| { | ||||
| 	if (wl_display_prepare_read(d) < 0) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	int ret = 0; | ||||
| 	do { | ||||
| 		ret = wl_display_flush(d); | ||||
| 	} while (ret < 0 && (errno == EINTR || errno == EAGAIN)); | ||||
| 	assert(ret >= 0); | ||||
| 
 | ||||
| 	struct pollfd pfd[1]; | ||||
| 	pfd[0].fd = wl_display_get_fd(d); | ||||
| 	pfd[0].events = POLLIN; | ||||
| 
 | ||||
| 	do { | ||||
| 		ret = poll(pfd, 1, -1); | ||||
| 	} while (ret < 0 && errno == EINTR); | ||||
| 	assert(ret > 0); | ||||
| 
 | ||||
| 	wl_display_read_events(d); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| dispatch_single_client(void) | ||||
| { | ||||
| 	struct client *c = client_connect(); | ||||
| 
 | ||||
| 	assert(wl_display_dispatch_pending_single(c->wl_display) == 0); | ||||
| 
 | ||||
| 	struct wl_registry *registry = wl_display_get_registry(c->wl_display); | ||||
| 
 | ||||
| 	dispatch_single_read_events(c->wl_display); | ||||
| 
 | ||||
| 	// [1815110.061] {Default Queue} wl_registry#3.global(1, "test", 1)
 | ||||
| 	assert(wl_display_dispatch_pending_single(c->wl_display) == 1); | ||||
| 
 | ||||
| 	dispatch_single_read_events(c->wl_display); | ||||
| 
 | ||||
| 	// [1815110.067] {Default Queue} wl_registry#3.global(2, "wl_seat", 1)
 | ||||
| 	assert(wl_display_dispatch_pending_single(c->wl_display) == 1); | ||||
| 
 | ||||
| 	// No more events
 | ||||
| 	assert(wl_display_dispatch_pending_single(c->wl_display) == 0); | ||||
| 
 | ||||
| 	wl_registry_destroy(registry); | ||||
| 
 | ||||
| 	client_disconnect(c); | ||||
| } | ||||
| 
 | ||||
| TEST(dispatch_single) | ||||
| { | ||||
| 	struct display *d = display_create(); | ||||
| 
 | ||||
| 	struct wl_global *global = wl_global_create(d->wl_display, | ||||
| 						    &wl_seat_interface, | ||||
| 						    1, d, bind_seat); | ||||
| 
 | ||||
| 	client_create_noarg(d, dispatch_single_client); | ||||
| 
 | ||||
| 	display_run(d); | ||||
| 
 | ||||
| 	wl_global_destroy(global); | ||||
| 
 | ||||
| 	display_destroy(d); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| terminate_display(void *arg) | ||||
| { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue