mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-10-29 05:40:16 -04:00 
			
		
		
		
	Compare commits
	
		
			24 commits
		
	
	
		
			b362e8fb4f
			...
			7ff7d3e354
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 7ff7d3e354 | ||
|   | 8198e0c827 | ||
|   | d81525a235 | ||
|   | 4673ef7e9c | ||
|   | 77730f10a0 | ||
|   | 264da6a92b | ||
|   | cd0d1543c0 | ||
|   | 90187031e6 | ||
|   | eecf3f7635 | ||
|   | adf84614ca | ||
|   | ba9f9a446f | ||
|   | 53fbc2b0c1 | ||
|   | fdac631d17 | ||
|   | 6c1da92018 | ||
|   | ca83185e8a | ||
|   | 4a0c4e2119 | ||
|   | 387adc6a79 | ||
|   | 0de833da29 | ||
|   | 2978fd701a | ||
|   | 5c2f31d8d6 | ||
|   | ce0ac4f29e | ||
|   | 1bee7aa4a7 | ||
|   | 6281ccbd3d | ||
|   | ecff0ee10c | 
					 17 changed files with 639 additions and 101 deletions
				
			
		|  | @ -43,7 +43,7 @@ include: | |||
|     # API changes. If you need new features from ci-templates you must bump | ||||
|     # this to the current SHA you require from the ci-templates repo, however | ||||
|     # be aware that you may need to account for API changes when doing so. | ||||
|     ref: f210ea84576f756816da37908771edcee14ef7e6 | ||||
|     ref: 48c2c583a865bd59be21e8938df247faf460099c | ||||
|     file: | ||||
|       - '/templates/debian.yml' | ||||
|       - '/templates/freebsd.yml' | ||||
|  | @ -306,11 +306,11 @@ armv7-release-debian-build: | |||
| .os-freebsd: | ||||
|   variables: | ||||
|     BUILD_OS: freebsd | ||||
|     FDO_DISTRIBUTION_VERSION: "13.2" | ||||
|     FDO_DISTRIBUTION_VERSION: "14.3" | ||||
|     FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2' | ||||
|     # bump this tag every time you change something which requires rebuilding the | ||||
|     # base image | ||||
|     FDO_DISTRIBUTION_TAG: "2023-08-02.0" | ||||
|     FDO_DISTRIBUTION_TAG: "2025-07-20.0" | ||||
|     # Don't build documentation since installing the required tools massively | ||||
|     # increases the VM image (and therefore container) size. | ||||
|     MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false" | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| #include "xcursor.h" | ||||
| #include "wayland-cursor.h" | ||||
| #include "wayland-client.h" | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
|  | @ -284,7 +285,8 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images, | |||
| { | ||||
| 	struct cursor *cursor; | ||||
| 	struct cursor_image *image; | ||||
| 	int i, size; | ||||
| 	size_t size; | ||||
| 	int i; | ||||
| 
 | ||||
| 	cursor = malloc(sizeof *cursor); | ||||
| 	if (!cursor) | ||||
|  | @ -314,7 +316,12 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images, | |||
| 		image->image.hotspot_y = images->images[i]->yhot; | ||||
| 		image->image.delay = images->images[i]->delay; | ||||
| 
 | ||||
| 		size = image->image.width * image->image.height * 4; | ||||
| 		size = (size_t) image->image.width * image->image.height * 4; | ||||
| 		if (size > INT_MAX) { | ||||
| 			free(image); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		image->offset = shm_pool_allocate(theme->pool, size); | ||||
| 		if (image->offset < 0) { | ||||
| 			free(image); | ||||
|  | @ -344,6 +351,8 @@ load_callback(struct xcursor_images *images, void *data) | |||
| { | ||||
| 	struct wl_cursor_theme *theme = data; | ||||
| 	struct wl_cursor *cursor; | ||||
| 	struct wl_cursor **p; | ||||
| 	size_t s; | ||||
| 
 | ||||
| 	if (wl_cursor_theme_get_cursor(theme, images->name)) { | ||||
| 		xcursor_images_destroy(images); | ||||
|  | @ -353,15 +362,14 @@ load_callback(struct xcursor_images *images, void *data) | |||
| 	cursor = wl_cursor_create_from_xcursor_images(images, theme); | ||||
| 
 | ||||
| 	if (cursor) { | ||||
| 		theme->cursor_count++; | ||||
| 		theme->cursors = | ||||
| 			realloc(theme->cursors, | ||||
| 				theme->cursor_count * sizeof theme->cursors[0]); | ||||
| 		s = theme->cursor_count + 1; | ||||
| 		p = realloc(theme->cursors, s * sizeof theme->cursors[0]); | ||||
| 
 | ||||
| 		if (theme->cursors == NULL) { | ||||
| 			theme->cursor_count--; | ||||
| 		if (p == NULL) { | ||||
| 			free(cursor); | ||||
| 		} else { | ||||
| 			theme->cursor_count = s; | ||||
| 			theme->cursors = p; | ||||
| 			theme->cursors[theme->cursor_count - 1] = cursor; | ||||
| 		} | ||||
| 	} | ||||
|  | @ -389,6 +397,9 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm) | |||
| 	if (!theme) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if (size < 0 || (size > 0 && INT_MAX / size / 4 < size)) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	if (!name) | ||||
| 		name = "default"; | ||||
| 
 | ||||
|  | @ -398,7 +409,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm) | |||
| 
 | ||||
| 	theme->pool = shm_pool_create(shm, size * size * 4); | ||||
| 	if (!theme->pool) | ||||
| 		goto out_error_pool; | ||||
| 		goto err; | ||||
| 
 | ||||
| 	xcursor_load_theme(name, size, load_callback, theme); | ||||
| 
 | ||||
|  | @ -410,7 +421,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm) | |||
| 
 | ||||
| 	return theme; | ||||
| 
 | ||||
| out_error_pool: | ||||
| err: | ||||
| 	free(theme); | ||||
| 	return NULL; | ||||
| } | ||||
|  |  | |||
|  | @ -259,6 +259,8 @@ xcursor_read_file_header(FILE *file) | |||
| 		return NULL; | ||||
| 	if (!xcursor_read_uint(file, &head.ntoc)) | ||||
| 		return NULL; | ||||
| 	if (head.header < XCURSOR_FILE_HEADER_LEN) | ||||
| 		return NULL; | ||||
| 	skip = head.header - XCURSOR_FILE_HEADER_LEN; | ||||
| 	if (skip) | ||||
| 		if (fseek(file, skip, SEEK_CUR) == EOF) | ||||
|  | @ -571,7 +573,7 @@ xcursor_build_theme_dir(const char *dir, const char *theme) | |||
| 	 * add space for any needed directory separators, one per component, | ||||
| 	 * and one for the trailing null | ||||
| 	 */ | ||||
| 	full_size = 1 + homelen + 1 + dirlen + 1 + themelen + 1; | ||||
| 	full_size = (size_t) 1 + homelen + 1 + dirlen + 1 + themelen + 1; | ||||
| 	full = malloc(full_size); | ||||
| 	if (!full) | ||||
| 		return NULL; | ||||
|  | @ -686,11 +688,15 @@ load_all_cursors_from_dir(const char *path, int size, | |||
| 			  void *user_data) | ||||
| { | ||||
| 	FILE *f; | ||||
| 	DIR *dir = opendir(path); | ||||
| 	DIR *dir; | ||||
| 	struct dirent *ent; | ||||
| 	char *full; | ||||
| 	struct xcursor_images *images; | ||||
| 
 | ||||
| 	if (!path) | ||||
| 		return; | ||||
| 
 | ||||
| 	dir = opendir(path); | ||||
| 	if (!dir) | ||||
| 		return; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										139
									
								
								doc/publican/sources/Color.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								doc/publican/sources/Color.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,139 @@ | |||
| <?xml version='1.0' encoding='utf-8' ?> | ||||
| <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ | ||||
| <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent"> | ||||
| %BOOK_ENTITIES; | ||||
| ]> | ||||
| 
 | ||||
| <chapter id="chap-Color-Management"> | ||||
|   <title>Color management</title> | ||||
| 
 | ||||
|   <section id="sect-Color-Management-preface"> | ||||
|     <title>Overview</title> | ||||
| 
 | ||||
|     <para> | ||||
|       Color management in Wayland considers only displays. All pictures in | ||||
|       Wayland are always display-referred, meaning that the pixel values are | ||||
|       intended as-is for some specific display where they would produce the | ||||
|       light emissions (<ulink | ||||
|       url="https://cie.co.at/eilvterm/17-23-002">stimuli</ulink>) the picture's | ||||
|       author desired. Wayland does not support displaying "raw" camera or | ||||
|       scanner images as they are not display-referred, nor are they even | ||||
|       pictures without complex and subjective processing. | ||||
|     </para> | ||||
|     <para> | ||||
|       Stimuli — the picture itself — are only half of the picture reproduction. | ||||
|       The other half is the environment where a display is viewed. A striking | ||||
|       example is comparing a brightly lit office to a dark movie theater, the | ||||
|       stimuli required to produce a good reading of the picture is greatly | ||||
|       different. Therefore display-referred does not include only the display | ||||
|       but the viewing environment as well. | ||||
|     </para> | ||||
|     <para> | ||||
|       Window systems have been very well capable of operating without any | ||||
|       explicit consideration to color management. This is because there used to | ||||
|       be the implicit assumption of the standard display, the sRGB display, | ||||
|       which all computer monitors implemented, more or less. The viewing | ||||
|       environment was and still is accounted by adjusting the display and/or the | ||||
|       room to produce a workable experience. Pictures are authored on a computer | ||||
|       system by drawing, painting and adjusting the picture until it looks right | ||||
|       on the author's monitor. This implicitly builds the standard display and | ||||
|       environment assumption into the picture data. Deviations from the sRGB | ||||
|       specification were minor enough that they often did not matter if not in a | ||||
|       professional context like the printing industry. Displaying video material | ||||
|       required some more attention to the details, because video and television | ||||
|       standards differ enough from the sRGB display. What really made explicit | ||||
|       color management a hard requirement for entertainment is the coming of | ||||
|       wide color gamut (WCG) and high dynamic range (HDR) materials and | ||||
|       displays. | ||||
|     </para> | ||||
|     <para> | ||||
|       The color management design in Wayland follows the general Wayland design | ||||
|       principles: compositors tell clients what would be the optimal thing to | ||||
|       do, clients tell the compositors what kind of pictures they are actually | ||||
|       producing, and then compositors display those pictures the best they can. | ||||
|     </para> | ||||
|   </section> | ||||
| 
 | ||||
|   <section id="sect-Color-Management-Protocol"> | ||||
|     <title>Protocol Interfaces</title> | ||||
| 
 | ||||
|     <para> | ||||
|       Color management interfaces in Wayland and divided into two protocols: | ||||
|       <ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-management?ref_type=heads">color-management</ulink> | ||||
|       and | ||||
|       <ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-representation?ref_type=heads">color-representation</ulink>. | ||||
|       They are designed to work together, but they can also be used | ||||
|       independently when the other one is not needed. | ||||
|     </para> | ||||
| 
 | ||||
|     <section id="sect-Color-Management-Protocol-color-management"> | ||||
|       <title>Color-management</title> | ||||
| 
 | ||||
|       <para> | ||||
| 	Color management protocol has two main purposes. First, it puts the | ||||
| 	responsibility of color management on the compositor. This means that | ||||
| 	clients do not necessarily need to care about color management at all, | ||||
| 	and can display just fine by using the traditional standard display | ||||
| 	assumption even when the actual display is wildly different. Clients | ||||
| 	can also choose to target some other assumed display and let the | ||||
| 	compositor handle it, or they can explicitly render for the actual | ||||
| 	display at hand. Second, when the window system has multiple different | ||||
| 	monitors, and a wl_surface happens to span more than one monitor, the | ||||
| 	compositor can display the surface content correctly on all spanned | ||||
| 	monitors simultaneously, as much as physically possible. | ||||
|       </para> | ||||
|       <para> | ||||
| 	Color-management protocol concentrates on colorimetry: when you have a | ||||
| 	pixel with RGB values, what stimulus do those values represent. The | ||||
| 	stimulus definition follows the CIE 1931 two-degree observer model. Some | ||||
| 	core concepts here are color primaries, white point, transfer function, | ||||
| 	and dynamic range. The viewing environment is represented in an | ||||
| 	extremely simplified way as the reference white luminance. The | ||||
| 	connection between pixel RGB values and stimulus plus viewing | ||||
| 	environment is recorded in an <emphasis>image description</emphasis> | ||||
| 	object. Clients can create image description objects and tag | ||||
| 	<code>wl_surface</code>s with them, to indicate what kind of surface | ||||
| 	content there will be. Clients can also ask what image description the | ||||
| 	compositor would prefer to have on the <code>wl_surface</code>, and that | ||||
| 	preference can change over time, e.g. when the <code>wl_surface</code> | ||||
| 	is moved from one | ||||
| 	<code>wl_output</code> to another. Following the compositor's preference | ||||
| 	may provide advantages in image quality and power consumption. | ||||
|       </para> | ||||
|       <para> | ||||
| 	Image description objects can come in two flavors: parametric and | ||||
| 	ICC-based. The above was written with parametric image descriptions in | ||||
| 	mind, and they have first-class support for HDR. ICC-based image | ||||
| 	descriptions are wrapping an ICC profile and have no other data. ICC | ||||
| 	profiles are the standard tool for standard dynamic range (SDR) display | ||||
| 	color management. This means the capabilities between the two flavors | ||||
| 	differ, and one cannot always be replaced by the other. Compositor | ||||
| 	support for each flavor is optional. | ||||
|       </para> | ||||
|     </section> | ||||
| 
 | ||||
|     <section id="sect-Color-Management-Protocol-color-representation"> | ||||
|       <title>Color-representation</title> | ||||
| 
 | ||||
|       <para> | ||||
| 	Color-representation protocol deals with (potentially sub-sampled) | ||||
| 	YCbCr-RGB conversion, quantization range, and the inclusion of alpha in | ||||
| 	the RGB color channels, a.k.a. pre-multiplication. There are several | ||||
| 	different specifications on how an YCbCr-like (including ICtCp) signal, | ||||
| 	with chroma sub-sampling or not, is created from a full-resolution RGB | ||||
| 	image. Again, a client can tag a <code>wl_surface</code> with | ||||
| 	color-representation metadata to tell the compositor what kind of pixel | ||||
| 	data will be displayed through the wl_surface. | ||||
|       </para> | ||||
|       <para> | ||||
| 	The main purpose of color-representation is to correctly off-load the | ||||
| 	YCbCr-RGB conversion to the compositor, which can then opportunistically | ||||
| 	off-load it further to very power-efficient fixed-function circuitry in | ||||
| 	a display controller. This can significantly reduce power consumption | ||||
| 	when watching videos compared to using a GPU for the same, and on some | ||||
| 	embedded hardware platforms it is a hard requirement for processing high | ||||
| 	resolution video. | ||||
|       </para> | ||||
|     </section> | ||||
|   </section> | ||||
| </chapter> | ||||
|  | @ -97,7 +97,9 @@ | |||
|       in the environment). Beginning in Wayland 1.15, implementations can | ||||
|       optionally support server socket endpoints located at arbitrary | ||||
|       locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis> | ||||
|       to the absolute path at which the server endpoint listens. | ||||
|       to the absolute path at which the server endpoint listens. The socket may | ||||
|       also be provided through file descriptor inheritance, in which case | ||||
|       <emphasis>WAYLAND_SOCKET</emphasis> is set. | ||||
|     </para> | ||||
|     <para> | ||||
|       Every message is structured as 32-bit words; values are represented in the | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
|   <xi:include href="Architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> | ||||
|   <xi:include href="Protocol.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> | ||||
|   <xi:include href="Xwayland.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> | ||||
|   <xi:include href="Color.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> | ||||
|   <xi:include href="ProtocolSpec.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> | ||||
|   <xi:include href="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> | ||||
|   <xi:include href="Server.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> | ||||
|  |  | |||
|  | @ -54,6 +54,7 @@ publican_sources = [ | |||
| 	'Protocol.xml', | ||||
| 	'Xwayland.xml', | ||||
| 	'Compositors.xml', | ||||
| 	'Color.xml', | ||||
| 	'Client.xml', | ||||
| 	'Server.xml' | ||||
| ] | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ if get_option('tests') | |||
| 		test( | ||||
| 			'wayland-egl symbols check', | ||||
| 			find_program('wayland-egl-symbols-check'), | ||||
| 			depends: wayland_egl, | ||||
| 			env: [ | ||||
| 				'WAYLAND_EGL_LIB=@0@'.format(wayland_egl_shared.full_path()), | ||||
| 				'NM=@0@'.format(nm_path) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| project( | ||||
| 	'wayland', 'c', | ||||
| 	version: '1.23.91', | ||||
| 	version: '1.24.90', | ||||
| 	license: 'MIT', | ||||
| 	meson_version: '>= 0.57.0', | ||||
| 	default_options: [ | ||||
|  | @ -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)) | ||||
|  |  | |||
|  | @ -26,6 +26,8 @@ | |||
| 
 | ||||
| #define _GNU_SOURCE | ||||
| 
 | ||||
| #include "../config.h" | ||||
| 
 | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
|  | @ -1491,16 +1493,61 @@ 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) | ||||
| 		 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; | ||||
| 	struct timespec tp; | ||||
| 	unsigned int time; | ||||
| 	uint64_t time; | ||||
| 	uint32_t nval; | ||||
| 	FILE *f; | ||||
| 	char *buffer; | ||||
|  | @ -1511,18 +1558,41 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, | |||
| 		return; | ||||
| 
 | ||||
| 	clock_gettime(CLOCK_REALTIME, &tp); | ||||
| 	time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); | ||||
| 	time = ((tp.tv_sec % 10000LL) * 1000000LL) + (tp.tv_nsec / 1000); | ||||
| 	fprintf(f, "%s[%7u.%03u] ", | ||||
| 		color ? WL_DEBUG_COLOR_GREEN : "", | ||||
| 		(unsigned int)(time / 1000), (unsigned int)(time % 1000)); | ||||
| 
 | ||||
| 	fprintf(f, "[%7u.%03u] ", time / 1000, time % 1000); | ||||
| #if defined(HAVE_GETTID) | ||||
| 	if (include_tid < 0) { | ||||
| 		include_tid = wl_check_env_token(getenv("WAYLAND_DEBUG"), "thread_id"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (queue_name) | ||||
| 		fprintf(f, "{%s} ", queue_name); | ||||
| 	if (include_tid) { | ||||
| 		fprintf(f, "%sTID#%d ", | ||||
| 			color ? WL_DEBUG_COLOR_CYAN : "", | ||||
| 			(int) gettid()); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	fprintf(f, "%s%s%s#%u.%s(", | ||||
| 	if (queue_name) { | ||||
| 		fprintf(f, "%s{%s} ", | ||||
| 			color ? WL_DEBUG_COLOR_YELLOW : "", | ||||
| 			queue_name); | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(f, "%s%s%s%s%s%s%s#%u%s.%s%s(", | ||||
| 		color ? WL_DEBUG_COLOR_RED : "", | ||||
| 		discarded ? "discarded " : "", | ||||
| 		color ? WL_DEBUG_COLOR_RESET : "", | ||||
| 		send ? " -> " : "", | ||||
| 		target->interface->name, target->id, | ||||
| 		closure->message->name); | ||||
| 		color ? WL_DEBUG_COLOR_BLUE : "", | ||||
| 		target->interface->name, | ||||
| 		color ? WL_DEBUG_COLOR_MAGENTA : "", | ||||
| 		target->id, | ||||
| 		color ? WL_DEBUG_COLOR_CYAN : "", | ||||
| 		closure->message->name, | ||||
| 		color ? WL_DEBUG_COLOR_RESET : ""); | ||||
| 
 | ||||
| 	for (i = 0; i < closure->count; i++) { | ||||
| 		signature = get_next_argument(signature, &arg); | ||||
|  | @ -1587,7 +1657,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(f, ")\n"); | ||||
| 	fprintf(f, ")%s\n", color ? WL_DEBUG_COLOR_RESET : ""); | ||||
| 
 | ||||
| 	if (fclose(f) == 0) { | ||||
| 		fprintf(stderr, "%s", buffer); | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -115,6 +115,7 @@ struct wl_display { | |||
| /** \endcond */ | ||||
| 
 | ||||
| static int debug_client = 0; | ||||
| static int debug_color = 0; | ||||
| 
 | ||||
| /**
 | ||||
|  * This helper function wakes up all threads that are | ||||
|  | @ -936,7 +937,7 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode, | |||
| 			queue_name = wl_event_queue_get_name(queue); | ||||
| 
 | ||||
| 		wl_closure_print(closure, &proxy->object, true, false, NULL, | ||||
| 				 queue_name); | ||||
| 				 queue_name, debug_color); | ||||
| 	} | ||||
| 
 | ||||
| 	if (wl_closure_send(closure, proxy->display->connection)) { | ||||
|  | @ -1229,10 +1230,23 @@ wl_display_connect_to_fd(int fd) | |||
| { | ||||
| 	struct wl_display *display; | ||||
| 	const char *debug; | ||||
| 	const char *no_color; | ||||
| 	const char *force_color; | ||||
| 
 | ||||
| 	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; | ||||
| 	} | ||||
| 
 | ||||
| 	if (force_color && force_color[0] != '\0') | ||||
| 		debug_color = 1; | ||||
| 
 | ||||
| 	if (no_color && no_color[0] != '\0') | ||||
| 		debug_color = 0; | ||||
| 
 | ||||
| 	display = zalloc(sizeof *display); | ||||
| 	if (display == NULL) { | ||||
|  | @ -1564,6 +1578,28 @@ queue_event(struct wl_display *display, int len) | |||
| 	id = p[0]; | ||||
| 	opcode = p[1] & 0xffff; | ||||
| 	size = p[1] >> 16; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If the message is larger than the maximum size of the | ||||
| 	 * connection buffer, the connection buffer will fill to | ||||
| 	 * its max size and stay there, with no message ever | ||||
| 	 * successfully being processed.  If the user of | ||||
| 	 * libwayland-client uses a level-triggered event loop, | ||||
| 	 * this will cause the client to enter a loop that | ||||
| 	 * consumes CPU.  To avoid this, immediately drop the | ||||
| 	 * connection.  Since the maximum size of a message should | ||||
| 	 * not depend on the max buffer size chosen by the client, | ||||
| 	 * always compare the message size against the | ||||
| 	 * limit enforced by libwayland 1.22 and below (4096), | ||||
| 	 * rather than the actual value the client chose. | ||||
| 	 */ | ||||
| 	if (size > WL_MAX_MESSAGE_SIZE) { | ||||
| 		wl_log("Message length %u exceeds limit %d\n", | ||||
| 		       size, WL_MAX_MESSAGE_SIZE); | ||||
| 		errno = E2BIG; | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (len < size) | ||||
| 		return 0; | ||||
| 
 | ||||
|  | @ -1578,12 +1614,16 @@ queue_event(struct wl_display *display, int len) | |||
| 		if (debug_client) { | ||||
| 			clock_gettime(CLOCK_REALTIME, &tp); | ||||
| 			time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); | ||||
| 
 | ||||
| 			fprintf(stderr, "[%7u.%03u] discarded [%s]#%d.[event %d]" | ||||
| 			fprintf(stderr, "%s[%7u.%03u] %sdiscarded %s[%s]%s#%u%s.[event %d]%s" | ||||
| 				"(%d fd, %d byte)\n", | ||||
| 				debug_color ? WL_DEBUG_COLOR_GREEN : "", | ||||
| 				time / 1000, time % 1000, | ||||
| 				debug_color ? WL_DEBUG_COLOR_RED : "", | ||||
| 				debug_color ? WL_DEBUG_COLOR_BLUE : "", | ||||
| 				zombie ? "zombie" : "unknown", | ||||
| 				id, opcode, | ||||
| 				debug_color ? WL_DEBUG_COLOR_MAGENTA : "", id, | ||||
| 				debug_color ? WL_DEBUG_COLOR_BLUE : "", opcode, | ||||
| 				debug_color ? WL_DEBUG_COLOR_RESET : "", | ||||
| 				num_zombie_fds, size); | ||||
| 		} | ||||
| 		if (num_zombie_fds > 0) | ||||
|  | @ -1668,7 +1708,7 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue) | |||
| 				 !(proxy->dispatcher || proxy->object.implementation); | ||||
| 
 | ||||
| 		wl_closure_print(closure, &proxy->object, false, discarded, | ||||
| 				 id_from_object, queue->name); | ||||
| 				 id_from_object, queue->name, debug_color); | ||||
| 	} | ||||
| 
 | ||||
| 	if (proxy_destroyed) { | ||||
|  | @ -1842,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 | ||||
|  | @ -2172,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 | ||||
|  | @ -2232,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 | ||||
|  |  | |||
|  | @ -49,6 +49,17 @@ | |||
| #define WL_CLOSURE_MAX_ARGS 20 | ||||
| #define WL_BUFFER_DEFAULT_SIZE_POT 12 | ||||
| #define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT) | ||||
| #if WL_BUFFER_DEFAULT_MAX_SIZE < WL_MAX_MESSAGE_SIZE | ||||
| # error default buffer cannot hold maximum-sized message | ||||
| #endif | ||||
| 
 | ||||
| #define WL_DEBUG_COLOR_RESET "\e[0m" | ||||
| #define WL_DEBUG_COLOR_RED "\e[31m" | ||||
| #define WL_DEBUG_COLOR_GREEN "\e[32m" | ||||
| #define WL_DEBUG_COLOR_YELLOW "\e[33m" | ||||
| #define WL_DEBUG_COLOR_BLUE "\e[34m" | ||||
| #define WL_DEBUG_COLOR_MAGENTA "\e[35m" | ||||
| #define WL_DEBUG_COLOR_CYAN "\e[36m" | ||||
| 
 | ||||
| /**
 | ||||
|  * Argument types used in signatures. | ||||
|  | @ -226,11 +237,14 @@ 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, | ||||
| 		 uint32_t (*n_parse)(union wl_argument *arg), | ||||
| 		 const char *queue_name); | ||||
| 		 const char *queue_name, int color); | ||||
| 
 | ||||
| void | ||||
| wl_closure_destroy(struct wl_closure *closure); | ||||
|  |  | |||
|  | @ -149,6 +149,7 @@ struct wl_protocol_logger { | |||
| }; | ||||
| 
 | ||||
| static int debug_server = 0; | ||||
| static int debug_color = 0; | ||||
| 
 | ||||
| static void | ||||
| log_closure(struct wl_resource *resource, | ||||
|  | @ -160,7 +161,7 @@ log_closure(struct wl_resource *resource, | |||
| 	struct wl_protocol_logger_message message; | ||||
| 
 | ||||
| 	if (debug_server) | ||||
| 		wl_closure_print(closure, object, send, false, NULL, NULL); | ||||
| 		wl_closure_print(closure, object, send, false, NULL, NULL, debug_color); | ||||
| 
 | ||||
| 	if (!wl_list_empty(&display->protocol_loggers)) { | ||||
| 		message.resource = resource; | ||||
|  | @ -397,6 +398,29 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) | |||
| 		wl_connection_copy(connection, p, sizeof p); | ||||
| 		opcode = p[1] & 0xffff; | ||||
| 		size = p[1] >> 16; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * If the message is larger than the maximum size of the | ||||
| 		 * connection buffer, the connection buffer will fill to | ||||
| 		 * its max size and stay there, with no message ever | ||||
| 		 * successfully being processed.  Since libwayland-server | ||||
| 		 * uses level-triggered epoll, it will cause the server to | ||||
| 		 * enter a loop that consumes CPU.  To avoid this, | ||||
| 		 * immediately disconnect the client with a protocol | ||||
| 		 * error.  Since the maximum size of a message should not | ||||
| 		 * depend on the buffer size chosen by the compositor, | ||||
| 		 * always compare the message size against the | ||||
| 		 * limit enforced by libwayland 1.22 and below (4096), | ||||
| 		 * rather than the actual value the compositor chose. | ||||
| 		 */ | ||||
| 		if (size > WL_MAX_MESSAGE_SIZE) { | ||||
| 			wl_resource_post_error(client->display_resource, | ||||
| 			                       WL_DISPLAY_ERROR_INVALID_METHOD, | ||||
| 			                       "message length %u exceeds %d", | ||||
| 			                       size, WL_MAX_MESSAGE_SIZE); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (len < size) | ||||
| 			break; | ||||
| 
 | ||||
|  | @ -1168,10 +1192,23 @@ wl_display_create(void) | |||
| { | ||||
| 	struct wl_display *display; | ||||
| 	const char *debug; | ||||
| 	const char *no_color; | ||||
| 	const char *force_color; | ||||
| 
 | ||||
| 	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; | ||||
| 	} | ||||
| 
 | ||||
| 	if (force_color && force_color[0] != '\0') | ||||
| 		debug_color = 1; | ||||
| 
 | ||||
| 	if (no_color && no_color[0] != '\0') | ||||
| 		debug_color = 0; | ||||
| 
 | ||||
| 	display = zalloc(sizeof *display); | ||||
| 	if (display == NULL) | ||||
|  | @ -1794,6 +1831,24 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** Automatically pick a Wayland display socket for the clients to connect to.
 | ||||
|  * | ||||
|  * \param display Wayland display to which the socket should be added. | ||||
|  * \return The socket name if success. NULL if failed. | ||||
|  * | ||||
|  * This adds a Unix socket to Wayland display which can be used by clients to | ||||
|  * connect to Wayland display. The name of the socket is chosen automatically | ||||
|  * as the first available name in the sequence "wayland-0", "wayland-1", | ||||
|  * "wayland-2", ..., "wayland-32". | ||||
|  * | ||||
|  * The string returned by this function is owned by the library and should | ||||
|  * not be freed. | ||||
|  * | ||||
|  * \sa wl_display_add_socket | ||||
|  * | ||||
|  * \memberof wl_display | ||||
|  */ | ||||
| WL_EXPORT const char * | ||||
| wl_display_add_socket_auto(struct wl_display *display) | ||||
| { | ||||
|  |  | |||
|  | @ -90,6 +90,14 @@ extern "C" { | |||
|  */ | ||||
| struct wl_object; | ||||
| 
 | ||||
| /**
 | ||||
|  * The maximum size of a protocol message. | ||||
|  * | ||||
|  * If a message size exceeds this value, the connection will be dropped. | ||||
|  * Servers will send an invalid_method error before disconnecting. | ||||
|  */ | ||||
| #define WL_MAX_MESSAGE_SIZE 4096 | ||||
| 
 | ||||
| /**
 | ||||
|  * Protocol message signature | ||||
|  * | ||||
|  |  | |||
|  | @ -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) | ||||
| { | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ tests_protocol_c = custom_target( | |||
| 	output: 'tests-protocol.c' | ||||
| ) | ||||
| 
 | ||||
| executable( | ||||
| exec_fd_leak_checker = executable( | ||||
| 	'exec-fd-leak-checker', | ||||
| 	'exec-fd-leak-checker.c', | ||||
| 	dependencies: test_runner_dep | ||||
|  | @ -96,78 +96,116 @@ if get_option('scanner') | |||
| endif | ||||
| 
 | ||||
| tests = { | ||||
| 	'array-test': [], | ||||
| 	'client-test': [ wayland_server_protocol_h ], | ||||
| 	'display-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 		tests_server_protocol_h, | ||||
| 		tests_client_protocol_c, | ||||
| 		tests_protocol_c, | ||||
| 	], | ||||
| 	'connection-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'event-loop-test': [ wayland_server_protocol_h ], | ||||
| 	'fixed-test': [], | ||||
| 	'interface-test': [ wayland_client_protocol_h ], | ||||
| 	'list-test': [], | ||||
| 	'map-test': [], | ||||
| 	'sanity-test' : [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'socket-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'queue-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'signal-test': [ wayland_server_protocol_h ], | ||||
| 	'newsignal-test': [ | ||||
| 		# wayland-server.c is needed here to access wl_priv_* functions | ||||
| 		files('../src/wayland-server.c'), | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'resources-test': [ wayland_server_protocol_h ], | ||||
| 	'message-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'compositor-introspection-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'protocol-logger-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'headers-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 		'headers-protocol-test.c', | ||||
| 		wayland_client_protocol_core_h, | ||||
| 		wayland_server_protocol_core_h, | ||||
| 		'headers-protocol-core-test.c', | ||||
| 	], | ||||
| 	'os-wrappers-test': [], | ||||
| 	'proxy-test': [ | ||||
| 		wayland_client_protocol_h, | ||||
| 		wayland_server_protocol_h, | ||||
| 	], | ||||
| 	'enum-validator-test': [], | ||||
| 	'array-test': {}, | ||||
| 	'client-test': { | ||||
| 		'extra_sources': [ wayland_server_protocol_h ], | ||||
| 	}, | ||||
| 	'display-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 			tests_server_protocol_h, | ||||
| 			tests_client_protocol_c, | ||||
| 			tests_protocol_c, | ||||
| 		], | ||||
| 	}, | ||||
| 	'connection-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'event-loop-test': { | ||||
| 		'extra_sources': [ wayland_server_protocol_h ], | ||||
| 	}, | ||||
| 	'fixed-test': {}, | ||||
| 	'interface-test': { | ||||
| 		'extra_sources': [ wayland_client_protocol_h ], | ||||
| 	}, | ||||
| 	'list-test': {}, | ||||
| 	'map-test': {}, | ||||
| 	'sanity-test' : { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 		'runtime_deps': [ exec_fd_leak_checker ], | ||||
| 	}, | ||||
| 	'socket-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'queue-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'signal-test': { | ||||
| 		'extra_sources': [ wayland_server_protocol_h ], | ||||
| 	}, | ||||
| 	'newsignal-test': { | ||||
| 		'extra_sources': [ | ||||
| 			# wayland-server.c is needed here to access wl_priv_* functions | ||||
| 			files('../src/wayland-server.c'), | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'resources-test': { | ||||
| 		'extra_sources': [ wayland_server_protocol_h ], | ||||
| 	}, | ||||
| 	'message-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'compositor-introspection-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'protocol-logger-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'headers-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 			'headers-protocol-test.c', | ||||
| 			wayland_client_protocol_core_h, | ||||
| 			wayland_server_protocol_core_h, | ||||
| 			'headers-protocol-core-test.c', | ||||
| 		], | ||||
| 	}, | ||||
| 	'os-wrappers-test': { | ||||
| 		'runtime_deps': [ exec_fd_leak_checker ], | ||||
| 	}, | ||||
| 	'proxy-test': { | ||||
| 		'extra_sources': [ | ||||
| 			wayland_client_protocol_h, | ||||
| 			wayland_server_protocol_h, | ||||
| 		], | ||||
| 	}, | ||||
| 	'enum-validator-test': {}, | ||||
| } | ||||
| 
 | ||||
| foreach test_name, test_extra_sources: tests | ||||
| foreach test_name, test_extras : tests | ||||
| 	test_extra_sources = test_extras.get('extra_sources', []) | ||||
| 	test_runtime_deps = test_extras.get('runtime_deps', []) | ||||
| 	test_sources = [ test_name + '.c' ] + test_extra_sources | ||||
| 	test_deps = [test_runner_dep, epoll_dep] | ||||
| 	bin = executable(test_name, test_sources, dependencies: test_deps) | ||||
| 	test( | ||||
| 		test_name, | ||||
| 		bin, | ||||
| 		depends: test_runtime_deps, | ||||
| 		env: [ | ||||
| 			'TEST_SRC_DIR=@0@'.format(meson.current_source_dir()), | ||||
| 			'TEST_BUILD_DIR=@0@'.format(meson.current_build_dir()), | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue