mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	Compare commits
	
		
			23 commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
							 | 
						d81525a235 | ||
| 
							 | 
						4673ef7e9c | ||
| 
							 | 
						77730f10a0 | ||
| 
							 | 
						264da6a92b | ||
| 
							 | 
						cd0d1543c0 | ||
| 
							 | 
						90187031e6 | ||
| 
							 | 
						eecf3f7635 | ||
| 
							 | 
						adf84614ca | ||
| 
							 | 
						ba9f9a446f | ||
| 
							 | 
						53fbc2b0c1 | ||
| 
							 | 
						fdac631d17 | ||
| 
							 | 
						6c1da92018 | ||
| 
							 | 
						ca83185e8a | ||
| 
							 | 
						4a0c4e2119 | ||
| 
							 | 
						387adc6a79 | ||
| 
							 | 
						0de833da29 | ||
| 
							 | 
						2978fd701a | ||
| 
							 | 
						5c2f31d8d6 | ||
| 
							 | 
						ce0ac4f29e | ||
| 
							 | 
						1bee7aa4a7 | ||
| 
							 | 
						6281ccbd3d | ||
| 
							 | 
						ecff0ee10c | ||
| 
							 | 
						827d0c30ad | 
					 13 changed files with 451 additions and 25 deletions
				
			
		| 
						 | 
					@ -43,7 +43,7 @@ include:
 | 
				
			||||||
    # API changes. If you need new features from ci-templates you must bump
 | 
					    # 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
 | 
					    # 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.
 | 
					    # be aware that you may need to account for API changes when doing so.
 | 
				
			||||||
    ref: f210ea84576f756816da37908771edcee14ef7e6
 | 
					    ref: 48c2c583a865bd59be21e8938df247faf460099c
 | 
				
			||||||
    file:
 | 
					    file:
 | 
				
			||||||
      - '/templates/debian.yml'
 | 
					      - '/templates/debian.yml'
 | 
				
			||||||
      - '/templates/freebsd.yml'
 | 
					      - '/templates/freebsd.yml'
 | 
				
			||||||
| 
						 | 
					@ -306,11 +306,11 @@ armv7-release-debian-build:
 | 
				
			||||||
.os-freebsd:
 | 
					.os-freebsd:
 | 
				
			||||||
  variables:
 | 
					  variables:
 | 
				
			||||||
    BUILD_OS: freebsd
 | 
					    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'
 | 
					    FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2'
 | 
				
			||||||
    # bump this tag every time you change something which requires rebuilding the
 | 
					    # bump this tag every time you change something which requires rebuilding the
 | 
				
			||||||
    # base image
 | 
					    # 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
 | 
					    # Don't build documentation since installing the required tools massively
 | 
				
			||||||
    # increases the VM image (and therefore container) size.
 | 
					    # increases the VM image (and therefore container) size.
 | 
				
			||||||
    MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false"
 | 
					    MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -398,7 +398,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (size < 0 || (size > 0 && INT_MAX / size / 4 < size))
 | 
						if (size < 0 || (size > 0 && INT_MAX / size / 4 < size))
 | 
				
			||||||
		return NULL;
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!name)
 | 
						if (!name)
 | 
				
			||||||
		name = "default";
 | 
							name = "default";
 | 
				
			||||||
| 
						 | 
					@ -409,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);
 | 
						theme->pool = shm_pool_create(shm, size * size * 4);
 | 
				
			||||||
	if (!theme->pool)
 | 
						if (!theme->pool)
 | 
				
			||||||
		goto out_error_pool;
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xcursor_load_theme(name, size, load_callback, theme);
 | 
						xcursor_load_theme(name, size, load_callback, theme);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -421,7 +421,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return theme;
 | 
						return theme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_error_pool:
 | 
					err:
 | 
				
			||||||
	free(theme);
 | 
						free(theme);
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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
 | 
					      in the environment). Beginning in Wayland 1.15, implementations can
 | 
				
			||||||
      optionally support server socket endpoints located at arbitrary
 | 
					      optionally support server socket endpoints located at arbitrary
 | 
				
			||||||
      locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis>
 | 
					      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>
 | 
				
			||||||
    <para>
 | 
					    <para>
 | 
				
			||||||
      Every message is structured as 32-bit words; values are represented in the
 | 
					      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="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="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="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="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="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 | 
				
			||||||
  <xi:include href="Server.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',
 | 
						'Protocol.xml',
 | 
				
			||||||
	'Xwayland.xml',
 | 
						'Xwayland.xml',
 | 
				
			||||||
	'Compositors.xml',
 | 
						'Compositors.xml',
 | 
				
			||||||
 | 
						'Color.xml',
 | 
				
			||||||
	'Client.xml',
 | 
						'Client.xml',
 | 
				
			||||||
	'Server.xml'
 | 
						'Server.xml'
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
project(
 | 
					project(
 | 
				
			||||||
	'wayland', 'c',
 | 
						'wayland', 'c',
 | 
				
			||||||
	version: '1.24.0',
 | 
						version: '1.24.90',
 | 
				
			||||||
	license: 'MIT',
 | 
						license: 'MIT',
 | 
				
			||||||
	meson_version: '>= 0.57.0',
 | 
						meson_version: '>= 0.57.0',
 | 
				
			||||||
	default_options: [
 | 
						default_options: [
 | 
				
			||||||
| 
						 | 
					@ -46,6 +46,7 @@ have_funcs = [
 | 
				
			||||||
	'memfd_create',
 | 
						'memfd_create',
 | 
				
			||||||
	'mremap',
 | 
						'mremap',
 | 
				
			||||||
	'strndup',
 | 
						'strndup',
 | 
				
			||||||
 | 
						'gettid',
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
foreach f: have_funcs
 | 
					foreach f: have_funcs
 | 
				
			||||||
	config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
 | 
						config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define _GNU_SOURCE
 | 
					#define _GNU_SOURCE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
| 
						 | 
					@ -1491,11 +1493,56 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
 | 
				
			||||||
	return result;
 | 
						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
 | 
					void
 | 
				
			||||||
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
 | 
					wl_closure_print(struct wl_closure *closure, struct wl_object *target,
 | 
				
			||||||
		 int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
 | 
							 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;
 | 
						int i;
 | 
				
			||||||
	struct argument_details arg;
 | 
						struct argument_details arg;
 | 
				
			||||||
	const char *signature = closure->message->signature;
 | 
						const char *signature = closure->message->signature;
 | 
				
			||||||
| 
						 | 
					@ -1512,17 +1559,40 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clock_gettime(CLOCK_REALTIME, &tp);
 | 
						clock_gettime(CLOCK_REALTIME, &tp);
 | 
				
			||||||
	time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
 | 
						time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
 | 
				
			||||||
 | 
						fprintf(f, "%s[%7u.%03u] ",
 | 
				
			||||||
 | 
							color ? WL_DEBUG_COLOR_GREEN : "",
 | 
				
			||||||
 | 
							time / 1000, 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)
 | 
						if (include_tid) {
 | 
				
			||||||
		fprintf(f, "{%s} ", queue_name);
 | 
							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 " : "",
 | 
							discarded ? "discarded " : "",
 | 
				
			||||||
 | 
							color ? WL_DEBUG_COLOR_RESET : "",
 | 
				
			||||||
		send ? " -> " : "",
 | 
							send ? " -> " : "",
 | 
				
			||||||
		target->interface->name, target->id,
 | 
							color ? WL_DEBUG_COLOR_BLUE : "",
 | 
				
			||||||
		closure->message->name);
 | 
							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++) {
 | 
						for (i = 0; i < closure->count; i++) {
 | 
				
			||||||
		signature = get_next_argument(signature, &arg);
 | 
							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) {
 | 
						if (fclose(f) == 0) {
 | 
				
			||||||
		fprintf(stderr, "%s", buffer);
 | 
							fprintf(stderr, "%s", buffer);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -268,9 +268,16 @@ int
 | 
				
			||||||
wl_display_dispatch_queue_pending(struct wl_display *display,
 | 
					wl_display_dispatch_queue_pending(struct wl_display *display,
 | 
				
			||||||
				  struct wl_event_queue *queue);
 | 
									  struct wl_event_queue *queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					wl_display_dispatch_queue_pending_single(struct wl_display *display,
 | 
				
			||||||
 | 
										 struct wl_event_queue *queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
wl_display_dispatch_pending(struct wl_display *display);
 | 
					wl_display_dispatch_pending(struct wl_display *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					wl_display_dispatch_pending_single(struct wl_display *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
wl_display_get_error(struct wl_display *display);
 | 
					wl_display_get_error(struct wl_display *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,6 +115,7 @@ struct wl_display {
 | 
				
			||||||
/** \endcond */
 | 
					/** \endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int debug_client = 0;
 | 
					static int debug_client = 0;
 | 
				
			||||||
 | 
					static int debug_color = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This helper function wakes up all threads that are
 | 
					 * 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);
 | 
								queue_name = wl_event_queue_get_name(queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wl_closure_print(closure, &proxy->object, true, false, NULL,
 | 
							wl_closure_print(closure, &proxy->object, true, false, NULL,
 | 
				
			||||||
				 queue_name);
 | 
									 queue_name, debug_color);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wl_closure_send(closure, proxy->display->connection)) {
 | 
						if (wl_closure_send(closure, proxy->display->connection)) {
 | 
				
			||||||
| 
						 | 
					@ -1229,10 +1230,23 @@ wl_display_connect_to_fd(int fd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wl_display *display;
 | 
						struct wl_display *display;
 | 
				
			||||||
	const char *debug;
 | 
						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");
 | 
						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;
 | 
							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);
 | 
						display = zalloc(sizeof *display);
 | 
				
			||||||
	if (display == NULL) {
 | 
						if (display == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -1600,12 +1614,16 @@ queue_event(struct wl_display *display, int len)
 | 
				
			||||||
		if (debug_client) {
 | 
							if (debug_client) {
 | 
				
			||||||
			clock_gettime(CLOCK_REALTIME, &tp);
 | 
								clock_gettime(CLOCK_REALTIME, &tp);
 | 
				
			||||||
			time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
 | 
								time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
 | 
				
			||||||
 | 
								fprintf(stderr, "%s[%7u.%03u] %sdiscarded %s[%s]%s#%u%s.[event %d]%s"
 | 
				
			||||||
			fprintf(stderr, "[%7u.%03u] discarded [%s]#%u.[event %d]"
 | 
					 | 
				
			||||||
				"(%d fd, %d byte)\n",
 | 
									"(%d fd, %d byte)\n",
 | 
				
			||||||
 | 
									debug_color ? WL_DEBUG_COLOR_GREEN : "",
 | 
				
			||||||
				time / 1000, time % 1000,
 | 
									time / 1000, time % 1000,
 | 
				
			||||||
 | 
									debug_color ? WL_DEBUG_COLOR_RED : "",
 | 
				
			||||||
 | 
									debug_color ? WL_DEBUG_COLOR_BLUE : "",
 | 
				
			||||||
				zombie ? "zombie" : "unknown",
 | 
									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);
 | 
									num_zombie_fds, size);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (num_zombie_fds > 0)
 | 
							if (num_zombie_fds > 0)
 | 
				
			||||||
| 
						 | 
					@ -1690,7 +1708,7 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
 | 
				
			||||||
				 !(proxy->dispatcher || proxy->object.implementation);
 | 
									 !(proxy->dispatcher || proxy->object.implementation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wl_closure_print(closure, &proxy->object, false, discarded,
 | 
							wl_closure_print(closure, &proxy->object, false, discarded,
 | 
				
			||||||
				 id_from_object, queue->name);
 | 
									 id_from_object, queue->name, debug_color);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (proxy_destroyed) {
 | 
						if (proxy_destroyed) {
 | 
				
			||||||
| 
						 | 
					@ -1864,6 +1882,34 @@ err:
 | 
				
			||||||
	return -1;
 | 
						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
 | 
					/** Prepare to read events from the display's file descriptor to a queue
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param display The display context object
 | 
					 * \param display The display context object
 | 
				
			||||||
| 
						 | 
					@ -2194,6 +2240,34 @@ wl_display_dispatch_queue_pending(struct wl_display *display,
 | 
				
			||||||
	return ret;
 | 
						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
 | 
					/** Process incoming events
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param display The display context object
 | 
					 * \param display The display context object
 | 
				
			||||||
| 
						 | 
					@ -2254,6 +2328,25 @@ wl_display_dispatch_pending(struct wl_display *display)
 | 
				
			||||||
						 &display->default_queue);
 | 
											 &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
 | 
					/** Retrieve the last error that occurred on a display
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param display The display context object
 | 
					 * \param display The display context object
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,6 +53,14 @@
 | 
				
			||||||
# error default buffer cannot hold maximum-sized message
 | 
					# error default buffer cannot hold maximum-sized message
 | 
				
			||||||
#endif
 | 
					#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.
 | 
					 * Argument types used in signatures.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -229,11 +237,14 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection);
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
 | 
					wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool
 | 
				
			||||||
 | 
					wl_check_env_token(const char *env, const char *token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
wl_closure_print(struct wl_closure *closure,
 | 
					wl_closure_print(struct wl_closure *closure,
 | 
				
			||||||
		 struct wl_object *target, int send, int discarded,
 | 
							 struct wl_object *target, int send, int discarded,
 | 
				
			||||||
		 uint32_t (*n_parse)(union wl_argument *arg),
 | 
							 uint32_t (*n_parse)(union wl_argument *arg),
 | 
				
			||||||
		 const char *queue_name);
 | 
							 const char *queue_name, int color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
wl_closure_destroy(struct wl_closure *closure);
 | 
					wl_closure_destroy(struct wl_closure *closure);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,6 +149,7 @@ struct wl_protocol_logger {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int debug_server = 0;
 | 
					static int debug_server = 0;
 | 
				
			||||||
 | 
					static int debug_color = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
log_closure(struct wl_resource *resource,
 | 
					log_closure(struct wl_resource *resource,
 | 
				
			||||||
| 
						 | 
					@ -160,7 +161,7 @@ log_closure(struct wl_resource *resource,
 | 
				
			||||||
	struct wl_protocol_logger_message message;
 | 
						struct wl_protocol_logger_message message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (debug_server)
 | 
						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)) {
 | 
						if (!wl_list_empty(&display->protocol_loggers)) {
 | 
				
			||||||
		message.resource = resource;
 | 
							message.resource = resource;
 | 
				
			||||||
| 
						 | 
					@ -1191,10 +1192,23 @@ wl_display_create(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wl_display *display;
 | 
						struct wl_display *display;
 | 
				
			||||||
	const char *debug;
 | 
						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");
 | 
						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;
 | 
							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);
 | 
						display = zalloc(sizeof *display);
 | 
				
			||||||
	if (display == NULL)
 | 
						if (display == NULL)
 | 
				
			||||||
| 
						 | 
					@ -1817,6 +1831,24 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
 | 
				
			||||||
	return 0;
 | 
						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_EXPORT const char *
 | 
				
			||||||
wl_display_add_socket_auto(struct wl_display *display)
 | 
					wl_display_add_socket_auto(struct wl_display *display)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1695,6 +1695,75 @@ TEST(global_remove)
 | 
				
			||||||
	display_destroy(d);
 | 
						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
 | 
					static void
 | 
				
			||||||
terminate_display(void *arg)
 | 
					terminate_display(void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue