mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Compare commits
78 commits
1df4f23fe5
...
7fc400ffff
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fc400ffff | ||
|
|
d81525a235 | ||
|
|
4673ef7e9c | ||
|
|
77730f10a0 | ||
|
|
264da6a92b | ||
|
|
cd0d1543c0 | ||
|
|
90187031e6 | ||
|
|
eecf3f7635 | ||
|
|
adf84614ca | ||
|
|
ba9f9a446f | ||
|
|
53fbc2b0c1 | ||
|
|
fdac631d17 | ||
|
|
6c1da92018 | ||
|
|
ca83185e8a | ||
|
|
4a0c4e2119 | ||
|
|
387adc6a79 | ||
|
|
0de833da29 | ||
|
|
2978fd701a | ||
|
|
5c2f31d8d6 | ||
|
|
ce0ac4f29e | ||
|
|
1bee7aa4a7 | ||
|
|
6281ccbd3d | ||
|
|
ecff0ee10c | ||
|
|
827d0c30ad | ||
|
|
62cd0990e8 | ||
|
|
9b169ff945 | ||
|
|
cc06c3825f | ||
|
|
8cad6f7b82 | ||
|
|
4497232102 | ||
|
|
3214f858e2 | ||
|
|
66fc3f007d | ||
|
|
9dd1b2d7e3 | ||
|
|
d2a3d33063 | ||
|
|
9367c4da76 | ||
|
|
af453f876e | ||
|
|
9ec01ab2dc | ||
|
|
6137c8c213 | ||
|
|
7033e74857 | ||
|
|
dbfa8d784e | ||
|
|
1ab6b693b1 | ||
|
|
afd498b6f5 | ||
|
|
7c2ffb0d71 | ||
|
|
02ad102e2d | ||
|
|
74f322c35a | ||
|
|
00dcf6b323 | ||
|
|
ddd348da7e | ||
|
|
ff8b885523 | ||
|
|
893e4fc46d | ||
|
|
9d5de6062b | ||
|
|
37469d5ced | ||
|
|
bdba21ec92 | ||
|
|
597a6b94f5 | ||
|
|
f246e619d1 | ||
|
|
9cb3d7aa9d | ||
|
|
290c36bc50 | ||
|
|
4273a5edc8 | ||
|
|
10df74c240 | ||
|
|
f67db75ec1 | ||
|
|
38f91fe6ad | ||
|
|
1b0d45e9c6 | ||
|
|
7c6259e9ad | ||
|
|
6c4a695045 | ||
|
|
0239b082b9 | ||
|
|
5b692b50b9 | ||
|
|
efa648056a | ||
|
|
58bb6c7211 | ||
|
|
2bbd80c8df | ||
|
|
65454cf7db | ||
|
|
64248963d3 | ||
|
|
a6a4e081da | ||
|
|
f6f0a3cdec | ||
|
|
0cecde304f | ||
|
|
fa1811ce3e | ||
|
|
c669d99259 | ||
|
|
caaa308c0d | ||
|
|
1d5772b7b9 | ||
|
|
a156431ea6 | ||
|
|
26c419e046 |
38 changed files with 2042 additions and 475 deletions
|
|
@ -43,7 +43,7 @@ include:
|
||||||
# API changes. If you need new features from ci-templates you must bump
|
# API changes. If you need new features from ci-templates you must bump
|
||||||
# this to the current SHA you require from the ci-templates repo, however
|
# this to the current SHA you require from the ci-templates repo, however
|
||||||
# be aware that you may need to account for API changes when doing so.
|
# be aware that you may need to account for API changes when doing so.
|
||||||
ref: b791bd48996e3ced9ca13f1c5ee82be8540b8adb
|
ref: 48c2c583a865bd59be21e8938df247faf460099c
|
||||||
file:
|
file:
|
||||||
- '/templates/debian.yml'
|
- '/templates/debian.yml'
|
||||||
- '/templates/freebsd.yml'
|
- '/templates/freebsd.yml'
|
||||||
|
|
@ -62,6 +62,13 @@ stages:
|
||||||
- "Build and test"
|
- "Build and test"
|
||||||
- "Other build configurations"
|
- "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:
|
.ci-rules:
|
||||||
rules:
|
rules:
|
||||||
- when: on_success
|
- when: on_success
|
||||||
|
|
@ -75,7 +82,7 @@ stages:
|
||||||
FDO_DISTRIBUTION_EXEC: 'pip3 install --break-system-packages meson~=0.57.2'
|
FDO_DISTRIBUTION_EXEC: 'pip3 install --break-system-packages meson~=0.57.2'
|
||||||
# bump this tag every time you change something which requires rebuilding the
|
# bump this tag every time you change something which requires rebuilding the
|
||||||
# base image
|
# base image
|
||||||
FDO_DISTRIBUTION_TAG: "2024-03-28.2"
|
FDO_DISTRIBUTION_TAG: "2025-01-21.1"
|
||||||
|
|
||||||
.debian-x86_64:
|
.debian-x86_64:
|
||||||
extends:
|
extends:
|
||||||
|
|
@ -94,6 +101,7 @@ stages:
|
||||||
- .os-debian
|
- .os-debian
|
||||||
variables:
|
variables:
|
||||||
BUILD_ARCH: "armv7"
|
BUILD_ARCH: "armv7"
|
||||||
|
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||||
|
|
||||||
|
|
||||||
# Does not inherit .ci-rules as we only want it to run in MR context.
|
# Does not inherit .ci-rules as we only want it to run in MR context.
|
||||||
|
|
@ -147,7 +155,6 @@ armv7-debian-container_prep:
|
||||||
stage: "Base container"
|
stage: "Base container"
|
||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: none
|
GIT_STRATEGY: none
|
||||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
|
||||||
|
|
||||||
|
|
||||||
# Core build environment.
|
# Core build environment.
|
||||||
|
|
@ -299,11 +306,11 @@ armv7-release-debian-build:
|
||||||
.os-freebsd:
|
.os-freebsd:
|
||||||
variables:
|
variables:
|
||||||
BUILD_OS: freebsd
|
BUILD_OS: freebsd
|
||||||
FDO_DISTRIBUTION_VERSION: "13.2"
|
FDO_DISTRIBUTION_VERSION: "14.3"
|
||||||
FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2'
|
FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2'
|
||||||
# bump this tag every time you change something which requires rebuilding the
|
# bump this tag every time you change something which requires rebuilding the
|
||||||
# base image
|
# base image
|
||||||
FDO_DISTRIBUTION_TAG: "2023-08-02.0"
|
FDO_DISTRIBUTION_TAG: "2025-07-20.0"
|
||||||
# Don't build documentation since installing the required tools massively
|
# Don't build documentation since installing the required tools massively
|
||||||
# increases the VM image (and therefore container) size.
|
# increases the VM image (and therefore container) size.
|
||||||
MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false"
|
MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false"
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
* http://fontforge.org/pcf-format.html
|
* http://fontforge.org/pcf-format.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "xcursor.h"
|
#include "xcursor.h"
|
||||||
#include "wayland-cursor.h"
|
#include "wayland-cursor.h"
|
||||||
#include "wayland-client.h"
|
#include "wayland-client.h"
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
@ -68,11 +69,16 @@ shm_pool_create(struct wl_shm *shm, int size)
|
||||||
goto err_close;
|
goto err_close;
|
||||||
|
|
||||||
pool->pool = wl_shm_create_pool(shm, pool->fd, size);
|
pool->pool = wl_shm_create_pool(shm, pool->fd, size);
|
||||||
|
if (!pool->pool)
|
||||||
|
goto err_unmap;
|
||||||
|
|
||||||
pool->size = size;
|
pool->size = size;
|
||||||
pool->used = 0;
|
pool->used = 0;
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
|
|
||||||
|
err_unmap:
|
||||||
|
munmap(pool->data, size);
|
||||||
err_close:
|
err_close:
|
||||||
close(pool->fd);
|
close(pool->fd);
|
||||||
err_free:
|
err_free:
|
||||||
|
|
@ -279,7 +285,8 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
|
||||||
{
|
{
|
||||||
struct cursor *cursor;
|
struct cursor *cursor;
|
||||||
struct cursor_image *image;
|
struct cursor_image *image;
|
||||||
int i, size;
|
size_t size;
|
||||||
|
int i;
|
||||||
|
|
||||||
cursor = malloc(sizeof *cursor);
|
cursor = malloc(sizeof *cursor);
|
||||||
if (!cursor)
|
if (!cursor)
|
||||||
|
|
@ -309,7 +316,12 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
|
||||||
image->image.hotspot_y = images->images[i]->yhot;
|
image->image.hotspot_y = images->images[i]->yhot;
|
||||||
image->image.delay = images->images[i]->delay;
|
image->image.delay = images->images[i]->delay;
|
||||||
|
|
||||||
size = image->image.width * image->image.height * 4;
|
size = (size_t) image->image.width * image->image.height * 4;
|
||||||
|
if (size > INT_MAX) {
|
||||||
|
free(image);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
image->offset = shm_pool_allocate(theme->pool, size);
|
image->offset = shm_pool_allocate(theme->pool, size);
|
||||||
if (image->offset < 0) {
|
if (image->offset < 0) {
|
||||||
free(image);
|
free(image);
|
||||||
|
|
@ -339,6 +351,8 @@ load_callback(struct xcursor_images *images, void *data)
|
||||||
{
|
{
|
||||||
struct wl_cursor_theme *theme = data;
|
struct wl_cursor_theme *theme = data;
|
||||||
struct wl_cursor *cursor;
|
struct wl_cursor *cursor;
|
||||||
|
struct wl_cursor **p;
|
||||||
|
size_t s;
|
||||||
|
|
||||||
if (wl_cursor_theme_get_cursor(theme, images->name)) {
|
if (wl_cursor_theme_get_cursor(theme, images->name)) {
|
||||||
xcursor_images_destroy(images);
|
xcursor_images_destroy(images);
|
||||||
|
|
@ -348,15 +362,14 @@ load_callback(struct xcursor_images *images, void *data)
|
||||||
cursor = wl_cursor_create_from_xcursor_images(images, theme);
|
cursor = wl_cursor_create_from_xcursor_images(images, theme);
|
||||||
|
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
theme->cursor_count++;
|
s = theme->cursor_count + 1;
|
||||||
theme->cursors =
|
p = realloc(theme->cursors, s * sizeof theme->cursors[0]);
|
||||||
realloc(theme->cursors,
|
|
||||||
theme->cursor_count * sizeof theme->cursors[0]);
|
|
||||||
|
|
||||||
if (theme->cursors == NULL) {
|
if (p == NULL) {
|
||||||
theme->cursor_count--;
|
|
||||||
free(cursor);
|
free(cursor);
|
||||||
} else {
|
} else {
|
||||||
|
theme->cursor_count = s;
|
||||||
|
theme->cursors = p;
|
||||||
theme->cursors[theme->cursor_count - 1] = cursor;
|
theme->cursors[theme->cursor_count - 1] = cursor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -384,6 +397,9 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
|
||||||
if (!theme)
|
if (!theme)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (size < 0 || (size > 0 && INT_MAX / size / 4 < size))
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
name = "default";
|
name = "default";
|
||||||
|
|
||||||
|
|
@ -393,7 +409,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
|
||||||
|
|
||||||
theme->pool = shm_pool_create(shm, size * size * 4);
|
theme->pool = shm_pool_create(shm, size * size * 4);
|
||||||
if (!theme->pool)
|
if (!theme->pool)
|
||||||
goto out_error_pool;
|
goto err;
|
||||||
|
|
||||||
xcursor_load_theme(name, size, load_callback, theme);
|
xcursor_load_theme(name, size, load_callback, theme);
|
||||||
|
|
||||||
|
|
@ -405,7 +421,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
|
||||||
|
|
||||||
return theme;
|
return theme;
|
||||||
|
|
||||||
out_error_pool:
|
err:
|
||||||
free(theme);
|
free(theme);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,8 @@ xcursor_read_file_header(FILE *file)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!xcursor_read_uint(file, &head.ntoc))
|
if (!xcursor_read_uint(file, &head.ntoc))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (head.header < XCURSOR_FILE_HEADER_LEN)
|
||||||
|
return NULL;
|
||||||
skip = head.header - XCURSOR_FILE_HEADER_LEN;
|
skip = head.header - XCURSOR_FILE_HEADER_LEN;
|
||||||
if (skip)
|
if (skip)
|
||||||
if (fseek(file, skip, SEEK_CUR) == EOF)
|
if (fseek(file, skip, SEEK_CUR) == EOF)
|
||||||
|
|
@ -571,7 +573,7 @@ xcursor_build_theme_dir(const char *dir, const char *theme)
|
||||||
* add space for any needed directory separators, one per component,
|
* add space for any needed directory separators, one per component,
|
||||||
* and one for the trailing null
|
* and one for the trailing null
|
||||||
*/
|
*/
|
||||||
full_size = 1 + homelen + 1 + dirlen + 1 + themelen + 1;
|
full_size = (size_t) 1 + homelen + 1 + dirlen + 1 + themelen + 1;
|
||||||
full = malloc(full_size);
|
full = malloc(full_size);
|
||||||
if (!full)
|
if (!full)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -686,11 +688,15 @@ load_all_cursors_from_dir(const char *path, int size,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
DIR *dir = opendir(path);
|
DIR *dir;
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
char *full;
|
char *full;
|
||||||
struct xcursor_images *images;
|
struct xcursor_images *images;
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dir = opendir(path);
|
||||||
if (!dir)
|
if (!dir)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -798,14 +804,14 @@ xcursor_load_theme_protected(const char *theme, int size,
|
||||||
free(xcursor_path);
|
free(xcursor_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Load all the cursor of a theme
|
/** Load all the cursors of a theme
|
||||||
*
|
*
|
||||||
* This function loads all the cursor images of a given theme and its
|
* This function loads all the cursor images of a given theme and its
|
||||||
* inherited themes. Each cursor is loaded into an struct xcursor_images object
|
* inherited themes. Each cursor is loaded into a struct xcursor_images object
|
||||||
* which is passed to the caller's load callback. If a cursor appears
|
* which is passed to the caller's load callback. If a cursor appears
|
||||||
* more than once across all the inherited themes, the load callback
|
* more than once across all the inherited themes, the load callback
|
||||||
* will be called multiple times, with possibly different struct xcursor_images
|
* will be called multiple times, with possibly different struct xcursor_images
|
||||||
* object which have the same name. The user is expected to destroy the
|
* objects which have the same name. The user is expected to destroy the
|
||||||
* struct xcursor_images objects passed to the callback with
|
* struct xcursor_images objects passed to the callback with
|
||||||
* xcursor_images_destroy().
|
* xcursor_images_destroy().
|
||||||
*
|
*
|
||||||
|
|
|
||||||
139
doc/publican/sources/Color.xml
Normal file
139
doc/publican/sources/Color.xml
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
||||||
|
%BOOK_ENTITIES;
|
||||||
|
]>
|
||||||
|
|
||||||
|
<chapter id="chap-Color-Management">
|
||||||
|
<title>Color management</title>
|
||||||
|
|
||||||
|
<section id="sect-Color-Management-preface">
|
||||||
|
<title>Overview</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Color management in Wayland considers only displays. All pictures in
|
||||||
|
Wayland are always display-referred, meaning that the pixel values are
|
||||||
|
intended as-is for some specific display where they would produce the
|
||||||
|
light emissions (<ulink
|
||||||
|
url="https://cie.co.at/eilvterm/17-23-002">stimuli</ulink>) the picture's
|
||||||
|
author desired. Wayland does not support displaying "raw" camera or
|
||||||
|
scanner images as they are not display-referred, nor are they even
|
||||||
|
pictures without complex and subjective processing.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Stimuli — the picture itself — are only half of the picture reproduction.
|
||||||
|
The other half is the environment where a display is viewed. A striking
|
||||||
|
example is comparing a brightly lit office to a dark movie theater, the
|
||||||
|
stimuli required to produce a good reading of the picture is greatly
|
||||||
|
different. Therefore display-referred does not include only the display
|
||||||
|
but the viewing environment as well.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Window systems have been very well capable of operating without any
|
||||||
|
explicit consideration to color management. This is because there used to
|
||||||
|
be the implicit assumption of the standard display, the sRGB display,
|
||||||
|
which all computer monitors implemented, more or less. The viewing
|
||||||
|
environment was and still is accounted by adjusting the display and/or the
|
||||||
|
room to produce a workable experience. Pictures are authored on a computer
|
||||||
|
system by drawing, painting and adjusting the picture until it looks right
|
||||||
|
on the author's monitor. This implicitly builds the standard display and
|
||||||
|
environment assumption into the picture data. Deviations from the sRGB
|
||||||
|
specification were minor enough that they often did not matter if not in a
|
||||||
|
professional context like the printing industry. Displaying video material
|
||||||
|
required some more attention to the details, because video and television
|
||||||
|
standards differ enough from the sRGB display. What really made explicit
|
||||||
|
color management a hard requirement for entertainment is the coming of
|
||||||
|
wide color gamut (WCG) and high dynamic range (HDR) materials and
|
||||||
|
displays.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The color management design in Wayland follows the general Wayland design
|
||||||
|
principles: compositors tell clients what would be the optimal thing to
|
||||||
|
do, clients tell the compositors what kind of pictures they are actually
|
||||||
|
producing, and then compositors display those pictures the best they can.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Color-Management-Protocol">
|
||||||
|
<title>Protocol Interfaces</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Color management interfaces in Wayland and divided into two protocols:
|
||||||
|
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-management?ref_type=heads">color-management</ulink>
|
||||||
|
and
|
||||||
|
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-representation?ref_type=heads">color-representation</ulink>.
|
||||||
|
They are designed to work together, but they can also be used
|
||||||
|
independently when the other one is not needed.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section id="sect-Color-Management-Protocol-color-management">
|
||||||
|
<title>Color-management</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Color management protocol has two main purposes. First, it puts the
|
||||||
|
responsibility of color management on the compositor. This means that
|
||||||
|
clients do not necessarily need to care about color management at all,
|
||||||
|
and can display just fine by using the traditional standard display
|
||||||
|
assumption even when the actual display is wildly different. Clients
|
||||||
|
can also choose to target some other assumed display and let the
|
||||||
|
compositor handle it, or they can explicitly render for the actual
|
||||||
|
display at hand. Second, when the window system has multiple different
|
||||||
|
monitors, and a wl_surface happens to span more than one monitor, the
|
||||||
|
compositor can display the surface content correctly on all spanned
|
||||||
|
monitors simultaneously, as much as physically possible.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Color-management protocol concentrates on colorimetry: when you have a
|
||||||
|
pixel with RGB values, what stimulus do those values represent. The
|
||||||
|
stimulus definition follows the CIE 1931 two-degree observer model. Some
|
||||||
|
core concepts here are color primaries, white point, transfer function,
|
||||||
|
and dynamic range. The viewing environment is represented in an
|
||||||
|
extremely simplified way as the reference white luminance. The
|
||||||
|
connection between pixel RGB values and stimulus plus viewing
|
||||||
|
environment is recorded in an <emphasis>image description</emphasis>
|
||||||
|
object. Clients can create image description objects and tag
|
||||||
|
<code>wl_surface</code>s with them, to indicate what kind of surface
|
||||||
|
content there will be. Clients can also ask what image description the
|
||||||
|
compositor would prefer to have on the <code>wl_surface</code>, and that
|
||||||
|
preference can change over time, e.g. when the <code>wl_surface</code>
|
||||||
|
is moved from one
|
||||||
|
<code>wl_output</code> to another. Following the compositor's preference
|
||||||
|
may provide advantages in image quality and power consumption.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Image description objects can come in two flavors: parametric and
|
||||||
|
ICC-based. The above was written with parametric image descriptions in
|
||||||
|
mind, and they have first-class support for HDR. ICC-based image
|
||||||
|
descriptions are wrapping an ICC profile and have no other data. ICC
|
||||||
|
profiles are the standard tool for standard dynamic range (SDR) display
|
||||||
|
color management. This means the capabilities between the two flavors
|
||||||
|
differ, and one cannot always be replaced by the other. Compositor
|
||||||
|
support for each flavor is optional.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Color-Management-Protocol-color-representation">
|
||||||
|
<title>Color-representation</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Color-representation protocol deals with (potentially sub-sampled)
|
||||||
|
YCbCr-RGB conversion, quantization range, and the inclusion of alpha in
|
||||||
|
the RGB color channels, a.k.a. pre-multiplication. There are several
|
||||||
|
different specifications on how an YCbCr-like (including ICtCp) signal,
|
||||||
|
with chroma sub-sampling or not, is created from a full-resolution RGB
|
||||||
|
image. Again, a client can tag a <code>wl_surface</code> with
|
||||||
|
color-representation metadata to tell the compositor what kind of pixel
|
||||||
|
data will be displayed through the wl_surface.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The main purpose of color-representation is to correctly off-load the
|
||||||
|
YCbCr-RGB conversion to the compositor, which can then opportunistically
|
||||||
|
off-load it further to very power-efficient fixed-function circuitry in
|
||||||
|
a display controller. This can significantly reduce power consumption
|
||||||
|
when watching videos compared to using a GPU for the same, and on some
|
||||||
|
embedded hardware platforms it is a hard requirement for processing high
|
||||||
|
resolution video.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Overall, the philosophy of Wayland is to provide clients with a way to
|
Overall, the philosophy of Wayland is to provide clients with a way to
|
||||||
manage windows and how their contents is displayed. Rendering is left
|
manage windows and how their contents are displayed. Rendering is left
|
||||||
to clients, and system wide memory management interfaces are used to
|
to clients, and system wide memory management interfaces are used to
|
||||||
pass buffer handles between clients and the compositing manager.
|
pass buffer handles between clients and the compositing manager.
|
||||||
</para>
|
</para>
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,9 @@
|
||||||
in the environment). Beginning in Wayland 1.15, implementations can
|
in the environment). Beginning in Wayland 1.15, implementations can
|
||||||
optionally support server socket endpoints located at arbitrary
|
optionally support server socket endpoints located at arbitrary
|
||||||
locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis>
|
locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis>
|
||||||
to the absolute path at which the server endpoint listens.
|
to the absolute path at which the server endpoint listens. The socket may
|
||||||
|
also be provided through file descriptor inheritance, in which case
|
||||||
|
<emphasis>WAYLAND_SOCKET</emphasis> is set.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Every message is structured as 32-bit words; values are represented in the
|
Every message is structured as 32-bit words; values are represented in the
|
||||||
|
|
@ -150,9 +152,10 @@
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Starts with an unsigned 32-bit length (including null terminator),
|
Starts with an unsigned 32-bit length (including null terminator),
|
||||||
followed by the string contents, including terminating null byte,
|
followed by the UTF-8 encoded string contents, including
|
||||||
then padding to a 32-bit boundary. A null value is represented
|
terminating null byte, then padding to a 32-bit boundary. A null
|
||||||
with a length of 0.
|
value is represented with a length of 0. Interior null bytes are
|
||||||
|
not permitted.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<xi:include href="Architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
<xi:include href="Architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
<xi:include href="Protocol.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
<xi:include href="Protocol.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
<xi:include href="Xwayland.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
<xi:include href="Xwayland.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Color.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
<xi:include href="ProtocolSpec.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
<xi:include href="ProtocolSpec.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
<xi:include href="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
<xi:include href="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||||
<xi:include href="Server.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
<xi:include href="Server.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ publican_sources = [
|
||||||
'Protocol.xml',
|
'Protocol.xml',
|
||||||
'Xwayland.xml',
|
'Xwayland.xml',
|
||||||
'Compositors.xml',
|
'Compositors.xml',
|
||||||
|
'Color.xml',
|
||||||
'Client.xml',
|
'Client.xml',
|
||||||
'Server.xml'
|
'Server.xml'
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ if get_option('tests')
|
||||||
test(
|
test(
|
||||||
'wayland-egl symbols check',
|
'wayland-egl symbols check',
|
||||||
find_program('wayland-egl-symbols-check'),
|
find_program('wayland-egl-symbols-check'),
|
||||||
|
depends: wayland_egl,
|
||||||
env: [
|
env: [
|
||||||
'WAYLAND_EGL_LIB=@0@'.format(wayland_egl_shared.full_path()),
|
'WAYLAND_EGL_LIB=@0@'.format(wayland_egl_shared.full_path()),
|
||||||
'NM=@0@'.format(nm_path)
|
'NM=@0@'.format(nm_path)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
project(
|
project(
|
||||||
'wayland', 'c',
|
'wayland', 'c',
|
||||||
version: '1.22.93',
|
version: '1.24.90',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>= 0.57.0',
|
meson_version: '>= 0.57.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
|
@ -46,6 +46,7 @@ have_funcs = [
|
||||||
'memfd_create',
|
'memfd_create',
|
||||||
'mremap',
|
'mremap',
|
||||||
'strndup',
|
'strndup',
|
||||||
|
'gettid',
|
||||||
]
|
]
|
||||||
foreach f: have_funcs
|
foreach f: have_funcs
|
||||||
config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
|
config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
|
||||||
|
|
@ -131,7 +132,9 @@ if get_option('scanner')
|
||||||
'wayland-scanner.mk',
|
'wayland-scanner.mk',
|
||||||
'protocol/wayland.xml',
|
'protocol/wayland.xml',
|
||||||
'protocol/wayland.dtd',
|
'protocol/wayland.dtd',
|
||||||
])
|
],
|
||||||
|
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'wayland'),
|
||||||
|
)
|
||||||
|
|
||||||
install_data(
|
install_data(
|
||||||
[ 'wayland-scanner.m4' ],
|
[ 'wayland-scanner.m4' ],
|
||||||
|
|
|
||||||
|
|
@ -501,8 +501,10 @@
|
||||||
<event name="release">
|
<event name="release">
|
||||||
<description summary="compositor releases buffer">
|
<description summary="compositor releases buffer">
|
||||||
Sent when this wl_buffer is no longer used by the compositor.
|
Sent when this wl_buffer is no longer used by the compositor.
|
||||||
The client is now free to reuse or destroy this buffer and its
|
|
||||||
backing storage.
|
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.
|
||||||
|
|
||||||
If a client receives a release event before the frame callback
|
If a client receives a release event before the frame callback
|
||||||
requested in the same wl_surface.commit that attaches this
|
requested in the same wl_surface.commit that attaches this
|
||||||
|
|
@ -1504,7 +1506,8 @@
|
||||||
the delivery of wl_buffer.release events becomes undefined. A well
|
the delivery of wl_buffer.release events becomes undefined. A well
|
||||||
behaved client should not rely on wl_buffer.release events in this
|
behaved client should not rely on wl_buffer.release events in this
|
||||||
case. Alternatively, a client could create multiple wl_buffer objects
|
case. Alternatively, a client could create multiple wl_buffer objects
|
||||||
from the same backing storage or use wp_linux_buffer_release.
|
from the same backing storage or use a protocol extension providing
|
||||||
|
per-commit release notifications.
|
||||||
|
|
||||||
Destroying the wl_buffer after wl_buffer.release does not change
|
Destroying the wl_buffer after wl_buffer.release does not change
|
||||||
the surface contents. Destroying the wl_buffer before wl_buffer.release
|
the surface contents. Destroying the wl_buffer before wl_buffer.release
|
||||||
|
|
@ -1514,9 +1517,15 @@
|
||||||
mutates the underlying buffer storage, the surface contents become
|
mutates the underlying buffer storage, the surface contents become
|
||||||
undefined immediately.
|
undefined immediately.
|
||||||
|
|
||||||
If wl_surface.attach is sent with a NULL wl_buffer, or the pending
|
If wl_surface.attach is sent with a NULL wl_buffer, the
|
||||||
wl_buffer has been destroyed, the following wl_surface.commit will
|
following wl_surface.commit will remove the surface content.
|
||||||
remove the surface content.
|
|
||||||
|
If a pending wl_buffer has been destroyed, the result is not specified.
|
||||||
|
Many compositors are known to remove the surface content on the following
|
||||||
|
wl_surface.commit, but this behaviour is not universal. Clients seeking to
|
||||||
|
maximise compatibility should not destroy pending buffers and should
|
||||||
|
ensure that they explicitly remove content from surfaces, even after
|
||||||
|
destroying buffers.
|
||||||
</description>
|
</description>
|
||||||
<arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
|
<arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
|
||||||
summary="buffer of surface contents"/>
|
summary="buffer of surface contents"/>
|
||||||
|
|
@ -1658,21 +1667,48 @@
|
||||||
etc.) is double-buffered. Protocol requests modify the pending state,
|
etc.) is double-buffered. Protocol requests modify the pending state,
|
||||||
as opposed to the active state in use by the compositor.
|
as opposed to the active state in use by the compositor.
|
||||||
|
|
||||||
A commit request atomically creates a content update from the pending
|
|
||||||
state, even if the pending state has not been touched. The content
|
|
||||||
update is placed in a queue until it becomes active. After commit, the
|
|
||||||
new pending state is as documented for each related request.
|
|
||||||
|
|
||||||
When the content update is applied, the wl_buffer is applied before all
|
|
||||||
other state. This means that all coordinates in double-buffered state
|
|
||||||
are relative to the newly attached wl_buffers, except for
|
|
||||||
wl_surface.attach itself. If there is no newly attached wl_buffer, the
|
|
||||||
coordinates are relative to the previous content update.
|
|
||||||
|
|
||||||
All requests that need a commit to become effective are documented
|
All requests that need a commit to become effective are documented
|
||||||
to affect double-buffered state.
|
to affect double-buffered state.
|
||||||
|
|
||||||
Other interfaces may add further double-buffered surface state.
|
Other interfaces may add further double-buffered surface state.
|
||||||
|
|
||||||
|
A commit request atomically creates a Content Update (CU) from the
|
||||||
|
pending state, even if the pending state has not been touched. The
|
||||||
|
content update is placed at the end of a per-surface queue until it
|
||||||
|
becomes active. After commit, the new pending state is as documented for
|
||||||
|
each related request.
|
||||||
|
|
||||||
|
A CU is either a Desync Content Update (DCU) or a Sync Content Update
|
||||||
|
(SCU). If the surface is effectively synchronized at the commit request,
|
||||||
|
it is a SCU, otherwise a DCU.
|
||||||
|
|
||||||
|
When a surface transitions from effectively synchronized to effectively
|
||||||
|
desynchronized, all SCUs in its queue which are not reachable by any
|
||||||
|
DCU become DCUs and dependency edges from outside the queue to these CUs
|
||||||
|
are removed.
|
||||||
|
|
||||||
|
See wl_subsurface for the definition of 'effectively synchronized' and
|
||||||
|
'effectively desynchronized'.
|
||||||
|
|
||||||
|
When a CU is placed in the queue, the CU has a dependency on the CU in
|
||||||
|
front of it and to the SCU at end of the queue of every direct child
|
||||||
|
surface if that SCU exists and does not have another dependent. This can
|
||||||
|
form a directed acyclic graph of CUs with dependencies as edges.
|
||||||
|
|
||||||
|
In addition to surface state, the CU can have constraints that must be
|
||||||
|
satisfied before it can be applied. Other interfaces may add CU
|
||||||
|
constraints.
|
||||||
|
|
||||||
|
All DCUs which do not have a SCU in front of themselves in their queue,
|
||||||
|
are candidates. If the graph that's reachable by a candidate does not
|
||||||
|
have any unsatisfied constraints, the entire graph must be applied
|
||||||
|
atomically.
|
||||||
|
|
||||||
|
When a CU is applied, the wl_buffer is applied before all other state.
|
||||||
|
This means that all coordinates in double-buffered state are relative to
|
||||||
|
the newly attached wl_buffers, except for wl_surface.attach itself. If
|
||||||
|
there is no newly attached wl_buffer, the coordinates are relative to
|
||||||
|
the previous content update.
|
||||||
</description>
|
</description>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
|
|
@ -1826,6 +1862,9 @@
|
||||||
x and y, combined with the new surface size define in which
|
x and y, combined with the new surface size define in which
|
||||||
directions the surface's size changes.
|
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
|
Surface location offset is double-buffered state, see
|
||||||
wl_surface.commit.
|
wl_surface.commit.
|
||||||
|
|
||||||
|
|
@ -1874,7 +1913,7 @@
|
||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_seat" version="9">
|
<interface name="wl_seat" version="10">
|
||||||
<description summary="group of input devices">
|
<description summary="group of input devices">
|
||||||
A seat is a group of keyboards, pointer and touch devices. This
|
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
|
object is published as a global during start up, or when such a
|
||||||
|
|
@ -1902,9 +1941,10 @@
|
||||||
|
|
||||||
<event name="capabilities">
|
<event name="capabilities">
|
||||||
<description summary="seat capabilities changed">
|
<description summary="seat capabilities changed">
|
||||||
This is emitted whenever a seat gains or loses the pointer,
|
This is sent on binding to the seat global or whenever a seat gains
|
||||||
keyboard or touch capabilities. The argument is a capability
|
or loses the pointer, keyboard or touch capabilities.
|
||||||
enum containing the complete set of capabilities this seat has.
|
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
|
When the pointer capability is added, a client may create a
|
||||||
wl_pointer object using the wl_seat.get_pointer request. This object
|
wl_pointer object using the wl_seat.get_pointer request. This object
|
||||||
|
|
@ -1986,9 +2026,9 @@
|
||||||
The same seat names are used for all clients. Thus, the name can be
|
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.
|
shared across processes to refer to a specific wl_seat global.
|
||||||
|
|
||||||
The name event is sent after binding to the seat global. This event is
|
The name event is sent after binding to the seat global, and should be sent
|
||||||
only sent once per seat object, and the name does not change over the
|
before announcing capabilities. This event only sent once per seat object,
|
||||||
lifetime of the wl_seat global.
|
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
|
Compositors may re-use the same seat name if the wl_seat global is
|
||||||
destroyed and re-created later.
|
destroyed and re-created later.
|
||||||
|
|
@ -2007,7 +2047,7 @@
|
||||||
|
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_pointer" version="9">
|
<interface name="wl_pointer" version="10">
|
||||||
<description summary="pointer input device">
|
<description summary="pointer input device">
|
||||||
The wl_pointer interface represents one or more input devices,
|
The wl_pointer interface represents one or more input devices,
|
||||||
such as mice, which control the pointer location and pointer_focus
|
such as mice, which control the pointer location and pointer_focus
|
||||||
|
|
@ -2420,7 +2460,7 @@
|
||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_keyboard" version="9">
|
<interface name="wl_keyboard" version="10">
|
||||||
<description summary="keyboard input device">
|
<description summary="keyboard input device">
|
||||||
The wl_keyboard interface represents one or more keyboards
|
The wl_keyboard interface represents one or more keyboards
|
||||||
associated with a seat.
|
associated with a seat.
|
||||||
|
|
@ -2473,6 +2513,9 @@
|
||||||
the surface argument and the keys currently logically down to the keys
|
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
|
in the keys argument. The compositor must not send this event if the
|
||||||
wl_keyboard already had an active surface immediately before this event.
|
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>
|
</description>
|
||||||
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
<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"/>
|
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
|
||||||
|
|
@ -2499,9 +2542,18 @@
|
||||||
<enum name="key_state">
|
<enum name="key_state">
|
||||||
<description summary="physical key state">
|
<description summary="physical key state">
|
||||||
Describes the physical state of a key that produced the key event.
|
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>
|
</description>
|
||||||
<entry name="released" value="0" summary="key is not pressed"/>
|
<entry name="released" value="0" summary="key is not pressed"/>
|
||||||
<entry name="pressed" value="1" summary="key is pressed"/>
|
<entry name="pressed" value="1" summary="key is pressed"/>
|
||||||
|
<entry name="repeated" value="2" summary="key was repeated" since="10"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<event name="key">
|
<event name="key">
|
||||||
|
|
@ -2524,6 +2576,11 @@
|
||||||
compositor must not send this event if state is pressed (resp. released)
|
compositor must not send this event if state is pressed (resp. released)
|
||||||
and the key was already logically down (resp. was not logically down)
|
and the key was already logically down (resp. was not logically down)
|
||||||
immediately before this event.
|
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>
|
</description>
|
||||||
<arg name="serial" type="uint" summary="serial number of the key event"/>
|
<arg name="serial" type="uint" summary="serial number of the key event"/>
|
||||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
|
@ -2584,7 +2641,7 @@
|
||||||
</event>
|
</event>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="wl_touch" version="9">
|
<interface name="wl_touch" version="10">
|
||||||
<description summary="touchscreen input device">
|
<description summary="touchscreen input device">
|
||||||
The wl_touch interface represents a touchscreen
|
The wl_touch interface represents a touchscreen
|
||||||
associated with a seat.
|
associated with a seat.
|
||||||
|
|
@ -3090,23 +3147,9 @@
|
||||||
hidden, or if a NULL wl_buffer is applied. These rules apply
|
hidden, or if a NULL wl_buffer is applied. These rules apply
|
||||||
recursively through the tree of surfaces.
|
recursively through the tree of surfaces.
|
||||||
|
|
||||||
The behaviour of a wl_surface.commit request on a sub-surface
|
A sub-surface can be in one of two modes. The possible modes are
|
||||||
depends on the sub-surface's mode. The possible modes are
|
synchronized and desynchronized, see methods wl_subsurface.set_sync and
|
||||||
synchronized and desynchronized, see methods
|
wl_subsurface.set_desync.
|
||||||
wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
|
|
||||||
mode caches the wl_surface state to be applied when the parent's
|
|
||||||
state gets applied, and desynchronized mode applies the pending
|
|
||||||
wl_surface state directly. A sub-surface is initially in the
|
|
||||||
synchronized mode.
|
|
||||||
|
|
||||||
Sub-surfaces also have another kind of state, which is managed by
|
|
||||||
wl_subsurface requests, as opposed to wl_surface requests. This
|
|
||||||
state includes the sub-surface position relative to the parent
|
|
||||||
surface (wl_subsurface.set_position), and the stacking order of
|
|
||||||
the parent and its sub-surfaces (wl_subsurface.place_above and
|
|
||||||
.place_below). This state is applied when the parent surface's
|
|
||||||
wl_surface state is applied, regardless of the sub-surface's mode.
|
|
||||||
As the exception, set_sync and set_desync are effective immediately.
|
|
||||||
|
|
||||||
The main surface can be thought to be always in desynchronized mode,
|
The main surface can be thought to be always in desynchronized mode,
|
||||||
since it does not have a parent in the sub-surfaces sense.
|
since it does not have a parent in the sub-surfaces sense.
|
||||||
|
|
@ -3118,6 +3161,22 @@
|
||||||
synchronized mode, and then assume that all its child and grand-child
|
synchronized mode, and then assume that all its child and grand-child
|
||||||
sub-surfaces are synchronized, too, without explicitly setting them.
|
sub-surfaces are synchronized, too, without explicitly setting them.
|
||||||
|
|
||||||
|
If a surface behaves as in synchronized mode, it is effectively
|
||||||
|
synchronized, otherwise it is effectively desynchronized.
|
||||||
|
|
||||||
|
A sub-surface is initially in the synchronized mode.
|
||||||
|
|
||||||
|
Sub-surfaces also have another kind of state, which is managed by
|
||||||
|
wl_subsurface requests, as opposed to wl_surface requests. This
|
||||||
|
state includes the sub-surface position relative to the parent
|
||||||
|
surface (wl_subsurface.set_position), and the stacking order of
|
||||||
|
the parent and its sub-surfaces (wl_subsurface.place_above and
|
||||||
|
.place_below).
|
||||||
|
|
||||||
|
This state is double-buffered on the parent's surface regardless of the
|
||||||
|
sub-surface's mode. As the exception, set_sync and set_desync are
|
||||||
|
effective immediately.
|
||||||
|
|
||||||
Destroying a sub-surface takes effect immediately. If you need to
|
Destroying a sub-surface takes effect immediately. If you need to
|
||||||
synchronize the removal of a sub-surface to the parent surface update,
|
synchronize the removal of a sub-surface to the parent surface update,
|
||||||
unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
|
unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
|
||||||
|
|
@ -3199,44 +3258,47 @@
|
||||||
<request name="set_sync">
|
<request name="set_sync">
|
||||||
<description summary="set sub-surface to synchronized mode">
|
<description summary="set sub-surface to synchronized mode">
|
||||||
Change the commit behaviour of the sub-surface to synchronized
|
Change the commit behaviour of the sub-surface to synchronized
|
||||||
mode, also described as the parent dependent mode.
|
mode.
|
||||||
|
|
||||||
In synchronized mode, wl_surface.commit on a sub-surface will
|
See wl_subsurface and wl_surface.commit for more information.
|
||||||
accumulate the committed state in a cache, but the state will
|
|
||||||
not be applied and hence will not change the compositor output.
|
|
||||||
The cached state is applied to the sub-surface immediately after
|
|
||||||
the parent surface's state is applied. This ensures atomic
|
|
||||||
updates of the parent and all its synchronized sub-surfaces.
|
|
||||||
Applying the cached state will invalidate the cache, so further
|
|
||||||
parent surface commits do not (re-)apply old state.
|
|
||||||
|
|
||||||
See wl_subsurface for the recursive effect of this mode.
|
|
||||||
</description>
|
</description>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
<request name="set_desync">
|
<request name="set_desync">
|
||||||
<description summary="set sub-surface to desynchronized mode">
|
<description summary="set sub-surface to desynchronized mode">
|
||||||
Change the commit behaviour of the sub-surface to desynchronized
|
Change the commit behaviour of the sub-surface to desynchronized
|
||||||
mode, also described as independent or freely running mode.
|
mode.
|
||||||
|
|
||||||
In desynchronized mode, wl_surface.commit on a sub-surface will
|
See wl_subsurface and wl_surface.commit for more information.
|
||||||
apply the pending state directly, without caching, as happens
|
|
||||||
normally with a wl_surface. Calling wl_surface.commit on the
|
|
||||||
parent surface has no effect on the sub-surface's wl_surface
|
|
||||||
state. This mode allows a sub-surface to be updated on its own.
|
|
||||||
|
|
||||||
If cached state exists when wl_surface.commit is called in
|
|
||||||
desynchronized mode, the pending state is added to the cached
|
|
||||||
state, and applied as a whole. This invalidates the cache.
|
|
||||||
|
|
||||||
Note: even if a sub-surface is set to desynchronized, a parent
|
|
||||||
sub-surface may override it to behave as synchronized. For details,
|
|
||||||
see wl_subsurface.
|
|
||||||
|
|
||||||
If a surface's parent surface behaves as desynchronized, then
|
|
||||||
the cached state is applied on set_desync.
|
|
||||||
</description>
|
</description>
|
||||||
</request>
|
</request>
|
||||||
</interface>
|
</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>
|
</protocol>
|
||||||
|
|
|
||||||
115
src/connection.c
115
src/connection.c
|
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <assert.h>
|
#include "../config.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
@ -75,7 +76,8 @@ struct wl_connection {
|
||||||
static inline size_t
|
static inline size_t
|
||||||
size_pot(uint32_t size_bits)
|
size_pot(uint32_t size_bits)
|
||||||
{
|
{
|
||||||
assert(size_bits < 8 * sizeof(size_t));
|
if (!(size_bits < 8 * sizeof(size_t)))
|
||||||
|
wl_abort("Too many bits for size_t\n");
|
||||||
|
|
||||||
return ((size_t)1) << size_bits;
|
return ((size_t)1) << size_bits;
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +262,7 @@ ring_buffer_ensure_space(struct wl_ring_buffer *b, size_t count)
|
||||||
* allowed).
|
* allowed).
|
||||||
*/
|
*/
|
||||||
if (net_size > size_pot(size_bits)) {
|
if (net_size > size_pot(size_bits)) {
|
||||||
wl_log("Data too big for buffer (%d + %zd > %zd).\n",
|
wl_log("Data too big for buffer (%zu + %zu > %zu).\n",
|
||||||
ring_buffer_size(b), count, size_pot(size_bits));
|
ring_buffer_size(b), count, size_pot(size_bits));
|
||||||
errno = E2BIG;
|
errno = E2BIG;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -928,7 +930,7 @@ wl_connection_demarshal(struct wl_connection *connection,
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
signature = get_next_argument(signature, &arg);
|
signature = get_next_argument(signature, &arg);
|
||||||
|
|
||||||
if (arg.type != WL_ARG_FD && p + 1 > end) {
|
if (arg.type != WL_ARG_FD && p >= end) {
|
||||||
wl_log("message too short, "
|
wl_log("message too short, "
|
||||||
"object (%d), message %s(%s)\n",
|
"object (%d), message %s(%s)\n",
|
||||||
closure->sender_id, message->name,
|
closure->sender_id, message->name,
|
||||||
|
|
@ -975,7 +977,7 @@ wl_connection_demarshal(struct wl_connection *connection,
|
||||||
|
|
||||||
s = (char *) p;
|
s = (char *) p;
|
||||||
|
|
||||||
if (length > 0 && s[length - 1] != '\0') {
|
if (s[length - 1] != '\0') {
|
||||||
wl_log("string not nul-terminated, "
|
wl_log("string not nul-terminated, "
|
||||||
"message %s(%s)\n",
|
"message %s(%s)\n",
|
||||||
message->name, message->signature);
|
message->name, message->signature);
|
||||||
|
|
@ -983,6 +985,14 @@ wl_connection_demarshal(struct wl_connection *connection,
|
||||||
goto err;
|
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;
|
closure->args[i].s = s;
|
||||||
p = next;
|
p = next;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1221,6 +1231,11 @@ wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
|
||||||
count + 2, &ffi_type_void, ffi_types);
|
count + 2, &ffi_type_void, ffi_types);
|
||||||
|
|
||||||
implementation = target->implementation;
|
implementation = target->implementation;
|
||||||
|
if (!implementation) {
|
||||||
|
wl_abort("Implementation of resource %d of %s is NULL\n",
|
||||||
|
target->id, target->interface->name);
|
||||||
|
}
|
||||||
|
|
||||||
if (!implementation[opcode]) {
|
if (!implementation[opcode]) {
|
||||||
wl_abort("listener function for opcode %u of %s is NULL\n",
|
wl_abort("listener function for opcode %u of %s is NULL\n",
|
||||||
opcode, target->interface->name);
|
opcode, target->interface->name);
|
||||||
|
|
@ -1343,7 +1358,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
|
||||||
if (arg.type == WL_ARG_FD)
|
if (arg.type == WL_ARG_FD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (p + 1 > end)
|
if (p >= end)
|
||||||
goto overflow;
|
goto overflow;
|
||||||
|
|
||||||
switch (arg.type) {
|
switch (arg.type) {
|
||||||
|
|
@ -1371,7 +1386,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
|
||||||
size = strlen(closure->args[i].s) + 1;
|
size = strlen(closure->args[i].s) + 1;
|
||||||
*p++ = size;
|
*p++ = size;
|
||||||
|
|
||||||
if (p + div_roundup(size, sizeof *p) > end)
|
if (div_roundup(size, sizeof *p) > (uint32_t)(end - p))
|
||||||
goto overflow;
|
goto overflow;
|
||||||
|
|
||||||
memcpy(p, closure->args[i].s, size);
|
memcpy(p, closure->args[i].s, size);
|
||||||
|
|
@ -1386,7 +1401,7 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
|
||||||
size = closure->args[i].a->size;
|
size = closure->args[i].a->size;
|
||||||
*p++ = size;
|
*p++ = size;
|
||||||
|
|
||||||
if (p + div_roundup(size, sizeof *p) > end)
|
if (div_roundup(size, sizeof *p) > (uint32_t)(end - p))
|
||||||
goto overflow;
|
goto overflow;
|
||||||
|
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
|
|
@ -1478,11 +1493,56 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
wl_check_env_token(const char *env, const char *token)
|
||||||
|
{
|
||||||
|
const char *ptr = env;
|
||||||
|
size_t token_len;
|
||||||
|
|
||||||
|
if (env == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
token_len = strlen(token);
|
||||||
|
|
||||||
|
// Scan the string for comma-separated tokens and look for a match.
|
||||||
|
while (true) {
|
||||||
|
const char *end;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
// Skip over any leading separators.
|
||||||
|
while (*ptr == ',')
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if (*ptr == '\x00')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
end = strchr(ptr + 1, ',');
|
||||||
|
|
||||||
|
// If there isn't another separarator, then the rest of the string
|
||||||
|
// is one token.
|
||||||
|
if (end == NULL)
|
||||||
|
return (strcmp(ptr, token) == 0);
|
||||||
|
|
||||||
|
len = end - ptr;
|
||||||
|
if (len == token_len && memcmp(ptr, token, len) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip to the next token.
|
||||||
|
ptr += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
|
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
|
||||||
int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
|
int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
|
||||||
const char *queue_name)
|
const char *queue_name, int color)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_GETTID)
|
||||||
|
static int include_tid = -1;
|
||||||
|
#endif // defined(HAVE_GETTID)
|
||||||
int i;
|
int i;
|
||||||
struct argument_details arg;
|
struct argument_details arg;
|
||||||
const char *signature = closure->message->signature;
|
const char *signature = closure->message->signature;
|
||||||
|
|
@ -1499,17 +1559,40 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &tp);
|
clock_gettime(CLOCK_REALTIME, &tp);
|
||||||
time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
|
time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
|
||||||
|
fprintf(f, "%s[%7u.%03u] ",
|
||||||
|
color ? WL_DEBUG_COLOR_GREEN : "",
|
||||||
|
time / 1000, time % 1000);
|
||||||
|
|
||||||
fprintf(f, "[%7u.%03u] ", time / 1000, time % 1000);
|
#if defined(HAVE_GETTID)
|
||||||
|
if (include_tid < 0) {
|
||||||
|
include_tid = wl_check_env_token(getenv("WAYLAND_DEBUG"), "thread_id");
|
||||||
|
}
|
||||||
|
|
||||||
if (queue_name)
|
if (include_tid) {
|
||||||
fprintf(f, "{%s} ", queue_name);
|
fprintf(f, "%sTID#%d ",
|
||||||
|
color ? WL_DEBUG_COLOR_CYAN : "",
|
||||||
|
(int) gettid());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fprintf(f, "%s%s%s#%u.%s(",
|
if (queue_name) {
|
||||||
|
fprintf(f, "%s{%s} ",
|
||||||
|
color ? WL_DEBUG_COLOR_YELLOW : "",
|
||||||
|
queue_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(f, "%s%s%s%s%s%s%s#%u%s.%s%s(",
|
||||||
|
color ? WL_DEBUG_COLOR_RED : "",
|
||||||
discarded ? "discarded " : "",
|
discarded ? "discarded " : "",
|
||||||
|
color ? WL_DEBUG_COLOR_RESET : "",
|
||||||
send ? " -> " : "",
|
send ? " -> " : "",
|
||||||
target->interface->name, target->id,
|
color ? WL_DEBUG_COLOR_BLUE : "",
|
||||||
closure->message->name);
|
target->interface->name,
|
||||||
|
color ? WL_DEBUG_COLOR_MAGENTA : "",
|
||||||
|
target->id,
|
||||||
|
color ? WL_DEBUG_COLOR_CYAN : "",
|
||||||
|
closure->message->name,
|
||||||
|
color ? WL_DEBUG_COLOR_RESET : "");
|
||||||
|
|
||||||
for (i = 0; i < closure->count; i++) {
|
for (i = 0; i < closure->count; i++) {
|
||||||
signature = get_next_argument(signature, &arg);
|
signature = get_next_argument(signature, &arg);
|
||||||
|
|
@ -1574,7 +1657,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f, ")\n");
|
fprintf(f, ")%s\n", color ? WL_DEBUG_COLOR_RESET : "");
|
||||||
|
|
||||||
if (fclose(f) == 0) {
|
if (fclose(f) == 0) {
|
||||||
fprintf(stderr, "%s", buffer);
|
fprintf(stderr, "%s", buffer);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -39,6 +38,7 @@
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include "timespec-util.h"
|
||||||
#include "wayland-util.h"
|
#include "wayland-util.h"
|
||||||
#include "wayland-private.h"
|
#include "wayland-private.h"
|
||||||
#include "wayland-server-core.h"
|
#include "wayland-server-core.h"
|
||||||
|
|
@ -447,7 +447,8 @@ wl_timer_heap_disarm(struct wl_timer_heap *timers,
|
||||||
struct wl_event_source_timer *last_end_evt;
|
struct wl_event_source_timer *last_end_evt;
|
||||||
int old_source_idx;
|
int old_source_idx;
|
||||||
|
|
||||||
assert(source->heap_idx >= 0);
|
if (!(source->heap_idx >= 0))
|
||||||
|
wl_abort("Timer has already been disarmed\n");
|
||||||
|
|
||||||
old_source_idx = source->heap_idx;
|
old_source_idx = source->heap_idx;
|
||||||
source->heap_idx = -1;
|
source->heap_idx = -1;
|
||||||
|
|
@ -476,7 +477,8 @@ wl_timer_heap_arm(struct wl_timer_heap *timers,
|
||||||
struct wl_event_source_timer *source,
|
struct wl_event_source_timer *source,
|
||||||
struct timespec deadline)
|
struct timespec deadline)
|
||||||
{
|
{
|
||||||
assert(source->heap_idx == -1);
|
if (!(source->heap_idx == -1))
|
||||||
|
wl_abort("Timer is already armed\n");
|
||||||
|
|
||||||
source->deadline = deadline;
|
source->deadline = deadline;
|
||||||
timers->data[timers->active] = source;
|
timers->data[timers->active] = source;
|
||||||
|
|
@ -972,57 +974,6 @@ 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
|
/** Wait for events and dispatch them
|
||||||
*
|
*
|
||||||
* \param loop The event loop whose sources to wait for.
|
* \param loop The event loop whose sources to wait for.
|
||||||
|
|
@ -1051,13 +1002,15 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
|
||||||
int i, count;
|
int i, count;
|
||||||
bool has_timers = false;
|
bool has_timers = false;
|
||||||
bool use_timeout = timeout > 0;
|
bool use_timeout = timeout > 0;
|
||||||
struct timespec now, end;
|
struct timespec now;
|
||||||
|
struct timespec deadline = {0};
|
||||||
|
struct timespec result;
|
||||||
|
|
||||||
wl_event_loop_dispatch_idle(loop);
|
wl_event_loop_dispatch_idle(loop);
|
||||||
|
|
||||||
if (use_timeout) {
|
if (use_timeout) {
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
end = timespec_add(now, ms_to_timespec(timeout));
|
timespec_add_msec(&deadline, &now, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
@ -1069,7 +1022,8 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
|
||||||
|
|
||||||
if (use_timeout) {
|
if (use_timeout) {
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
timeout = timespec_to_ms(timespec_sub(end, now));
|
timespec_sub(&result, &deadline, &now);
|
||||||
|
timeout = timespec_to_msec(&result);
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
/* too late */
|
/* too late */
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,7 @@ if get_option('libraries')
|
||||||
description: 'Server side implementation of the Wayland protocol',
|
description: 'Server side implementation of the Wayland protocol',
|
||||||
version: meson.project_version(),
|
version: meson.project_version(),
|
||||||
filebase: 'wayland-server',
|
filebase: 'wayland-server',
|
||||||
|
libraries: mathlib_dep,
|
||||||
variables: [
|
variables: [
|
||||||
'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
|
'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
|
||||||
'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
|
'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
|
||||||
|
|
@ -251,6 +252,7 @@ if get_option('libraries')
|
||||||
description: 'Wayland client side library',
|
description: 'Wayland client side library',
|
||||||
version: meson.project_version(),
|
version: meson.project_version(),
|
||||||
filebase: 'wayland-client',
|
filebase: 'wayland-client',
|
||||||
|
libraries: mathlib_dep,
|
||||||
variables: [
|
variables: [
|
||||||
'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
|
'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
|
||||||
'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
|
'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
|
||||||
|
|
|
||||||
|
|
@ -1378,6 +1378,58 @@ 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
|
static void
|
||||||
emit_enumerations(struct interface *interface, bool with_validators)
|
emit_enumerations(struct interface *interface, bool with_validators)
|
||||||
{
|
{
|
||||||
|
|
@ -1439,35 +1491,11 @@ 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",
|
printf("#endif /* %s_%s_ENUM */\n\n",
|
||||||
interface->uppercase_name, e->uppercase_name);
|
interface->uppercase_name, e->uppercase_name);
|
||||||
|
|
||||||
|
if (with_validators)
|
||||||
|
emit_validator(interface, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
311
src/timespec-util.h
Normal file
311
src/timespec-util.h
Normal file
|
|
@ -0,0 +1,311 @@
|
||||||
|
/*
|
||||||
|
* 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,6 +34,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct timespec;
|
||||||
|
|
||||||
/** \class wl_proxy
|
/** \class wl_proxy
|
||||||
*
|
*
|
||||||
* \brief Represents a protocol object on the client side.
|
* \brief Represents a protocol object on the client side.
|
||||||
|
|
@ -219,6 +221,9 @@ wl_proxy_get_tag(struct wl_proxy *proxy);
|
||||||
const char *
|
const char *
|
||||||
wl_proxy_get_class(struct wl_proxy *proxy);
|
wl_proxy_get_class(struct wl_proxy *proxy);
|
||||||
|
|
||||||
|
const struct wl_interface *
|
||||||
|
wl_proxy_get_interface(struct wl_proxy *proxy);
|
||||||
|
|
||||||
struct wl_display *
|
struct wl_display *
|
||||||
wl_proxy_get_display(struct wl_proxy *proxy);
|
wl_proxy_get_display(struct wl_proxy *proxy);
|
||||||
|
|
||||||
|
|
@ -250,13 +255,29 @@ int
|
||||||
wl_display_dispatch_queue(struct wl_display *display,
|
wl_display_dispatch_queue(struct wl_display *display,
|
||||||
struct wl_event_queue *queue);
|
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
|
int
|
||||||
wl_display_dispatch_queue_pending(struct wl_display *display,
|
wl_display_dispatch_queue_pending(struct wl_display *display,
|
||||||
struct wl_event_queue *queue);
|
struct wl_event_queue *queue);
|
||||||
|
|
||||||
|
int
|
||||||
|
wl_display_dispatch_queue_pending_single(struct wl_display *display,
|
||||||
|
struct wl_event_queue *queue);
|
||||||
|
|
||||||
int
|
int
|
||||||
wl_display_dispatch_pending(struct wl_display *display);
|
wl_display_dispatch_pending(struct wl_display *display);
|
||||||
|
|
||||||
|
int
|
||||||
|
wl_display_dispatch_pending_single(struct wl_display *display);
|
||||||
|
|
||||||
int
|
int
|
||||||
wl_display_get_error(struct wl_display *display);
|
wl_display_get_error(struct wl_display *display);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
@ -46,6 +45,7 @@
|
||||||
#include "wayland-os.h"
|
#include "wayland-os.h"
|
||||||
#include "wayland-client.h"
|
#include "wayland-client.h"
|
||||||
#include "wayland-private.h"
|
#include "wayland-private.h"
|
||||||
|
#include "timespec-util.h"
|
||||||
|
|
||||||
/** \cond */
|
/** \cond */
|
||||||
|
|
||||||
|
|
@ -115,6 +115,7 @@ struct wl_display {
|
||||||
/** \endcond */
|
/** \endcond */
|
||||||
|
|
||||||
static int debug_client = 0;
|
static int debug_client = 0;
|
||||||
|
static int debug_color = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This helper function wakes up all threads that are
|
* This helper function wakes up all threads that are
|
||||||
|
|
@ -235,13 +236,16 @@ wl_event_queue_init(struct wl_event_queue *queue,
|
||||||
static void
|
static void
|
||||||
wl_proxy_unref(struct wl_proxy *proxy)
|
wl_proxy_unref(struct wl_proxy *proxy)
|
||||||
{
|
{
|
||||||
assert(proxy->refcount > 0);
|
if (!(proxy->refcount > 0))
|
||||||
|
wl_abort("Proxy requested for unref has no references\n");
|
||||||
if (--proxy->refcount > 0)
|
if (--proxy->refcount > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* If we get here, the client must have explicitly requested
|
/* If we get here, the client must have explicitly requested
|
||||||
* deletion. */
|
* deletion. */
|
||||||
assert(proxy->flags & WL_PROXY_FLAG_DESTROYED);
|
if (!(proxy->flags & WL_PROXY_FLAG_DESTROYED))
|
||||||
|
wl_abort("Proxy with no references not yet explicitly"
|
||||||
|
"destroyed\n");
|
||||||
free(proxy);
|
free(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -671,6 +675,9 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
|
||||||
* This function is useful in clients with multiple listeners on the same
|
* This function is useful in clients with multiple listeners on the same
|
||||||
* interface to allow the identification of which code to execute.
|
* 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
|
* \memberof wl_proxy
|
||||||
*/
|
*/
|
||||||
WL_EXPORT const void *
|
WL_EXPORT const void *
|
||||||
|
|
@ -914,21 +921,29 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
|
||||||
|
|
||||||
closure = wl_closure_marshal(&proxy->object, opcode, args, message);
|
closure = wl_closure_marshal(&proxy->object, opcode, args, message);
|
||||||
if (closure == NULL) {
|
if (closure == NULL) {
|
||||||
wl_log("Error marshalling request: %s\n", strerror(errno));
|
wl_log("Error marshalling request for %s.%s: %s\n",
|
||||||
|
proxy->object.interface->name, message->name,
|
||||||
|
strerror(errno));
|
||||||
display_fatal_error(proxy->display, errno);
|
display_fatal_error(proxy->display, errno);
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_client) {
|
if (debug_client) {
|
||||||
struct wl_event_queue *queue;
|
struct wl_event_queue *queue;
|
||||||
|
const char *queue_name = NULL;
|
||||||
|
|
||||||
queue = wl_proxy_get_queue(proxy);
|
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,
|
wl_closure_print(closure, &proxy->object, true, false, NULL,
|
||||||
wl_event_queue_get_name(queue));
|
queue_name, debug_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl_closure_send(closure, proxy->display->connection)) {
|
if (wl_closure_send(closure, proxy->display->connection)) {
|
||||||
wl_log("Error sending request: %s\n", strerror(errno));
|
wl_log("Error sending request for %s.%s: %s\n",
|
||||||
|
proxy->object.interface->name, message->name,
|
||||||
|
strerror(errno));
|
||||||
display_fatal_error(proxy->display, errno);
|
display_fatal_error(proxy->display, errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1172,7 +1187,8 @@ connect_to_socket(const char *name)
|
||||||
"%s", name) + 1;
|
"%s", name) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(name_size > 0);
|
if (!(name_size > 0))
|
||||||
|
wl_abort("Error assigning path name for socket connection\n");
|
||||||
if (name_size > (int)sizeof addr.sun_path) {
|
if (name_size > (int)sizeof addr.sun_path) {
|
||||||
if (!path_is_absolute) {
|
if (!path_is_absolute) {
|
||||||
wl_log("error: socket path \"%s/%s\" plus null terminator"
|
wl_log("error: socket path \"%s/%s\" plus null terminator"
|
||||||
|
|
@ -1214,10 +1230,23 @@ wl_display_connect_to_fd(int fd)
|
||||||
{
|
{
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
const char *debug;
|
const char *debug;
|
||||||
|
const char *no_color;
|
||||||
|
const char *force_color;
|
||||||
|
|
||||||
|
no_color = getenv("NO_COLOR");
|
||||||
|
force_color = getenv("FORCE_COLOR");
|
||||||
debug = getenv("WAYLAND_DEBUG");
|
debug = getenv("WAYLAND_DEBUG");
|
||||||
if (debug && (strstr(debug, "client") || strstr(debug, "1")))
|
if (debug && (wl_check_env_token(debug, "client") || wl_check_env_token(debug, "1"))) {
|
||||||
debug_client = 1;
|
debug_client = 1;
|
||||||
|
if (isatty(fileno(stderr)))
|
||||||
|
debug_color = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force_color && force_color[0] != '\0')
|
||||||
|
debug_color = 1;
|
||||||
|
|
||||||
|
if (no_color && no_color[0] != '\0')
|
||||||
|
debug_color = 0;
|
||||||
|
|
||||||
display = zalloc(sizeof *display);
|
display = zalloc(sizeof *display);
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
|
|
@ -1549,6 +1578,28 @@ queue_event(struct wl_display *display, int len)
|
||||||
id = p[0];
|
id = p[0];
|
||||||
opcode = p[1] & 0xffff;
|
opcode = p[1] & 0xffff;
|
||||||
size = p[1] >> 16;
|
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)
|
if (len < size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -1563,12 +1614,16 @@ queue_event(struct wl_display *display, int len)
|
||||||
if (debug_client) {
|
if (debug_client) {
|
||||||
clock_gettime(CLOCK_REALTIME, &tp);
|
clock_gettime(CLOCK_REALTIME, &tp);
|
||||||
time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
|
time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
|
||||||
|
fprintf(stderr, "%s[%7u.%03u] %sdiscarded %s[%s]%s#%u%s.[event %d]%s"
|
||||||
fprintf(stderr, "[%7u.%03u] discarded [%s]#%d.[event %d]"
|
|
||||||
"(%d fd, %d byte)\n",
|
"(%d fd, %d byte)\n",
|
||||||
|
debug_color ? WL_DEBUG_COLOR_GREEN : "",
|
||||||
time / 1000, time % 1000,
|
time / 1000, time % 1000,
|
||||||
|
debug_color ? WL_DEBUG_COLOR_RED : "",
|
||||||
|
debug_color ? WL_DEBUG_COLOR_BLUE : "",
|
||||||
zombie ? "zombie" : "unknown",
|
zombie ? "zombie" : "unknown",
|
||||||
id, opcode,
|
debug_color ? WL_DEBUG_COLOR_MAGENTA : "", id,
|
||||||
|
debug_color ? WL_DEBUG_COLOR_BLUE : "", opcode,
|
||||||
|
debug_color ? WL_DEBUG_COLOR_RESET : "",
|
||||||
num_zombie_fds, size);
|
num_zombie_fds, size);
|
||||||
}
|
}
|
||||||
if (num_zombie_fds > 0)
|
if (num_zombie_fds > 0)
|
||||||
|
|
@ -1653,7 +1708,7 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
|
||||||
!(proxy->dispatcher || proxy->object.implementation);
|
!(proxy->dispatcher || proxy->object.implementation);
|
||||||
|
|
||||||
wl_closure_print(closure, &proxy->object, false, discarded,
|
wl_closure_print(closure, &proxy->object, false, discarded,
|
||||||
id_from_object, queue->name);
|
id_from_object, queue->name, debug_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy_destroyed) {
|
if (proxy_destroyed) {
|
||||||
|
|
@ -1827,6 +1882,34 @@ err:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
dispatch_queue_single(struct wl_display *display, struct wl_event_queue *queue)
|
||||||
|
{
|
||||||
|
if (display->last_error)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while (!wl_list_empty(&display->display_queue.event_list)) {
|
||||||
|
dispatch_event(display, &display->display_queue);
|
||||||
|
if (display->last_error)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wl_list_empty(&queue->event_list)) {
|
||||||
|
dispatch_event(display, queue);
|
||||||
|
if (display->last_error)
|
||||||
|
goto err;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
errno = display->last_error;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/** Prepare to read events from the display's file descriptor to a queue
|
/** Prepare to read events from the display's file descriptor to a queue
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
@ -1942,20 +2025,142 @@ wl_display_cancel_read(struct wl_display *display)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wl_display_poll(struct wl_display *display, short int events)
|
wl_display_poll(struct wl_display *display,
|
||||||
|
short int events,
|
||||||
|
const struct timespec *timeout)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct pollfd pfd[1];
|
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].fd = display->fd;
|
||||||
pfd[0].events = events;
|
pfd[0].events = events;
|
||||||
do {
|
do {
|
||||||
ret = poll(pfd, 1, -1);
|
if (timeout) {
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
timespec_sub_saturate(&result, &deadline, &now);
|
||||||
|
remaining_timeout = &result;
|
||||||
|
}
|
||||||
|
ret = ppoll(pfd, 1, remaining_timeout, NULL);
|
||||||
} while (ret == -1 && errno == EINTR);
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
|
||||||
return ret;
|
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
|
/** Dispatch events in an event queue
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
@ -1987,8 +2192,8 @@ wl_display_poll(struct wl_display *display, short int events)
|
||||||
* \note Since Wayland 1.5 the display has an extra queue
|
* \note Since Wayland 1.5 the display has an extra queue
|
||||||
* for its own events (i. e. delete_id). This queue is dispatched always,
|
* 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.
|
* no matter what queue we passed as an argument to this function.
|
||||||
* That means that this function can return non-0 value even when it
|
* That means that this function can return even when it has not dispatched any
|
||||||
* haven't dispatched any event for the given queue.
|
* event for the given queue.
|
||||||
*
|
*
|
||||||
* \sa wl_display_dispatch(), wl_display_dispatch_pending(),
|
* \sa wl_display_dispatch(), wl_display_dispatch_pending(),
|
||||||
* wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue()
|
* wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue()
|
||||||
|
|
@ -2001,37 +2206,10 @@ wl_display_dispatch_queue(struct wl_display *display,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (wl_display_prepare_read_queue(display, queue) == -1)
|
ret = wl_display_dispatch_queue_timeout(display, queue, NULL);
|
||||||
return wl_display_dispatch_queue_pending(display, queue);
|
assert(ret == -1 || ret > 0);
|
||||||
|
|
||||||
while (true) {
|
return ret;
|
||||||
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
|
/** Dispatch pending events in an event queue
|
||||||
|
|
@ -2062,6 +2240,34 @@ wl_display_dispatch_queue_pending(struct wl_display *display,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Dispatch at most one pending event in an event queue
|
||||||
|
*
|
||||||
|
* \param display The display context object
|
||||||
|
* \param queue The event queue to dispatch
|
||||||
|
* \return The number of dispatched events (0 or 1) on success or -1 on failure
|
||||||
|
*
|
||||||
|
* Dispatch at most one pending event for objects assigned to the given
|
||||||
|
* event queue. On failure -1 is returned and errno set appropriately.
|
||||||
|
* If there are no events queued, this function returns immediately.
|
||||||
|
*
|
||||||
|
* \memberof wl_display
|
||||||
|
* \since 1.25.0
|
||||||
|
*/
|
||||||
|
WL_EXPORT int
|
||||||
|
wl_display_dispatch_queue_pending_single(struct wl_display *display,
|
||||||
|
struct wl_event_queue *queue)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&display->mutex);
|
||||||
|
|
||||||
|
ret = dispatch_queue_single(display, queue);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&display->mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/** Process incoming events
|
/** Process incoming events
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
@ -2122,6 +2328,25 @@ wl_display_dispatch_pending(struct wl_display *display)
|
||||||
&display->default_queue);
|
&display->default_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Dispatch at most one pending event in the default event queue.
|
||||||
|
*
|
||||||
|
* \param display The display context object
|
||||||
|
* \return The number of dispatched events (0 or 1) on success or -1 on failure
|
||||||
|
*
|
||||||
|
* Dispatch at most one pending event for objects assigned to the default
|
||||||
|
* event queue. On failure -1 is returned and errno set appropriately.
|
||||||
|
* If there are no events queued, this function returns immediately.
|
||||||
|
*
|
||||||
|
* \memberof wl_display
|
||||||
|
* \since 1.25.0
|
||||||
|
*/
|
||||||
|
WL_EXPORT int
|
||||||
|
wl_display_dispatch_pending_single(struct wl_display *display)
|
||||||
|
{
|
||||||
|
return wl_display_dispatch_queue_pending_single(display,
|
||||||
|
&display->default_queue);
|
||||||
|
}
|
||||||
|
|
||||||
/** Retrieve the last error that occurred on a display
|
/** Retrieve the last error that occurred on a display
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
@ -2403,6 +2628,20 @@ wl_proxy_get_class(struct wl_proxy *proxy)
|
||||||
return proxy->object.interface->name;
|
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
|
/** Get the display of a proxy object
|
||||||
*
|
*
|
||||||
* \param proxy The proxy object
|
* \param proxy The proxy object
|
||||||
|
|
@ -2453,7 +2692,9 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
|
||||||
wl_list_remove(&proxy->queue_link);
|
wl_list_remove(&proxy->queue_link);
|
||||||
|
|
||||||
if (queue) {
|
if (queue) {
|
||||||
assert(proxy->display == queue->display);
|
if (!(proxy->display == queue->display))
|
||||||
|
wl_abort("Proxy and queue point to different "
|
||||||
|
"wl_displays");
|
||||||
proxy->queue = queue;
|
proxy->queue = queue;
|
||||||
} else {
|
} else {
|
||||||
proxy->queue = &proxy->display->default_queue;
|
proxy->queue = &proxy->display->default_queue;
|
||||||
|
|
@ -2581,7 +2822,8 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper)
|
||||||
wl_abort("Tried to destroy non-wrapper proxy with "
|
wl_abort("Tried to destroy non-wrapper proxy with "
|
||||||
"wl_proxy_wrapper_destroy\n");
|
"wl_proxy_wrapper_destroy\n");
|
||||||
|
|
||||||
assert(wrapper->refcount == 1);
|
if (!(wrapper->refcount == 1))
|
||||||
|
wl_abort("Expected proxy wrapper's refcount to be 1\n");
|
||||||
|
|
||||||
pthread_mutex_lock(&wrapper->display->mutex);
|
pthread_mutex_lock(&wrapper->display->mutex);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,17 @@
|
||||||
#define WL_CLOSURE_MAX_ARGS 20
|
#define WL_CLOSURE_MAX_ARGS 20
|
||||||
#define WL_BUFFER_DEFAULT_SIZE_POT 12
|
#define WL_BUFFER_DEFAULT_SIZE_POT 12
|
||||||
#define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT)
|
#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.
|
* Argument types used in signatures.
|
||||||
|
|
@ -226,11 +237,14 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection);
|
||||||
int
|
int
|
||||||
wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
|
wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
|
||||||
|
|
||||||
|
bool
|
||||||
|
wl_check_env_token(const char *env, const char *token);
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_closure_print(struct wl_closure *closure,
|
wl_closure_print(struct wl_closure *closure,
|
||||||
struct wl_object *target, int send, int discarded,
|
struct wl_object *target, int send, int discarded,
|
||||||
uint32_t (*n_parse)(union wl_argument *arg),
|
uint32_t (*n_parse)(union wl_argument *arg),
|
||||||
const char *queue_name);
|
const char *queue_name, int color);
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_closure_destroy(struct wl_closure *closure);
|
wl_closure_destroy(struct wl_closure *closure);
|
||||||
|
|
|
||||||
|
|
@ -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 version, uint32_t id);
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
wl_display_get_serial(struct wl_display *display);
|
wl_display_get_serial(const struct wl_display *display);
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
wl_display_next_serial(struct wl_display *display);
|
wl_display_next_serial(struct wl_display *display);
|
||||||
|
|
@ -324,7 +324,7 @@ void
|
||||||
wl_client_flush(struct wl_client *client);
|
wl_client_flush(struct wl_client *client);
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_client_get_credentials(struct wl_client *client,
|
wl_client_get_credentials(const struct wl_client *client,
|
||||||
pid_t *pid, uid_t *uid, gid_t *gid);
|
pid_t *pid, uid_t *uid, gid_t *gid);
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -550,7 +550,10 @@ void
|
||||||
wl_resource_queue_event_array(struct wl_resource *resource,
|
wl_resource_queue_event_array(struct wl_resource *resource,
|
||||||
uint32_t opcode, union wl_argument *args);
|
uint32_t opcode, union wl_argument *args);
|
||||||
|
|
||||||
/* msg is a printf format string, variable args are its args. */
|
void
|
||||||
|
wl_resource_post_error_vargs(struct wl_resource *resource,
|
||||||
|
uint32_t code, const char *msg, va_list argp);
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_resource_post_error(struct wl_resource *resource,
|
wl_resource_post_error(struct wl_resource *resource,
|
||||||
uint32_t code, const char *msg, ...) WL_PRINTF(3, 4);
|
uint32_t code, const char *msg, ...) WL_PRINTF(3, 4);
|
||||||
|
|
@ -583,7 +586,7 @@ void
|
||||||
wl_resource_destroy(struct wl_resource *resource);
|
wl_resource_destroy(struct wl_resource *resource);
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
wl_resource_get_id(struct wl_resource *resource);
|
wl_resource_get_id(const struct wl_resource *resource);
|
||||||
|
|
||||||
struct wl_list *
|
struct wl_list *
|
||||||
wl_resource_get_link(struct wl_resource *resource);
|
wl_resource_get_link(struct wl_resource *resource);
|
||||||
|
|
@ -604,7 +607,7 @@ void *
|
||||||
wl_resource_get_user_data(struct wl_resource *resource);
|
wl_resource_get_user_data(struct wl_resource *resource);
|
||||||
|
|
||||||
int
|
int
|
||||||
wl_resource_get_version(struct wl_resource *resource);
|
wl_resource_get_version(const struct wl_resource *resource);
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_resource_set_destructor(struct wl_resource *resource,
|
wl_resource_set_destructor(struct wl_resource *resource,
|
||||||
|
|
@ -614,8 +617,12 @@ int
|
||||||
wl_resource_instance_of(struct wl_resource *resource,
|
wl_resource_instance_of(struct wl_resource *resource,
|
||||||
const struct wl_interface *interface,
|
const struct wl_interface *interface,
|
||||||
const void *implementation);
|
const void *implementation);
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
wl_resource_get_class(struct wl_resource *resource);
|
wl_resource_get_class(const struct wl_resource *resource);
|
||||||
|
|
||||||
|
const struct wl_interface *
|
||||||
|
wl_resource_get_interface(struct wl_resource *resource);
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_resource_add_destroy_listener(struct wl_resource *resource,
|
wl_resource_add_destroy_listener(struct wl_resource *resource,
|
||||||
|
|
@ -651,16 +658,22 @@ void *
|
||||||
wl_shm_buffer_get_data(struct wl_shm_buffer *buffer);
|
wl_shm_buffer_get_data(struct wl_shm_buffer *buffer);
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer);
|
wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer);
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
wl_shm_buffer_get_format(struct wl_shm_buffer *buffer);
|
wl_shm_buffer_get_format(const struct wl_shm_buffer *buffer);
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
wl_shm_buffer_get_width(struct wl_shm_buffer *buffer);
|
wl_shm_buffer_get_width(const struct wl_shm_buffer *buffer);
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
wl_shm_buffer_get_height(struct wl_shm_buffer *buffer);
|
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);
|
||||||
|
|
||||||
struct wl_shm_pool *
|
struct wl_shm_pool *
|
||||||
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer);
|
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer);
|
||||||
|
|
@ -674,10 +687,11 @@ wl_display_init_shm(struct wl_display *display);
|
||||||
uint32_t *
|
uint32_t *
|
||||||
wl_display_add_shm_format(struct wl_display *display, uint32_t format);
|
wl_display_add_shm_format(struct wl_display *display, uint32_t format);
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
struct wl_shm_buffer *
|
struct wl_shm_buffer *
|
||||||
wl_shm_buffer_create(struct wl_client *client,
|
wl_shm_buffer_create(struct wl_client *client,
|
||||||
uint32_t id, int32_t width, int32_t height,
|
uint32_t id, int32_t width, int32_t height,
|
||||||
int32_t stride, uint32_t format) WL_DEPRECATED;
|
int32_t stride, uint32_t format);
|
||||||
|
|
||||||
void
|
void
|
||||||
wl_log_set_handler_server(wl_log_func_t handler);
|
wl_log_set_handler_server(wl_log_func_t handler);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
|
|
@ -150,6 +149,7 @@ struct wl_protocol_logger {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int debug_server = 0;
|
static int debug_server = 0;
|
||||||
|
static int debug_color = 0;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
log_closure(struct wl_resource *resource,
|
log_closure(struct wl_resource *resource,
|
||||||
|
|
@ -161,7 +161,7 @@ log_closure(struct wl_resource *resource,
|
||||||
struct wl_protocol_logger_message message;
|
struct wl_protocol_logger_message message;
|
||||||
|
|
||||||
if (debug_server)
|
if (debug_server)
|
||||||
wl_closure_print(closure, object, send, false, NULL, NULL);
|
wl_closure_print(closure, object, send, false, NULL, NULL, debug_color);
|
||||||
|
|
||||||
if (!wl_list_empty(&display->protocol_loggers)) {
|
if (!wl_list_empty(&display->protocol_loggers)) {
|
||||||
message.resource = resource;
|
message.resource = resource;
|
||||||
|
|
@ -288,7 +288,16 @@ wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
|
||||||
wl_resource_queue_event_array(resource, opcode, args);
|
wl_resource_queue_event_array(resource, opcode, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/** 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
|
||||||
wl_resource_post_error_vargs(struct wl_resource *resource,
|
wl_resource_post_error_vargs(struct wl_resource *resource,
|
||||||
uint32_t code, const char *msg, va_list argp)
|
uint32_t code, const char *msg, va_list argp)
|
||||||
{
|
{
|
||||||
|
|
@ -310,9 +319,17 @@ wl_resource_post_error_vargs(struct wl_resource *resource,
|
||||||
wl_resource_post_event(client->display_resource,
|
wl_resource_post_event(client->display_resource,
|
||||||
WL_DISPLAY_ERROR, resource, code, buffer);
|
WL_DISPLAY_ERROR, resource, code, buffer);
|
||||||
client->error = true;
|
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_EXPORT void
|
||||||
wl_resource_post_error(struct wl_resource *resource,
|
wl_resource_post_error(struct wl_resource *resource,
|
||||||
uint32_t code, const char *msg, ...)
|
uint32_t code, const char *msg, ...)
|
||||||
|
|
@ -381,6 +398,29 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
||||||
wl_connection_copy(connection, p, sizeof p);
|
wl_connection_copy(connection, p, sizeof p);
|
||||||
opcode = p[1] & 0xffff;
|
opcode = p[1] & 0xffff;
|
||||||
size = p[1] >> 16;
|
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)
|
if (len < size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -603,7 +643,7 @@ err_client:
|
||||||
* \memberof wl_client
|
* \memberof wl_client
|
||||||
*/
|
*/
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
wl_client_get_credentials(struct wl_client *client,
|
wl_client_get_credentials(const struct wl_client *client,
|
||||||
pid_t *pid, uid_t *uid, gid_t *gid)
|
pid_t *pid, uid_t *uid, gid_t *gid)
|
||||||
{
|
{
|
||||||
if (pid)
|
if (pid)
|
||||||
|
|
@ -783,7 +823,7 @@ wl_resource_destroy(struct wl_resource *resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT uint32_t
|
WL_EXPORT uint32_t
|
||||||
wl_resource_get_id(struct wl_resource *resource)
|
wl_resource_get_id(const struct wl_resource *resource)
|
||||||
{
|
{
|
||||||
return resource->object.id;
|
return resource->object.id;
|
||||||
}
|
}
|
||||||
|
|
@ -837,7 +877,7 @@ wl_resource_get_user_data(struct wl_resource *resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT int
|
WL_EXPORT int
|
||||||
wl_resource_get_version(struct wl_resource *resource)
|
wl_resource_get_version(const struct wl_resource *resource)
|
||||||
{
|
{
|
||||||
return resource->version;
|
return resource->version;
|
||||||
}
|
}
|
||||||
|
|
@ -884,11 +924,25 @@ wl_resource_get_destroy_listener(struct wl_resource *resource,
|
||||||
* \memberof wl_resource
|
* \memberof wl_resource
|
||||||
*/
|
*/
|
||||||
WL_EXPORT const char *
|
WL_EXPORT const char *
|
||||||
wl_resource_get_class(struct wl_resource *resource)
|
wl_resource_get_class(const struct wl_resource *resource)
|
||||||
{
|
{
|
||||||
return resource->object.interface->name;
|
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
|
* Add a listener to be called at the beginning of wl_client destruction
|
||||||
*
|
*
|
||||||
|
|
@ -1138,10 +1192,23 @@ wl_display_create(void)
|
||||||
{
|
{
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
const char *debug;
|
const char *debug;
|
||||||
|
const char *no_color;
|
||||||
|
const char *force_color;
|
||||||
|
|
||||||
|
no_color = getenv("NO_COLOR");
|
||||||
|
force_color = getenv("FORCE_COLOR");
|
||||||
debug = getenv("WAYLAND_DEBUG");
|
debug = getenv("WAYLAND_DEBUG");
|
||||||
if (debug && (strstr(debug, "server") || strstr(debug, "1")))
|
if (debug && (wl_check_env_token(debug, "server") || wl_check_env_token(debug, "1"))) {
|
||||||
debug_server = 1;
|
debug_server = 1;
|
||||||
|
if (isatty(fileno(stderr)))
|
||||||
|
debug_color = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force_color && force_color[0] != '\0')
|
||||||
|
debug_color = 1;
|
||||||
|
|
||||||
|
if (no_color && no_color[0] != '\0')
|
||||||
|
debug_color = 0;
|
||||||
|
|
||||||
display = zalloc(sizeof *display);
|
display = zalloc(sizeof *display);
|
||||||
if (display == NULL)
|
if (display == NULL)
|
||||||
|
|
@ -1480,7 +1547,7 @@ wl_global_set_user_data(struct wl_global *global, void *data)
|
||||||
* \memberof wl_display
|
* \memberof wl_display
|
||||||
*/
|
*/
|
||||||
WL_EXPORT uint32_t
|
WL_EXPORT uint32_t
|
||||||
wl_display_get_serial(struct wl_display *display)
|
wl_display_get_serial(const struct wl_display *display)
|
||||||
{
|
{
|
||||||
return display->serial;
|
return display->serial;
|
||||||
}
|
}
|
||||||
|
|
@ -1517,7 +1584,8 @@ wl_display_terminate(struct wl_display *display)
|
||||||
display->run = false;
|
display->run = false;
|
||||||
|
|
||||||
ret = write(display->terminate_efd, &terminate, sizeof(terminate));
|
ret = write(display->terminate_efd, &terminate, sizeof(terminate));
|
||||||
assert (ret >= 0 || errno == EAGAIN);
|
if (ret < 0 && errno != EAGAIN)
|
||||||
|
wl_abort("Write failed at shutdown\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
|
|
@ -1714,7 +1782,8 @@ 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,
|
name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
|
||||||
"%s%s%s", runtime_dir, separator, name) + 1;
|
"%s%s%s", runtime_dir, separator, name) + 1;
|
||||||
|
|
||||||
assert(name_size > 0);
|
if (!(name_size > 0))
|
||||||
|
wl_abort("Error assigning path name for socket address\n");
|
||||||
if (name_size > (int)sizeof s->addr.sun_path) {
|
if (name_size > (int)sizeof s->addr.sun_path) {
|
||||||
wl_log("error: socket path \"%s%s%s\" plus null terminator"
|
wl_log("error: socket path \"%s%s%s\" plus null terminator"
|
||||||
" exceeds 108 bytes\n", runtime_dir, separator, name);
|
" exceeds 108 bytes\n", runtime_dir, separator, name);
|
||||||
|
|
@ -1762,6 +1831,24 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Automatically pick a Wayland display socket for the clients to connect to.
|
||||||
|
*
|
||||||
|
* \param display Wayland display to which the socket should be added.
|
||||||
|
* \return The socket name if success. NULL if failed.
|
||||||
|
*
|
||||||
|
* This adds a Unix socket to Wayland display which can be used by clients to
|
||||||
|
* connect to Wayland display. The name of the socket is chosen automatically
|
||||||
|
* as the first available name in the sequence "wayland-0", "wayland-1",
|
||||||
|
* "wayland-2", ..., "wayland-32".
|
||||||
|
*
|
||||||
|
* The string returned by this function is owned by the library and should
|
||||||
|
* not be freed.
|
||||||
|
*
|
||||||
|
* \sa wl_display_add_socket
|
||||||
|
*
|
||||||
|
* \memberof wl_display
|
||||||
|
*/
|
||||||
WL_EXPORT const char *
|
WL_EXPORT const char *
|
||||||
wl_display_add_socket_auto(struct wl_display *display)
|
wl_display_add_socket_auto(struct wl_display *display)
|
||||||
{
|
{
|
||||||
|
|
@ -2042,7 +2129,7 @@ wl_log_set_handler_server(wl_log_func_t handler)
|
||||||
* \param func The function to call to log a new protocol message
|
* \param func The function to call to log a new protocol message
|
||||||
* \param user_data The user data pointer to pass to \a func
|
* \param user_data The user data pointer to pass to \a func
|
||||||
*
|
*
|
||||||
* \return The protol logger object on success, NULL on failure.
|
* \return The protocol logger object on success, NULL on failure.
|
||||||
*
|
*
|
||||||
* \sa wl_protocol_logger_destroy
|
* \sa wl_protocol_logger_destroy
|
||||||
*
|
*
|
||||||
|
|
@ -2483,9 +2570,10 @@ wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data)
|
||||||
|
|
||||||
/** \cond */ /* Deprecated functions below. */
|
/** \cond */ /* Deprecated functions below. */
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
uint32_t
|
uint32_t
|
||||||
wl_client_add_resource(struct wl_client *client,
|
wl_client_add_resource(struct wl_client *client,
|
||||||
struct wl_resource *resource) WL_DEPRECATED;
|
struct wl_resource *resource);
|
||||||
|
|
||||||
WL_EXPORT uint32_t
|
WL_EXPORT uint32_t
|
||||||
wl_client_add_resource(struct wl_client *client,
|
wl_client_add_resource(struct wl_client *client,
|
||||||
|
|
@ -2514,11 +2602,12 @@ wl_client_add_resource(struct wl_client *client,
|
||||||
return resource->object.id;
|
return resource->object.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
struct wl_resource *
|
struct wl_resource *
|
||||||
wl_client_add_object(struct wl_client *client,
|
wl_client_add_object(struct wl_client *client,
|
||||||
const struct wl_interface *interface,
|
const struct wl_interface *interface,
|
||||||
const void *implementation,
|
const void *implementation,
|
||||||
uint32_t id, void *data) WL_DEPRECATED;
|
uint32_t id, void *data);
|
||||||
|
|
||||||
WL_EXPORT struct wl_resource *
|
WL_EXPORT struct wl_resource *
|
||||||
wl_client_add_object(struct wl_client *client,
|
wl_client_add_object(struct wl_client *client,
|
||||||
|
|
@ -2537,10 +2626,11 @@ wl_client_add_object(struct wl_client *client,
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
struct wl_resource *
|
struct wl_resource *
|
||||||
wl_client_new_object(struct wl_client *client,
|
wl_client_new_object(struct wl_client *client,
|
||||||
const struct wl_interface *interface,
|
const struct wl_interface *interface,
|
||||||
const void *implementation, void *data) WL_DEPRECATED;
|
const void *implementation, void *data);
|
||||||
|
|
||||||
WL_EXPORT struct wl_resource *
|
WL_EXPORT struct wl_resource *
|
||||||
wl_client_new_object(struct wl_client *client,
|
wl_client_new_object(struct wl_client *client,
|
||||||
|
|
@ -2599,10 +2689,11 @@ wl_client_get_user_data(struct wl_client *client)
|
||||||
return client->data;
|
return client->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
struct wl_global *
|
struct wl_global *
|
||||||
wl_display_add_global(struct wl_display *display,
|
wl_display_add_global(struct wl_display *display,
|
||||||
const struct wl_interface *interface,
|
const struct wl_interface *interface,
|
||||||
void *data, wl_global_bind_func_t bind) WL_DEPRECATED;
|
void *data, wl_global_bind_func_t bind);
|
||||||
|
|
||||||
WL_EXPORT struct wl_global *
|
WL_EXPORT struct wl_global *
|
||||||
wl_display_add_global(struct wl_display *display,
|
wl_display_add_global(struct wl_display *display,
|
||||||
|
|
@ -2612,9 +2703,10 @@ wl_display_add_global(struct wl_display *display,
|
||||||
return wl_global_create(display, interface, interface->version, data, bind);
|
return wl_global_create(display, interface, interface->version, data, bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
void
|
void
|
||||||
wl_display_remove_global(struct wl_display *display,
|
wl_display_remove_global(struct wl_display *display,
|
||||||
struct wl_global *global) WL_DEPRECATED;
|
struct wl_global *global);
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
wl_display_remove_global(struct wl_display *display, struct wl_global *global)
|
wl_display_remove_global(struct wl_display *display, struct wl_global *global)
|
||||||
|
|
|
||||||
|
|
@ -70,30 +70,35 @@ struct wl_resource {
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
uint32_t
|
uint32_t
|
||||||
wl_client_add_resource(struct wl_client *client,
|
wl_client_add_resource(struct wl_client *client,
|
||||||
struct wl_resource *resource) WL_DEPRECATED;
|
struct wl_resource *resource);
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
struct wl_resource *
|
struct wl_resource *
|
||||||
wl_client_add_object(struct wl_client *client,
|
wl_client_add_object(struct wl_client *client,
|
||||||
const struct wl_interface *interface,
|
const struct wl_interface *interface,
|
||||||
const void *implementation,
|
const void *implementation,
|
||||||
uint32_t id, void *data) WL_DEPRECATED;
|
uint32_t id, void *data);
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
struct wl_resource *
|
struct wl_resource *
|
||||||
wl_client_new_object(struct wl_client *client,
|
wl_client_new_object(struct wl_client *client,
|
||||||
const struct wl_interface *interface,
|
const struct wl_interface *interface,
|
||||||
const void *implementation, void *data) WL_DEPRECATED;
|
const void *implementation, void *data);
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
struct wl_global *
|
struct wl_global *
|
||||||
wl_display_add_global(struct wl_display *display,
|
wl_display_add_global(struct wl_display *display,
|
||||||
const struct wl_interface *interface,
|
const struct wl_interface *interface,
|
||||||
void *data,
|
void *data,
|
||||||
wl_global_bind_func_t bind) WL_DEPRECATED;
|
wl_global_bind_func_t bind);
|
||||||
|
|
||||||
|
WL_DEPRECATED
|
||||||
void
|
void
|
||||||
wl_display_remove_global(struct wl_display *display,
|
wl_display_remove_global(struct wl_display *display,
|
||||||
struct wl_global *global) WL_DEPRECATED;
|
struct wl_global *global);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -85,6 +84,10 @@ struct wl_shm_pool {
|
||||||
*/
|
*/
|
||||||
struct wl_shm_buffer {
|
struct wl_shm_buffer {
|
||||||
struct wl_resource *resource;
|
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 width, height;
|
||||||
int32_t stride;
|
int32_t stride;
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
|
|
@ -144,12 +147,16 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external)
|
||||||
{
|
{
|
||||||
if (external) {
|
if (external) {
|
||||||
pool->external_refcount--;
|
pool->external_refcount--;
|
||||||
assert(pool->external_refcount >= 0);
|
if (pool->external_refcount < 0)
|
||||||
|
wl_abort("Requested to unref an external reference to "
|
||||||
|
"pool but none found\n");
|
||||||
if (pool->external_refcount == 0)
|
if (pool->external_refcount == 0)
|
||||||
shm_pool_finish_resize(pool);
|
shm_pool_finish_resize(pool);
|
||||||
} else {
|
} else {
|
||||||
pool->internal_refcount--;
|
pool->internal_refcount--;
|
||||||
assert(pool->internal_refcount >= 0);
|
if (pool->internal_refcount < 0)
|
||||||
|
wl_abort("Requested to unref an internal reference to "
|
||||||
|
"pool but none found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->internal_refcount + pool->external_refcount > 0)
|
if (pool->internal_refcount + pool->external_refcount > 0)
|
||||||
|
|
@ -162,13 +169,38 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external)
|
||||||
free(pool);
|
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
|
static void
|
||||||
destroy_buffer(struct wl_resource *resource)
|
destroy_buffer(struct wl_resource *resource)
|
||||||
{
|
{
|
||||||
struct wl_shm_buffer *buffer = wl_resource_get_user_data(resource);
|
struct wl_shm_buffer *buffer = wl_resource_get_user_data(resource);
|
||||||
|
|
||||||
shm_pool_unref(buffer->pool, false);
|
shm_buffer_unref(buffer, false);
|
||||||
free(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -202,6 +234,17 @@ format_is_supported(struct wl_client *client, uint32_t format)
|
||||||
return false;
|
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
|
static void
|
||||||
shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
||||||
uint32_t id, int32_t offset,
|
uint32_t id, int32_t offset,
|
||||||
|
|
@ -234,6 +277,14 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
||||||
return;
|
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->width = width;
|
||||||
buffer->height = height;
|
buffer->height = height;
|
||||||
buffer->format = format;
|
buffer->format = format;
|
||||||
|
|
@ -441,7 +492,7 @@ wl_shm_buffer_get(struct wl_resource *resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT int32_t
|
WL_EXPORT int32_t
|
||||||
wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer)
|
wl_shm_buffer_get_stride(const struct wl_shm_buffer *buffer)
|
||||||
{
|
{
|
||||||
return buffer->stride;
|
return buffer->stride;
|
||||||
}
|
}
|
||||||
|
|
@ -458,8 +509,8 @@ wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer)
|
||||||
* SIGBUS signals. This can happen if the client claims that the
|
* SIGBUS signals. This can happen if the client claims that the
|
||||||
* buffer is larger than it is or if something truncates the
|
* buffer is larger than it is or if something truncates the
|
||||||
* underlying file. To prevent this signal from causing the compositor
|
* underlying file. To prevent this signal from causing the compositor
|
||||||
* to crash you should call wl_shm_buffer_begin_access and
|
* to crash you should call wl_shm_buffer_begin_access() and
|
||||||
* wl_shm_buffer_end_access around code that reads from the memory.
|
* wl_shm_buffer_end_access() around code that reads from the memory.
|
||||||
*
|
*
|
||||||
* \memberof wl_shm_buffer
|
* \memberof wl_shm_buffer
|
||||||
*/
|
*/
|
||||||
|
|
@ -475,23 +526,62 @@ wl_shm_buffer_get_data(struct wl_shm_buffer *buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT uint32_t
|
WL_EXPORT uint32_t
|
||||||
wl_shm_buffer_get_format(struct wl_shm_buffer *buffer)
|
wl_shm_buffer_get_format(const struct wl_shm_buffer *buffer)
|
||||||
{
|
{
|
||||||
return buffer->format;
|
return buffer->format;
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT int32_t
|
WL_EXPORT int32_t
|
||||||
wl_shm_buffer_get_width(struct wl_shm_buffer *buffer)
|
wl_shm_buffer_get_width(const struct wl_shm_buffer *buffer)
|
||||||
{
|
{
|
||||||
return buffer->width;
|
return buffer->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT int32_t
|
WL_EXPORT int32_t
|
||||||
wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
|
wl_shm_buffer_get_height(const struct wl_shm_buffer *buffer)
|
||||||
{
|
{
|
||||||
return buffer->height;
|
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
|
/** Get a reference to a shm_buffer's shm_pool
|
||||||
*
|
*
|
||||||
* \param buffer The buffer object
|
* \param buffer The buffer object
|
||||||
|
|
@ -499,7 +589,7 @@ wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
|
||||||
* Returns a pointer to a buffer's shm_pool and increases the
|
* Returns a pointer to a buffer's shm_pool and increases the
|
||||||
* shm_pool refcount.
|
* 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
|
* it no longer needs the reference to ensure proper destruction
|
||||||
* of the pool.
|
* of the pool.
|
||||||
*
|
*
|
||||||
|
|
@ -509,9 +599,6 @@ wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
|
||||||
WL_EXPORT struct wl_shm_pool *
|
WL_EXPORT struct wl_shm_pool *
|
||||||
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer)
|
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer)
|
||||||
{
|
{
|
||||||
assert(buffer->pool->internal_refcount +
|
|
||||||
buffer->pool->external_refcount);
|
|
||||||
|
|
||||||
buffer->pool->external_refcount++;
|
buffer->pool->external_refcount++;
|
||||||
return buffer->pool;
|
return buffer->pool;
|
||||||
}
|
}
|
||||||
|
|
@ -613,7 +700,7 @@ init_sigbus_data_key(void)
|
||||||
* In order to make the compositor robust against clients that change
|
* In order to make the compositor robust against clients that change
|
||||||
* the size of the underlying file or lie about its size, you should
|
* the size of the underlying file or lie about its size, you should
|
||||||
* protect access to the buffer by calling this function before
|
* 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
|
* afterwards. This will install a signal handler for SIGBUS which
|
||||||
* will prevent the compositor from crashing.
|
* will prevent the compositor from crashing.
|
||||||
*
|
*
|
||||||
|
|
@ -624,15 +711,15 @@ init_sigbus_data_key(void)
|
||||||
*
|
*
|
||||||
* If a SIGBUS signal is received for an address within the range of
|
* 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
|
* 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
|
* is for an address outside that range then the signal handler will
|
||||||
* reraise the signal which would will likely cause the compositor to
|
* reraise the signal which would will likely cause the compositor to
|
||||||
* terminate.
|
* terminate.
|
||||||
*
|
*
|
||||||
* It is safe to nest calls to these functions as long as the nested
|
* It is safe to nest calls to these functions as long as the nested
|
||||||
* calls are all accessing the same buffer. The number of calls to
|
* 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_end_access() must match the number of calls to
|
||||||
* wl_shm_buffer_begin_access. These functions are thread-safe and it
|
* wl_shm_buffer_begin_access(). These functions are thread-safe and it
|
||||||
* is allowed to simultaneously access different buffers or the same
|
* is allowed to simultaneously access different buffers or the same
|
||||||
* buffer from multiple threads.
|
* buffer from multiple threads.
|
||||||
*
|
*
|
||||||
|
|
@ -658,18 +745,19 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
|
||||||
pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data);
|
pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sigbus_data->current_pool == NULL ||
|
if (!(sigbus_data->current_pool == NULL ||
|
||||||
sigbus_data->current_pool == pool);
|
sigbus_data->current_pool == pool))
|
||||||
|
wl_abort("Incorrect pool passed for current thread\n");
|
||||||
|
|
||||||
sigbus_data->current_pool = pool;
|
sigbus_data->current_pool = pool;
|
||||||
sigbus_data->access_count++;
|
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
|
* \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
|
* buffer is no longer being accessed. If a SIGBUS signal was
|
||||||
* generated in-between these two calls then the resource for the
|
* generated in-between these two calls then the resource for the
|
||||||
* given buffer will be sent an error.
|
* given buffer will be sent an error.
|
||||||
|
|
@ -686,13 +774,22 @@ wl_shm_buffer_end_access(struct wl_shm_buffer *buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
|
sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
|
||||||
assert(sigbus_data && sigbus_data->access_count >= 1);
|
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");
|
||||||
|
|
||||||
if (--sigbus_data->access_count == 0) {
|
if (--sigbus_data->access_count == 0) {
|
||||||
if (sigbus_data->fallback_mapping_used) {
|
if (sigbus_data->fallback_mapping_used) {
|
||||||
wl_resource_post_error(buffer->resource,
|
if (buffer->resource) {
|
||||||
WL_SHM_ERROR_INVALID_FD,
|
wl_resource_post_error(buffer->resource,
|
||||||
"error accessing SHM buffer");
|
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");
|
||||||
|
}
|
||||||
sigbus_data->fallback_mapping_used = 0;
|
sigbus_data->fallback_mapping_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Deprecated attribute */
|
/** Deprecated attribute */
|
||||||
#if __STDC_VERSION__ >= 202311L
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || (defined(__cplusplus) && __cplusplus >= 201402L)
|
||||||
#define WL_DEPRECATED [[deprecated]]
|
#define WL_DEPRECATED [[deprecated]]
|
||||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||||
#define WL_DEPRECATED __attribute__ ((deprecated))
|
#define WL_DEPRECATED __attribute__ ((deprecated))
|
||||||
|
|
@ -70,7 +70,7 @@ extern "C" {
|
||||||
#define WL_PRINTF(x, y)
|
#define WL_PRINTF(x, y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __STDC_VERSION__ >= 202311L
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
|
||||||
#define WL_TYPEOF(expr) typeof(expr)
|
#define WL_TYPEOF(expr) typeof(expr)
|
||||||
#else
|
#else
|
||||||
#define WL_TYPEOF(expr) __typeof__(expr)
|
#define WL_TYPEOF(expr) __typeof__(expr)
|
||||||
|
|
@ -90,6 +90,14 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
struct wl_object;
|
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
|
* Protocol message signature
|
||||||
*
|
*
|
||||||
|
|
@ -635,7 +643,7 @@ wl_fixed_to_double(wl_fixed_t f)
|
||||||
static inline wl_fixed_t
|
static inline wl_fixed_t
|
||||||
wl_fixed_from_double(double d)
|
wl_fixed_from_double(double d)
|
||||||
{
|
{
|
||||||
return (wl_fixed_t) (d * 256.0);
|
return (wl_fixed_t) (round(d * 256.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -686,7 +686,7 @@ TEST(connection_marshal_big_enough)
|
||||||
|
|
||||||
TEST(connection_marshal_unbounded_boundary_size)
|
TEST(connection_marshal_unbounded_boundary_size)
|
||||||
{
|
{
|
||||||
/* A string of lenth 8178 requires a buffer size of exactly 2^13. */
|
/* A string of length 8178 requires a buffer size of exactly 2^13. */
|
||||||
struct marshal_data data;
|
struct marshal_data data;
|
||||||
char *big_string = malloc(8178);
|
char *big_string = malloc(8178);
|
||||||
assert(big_string);
|
assert(big_string);
|
||||||
|
|
|
||||||
|
|
@ -901,6 +901,10 @@ enum wl_display_error {
|
||||||
*/
|
*/
|
||||||
WL_DISPLAY_ERROR_NO_MEMORY = 2,
|
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
|
* @ingroup iface_wl_display
|
||||||
* Validate a wl_display error value.
|
* Validate a wl_display error value.
|
||||||
|
|
@ -921,7 +925,7 @@ wl_display_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_DISPLAY_ERROR_ENUM */
|
#endif /* WL_DISPLAY_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_display
|
* @ingroup iface_wl_display
|
||||||
|
|
@ -1194,6 +1198,10 @@ enum wl_shm_error {
|
||||||
*/
|
*/
|
||||||
WL_SHM_ERROR_INVALID_FD = 2,
|
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
|
* @ingroup iface_wl_shm
|
||||||
* Validate a wl_shm error value.
|
* Validate a wl_shm error value.
|
||||||
|
|
@ -1214,7 +1222,7 @@ wl_shm_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_SHM_ERROR_ENUM */
|
#endif /* WL_SHM_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_SHM_FORMAT_ENUM
|
#ifndef WL_SHM_FORMAT_ENUM
|
||||||
#define WL_SHM_FORMAT_ENUM
|
#define WL_SHM_FORMAT_ENUM
|
||||||
|
|
@ -1466,6 +1474,10 @@ enum wl_shm_format {
|
||||||
*/
|
*/
|
||||||
WL_SHM_FORMAT_YVU444 = 0x34325659,
|
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
|
* @ingroup iface_wl_shm
|
||||||
* Validate a wl_shm format value.
|
* Validate a wl_shm format value.
|
||||||
|
|
@ -1596,7 +1608,7 @@ wl_shm_format_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_SHM_FORMAT_ENUM */
|
#endif /* WL_SHM_FORMAT_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_shm
|
* @ingroup iface_wl_shm
|
||||||
|
|
@ -1706,6 +1718,10 @@ enum wl_data_offer_error {
|
||||||
*/
|
*/
|
||||||
WL_DATA_OFFER_ERROR_INVALID_OFFER = 3,
|
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
|
* @ingroup iface_wl_data_offer
|
||||||
* Validate a wl_data_offer error value.
|
* Validate a wl_data_offer error value.
|
||||||
|
|
@ -1728,7 +1744,7 @@ wl_data_offer_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_DATA_OFFER_ERROR_ENUM */
|
#endif /* WL_DATA_OFFER_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_data_offer
|
* @ingroup iface_wl_data_offer
|
||||||
|
|
@ -1940,6 +1956,10 @@ enum wl_data_source_error {
|
||||||
*/
|
*/
|
||||||
WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1,
|
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
|
* @ingroup iface_wl_data_source
|
||||||
* Validate a wl_data_source error value.
|
* Validate a wl_data_source error value.
|
||||||
|
|
@ -1958,7 +1978,7 @@ wl_data_source_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_DATA_SOURCE_ERROR_ENUM */
|
#endif /* WL_DATA_SOURCE_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_data_source
|
* @ingroup iface_wl_data_source
|
||||||
|
|
@ -2130,6 +2150,10 @@ enum wl_data_device_error {
|
||||||
*/
|
*/
|
||||||
WL_DATA_DEVICE_ERROR_ROLE = 0,
|
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
|
* @ingroup iface_wl_data_device
|
||||||
* Validate a wl_data_device error value.
|
* Validate a wl_data_device error value.
|
||||||
|
|
@ -2146,7 +2170,7 @@ wl_data_device_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_DATA_DEVICE_ERROR_ENUM */
|
#endif /* WL_DATA_DEVICE_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_data_device
|
* @ingroup iface_wl_data_device
|
||||||
|
|
@ -2387,6 +2411,10 @@ enum wl_data_device_manager_dnd_action {
|
||||||
*/
|
*/
|
||||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4,
|
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
|
* @ingroup iface_wl_data_device_manager
|
||||||
* Validate a wl_data_device_manager dnd_action value.
|
* Validate a wl_data_device_manager dnd_action value.
|
||||||
|
|
@ -2396,20 +2424,18 @@ enum wl_data_device_manager_dnd_action {
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
wl_data_device_manager_dnd_action_is_valid(uint32_t value, uint32_t version) {
|
wl_data_device_manager_dnd_action_is_valid(uint32_t value, uint32_t version) {
|
||||||
switch (value) {
|
uint32_t valid = 0;
|
||||||
case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
||||||
case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||||
case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||||
case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||||
default:
|
return (value & ~valid) == 0;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
|
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_data_device_manager
|
* @ingroup iface_wl_data_device_manager
|
||||||
|
|
@ -2456,6 +2482,10 @@ enum wl_shell_error {
|
||||||
*/
|
*/
|
||||||
WL_SHELL_ERROR_ROLE = 0,
|
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
|
* @ingroup iface_wl_shell
|
||||||
* Validate a wl_shell error value.
|
* Validate a wl_shell error value.
|
||||||
|
|
@ -2472,7 +2502,7 @@ wl_shell_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_SHELL_ERROR_ENUM */
|
#endif /* WL_SHELL_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_shell
|
* @ingroup iface_wl_shell
|
||||||
|
|
@ -2551,6 +2581,10 @@ enum wl_shell_surface_resize {
|
||||||
*/
|
*/
|
||||||
WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10,
|
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
|
* @ingroup iface_wl_shell_surface
|
||||||
* Validate a wl_shell_surface resize value.
|
* Validate a wl_shell_surface resize value.
|
||||||
|
|
@ -2560,30 +2594,28 @@ enum wl_shell_surface_resize {
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
wl_shell_surface_resize_is_valid(uint32_t value, uint32_t version) {
|
wl_shell_surface_resize_is_valid(uint32_t value, uint32_t version) {
|
||||||
switch (value) {
|
uint32_t valid = 0;
|
||||||
case WL_SHELL_SURFACE_RESIZE_NONE:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_NONE;
|
||||||
case WL_SHELL_SURFACE_RESIZE_TOP:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_TOP;
|
||||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
||||||
case WL_SHELL_SURFACE_RESIZE_LEFT:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_LEFT;
|
||||||
case WL_SHELL_SURFACE_RESIZE_TOP_LEFT:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
|
||||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
|
||||||
case WL_SHELL_SURFACE_RESIZE_RIGHT:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_RIGHT;
|
||||||
case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
|
||||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
|
||||||
default:
|
return (value & ~valid) == 0;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
|
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
|
#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
|
||||||
#define WL_SHELL_SURFACE_TRANSIENT_ENUM
|
#define WL_SHELL_SURFACE_TRANSIENT_ENUM
|
||||||
|
|
@ -2600,6 +2632,10 @@ enum wl_shell_surface_transient {
|
||||||
*/
|
*/
|
||||||
WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1,
|
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
|
* @ingroup iface_wl_shell_surface
|
||||||
* Validate a wl_shell_surface transient value.
|
* Validate a wl_shell_surface transient value.
|
||||||
|
|
@ -2609,14 +2645,12 @@ enum wl_shell_surface_transient {
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
wl_shell_surface_transient_is_valid(uint32_t value, uint32_t version) {
|
wl_shell_surface_transient_is_valid(uint32_t value, uint32_t version) {
|
||||||
switch (value) {
|
uint32_t valid = 0;
|
||||||
case WL_SHELL_SURFACE_TRANSIENT_INACTIVE:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
|
||||||
default:
|
return (value & ~valid) == 0;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
|
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
||||||
#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
||||||
|
|
@ -2646,6 +2680,10 @@ enum wl_shell_surface_fullscreen_method {
|
||||||
*/
|
*/
|
||||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3,
|
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
|
* @ingroup iface_wl_shell_surface
|
||||||
* Validate a wl_shell_surface fullscreen_method value.
|
* Validate a wl_shell_surface fullscreen_method value.
|
||||||
|
|
@ -2668,7 +2706,7 @@ wl_shell_surface_fullscreen_method_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
|
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_shell_surface
|
* @ingroup iface_wl_shell_surface
|
||||||
|
|
@ -3000,6 +3038,10 @@ enum wl_surface_error {
|
||||||
*/
|
*/
|
||||||
WL_SURFACE_ERROR_INVALID_TRANSFORM = 1,
|
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
|
* @ingroup iface_wl_surface
|
||||||
* Validate a wl_surface error value.
|
* Validate a wl_surface error value.
|
||||||
|
|
@ -3018,7 +3060,7 @@ wl_surface_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_SURFACE_ERROR_ENUM */
|
#endif /* WL_SURFACE_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_surface
|
* @ingroup iface_wl_surface
|
||||||
|
|
@ -3477,6 +3519,10 @@ enum wl_seat_capability {
|
||||||
*/
|
*/
|
||||||
WL_SEAT_CAPABILITY_TOUCH = 4,
|
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
|
* @ingroup iface_wl_seat
|
||||||
* Validate a wl_seat capability value.
|
* Validate a wl_seat capability value.
|
||||||
|
|
@ -3486,18 +3532,16 @@ enum wl_seat_capability {
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
wl_seat_capability_is_valid(uint32_t value, uint32_t version) {
|
wl_seat_capability_is_valid(uint32_t value, uint32_t version) {
|
||||||
switch (value) {
|
uint32_t valid = 0;
|
||||||
case WL_SEAT_CAPABILITY_POINTER:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SEAT_CAPABILITY_POINTER;
|
||||||
case WL_SEAT_CAPABILITY_KEYBOARD:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SEAT_CAPABILITY_KEYBOARD;
|
||||||
case WL_SEAT_CAPABILITY_TOUCH:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_SEAT_CAPABILITY_TOUCH;
|
||||||
default:
|
return (value & ~valid) == 0;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* WL_SEAT_CAPABILITY_ENUM */
|
#endif /* WL_SEAT_CAPABILITY_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_seat
|
* @ingroup iface_wl_seat
|
||||||
|
|
@ -3621,6 +3665,10 @@ enum wl_pointer_error {
|
||||||
*/
|
*/
|
||||||
WL_POINTER_ERROR_ROLE = 0,
|
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
|
* @ingroup iface_wl_pointer
|
||||||
* Validate a wl_pointer error value.
|
* Validate a wl_pointer error value.
|
||||||
|
|
@ -3637,7 +3685,7 @@ wl_pointer_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_POINTER_ERROR_ENUM */
|
#endif /* WL_POINTER_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_POINTER_BUTTON_STATE_ENUM
|
#ifndef WL_POINTER_BUTTON_STATE_ENUM
|
||||||
#define WL_POINTER_BUTTON_STATE_ENUM
|
#define WL_POINTER_BUTTON_STATE_ENUM
|
||||||
|
|
@ -3658,6 +3706,10 @@ enum wl_pointer_button_state {
|
||||||
*/
|
*/
|
||||||
WL_POINTER_BUTTON_STATE_PRESSED = 1,
|
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
|
* @ingroup iface_wl_pointer
|
||||||
* Validate a wl_pointer button_state value.
|
* Validate a wl_pointer button_state value.
|
||||||
|
|
@ -3676,7 +3728,7 @@ wl_pointer_button_state_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_POINTER_BUTTON_STATE_ENUM */
|
#endif /* WL_POINTER_BUTTON_STATE_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_POINTER_AXIS_ENUM
|
#ifndef WL_POINTER_AXIS_ENUM
|
||||||
#define WL_POINTER_AXIS_ENUM
|
#define WL_POINTER_AXIS_ENUM
|
||||||
|
|
@ -3696,6 +3748,10 @@ enum wl_pointer_axis {
|
||||||
*/
|
*/
|
||||||
WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1,
|
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
|
* @ingroup iface_wl_pointer
|
||||||
* Validate a wl_pointer axis value.
|
* Validate a wl_pointer axis value.
|
||||||
|
|
@ -3714,7 +3770,7 @@ wl_pointer_axis_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_POINTER_AXIS_ENUM */
|
#endif /* WL_POINTER_AXIS_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_POINTER_AXIS_SOURCE_ENUM
|
#ifndef WL_POINTER_AXIS_SOURCE_ENUM
|
||||||
#define WL_POINTER_AXIS_SOURCE_ENUM
|
#define WL_POINTER_AXIS_SOURCE_ENUM
|
||||||
|
|
@ -3762,6 +3818,10 @@ enum wl_pointer_axis_source {
|
||||||
* @ingroup iface_wl_pointer
|
* @ingroup iface_wl_pointer
|
||||||
*/
|
*/
|
||||||
#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
|
#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
|
* @ingroup iface_wl_pointer
|
||||||
* Validate a wl_pointer axis_source value.
|
* Validate a wl_pointer axis_source value.
|
||||||
|
|
@ -3784,7 +3844,7 @@ wl_pointer_axis_source_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
|
#endif /* WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_pointer
|
* @ingroup iface_wl_pointer
|
||||||
|
|
@ -4045,6 +4105,10 @@ enum wl_keyboard_keymap_format {
|
||||||
*/
|
*/
|
||||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1,
|
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
|
* @ingroup iface_wl_keyboard
|
||||||
* Validate a wl_keyboard keymap_format value.
|
* Validate a wl_keyboard keymap_format value.
|
||||||
|
|
@ -4063,7 +4127,7 @@ wl_keyboard_keymap_format_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
|
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_KEYBOARD_KEY_STATE_ENUM
|
#ifndef WL_KEYBOARD_KEY_STATE_ENUM
|
||||||
#define WL_KEYBOARD_KEY_STATE_ENUM
|
#define WL_KEYBOARD_KEY_STATE_ENUM
|
||||||
|
|
@ -4083,6 +4147,10 @@ enum wl_keyboard_key_state {
|
||||||
*/
|
*/
|
||||||
WL_KEYBOARD_KEY_STATE_PRESSED = 1,
|
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
|
* @ingroup iface_wl_keyboard
|
||||||
* Validate a wl_keyboard key_state value.
|
* Validate a wl_keyboard key_state value.
|
||||||
|
|
@ -4101,7 +4169,7 @@ wl_keyboard_key_state_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
|
#endif /* WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_keyboard
|
* @ingroup iface_wl_keyboard
|
||||||
|
|
@ -4427,6 +4495,10 @@ enum wl_output_subpixel {
|
||||||
*/
|
*/
|
||||||
WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5,
|
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
|
* @ingroup iface_wl_output
|
||||||
* Validate a wl_output subpixel value.
|
* Validate a wl_output subpixel value.
|
||||||
|
|
@ -4453,7 +4525,7 @@ wl_output_subpixel_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
|
#endif /* WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_OUTPUT_TRANSFORM_ENUM
|
#ifndef WL_OUTPUT_TRANSFORM_ENUM
|
||||||
#define WL_OUTPUT_TRANSFORM_ENUM
|
#define WL_OUTPUT_TRANSFORM_ENUM
|
||||||
|
|
@ -4507,6 +4579,10 @@ enum wl_output_transform {
|
||||||
*/
|
*/
|
||||||
WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7,
|
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
|
* @ingroup iface_wl_output
|
||||||
* Validate a wl_output transform value.
|
* Validate a wl_output transform value.
|
||||||
|
|
@ -4537,7 +4613,7 @@ wl_output_transform_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_OUTPUT_TRANSFORM_ENUM */
|
#endif /* WL_OUTPUT_TRANSFORM_ENUM_IS_VALID */
|
||||||
|
|
||||||
#ifndef WL_OUTPUT_MODE_ENUM
|
#ifndef WL_OUTPUT_MODE_ENUM
|
||||||
#define WL_OUTPUT_MODE_ENUM
|
#define WL_OUTPUT_MODE_ENUM
|
||||||
|
|
@ -4558,6 +4634,10 @@ enum wl_output_mode {
|
||||||
*/
|
*/
|
||||||
WL_OUTPUT_MODE_PREFERRED = 0x2,
|
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
|
* @ingroup iface_wl_output
|
||||||
* Validate a wl_output mode value.
|
* Validate a wl_output mode value.
|
||||||
|
|
@ -4567,16 +4647,14 @@ enum wl_output_mode {
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
wl_output_mode_is_valid(uint32_t value, uint32_t version) {
|
wl_output_mode_is_valid(uint32_t value, uint32_t version) {
|
||||||
switch (value) {
|
uint32_t valid = 0;
|
||||||
case WL_OUTPUT_MODE_CURRENT:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_OUTPUT_MODE_CURRENT;
|
||||||
case WL_OUTPUT_MODE_PREFERRED:
|
if (version >= 1)
|
||||||
return version >= 1;
|
valid |= WL_OUTPUT_MODE_PREFERRED;
|
||||||
default:
|
return (value & ~valid) == 0;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* WL_OUTPUT_MODE_ENUM */
|
#endif /* WL_OUTPUT_MODE_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_output
|
* @ingroup iface_wl_output
|
||||||
|
|
@ -4744,6 +4822,10 @@ enum wl_subcompositor_error {
|
||||||
*/
|
*/
|
||||||
WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0,
|
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
|
* @ingroup iface_wl_subcompositor
|
||||||
* Validate a wl_subcompositor error value.
|
* Validate a wl_subcompositor error value.
|
||||||
|
|
@ -4760,7 +4842,7 @@ wl_subcompositor_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
|
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_subcompositor
|
* @ingroup iface_wl_subcompositor
|
||||||
|
|
@ -4815,6 +4897,10 @@ enum wl_subsurface_error {
|
||||||
*/
|
*/
|
||||||
WL_SUBSURFACE_ERROR_BAD_SURFACE = 0,
|
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
|
* @ingroup iface_wl_subsurface
|
||||||
* Validate a wl_subsurface error value.
|
* Validate a wl_subsurface error value.
|
||||||
|
|
@ -4831,7 +4917,7 @@ wl_subsurface_error_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WL_SUBSURFACE_ERROR_ENUM */
|
#endif /* WL_SUBSURFACE_ERROR_ENUM_IS_VALID */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_wl_subsurface
|
* @ingroup iface_wl_subsurface
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,29 @@ enum intf_A_foo {
|
||||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
||||||
#endif /* INTF_A_FOO_ENUM */
|
#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
|
* @ingroup iface_intf_A
|
||||||
* @struct intf_A_listener
|
* @struct intf_A_listener
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,29 @@ enum intf_A_foo {
|
||||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
||||||
#endif /* INTF_A_FOO_ENUM */
|
#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
|
* @ingroup iface_intf_A
|
||||||
* @struct intf_A_listener
|
* @struct intf_A_listener
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,10 @@ enum intf_A_foo {
|
||||||
* @ingroup iface_intf_A
|
* @ingroup iface_intf_A
|
||||||
*/
|
*/
|
||||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
#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
|
* @ingroup iface_intf_A
|
||||||
* Validate a intf_A foo value.
|
* Validate a intf_A foo value.
|
||||||
|
|
@ -131,7 +135,52 @@ intf_A_foo_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* INTF_A_FOO_ENUM */
|
#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 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_intf_A
|
* @ingroup iface_intf_A
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,10 @@ enum intf_A_foo {
|
||||||
* @ingroup iface_intf_A
|
* @ingroup iface_intf_A
|
||||||
*/
|
*/
|
||||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
#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
|
* @ingroup iface_intf_A
|
||||||
* Validate a intf_A foo value.
|
* Validate a intf_A foo value.
|
||||||
|
|
@ -131,7 +135,52 @@ intf_A_foo_is_valid(uint32_t value, uint32_t version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* INTF_A_FOO_ENUM */
|
#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 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup iface_intf_A
|
* @ingroup iface_intf_A
|
||||||
|
|
|
||||||
|
|
@ -58,5 +58,12 @@
|
||||||
<entry name="negative" value="-1" since="2" summary="this is a negative value"/>
|
<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"/>
|
<entry name="deprecated" value="3" since="2" deprecated-since="3" summary="this is a deprecated value"/>
|
||||||
</enum>
|
</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>
|
</interface>
|
||||||
</protocol>
|
</protocol>
|
||||||
|
|
|
||||||
|
|
@ -924,7 +924,7 @@ TEST(versions)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
check_error_on_destroyed_object(void *data)
|
check_error_on_destroyed_object(void)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct wl_seat *seat;
|
struct wl_seat *seat;
|
||||||
|
|
@ -1043,7 +1043,7 @@ TEST(filtered_global_is_hidden)
|
||||||
1, d, bind_data_offer);
|
1, d, bind_data_offer);
|
||||||
wl_display_set_global_filter(d->wl_display, global_filter, NULL);
|
wl_display_set_global_filter(d->wl_display, global_filter, NULL);
|
||||||
|
|
||||||
client_create_noarg(d, get_globals);
|
client_create(d, get_globals, NULL);
|
||||||
display_run(d);
|
display_run(d);
|
||||||
|
|
||||||
wl_global_destroy(g);
|
wl_global_destroy(g);
|
||||||
|
|
@ -1052,13 +1052,13 @@ TEST(filtered_global_is_hidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_dynamic_globals(void *data)
|
get_dynamic_globals(void)
|
||||||
{
|
{
|
||||||
struct client *c = client_connect();
|
struct client *c = client_connect();
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
||||||
registry = wl_display_get_registry(c->wl_display);
|
registry = wl_display_get_registry(c->wl_display);
|
||||||
wl_registry_add_listener(registry, ®istry_listener_filtered, data);
|
wl_registry_add_listener(registry, ®istry_listener_filtered, NULL);
|
||||||
wl_display_roundtrip(c->wl_display);
|
wl_display_roundtrip(c->wl_display);
|
||||||
|
|
||||||
/* Wait for the server to create a new global */
|
/* 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
|
static void
|
||||||
zombie_client(void *data)
|
zombie_client(void)
|
||||||
{
|
{
|
||||||
struct client *c = client_connect();
|
struct client *c = client_connect();
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
@ -1376,7 +1376,7 @@ static const struct wl_registry_listener double_zombie_fd_registry_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
double_zombie_client(void *data)
|
double_zombie_client(void)
|
||||||
{
|
{
|
||||||
struct client *c = client_connect();
|
struct client *c = client_connect();
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
@ -1436,7 +1436,7 @@ static const struct wl_registry_listener bind_interface_mismatch_registry_listen
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
registry_bind_interface_mismatch_client(void *data)
|
registry_bind_interface_mismatch_client(void)
|
||||||
{
|
{
|
||||||
struct client *c = client_connect();
|
struct client *c = client_connect();
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
@ -1598,7 +1598,7 @@ static const struct wl_registry_listener global_remove_before_registry_listener
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
global_remove_before_client(void *data)
|
global_remove_before_client(void)
|
||||||
{
|
{
|
||||||
struct client *c = client_connect();
|
struct client *c = client_connect();
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
@ -1648,7 +1648,7 @@ static const struct wl_registry_listener global_remove_after_registry_listener =
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
global_remove_after_client(void *data)
|
global_remove_after_client(void)
|
||||||
{
|
{
|
||||||
struct client *c = client_connect();
|
struct client *c = client_connect();
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
@ -1695,6 +1695,75 @@ TEST(global_remove)
|
||||||
display_destroy(d);
|
display_destroy(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatch_single_read_events(struct wl_display *d)
|
||||||
|
{
|
||||||
|
if (wl_display_prepare_read(d) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
do {
|
||||||
|
ret = wl_display_flush(d);
|
||||||
|
} while (ret < 0 && (errno == EINTR || errno == EAGAIN));
|
||||||
|
assert(ret >= 0);
|
||||||
|
|
||||||
|
struct pollfd pfd[1];
|
||||||
|
pfd[0].fd = wl_display_get_fd(d);
|
||||||
|
pfd[0].events = POLLIN;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = poll(pfd, 1, -1);
|
||||||
|
} while (ret < 0 && errno == EINTR);
|
||||||
|
assert(ret > 0);
|
||||||
|
|
||||||
|
wl_display_read_events(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatch_single_client(void)
|
||||||
|
{
|
||||||
|
struct client *c = client_connect();
|
||||||
|
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
|
||||||
|
|
||||||
|
struct wl_registry *registry = wl_display_get_registry(c->wl_display);
|
||||||
|
|
||||||
|
dispatch_single_read_events(c->wl_display);
|
||||||
|
|
||||||
|
// [1815110.061] {Default Queue} wl_registry#3.global(1, "test", 1)
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
|
||||||
|
|
||||||
|
dispatch_single_read_events(c->wl_display);
|
||||||
|
|
||||||
|
// [1815110.067] {Default Queue} wl_registry#3.global(2, "wl_seat", 1)
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
|
||||||
|
|
||||||
|
// No more events
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
|
||||||
|
|
||||||
|
wl_registry_destroy(registry);
|
||||||
|
|
||||||
|
client_disconnect(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(dispatch_single)
|
||||||
|
{
|
||||||
|
struct display *d = display_create();
|
||||||
|
|
||||||
|
struct wl_global *global = wl_global_create(d->wl_display,
|
||||||
|
&wl_seat_interface,
|
||||||
|
1, d, bind_seat);
|
||||||
|
|
||||||
|
client_create_noarg(d, dispatch_single_client);
|
||||||
|
|
||||||
|
display_run(d);
|
||||||
|
|
||||||
|
wl_global_destroy(global);
|
||||||
|
|
||||||
|
display_destroy(d);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
terminate_display(void *arg)
|
terminate_display(void *arg)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,19 @@ 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_THIRD, 2));
|
||||||
|
|
||||||
assert(intf_A_foo_is_valid(INTF_A_FOO_NEGATIVE, 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'
|
output: 'tests-protocol.c'
|
||||||
)
|
)
|
||||||
|
|
||||||
executable(
|
exec_fd_leak_checker = executable(
|
||||||
'exec-fd-leak-checker',
|
'exec-fd-leak-checker',
|
||||||
'exec-fd-leak-checker.c',
|
'exec-fd-leak-checker.c',
|
||||||
dependencies: test_runner_dep
|
dependencies: test_runner_dep
|
||||||
|
|
@ -96,78 +96,116 @@ if get_option('scanner')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
tests = {
|
tests = {
|
||||||
'array-test': [],
|
'array-test': {},
|
||||||
'client-test': [ wayland_server_protocol_h ],
|
'client-test': {
|
||||||
'display-test': [
|
'extra_sources': [ wayland_server_protocol_h ],
|
||||||
wayland_client_protocol_h,
|
},
|
||||||
wayland_server_protocol_h,
|
'display-test': {
|
||||||
tests_server_protocol_h,
|
'extra_sources': [
|
||||||
tests_client_protocol_c,
|
wayland_client_protocol_h,
|
||||||
tests_protocol_c,
|
wayland_server_protocol_h,
|
||||||
],
|
tests_server_protocol_h,
|
||||||
'connection-test': [
|
tests_client_protocol_c,
|
||||||
wayland_client_protocol_h,
|
tests_protocol_c,
|
||||||
wayland_server_protocol_h,
|
],
|
||||||
],
|
},
|
||||||
'event-loop-test': [ wayland_server_protocol_h ],
|
'connection-test': {
|
||||||
'fixed-test': [],
|
'extra_sources': [
|
||||||
'interface-test': [ wayland_client_protocol_h ],
|
wayland_client_protocol_h,
|
||||||
'list-test': [],
|
wayland_server_protocol_h,
|
||||||
'map-test': [],
|
],
|
||||||
'sanity-test' : [
|
},
|
||||||
wayland_client_protocol_h,
|
'event-loop-test': {
|
||||||
wayland_server_protocol_h,
|
'extra_sources': [ wayland_server_protocol_h ],
|
||||||
],
|
},
|
||||||
'socket-test': [
|
'fixed-test': {},
|
||||||
wayland_client_protocol_h,
|
'interface-test': {
|
||||||
wayland_server_protocol_h,
|
'extra_sources': [ wayland_client_protocol_h ],
|
||||||
],
|
},
|
||||||
'queue-test': [
|
'list-test': {},
|
||||||
wayland_client_protocol_h,
|
'map-test': {},
|
||||||
wayland_server_protocol_h,
|
'sanity-test' : {
|
||||||
],
|
'extra_sources': [
|
||||||
'signal-test': [ wayland_server_protocol_h ],
|
wayland_client_protocol_h,
|
||||||
'newsignal-test': [
|
wayland_server_protocol_h,
|
||||||
# wayland-server.c is needed here to access wl_priv_* functions
|
],
|
||||||
files('../src/wayland-server.c'),
|
'runtime_deps': [ exec_fd_leak_checker ],
|
||||||
wayland_server_protocol_h,
|
},
|
||||||
],
|
'socket-test': {
|
||||||
'resources-test': [ wayland_server_protocol_h ],
|
'extra_sources': [
|
||||||
'message-test': [
|
wayland_client_protocol_h,
|
||||||
wayland_client_protocol_h,
|
wayland_server_protocol_h,
|
||||||
wayland_server_protocol_h,
|
],
|
||||||
],
|
},
|
||||||
'compositor-introspection-test': [
|
'queue-test': {
|
||||||
wayland_client_protocol_h,
|
'extra_sources': [
|
||||||
wayland_server_protocol_h,
|
wayland_client_protocol_h,
|
||||||
],
|
wayland_server_protocol_h,
|
||||||
'protocol-logger-test': [
|
],
|
||||||
wayland_client_protocol_h,
|
},
|
||||||
wayland_server_protocol_h,
|
'signal-test': {
|
||||||
],
|
'extra_sources': [ wayland_server_protocol_h ],
|
||||||
'headers-test': [
|
},
|
||||||
wayland_client_protocol_h,
|
'newsignal-test': {
|
||||||
wayland_server_protocol_h,
|
'extra_sources': [
|
||||||
'headers-protocol-test.c',
|
# wayland-server.c is needed here to access wl_priv_* functions
|
||||||
wayland_client_protocol_core_h,
|
files('../src/wayland-server.c'),
|
||||||
wayland_server_protocol_core_h,
|
wayland_server_protocol_h,
|
||||||
'headers-protocol-core-test.c',
|
],
|
||||||
],
|
},
|
||||||
'os-wrappers-test': [],
|
'resources-test': {
|
||||||
'proxy-test': [
|
'extra_sources': [ wayland_server_protocol_h ],
|
||||||
wayland_client_protocol_h,
|
},
|
||||||
wayland_server_protocol_h,
|
'message-test': {
|
||||||
],
|
'extra_sources': [
|
||||||
'enum-validator-test': [],
|
wayland_client_protocol_h,
|
||||||
|
wayland_server_protocol_h,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'compositor-introspection-test': {
|
||||||
|
'extra_sources': [
|
||||||
|
wayland_client_protocol_h,
|
||||||
|
wayland_server_protocol_h,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'protocol-logger-test': {
|
||||||
|
'extra_sources': [
|
||||||
|
wayland_client_protocol_h,
|
||||||
|
wayland_server_protocol_h,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'headers-test': {
|
||||||
|
'extra_sources': [
|
||||||
|
wayland_client_protocol_h,
|
||||||
|
wayland_server_protocol_h,
|
||||||
|
'headers-protocol-test.c',
|
||||||
|
wayland_client_protocol_core_h,
|
||||||
|
wayland_server_protocol_core_h,
|
||||||
|
'headers-protocol-core-test.c',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'os-wrappers-test': {
|
||||||
|
'runtime_deps': [ exec_fd_leak_checker ],
|
||||||
|
},
|
||||||
|
'proxy-test': {
|
||||||
|
'extra_sources': [
|
||||||
|
wayland_client_protocol_h,
|
||||||
|
wayland_server_protocol_h,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'enum-validator-test': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach test_name, test_extra_sources: tests
|
foreach test_name, test_extras : tests
|
||||||
|
test_extra_sources = test_extras.get('extra_sources', [])
|
||||||
|
test_runtime_deps = test_extras.get('runtime_deps', [])
|
||||||
test_sources = [ test_name + '.c' ] + test_extra_sources
|
test_sources = [ test_name + '.c' ] + test_extra_sources
|
||||||
test_deps = [test_runner_dep, epoll_dep]
|
test_deps = [test_runner_dep, epoll_dep]
|
||||||
bin = executable(test_name, test_sources, dependencies: test_deps)
|
bin = executable(test_name, test_sources, dependencies: test_deps)
|
||||||
test(
|
test(
|
||||||
test_name,
|
test_name,
|
||||||
bin,
|
bin,
|
||||||
|
depends: test_runtime_deps,
|
||||||
env: [
|
env: [
|
||||||
'TEST_SRC_DIR=@0@'.format(meson.current_source_dir()),
|
'TEST_SRC_DIR=@0@'.format(meson.current_source_dir()),
|
||||||
'TEST_BUILD_DIR=@0@'.format(meson.current_build_dir()),
|
'TEST_BUILD_DIR=@0@'.format(meson.current_build_dir()),
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "wayland-server.h"
|
#include "wayland-server.h"
|
||||||
#include "test-runner.h"
|
#include "test-runner.h"
|
||||||
#include "test-compositor.h"
|
#include "test-compositor.h"
|
||||||
|
#include "../src/timespec-util.h"
|
||||||
|
|
||||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
|
|
||||||
|
|
@ -571,6 +572,68 @@ client_test_queue_names(void)
|
||||||
wl_display_disconnect(display);
|
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
|
static void
|
||||||
dummy_bind(struct wl_client *client,
|
dummy_bind(struct wl_client *client,
|
||||||
void *data, uint32_t version, uint32_t id)
|
void *data, uint32_t version, uint32_t id)
|
||||||
|
|
@ -709,3 +772,27 @@ TEST(queue_names)
|
||||||
|
|
||||||
display_destroy(d);
|
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
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct client *client_connect()
|
struct client *client_connect(void)
|
||||||
{
|
{
|
||||||
struct wl_registry *reg;
|
struct wl_registry *reg;
|
||||||
struct client *c = calloc(1, sizeof *c);
|
struct client *c = calloc(1, sizeof *c);
|
||||||
|
|
|
||||||
|
|
@ -118,5 +118,17 @@ struct client_info *client_create_with_name(struct display *d,
|
||||||
void *data,
|
void *data,
|
||||||
const char *name);
|
const char *name);
|
||||||
#define client_create(d, c, data) client_create_with_name((d), (c), data, (#c))
|
#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) \
|
#define client_create_noarg(d, c) \
|
||||||
client_create_with_name((d), (void(*)(void *)) (c), NULL, (#c))
|
client_create_with_name_noarg((d), (c), (#c))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue