mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "main" and "1.23.0" have entirely different histories.
		
	
	
		
	
		
					 38 changed files with 416 additions and 1972 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: 48c2c583a865bd59be21e8938df247faf460099c
 | 
			
		||||
    ref: b791bd48996e3ced9ca13f1c5ee82be8540b8adb
 | 
			
		||||
    file:
 | 
			
		||||
      - '/templates/debian.yml'
 | 
			
		||||
      - '/templates/freebsd.yml'
 | 
			
		||||
| 
						 | 
				
			
			@ -62,13 +62,6 @@ stages:
 | 
			
		|||
  - "Build and test"
 | 
			
		||||
  - "Other build configurations"
 | 
			
		||||
 | 
			
		||||
workflow:
 | 
			
		||||
  rules:
 | 
			
		||||
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
 | 
			
		||||
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
 | 
			
		||||
      when: never
 | 
			
		||||
    - if: $CI_COMMIT_BRANCH
 | 
			
		||||
 | 
			
		||||
.ci-rules:
 | 
			
		||||
  rules:
 | 
			
		||||
    - when: on_success
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +75,7 @@ workflow:
 | 
			
		|||
    FDO_DISTRIBUTION_EXEC: 'pip3 install --break-system-packages meson~=0.57.2'
 | 
			
		||||
    # bump this tag every time you change something which requires rebuilding the
 | 
			
		||||
    # base image
 | 
			
		||||
    FDO_DISTRIBUTION_TAG: "2025-01-21.1"
 | 
			
		||||
    FDO_DISTRIBUTION_TAG: "2024-03-28.2"
 | 
			
		||||
 | 
			
		||||
.debian-x86_64:
 | 
			
		||||
  extends:
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +94,6 @@ workflow:
 | 
			
		|||
    - .os-debian
 | 
			
		||||
  variables:
 | 
			
		||||
    BUILD_ARCH: "armv7"
 | 
			
		||||
    FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Does not inherit .ci-rules as we only want it to run in MR context.
 | 
			
		||||
| 
						 | 
				
			
			@ -155,6 +147,7 @@ armv7-debian-container_prep:
 | 
			
		|||
  stage: "Base container"
 | 
			
		||||
  variables:
 | 
			
		||||
    GIT_STRATEGY: none
 | 
			
		||||
    FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Core build environment.
 | 
			
		||||
| 
						 | 
				
			
			@ -306,11 +299,11 @@ armv7-release-debian-build:
 | 
			
		|||
.os-freebsd:
 | 
			
		||||
  variables:
 | 
			
		||||
    BUILD_OS: freebsd
 | 
			
		||||
    FDO_DISTRIBUTION_VERSION: "14.3"
 | 
			
		||||
    FDO_DISTRIBUTION_VERSION: "13.2"
 | 
			
		||||
    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: "2025-07-20.0"
 | 
			
		||||
    FDO_DISTRIBUTION_TAG: "2023-08-02.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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@
 | 
			
		|||
 * http://fontforge.org/pcf-format.html
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,6 @@
 | 
			
		|||
#include "xcursor.h"
 | 
			
		||||
#include "wayland-cursor.h"
 | 
			
		||||
#include "wayland-client.h"
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -69,16 +68,11 @@ shm_pool_create(struct wl_shm *shm, int size)
 | 
			
		|||
		goto err_close;
 | 
			
		||||
 | 
			
		||||
	pool->pool = wl_shm_create_pool(shm, pool->fd, size);
 | 
			
		||||
	if (!pool->pool)
 | 
			
		||||
		goto err_unmap;
 | 
			
		||||
 | 
			
		||||
	pool->size = size;
 | 
			
		||||
	pool->used = 0;
 | 
			
		||||
 | 
			
		||||
	return pool;
 | 
			
		||||
 | 
			
		||||
err_unmap:
 | 
			
		||||
	munmap(pool->data, size);
 | 
			
		||||
err_close:
 | 
			
		||||
	close(pool->fd);
 | 
			
		||||
err_free:
 | 
			
		||||
| 
						 | 
				
			
			@ -285,8 +279,7 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
 | 
			
		|||
{
 | 
			
		||||
	struct cursor *cursor;
 | 
			
		||||
	struct cursor_image *image;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	int i;
 | 
			
		||||
	int i, size;
 | 
			
		||||
 | 
			
		||||
	cursor = malloc(sizeof *cursor);
 | 
			
		||||
	if (!cursor)
 | 
			
		||||
| 
						 | 
				
			
			@ -316,12 +309,7 @@ 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 = (size_t) image->image.width * image->image.height * 4;
 | 
			
		||||
		if (size > INT_MAX) {
 | 
			
		||||
			free(image);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		size = image->image.width * image->image.height * 4;
 | 
			
		||||
		image->offset = shm_pool_allocate(theme->pool, size);
 | 
			
		||||
		if (image->offset < 0) {
 | 
			
		||||
			free(image);
 | 
			
		||||
| 
						 | 
				
			
			@ -351,8 +339,6 @@ 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);
 | 
			
		||||
| 
						 | 
				
			
			@ -362,14 +348,15 @@ load_callback(struct xcursor_images *images, void *data)
 | 
			
		|||
	cursor = wl_cursor_create_from_xcursor_images(images, theme);
 | 
			
		||||
 | 
			
		||||
	if (cursor) {
 | 
			
		||||
		s = theme->cursor_count + 1;
 | 
			
		||||
		p = realloc(theme->cursors, s * sizeof theme->cursors[0]);
 | 
			
		||||
		theme->cursor_count++;
 | 
			
		||||
		theme->cursors =
 | 
			
		||||
			realloc(theme->cursors,
 | 
			
		||||
				theme->cursor_count * sizeof theme->cursors[0]);
 | 
			
		||||
 | 
			
		||||
		if (p == NULL) {
 | 
			
		||||
		if (theme->cursors == NULL) {
 | 
			
		||||
			theme->cursor_count--;
 | 
			
		||||
			free(cursor);
 | 
			
		||||
		} else {
 | 
			
		||||
			theme->cursor_count = s;
 | 
			
		||||
			theme->cursors = p;
 | 
			
		||||
			theme->cursors[theme->cursor_count - 1] = cursor;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -397,9 +384,6 @@ 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";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -409,7 +393,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 err;
 | 
			
		||||
		goto out_error_pool;
 | 
			
		||||
 | 
			
		||||
	xcursor_load_theme(name, size, load_callback, theme);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -421,7 +405,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
 | 
			
		|||
 | 
			
		||||
	return theme;
 | 
			
		||||
 | 
			
		||||
err:
 | 
			
		||||
out_error_pool:
 | 
			
		||||
	free(theme);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -259,8 +259,6 @@ 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -573,7 +571,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 = (size_t) 1 + homelen + 1 + dirlen + 1 + themelen + 1;
 | 
			
		||||
	full_size = 1 + homelen + 1 + dirlen + 1 + themelen + 1;
 | 
			
		||||
	full = malloc(full_size);
 | 
			
		||||
	if (!full)
 | 
			
		||||
		return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -688,15 +686,11 @@ load_all_cursors_from_dir(const char *path, int size,
 | 
			
		|||
			  void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	FILE *f;
 | 
			
		||||
	DIR *dir;
 | 
			
		||||
	DIR *dir = opendir(path);
 | 
			
		||||
	struct dirent *ent;
 | 
			
		||||
	char *full;
 | 
			
		||||
	struct xcursor_images *images;
 | 
			
		||||
 | 
			
		||||
	if (!path)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	dir = opendir(path);
 | 
			
		||||
	if (!dir)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -804,14 +798,14 @@ xcursor_load_theme_protected(const char *theme, int size,
 | 
			
		|||
	free(xcursor_path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Load all the cursors of a theme
 | 
			
		||||
/** Load all the cursor of a theme
 | 
			
		||||
 *
 | 
			
		||||
 * This function loads all the cursor images of a given theme and its
 | 
			
		||||
 * inherited themes. Each cursor is loaded into a struct xcursor_images object
 | 
			
		||||
 * inherited themes. Each cursor is loaded into an struct xcursor_images object
 | 
			
		||||
 * which is passed to the caller's load callback. If a cursor appears
 | 
			
		||||
 * more than once across all the inherited themes, the load callback
 | 
			
		||||
 * will be called multiple times, with possibly different struct xcursor_images
 | 
			
		||||
 * objects which have the same name. The user is expected to destroy the
 | 
			
		||||
 * object which have the same name. The user is expected to destroy the
 | 
			
		||||
 * struct xcursor_images objects passed to the callback with
 | 
			
		||||
 * xcursor_images_destroy().
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,139 +0,0 @@
 | 
			
		|||
<?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>
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +87,7 @@
 | 
			
		|||
    </para>
 | 
			
		||||
    <para>
 | 
			
		||||
      Overall, the philosophy of Wayland is to provide clients with a way to
 | 
			
		||||
      manage windows and how their contents are displayed.  Rendering is left
 | 
			
		||||
      manage windows and how their contents is displayed.  Rendering is left
 | 
			
		||||
      to clients, and system wide memory management interfaces are used to
 | 
			
		||||
      pass buffer handles between clients and the compositing manager.
 | 
			
		||||
    </para>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,9 +97,7 @@
 | 
			
		|||
      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. The socket may
 | 
			
		||||
      also be provided through file descriptor inheritance, in which case
 | 
			
		||||
      <emphasis>WAYLAND_SOCKET</emphasis> is set.
 | 
			
		||||
      to the absolute path at which the server endpoint listens.
 | 
			
		||||
    </para>
 | 
			
		||||
    <para>
 | 
			
		||||
      Every message is structured as 32-bit words; values are represented in the
 | 
			
		||||
| 
						 | 
				
			
			@ -152,10 +150,9 @@
 | 
			
		|||
	  <listitem>
 | 
			
		||||
	    <para>
 | 
			
		||||
	      Starts with an unsigned 32-bit length (including null terminator),
 | 
			
		||||
	      followed by the UTF-8 encoded string contents, including
 | 
			
		||||
	      terminating null byte, then padding to a 32-bit boundary. A null
 | 
			
		||||
	      value is represented with a length of 0. Interior null bytes are
 | 
			
		||||
	      not permitted.
 | 
			
		||||
	      followed by the string contents, including terminating null byte,
 | 
			
		||||
	      then padding to a 32-bit boundary. A null value is represented
 | 
			
		||||
	      with a length of 0.
 | 
			
		||||
	    </para>
 | 
			
		||||
	  </listitem>
 | 
			
		||||
	</varlistentry>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,6 @@
 | 
			
		|||
  <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,7 +54,6 @@ publican_sources = [
 | 
			
		|||
	'Protocol.xml',
 | 
			
		||||
	'Xwayland.xml',
 | 
			
		||||
	'Compositors.xml',
 | 
			
		||||
	'Color.xml',
 | 
			
		||||
	'Client.xml',
 | 
			
		||||
	'Server.xml'
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,6 @@ 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.24.90',
 | 
			
		||||
	version: '1.23.0',
 | 
			
		||||
	license: 'MIT',
 | 
			
		||||
	meson_version: '>= 0.57.0',
 | 
			
		||||
	default_options: [
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +46,6 @@ have_funcs = [
 | 
			
		|||
	'memfd_create',
 | 
			
		||||
	'mremap',
 | 
			
		||||
	'strndup',
 | 
			
		||||
	'gettid',
 | 
			
		||||
]
 | 
			
		||||
foreach f: have_funcs
 | 
			
		||||
	config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
 | 
			
		||||
| 
						 | 
				
			
			@ -132,9 +131,7 @@ if get_option('scanner')
 | 
			
		|||
		'wayland-scanner.mk',
 | 
			
		||||
		'protocol/wayland.xml',
 | 
			
		||||
		'protocol/wayland.dtd',
 | 
			
		||||
	],
 | 
			
		||||
		install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'wayland'),
 | 
			
		||||
	)
 | 
			
		||||
	])
 | 
			
		||||
 | 
			
		||||
	install_data(
 | 
			
		||||
		[ 'wayland-scanner.m4' ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -501,10 +501,8 @@
 | 
			
		|||
    <event name="release">
 | 
			
		||||
      <description summary="compositor releases buffer">
 | 
			
		||||
	Sent when this wl_buffer is no longer used by the compositor.
 | 
			
		||||
 | 
			
		||||
	For more information on when release events may or may not be sent,
 | 
			
		||||
	and what consequences it has, please see the description of
 | 
			
		||||
	wl_surface.attach.
 | 
			
		||||
	The client is now free to reuse or destroy this buffer and its
 | 
			
		||||
	backing storage.
 | 
			
		||||
 | 
			
		||||
	If a client receives a release event before the frame callback
 | 
			
		||||
	requested in the same wl_surface.commit that attaches this
 | 
			
		||||
| 
						 | 
				
			
			@ -1506,8 +1504,7 @@
 | 
			
		|||
	the delivery of wl_buffer.release events becomes undefined. A well
 | 
			
		||||
	behaved client should not rely on wl_buffer.release events in this
 | 
			
		||||
	case. Alternatively, a client could create multiple wl_buffer objects
 | 
			
		||||
	from the same backing storage or use a protocol extension providing
 | 
			
		||||
	per-commit release notifications.
 | 
			
		||||
	from the same backing storage or use wp_linux_buffer_release.
 | 
			
		||||
 | 
			
		||||
	Destroying the wl_buffer after wl_buffer.release does not change
 | 
			
		||||
	the surface contents. Destroying the wl_buffer before wl_buffer.release
 | 
			
		||||
| 
						 | 
				
			
			@ -1835,9 +1832,6 @@
 | 
			
		|||
	x and y, combined with the new surface size define in which
 | 
			
		||||
	directions the surface's size changes.
 | 
			
		||||
 | 
			
		||||
	The exact semantics of wl_surface.offset are role-specific. Refer to
 | 
			
		||||
	the documentation of specific roles for more information.
 | 
			
		||||
 | 
			
		||||
	Surface location offset is double-buffered state, see
 | 
			
		||||
	wl_surface.commit.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1886,7 +1880,7 @@
 | 
			
		|||
    </event>
 | 
			
		||||
   </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="wl_seat" version="10">
 | 
			
		||||
  <interface name="wl_seat" version="9">
 | 
			
		||||
    <description summary="group of input devices">
 | 
			
		||||
      A seat is a group of keyboards, pointer and touch devices. This
 | 
			
		||||
      object is published as a global during start up, or when such a
 | 
			
		||||
| 
						 | 
				
			
			@ -1914,10 +1908,9 @@
 | 
			
		|||
 | 
			
		||||
    <event name="capabilities">
 | 
			
		||||
      <description summary="seat capabilities changed">
 | 
			
		||||
	This is sent on binding to the seat global or whenever a seat gains
 | 
			
		||||
	or loses the pointer, keyboard or touch capabilities.
 | 
			
		||||
	The argument is a capability enum containing the complete set of
 | 
			
		||||
	capabilities this seat has.
 | 
			
		||||
	This is emitted whenever a seat gains or loses the pointer,
 | 
			
		||||
	keyboard or touch capabilities.  The argument is a capability
 | 
			
		||||
	enum containing the complete set of capabilities this seat has.
 | 
			
		||||
 | 
			
		||||
	When the pointer capability is added, a client may create a
 | 
			
		||||
	wl_pointer object using the wl_seat.get_pointer request. This object
 | 
			
		||||
| 
						 | 
				
			
			@ -1999,9 +1992,9 @@
 | 
			
		|||
	The same seat names are used for all clients. Thus, the name can be
 | 
			
		||||
	shared across processes to refer to a specific wl_seat global.
 | 
			
		||||
 | 
			
		||||
	The name event is sent after binding to the seat global, and should be sent
 | 
			
		||||
	before announcing capabilities. This event only sent once per seat object,
 | 
			
		||||
	and the name does not change over the lifetime of the wl_seat global.
 | 
			
		||||
	The name event is sent after binding to the seat global. This event is
 | 
			
		||||
	only sent once per seat object, and the name does not change over the
 | 
			
		||||
	lifetime of the wl_seat global.
 | 
			
		||||
 | 
			
		||||
	Compositors may re-use the same seat name if the wl_seat global is
 | 
			
		||||
	destroyed and re-created later.
 | 
			
		||||
| 
						 | 
				
			
			@ -2020,7 +2013,7 @@
 | 
			
		|||
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="wl_pointer" version="10">
 | 
			
		||||
  <interface name="wl_pointer" version="9">
 | 
			
		||||
    <description summary="pointer input device">
 | 
			
		||||
      The wl_pointer interface represents one or more input devices,
 | 
			
		||||
      such as mice, which control the pointer location and pointer_focus
 | 
			
		||||
| 
						 | 
				
			
			@ -2433,7 +2426,7 @@
 | 
			
		|||
    </event>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="wl_keyboard" version="10">
 | 
			
		||||
  <interface name="wl_keyboard" version="9">
 | 
			
		||||
    <description summary="keyboard input device">
 | 
			
		||||
      The wl_keyboard interface represents one or more keyboards
 | 
			
		||||
      associated with a seat.
 | 
			
		||||
| 
						 | 
				
			
			@ -2486,9 +2479,6 @@
 | 
			
		|||
	the surface argument and the keys currently logically down to the keys
 | 
			
		||||
	in the keys argument. The compositor must not send this event if the
 | 
			
		||||
	wl_keyboard already had an active surface immediately before this event.
 | 
			
		||||
 | 
			
		||||
	Clients should not use the list of pressed keys to emulate key-press
 | 
			
		||||
	events. The order of keys in the list is unspecified.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="serial" type="uint" summary="serial number of the enter event"/>
 | 
			
		||||
      <arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
 | 
			
		||||
| 
						 | 
				
			
			@ -2515,18 +2505,9 @@
 | 
			
		|||
    <enum name="key_state">
 | 
			
		||||
      <description summary="physical key state">
 | 
			
		||||
	Describes the physical state of a key that produced the key event.
 | 
			
		||||
 | 
			
		||||
	Since version 10, the key can be in a "repeated" pseudo-state which
 | 
			
		||||
	means the same as "pressed", but is used to signal repetition in the
 | 
			
		||||
	key event.
 | 
			
		||||
 | 
			
		||||
	The key may only enter the repeated state after entering the pressed
 | 
			
		||||
	state and before entering the released state. This event may be
 | 
			
		||||
	generated multiple times while the key is down.
 | 
			
		||||
      </description>
 | 
			
		||||
      <entry name="released" value="0" summary="key is not pressed"/>
 | 
			
		||||
      <entry name="pressed" value="1" summary="key is pressed"/>
 | 
			
		||||
      <entry name="repeated" value="2" summary="key was repeated" since="10"/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
    <event name="key">
 | 
			
		||||
| 
						 | 
				
			
			@ -2549,11 +2530,6 @@
 | 
			
		|||
	compositor must not send this event if state is pressed (resp. released)
 | 
			
		||||
	and the key was already logically down (resp. was not logically down)
 | 
			
		||||
	immediately before this event.
 | 
			
		||||
 | 
			
		||||
	Since version 10, compositors may send key events with the "repeated"
 | 
			
		||||
	key state when a wl_keyboard.repeat_info event with a rate argument of
 | 
			
		||||
	0 has been received. This allows the compositor to take over the
 | 
			
		||||
	responsibility of key repetition.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="serial" type="uint" summary="serial number of the key event"/>
 | 
			
		||||
      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
 | 
			
		||||
| 
						 | 
				
			
			@ -2614,7 +2590,7 @@
 | 
			
		|||
    </event>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="wl_touch" version="10">
 | 
			
		||||
  <interface name="wl_touch" version="9">
 | 
			
		||||
    <description summary="touchscreen input device">
 | 
			
		||||
      The wl_touch interface represents a touchscreen
 | 
			
		||||
      associated with a seat.
 | 
			
		||||
| 
						 | 
				
			
			@ -3269,31 +3245,4 @@
 | 
			
		|||
    </request>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="wl_fixes" version="1">
 | 
			
		||||
    <description summary="wayland protocol fixes">
 | 
			
		||||
      This global fixes problems with other core-protocol interfaces that
 | 
			
		||||
      cannot be fixed in these interfaces themselves.
 | 
			
		||||
    </description>
 | 
			
		||||
 | 
			
		||||
    <request name="destroy" type="destructor">
 | 
			
		||||
      <description summary="destroys this object"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <request name="destroy_registry">
 | 
			
		||||
      <description summary="destroy a wl_registry">
 | 
			
		||||
	This request destroys a wl_registry object.
 | 
			
		||||
 | 
			
		||||
	The client should no longer use the wl_registry after making this
 | 
			
		||||
	request.
 | 
			
		||||
 | 
			
		||||
	The compositor will emit a wl_display.delete_id event with the object ID
 | 
			
		||||
	of the registry and will no longer emit any events on the registry. The
 | 
			
		||||
	client should re-use the object ID once it receives the
 | 
			
		||||
	wl_display.delete_id event.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="registry" type="object" interface="wl_registry"
 | 
			
		||||
	   summary="the registry to destroy"/>
 | 
			
		||||
    </request>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
</protocol>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										115
									
								
								src/connection.c
									
										
									
									
									
								
							
							
						
						
									
										115
									
								
								src/connection.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -26,8 +26,7 @@
 | 
			
		|||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
#include "../config.h"
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -76,8 +75,7 @@ struct wl_connection {
 | 
			
		|||
static inline size_t
 | 
			
		||||
size_pot(uint32_t size_bits)
 | 
			
		||||
{
 | 
			
		||||
	if (!(size_bits < 8 * sizeof(size_t)))
 | 
			
		||||
		wl_abort("Too many bits for size_t\n");
 | 
			
		||||
	assert(size_bits < 8 * sizeof(size_t));
 | 
			
		||||
 | 
			
		||||
	return ((size_t)1) << size_bits;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +260,7 @@ ring_buffer_ensure_space(struct wl_ring_buffer *b, size_t count)
 | 
			
		|||
	 * allowed).
 | 
			
		||||
	 */
 | 
			
		||||
	if (net_size > size_pot(size_bits)) {
 | 
			
		||||
		wl_log("Data too big for buffer (%zu + %zu > %zu).\n",
 | 
			
		||||
		wl_log("Data too big for buffer (%d + %zd > %zd).\n",
 | 
			
		||||
		       ring_buffer_size(b), count, size_pot(size_bits));
 | 
			
		||||
		errno = E2BIG;
 | 
			
		||||
		return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -930,7 +928,7 @@ wl_connection_demarshal(struct wl_connection *connection,
 | 
			
		|||
	for (i = 0; i < count; i++) {
 | 
			
		||||
		signature = get_next_argument(signature, &arg);
 | 
			
		||||
 | 
			
		||||
		if (arg.type != WL_ARG_FD && p >= end) {
 | 
			
		||||
		if (arg.type != WL_ARG_FD && p + 1 > end) {
 | 
			
		||||
			wl_log("message too short, "
 | 
			
		||||
			       "object (%d), message %s(%s)\n",
 | 
			
		||||
			       closure->sender_id, message->name,
 | 
			
		||||
| 
						 | 
				
			
			@ -977,7 +975,7 @@ wl_connection_demarshal(struct wl_connection *connection,
 | 
			
		|||
 | 
			
		||||
			s = (char *) p;
 | 
			
		||||
 | 
			
		||||
			if (s[length - 1] != '\0') {
 | 
			
		||||
			if (length > 0 && s[length - 1] != '\0') {
 | 
			
		||||
				wl_log("string not nul-terminated, "
 | 
			
		||||
				       "message %s(%s)\n",
 | 
			
		||||
				       message->name, message->signature);
 | 
			
		||||
| 
						 | 
				
			
			@ -985,14 +983,6 @@ wl_connection_demarshal(struct wl_connection *connection,
 | 
			
		|||
				goto err;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (strlen(s) != length - 1) {
 | 
			
		||||
				wl_log("string has embedded nul at offset %zu, "
 | 
			
		||||
				       "message %s(%s)\n", strlen(s),
 | 
			
		||||
				       message->name, message->signature);
 | 
			
		||||
				errno = EINVAL;
 | 
			
		||||
				goto err;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			closure->args[i].s = s;
 | 
			
		||||
			p = next;
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1231,11 +1221,6 @@ wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
 | 
			
		|||
		     count + 2, &ffi_type_void, ffi_types);
 | 
			
		||||
 | 
			
		||||
	implementation = target->implementation;
 | 
			
		||||
	if (!implementation) {
 | 
			
		||||
		wl_abort("Implementation of resource %d of %s is NULL\n",
 | 
			
		||||
			  target->id, target->interface->name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!implementation[opcode]) {
 | 
			
		||||
		wl_abort("listener function for opcode %u of %s is NULL\n",
 | 
			
		||||
			 opcode, target->interface->name);
 | 
			
		||||
| 
						 | 
				
			
			@ -1358,7 +1343,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
 | 
			
		|||
		if (arg.type == WL_ARG_FD)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (p >= end)
 | 
			
		||||
		if (p + 1 > end)
 | 
			
		||||
			goto overflow;
 | 
			
		||||
 | 
			
		||||
		switch (arg.type) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1386,7 +1371,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
 | 
			
		|||
			size = strlen(closure->args[i].s) + 1;
 | 
			
		||||
			*p++ = size;
 | 
			
		||||
 | 
			
		||||
			if (div_roundup(size, sizeof *p) > (uint32_t)(end - p))
 | 
			
		||||
			if (p + div_roundup(size, sizeof *p) > end)
 | 
			
		||||
				goto overflow;
 | 
			
		||||
 | 
			
		||||
			memcpy(p, closure->args[i].s, size);
 | 
			
		||||
| 
						 | 
				
			
			@ -1401,7 +1386,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
 | 
			
		|||
			size = closure->args[i].a->size;
 | 
			
		||||
			*p++ = size;
 | 
			
		||||
 | 
			
		||||
			if (div_roundup(size, sizeof *p) > (uint32_t)(end - p))
 | 
			
		||||
			if (p + div_roundup(size, sizeof *p) > end)
 | 
			
		||||
				goto overflow;
 | 
			
		||||
 | 
			
		||||
			if (size != 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -1493,56 +1478,11 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
 | 
			
		|||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
wl_check_env_token(const char *env, const char *token)
 | 
			
		||||
{
 | 
			
		||||
	const char *ptr = env;
 | 
			
		||||
	size_t token_len;
 | 
			
		||||
 | 
			
		||||
	if (env == NULL)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	token_len = strlen(token);
 | 
			
		||||
 | 
			
		||||
	// Scan the string for comma-separated tokens and look for a match.
 | 
			
		||||
	while (true) {
 | 
			
		||||
		const char *end;
 | 
			
		||||
		size_t len;
 | 
			
		||||
 | 
			
		||||
		// Skip over any leading separators.
 | 
			
		||||
		while (*ptr == ',')
 | 
			
		||||
			ptr++;
 | 
			
		||||
 | 
			
		||||
		if (*ptr == '\x00')
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		end = strchr(ptr + 1, ',');
 | 
			
		||||
 | 
			
		||||
		// If there isn't another separarator, then the rest of the string
 | 
			
		||||
		// is one token.
 | 
			
		||||
		if (end == NULL)
 | 
			
		||||
			return (strcmp(ptr, token) == 0);
 | 
			
		||||
 | 
			
		||||
		len = end - ptr;
 | 
			
		||||
		if (len == token_len && memcmp(ptr, token, len) == 0) {
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Skip to the next token.
 | 
			
		||||
		ptr += len;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
 | 
			
		||||
		 int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
 | 
			
		||||
		 const char *queue_name, int color)
 | 
			
		||||
		 const char *queue_name)
 | 
			
		||||
{
 | 
			
		||||
#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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1559,40 +1499,17 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
 | 
			
		|||
 | 
			
		||||
	clock_gettime(CLOCK_REALTIME, &tp);
 | 
			
		||||
	time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
 | 
			
		||||
	fprintf(f, "%s[%7u.%03u] ",
 | 
			
		||||
		color ? WL_DEBUG_COLOR_GREEN : "",
 | 
			
		||||
		time / 1000, time % 1000);
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_GETTID)
 | 
			
		||||
	if (include_tid < 0) {
 | 
			
		||||
		include_tid = wl_check_env_token(getenv("WAYLAND_DEBUG"), "thread_id");
 | 
			
		||||
	}
 | 
			
		||||
	fprintf(f, "[%7u.%03u] ", time / 1000, time % 1000);
 | 
			
		||||
 | 
			
		||||
	if (include_tid) {
 | 
			
		||||
		fprintf(f, "%sTID#%d ",
 | 
			
		||||
			color ? WL_DEBUG_COLOR_CYAN : "",
 | 
			
		||||
			(int) gettid());
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	if (queue_name)
 | 
			
		||||
		fprintf(f, "{%s} ", queue_name);
 | 
			
		||||
 | 
			
		||||
	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 : "",
 | 
			
		||||
	fprintf(f, "%s%s%s#%u.%s(",
 | 
			
		||||
		discarded ? "discarded " : "",
 | 
			
		||||
		color ? WL_DEBUG_COLOR_RESET : "",
 | 
			
		||||
		send ? " -> " : "",
 | 
			
		||||
		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 : "");
 | 
			
		||||
		target->interface->name, target->id,
 | 
			
		||||
		closure->message->name);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < closure->count; i++) {
 | 
			
		||||
		signature = get_next_argument(signature, &arg);
 | 
			
		||||
| 
						 | 
				
			
			@ -1657,7 +1574,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fprintf(f, ")%s\n", color ? WL_DEBUG_COLOR_RESET : "");
 | 
			
		||||
	fprintf(f, ")\n");
 | 
			
		||||
 | 
			
		||||
	if (fclose(f) == 0) {
 | 
			
		||||
		fprintf(stderr, "%s", buffer);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@
 | 
			
		|||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +39,6 @@
 | 
			
		|||
#include <sys/signalfd.h>
 | 
			
		||||
#include <sys/timerfd.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include "timespec-util.h"
 | 
			
		||||
#include "wayland-util.h"
 | 
			
		||||
#include "wayland-private.h"
 | 
			
		||||
#include "wayland-server-core.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -447,8 +447,7 @@ wl_timer_heap_disarm(struct wl_timer_heap *timers,
 | 
			
		|||
	struct wl_event_source_timer *last_end_evt;
 | 
			
		||||
	int old_source_idx;
 | 
			
		||||
 | 
			
		||||
	if (!(source->heap_idx >= 0))
 | 
			
		||||
		wl_abort("Timer has already been disarmed\n");
 | 
			
		||||
	assert(source->heap_idx >= 0);
 | 
			
		||||
 | 
			
		||||
	old_source_idx = source->heap_idx;
 | 
			
		||||
	source->heap_idx = -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -477,8 +476,7 @@ wl_timer_heap_arm(struct wl_timer_heap *timers,
 | 
			
		|||
		  struct wl_event_source_timer *source,
 | 
			
		||||
		  struct timespec deadline)
 | 
			
		||||
{
 | 
			
		||||
	if (!(source->heap_idx == -1))
 | 
			
		||||
		wl_abort("Timer is already armed\n");
 | 
			
		||||
	assert(source->heap_idx == -1);
 | 
			
		||||
 | 
			
		||||
	source->deadline = deadline;
 | 
			
		||||
	timers->data[timers->active] = source;
 | 
			
		||||
| 
						 | 
				
			
			@ -974,6 +972,57 @@ wl_event_loop_dispatch_idle(struct wl_event_loop *loop)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
timespec_to_ms(struct timespec value)
 | 
			
		||||
{
 | 
			
		||||
	return (value.tv_sec * 1000) + (value.tv_nsec / 1000000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct timespec
 | 
			
		||||
ms_to_timespec(int ms)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec val;
 | 
			
		||||
	val.tv_sec = ms / 1000;
 | 
			
		||||
	val.tv_nsec = (ms % 1000) * 1000000;
 | 
			
		||||
	return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct timespec
 | 
			
		||||
timespec_normalize(struct timespec value)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec result = value;
 | 
			
		||||
 | 
			
		||||
	while (result.tv_nsec >= 1000000000) {
 | 
			
		||||
		result.tv_nsec -= 1000000000;
 | 
			
		||||
		result.tv_sec++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (result.tv_nsec < 0) {
 | 
			
		||||
		result.tv_nsec += 1000000000;
 | 
			
		||||
		result.tv_sec--;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct timespec
 | 
			
		||||
timespec_add(struct timespec a, struct timespec b)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec result;
 | 
			
		||||
	result.tv_sec = a.tv_sec + b.tv_sec;
 | 
			
		||||
	result.tv_nsec = a.tv_nsec + b.tv_nsec;
 | 
			
		||||
	return timespec_normalize(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct timespec
 | 
			
		||||
timespec_sub(struct timespec a, struct timespec b)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec result;
 | 
			
		||||
	result.tv_sec = a.tv_sec - b.tv_sec;
 | 
			
		||||
	result.tv_nsec = a.tv_nsec - b.tv_nsec;
 | 
			
		||||
	return timespec_normalize(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Wait for events and dispatch them
 | 
			
		||||
 *
 | 
			
		||||
 * \param loop The event loop whose sources to wait for.
 | 
			
		||||
| 
						 | 
				
			
			@ -1002,15 +1051,13 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
 | 
			
		|||
	int i, count;
 | 
			
		||||
	bool has_timers = false;
 | 
			
		||||
	bool use_timeout = timeout > 0;
 | 
			
		||||
	struct timespec now;
 | 
			
		||||
	struct timespec deadline = {0};
 | 
			
		||||
	struct timespec result;
 | 
			
		||||
	struct timespec now, end;
 | 
			
		||||
 | 
			
		||||
	wl_event_loop_dispatch_idle(loop);
 | 
			
		||||
 | 
			
		||||
	if (use_timeout) {
 | 
			
		||||
		clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
		timespec_add_msec(&deadline, &now, timeout);
 | 
			
		||||
		end = timespec_add(now, ms_to_timespec(timeout));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (true) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1022,8 +1069,7 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
 | 
			
		|||
 | 
			
		||||
		if (use_timeout) {
 | 
			
		||||
			clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
			timespec_sub(&result, &deadline, &now);
 | 
			
		||||
			timeout = timespec_to_msec(&result);
 | 
			
		||||
			timeout = timespec_to_ms(timespec_sub(end, now));
 | 
			
		||||
			if (timeout <= 0) {
 | 
			
		||||
				/* too late */
 | 
			
		||||
				count = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -212,7 +212,6 @@ if get_option('libraries')
 | 
			
		|||
		description: 'Server side implementation of the Wayland protocol',
 | 
			
		||||
		version: meson.project_version(),
 | 
			
		||||
		filebase: 'wayland-server',
 | 
			
		||||
		libraries: mathlib_dep,
 | 
			
		||||
		variables: [
 | 
			
		||||
			'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
 | 
			
		||||
			'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
 | 
			
		||||
| 
						 | 
				
			
			@ -252,7 +251,6 @@ if get_option('libraries')
 | 
			
		|||
		description: 'Wayland client side library',
 | 
			
		||||
		version: meson.project_version(),
 | 
			
		||||
		filebase: 'wayland-client',
 | 
			
		||||
		libraries: mathlib_dep,
 | 
			
		||||
		variables: [
 | 
			
		||||
			'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
 | 
			
		||||
			'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1378,58 +1378,6 @@ emit_event_wrappers(struct wl_list *message_list, struct interface *interface)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_validator(struct interface *interface, struct enumeration *e)
 | 
			
		||||
{
 | 
			
		||||
	struct entry *entry;
 | 
			
		||||
 | 
			
		||||
	printf("#ifndef %s_%s_ENUM_IS_VALID\n",
 | 
			
		||||
	       interface->uppercase_name, e->uppercase_name);
 | 
			
		||||
	printf("#define %s_%s_ENUM_IS_VALID\n",
 | 
			
		||||
	       interface->uppercase_name, e->uppercase_name);
 | 
			
		||||
 | 
			
		||||
	printf("/**\n"
 | 
			
		||||
	       " * @ingroup iface_%s\n"
 | 
			
		||||
	       " * Validate a %s %s value.\n"
 | 
			
		||||
	       " *\n"
 | 
			
		||||
	       " * @return true on success, false on error.\n"
 | 
			
		||||
	       " * @ref %s_%s\n"
 | 
			
		||||
	       " */\n"
 | 
			
		||||
	       "static inline bool\n"
 | 
			
		||||
	       "%s_%s_is_valid(uint32_t value, uint32_t version) {\n",
 | 
			
		||||
	       interface->name, interface->name, e->name,
 | 
			
		||||
	       interface->name, e->name,
 | 
			
		||||
	       interface->name, e->name);
 | 
			
		||||
 | 
			
		||||
	if (e->bitfield) {
 | 
			
		||||
		printf("	uint32_t valid = 0;\n");
 | 
			
		||||
		wl_list_for_each(entry, &e->entry_list, link) {
 | 
			
		||||
			printf("	if (version >= %d)\n"
 | 
			
		||||
			       "		valid |= %s_%s_%s;\n",
 | 
			
		||||
			       entry->since,
 | 
			
		||||
			       interface->uppercase_name, e->uppercase_name,
 | 
			
		||||
			       entry->uppercase_name);
 | 
			
		||||
		}
 | 
			
		||||
		printf("	return (value & ~valid) == 0;\n");
 | 
			
		||||
	} else {
 | 
			
		||||
		printf("	switch (value) {\n");
 | 
			
		||||
		wl_list_for_each(entry, &e->entry_list, link) {
 | 
			
		||||
			printf("	case %s%s_%s_%s:\n"
 | 
			
		||||
			       "		return version >= %d;\n",
 | 
			
		||||
			       entry->value[0] == '-' ? "(uint32_t)" : "",
 | 
			
		||||
			       interface->uppercase_name, e->uppercase_name,
 | 
			
		||||
			       entry->uppercase_name, entry->since);
 | 
			
		||||
		}
 | 
			
		||||
		printf("	default:\n"
 | 
			
		||||
		       "		return false;\n"
 | 
			
		||||
		       "	}\n");
 | 
			
		||||
	}
 | 
			
		||||
	printf("}\n");
 | 
			
		||||
 | 
			
		||||
	printf("#endif /* %s_%s_ENUM_IS_VALID */\n\n",
 | 
			
		||||
	       interface->uppercase_name, e->uppercase_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_enumerations(struct interface *interface, bool with_validators)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1491,11 +1439,35 @@ emit_enumerations(struct interface *interface, bool with_validators)
 | 
			
		|||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (with_validators) {
 | 
			
		||||
			printf("/**\n"
 | 
			
		||||
			       " * @ingroup iface_%s\n"
 | 
			
		||||
			       " * Validate a %s %s value.\n"
 | 
			
		||||
			       " *\n"
 | 
			
		||||
			       " * @return true on success, false on error.\n"
 | 
			
		||||
			       " * @ref %s_%s\n"
 | 
			
		||||
			       " */\n"
 | 
			
		||||
			       "static inline bool\n"
 | 
			
		||||
			       "%s_%s_is_valid(uint32_t value, uint32_t version) {\n"
 | 
			
		||||
			       "	switch (value) {\n",
 | 
			
		||||
			       interface->name, interface->name, e->name,
 | 
			
		||||
			       interface->name, e->name,
 | 
			
		||||
			       interface->name, e->name);
 | 
			
		||||
			wl_list_for_each(entry, &e->entry_list, link) {
 | 
			
		||||
				printf("	case %s%s_%s_%s:\n"
 | 
			
		||||
				       "		return version >= %d;\n",
 | 
			
		||||
				       entry->value[0] == '-' ? "(uint32_t)" : "",
 | 
			
		||||
				       interface->uppercase_name, e->uppercase_name,
 | 
			
		||||
				       entry->uppercase_name, entry->since);
 | 
			
		||||
			}
 | 
			
		||||
			printf("	default:\n"
 | 
			
		||||
			       "		return false;\n"
 | 
			
		||||
			       "	}\n"
 | 
			
		||||
			       "}\n");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		printf("#endif /* %s_%s_ENUM */\n\n",
 | 
			
		||||
		       interface->uppercase_name, e->uppercase_name);
 | 
			
		||||
 | 
			
		||||
		if (with_validators)
 | 
			
		||||
			emit_validator(interface, e);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,311 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright © 2014 - 2015 Collabora, Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
 * a copy of this software and associated documentation files (the
 | 
			
		||||
 * "Software"), to deal in the Software without restriction, including
 | 
			
		||||
 * without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
 * distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
 * permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
 * the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice (including the
 | 
			
		||||
 * next paragraph) shall be included in all copies or substantial
 | 
			
		||||
 * portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
			
		||||
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
			
		||||
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TIMESPEC_UTIL_H
 | 
			
		||||
#define TIMESPEC_UTIL_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#define NSEC_PER_SEC 1000000000
 | 
			
		||||
 | 
			
		||||
/* Subtract timespecs
 | 
			
		||||
 *
 | 
			
		||||
 * \param r[out] result: a - b
 | 
			
		||||
 * \param a[in] operand
 | 
			
		||||
 * \param b[in] operand
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_sub(struct timespec *r,
 | 
			
		||||
	     const struct timespec *a, const struct timespec *b)
 | 
			
		||||
{
 | 
			
		||||
	r->tv_sec = a->tv_sec - b->tv_sec;
 | 
			
		||||
	r->tv_nsec = a->tv_nsec - b->tv_nsec;
 | 
			
		||||
	if (r->tv_nsec < 0) {
 | 
			
		||||
		r->tv_sec--;
 | 
			
		||||
		r->tv_nsec += NSEC_PER_SEC;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Add a nanosecond value to a timespec
 | 
			
		||||
 *
 | 
			
		||||
 * \param r[out] result: a + b
 | 
			
		||||
 * \param a[in] base operand as timespec
 | 
			
		||||
 * \param b[in] operand in nanoseconds
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_add_nsec(struct timespec *r, const struct timespec *a, int64_t b)
 | 
			
		||||
{
 | 
			
		||||
	r->tv_sec = a->tv_sec + (b / NSEC_PER_SEC);
 | 
			
		||||
	r->tv_nsec = a->tv_nsec + (b % NSEC_PER_SEC);
 | 
			
		||||
 | 
			
		||||
	if (r->tv_nsec >= NSEC_PER_SEC) {
 | 
			
		||||
		r->tv_sec++;
 | 
			
		||||
		r->tv_nsec -= NSEC_PER_SEC;
 | 
			
		||||
	} else if (r->tv_nsec < 0) {
 | 
			
		||||
		r->tv_sec--;
 | 
			
		||||
		r->tv_nsec += NSEC_PER_SEC;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Add a millisecond value to a timespec
 | 
			
		||||
 *
 | 
			
		||||
 * \param r[out] result: a + b
 | 
			
		||||
 * \param a[in] base operand as timespec
 | 
			
		||||
 * \param b[in] operand in milliseconds
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_add_msec(struct timespec *r, const struct timespec *a, int64_t b)
 | 
			
		||||
{
 | 
			
		||||
	timespec_add_nsec(r, a, b * 1000000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert timespec to nanoseconds
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \return nanoseconds
 | 
			
		||||
 */
 | 
			
		||||
static inline int64_t
 | 
			
		||||
timespec_to_nsec(const struct timespec *a)
 | 
			
		||||
{
 | 
			
		||||
	return (int64_t)a->tv_sec * NSEC_PER_SEC + a->tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Subtract timespecs and return result in nanoseconds
 | 
			
		||||
 *
 | 
			
		||||
 * \param a[in] operand
 | 
			
		||||
 * \param b[in] operand
 | 
			
		||||
 * \return to_nanoseconds(a - b)
 | 
			
		||||
 */
 | 
			
		||||
static inline int64_t
 | 
			
		||||
timespec_sub_to_nsec(const struct timespec *a, const struct timespec *b)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec r;
 | 
			
		||||
	timespec_sub(&r, a, b);
 | 
			
		||||
	return timespec_to_nsec(&r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert timespec to milliseconds
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \return milliseconds
 | 
			
		||||
 *
 | 
			
		||||
 * Rounding to integer milliseconds happens always down (floor()).
 | 
			
		||||
 */
 | 
			
		||||
static inline int64_t
 | 
			
		||||
timespec_to_msec(const struct timespec *a)
 | 
			
		||||
{
 | 
			
		||||
	return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Subtract timespecs and return result in milliseconds
 | 
			
		||||
 *
 | 
			
		||||
 * \param a[in] operand
 | 
			
		||||
 * \param b[in] operand
 | 
			
		||||
 * \return to_milliseconds(a - b)
 | 
			
		||||
 */
 | 
			
		||||
static inline int64_t
 | 
			
		||||
timespec_sub_to_msec(const struct timespec *a, const struct timespec *b)
 | 
			
		||||
{
 | 
			
		||||
	return timespec_sub_to_nsec(a, b) / 1000000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert timespec to microseconds
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \return microseconds
 | 
			
		||||
 *
 | 
			
		||||
 * Rounding to integer microseconds happens always down (floor()).
 | 
			
		||||
 */
 | 
			
		||||
static inline int64_t
 | 
			
		||||
timespec_to_usec(const struct timespec *a)
 | 
			
		||||
{
 | 
			
		||||
	return (int64_t)a->tv_sec * 1000000 + a->tv_nsec / 1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert timespec to protocol data
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \param tv_sec_hi[out] the high bytes of the seconds part
 | 
			
		||||
 * \param tv_sec_lo[out] the low bytes of the seconds part
 | 
			
		||||
 * \param tv_nsec[out] the nanoseconds part
 | 
			
		||||
 *
 | 
			
		||||
 * The input timespec must be normalized (the nanoseconds part should
 | 
			
		||||
 * be less than 1 second) and non-negative.
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_to_proto(const struct timespec *a, uint32_t *tv_sec_hi,
 | 
			
		||||
                  uint32_t *tv_sec_lo, uint32_t *tv_nsec)
 | 
			
		||||
{
 | 
			
		||||
	assert(a->tv_sec >= 0);
 | 
			
		||||
	assert(a->tv_nsec >= 0 && a->tv_nsec < NSEC_PER_SEC);
 | 
			
		||||
 | 
			
		||||
	uint64_t sec64 = a->tv_sec;
 | 
			
		||||
 | 
			
		||||
	*tv_sec_hi = sec64 >> 32;
 | 
			
		||||
	*tv_sec_lo = sec64 & 0xffffffff;
 | 
			
		||||
	*tv_nsec = a->tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert nanoseconds to timespec
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \param b nanoseconds
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_from_nsec(struct timespec *a, int64_t b)
 | 
			
		||||
{
 | 
			
		||||
	a->tv_sec = b / NSEC_PER_SEC;
 | 
			
		||||
	a->tv_nsec = b % NSEC_PER_SEC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert microseconds to timespec
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \param b microseconds
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_from_usec(struct timespec *a, int64_t b)
 | 
			
		||||
{
 | 
			
		||||
	timespec_from_nsec(a, b * 1000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert milliseconds to timespec
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \param b milliseconds
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_from_msec(struct timespec *a, int64_t b)
 | 
			
		||||
{
 | 
			
		||||
	timespec_from_nsec(a, b * 1000000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert protocol data to timespec
 | 
			
		||||
 *
 | 
			
		||||
 * \param a[out] timespec
 | 
			
		||||
 * \param tv_sec_hi the high bytes of seconds part
 | 
			
		||||
 * \param tv_sec_lo the low bytes of seconds part
 | 
			
		||||
 * \param tv_nsec the nanoseconds part
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_from_proto(struct timespec *a, uint32_t tv_sec_hi,
 | 
			
		||||
                    uint32_t tv_sec_lo, uint32_t tv_nsec)
 | 
			
		||||
{
 | 
			
		||||
	a->tv_sec = ((uint64_t)tv_sec_hi << 32) + tv_sec_lo;
 | 
			
		||||
	a->tv_nsec = tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check if a timespec is zero
 | 
			
		||||
 *
 | 
			
		||||
 * \param a timespec
 | 
			
		||||
 * \return whether the timespec is zero
 | 
			
		||||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
timespec_is_zero(const struct timespec *a)
 | 
			
		||||
{
 | 
			
		||||
	return a->tv_sec == 0 && a->tv_nsec == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check if two timespecs are equal
 | 
			
		||||
 *
 | 
			
		||||
 * \param a[in] timespec to check
 | 
			
		||||
 * \param b[in] timespec to check
 | 
			
		||||
 * \return whether timespecs a and b are equal
 | 
			
		||||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
timespec_eq(const struct timespec *a, const struct timespec *b)
 | 
			
		||||
{
 | 
			
		||||
	return a->tv_sec == b->tv_sec &&
 | 
			
		||||
	       a->tv_nsec == b->tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Convert milli-Hertz to nanoseconds
 | 
			
		||||
 *
 | 
			
		||||
 * \param mhz frequency in mHz, not zero
 | 
			
		||||
 * \return period in nanoseconds
 | 
			
		||||
 */
 | 
			
		||||
static inline int64_t
 | 
			
		||||
millihz_to_nsec(uint32_t mhz)
 | 
			
		||||
{
 | 
			
		||||
	assert(mhz > 0);
 | 
			
		||||
	return 1000000000000LL / mhz;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks whether a timespec value is after another
 | 
			
		||||
 *
 | 
			
		||||
 * \param a[in] timespec to compare
 | 
			
		||||
 * \param b[in] timespec to compare
 | 
			
		||||
 * \return whether a is after b
 | 
			
		||||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
timespec_after(const struct timespec *a, const struct timespec *b)
 | 
			
		||||
{
 | 
			
		||||
	return (a->tv_sec == b->tv_sec) ?
 | 
			
		||||
	       (a->tv_nsec > b->tv_nsec) :
 | 
			
		||||
	       (a->tv_sec > b->tv_sec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add timespecs
 | 
			
		||||
 *
 | 
			
		||||
 * \param r[out] result: a + b
 | 
			
		||||
 * \param a[in] operand
 | 
			
		||||
 * \param b[in] operand
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_add(struct timespec *r,
 | 
			
		||||
             const struct timespec *a, const struct timespec *b)
 | 
			
		||||
{
 | 
			
		||||
	r->tv_sec = a->tv_sec + b->tv_sec;
 | 
			
		||||
	r->tv_nsec = a->tv_nsec + b->tv_nsec;
 | 
			
		||||
	if (r->tv_nsec > NSEC_PER_SEC) {
 | 
			
		||||
		r->tv_sec++;
 | 
			
		||||
		r->tv_nsec -= NSEC_PER_SEC;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Saturating timespec subtraction
 | 
			
		||||
 *
 | 
			
		||||
 * \param r[out] result: max(a - b, 0)
 | 
			
		||||
 * \param a[in] operand
 | 
			
		||||
 * \param b[in] operand
 | 
			
		||||
 */
 | 
			
		||||
static inline void
 | 
			
		||||
timespec_sub_saturate(struct timespec *r,
 | 
			
		||||
                      const struct timespec *a, const struct timespec *b)
 | 
			
		||||
{
 | 
			
		||||
   timespec_sub(r, a, b);
 | 
			
		||||
   if (r->tv_sec < 0) {
 | 
			
		||||
      r->tv_sec = 0;
 | 
			
		||||
      r->tv_nsec = 0;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* TIMESPEC_UTIL_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -34,8 +34,6 @@
 | 
			
		|||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct timespec;
 | 
			
		||||
 | 
			
		||||
/** \class wl_proxy
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Represents a protocol object on the client side.
 | 
			
		||||
| 
						 | 
				
			
			@ -221,9 +219,6 @@ wl_proxy_get_tag(struct wl_proxy *proxy);
 | 
			
		|||
const char *
 | 
			
		||||
wl_proxy_get_class(struct wl_proxy *proxy);
 | 
			
		||||
 | 
			
		||||
const struct wl_interface *
 | 
			
		||||
wl_proxy_get_interface(struct wl_proxy *proxy);
 | 
			
		||||
 | 
			
		||||
struct wl_display *
 | 
			
		||||
wl_proxy_get_display(struct wl_proxy *proxy);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -255,29 +250,13 @@ int
 | 
			
		|||
wl_display_dispatch_queue(struct wl_display *display,
 | 
			
		||||
			  struct wl_event_queue *queue);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
wl_display_dispatch_timeout(struct wl_display *display,
 | 
			
		||||
			    const struct timespec *timeout);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
wl_display_dispatch_queue_timeout(struct wl_display *display,
 | 
			
		||||
				  struct wl_event_queue *queue,
 | 
			
		||||
				  const struct timespec *timeout);
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@
 | 
			
		|||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +46,6 @@
 | 
			
		|||
#include "wayland-os.h"
 | 
			
		||||
#include "wayland-client.h"
 | 
			
		||||
#include "wayland-private.h"
 | 
			
		||||
#include "timespec-util.h"
 | 
			
		||||
 | 
			
		||||
/** \cond */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +115,6 @@ struct wl_display {
 | 
			
		|||
/** \endcond */
 | 
			
		||||
 | 
			
		||||
static int debug_client = 0;
 | 
			
		||||
static int debug_color = 0;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This helper function wakes up all threads that are
 | 
			
		||||
| 
						 | 
				
			
			@ -236,16 +235,13 @@ wl_event_queue_init(struct wl_event_queue *queue,
 | 
			
		|||
static void
 | 
			
		||||
wl_proxy_unref(struct wl_proxy *proxy)
 | 
			
		||||
{
 | 
			
		||||
	if (!(proxy->refcount > 0))
 | 
			
		||||
		wl_abort("Proxy requested for unref has no references\n");
 | 
			
		||||
	assert(proxy->refcount > 0);
 | 
			
		||||
	if (--proxy->refcount > 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* If we get here, the client must have explicitly requested
 | 
			
		||||
	 * deletion. */
 | 
			
		||||
	if (!(proxy->flags & WL_PROXY_FLAG_DESTROYED))
 | 
			
		||||
		wl_abort("Proxy with no references not yet explicitly"
 | 
			
		||||
			 "destroyed\n");
 | 
			
		||||
	assert(proxy->flags & WL_PROXY_FLAG_DESTROYED);
 | 
			
		||||
	free(proxy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -675,9 +671,6 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
 | 
			
		|||
 * This function is useful in clients with multiple listeners on the same
 | 
			
		||||
 * interface to allow the identification of which code to execute.
 | 
			
		||||
 *
 | 
			
		||||
 * If \ref wl_proxy_add_dispatcher was used, this function returns the
 | 
			
		||||
 * dispatcher_data pointer instead.
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_proxy
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT const void *
 | 
			
		||||
| 
						 | 
				
			
			@ -921,29 +914,21 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
 | 
			
		|||
 | 
			
		||||
	closure = wl_closure_marshal(&proxy->object, opcode, args, message);
 | 
			
		||||
	if (closure == NULL) {
 | 
			
		||||
		wl_log("Error marshalling request for %s.%s: %s\n",
 | 
			
		||||
		       proxy->object.interface->name, message->name,
 | 
			
		||||
		       strerror(errno));
 | 
			
		||||
		wl_log("Error marshalling request: %s\n", strerror(errno));
 | 
			
		||||
		display_fatal_error(proxy->display, errno);
 | 
			
		||||
		goto err_unlock;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (debug_client) {
 | 
			
		||||
		struct wl_event_queue *queue;
 | 
			
		||||
		const char *queue_name = NULL;
 | 
			
		||||
 | 
			
		||||
		queue = wl_proxy_get_queue(proxy);
 | 
			
		||||
		if (queue)
 | 
			
		||||
			queue_name = wl_event_queue_get_name(queue);
 | 
			
		||||
 | 
			
		||||
		wl_closure_print(closure, &proxy->object, true, false, NULL,
 | 
			
		||||
				 queue_name, debug_color);
 | 
			
		||||
				 wl_event_queue_get_name(queue));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (wl_closure_send(closure, proxy->display->connection)) {
 | 
			
		||||
		wl_log("Error sending request for %s.%s: %s\n",
 | 
			
		||||
		       proxy->object.interface->name, message->name,
 | 
			
		||||
		       strerror(errno));
 | 
			
		||||
		wl_log("Error sending request: %s\n", strerror(errno));
 | 
			
		||||
		display_fatal_error(proxy->display, errno);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1187,8 +1172,7 @@ connect_to_socket(const char *name)
 | 
			
		|||
			         "%s", name) + 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(name_size > 0))
 | 
			
		||||
		wl_abort("Error assigning path name for socket connection\n");
 | 
			
		||||
	assert(name_size > 0);
 | 
			
		||||
	if (name_size > (int)sizeof addr.sun_path) {
 | 
			
		||||
		if (!path_is_absolute) {
 | 
			
		||||
			wl_log("error: socket path \"%s/%s\" plus null terminator"
 | 
			
		||||
| 
						 | 
				
			
			@ -1230,23 +1214,10 @@ 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 && (wl_check_env_token(debug, "client") || wl_check_env_token(debug, "1"))) {
 | 
			
		||||
	if (debug && (strstr(debug, "client") || strstr(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) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1578,28 +1549,6 @@ 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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1614,16 +1563,12 @@ 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, "%s[%7u.%03u] %sdiscarded %s[%s]%s#%u%s.[event %d]%s"
 | 
			
		||||
 | 
			
		||||
			fprintf(stderr, "[%7u.%03u] discarded [%s]#%d.[event %d]"
 | 
			
		||||
				"(%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",
 | 
			
		||||
				debug_color ? WL_DEBUG_COLOR_MAGENTA : "", id,
 | 
			
		||||
				debug_color ? WL_DEBUG_COLOR_BLUE : "", opcode,
 | 
			
		||||
				debug_color ? WL_DEBUG_COLOR_RESET : "",
 | 
			
		||||
				id, opcode,
 | 
			
		||||
				num_zombie_fds, size);
 | 
			
		||||
		}
 | 
			
		||||
		if (num_zombie_fds > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -1708,7 +1653,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, debug_color);
 | 
			
		||||
				 id_from_object, queue->name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (proxy_destroyed) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1882,34 +1827,6 @@ 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
 | 
			
		||||
| 
						 | 
				
			
			@ -2025,142 +1942,20 @@ wl_display_cancel_read(struct wl_display *display)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
wl_display_poll(struct wl_display *display,
 | 
			
		||||
		short int events,
 | 
			
		||||
		const struct timespec *timeout)
 | 
			
		||||
wl_display_poll(struct wl_display *display, short int events)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct pollfd pfd[1];
 | 
			
		||||
	struct timespec now;
 | 
			
		||||
	struct timespec deadline = {0};
 | 
			
		||||
	struct timespec result;
 | 
			
		||||
	struct timespec *remaining_timeout = NULL;
 | 
			
		||||
 | 
			
		||||
	if (timeout) {
 | 
			
		||||
		clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
		timespec_add(&deadline, &now, timeout);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pfd[0].fd = display->fd;
 | 
			
		||||
	pfd[0].events = events;
 | 
			
		||||
	do {
 | 
			
		||||
		if (timeout) {
 | 
			
		||||
			clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
			timespec_sub_saturate(&result, &deadline, &now);
 | 
			
		||||
			remaining_timeout = &result;
 | 
			
		||||
		}
 | 
			
		||||
		ret = ppoll(pfd, 1, remaining_timeout, NULL);
 | 
			
		||||
		ret = poll(pfd, 1, -1);
 | 
			
		||||
	} while (ret == -1 && errno == EINTR);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Dispatch events in an event queue with a timeout
 | 
			
		||||
 *
 | 
			
		||||
 * \param display The display context object
 | 
			
		||||
 * \param queue The event queue to dispatch
 | 
			
		||||
 * \param timeout A timeout describing how long the call should block trying to
 | 
			
		||||
 * dispatch events
 | 
			
		||||
 * \return The number of dispatched events on success, -1 on failure
 | 
			
		||||
 *
 | 
			
		||||
 * This function behaves identical to wl_display_dispatch_queue() except
 | 
			
		||||
 * that it also takes a timeout and returns 0 if the timeout elapsed.
 | 
			
		||||
 *
 | 
			
		||||
 * Passing NULL as a timeout means an infinite timeout. An empty timespec
 | 
			
		||||
 * causes wl_display_dispatch_queue_timeout() to return immediately even if no
 | 
			
		||||
 * events have been dispatched.
 | 
			
		||||
 *
 | 
			
		||||
 * If a timeout is passed to wl_display_dispatch_queue_timeout() it is updated
 | 
			
		||||
 * to the remaining time.
 | 
			
		||||
 *
 | 
			
		||||
 * \sa wl_display_dispatch_queue()
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_display
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT int
 | 
			
		||||
wl_display_dispatch_queue_timeout(struct wl_display *display,
 | 
			
		||||
				  struct wl_event_queue *queue,
 | 
			
		||||
				  const struct timespec *timeout)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct timespec now;
 | 
			
		||||
	struct timespec deadline = {0};
 | 
			
		||||
	struct timespec result;
 | 
			
		||||
	struct timespec *remaining_timeout = NULL;
 | 
			
		||||
 | 
			
		||||
	if (timeout) {
 | 
			
		||||
		clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
		timespec_add(&deadline, &now, timeout);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (wl_display_prepare_read_queue(display, queue) == -1)
 | 
			
		||||
		return wl_display_dispatch_queue_pending(display, queue);
 | 
			
		||||
 | 
			
		||||
	while (true) {
 | 
			
		||||
		ret = wl_display_flush(display);
 | 
			
		||||
 | 
			
		||||
		if (ret != -1 || errno != EAGAIN)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		if (timeout) {
 | 
			
		||||
			clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
			timespec_sub_saturate(&result, &deadline, &now);
 | 
			
		||||
			remaining_timeout = &result;
 | 
			
		||||
		}
 | 
			
		||||
		ret = wl_display_poll(display, POLLOUT, remaining_timeout);
 | 
			
		||||
 | 
			
		||||
		if (ret <= 0) {
 | 
			
		||||
			wl_display_cancel_read(display);
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Don't stop if flushing hits an EPIPE; continue so we can read any
 | 
			
		||||
	 * protocol error that may have triggered it. */
 | 
			
		||||
	if (ret < 0 && errno != EPIPE) {
 | 
			
		||||
		wl_display_cancel_read(display);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (true) {
 | 
			
		||||
		if (timeout) {
 | 
			
		||||
			clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
			timespec_sub_saturate(&result, &deadline, &now);
 | 
			
		||||
			remaining_timeout = &result;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = wl_display_poll(display, POLLIN, remaining_timeout);
 | 
			
		||||
		if (ret <= 0) {
 | 
			
		||||
			wl_display_cancel_read(display);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = wl_display_read_events(display);
 | 
			
		||||
		if (ret == -1)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		ret = wl_display_dispatch_queue_pending(display, queue);
 | 
			
		||||
		if (ret != 0)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		/* We managed to read data from the display but there is no
 | 
			
		||||
		 * complete event to dispatch yet. Try reading again. */
 | 
			
		||||
		if (wl_display_prepare_read_queue(display, queue) == -1)
 | 
			
		||||
			return wl_display_dispatch_queue_pending(display, queue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT int
 | 
			
		||||
wl_display_dispatch_timeout(struct wl_display *display,
 | 
			
		||||
			    const struct timespec *timeout)
 | 
			
		||||
{
 | 
			
		||||
	return wl_display_dispatch_queue_timeout(display,
 | 
			
		||||
						 &display->default_queue,
 | 
			
		||||
						 timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Dispatch events in an event queue
 | 
			
		||||
 *
 | 
			
		||||
 * \param display The display context object
 | 
			
		||||
| 
						 | 
				
			
			@ -2192,8 +1987,8 @@ wl_display_dispatch_timeout(struct wl_display *display,
 | 
			
		|||
 * \note Since Wayland 1.5 the display has an extra queue
 | 
			
		||||
 * for its own events (i. e. delete_id). This queue is dispatched always,
 | 
			
		||||
 * no matter what queue we passed as an argument to this function.
 | 
			
		||||
 * That means that this function can return even when it has not dispatched any
 | 
			
		||||
 * event for the given queue.
 | 
			
		||||
 * That means that this function can return non-0 value even when it
 | 
			
		||||
 * haven't dispatched any event for the given queue.
 | 
			
		||||
 *
 | 
			
		||||
 * \sa wl_display_dispatch(), wl_display_dispatch_pending(),
 | 
			
		||||
 * wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue()
 | 
			
		||||
| 
						 | 
				
			
			@ -2206,10 +2001,37 @@ wl_display_dispatch_queue(struct wl_display *display,
 | 
			
		|||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = wl_display_dispatch_queue_timeout(display, queue, NULL);
 | 
			
		||||
	assert(ret == -1 || ret > 0);
 | 
			
		||||
	if (wl_display_prepare_read_queue(display, queue) == -1)
 | 
			
		||||
		return wl_display_dispatch_queue_pending(display, queue);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
	while (true) {
 | 
			
		||||
		ret = wl_display_flush(display);
 | 
			
		||||
 | 
			
		||||
		if (ret != -1 || errno != EAGAIN)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		if (wl_display_poll(display, POLLOUT) == -1) {
 | 
			
		||||
			wl_display_cancel_read(display);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Don't stop if flushing hits an EPIPE; continue so we can read any
 | 
			
		||||
	 * protocol error that may have triggered it. */
 | 
			
		||||
	if (ret < 0 && errno != EPIPE) {
 | 
			
		||||
		wl_display_cancel_read(display);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (wl_display_poll(display, POLLIN) == -1) {
 | 
			
		||||
		wl_display_cancel_read(display);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (wl_display_read_events(display) == -1)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	return wl_display_dispatch_queue_pending(display, queue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Dispatch pending events in an event queue
 | 
			
		||||
| 
						 | 
				
			
			@ -2240,34 +2062,6 @@ 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
 | 
			
		||||
| 
						 | 
				
			
			@ -2328,25 +2122,6 @@ 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
 | 
			
		||||
| 
						 | 
				
			
			@ -2628,20 +2403,6 @@ wl_proxy_get_class(struct wl_proxy *proxy)
 | 
			
		|||
	return proxy->object.interface->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Get the interface of a proxy object
 | 
			
		||||
 *
 | 
			
		||||
 * \param proxy The proxy object
 | 
			
		||||
 * \return The interface of the object associated with the proxy
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_proxy
 | 
			
		||||
 * \since 1.24
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT const struct wl_interface *
 | 
			
		||||
wl_proxy_get_interface(struct wl_proxy *proxy)
 | 
			
		||||
{
 | 
			
		||||
	return proxy->object.interface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Get the display of a proxy object
 | 
			
		||||
 *
 | 
			
		||||
 * \param proxy The proxy object
 | 
			
		||||
| 
						 | 
				
			
			@ -2692,9 +2453,7 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
 | 
			
		|||
	wl_list_remove(&proxy->queue_link);
 | 
			
		||||
 | 
			
		||||
	if (queue) {
 | 
			
		||||
		if (!(proxy->display == queue->display))
 | 
			
		||||
			wl_abort("Proxy and queue point to different "
 | 
			
		||||
				 "wl_displays");
 | 
			
		||||
		assert(proxy->display == queue->display);
 | 
			
		||||
		proxy->queue = queue;
 | 
			
		||||
	} else {
 | 
			
		||||
		proxy->queue = &proxy->display->default_queue;
 | 
			
		||||
| 
						 | 
				
			
			@ -2822,8 +2581,7 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper)
 | 
			
		|||
		wl_abort("Tried to destroy non-wrapper proxy with "
 | 
			
		||||
			 "wl_proxy_wrapper_destroy\n");
 | 
			
		||||
 | 
			
		||||
	if (!(wrapper->refcount == 1))
 | 
			
		||||
		wl_abort("Expected proxy wrapper's refcount to be 1\n");
 | 
			
		||||
	assert(wrapper->refcount == 1);
 | 
			
		||||
 | 
			
		||||
	pthread_mutex_lock(&wrapper->display->mutex);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,17 +49,6 @@
 | 
			
		|||
#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.
 | 
			
		||||
| 
						 | 
				
			
			@ -237,14 +226,11 @@ 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, int color);
 | 
			
		||||
		 const char *queue_name);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_closure_destroy(struct wl_closure *closure);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -227,7 +227,7 @@ typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
 | 
			
		|||
				      uint32_t version, uint32_t id);
 | 
			
		||||
 | 
			
		||||
uint32_t
 | 
			
		||||
wl_display_get_serial(const struct wl_display *display);
 | 
			
		||||
wl_display_get_serial(struct wl_display *display);
 | 
			
		||||
 | 
			
		||||
uint32_t
 | 
			
		||||
wl_display_next_serial(struct wl_display *display);
 | 
			
		||||
| 
						 | 
				
			
			@ -324,7 +324,7 @@ void
 | 
			
		|||
wl_client_flush(struct wl_client *client);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_client_get_credentials(const struct wl_client *client,
 | 
			
		||||
wl_client_get_credentials(struct wl_client *client,
 | 
			
		||||
			  pid_t *pid, uid_t *uid, gid_t *gid);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
| 
						 | 
				
			
			@ -550,10 +550,7 @@ void
 | 
			
		|||
wl_resource_queue_event_array(struct wl_resource *resource,
 | 
			
		||||
			      uint32_t opcode, union wl_argument *args);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_resource_post_error_vargs(struct wl_resource *resource,
 | 
			
		||||
			     uint32_t code, const char *msg, va_list argp);
 | 
			
		||||
 | 
			
		||||
/* msg is a printf format string, variable args are its args. */
 | 
			
		||||
void
 | 
			
		||||
wl_resource_post_error(struct wl_resource *resource,
 | 
			
		||||
		       uint32_t code, const char *msg, ...) WL_PRINTF(3, 4);
 | 
			
		||||
| 
						 | 
				
			
			@ -586,7 +583,7 @@ void
 | 
			
		|||
wl_resource_destroy(struct wl_resource *resource);
 | 
			
		||||
 | 
			
		||||
uint32_t
 | 
			
		||||
wl_resource_get_id(const struct wl_resource *resource);
 | 
			
		||||
wl_resource_get_id(struct wl_resource *resource);
 | 
			
		||||
 | 
			
		||||
struct wl_list *
 | 
			
		||||
wl_resource_get_link(struct wl_resource *resource);
 | 
			
		||||
| 
						 | 
				
			
			@ -607,7 +604,7 @@ void *
 | 
			
		|||
wl_resource_get_user_data(struct wl_resource *resource);
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
wl_resource_get_version(const struct wl_resource *resource);
 | 
			
		||||
wl_resource_get_version(struct wl_resource *resource);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_resource_set_destructor(struct wl_resource *resource,
 | 
			
		||||
| 
						 | 
				
			
			@ -617,12 +614,8 @@ int
 | 
			
		|||
wl_resource_instance_of(struct wl_resource *resource,
 | 
			
		||||
			const struct wl_interface *interface,
 | 
			
		||||
			const void *implementation);
 | 
			
		||||
 | 
			
		||||
const char *
 | 
			
		||||
wl_resource_get_class(const struct wl_resource *resource);
 | 
			
		||||
 | 
			
		||||
const struct wl_interface *
 | 
			
		||||
wl_resource_get_interface(struct wl_resource *resource);
 | 
			
		||||
wl_resource_get_class(struct wl_resource *resource);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_resource_add_destroy_listener(struct wl_resource *resource,
 | 
			
		||||
| 
						 | 
				
			
			@ -658,22 +651,16 @@ void *
 | 
			
		|||
wl_shm_buffer_get_data(struct wl_shm_buffer *buffer);
 | 
			
		||||
 | 
			
		||||
int32_t
 | 
			
		||||
wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer);
 | 
			
		||||
wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer);
 | 
			
		||||
 | 
			
		||||
uint32_t
 | 
			
		||||
wl_shm_buffer_get_format(const struct wl_shm_buffer *buffer);
 | 
			
		||||
wl_shm_buffer_get_format(struct wl_shm_buffer *buffer);
 | 
			
		||||
 | 
			
		||||
int32_t
 | 
			
		||||
wl_shm_buffer_get_width(const struct wl_shm_buffer *buffer);
 | 
			
		||||
wl_shm_buffer_get_width(struct wl_shm_buffer *buffer);
 | 
			
		||||
 | 
			
		||||
int32_t
 | 
			
		||||
wl_shm_buffer_get_height(const struct wl_shm_buffer *buffer);
 | 
			
		||||
 | 
			
		||||
struct wl_shm_buffer *
 | 
			
		||||
wl_shm_buffer_ref(struct wl_shm_buffer *buffer);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_shm_buffer_unref(struct wl_shm_buffer *buffer);
 | 
			
		||||
wl_shm_buffer_get_height(struct wl_shm_buffer *buffer);
 | 
			
		||||
 | 
			
		||||
struct wl_shm_pool *
 | 
			
		||||
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer);
 | 
			
		||||
| 
						 | 
				
			
			@ -687,11 +674,10 @@ wl_display_init_shm(struct wl_display *display);
 | 
			
		|||
uint32_t *
 | 
			
		||||
wl_display_add_shm_format(struct wl_display *display, uint32_t format);
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
struct wl_shm_buffer *
 | 
			
		||||
wl_shm_buffer_create(struct wl_client *client,
 | 
			
		||||
		     uint32_t id, int32_t width, int32_t height,
 | 
			
		||||
		     int32_t stride, uint32_t format);
 | 
			
		||||
		     int32_t stride, uint32_t format) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
wl_log_set_handler_server(wl_log_func_t handler);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@
 | 
			
		|||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/eventfd.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -149,7 +150,6 @@ struct wl_protocol_logger {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static int debug_server = 0;
 | 
			
		||||
static int debug_color = 0;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
log_closure(struct wl_resource *resource,
 | 
			
		||||
| 
						 | 
				
			
			@ -161,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, debug_color);
 | 
			
		||||
		wl_closure_print(closure, object, send, false, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	if (!wl_list_empty(&display->protocol_loggers)) {
 | 
			
		||||
		message.resource = resource;
 | 
			
		||||
| 
						 | 
				
			
			@ -288,16 +288,7 @@ wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
 | 
			
		|||
	wl_resource_queue_event_array(resource, opcode, args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Post a protocol error
 | 
			
		||||
 *
 | 
			
		||||
 * \param resource The resource object
 | 
			
		||||
 * \param code The error code
 | 
			
		||||
 * \param msg The error message format string
 | 
			
		||||
 * \param argp The format string argument list
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_resource
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT void
 | 
			
		||||
static void
 | 
			
		||||
wl_resource_post_error_vargs(struct wl_resource *resource,
 | 
			
		||||
			     uint32_t code, const char *msg, va_list argp)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -319,17 +310,9 @@ wl_resource_post_error_vargs(struct wl_resource *resource,
 | 
			
		|||
	wl_resource_post_event(client->display_resource,
 | 
			
		||||
			       WL_DISPLAY_ERROR, resource, code, buffer);
 | 
			
		||||
	client->error = true;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Post a protocol error
 | 
			
		||||
 *
 | 
			
		||||
 * \param resource The resource object
 | 
			
		||||
 * \param code The error code
 | 
			
		||||
 * \param msg The error message format string
 | 
			
		||||
 * \param ... The format string arguments
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_resource
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT void
 | 
			
		||||
wl_resource_post_error(struct wl_resource *resource,
 | 
			
		||||
		       uint32_t code, const char *msg, ...)
 | 
			
		||||
| 
						 | 
				
			
			@ -398,29 +381,6 @@ 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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -643,7 +603,7 @@ err_client:
 | 
			
		|||
 * \memberof wl_client
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT void
 | 
			
		||||
wl_client_get_credentials(const struct wl_client *client,
 | 
			
		||||
wl_client_get_credentials(struct wl_client *client,
 | 
			
		||||
			  pid_t *pid, uid_t *uid, gid_t *gid)
 | 
			
		||||
{
 | 
			
		||||
	if (pid)
 | 
			
		||||
| 
						 | 
				
			
			@ -823,7 +783,7 @@ wl_resource_destroy(struct wl_resource *resource)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT uint32_t
 | 
			
		||||
wl_resource_get_id(const struct wl_resource *resource)
 | 
			
		||||
wl_resource_get_id(struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
	return resource->object.id;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -877,7 +837,7 @@ wl_resource_get_user_data(struct wl_resource *resource)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT int
 | 
			
		||||
wl_resource_get_version(const struct wl_resource *resource)
 | 
			
		||||
wl_resource_get_version(struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
	return resource->version;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -924,25 +884,11 @@ wl_resource_get_destroy_listener(struct wl_resource *resource,
 | 
			
		|||
 * \memberof wl_resource
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT const char *
 | 
			
		||||
wl_resource_get_class(const struct wl_resource *resource)
 | 
			
		||||
wl_resource_get_class(struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
	return resource->object.interface->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Get the interface of a resource object
 | 
			
		||||
 *
 | 
			
		||||
 * \param resource The resource object
 | 
			
		||||
 * \return The interface of the object associated with the resource
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_resource
 | 
			
		||||
 * \since 1.24
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT const struct wl_interface *
 | 
			
		||||
wl_resource_get_interface(struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
	return resource->object.interface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add a listener to be called at the beginning of wl_client destruction
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -1192,23 +1138,10 @@ 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 && (wl_check_env_token(debug, "server") || wl_check_env_token(debug, "1"))) {
 | 
			
		||||
	if (debug && (strstr(debug, "server") || strstr(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)
 | 
			
		||||
| 
						 | 
				
			
			@ -1547,7 +1480,7 @@ wl_global_set_user_data(struct wl_global *global, void *data)
 | 
			
		|||
 * \memberof wl_display
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT uint32_t
 | 
			
		||||
wl_display_get_serial(const struct wl_display *display)
 | 
			
		||||
wl_display_get_serial(struct wl_display *display)
 | 
			
		||||
{
 | 
			
		||||
	return display->serial;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1584,8 +1517,7 @@ wl_display_terminate(struct wl_display *display)
 | 
			
		|||
	display->run = false;
 | 
			
		||||
 | 
			
		||||
	ret = write(display->terminate_efd, &terminate, sizeof(terminate));
 | 
			
		||||
	if (ret < 0 && errno != EAGAIN)
 | 
			
		||||
		wl_abort("Write failed at shutdown\n");
 | 
			
		||||
	assert (ret >= 0 || errno == EAGAIN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT void
 | 
			
		||||
| 
						 | 
				
			
			@ -1782,8 +1714,7 @@ wl_socket_init_for_display_name(struct wl_socket *s, const char *name)
 | 
			
		|||
	name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
 | 
			
		||||
			     "%s%s%s", runtime_dir, separator, name) + 1;
 | 
			
		||||
 | 
			
		||||
	if (!(name_size > 0))
 | 
			
		||||
		wl_abort("Error assigning path name for socket address\n");
 | 
			
		||||
	assert(name_size > 0);
 | 
			
		||||
	if (name_size > (int)sizeof s->addr.sun_path) {
 | 
			
		||||
		wl_log("error: socket path \"%s%s%s\" plus null terminator"
 | 
			
		||||
		       " exceeds 108 bytes\n", runtime_dir, separator, name);
 | 
			
		||||
| 
						 | 
				
			
			@ -1831,24 +1762,6 @@ _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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -2129,7 +2042,7 @@ wl_log_set_handler_server(wl_log_func_t handler)
 | 
			
		|||
 * \param func The function to call to log a new protocol message
 | 
			
		||||
 * \param user_data The user data pointer to pass to \a func
 | 
			
		||||
 *
 | 
			
		||||
 * \return The protocol logger object on success, NULL on failure.
 | 
			
		||||
 * \return The protol logger object on success, NULL on failure.
 | 
			
		||||
 *
 | 
			
		||||
 * \sa wl_protocol_logger_destroy
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -2570,10 +2483,9 @@ wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data)
 | 
			
		|||
 | 
			
		||||
/** \cond */ /* Deprecated functions below. */
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
uint32_t
 | 
			
		||||
wl_client_add_resource(struct wl_client *client,
 | 
			
		||||
		       struct wl_resource *resource);
 | 
			
		||||
		       struct wl_resource *resource) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_EXPORT uint32_t
 | 
			
		||||
wl_client_add_resource(struct wl_client *client,
 | 
			
		||||
| 
						 | 
				
			
			@ -2602,12 +2514,11 @@ wl_client_add_resource(struct wl_client *client,
 | 
			
		|||
	return resource->object.id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
struct wl_resource *
 | 
			
		||||
wl_client_add_object(struct wl_client *client,
 | 
			
		||||
		     const struct wl_interface *interface,
 | 
			
		||||
		     const void *implementation,
 | 
			
		||||
		     uint32_t id, void *data);
 | 
			
		||||
		     uint32_t id, void *data) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_EXPORT struct wl_resource *
 | 
			
		||||
wl_client_add_object(struct wl_client *client,
 | 
			
		||||
| 
						 | 
				
			
			@ -2626,11 +2537,10 @@ wl_client_add_object(struct wl_client *client,
 | 
			
		|||
	return resource;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
struct wl_resource *
 | 
			
		||||
wl_client_new_object(struct wl_client *client,
 | 
			
		||||
		     const struct wl_interface *interface,
 | 
			
		||||
		     const void *implementation, void *data);
 | 
			
		||||
		     const void *implementation, void *data) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_EXPORT struct wl_resource *
 | 
			
		||||
wl_client_new_object(struct wl_client *client,
 | 
			
		||||
| 
						 | 
				
			
			@ -2689,11 +2599,10 @@ wl_client_get_user_data(struct wl_client *client)
 | 
			
		|||
	return client->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
struct wl_global *
 | 
			
		||||
wl_display_add_global(struct wl_display *display,
 | 
			
		||||
		      const struct wl_interface *interface,
 | 
			
		||||
		      void *data, wl_global_bind_func_t bind);
 | 
			
		||||
		      void *data, wl_global_bind_func_t bind) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_EXPORT struct wl_global *
 | 
			
		||||
wl_display_add_global(struct wl_display *display,
 | 
			
		||||
| 
						 | 
				
			
			@ -2703,10 +2612,9 @@ wl_display_add_global(struct wl_display *display,
 | 
			
		|||
	return wl_global_create(display, interface, interface->version, data, bind);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
void
 | 
			
		||||
wl_display_remove_global(struct wl_display *display,
 | 
			
		||||
			 struct wl_global *global);
 | 
			
		||||
			 struct wl_global *global) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_EXPORT void
 | 
			
		||||
wl_display_remove_global(struct wl_display *display, struct wl_global *global)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,35 +70,30 @@ struct wl_resource {
 | 
			
		|||
	void *data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
uint32_t
 | 
			
		||||
wl_client_add_resource(struct wl_client *client,
 | 
			
		||||
		       struct wl_resource *resource);
 | 
			
		||||
		       struct wl_resource *resource) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
struct wl_resource *
 | 
			
		||||
wl_client_add_object(struct wl_client *client,
 | 
			
		||||
		     const struct wl_interface *interface,
 | 
			
		||||
		     const void *implementation,
 | 
			
		||||
		     uint32_t id, void *data);
 | 
			
		||||
		     uint32_t id, void *data) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
struct wl_resource *
 | 
			
		||||
wl_client_new_object(struct wl_client *client,
 | 
			
		||||
		     const struct wl_interface *interface,
 | 
			
		||||
		     const void *implementation, void *data);
 | 
			
		||||
		     const void *implementation, void *data) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
struct wl_global *
 | 
			
		||||
wl_display_add_global(struct wl_display *display,
 | 
			
		||||
		      const struct wl_interface *interface,
 | 
			
		||||
		      void *data,
 | 
			
		||||
		      wl_global_bind_func_t bind);
 | 
			
		||||
		      wl_global_bind_func_t bind) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
WL_DEPRECATED
 | 
			
		||||
void
 | 
			
		||||
wl_display_remove_global(struct wl_display *display,
 | 
			
		||||
			 struct wl_global *global);
 | 
			
		||||
			 struct wl_global *global) WL_DEPRECATED;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,7 @@
 | 
			
		|||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -84,10 +85,6 @@ struct wl_shm_pool {
 | 
			
		|||
 */
 | 
			
		||||
struct wl_shm_buffer {
 | 
			
		||||
	struct wl_resource *resource;
 | 
			
		||||
	int internal_refcount;
 | 
			
		||||
	int external_refcount;
 | 
			
		||||
	struct wl_client *client;
 | 
			
		||||
	struct wl_listener client_destroy_listener;
 | 
			
		||||
	int32_t width, height;
 | 
			
		||||
	int32_t stride;
 | 
			
		||||
	uint32_t format;
 | 
			
		||||
| 
						 | 
				
			
			@ -147,16 +144,12 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external)
 | 
			
		|||
{
 | 
			
		||||
	if (external) {
 | 
			
		||||
		pool->external_refcount--;
 | 
			
		||||
		if (pool->external_refcount < 0)
 | 
			
		||||
			wl_abort("Requested to unref an external reference to "
 | 
			
		||||
				 "pool but none found\n");
 | 
			
		||||
		assert(pool->external_refcount >= 0);
 | 
			
		||||
		if (pool->external_refcount == 0)
 | 
			
		||||
			shm_pool_finish_resize(pool);
 | 
			
		||||
	} else {
 | 
			
		||||
		pool->internal_refcount--;
 | 
			
		||||
		if (pool->internal_refcount < 0)
 | 
			
		||||
			wl_abort("Requested to unref an internal reference to "
 | 
			
		||||
				 "pool but none found\n");
 | 
			
		||||
		assert(pool->internal_refcount >= 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pool->internal_refcount + pool->external_refcount > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -169,38 +162,13 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external)
 | 
			
		|||
	free(pool);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shm_buffer_unref(struct wl_shm_buffer *buffer, bool external)
 | 
			
		||||
{
 | 
			
		||||
	if (external) {
 | 
			
		||||
		buffer->external_refcount--;
 | 
			
		||||
		if (buffer->external_refcount < 0) {
 | 
			
		||||
			wl_abort("Requested to unref an external reference to "
 | 
			
		||||
				 "buffer but none found\n");
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		buffer->internal_refcount--;
 | 
			
		||||
		if (buffer->internal_refcount < 0) {
 | 
			
		||||
			wl_abort("Requested to unref an internal reference to "
 | 
			
		||||
				 "buffer but none found\n");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (buffer->internal_refcount + buffer->external_refcount > 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (buffer->client)
 | 
			
		||||
		wl_list_remove(&buffer->client_destroy_listener.link);
 | 
			
		||||
	shm_pool_unref(buffer->pool, false);
 | 
			
		||||
	free(buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
destroy_buffer(struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
	struct wl_shm_buffer *buffer = wl_resource_get_user_data(resource);
 | 
			
		||||
 | 
			
		||||
	shm_buffer_unref(buffer, false);
 | 
			
		||||
	shm_pool_unref(buffer->pool, false);
 | 
			
		||||
	free(buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -234,17 +202,6 @@ format_is_supported(struct wl_client *client, uint32_t format)
 | 
			
		|||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shm_buffer_client_destroy_notify(struct wl_listener *listener, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct wl_shm_buffer *buffer =
 | 
			
		||||
		wl_container_of(listener, buffer, client_destroy_listener);
 | 
			
		||||
 | 
			
		||||
	buffer->client = NULL;
 | 
			
		||||
	wl_list_remove(&buffer->client_destroy_listener.link);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
 | 
			
		||||
		       uint32_t id, int32_t offset,
 | 
			
		||||
| 
						 | 
				
			
			@ -277,14 +234,6 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buffer->client = client;
 | 
			
		||||
	buffer->client_destroy_listener.notify =
 | 
			
		||||
		shm_buffer_client_destroy_notify;
 | 
			
		||||
	wl_client_add_destroy_listener(buffer->client,
 | 
			
		||||
				       &buffer->client_destroy_listener);
 | 
			
		||||
 | 
			
		||||
	buffer->internal_refcount = 1;
 | 
			
		||||
	buffer->external_refcount = 0;
 | 
			
		||||
	buffer->width = width;
 | 
			
		||||
	buffer->height = height;
 | 
			
		||||
	buffer->format = format;
 | 
			
		||||
| 
						 | 
				
			
			@ -492,7 +441,7 @@ wl_shm_buffer_get(struct wl_resource *resource)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT int32_t
 | 
			
		||||
wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer)
 | 
			
		||||
wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
	return buffer->stride;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -509,8 +458,8 @@ wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer)
 | 
			
		|||
 * SIGBUS signals. This can happen if the client claims that the
 | 
			
		||||
 * buffer is larger than it is or if something truncates the
 | 
			
		||||
 * underlying file. To prevent this signal from causing the compositor
 | 
			
		||||
 * to crash you should call wl_shm_buffer_begin_access() and
 | 
			
		||||
 * wl_shm_buffer_end_access() around code that reads from the memory.
 | 
			
		||||
 * to crash you should call wl_shm_buffer_begin_access and
 | 
			
		||||
 * wl_shm_buffer_end_access around code that reads from the memory.
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_shm_buffer
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -526,62 +475,23 @@ wl_shm_buffer_get_data(struct wl_shm_buffer *buffer)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT uint32_t
 | 
			
		||||
wl_shm_buffer_get_format(const struct wl_shm_buffer *buffer)
 | 
			
		||||
wl_shm_buffer_get_format(struct wl_shm_buffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
	return buffer->format;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT int32_t
 | 
			
		||||
wl_shm_buffer_get_width(const struct wl_shm_buffer *buffer)
 | 
			
		||||
wl_shm_buffer_get_width(struct wl_shm_buffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
	return buffer->width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WL_EXPORT int32_t
 | 
			
		||||
wl_shm_buffer_get_height(const struct wl_shm_buffer *buffer)
 | 
			
		||||
wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
	return buffer->height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Reference a shm_buffer
 | 
			
		||||
 *
 | 
			
		||||
 * \param buffer The buffer object
 | 
			
		||||
 *
 | 
			
		||||
 * Returns a pointer to the buffer and increases the refcount.
 | 
			
		||||
 *
 | 
			
		||||
 * The compositor must remember to call wl_shm_buffer_unref() when
 | 
			
		||||
 * it no longer needs the reference to ensure proper destruction
 | 
			
		||||
 * of the buffer.
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_shm_buffer
 | 
			
		||||
 * \sa wl_shm_buffer_unref
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT struct wl_shm_buffer *
 | 
			
		||||
wl_shm_buffer_ref(struct wl_shm_buffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
	buffer->external_refcount++;
 | 
			
		||||
	return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Unreference a shm_buffer
 | 
			
		||||
 *
 | 
			
		||||
 * \param buffer The buffer object
 | 
			
		||||
 *
 | 
			
		||||
 * Drops a reference to a buffer object.
 | 
			
		||||
 *
 | 
			
		||||
 * This is only necessary if the compositor has explicitly
 | 
			
		||||
 * taken a reference with wl_shm_buffer_ref(), otherwise
 | 
			
		||||
 * the buffer will be automatically destroyed when appropriate.
 | 
			
		||||
 *
 | 
			
		||||
 * \memberof wl_shm_buffer
 | 
			
		||||
 * \sa wl_shm_buffer_ref
 | 
			
		||||
 */
 | 
			
		||||
WL_EXPORT void
 | 
			
		||||
wl_shm_buffer_unref(struct wl_shm_buffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
	shm_buffer_unref(buffer, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Get a reference to a shm_buffer's shm_pool
 | 
			
		||||
 *
 | 
			
		||||
 * \param buffer The buffer object
 | 
			
		||||
| 
						 | 
				
			
			@ -589,7 +499,7 @@ wl_shm_buffer_unref(struct wl_shm_buffer *buffer)
 | 
			
		|||
 * Returns a pointer to a buffer's shm_pool and increases the
 | 
			
		||||
 * shm_pool refcount.
 | 
			
		||||
 *
 | 
			
		||||
 * The compositor must remember to call wl_shm_pool_unref() when
 | 
			
		||||
 * The compositor must remember to call wl_shm_pool_unref when
 | 
			
		||||
 * it no longer needs the reference to ensure proper destruction
 | 
			
		||||
 * of the pool.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -599,6 +509,9 @@ wl_shm_buffer_unref(struct wl_shm_buffer *buffer)
 | 
			
		|||
WL_EXPORT struct wl_shm_pool *
 | 
			
		||||
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
	assert(buffer->pool->internal_refcount +
 | 
			
		||||
	       buffer->pool->external_refcount);
 | 
			
		||||
 | 
			
		||||
	buffer->pool->external_refcount++;
 | 
			
		||||
	return buffer->pool;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -700,7 +613,7 @@ init_sigbus_data_key(void)
 | 
			
		|||
 * In order to make the compositor robust against clients that change
 | 
			
		||||
 * the size of the underlying file or lie about its size, you should
 | 
			
		||||
 * protect access to the buffer by calling this function before
 | 
			
		||||
 * reading from the memory and call wl_shm_buffer_end_access()
 | 
			
		||||
 * reading from the memory and call wl_shm_buffer_end_access
 | 
			
		||||
 * afterwards. This will install a signal handler for SIGBUS which
 | 
			
		||||
 * will prevent the compositor from crashing.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -711,15 +624,15 @@ init_sigbus_data_key(void)
 | 
			
		|||
 *
 | 
			
		||||
 * If a SIGBUS signal is received for an address within the range of
 | 
			
		||||
 * the SHM pool of the given buffer then the client will be sent an
 | 
			
		||||
 * error event when wl_shm_buffer_end_access() is called. If the signal
 | 
			
		||||
 * error event when wl_shm_buffer_end_access is called. If the signal
 | 
			
		||||
 * is for an address outside that range then the signal handler will
 | 
			
		||||
 * reraise the signal which would will likely cause the compositor to
 | 
			
		||||
 * terminate.
 | 
			
		||||
 *
 | 
			
		||||
 * It is safe to nest calls to these functions as long as the nested
 | 
			
		||||
 * calls are all accessing the same pool. The number of calls to
 | 
			
		||||
 * wl_shm_buffer_end_access() must match the number of calls to
 | 
			
		||||
 * wl_shm_buffer_begin_access(). These functions are thread-safe and it
 | 
			
		||||
 * calls are all accessing the same buffer. The number of calls to
 | 
			
		||||
 * wl_shm_buffer_end_access must match the number of calls to
 | 
			
		||||
 * wl_shm_buffer_begin_access. These functions are thread-safe and it
 | 
			
		||||
 * is allowed to simultaneously access different buffers or the same
 | 
			
		||||
 * buffer from multiple threads.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -745,19 +658,18 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
 | 
			
		|||
		pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(sigbus_data->current_pool == NULL ||
 | 
			
		||||
	       sigbus_data->current_pool == pool))
 | 
			
		||||
		wl_abort("Incorrect pool passed for current thread\n");
 | 
			
		||||
	assert(sigbus_data->current_pool == NULL ||
 | 
			
		||||
	       sigbus_data->current_pool == pool);
 | 
			
		||||
 | 
			
		||||
	sigbus_data->current_pool = pool;
 | 
			
		||||
	sigbus_data->access_count++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Ends the access to a buffer started by wl_shm_buffer_begin_access()
 | 
			
		||||
/** Ends the access to a buffer started by wl_shm_buffer_begin_access
 | 
			
		||||
 *
 | 
			
		||||
 * \param buffer The SHM buffer
 | 
			
		||||
 *
 | 
			
		||||
 * This should be called after wl_shm_buffer_begin_access() once the
 | 
			
		||||
 * This should be called after wl_shm_buffer_begin_access once the
 | 
			
		||||
 * buffer is no longer being accessed. If a SIGBUS signal was
 | 
			
		||||
 * generated in-between these two calls then the resource for the
 | 
			
		||||
 * given buffer will be sent an error.
 | 
			
		||||
| 
						 | 
				
			
			@ -774,22 +686,13 @@ wl_shm_buffer_end_access(struct wl_shm_buffer *buffer)
 | 
			
		|||
		return;
 | 
			
		||||
 | 
			
		||||
	sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
 | 
			
		||||
	if (!(sigbus_data && sigbus_data->access_count >= 1))
 | 
			
		||||
		wl_abort("sigbus_data is NULL or wl_shm_buffer_begin_access "
 | 
			
		||||
			 "wasn't called before\n");
 | 
			
		||||
	assert(sigbus_data && sigbus_data->access_count >= 1);
 | 
			
		||||
 | 
			
		||||
	if (--sigbus_data->access_count == 0) {
 | 
			
		||||
		if (sigbus_data->fallback_mapping_used) {
 | 
			
		||||
			if (buffer->resource) {
 | 
			
		||||
				wl_resource_post_error(buffer->resource,
 | 
			
		||||
						       WL_SHM_ERROR_INVALID_FD,
 | 
			
		||||
						       "error accessing SHM buffer");
 | 
			
		||||
			} else if (buffer->client) {
 | 
			
		||||
				wl_client_post_implementation_error(buffer->client,
 | 
			
		||||
								    "Error accessing SHM buffer of a "
 | 
			
		||||
								    "wl_buffer resource which has "
 | 
			
		||||
								    "already been destroyed");
 | 
			
		||||
			}
 | 
			
		||||
			wl_resource_post_error(buffer->resource,
 | 
			
		||||
					       WL_SHM_ERROR_INVALID_FD,
 | 
			
		||||
					       "error accessing SHM buffer");
 | 
			
		||||
			sigbus_data->fallback_mapping_used = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ extern "C" {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
/** Deprecated attribute */
 | 
			
		||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || (defined(__cplusplus) && __cplusplus >= 201402L)
 | 
			
		||||
#if __STDC_VERSION__ >= 202311L
 | 
			
		||||
#define WL_DEPRECATED [[deprecated]]
 | 
			
		||||
#elif defined(__GNUC__) && __GNUC__ >= 4
 | 
			
		||||
#define WL_DEPRECATED __attribute__ ((deprecated))
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +70,7 @@ extern "C" {
 | 
			
		|||
#define WL_PRINTF(x, y)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
 | 
			
		||||
#if __STDC_VERSION__ >= 202311L
 | 
			
		||||
#define WL_TYPEOF(expr) typeof(expr)
 | 
			
		||||
#else
 | 
			
		||||
#define WL_TYPEOF(expr) __typeof__(expr)
 | 
			
		||||
| 
						 | 
				
			
			@ -90,14 +90,6 @@ 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
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -643,7 +635,7 @@ wl_fixed_to_double(wl_fixed_t f)
 | 
			
		|||
static inline wl_fixed_t
 | 
			
		||||
wl_fixed_from_double(double d)
 | 
			
		||||
{
 | 
			
		||||
	return (wl_fixed_t) (round(d * 256.0));
 | 
			
		||||
	return (wl_fixed_t) (d * 256.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -686,7 +686,7 @@ TEST(connection_marshal_big_enough)
 | 
			
		|||
 | 
			
		||||
TEST(connection_marshal_unbounded_boundary_size)
 | 
			
		||||
{
 | 
			
		||||
	/* A string of length 8178 requires a buffer size of exactly 2^13. */
 | 
			
		||||
	/* A string of lenth 8178 requires a buffer size of exactly 2^13. */
 | 
			
		||||
	struct marshal_data data;
 | 
			
		||||
	char *big_string = malloc(8178);
 | 
			
		||||
	assert(big_string);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -901,10 +901,6 @@ enum wl_display_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_DISPLAY_ERROR_NO_MEMORY = 2,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_DISPLAY_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_DISPLAY_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_DISPLAY_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_display
 | 
			
		||||
 * Validate a wl_display error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -925,7 +921,7 @@ wl_display_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_DISPLAY_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_DISPLAY_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_display
 | 
			
		||||
| 
						 | 
				
			
			@ -1198,10 +1194,6 @@ enum wl_shm_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SHM_ERROR_INVALID_FD = 2,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SHM_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHM_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_SHM_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shm
 | 
			
		||||
 * Validate a wl_shm error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -1222,7 +1214,7 @@ wl_shm_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SHM_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SHM_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHM_FORMAT_ENUM
 | 
			
		||||
#define WL_SHM_FORMAT_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -1474,10 +1466,6 @@ enum wl_shm_format {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SHM_FORMAT_YVU444 = 0x34325659,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SHM_FORMAT_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHM_FORMAT_ENUM_IS_VALID
 | 
			
		||||
#define WL_SHM_FORMAT_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shm
 | 
			
		||||
 * Validate a wl_shm format value.
 | 
			
		||||
| 
						 | 
				
			
			@ -1608,7 +1596,7 @@ wl_shm_format_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SHM_FORMAT_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SHM_FORMAT_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shm
 | 
			
		||||
| 
						 | 
				
			
			@ -1718,10 +1706,6 @@ enum wl_data_offer_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_DATA_OFFER_ERROR_INVALID_OFFER = 3,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_DATA_OFFER_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_DATA_OFFER_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_DATA_OFFER_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_offer
 | 
			
		||||
 * Validate a wl_data_offer error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -1744,7 +1728,7 @@ wl_data_offer_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_DATA_OFFER_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_DATA_OFFER_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_offer
 | 
			
		||||
| 
						 | 
				
			
			@ -1956,10 +1940,6 @@ enum wl_data_source_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_DATA_SOURCE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_DATA_SOURCE_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_DATA_SOURCE_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_source
 | 
			
		||||
 * Validate a wl_data_source error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -1978,7 +1958,7 @@ wl_data_source_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_DATA_SOURCE_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_DATA_SOURCE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_source
 | 
			
		||||
| 
						 | 
				
			
			@ -2150,10 +2130,6 @@ enum wl_data_device_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_DATA_DEVICE_ERROR_ROLE = 0,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_DATA_DEVICE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_DATA_DEVICE_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_DATA_DEVICE_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_device
 | 
			
		||||
 * Validate a wl_data_device error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -2170,7 +2146,7 @@ wl_data_device_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_DATA_DEVICE_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_DATA_DEVICE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_device
 | 
			
		||||
| 
						 | 
				
			
			@ -2411,10 +2387,6 @@ enum wl_data_device_manager_dnd_action {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID
 | 
			
		||||
#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_device_manager
 | 
			
		||||
 * Validate a wl_data_device_manager dnd_action value.
 | 
			
		||||
| 
						 | 
				
			
			@ -2424,18 +2396,20 @@ enum wl_data_device_manager_dnd_action {
 | 
			
		|||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
wl_data_device_manager_dnd_action_is_valid(uint32_t value, uint32_t version) {
 | 
			
		||||
	uint32_t valid = 0;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
 | 
			
		||||
	return (value & ~valid) == 0;
 | 
			
		||||
	switch (value) {
 | 
			
		||||
	case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	default:
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_data_device_manager
 | 
			
		||||
| 
						 | 
				
			
			@ -2482,10 +2456,6 @@ enum wl_shell_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SHELL_ERROR_ROLE = 0,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SHELL_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHELL_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_SHELL_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shell
 | 
			
		||||
 * Validate a wl_shell error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -2502,7 +2472,7 @@ wl_shell_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SHELL_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SHELL_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shell
 | 
			
		||||
| 
						 | 
				
			
			@ -2581,10 +2551,6 @@ enum wl_shell_surface_resize {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID
 | 
			
		||||
#define WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shell_surface
 | 
			
		||||
 * Validate a wl_shell_surface resize value.
 | 
			
		||||
| 
						 | 
				
			
			@ -2594,28 +2560,30 @@ enum wl_shell_surface_resize {
 | 
			
		|||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
wl_shell_surface_resize_is_valid(uint32_t value, uint32_t version) {
 | 
			
		||||
	uint32_t valid = 0;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_NONE;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_TOP;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_LEFT;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_RIGHT;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
 | 
			
		||||
	return (value & ~valid) == 0;
 | 
			
		||||
	switch (value) {
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_NONE:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_TOP:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_BOTTOM:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_LEFT:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_TOP_LEFT:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_RIGHT:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	default:
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
 | 
			
		||||
#define WL_SHELL_SURFACE_TRANSIENT_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -2632,10 +2600,6 @@ enum wl_shell_surface_transient {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID
 | 
			
		||||
#define WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shell_surface
 | 
			
		||||
 * Validate a wl_shell_surface transient value.
 | 
			
		||||
| 
						 | 
				
			
			@ -2645,12 +2609,14 @@ enum wl_shell_surface_transient {
 | 
			
		|||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
wl_shell_surface_transient_is_valid(uint32_t value, uint32_t version) {
 | 
			
		||||
	uint32_t valid = 0;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
 | 
			
		||||
	return (value & ~valid) == 0;
 | 
			
		||||
	switch (value) {
 | 
			
		||||
	case WL_SHELL_SURFACE_TRANSIENT_INACTIVE:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	default:
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
 | 
			
		||||
#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -2680,10 +2646,6 @@ enum wl_shell_surface_fullscreen_method {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID
 | 
			
		||||
#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shell_surface
 | 
			
		||||
 * Validate a wl_shell_surface fullscreen_method value.
 | 
			
		||||
| 
						 | 
				
			
			@ -2706,7 +2668,7 @@ wl_shell_surface_fullscreen_method_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_shell_surface
 | 
			
		||||
| 
						 | 
				
			
			@ -3038,10 +3000,6 @@ enum wl_surface_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SURFACE_ERROR_INVALID_TRANSFORM = 1,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SURFACE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SURFACE_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_SURFACE_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_surface
 | 
			
		||||
 * Validate a wl_surface error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -3060,7 +3018,7 @@ wl_surface_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SURFACE_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SURFACE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_surface
 | 
			
		||||
| 
						 | 
				
			
			@ -3519,10 +3477,6 @@ enum wl_seat_capability {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SEAT_CAPABILITY_TOUCH = 4,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SEAT_CAPABILITY_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SEAT_CAPABILITY_ENUM_IS_VALID
 | 
			
		||||
#define WL_SEAT_CAPABILITY_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_seat
 | 
			
		||||
 * Validate a wl_seat capability value.
 | 
			
		||||
| 
						 | 
				
			
			@ -3532,16 +3486,18 @@ enum wl_seat_capability {
 | 
			
		|||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
wl_seat_capability_is_valid(uint32_t value, uint32_t version) {
 | 
			
		||||
	uint32_t valid = 0;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SEAT_CAPABILITY_POINTER;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SEAT_CAPABILITY_KEYBOARD;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_SEAT_CAPABILITY_TOUCH;
 | 
			
		||||
	return (value & ~valid) == 0;
 | 
			
		||||
	switch (value) {
 | 
			
		||||
	case WL_SEAT_CAPABILITY_POINTER:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SEAT_CAPABILITY_KEYBOARD:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_SEAT_CAPABILITY_TOUCH:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	default:
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SEAT_CAPABILITY_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SEAT_CAPABILITY_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_seat
 | 
			
		||||
| 
						 | 
				
			
			@ -3665,10 +3621,6 @@ enum wl_pointer_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_POINTER_ERROR_ROLE = 0,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_POINTER_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_POINTER_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_POINTER_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_pointer
 | 
			
		||||
 * Validate a wl_pointer error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -3685,7 +3637,7 @@ wl_pointer_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_POINTER_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_POINTER_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_POINTER_BUTTON_STATE_ENUM
 | 
			
		||||
#define WL_POINTER_BUTTON_STATE_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -3706,10 +3658,6 @@ enum wl_pointer_button_state {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_POINTER_BUTTON_STATE_PRESSED = 1,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_POINTER_BUTTON_STATE_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_POINTER_BUTTON_STATE_ENUM_IS_VALID
 | 
			
		||||
#define WL_POINTER_BUTTON_STATE_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_pointer
 | 
			
		||||
 * Validate a wl_pointer button_state value.
 | 
			
		||||
| 
						 | 
				
			
			@ -3728,7 +3676,7 @@ wl_pointer_button_state_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_POINTER_BUTTON_STATE_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_POINTER_BUTTON_STATE_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_POINTER_AXIS_ENUM
 | 
			
		||||
#define WL_POINTER_AXIS_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -3748,10 +3696,6 @@ enum wl_pointer_axis {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_POINTER_AXIS_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_POINTER_AXIS_ENUM_IS_VALID
 | 
			
		||||
#define WL_POINTER_AXIS_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_pointer
 | 
			
		||||
 * Validate a wl_pointer axis value.
 | 
			
		||||
| 
						 | 
				
			
			@ -3770,7 +3714,7 @@ wl_pointer_axis_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_POINTER_AXIS_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_POINTER_AXIS_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_POINTER_AXIS_SOURCE_ENUM
 | 
			
		||||
#define WL_POINTER_AXIS_SOURCE_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -3818,10 +3762,6 @@ enum wl_pointer_axis_source {
 | 
			
		|||
 * @ingroup iface_wl_pointer
 | 
			
		||||
 */
 | 
			
		||||
#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
 | 
			
		||||
#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID
 | 
			
		||||
#define WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_pointer
 | 
			
		||||
 * Validate a wl_pointer axis_source value.
 | 
			
		||||
| 
						 | 
				
			
			@ -3844,7 +3784,7 @@ wl_pointer_axis_source_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_pointer
 | 
			
		||||
| 
						 | 
				
			
			@ -4105,10 +4045,6 @@ enum wl_keyboard_keymap_format {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID
 | 
			
		||||
#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_keyboard
 | 
			
		||||
 * Validate a wl_keyboard keymap_format value.
 | 
			
		||||
| 
						 | 
				
			
			@ -4127,7 +4063,7 @@ wl_keyboard_keymap_format_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_KEYBOARD_KEY_STATE_ENUM
 | 
			
		||||
#define WL_KEYBOARD_KEY_STATE_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -4147,10 +4083,6 @@ enum wl_keyboard_key_state {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_KEYBOARD_KEY_STATE_PRESSED = 1,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID
 | 
			
		||||
#define WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_keyboard
 | 
			
		||||
 * Validate a wl_keyboard key_state value.
 | 
			
		||||
| 
						 | 
				
			
			@ -4169,7 +4101,7 @@ wl_keyboard_key_state_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_keyboard
 | 
			
		||||
| 
						 | 
				
			
			@ -4495,10 +4427,6 @@ enum wl_output_subpixel {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID
 | 
			
		||||
#define WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_output
 | 
			
		||||
 * Validate a wl_output subpixel value.
 | 
			
		||||
| 
						 | 
				
			
			@ -4525,7 +4453,7 @@ wl_output_subpixel_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_OUTPUT_TRANSFORM_ENUM
 | 
			
		||||
#define WL_OUTPUT_TRANSFORM_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -4579,10 +4507,6 @@ enum wl_output_transform {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_OUTPUT_TRANSFORM_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_OUTPUT_TRANSFORM_ENUM_IS_VALID
 | 
			
		||||
#define WL_OUTPUT_TRANSFORM_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_output
 | 
			
		||||
 * Validate a wl_output transform value.
 | 
			
		||||
| 
						 | 
				
			
			@ -4613,7 +4537,7 @@ wl_output_transform_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_OUTPUT_TRANSFORM_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_OUTPUT_TRANSFORM_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_OUTPUT_MODE_ENUM
 | 
			
		||||
#define WL_OUTPUT_MODE_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -4634,10 +4558,6 @@ enum wl_output_mode {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_OUTPUT_MODE_PREFERRED = 0x2,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_OUTPUT_MODE_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_OUTPUT_MODE_ENUM_IS_VALID
 | 
			
		||||
#define WL_OUTPUT_MODE_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_output
 | 
			
		||||
 * Validate a wl_output mode value.
 | 
			
		||||
| 
						 | 
				
			
			@ -4647,14 +4567,16 @@ enum wl_output_mode {
 | 
			
		|||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
wl_output_mode_is_valid(uint32_t value, uint32_t version) {
 | 
			
		||||
	uint32_t valid = 0;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_OUTPUT_MODE_CURRENT;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= WL_OUTPUT_MODE_PREFERRED;
 | 
			
		||||
	return (value & ~valid) == 0;
 | 
			
		||||
	switch (value) {
 | 
			
		||||
	case WL_OUTPUT_MODE_CURRENT:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	case WL_OUTPUT_MODE_PREFERRED:
 | 
			
		||||
		return version >= 1;
 | 
			
		||||
	default:
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_OUTPUT_MODE_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_OUTPUT_MODE_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_output
 | 
			
		||||
| 
						 | 
				
			
			@ -4822,10 +4744,6 @@ enum wl_subcompositor_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_subcompositor
 | 
			
		||||
 * Validate a wl_subcompositor error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -4842,7 +4760,7 @@ wl_subcompositor_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_subcompositor
 | 
			
		||||
| 
						 | 
				
			
			@ -4897,10 +4815,6 @@ enum wl_subsurface_error {
 | 
			
		|||
	 */
 | 
			
		||||
	WL_SUBSURFACE_ERROR_BAD_SURFACE = 0,
 | 
			
		||||
};
 | 
			
		||||
#endif /* WL_SUBSURFACE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef WL_SUBSURFACE_ERROR_ENUM_IS_VALID
 | 
			
		||||
#define WL_SUBSURFACE_ERROR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_subsurface
 | 
			
		||||
 * Validate a wl_subsurface error value.
 | 
			
		||||
| 
						 | 
				
			
			@ -4917,7 +4831,7 @@ wl_subsurface_error_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* WL_SUBSURFACE_ERROR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* WL_SUBSURFACE_ERROR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_wl_subsurface
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,29 +106,6 @@ enum intf_A_foo {
 | 
			
		|||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_BAR_ENUM
 | 
			
		||||
#define INTF_A_BAR_ENUM
 | 
			
		||||
enum intf_A_bar {
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the first
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_FIRST = 0x01,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the second
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_SECOND = 0x02,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the third
 | 
			
		||||
	 * @since 2
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_THIRD = 0x04,
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 */
 | 
			
		||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_BAR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 * @struct intf_A_listener
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,29 +106,6 @@ enum intf_A_foo {
 | 
			
		|||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_BAR_ENUM
 | 
			
		||||
#define INTF_A_BAR_ENUM
 | 
			
		||||
enum intf_A_bar {
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the first
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_FIRST = 0x01,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the second
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_SECOND = 0x02,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the third
 | 
			
		||||
	 * @since 2
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_THIRD = 0x04,
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 */
 | 
			
		||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_BAR_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 * @struct intf_A_listener
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,10 +107,6 @@ enum intf_A_foo {
 | 
			
		|||
 * @ingroup iface_intf_A
 | 
			
		||||
 */
 | 
			
		||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_FOO_ENUM_IS_VALID
 | 
			
		||||
#define INTF_A_FOO_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 * Validate a intf_A foo value.
 | 
			
		||||
| 
						 | 
				
			
			@ -135,52 +131,7 @@ intf_A_foo_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM_IS_VALID */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_BAR_ENUM
 | 
			
		||||
#define INTF_A_BAR_ENUM
 | 
			
		||||
enum intf_A_bar {
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the first
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_FIRST = 0x01,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the second
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_SECOND = 0x02,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the third
 | 
			
		||||
	 * @since 2
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_THIRD = 0x04,
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 */
 | 
			
		||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_BAR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_BAR_ENUM_IS_VALID
 | 
			
		||||
#define INTF_A_BAR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 * Validate a intf_A bar value.
 | 
			
		||||
 *
 | 
			
		||||
 * @return true on success, false on error.
 | 
			
		||||
 * @ref intf_A_bar
 | 
			
		||||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
intf_A_bar_is_valid(uint32_t value, uint32_t version) {
 | 
			
		||||
	uint32_t valid = 0;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= INTF_A_BAR_FIRST;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= INTF_A_BAR_SECOND;
 | 
			
		||||
	if (version >= 2)
 | 
			
		||||
		valid |= INTF_A_BAR_THIRD;
 | 
			
		||||
	return (value & ~valid) == 0;
 | 
			
		||||
}
 | 
			
		||||
#endif /* INTF_A_BAR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,10 +107,6 @@ enum intf_A_foo {
 | 
			
		|||
 * @ingroup iface_intf_A
 | 
			
		||||
 */
 | 
			
		||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_FOO_ENUM_IS_VALID
 | 
			
		||||
#define INTF_A_FOO_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 * Validate a intf_A foo value.
 | 
			
		||||
| 
						 | 
				
			
			@ -135,52 +131,7 @@ intf_A_foo_is_valid(uint32_t value, uint32_t version) {
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM_IS_VALID */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_BAR_ENUM
 | 
			
		||||
#define INTF_A_BAR_ENUM
 | 
			
		||||
enum intf_A_bar {
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the first
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_FIRST = 0x01,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the second
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_SECOND = 0x02,
 | 
			
		||||
	/**
 | 
			
		||||
	 * this is the third
 | 
			
		||||
	 * @since 2
 | 
			
		||||
	 */
 | 
			
		||||
	INTF_A_BAR_THIRD = 0x04,
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 */
 | 
			
		||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
 | 
			
		||||
#endif /* INTF_A_BAR_ENUM */
 | 
			
		||||
 | 
			
		||||
#ifndef INTF_A_BAR_ENUM_IS_VALID
 | 
			
		||||
#define INTF_A_BAR_ENUM_IS_VALID
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
 * Validate a intf_A bar value.
 | 
			
		||||
 *
 | 
			
		||||
 * @return true on success, false on error.
 | 
			
		||||
 * @ref intf_A_bar
 | 
			
		||||
 */
 | 
			
		||||
static inline bool
 | 
			
		||||
intf_A_bar_is_valid(uint32_t value, uint32_t version) {
 | 
			
		||||
	uint32_t valid = 0;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= INTF_A_BAR_FIRST;
 | 
			
		||||
	if (version >= 1)
 | 
			
		||||
		valid |= INTF_A_BAR_SECOND;
 | 
			
		||||
	if (version >= 2)
 | 
			
		||||
		valid |= INTF_A_BAR_THIRD;
 | 
			
		||||
	return (value & ~valid) == 0;
 | 
			
		||||
}
 | 
			
		||||
#endif /* INTF_A_BAR_ENUM_IS_VALID */
 | 
			
		||||
#endif /* INTF_A_FOO_ENUM */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @ingroup iface_intf_A
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,12 +58,5 @@
 | 
			
		|||
	<entry name="negative" value="-1" since="2" summary="this is a negative value"/>
 | 
			
		||||
	<entry name="deprecated" value="3" since="2" deprecated-since="3" summary="this is a deprecated value"/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
    <enum name="bar" bitfield="true">
 | 
			
		||||
      <entry name="first" value="0x01" summary="this is the first"/>
 | 
			
		||||
      <entry name="second" value="0x02" summary="this is the second"/>
 | 
			
		||||
      <entry name="third" value="0x04" since="2" summary="this is the third"/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
  </interface>
 | 
			
		||||
</protocol>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -924,7 +924,7 @@ TEST(versions)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
check_error_on_destroyed_object(void)
 | 
			
		||||
check_error_on_destroyed_object(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *c;
 | 
			
		||||
	struct wl_seat *seat;
 | 
			
		||||
| 
						 | 
				
			
			@ -1043,7 +1043,7 @@ TEST(filtered_global_is_hidden)
 | 
			
		|||
		      1, d, bind_data_offer);
 | 
			
		||||
	wl_display_set_global_filter(d->wl_display, global_filter, NULL);
 | 
			
		||||
 | 
			
		||||
	client_create(d, get_globals, NULL);
 | 
			
		||||
	client_create_noarg(d, get_globals);
 | 
			
		||||
	display_run(d);
 | 
			
		||||
 | 
			
		||||
	wl_global_destroy(g);
 | 
			
		||||
| 
						 | 
				
			
			@ -1052,13 +1052,13 @@ TEST(filtered_global_is_hidden)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
get_dynamic_globals(void)
 | 
			
		||||
get_dynamic_globals(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *c = client_connect();
 | 
			
		||||
	struct wl_registry *registry;
 | 
			
		||||
 | 
			
		||||
	registry = wl_display_get_registry(c->wl_display);
 | 
			
		||||
	wl_registry_add_listener(registry, ®istry_listener_filtered, NULL);
 | 
			
		||||
	wl_registry_add_listener(registry, ®istry_listener_filtered, data);
 | 
			
		||||
	wl_display_roundtrip(c->wl_display);
 | 
			
		||||
 | 
			
		||||
	/* Wait for the server to create a new global */
 | 
			
		||||
| 
						 | 
				
			
			@ -1206,7 +1206,7 @@ static const struct wl_registry_listener zombie_fd_registry_listener = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
zombie_client(void)
 | 
			
		||||
zombie_client(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *c = client_connect();
 | 
			
		||||
	struct wl_registry *registry;
 | 
			
		||||
| 
						 | 
				
			
			@ -1376,7 +1376,7 @@ static const struct wl_registry_listener double_zombie_fd_registry_listener = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
double_zombie_client(void)
 | 
			
		||||
double_zombie_client(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *c = client_connect();
 | 
			
		||||
	struct wl_registry *registry;
 | 
			
		||||
| 
						 | 
				
			
			@ -1436,7 +1436,7 @@ static const struct wl_registry_listener bind_interface_mismatch_registry_listen
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
registry_bind_interface_mismatch_client(void)
 | 
			
		||||
registry_bind_interface_mismatch_client(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *c = client_connect();
 | 
			
		||||
	struct wl_registry *registry;
 | 
			
		||||
| 
						 | 
				
			
			@ -1598,7 +1598,7 @@ static const struct wl_registry_listener global_remove_before_registry_listener
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
global_remove_before_client(void)
 | 
			
		||||
global_remove_before_client(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *c = client_connect();
 | 
			
		||||
	struct wl_registry *registry;
 | 
			
		||||
| 
						 | 
				
			
			@ -1648,7 +1648,7 @@ static const struct wl_registry_listener global_remove_after_registry_listener =
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
global_remove_after_client(void)
 | 
			
		||||
global_remove_after_client(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *c = client_connect();
 | 
			
		||||
	struct wl_registry *registry;
 | 
			
		||||
| 
						 | 
				
			
			@ -1695,75 +1695,6 @@ 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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,19 +10,4 @@ main(int argc, char *argv[]) {
 | 
			
		|||
	assert(intf_A_foo_is_valid(INTF_A_FOO_THIRD, 2));
 | 
			
		||||
 | 
			
		||||
	assert(intf_A_foo_is_valid(INTF_A_FOO_NEGATIVE, 2));
 | 
			
		||||
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST, 1));
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST, 2));
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_SECOND, 1));
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_SECOND, 2));
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_SECOND, 1));
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_SECOND, 2));
 | 
			
		||||
 | 
			
		||||
	assert(!intf_A_bar_is_valid(INTF_A_BAR_THIRD, 1));
 | 
			
		||||
	assert(!intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_THIRD, 1));
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_THIRD, 2));
 | 
			
		||||
	assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_THIRD, 2));
 | 
			
		||||
 | 
			
		||||
	assert(!intf_A_bar_is_valid(0xFF, 1));
 | 
			
		||||
	assert(!intf_A_bar_is_valid(0xFF, 2));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ tests_protocol_c = custom_target(
 | 
			
		|||
	output: 'tests-protocol.c'
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
exec_fd_leak_checker = executable(
 | 
			
		||||
executable(
 | 
			
		||||
	'exec-fd-leak-checker',
 | 
			
		||||
	'exec-fd-leak-checker.c',
 | 
			
		||||
	dependencies: test_runner_dep
 | 
			
		||||
| 
						 | 
				
			
			@ -96,116 +96,78 @@ if get_option('scanner')
 | 
			
		|||
endif
 | 
			
		||||
 | 
			
		||||
tests = {
 | 
			
		||||
	'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': {},
 | 
			
		||||
	'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': [],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
foreach test_name, test_extras : tests
 | 
			
		||||
	test_extra_sources = test_extras.get('extra_sources', [])
 | 
			
		||||
	test_runtime_deps = test_extras.get('runtime_deps', [])
 | 
			
		||||
foreach test_name, test_extra_sources: tests
 | 
			
		||||
	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()),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,6 @@
 | 
			
		|||
#include "wayland-server.h"
 | 
			
		||||
#include "test-runner.h"
 | 
			
		||||
#include "test-compositor.h"
 | 
			
		||||
#include "../src/timespec-util.h"
 | 
			
		||||
 | 
			
		||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -572,68 +571,6 @@ client_test_queue_names(void)
 | 
			
		|||
	wl_display_disconnect(display);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dispatch_timeout_sync_callback(void *data, struct wl_callback *callback,
 | 
			
		||||
			       uint32_t serial)
 | 
			
		||||
{
 | 
			
		||||
	bool *done = data;
 | 
			
		||||
 | 
			
		||||
	*done = true;
 | 
			
		||||
	wl_callback_destroy(callback);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct wl_callback_listener dispatch_timeout_sync_listener = {
 | 
			
		||||
	dispatch_timeout_sync_callback
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
client_test_queue_dispatch_simple(void)
 | 
			
		||||
{
 | 
			
		||||
	struct wl_display *display;
 | 
			
		||||
	struct timespec timeout;
 | 
			
		||||
	struct wl_callback *callback;
 | 
			
		||||
	bool done = false;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	display = wl_display_connect(NULL);
 | 
			
		||||
	assert(display);
 | 
			
		||||
 | 
			
		||||
	callback = wl_display_sync(display);
 | 
			
		||||
	assert(callback != NULL);
 | 
			
		||||
	wl_callback_add_listener(callback, &dispatch_timeout_sync_listener, &done);
 | 
			
		||||
 | 
			
		||||
	timespec_from_msec(&timeout, 1000);
 | 
			
		||||
 | 
			
		||||
	while (!done) {
 | 
			
		||||
		ret = wl_display_dispatch_timeout(display, &timeout);
 | 
			
		||||
		assert(ret > 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_display_disconnect(display);
 | 
			
		||||
 | 
			
		||||
	exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
client_test_queue_dispatch_timeout(void)
 | 
			
		||||
{
 | 
			
		||||
	struct wl_display *display;
 | 
			
		||||
	struct timespec timeout;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	display = wl_display_connect(NULL);
 | 
			
		||||
	assert(display);
 | 
			
		||||
 | 
			
		||||
	timespec_from_msec(&timeout, 100);
 | 
			
		||||
 | 
			
		||||
	ret = wl_display_dispatch_timeout(display, &timeout);
 | 
			
		||||
	assert(ret == 0);
 | 
			
		||||
 | 
			
		||||
	wl_display_disconnect(display);
 | 
			
		||||
 | 
			
		||||
	exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
dummy_bind(struct wl_client *client,
 | 
			
		||||
	   void *data, uint32_t version, uint32_t id)
 | 
			
		||||
| 
						 | 
				
			
			@ -772,27 +709,3 @@ TEST(queue_names)
 | 
			
		|||
 | 
			
		||||
	display_destroy(d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(queue_dispatch_simple)
 | 
			
		||||
{
 | 
			
		||||
	struct display *d = display_create();
 | 
			
		||||
 | 
			
		||||
	test_set_timeout(2);
 | 
			
		||||
 | 
			
		||||
	client_create_noarg(d, client_test_queue_dispatch_simple);
 | 
			
		||||
	display_run(d);
 | 
			
		||||
 | 
			
		||||
	display_destroy(d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(queue_dispatch_timeout)
 | 
			
		||||
{
 | 
			
		||||
	struct display *d = display_create();
 | 
			
		||||
 | 
			
		||||
	test_set_timeout(2);
 | 
			
		||||
 | 
			
		||||
	client_create_noarg(d, client_test_queue_dispatch_timeout);
 | 
			
		||||
	display_run(d);
 | 
			
		||||
 | 
			
		||||
	display_destroy(d);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -507,7 +507,7 @@ static const struct wl_registry_listener registry_listener =
 | 
			
		|||
	NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct client *client_connect(void)
 | 
			
		||||
struct client *client_connect()
 | 
			
		||||
{
 | 
			
		||||
	struct wl_registry *reg;
 | 
			
		||||
	struct client *c = calloc(1, sizeof *c);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,17 +118,5 @@ struct client_info *client_create_with_name(struct display *d,
 | 
			
		|||
					    void *data,
 | 
			
		||||
					    const char *name);
 | 
			
		||||
#define client_create(d, c, data) client_create_with_name((d), (c), data, (#c))
 | 
			
		||||
static inline void noarg_cb(void *data)
 | 
			
		||||
{
 | 
			
		||||
	void (*cb)(void) = data;
 | 
			
		||||
	cb();
 | 
			
		||||
}
 | 
			
		||||
static inline struct client_info *client_create_with_name_noarg(struct display *d,
 | 
			
		||||
								void (*client_main)(void),
 | 
			
		||||
								const char *name)
 | 
			
		||||
{
 | 
			
		||||
	return client_create_with_name(d, noarg_cb, client_main, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define client_create_noarg(d, c) \
 | 
			
		||||
	client_create_with_name_noarg((d), (c), (#c))
 | 
			
		||||
	client_create_with_name((d), (void(*)(void *)) (c), NULL, (#c))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue