mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Compare commits
165 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d81525a235 | ||
|
|
4673ef7e9c | ||
|
|
77730f10a0 | ||
|
|
264da6a92b | ||
|
|
cd0d1543c0 | ||
|
|
90187031e6 | ||
|
|
eecf3f7635 | ||
|
|
adf84614ca | ||
|
|
ba9f9a446f | ||
|
|
53fbc2b0c1 | ||
|
|
fdac631d17 | ||
|
|
6c1da92018 | ||
|
|
ca83185e8a | ||
|
|
4a0c4e2119 | ||
|
|
387adc6a79 | ||
|
|
0de833da29 | ||
|
|
2978fd701a | ||
|
|
5c2f31d8d6 | ||
|
|
ce0ac4f29e | ||
|
|
1bee7aa4a7 | ||
|
|
6281ccbd3d | ||
|
|
ecff0ee10c | ||
|
|
827d0c30ad | ||
|
|
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 | ||
|
|
0b1626f473 | ||
|
|
4bade62938 | ||
|
|
17965d99e8 | ||
|
|
f870320958 | ||
|
|
9e4f256927 | ||
|
|
6963320218 | ||
|
|
e60c631ff2 | ||
|
|
9069af78a7 | ||
|
|
6e1db53916 | ||
|
|
80c65f862f | ||
|
|
da8e1bbc45 | ||
|
|
ee12e69b8f | ||
|
|
16aee2ec38 | ||
|
|
b258d5f361 | ||
|
|
5eeaac6e11 | ||
|
|
af1dc3ef4b | ||
|
|
03e304544b | ||
|
|
c5d145a602 | ||
|
|
37699a98b1 | ||
|
|
e7df1f2af2 | ||
|
|
ad4ed17335 | ||
|
|
d074d52902 | ||
|
|
36cef8653f | ||
|
|
4945f2664f | ||
|
|
2e0dbb7021 | ||
|
|
fbd7460737 | ||
|
|
2621484037 | ||
|
|
8a7ecd774c | ||
|
|
aa2a6d560b | ||
|
|
44b1c0c737 | ||
|
|
440defbd2b | ||
|
|
7a1e7dd549 | ||
|
|
830883e5b2 | ||
|
|
155dd63b58 | ||
|
|
47de87263c | ||
|
|
d80bce5f1a | ||
|
|
791912c678 | ||
|
|
a74aa93394 | ||
|
|
9c4213ed3e | ||
|
|
6a7284c632 | ||
|
|
d275bc7f84 | ||
|
|
8f499bf404 | ||
|
|
88ece8a44d | ||
|
|
b42218f790 | ||
|
|
2f17d480e8 | ||
|
|
9867bdb111 | ||
|
|
8c49ee3112 | ||
|
|
fd42f70baf | ||
|
|
f06736a8a0 | ||
|
|
9e233e31a2 | ||
|
|
8072ab0a50 | ||
|
|
647398ead4 | ||
|
|
56b9c92b98 | ||
|
|
dc1da181db | ||
|
|
6daa1b8713 | ||
|
|
0e139cfbc7 | ||
|
|
6626d4d98c | ||
|
|
86588fbdeb | ||
|
|
82d8b21827 | ||
|
|
8a19dc19a1 | ||
|
|
2a91f01d6c | ||
|
|
3007718b0c | ||
|
|
e4eb42d073 | ||
|
|
50ea9c5b1c | ||
|
|
edb943dc64 | ||
|
|
379a6f6759 | ||
|
|
63b0050561 | ||
|
|
a81f947aff | ||
|
|
7b27881cd1 | ||
|
|
72da004b3e | ||
|
|
e3908eb360 | ||
|
|
6d33346571 | ||
|
|
4ec379ebcc | ||
|
|
4a7348e48c | ||
|
|
f181de1bcf | ||
|
|
56dfdb7614 | ||
|
|
a3c499493b | ||
|
|
f3026c916e | ||
|
|
2aec19ce41 | ||
|
|
8f2a33cffc | ||
|
|
0e0ae7e290 | ||
|
|
11b17c1286 | ||
|
|
b1b97e8d34 | ||
|
|
d40052e083 | ||
|
|
3bac2e5fb8 | ||
|
|
1e259a255a | ||
|
|
307b23626d | ||
|
|
cdd890a6f8 |
64 changed files with 5444 additions and 900 deletions
|
|
@ -37,15 +37,13 @@
|
|||
# - documentation at https://freedesktop.pages.freedesktop.org/ci-templates/
|
||||
# - repo at https://gitlab.freedesktop.org/freedesktop/ci-templates/
|
||||
|
||||
# Here we use a fixed ref in order to isolate ourselves from ci-templates
|
||||
# API changes. If you need new features from ci-templates you must bump
|
||||
# this to the current SHA you require from the ci-templates repo, however
|
||||
# be aware that you may need to account for API changes when doing so.
|
||||
.templates_sha: &template_sha d5aa3941aa03c2f716595116354fb81eb8012acb # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||
|
||||
include:
|
||||
- project: 'freedesktop/ci-templates'
|
||||
ref: *template_sha
|
||||
# Here we use a fixed ref in order to isolate ourselves from ci-templates
|
||||
# API changes. If you need new features from ci-templates you must bump
|
||||
# this to the current SHA you require from the ci-templates repo, however
|
||||
# be aware that you may need to account for API changes when doing so.
|
||||
ref: 48c2c583a865bd59be21e8938df247faf460099c
|
||||
file:
|
||||
- '/templates/debian.yml'
|
||||
- '/templates/freebsd.yml'
|
||||
|
|
@ -64,6 +62,13 @@ stages:
|
|||
- "Build and test"
|
||||
- "Other build configurations"
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
|
||||
.ci-rules:
|
||||
rules:
|
||||
- when: on_success
|
||||
|
|
@ -72,12 +77,12 @@ stages:
|
|||
.os-debian:
|
||||
variables:
|
||||
BUILD_OS: debian
|
||||
FDO_DISTRIBUTION_VERSION: bullseye
|
||||
FDO_DISTRIBUTION_VERSION: bookworm
|
||||
FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config libexpat1-dev libffi-dev libxml2-dev doxygen graphviz xmlto xsltproc docbook-xsl python3-pip python3-setuptools ninja-build'
|
||||
FDO_DISTRIBUTION_EXEC: 'pip3 install meson==0.56.0'
|
||||
FDO_DISTRIBUTION_EXEC: 'pip3 install --break-system-packages meson~=0.57.2'
|
||||
# bump this tag every time you change something which requires rebuilding the
|
||||
# base image
|
||||
FDO_DISTRIBUTION_TAG: "2022-08-08.0"
|
||||
FDO_DISTRIBUTION_TAG: "2025-01-21.1"
|
||||
|
||||
.debian-x86_64:
|
||||
extends:
|
||||
|
|
@ -96,6 +101,7 @@ stages:
|
|||
- .os-debian
|
||||
variables:
|
||||
BUILD_ARCH: "armv7"
|
||||
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||
|
||||
|
||||
# Does not inherit .ci-rules as we only want it to run in MR context.
|
||||
|
|
@ -149,7 +155,6 @@ armv7-debian-container_prep:
|
|||
stage: "Base container"
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
||||
|
||||
|
||||
# Core build environment.
|
||||
|
|
@ -219,7 +224,7 @@ armv7-debian-container_prep:
|
|||
stage: "Build and test"
|
||||
script:
|
||||
- cd "$BUILDDIR"
|
||||
- meson --prefix="$PREFIX" -Dicon_directory=/usr/share/X11/icons -Dwerror=true ${MESON_BUILD_TYPE} ..
|
||||
- meson --prefix="$PREFIX" -Dicon_directory=/usr/share/X11/icons --fatal-meson-warnings -Dwerror=true ${MESON_BUILD_TYPE} ..
|
||||
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
- meson test --num-processes ${FDO_CI_CONCURRENT:-4}
|
||||
- ninja clean
|
||||
|
|
@ -301,14 +306,14 @@ armv7-release-debian-build:
|
|||
.os-freebsd:
|
||||
variables:
|
||||
BUILD_OS: freebsd
|
||||
FDO_DISTRIBUTION_VERSION: "13.1"
|
||||
FDO_DISTRIBUTION_VERSION: "14.3"
|
||||
FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2'
|
||||
# bump this tag every time you change something which requires rebuilding the
|
||||
# base image
|
||||
FDO_DISTRIBUTION_TAG: "2022-09-08.0"
|
||||
FDO_DISTRIBUTION_TAG: "2025-07-20.0"
|
||||
# Don't build documentation since installing the required tools massively
|
||||
# increases the VM image (and therefore container) size.
|
||||
MESON_ARGS: "-Ddocumentation=false"
|
||||
MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false"
|
||||
|
||||
.freebsd-x86_64:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ library only. Issues with Wayland during day-to-day usage are almost
|
|||
certainly a bug in your compositor and **not** a bug with in this
|
||||
repository.
|
||||
|
||||
Please remove this comment before filing your bug.
|
||||
Please remove this comment before filing your issue.
|
||||
-->
|
||||
33
.triage-policies.yml
Normal file
33
.triage-policies.yml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# This is a set of bugbot commands for issues and merge requests - setting any of the
|
||||
# bugbot::foo labels will trigger gitlab-triage to run with this ruleset (well, the
|
||||
# one we have on the main branch at the time)
|
||||
#
|
||||
# Note that for adding labels, the label must first created in the project.
|
||||
resource_rules:
|
||||
issues:
|
||||
rules:
|
||||
- name: "Close bugs that aren't Wayland bugs"
|
||||
conditions:
|
||||
labels:
|
||||
- "bugbot::not-wayland"
|
||||
actions:
|
||||
remove_labels:
|
||||
- "bugbot::not-wayland"
|
||||
comment: |
|
||||
Thank you for the report, but your issue does not look like it would belong here. Sorry.
|
||||
|
||||
This repository is for the Wayland protocol specification and the
|
||||
low-level C library that deals with the protocol.
|
||||
|
||||
This issue here is a bug not with the protocol itself but with either
|
||||
- your compositor or desktop environment's implementation of the Wayland protocol and surrounding functionality,
|
||||
- the individual application that triggers this issue, or
|
||||
- the kernel driver used by your hardware
|
||||
|
||||
Please file the issue against your compositor/desktop environment, the application
|
||||
or the kernel drivers instead, whichever seems more likely to you. If you are not sure,
|
||||
file an issue against the application.
|
||||
status: "close"
|
||||
merge_requests:
|
||||
rules:
|
||||
[]
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
* http://fontforge.org/pcf-format.html
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
|||
|
|
@ -551,4 +551,19 @@ static struct cursor_metadata {
|
|||
{ "xterm", 9, 16, 4, 8, 2400 },
|
||||
{ "hand1", 13, 16, 12, 0, 2544 },
|
||||
{ "watch", 16, 16, 15, 9, 2752 },
|
||||
|
||||
/* https://www.freedesktop.org/wiki/Specifications/cursor-spec/ */
|
||||
{ "sw-resize", 16, 16, 1, 14, 0 },
|
||||
{ "se-resize", 16, 16, 14, 14, 256 },
|
||||
{ "s-resize", 15, 16, 7, 14, 512 },
|
||||
{ "all-scroll", 16, 16, 8, 8, 752 },
|
||||
{ "default", 10, 16, 1, 1, 1008 },
|
||||
{ "w-resize", 16, 15, 1, 7, 1168 },
|
||||
{ "e-resize", 16, 15, 14, 7, 1408 },
|
||||
{ "nw-resize", 16, 16, 1, 1, 1648 },
|
||||
{ "ne-resize", 16, 16, 14, 1, 1904 },
|
||||
{ "n-resize", 15, 16, 7, 1, 2160 },
|
||||
{ "text", 9, 16, 4, 8, 2400 },
|
||||
{ "pointer", 13, 16, 12, 0, 2544 },
|
||||
{ "wait", 16, 16, 15, 9, 2752 },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@
|
|||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/* Fallback to no flag when missing the definition */
|
||||
#ifndef MFD_NOEXEC_SEAL
|
||||
#define MFD_NOEXEC_SEAL 0
|
||||
#endif
|
||||
|
||||
#include "os-compatibility.h"
|
||||
|
||||
#ifndef HAVE_MKOSTEMP
|
||||
|
|
@ -124,7 +129,21 @@ os_create_anonymous_file(off_t size)
|
|||
int fd;
|
||||
|
||||
#ifdef HAVE_MEMFD_CREATE
|
||||
fd = memfd_create("wayland-cursor", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
/*
|
||||
* Linux kernels older than 6.3 reject MFD_NOEXEC_SEAL with EINVAL.
|
||||
* Try first *with* it, and if that fails, try again *without* it.
|
||||
*/
|
||||
errno = 0;
|
||||
fd = memfd_create(
|
||||
"wayland-cursor",
|
||||
MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL);
|
||||
|
||||
if (fd < 0 && errno == EINVAL && MFD_NOEXEC_SEAL != 0) {
|
||||
fd = memfd_create(
|
||||
"wayland-cursor",
|
||||
MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
}
|
||||
|
||||
if (fd >= 0) {
|
||||
/* We can add this seal before calling posix_fallocate(), as
|
||||
* the file is currently zero-sized anyway.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "xcursor.h"
|
||||
#include "wayland-cursor.h"
|
||||
#include "wayland-client.h"
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -68,11 +69,16 @@ shm_pool_create(struct wl_shm *shm, int size)
|
|||
goto err_close;
|
||||
|
||||
pool->pool = wl_shm_create_pool(shm, pool->fd, size);
|
||||
if (!pool->pool)
|
||||
goto err_unmap;
|
||||
|
||||
pool->size = size;
|
||||
pool->used = 0;
|
||||
|
||||
return pool;
|
||||
|
||||
err_unmap:
|
||||
munmap(pool->data, size);
|
||||
err_close:
|
||||
close(pool->fd);
|
||||
err_free:
|
||||
|
|
@ -279,7 +285,8 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
|
|||
{
|
||||
struct cursor *cursor;
|
||||
struct cursor_image *image;
|
||||
int i, size;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
cursor = malloc(sizeof *cursor);
|
||||
if (!cursor)
|
||||
|
|
@ -309,7 +316,12 @@ wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
|
|||
image->image.hotspot_y = images->images[i]->yhot;
|
||||
image->image.delay = images->images[i]->delay;
|
||||
|
||||
size = image->image.width * image->image.height * 4;
|
||||
size = (size_t) image->image.width * image->image.height * 4;
|
||||
if (size > INT_MAX) {
|
||||
free(image);
|
||||
break;
|
||||
}
|
||||
|
||||
image->offset = shm_pool_allocate(theme->pool, size);
|
||||
if (image->offset < 0) {
|
||||
free(image);
|
||||
|
|
@ -339,6 +351,8 @@ load_callback(struct xcursor_images *images, void *data)
|
|||
{
|
||||
struct wl_cursor_theme *theme = data;
|
||||
struct wl_cursor *cursor;
|
||||
struct wl_cursor **p;
|
||||
size_t s;
|
||||
|
||||
if (wl_cursor_theme_get_cursor(theme, images->name)) {
|
||||
xcursor_images_destroy(images);
|
||||
|
|
@ -348,15 +362,14 @@ load_callback(struct xcursor_images *images, void *data)
|
|||
cursor = wl_cursor_create_from_xcursor_images(images, theme);
|
||||
|
||||
if (cursor) {
|
||||
theme->cursor_count++;
|
||||
theme->cursors =
|
||||
realloc(theme->cursors,
|
||||
theme->cursor_count * sizeof theme->cursors[0]);
|
||||
s = theme->cursor_count + 1;
|
||||
p = realloc(theme->cursors, s * sizeof theme->cursors[0]);
|
||||
|
||||
if (theme->cursors == NULL) {
|
||||
theme->cursor_count--;
|
||||
if (p == NULL) {
|
||||
free(cursor);
|
||||
} else {
|
||||
theme->cursor_count = s;
|
||||
theme->cursors = p;
|
||||
theme->cursors[theme->cursor_count - 1] = cursor;
|
||||
}
|
||||
}
|
||||
|
|
@ -384,6 +397,9 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
|
|||
if (!theme)
|
||||
return NULL;
|
||||
|
||||
if (size < 0 || (size > 0 && INT_MAX / size / 4 < size))
|
||||
goto err;
|
||||
|
||||
if (!name)
|
||||
name = "default";
|
||||
|
||||
|
|
@ -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);
|
||||
if (!theme->pool)
|
||||
goto out_error_pool;
|
||||
goto err;
|
||||
|
||||
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;
|
||||
|
||||
out_error_pool:
|
||||
err:
|
||||
free(theme);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
107
cursor/xcursor.c
107
cursor/xcursor.c
|
|
@ -259,6 +259,8 @@ xcursor_read_file_header(FILE *file)
|
|||
return NULL;
|
||||
if (!xcursor_read_uint(file, &head.ntoc))
|
||||
return NULL;
|
||||
if (head.header < XCURSOR_FILE_HEADER_LEN)
|
||||
return NULL;
|
||||
skip = head.header - XCURSOR_FILE_HEADER_LEN;
|
||||
if (skip)
|
||||
if (fseek(file, skip, SEEK_CUR) == EOF)
|
||||
|
|
@ -571,7 +573,7 @@ xcursor_build_theme_dir(const char *dir, const char *theme)
|
|||
* add space for any needed directory separators, one per component,
|
||||
* and one for the trailing null
|
||||
*/
|
||||
full_size = 1 + homelen + 1 + dirlen + 1 + themelen + 1;
|
||||
full_size = (size_t) 1 + homelen + 1 + dirlen + 1 + themelen + 1;
|
||||
full = malloc(full_size);
|
||||
if (!full)
|
||||
return NULL;
|
||||
|
|
@ -585,6 +587,7 @@ xcursor_build_fullname(const char *dir, const char *subdir, const char *file)
|
|||
{
|
||||
char *full;
|
||||
size_t full_size;
|
||||
int ret;
|
||||
|
||||
if (!dir || !subdir || !file)
|
||||
return NULL;
|
||||
|
|
@ -593,7 +596,11 @@ xcursor_build_fullname(const char *dir, const char *subdir, const char *file)
|
|||
full = malloc(full_size);
|
||||
if (!full)
|
||||
return NULL;
|
||||
snprintf(full, full_size, "%s/%s/%s", dir, subdir, file);
|
||||
ret = snprintf(full, full_size, "%s/%s/%s", dir, subdir, file);
|
||||
if (ret < 0) {
|
||||
free(full);
|
||||
return NULL;
|
||||
}
|
||||
return full;
|
||||
}
|
||||
|
||||
|
|
@ -681,11 +688,15 @@ load_all_cursors_from_dir(const char *path, int size,
|
|||
void *user_data)
|
||||
{
|
||||
FILE *f;
|
||||
DIR *dir = opendir(path);
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char *full;
|
||||
struct xcursor_images *images;
|
||||
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
dir = opendir(path);
|
||||
if (!dir)
|
||||
return;
|
||||
|
||||
|
|
@ -721,38 +732,45 @@ load_all_cursors_from_dir(const char *path, int size,
|
|||
closedir(dir);
|
||||
}
|
||||
|
||||
/** Load all the cursor of a theme
|
||||
*
|
||||
* This function loads all the cursor images of a given theme and its
|
||||
* inherited themes. Each cursor is loaded into an struct xcursor_images object
|
||||
* which is passed to the caller's load callback. If a cursor appears
|
||||
* more than once across all the inherited themes, the load callback
|
||||
* will be called multiple times, with possibly different struct xcursor_images
|
||||
* object which have the same name. The user is expected to destroy the
|
||||
* struct xcursor_images objects passed to the callback with
|
||||
* xcursor_images_destroy().
|
||||
*
|
||||
* \param theme The name of theme that should be loaded
|
||||
* \param size The desired size of the cursor images
|
||||
* \param load_callback A callback function that will be called
|
||||
* for each cursor loaded. The first parameter is the struct xcursor_images
|
||||
* object representing the loaded cursor and the second is a pointer
|
||||
* to data provided by the user.
|
||||
* \param user_data The data that should be passed to the load callback
|
||||
*/
|
||||
void
|
||||
xcursor_load_theme(const char *theme, int size,
|
||||
struct xcursor_nodelist {
|
||||
size_t nodelen;
|
||||
const char *node;
|
||||
struct xcursor_nodelist *next;
|
||||
};
|
||||
|
||||
static bool
|
||||
nodelist_contains(struct xcursor_nodelist *nodelist, const char *s, size_t ss)
|
||||
{
|
||||
struct xcursor_nodelist *vi;
|
||||
|
||||
for (vi = nodelist; vi && vi->node; vi = vi->next) {
|
||||
if (vi->nodelen == ss && !strncmp(s, vi->node, vi->nodelen))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
xcursor_load_theme_protected(const char *theme, int size,
|
||||
void (*load_callback)(struct xcursor_images *, void *),
|
||||
void *user_data)
|
||||
void *user_data,
|
||||
struct xcursor_nodelist *visited_nodes)
|
||||
{
|
||||
char *full, *dir;
|
||||
char *inherits = NULL;
|
||||
const char *path, *i;
|
||||
char *xcursor_path;
|
||||
size_t si;
|
||||
struct xcursor_nodelist current_node;
|
||||
|
||||
if (!theme)
|
||||
theme = "default";
|
||||
|
||||
current_node.next = visited_nodes;
|
||||
current_node.node = theme;
|
||||
current_node.nodelen = strlen(theme);
|
||||
visited_nodes = ¤t_node;
|
||||
|
||||
xcursor_path = xcursor_library_path();
|
||||
for (path = xcursor_path;
|
||||
path;
|
||||
|
|
@ -775,9 +793,44 @@ xcursor_load_theme(const char *theme, int size,
|
|||
free(dir);
|
||||
}
|
||||
|
||||
for (i = inherits; i; i = xcursor_next_path(i))
|
||||
xcursor_load_theme(i, size, load_callback, user_data);
|
||||
for (i = inherits; i; i = xcursor_next_path(i)) {
|
||||
si = strlen(i);
|
||||
if (nodelist_contains(visited_nodes, i, si))
|
||||
continue;
|
||||
xcursor_load_theme_protected(i, size, load_callback, user_data, visited_nodes);
|
||||
}
|
||||
|
||||
free(inherits);
|
||||
free(xcursor_path);
|
||||
}
|
||||
|
||||
/** Load all the cursors of a theme
|
||||
*
|
||||
* This function loads all the cursor images of a given theme and its
|
||||
* inherited themes. Each cursor is loaded into a struct xcursor_images object
|
||||
* which is passed to the caller's load callback. If a cursor appears
|
||||
* more than once across all the inherited themes, the load callback
|
||||
* will be called multiple times, with possibly different struct xcursor_images
|
||||
* objects which have the same name. The user is expected to destroy the
|
||||
* struct xcursor_images objects passed to the callback with
|
||||
* xcursor_images_destroy().
|
||||
*
|
||||
* \param theme The name of theme that should be loaded
|
||||
* \param size The desired size of the cursor images
|
||||
* \param load_callback A callback function that will be called
|
||||
* for each cursor loaded. The first parameter is the struct xcursor_images
|
||||
* object representing the loaded cursor and the second is a pointer
|
||||
* to data provided by the user.
|
||||
* \param user_data The data that should be passed to the load callback
|
||||
*/
|
||||
void
|
||||
xcursor_load_theme(const char *theme, int size,
|
||||
void (*load_callback)(struct xcursor_images *, void *),
|
||||
void *user_data)
|
||||
{
|
||||
xcursor_load_theme_protected(theme,
|
||||
size,
|
||||
load_callback,
|
||||
user_data,
|
||||
NULL);
|
||||
}
|
||||
|
|
|
|||
139
doc/publican/sources/Color.xml
Normal file
139
doc/publican/sources/Color.xml
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
|
||||
%BOOK_ENTITIES;
|
||||
]>
|
||||
|
||||
<chapter id="chap-Color-Management">
|
||||
<title>Color management</title>
|
||||
|
||||
<section id="sect-Color-Management-preface">
|
||||
<title>Overview</title>
|
||||
|
||||
<para>
|
||||
Color management in Wayland considers only displays. All pictures in
|
||||
Wayland are always display-referred, meaning that the pixel values are
|
||||
intended as-is for some specific display where they would produce the
|
||||
light emissions (<ulink
|
||||
url="https://cie.co.at/eilvterm/17-23-002">stimuli</ulink>) the picture's
|
||||
author desired. Wayland does not support displaying "raw" camera or
|
||||
scanner images as they are not display-referred, nor are they even
|
||||
pictures without complex and subjective processing.
|
||||
</para>
|
||||
<para>
|
||||
Stimuli — the picture itself — are only half of the picture reproduction.
|
||||
The other half is the environment where a display is viewed. A striking
|
||||
example is comparing a brightly lit office to a dark movie theater, the
|
||||
stimuli required to produce a good reading of the picture is greatly
|
||||
different. Therefore display-referred does not include only the display
|
||||
but the viewing environment as well.
|
||||
</para>
|
||||
<para>
|
||||
Window systems have been very well capable of operating without any
|
||||
explicit consideration to color management. This is because there used to
|
||||
be the implicit assumption of the standard display, the sRGB display,
|
||||
which all computer monitors implemented, more or less. The viewing
|
||||
environment was and still is accounted by adjusting the display and/or the
|
||||
room to produce a workable experience. Pictures are authored on a computer
|
||||
system by drawing, painting and adjusting the picture until it looks right
|
||||
on the author's monitor. This implicitly builds the standard display and
|
||||
environment assumption into the picture data. Deviations from the sRGB
|
||||
specification were minor enough that they often did not matter if not in a
|
||||
professional context like the printing industry. Displaying video material
|
||||
required some more attention to the details, because video and television
|
||||
standards differ enough from the sRGB display. What really made explicit
|
||||
color management a hard requirement for entertainment is the coming of
|
||||
wide color gamut (WCG) and high dynamic range (HDR) materials and
|
||||
displays.
|
||||
</para>
|
||||
<para>
|
||||
The color management design in Wayland follows the general Wayland design
|
||||
principles: compositors tell clients what would be the optimal thing to
|
||||
do, clients tell the compositors what kind of pictures they are actually
|
||||
producing, and then compositors display those pictures the best they can.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="sect-Color-Management-Protocol">
|
||||
<title>Protocol Interfaces</title>
|
||||
|
||||
<para>
|
||||
Color management interfaces in Wayland and divided into two protocols:
|
||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-management?ref_type=heads">color-management</ulink>
|
||||
and
|
||||
<ulink url="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/tree/main/staging/color-representation?ref_type=heads">color-representation</ulink>.
|
||||
They are designed to work together, but they can also be used
|
||||
independently when the other one is not needed.
|
||||
</para>
|
||||
|
||||
<section id="sect-Color-Management-Protocol-color-management">
|
||||
<title>Color-management</title>
|
||||
|
||||
<para>
|
||||
Color management protocol has two main purposes. First, it puts the
|
||||
responsibility of color management on the compositor. This means that
|
||||
clients do not necessarily need to care about color management at all,
|
||||
and can display just fine by using the traditional standard display
|
||||
assumption even when the actual display is wildly different. Clients
|
||||
can also choose to target some other assumed display and let the
|
||||
compositor handle it, or they can explicitly render for the actual
|
||||
display at hand. Second, when the window system has multiple different
|
||||
monitors, and a wl_surface happens to span more than one monitor, the
|
||||
compositor can display the surface content correctly on all spanned
|
||||
monitors simultaneously, as much as physically possible.
|
||||
</para>
|
||||
<para>
|
||||
Color-management protocol concentrates on colorimetry: when you have a
|
||||
pixel with RGB values, what stimulus do those values represent. The
|
||||
stimulus definition follows the CIE 1931 two-degree observer model. Some
|
||||
core concepts here are color primaries, white point, transfer function,
|
||||
and dynamic range. The viewing environment is represented in an
|
||||
extremely simplified way as the reference white luminance. The
|
||||
connection between pixel RGB values and stimulus plus viewing
|
||||
environment is recorded in an <emphasis>image description</emphasis>
|
||||
object. Clients can create image description objects and tag
|
||||
<code>wl_surface</code>s with them, to indicate what kind of surface
|
||||
content there will be. Clients can also ask what image description the
|
||||
compositor would prefer to have on the <code>wl_surface</code>, and that
|
||||
preference can change over time, e.g. when the <code>wl_surface</code>
|
||||
is moved from one
|
||||
<code>wl_output</code> to another. Following the compositor's preference
|
||||
may provide advantages in image quality and power consumption.
|
||||
</para>
|
||||
<para>
|
||||
Image description objects can come in two flavors: parametric and
|
||||
ICC-based. The above was written with parametric image descriptions in
|
||||
mind, and they have first-class support for HDR. ICC-based image
|
||||
descriptions are wrapping an ICC profile and have no other data. ICC
|
||||
profiles are the standard tool for standard dynamic range (SDR) display
|
||||
color management. This means the capabilities between the two flavors
|
||||
differ, and one cannot always be replaced by the other. Compositor
|
||||
support for each flavor is optional.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="sect-Color-Management-Protocol-color-representation">
|
||||
<title>Color-representation</title>
|
||||
|
||||
<para>
|
||||
Color-representation protocol deals with (potentially sub-sampled)
|
||||
YCbCr-RGB conversion, quantization range, and the inclusion of alpha in
|
||||
the RGB color channels, a.k.a. pre-multiplication. There are several
|
||||
different specifications on how an YCbCr-like (including ICtCp) signal,
|
||||
with chroma sub-sampling or not, is created from a full-resolution RGB
|
||||
image. Again, a client can tag a <code>wl_surface</code> with
|
||||
color-representation metadata to tell the compositor what kind of pixel
|
||||
data will be displayed through the wl_surface.
|
||||
</para>
|
||||
<para>
|
||||
The main purpose of color-representation is to correctly off-load the
|
||||
YCbCr-RGB conversion to the compositor, which can then opportunistically
|
||||
off-load it further to very power-efficient fixed-function circuitry in
|
||||
a display controller. This can significantly reduce power consumption
|
||||
when watching videos compared to using a GPU for the same, and on some
|
||||
embedded hardware platforms it is a hard requirement for processing high
|
||||
resolution video.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
</para>
|
||||
<para>
|
||||
Overall, the philosophy of Wayland is to provide clients with a way to
|
||||
manage windows and how their contents 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
|
||||
pass buffer handles between clients and the compositing manager.
|
||||
</para>
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@
|
|||
in the environment). Beginning in Wayland 1.15, implementations can
|
||||
optionally support server socket endpoints located at arbitrary
|
||||
locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis>
|
||||
to the absolute path at which the server endpoint listens.
|
||||
to the absolute path at which the server endpoint listens. The socket may
|
||||
also be provided through file descriptor inheritance, in which case
|
||||
<emphasis>WAYLAND_SOCKET</emphasis> is set.
|
||||
</para>
|
||||
<para>
|
||||
Every message is structured as 32-bit words; values are represented in the
|
||||
|
|
@ -150,9 +152,10 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Starts with an unsigned 32-bit length (including null terminator),
|
||||
followed by the string contents, including terminating null byte,
|
||||
then padding to a 32-bit boundary. A null value is represented
|
||||
with a length of 0.
|
||||
followed by the UTF-8 encoded string contents, including
|
||||
terminating null byte, then padding to a 32-bit boundary. A null
|
||||
value is represented with a length of 0. Interior null bytes are
|
||||
not permitted.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
@ -312,9 +315,10 @@
|
|||
reserved to represent a null or non-existent object.
|
||||
|
||||
For efficiency purposes, the IDs are densely packed in the sense that
|
||||
the ID N will not be used until N-1 has been used. Any ID allocation
|
||||
algorithm that does not maintain this property is incompatible with
|
||||
the implementation in libwayland.
|
||||
the ID N will not be used until N-1 has been used. This ordering is
|
||||
not merely a guideline, but a strict requirement, and there are
|
||||
implementations of the protocol that rigorously enforce this rule,
|
||||
including the ubiquitous libwayland.
|
||||
</para>
|
||||
</section>
|
||||
<section id="sect-Protocol-Compositor">
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
<xi:include href="Architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<xi:include href="Protocol.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<xi:include href="Xwayland.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<xi:include href="Color.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<xi:include href="ProtocolSpec.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<xi:include href="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||
<xi:include href="Server.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ publican_sources = [
|
|||
'Protocol.xml',
|
||||
'Xwayland.xml',
|
||||
'Compositors.xml',
|
||||
'Color.xml',
|
||||
'Client.xml',
|
||||
'Server.xml'
|
||||
]
|
||||
|
|
|
|||
|
|
@ -9,18 +9,27 @@ wayland_egl = library(
|
|||
install: true
|
||||
)
|
||||
|
||||
executable('wayland-egl-abi-check', 'wayland-egl-abi-check.c')
|
||||
if get_option('tests')
|
||||
wayland_egl_abi_check = executable('wayland-egl-abi-check', 'wayland-egl-abi-check.c')
|
||||
test('wayland-egl abi check', wayland_egl_abi_check)
|
||||
|
||||
nm_path = find_program('nm').full_path()
|
||||
|
||||
test(
|
||||
'wayland-egl symbols check',
|
||||
find_program('wayland-egl-symbols-check'),
|
||||
env: [
|
||||
'WAYLAND_EGL_LIB=@0@'.format(wayland_egl.full_path()),
|
||||
'NM=@0@'.format(nm_path)
|
||||
]
|
||||
)
|
||||
if get_option('default_library') != 'static'
|
||||
nm_path = find_program(['llvm-nm', 'nm']).full_path()
|
||||
wayland_egl_shared = wayland_egl
|
||||
if get_option('default_library') == 'both'
|
||||
wayland_egl_shared = wayland_egl.get_shared_lib()
|
||||
endif
|
||||
test(
|
||||
'wayland-egl symbols check',
|
||||
find_program('wayland-egl-symbols-check'),
|
||||
depends: wayland_egl,
|
||||
env: [
|
||||
'WAYLAND_EGL_LIB=@0@'.format(wayland_egl_shared.full_path()),
|
||||
'NM=@0@'.format(nm_path)
|
||||
]
|
||||
)
|
||||
endif
|
||||
endif
|
||||
|
||||
install_headers([
|
||||
'wayland-egl.h',
|
||||
|
|
|
|||
13
meson.build
13
meson.build
|
|
@ -1,8 +1,8 @@
|
|||
project(
|
||||
'wayland', 'c',
|
||||
version: '1.22.0',
|
||||
version: '1.24.90',
|
||||
license: 'MIT',
|
||||
meson_version: '>= 0.56.0',
|
||||
meson_version: '>= 0.57.0',
|
||||
default_options: [
|
||||
'warning_level=2',
|
||||
'buildtype=debugoptimized',
|
||||
|
|
@ -16,7 +16,7 @@ config_h.set_quoted('PACKAGE', meson.project_name())
|
|||
config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
|
||||
cc_args = []
|
||||
if host_machine.system() != 'freebsd'
|
||||
if host_machine.system() not in ['freebsd', 'openbsd']
|
||||
cc_args += ['-D_POSIX_C_SOURCE=200809L']
|
||||
endif
|
||||
add_project_arguments(cc_args, language: 'c')
|
||||
|
|
@ -46,6 +46,7 @@ have_funcs = [
|
|||
'memfd_create',
|
||||
'mremap',
|
||||
'strndup',
|
||||
'gettid',
|
||||
]
|
||||
foreach f: have_funcs
|
||||
config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
|
||||
|
|
@ -69,7 +70,7 @@ endif
|
|||
config_h.set10('HAVE_BROKEN_MSG_CMSG_CLOEXEC', have_broken_msg_cmsg_cloexec)
|
||||
|
||||
if get_option('libraries')
|
||||
if host_machine.system() == 'freebsd'
|
||||
if host_machine.system() in ['freebsd', 'openbsd']
|
||||
# When building for FreeBSD, epoll(7) is provided by a userspace
|
||||
# wrapper around kqueue(2).
|
||||
epoll_dep = dependency('epoll-shim')
|
||||
|
|
@ -131,7 +132,9 @@ if get_option('scanner')
|
|||
'wayland-scanner.mk',
|
||||
'protocol/wayland.xml',
|
||||
'protocol/wayland.dtd',
|
||||
])
|
||||
],
|
||||
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'wayland'),
|
||||
)
|
||||
|
||||
install_data(
|
||||
[ 'wayland-scanner.m4' ],
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@
|
|||
<!ATTLIST request name CDATA #REQUIRED>
|
||||
<!ATTLIST request type CDATA #IMPLIED>
|
||||
<!ATTLIST request since CDATA #IMPLIED>
|
||||
<!ATTLIST request deprecated-since CDATA #IMPLIED>
|
||||
<!ELEMENT event (description?,arg*)>
|
||||
<!ATTLIST event name CDATA #REQUIRED>
|
||||
<!ATTLIST event type CDATA #IMPLIED>
|
||||
<!ATTLIST event since CDATA #IMPLIED>
|
||||
<!ATTLIST event deprecated-since CDATA #IMPLIED>
|
||||
<!ELEMENT enum (description?,entry*)>
|
||||
<!ATTLIST enum name CDATA #REQUIRED>
|
||||
<!ATTLIST enum since CDATA #IMPLIED>
|
||||
|
|
@ -21,6 +23,7 @@
|
|||
<!ATTLIST entry value CDATA #REQUIRED>
|
||||
<!ATTLIST entry summary CDATA #IMPLIED>
|
||||
<!ATTLIST entry since CDATA #IMPLIED>
|
||||
<!ATTLIST entry deprecated-since CDATA #IMPLIED>
|
||||
<!ELEMENT arg (description?)>
|
||||
<!ATTLIST arg name CDATA #REQUIRED>
|
||||
<!ATTLIST arg type CDATA #REQUIRED>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
compositor after the callback is fired and as such the client must not
|
||||
attempt to use it after that point.
|
||||
|
||||
The callback_data passed in the callback is the event serial.
|
||||
The callback_data passed in the callback is undefined and should be ignored.
|
||||
</description>
|
||||
<arg name="callback" type="new_id" interface="wl_callback"
|
||||
summary="callback object for the sync request"/>
|
||||
|
|
@ -212,7 +212,7 @@
|
|||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_shm_pool" version="1">
|
||||
<interface name="wl_shm_pool" version="2">
|
||||
<description summary="a shared memory pool">
|
||||
The wl_shm_pool object encapsulates a piece of memory shared
|
||||
between the compositor and client. Through the wl_shm_pool
|
||||
|
|
@ -262,17 +262,17 @@
|
|||
created, but using the new size. This request can only be
|
||||
used to make the pool bigger.
|
||||
|
||||
This request only changes the amount of bytes that are mmapped
|
||||
by the server and does not touch the file corresponding to the
|
||||
file descriptor passed at creation time. It is the client's
|
||||
responsibility to ensure that the file is at least as big as
|
||||
the new pool size.
|
||||
This request only changes the amount of bytes that are mmapped
|
||||
by the server and does not touch the file corresponding to the
|
||||
file descriptor passed at creation time. It is the client's
|
||||
responsibility to ensure that the file is at least as big as
|
||||
the new pool size.
|
||||
</description>
|
||||
<arg name="size" type="int" summary="new size of the pool, in bytes"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_shm" version="1">
|
||||
<interface name="wl_shm" version="2">
|
||||
<description summary="shared memory support">
|
||||
A singleton global object that provides support for shared
|
||||
memory.
|
||||
|
|
@ -419,6 +419,21 @@
|
|||
<entry name="xbgr16161616" value="0x38344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
|
||||
<entry name="argb16161616" value="0x38345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
|
||||
<entry name="abgr16161616" value="0x38344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
|
||||
<entry name="c1" value="0x20203143" summary="[7:0] C0:C1:C2:C3:C4:C5:C6:C7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
|
||||
<entry name="c2" value="0x20203243" summary="[7:0] C0:C1:C2:C3 2:2:2:2 four pixels/byte"/>
|
||||
<entry name="c4" value="0x20203443" summary="[7:0] C0:C1 4:4 two pixels/byte"/>
|
||||
<entry name="d1" value="0x20203144" summary="[7:0] D0:D1:D2:D3:D4:D5:D6:D7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
|
||||
<entry name="d2" value="0x20203244" summary="[7:0] D0:D1:D2:D3 2:2:2:2 four pixels/byte"/>
|
||||
<entry name="d4" value="0x20203444" summary="[7:0] D0:D1 4:4 two pixels/byte"/>
|
||||
<entry name="d8" value="0x20203844" summary="[7:0] D"/>
|
||||
<entry name="r1" value="0x20203152" summary="[7:0] R0:R1:R2:R3:R4:R5:R6:R7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
|
||||
<entry name="r2" value="0x20203252" summary="[7:0] R0:R1:R2:R3 2:2:2:2 four pixels/byte"/>
|
||||
<entry name="r4" value="0x20203452" summary="[7:0] R0:R1 4:4 two pixels/byte"/>
|
||||
<entry name="r10" value="0x20303152" summary="[15:0] x:R 6:10 little endian"/>
|
||||
<entry name="r12" value="0x20323152" summary="[15:0] x:R 4:12 little endian"/>
|
||||
<entry name="avuy8888" value="0x59555641" summary="[31:0] A:Cr:Cb:Y 8:8:8:8 little endian"/>
|
||||
<entry name="xvuy8888" value="0x59555658" summary="[31:0] X:Cr:Cb:Y 8:8:8:8 little endian"/>
|
||||
<entry name="p030" value="0x30333050" summary="2x2 subsampled Cr:Cb plane 10 bits per channel packed"/>
|
||||
</enum>
|
||||
|
||||
<request name="create_pool">
|
||||
|
|
@ -442,6 +457,17 @@
|
|||
</description>
|
||||
<arg name="format" type="uint" enum="format" summary="buffer pixel format"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<request name="release" type="destructor" since="2">
|
||||
<description summary="release the shm object">
|
||||
Using this request a client can tell the server that it is not going to
|
||||
use the shm object anymore.
|
||||
|
||||
Objects created via this interface remain unaffected.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_buffer" version="1">
|
||||
|
|
@ -453,9 +479,11 @@
|
|||
client provides and updates the contents is defined by the buffer factory
|
||||
interface.
|
||||
|
||||
If the buffer uses a format that has an alpha channel, the alpha channel
|
||||
is assumed to be premultiplied in the color channels unless otherwise
|
||||
specified.
|
||||
Color channels are assumed to be electrical rather than optical (in other
|
||||
words, encoded with a transfer function) unless otherwise specified. If
|
||||
the buffer uses a format that has an alpha channel, the alpha channel is
|
||||
assumed to be premultiplied into the electrical color channel values
|
||||
(after transfer function encoding) unless otherwise specified.
|
||||
|
||||
Note, because wl_buffer objects are created from multiple independent
|
||||
factory interfaces, the wl_buffer interface is frozen at version 1.
|
||||
|
|
@ -473,8 +501,10 @@
|
|||
<event name="release">
|
||||
<description summary="compositor releases buffer">
|
||||
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
|
||||
requested in the same wl_surface.commit that attaches this
|
||||
|
|
@ -847,6 +877,7 @@
|
|||
|
||||
<enum name="error">
|
||||
<entry name="role" value="0" summary="given wl_surface has another role"/>
|
||||
<entry name="used_source" value="1" summary="source has already been used"/>
|
||||
</enum>
|
||||
|
||||
<request name="start_drag">
|
||||
|
|
@ -868,7 +899,7 @@
|
|||
The icon surface is an optional (can be NULL) surface that
|
||||
provides an icon to be moved around with the cursor. Initially,
|
||||
the top-left corner of the icon surface is placed at the cursor
|
||||
hotspot, but subsequent wl_surface.attach request can move the
|
||||
hotspot, but subsequent wl_surface.offset requests can move the
|
||||
relative position. Attach requests must be confirmed with
|
||||
wl_surface.commit as usual. The icon surface is given the role of
|
||||
a drag-and-drop icon. If the icon surface already has another role,
|
||||
|
|
@ -876,6 +907,10 @@
|
|||
|
||||
The input region is ignored for wl_surfaces with the role of a
|
||||
drag-and-drop icon.
|
||||
|
||||
The given source may not be used in any further set_selection or
|
||||
start_drag requests. Attempting to reuse a previously-used source
|
||||
may send a used_source error.
|
||||
</description>
|
||||
<arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/>
|
||||
<arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/>
|
||||
|
|
@ -889,6 +924,10 @@
|
|||
to the data from the source on behalf of the client.
|
||||
|
||||
To unset the selection, set the source to NULL.
|
||||
|
||||
The given source may not be used in any further set_selection or
|
||||
start_drag requests. Attempting to reuse a previously-used source
|
||||
may send a used_source error.
|
||||
</description>
|
||||
<arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the selection"/>
|
||||
<arg name="serial" type="uint" summary="serial number of the event that triggered this request"/>
|
||||
|
|
@ -1411,7 +1450,7 @@
|
|||
<entry name="invalid_size" value="2" summary="buffer size is invalid"/>
|
||||
<entry name="invalid_offset" value="3" summary="buffer offset is invalid"/>
|
||||
<entry name="defunct_role_object" value="4"
|
||||
summary="surface was destroyed before its role object"/>
|
||||
summary="surface was destroyed before its role object"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
|
|
@ -1440,9 +1479,9 @@
|
|||
|
||||
When the bound wl_surface version is 5 or higher, passing any
|
||||
non-zero x or y is a protocol violation, and will result in an
|
||||
'invalid_offset' error being raised. The x and y arguments are ignored
|
||||
and do not change the pending state. To achieve equivalent semantics,
|
||||
use wl_surface.offset.
|
||||
'invalid_offset' error being raised. The x and y arguments are ignored
|
||||
and do not change the pending state. To achieve equivalent semantics,
|
||||
use wl_surface.offset.
|
||||
|
||||
Surface contents are double-buffered state, see wl_surface.commit.
|
||||
|
||||
|
|
@ -1467,7 +1506,8 @@
|
|||
the delivery of wl_buffer.release events becomes undefined. A well
|
||||
behaved client should not rely on wl_buffer.release events in this
|
||||
case. Alternatively, a client could create multiple wl_buffer objects
|
||||
from the same backing storage or use 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
|
||||
the surface contents. Destroying the wl_buffer before wl_buffer.release
|
||||
|
|
@ -1479,6 +1519,13 @@
|
|||
|
||||
If wl_surface.attach is sent with a NULL wl_buffer, the
|
||||
following wl_surface.commit will 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>
|
||||
<arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
|
||||
summary="buffer of surface contents"/>
|
||||
|
|
@ -1618,16 +1665,18 @@
|
|||
<description summary="commit pending surface state">
|
||||
Surface state (input, opaque, and damage regions, attached buffers,
|
||||
etc.) is double-buffered. Protocol requests modify the pending state,
|
||||
as opposed to the current state in use by the compositor. A commit
|
||||
request atomically applies all pending state, replacing the current
|
||||
state. After commit, the new pending state is as documented for each
|
||||
related request.
|
||||
as opposed to the active state in use by the compositor.
|
||||
|
||||
On commit, a pending wl_buffer is applied first, and all other state
|
||||
second. This means that all coordinates in double-buffered state are
|
||||
relative to the new wl_buffer coming into use, except for
|
||||
wl_surface.attach itself. If there is no pending wl_buffer, the
|
||||
coordinates are relative to the current surface contents.
|
||||
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
|
||||
to affect double-buffered state.
|
||||
|
|
@ -1666,10 +1715,12 @@
|
|||
|
||||
<request name="set_buffer_transform" since="2">
|
||||
<description summary="sets the buffer transformation">
|
||||
This request sets an optional transformation on how the compositor
|
||||
interprets the contents of the buffer attached to the surface. The
|
||||
accepted values for the transform parameter are the values for
|
||||
wl_output.transform.
|
||||
This request sets the transformation that the client has already applied
|
||||
to the content of the buffer. The accepted values for the transform
|
||||
parameter are the values for wl_output.transform.
|
||||
|
||||
The compositor applies the inverse of this transformation whenever it
|
||||
uses the buffer contents.
|
||||
|
||||
Buffer transform is double-buffered state, see wl_surface.commit.
|
||||
|
||||
|
|
@ -1725,11 +1776,11 @@
|
|||
a buffer that is larger (by a factor of scale in each dimension)
|
||||
than the desired surface size.
|
||||
|
||||
If scale is not positive the invalid_scale protocol error is
|
||||
If scale is not greater than 0 the invalid_scale protocol error is
|
||||
raised.
|
||||
</description>
|
||||
<arg name="scale" type="int"
|
||||
summary="positive scale for interpreting buffer contents"/>
|
||||
summary="scale for interpreting buffer contents"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
|
|
@ -1784,6 +1835,9 @@
|
|||
x and y, combined with the new surface size define in which
|
||||
directions the surface's size changes.
|
||||
|
||||
The exact semantics of wl_surface.offset are role-specific. Refer to
|
||||
the documentation of specific roles for more information.
|
||||
|
||||
Surface location offset is double-buffered state, see
|
||||
wl_surface.commit.
|
||||
|
||||
|
|
@ -1802,10 +1856,15 @@
|
|||
This event indicates the preferred buffer scale for this surface. It is
|
||||
sent whenever the compositor's preference changes.
|
||||
|
||||
Before receiving this event the preferred buffer scale for this surface
|
||||
is 1.
|
||||
|
||||
It is intended that scaling aware clients use this event to scale their
|
||||
content and use wl_surface.set_buffer_scale to indicate the scale they
|
||||
have rendered with. This allows clients to supply a higher detail
|
||||
buffer.
|
||||
|
||||
The compositor shall emit a scale value greater than 0.
|
||||
</description>
|
||||
<arg name="factor" type="int" summary="preferred scaling factor"/>
|
||||
</event>
|
||||
|
|
@ -1815,16 +1874,19 @@
|
|||
This event indicates the preferred buffer transform for this surface.
|
||||
It is sent whenever the compositor's preference changes.
|
||||
|
||||
It is intended that transform aware clients use this event to apply the
|
||||
transform to their content and use wl_surface.set_buffer_transform to
|
||||
indicate the transform they have rendered with.
|
||||
Before receiving this event the preferred buffer transform for this
|
||||
surface is normal.
|
||||
|
||||
Applying this transformation to the surface buffer contents and using
|
||||
wl_surface.set_buffer_transform might allow the compositor to use the
|
||||
surface buffer more efficiently.
|
||||
</description>
|
||||
<arg name="transform" type="uint" enum="wl_output.transform"
|
||||
summary="preferred transform"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_seat" version="9">
|
||||
<interface name="wl_seat" version="10">
|
||||
<description summary="group of input devices">
|
||||
A seat is a group of keyboards, pointer and touch devices. This
|
||||
object is published as a global during start up, or when such a
|
||||
|
|
@ -1852,9 +1914,10 @@
|
|||
|
||||
<event name="capabilities">
|
||||
<description summary="seat capabilities changed">
|
||||
This is emitted whenever a seat gains or loses the pointer,
|
||||
keyboard or touch capabilities. The argument is a capability
|
||||
enum containing the complete set of capabilities this seat has.
|
||||
This is sent on binding to the seat global or whenever a seat gains
|
||||
or loses the pointer, keyboard or touch capabilities.
|
||||
The argument is a capability enum containing the complete set of
|
||||
capabilities this seat has.
|
||||
|
||||
When the pointer capability is added, a client may create a
|
||||
wl_pointer object using the wl_seat.get_pointer request. This object
|
||||
|
|
@ -1936,9 +1999,9 @@
|
|||
The same seat names are used for all clients. Thus, the name can be
|
||||
shared across processes to refer to a specific wl_seat global.
|
||||
|
||||
The name event is sent after binding to the seat global. This event is
|
||||
only sent once per seat object, and the name does not change over the
|
||||
lifetime of the wl_seat global.
|
||||
The name event is sent after binding to the seat global, and should be sent
|
||||
before announcing capabilities. This event only sent once per seat object,
|
||||
and the name does not change over the lifetime of the wl_seat global.
|
||||
|
||||
Compositors may re-use the same seat name if the wl_seat global is
|
||||
destroyed and re-created later.
|
||||
|
|
@ -1957,7 +2020,7 @@
|
|||
|
||||
</interface>
|
||||
|
||||
<interface name="wl_pointer" version="9">
|
||||
<interface name="wl_pointer" version="10">
|
||||
<description summary="pointer input device">
|
||||
The wl_pointer interface represents one or more input devices,
|
||||
such as mice, which control the pointer location and pointer_focus
|
||||
|
|
@ -1992,9 +2055,9 @@
|
|||
where (x, y) are the coordinates of the pointer location, in
|
||||
surface-local coordinates.
|
||||
|
||||
On surface.attach requests to the pointer surface, hotspot_x
|
||||
On wl_surface.offset requests to the pointer surface, hotspot_x
|
||||
and hotspot_y are decremented by the x and y parameters
|
||||
passed to the request. Attach must be confirmed by
|
||||
passed to the request. The offset must be applied by
|
||||
wl_surface.commit as usual.
|
||||
|
||||
The hotspot can also be updated by passing the currently set
|
||||
|
|
@ -2248,7 +2311,7 @@
|
|||
<arg name="axis" type="uint" enum="axis" summary="the axis stopped with this event"/>
|
||||
</event>
|
||||
|
||||
<event name="axis_discrete" since="5">
|
||||
<event name="axis_discrete" since="5" deprecated-since="8">
|
||||
<description summary="axis click event">
|
||||
Discrete step information for scroll and other axes.
|
||||
|
||||
|
|
@ -2370,10 +2433,20 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_keyboard" version="9">
|
||||
<interface name="wl_keyboard" version="10">
|
||||
<description summary="keyboard input device">
|
||||
The wl_keyboard interface represents one or more keyboards
|
||||
associated with a seat.
|
||||
|
||||
Each wl_keyboard has the following logical state:
|
||||
|
||||
- an active surface (possibly null),
|
||||
- the keys currently logically down,
|
||||
- the active modifiers,
|
||||
- the active group.
|
||||
|
||||
By default, the active surface is null, the keys currently logically down
|
||||
are empty, the active modifiers and the active group are 0.
|
||||
</description>
|
||||
|
||||
<enum name="keymap_format">
|
||||
|
|
@ -2408,10 +2481,18 @@
|
|||
|
||||
The compositor must send the wl_keyboard.modifiers event after this
|
||||
event.
|
||||
|
||||
In the wl_keyboard logical state, this event sets the active surface to
|
||||
the surface argument and the keys currently logically down to the keys
|
||||
in the keys argument. The compositor must not send this event if the
|
||||
wl_keyboard already had an active surface immediately before this event.
|
||||
|
||||
Clients should not use the list of pressed keys to emulate key-press
|
||||
events. The order of keys in the list is unspecified.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
||||
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
|
||||
<arg name="keys" type="array" summary="the currently pressed keys"/>
|
||||
<arg name="keys" type="array" summary="the keys currently logically down"/>
|
||||
</event>
|
||||
|
||||
<event name="leave">
|
||||
|
|
@ -2422,8 +2503,10 @@
|
|||
The leave notification is sent before the enter notification
|
||||
for the new focus.
|
||||
|
||||
After this event client must assume that all keys, including modifiers,
|
||||
are lifted and also it must stop key repeating if there's some going on.
|
||||
In the wl_keyboard logical state, this event resets all values to their
|
||||
defaults. The compositor must not send this event if the active surface
|
||||
of the wl_keyboard was not equal to the surface argument immediately
|
||||
before this event.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial number of the leave event"/>
|
||||
<arg name="surface" type="object" interface="wl_surface" summary="surface that lost keyboard focus"/>
|
||||
|
|
@ -2432,9 +2515,18 @@
|
|||
<enum name="key_state">
|
||||
<description summary="physical key state">
|
||||
Describes the physical state of a key that produced the key event.
|
||||
|
||||
Since version 10, the key can be in a "repeated" pseudo-state which
|
||||
means the same as "pressed", but is used to signal repetition in the
|
||||
key event.
|
||||
|
||||
The key may only enter the repeated state after entering the pressed
|
||||
state and before entering the released state. This event may be
|
||||
generated multiple times while the key is down.
|
||||
</description>
|
||||
<entry name="released" value="0" summary="key is not pressed"/>
|
||||
<entry name="pressed" value="1" summary="key is pressed"/>
|
||||
<entry name="repeated" value="2" summary="key was repeated" since="10"/>
|
||||
</enum>
|
||||
|
||||
<event name="key">
|
||||
|
|
@ -2448,6 +2540,20 @@
|
|||
|
||||
If this event produces a change in modifiers, then the resulting
|
||||
wl_keyboard.modifiers event must be sent after this event.
|
||||
|
||||
In the wl_keyboard logical state, this event adds the key to the keys
|
||||
currently logically down (if the state argument is pressed) or removes
|
||||
the key from the keys currently logically down (if the state argument is
|
||||
released). The compositor must not send this event if the wl_keyboard
|
||||
did not have an active surface immediately before this event. The
|
||||
compositor must not send this event if state is pressed (resp. released)
|
||||
and the key was already logically down (resp. was not logically down)
|
||||
immediately before this event.
|
||||
|
||||
Since version 10, compositors may send key events with the "repeated"
|
||||
key state when a wl_keyboard.repeat_info event with a rate argument of
|
||||
0 has been received. This allows the compositor to take over the
|
||||
responsibility of key repetition.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial number of the key event"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
|
|
@ -2459,6 +2565,17 @@
|
|||
<description summary="modifier and group state">
|
||||
Notifies clients that the modifier and/or group state has
|
||||
changed, and it should update its local state.
|
||||
|
||||
The compositor may send this event without a surface of the client
|
||||
having keyboard focus, for example to tie modifier information to
|
||||
pointer focus instead. If a modifier event with pressed modifiers is sent
|
||||
without a prior enter event, the client can assume the modifier state is
|
||||
valid until it receives the next wl_keyboard.modifiers event. In order to
|
||||
reset the modifier state again, the compositor can send a
|
||||
wl_keyboard.modifiers event with no pressed modifiers.
|
||||
|
||||
In the wl_keyboard logical state, this event updates the modifiers and
|
||||
group.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial number of the modifiers event"/>
|
||||
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
|
||||
|
|
@ -2497,7 +2614,7 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_touch" version="9">
|
||||
<interface name="wl_touch" version="10">
|
||||
<description summary="touchscreen input device">
|
||||
The wl_touch interface represents a touchscreen
|
||||
associated with a seat.
|
||||
|
|
@ -2566,6 +2683,8 @@
|
|||
currently active on this client's surface. The client is
|
||||
responsible for finalizing the touch points, future touch points on
|
||||
this surface may reuse the touch point ID.
|
||||
|
||||
No frame event is required after the cancel event.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
|
|
@ -2665,10 +2784,9 @@
|
|||
</enum>
|
||||
|
||||
<enum name="transform">
|
||||
<description summary="transform from framebuffer to output">
|
||||
This describes the transform that a compositor will apply to a
|
||||
surface to compensate for the rotation or mirroring of an
|
||||
output device.
|
||||
<description summary="transformation applied to buffer contents">
|
||||
This describes transformations that clients and compositors apply to
|
||||
buffer contents.
|
||||
|
||||
The flipped values correspond to an initial flip around a
|
||||
vertical axis followed by rotation.
|
||||
|
|
@ -2700,6 +2818,10 @@
|
|||
The geometry event will be followed by a done event (starting from
|
||||
version 2).
|
||||
|
||||
Clients should use wl_surface.preferred_buffer_transform instead of the
|
||||
transform advertised by this event to find the preferred buffer
|
||||
transform to use for a surface.
|
||||
|
||||
Note: wl_output only advertises partial information about the output
|
||||
position and identification. Some compositors, for instance those not
|
||||
implementing a desktop-style output layout or those exposing virtual
|
||||
|
|
@ -2722,7 +2844,7 @@
|
|||
<arg name="model" type="string"
|
||||
summary="textual description of the model"/>
|
||||
<arg name="transform" type="int" enum="transform"
|
||||
summary="transform that maps framebuffer to output"/>
|
||||
summary="additional transformation applied to buffer contents during presentation"/>
|
||||
</event>
|
||||
|
||||
<enum name="mode" bitfield="true">
|
||||
|
|
@ -2795,8 +2917,9 @@
|
|||
This event contains scaling geometry information
|
||||
that is not in the geometry event. It may be sent after
|
||||
binding the output object or if the output scale changes
|
||||
later. If it is not sent, the client should assume a
|
||||
scale of 1.
|
||||
later. The compositor will emit a non-zero, positive
|
||||
value for scale. If it is not sent, the client should
|
||||
assume a scale of 1.
|
||||
|
||||
A scale larger than 1 means that the compositor will
|
||||
automatically scale surface buffers by this amount
|
||||
|
|
@ -2804,12 +2927,9 @@
|
|||
displays where applications rendering at the native
|
||||
resolution would be too small to be legible.
|
||||
|
||||
It is intended that scaling aware clients track the
|
||||
current output of a surface, and if it is on a scaled
|
||||
output it should use wl_surface.set_buffer_scale with
|
||||
the scale of the output. That way the compositor can
|
||||
avoid scaling the surface, and the client can supply
|
||||
a higher detail image.
|
||||
Clients should use wl_surface.preferred_buffer_scale
|
||||
instead of this event to find the preferred buffer
|
||||
scale to use for a surface.
|
||||
|
||||
The scale event will be followed by a done event.
|
||||
</description>
|
||||
|
|
@ -3035,6 +3155,11 @@
|
|||
|
||||
If the parent wl_surface object is destroyed, the sub-surface is
|
||||
unmapped.
|
||||
|
||||
A sub-surface never has the keyboard focus of any seat.
|
||||
|
||||
The wl_surface.offset request is ignored: clients must use set_position
|
||||
instead to move the sub-surface.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
|
|
@ -3060,9 +3185,7 @@
|
|||
surface area. Negative values are allowed.
|
||||
|
||||
The scheduled coordinates will take effect whenever the state of the
|
||||
parent surface is applied. When this happens depends on whether the
|
||||
parent surface is in synchronized mode or not. See
|
||||
wl_subsurface.set_sync and wl_subsurface.set_desync for details.
|
||||
parent surface is applied.
|
||||
|
||||
If more than one set_position request is invoked by the client before
|
||||
the commit of the parent surface, the position of a new request always
|
||||
|
|
@ -3085,9 +3208,7 @@
|
|||
The z-order is double-buffered. Requests are handled in order and
|
||||
applied immediately to a pending state. The final pending state is
|
||||
copied to the active state the next time the state of the parent
|
||||
surface is applied. When this happens depends on whether the parent
|
||||
surface is in synchronized mode or not. See wl_subsurface.set_sync and
|
||||
wl_subsurface.set_desync for details.
|
||||
surface is applied.
|
||||
|
||||
A new sub-surface is initially added as the top-most in the stack
|
||||
of its siblings and parent.
|
||||
|
|
@ -3148,4 +3269,31 @@
|
|||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_fixes" version="1">
|
||||
<description summary="wayland protocol fixes">
|
||||
This global fixes problems with other core-protocol interfaces that
|
||||
cannot be fixed in these interfaces themselves.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroys this object"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy_registry">
|
||||
<description summary="destroy a wl_registry">
|
||||
This request destroys a wl_registry object.
|
||||
|
||||
The client should no longer use the wl_registry after making this
|
||||
request.
|
||||
|
||||
The compositor will emit a wl_display.delete_id event with the object ID
|
||||
of the registry and will no longer emit any events on the registry. The
|
||||
client should re-use the object ID once it receives the
|
||||
wl_display.delete_id event.
|
||||
</description>
|
||||
<arg name="registry" type="object" interface="wl_registry"
|
||||
summary="the registry to destroy"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
|
|
|
|||
722
src/connection.c
722
src/connection.c
File diff suppressed because it is too large
Load diff
|
|
@ -23,7 +23,6 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -39,9 +38,11 @@
|
|||
#include <sys/signalfd.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <unistd.h>
|
||||
#include "timespec-util.h"
|
||||
#include "wayland-util.h"
|
||||
#include "wayland-private.h"
|
||||
#include "wayland-server-core.h"
|
||||
#include "wayland-server-private.h"
|
||||
#include "wayland-os.h"
|
||||
|
||||
/** \cond INTERNAL */
|
||||
|
|
@ -73,7 +74,7 @@ struct wl_event_loop {
|
|||
struct wl_list idle_list;
|
||||
struct wl_list destroy_list;
|
||||
|
||||
struct wl_signal destroy_signal;
|
||||
struct wl_priv_signal destroy_signal;
|
||||
|
||||
struct wl_timer_heap timers;
|
||||
};
|
||||
|
|
@ -446,7 +447,8 @@ wl_timer_heap_disarm(struct wl_timer_heap *timers,
|
|||
struct wl_event_source_timer *last_end_evt;
|
||||
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;
|
||||
source->heap_idx = -1;
|
||||
|
|
@ -475,7 +477,8 @@ wl_timer_heap_arm(struct wl_timer_heap *timers,
|
|||
struct wl_event_source_timer *source,
|
||||
struct timespec deadline)
|
||||
{
|
||||
assert(source->heap_idx == -1);
|
||||
if (!(source->heap_idx == -1))
|
||||
wl_abort("Timer is already armed\n");
|
||||
|
||||
source->deadline = deadline;
|
||||
timers->data[timers->active] = source;
|
||||
|
|
@ -898,7 +901,7 @@ wl_event_loop_create(void)
|
|||
wl_list_init(&loop->idle_list);
|
||||
wl_list_init(&loop->destroy_list);
|
||||
|
||||
wl_signal_init(&loop->destroy_signal);
|
||||
wl_priv_signal_init(&loop->destroy_signal);
|
||||
|
||||
wl_timer_heap_init(&loop->timers, loop);
|
||||
|
||||
|
|
@ -921,7 +924,7 @@ wl_event_loop_create(void)
|
|||
WL_EXPORT void
|
||||
wl_event_loop_destroy(struct wl_event_loop *loop)
|
||||
{
|
||||
wl_signal_emit(&loop->destroy_signal, loop);
|
||||
wl_priv_signal_final_emit(&loop->destroy_signal, loop);
|
||||
|
||||
wl_event_loop_process_destroy_list(loop);
|
||||
wl_timer_heap_release(&loop->timers);
|
||||
|
|
@ -998,17 +1001,46 @@ wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
|
|||
struct wl_event_source *source;
|
||||
int i, count;
|
||||
bool has_timers = false;
|
||||
bool use_timeout = timeout > 0;
|
||||
struct timespec now;
|
||||
struct timespec deadline = {0};
|
||||
struct timespec result;
|
||||
|
||||
wl_event_loop_dispatch_idle(loop);
|
||||
|
||||
count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
|
||||
if (use_timeout) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
timespec_add_msec(&deadline, &now, timeout);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
|
||||
if (count >= 0)
|
||||
break; /* have events or timeout */
|
||||
else if (count < 0 && errno != EINTR && errno != EAGAIN)
|
||||
break; /* have error */
|
||||
|
||||
if (use_timeout) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
timespec_sub(&result, &deadline, &now);
|
||||
timeout = timespec_to_msec(&result);
|
||||
if (timeout <= 0) {
|
||||
/* too late */
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
source = ep[i].data.ptr;
|
||||
if (source == &loop->timers.base)
|
||||
if (source == &loop->timers.base) {
|
||||
has_timers = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_timers) {
|
||||
|
|
@ -1070,7 +1102,7 @@ WL_EXPORT void
|
|||
wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
|
||||
struct wl_listener *listener)
|
||||
{
|
||||
wl_signal_add(&loop->destroy_signal, listener);
|
||||
wl_priv_signal_add(&loop->destroy_signal, listener);
|
||||
}
|
||||
|
||||
/** Get the listener struct for the specified callback
|
||||
|
|
@ -1086,5 +1118,5 @@ WL_EXPORT struct wl_listener *
|
|||
wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
|
||||
wl_notify_func_t notify)
|
||||
{
|
||||
return wl_signal_get(&loop->destroy_signal, notify);
|
||||
return wl_priv_signal_get(&loop->destroy_signal, notify);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ if get_option('scanner')
|
|||
version: meson.project_version(),
|
||||
variables: [
|
||||
'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
|
||||
'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name()),
|
||||
'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name()),
|
||||
'bindir=' + join_paths('${prefix}', get_option('bindir')),
|
||||
'wayland_scanner=${bindir}/wayland-scanner'
|
||||
],
|
||||
|
|
@ -74,6 +74,9 @@ if get_option('scanner')
|
|||
|
||||
if meson.can_run_host_binaries()
|
||||
meson.override_find_program('wayland-scanner', wayland_scanner)
|
||||
meson.override_dependency('wayland-scanner', declare_dependency(
|
||||
variables: { 'wayland_scanner': 'wayland-scanner' },
|
||||
))
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
@ -209,9 +212,10 @@ if get_option('libraries')
|
|||
description: 'Server side implementation of the Wayland protocol',
|
||||
version: meson.project_version(),
|
||||
filebase: 'wayland-server',
|
||||
libraries: mathlib_dep,
|
||||
variables: [
|
||||
'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
|
||||
'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name())
|
||||
'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
|
||||
]
|
||||
)
|
||||
|
||||
|
|
@ -248,9 +252,10 @@ if get_option('libraries')
|
|||
description: 'Wayland client side library',
|
||||
version: meson.project_version(),
|
||||
filebase: 'wayland-client',
|
||||
libraries: mathlib_dep,
|
||||
variables: [
|
||||
'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
|
||||
'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name())
|
||||
'pkgdatadir=' + join_paths('${pc_sysrootdir}${datarootdir}', meson.project_name())
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
|||
153
src/scanner.c
153
src/scanner.c
|
|
@ -67,7 +67,7 @@ enum visibility {
|
|||
static int
|
||||
usage(int ret)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [OPTION] [client-header|server-header|private-code|public-code]"
|
||||
fprintf(stderr, "usage: %s [OPTION] [client-header|server-header|enum-header|private-code|public-code]"
|
||||
" [input_file output_file]\n", PROGRAM_NAME);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Converts XML protocol descriptions supplied on "
|
||||
|
|
@ -175,7 +175,7 @@ struct interface {
|
|||
char *name;
|
||||
char *uppercase_name;
|
||||
int version;
|
||||
int since;
|
||||
int since, deprecated_since;
|
||||
struct wl_list request_list;
|
||||
struct wl_list event_list;
|
||||
struct wl_list enumeration_list;
|
||||
|
|
@ -194,7 +194,7 @@ struct message {
|
|||
int type_index;
|
||||
int all_null;
|
||||
int destructor;
|
||||
int since;
|
||||
int since, deprecated_since;
|
||||
struct description *description;
|
||||
};
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ struct entry {
|
|||
char *uppercase_name;
|
||||
char *value;
|
||||
char *summary;
|
||||
int since;
|
||||
int since, deprecated_since;
|
||||
struct wl_list link;
|
||||
struct description *description;
|
||||
};
|
||||
|
|
@ -697,6 +697,25 @@ version_from_since(struct parse_context *ctx, const char *since)
|
|||
return version;
|
||||
}
|
||||
|
||||
static int
|
||||
version_from_deprecated_since(struct parse_context *ctx, const char *deprecated_since)
|
||||
{
|
||||
int version;
|
||||
|
||||
if (deprecated_since == NULL)
|
||||
return 0;
|
||||
|
||||
version = strtouint(deprecated_since);
|
||||
if (version == -1) {
|
||||
fail(&ctx->loc, "invalid integer (%s)\n", deprecated_since);
|
||||
} else if (version > ctx->interface->version) {
|
||||
fail(&ctx->loc, "deprecated-since (%u) larger than version (%u)\n",
|
||||
version, ctx->interface->version);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
static void
|
||||
start_element(void *data, const char *element_name, const char **atts)
|
||||
{
|
||||
|
|
@ -713,6 +732,7 @@ start_element(void *data, const char *element_name, const char **atts)
|
|||
const char *value = NULL;
|
||||
const char *summary = NULL;
|
||||
const char *since = NULL;
|
||||
const char *deprecated_since = NULL;
|
||||
const char *allow_null = NULL;
|
||||
const char *enumeration_name = NULL;
|
||||
const char *bitfield = NULL;
|
||||
|
|
@ -737,6 +757,8 @@ start_element(void *data, const char *element_name, const char **atts)
|
|||
summary = atts[i + 1];
|
||||
if (strcmp(atts[i], "since") == 0)
|
||||
since = atts[i + 1];
|
||||
if (strcmp(atts[i], "deprecated-since") == 0)
|
||||
deprecated_since = atts[i + 1];
|
||||
if (strcmp(atts[i], "allow-null") == 0)
|
||||
allow_null = atts[i + 1];
|
||||
if (strcmp(atts[i], "enum") == 0)
|
||||
|
|
@ -786,12 +808,18 @@ start_element(void *data, const char *element_name, const char **atts)
|
|||
message->destructor = 1;
|
||||
|
||||
version = version_from_since(ctx, since);
|
||||
|
||||
if (version < ctx->interface->since)
|
||||
warn(&ctx->loc, "since version not increasing\n");
|
||||
ctx->interface->since = version;
|
||||
message->since = version;
|
||||
|
||||
version = version_from_deprecated_since(ctx, deprecated_since);
|
||||
if (version > 0 && version <= message->since)
|
||||
fail(&ctx->loc, "deprecated-since version (%d) smaller "
|
||||
"or equal to since version (%u)\n",
|
||||
version, message->since);
|
||||
message->deprecated_since = version;
|
||||
|
||||
if (strcmp(name, "destroy") == 0 && !message->destructor)
|
||||
fail(&ctx->loc, "destroy request should be destructor type");
|
||||
|
||||
|
|
@ -872,13 +900,20 @@ start_element(void *data, const char *element_name, const char **atts)
|
|||
|
||||
validate_identifier(&ctx->loc, name, TRAILING_IDENT);
|
||||
entry = create_entry(name, value);
|
||||
version = version_from_since(ctx, since);
|
||||
|
||||
version = version_from_since(ctx, since);
|
||||
if (version < ctx->enumeration->since)
|
||||
warn(&ctx->loc, "since version not increasing\n");
|
||||
ctx->enumeration->since = version;
|
||||
entry->since = version;
|
||||
|
||||
version = version_from_deprecated_since(ctx, deprecated_since);
|
||||
if (version > 0 && version <= entry->since)
|
||||
fail(&ctx->loc, "deprecated-since version (%d) smaller "
|
||||
"or equal to since version (%u)\n",
|
||||
version, entry->since);
|
||||
entry->deprecated_since = version;
|
||||
|
||||
if (summary)
|
||||
entry->summary = xstrdup(summary);
|
||||
else
|
||||
|
|
@ -1344,7 +1379,59 @@ emit_event_wrappers(struct wl_list *message_list, struct interface *interface)
|
|||
}
|
||||
|
||||
static void
|
||||
emit_enumerations(struct interface *interface)
|
||||
emit_validator(struct interface *interface, struct enumeration *e)
|
||||
{
|
||||
struct entry *entry;
|
||||
|
||||
printf("#ifndef %s_%s_ENUM_IS_VALID\n",
|
||||
interface->uppercase_name, e->uppercase_name);
|
||||
printf("#define %s_%s_ENUM_IS_VALID\n",
|
||||
interface->uppercase_name, e->uppercase_name);
|
||||
|
||||
printf("/**\n"
|
||||
" * @ingroup iface_%s\n"
|
||||
" * Validate a %s %s value.\n"
|
||||
" *\n"
|
||||
" * @return true on success, false on error.\n"
|
||||
" * @ref %s_%s\n"
|
||||
" */\n"
|
||||
"static inline bool\n"
|
||||
"%s_%s_is_valid(uint32_t value, uint32_t version) {\n",
|
||||
interface->name, interface->name, e->name,
|
||||
interface->name, e->name,
|
||||
interface->name, e->name);
|
||||
|
||||
if (e->bitfield) {
|
||||
printf(" uint32_t valid = 0;\n");
|
||||
wl_list_for_each(entry, &e->entry_list, link) {
|
||||
printf(" if (version >= %d)\n"
|
||||
" valid |= %s_%s_%s;\n",
|
||||
entry->since,
|
||||
interface->uppercase_name, e->uppercase_name,
|
||||
entry->uppercase_name);
|
||||
}
|
||||
printf(" return (value & ~valid) == 0;\n");
|
||||
} else {
|
||||
printf(" switch (value) {\n");
|
||||
wl_list_for_each(entry, &e->entry_list, link) {
|
||||
printf(" case %s%s_%s_%s:\n"
|
||||
" return version >= %d;\n",
|
||||
entry->value[0] == '-' ? "(uint32_t)" : "",
|
||||
interface->uppercase_name, e->uppercase_name,
|
||||
entry->uppercase_name, entry->since);
|
||||
}
|
||||
printf(" default:\n"
|
||||
" return false;\n"
|
||||
" }\n");
|
||||
}
|
||||
printf("}\n");
|
||||
|
||||
printf("#endif /* %s_%s_ENUM_IS_VALID */\n\n",
|
||||
interface->uppercase_name, e->uppercase_name);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_enumerations(struct interface *interface, bool with_validators)
|
||||
{
|
||||
struct enumeration *e;
|
||||
struct entry *entry;
|
||||
|
|
@ -1380,6 +1467,9 @@ emit_enumerations(struct interface *interface)
|
|||
}
|
||||
if (entry->since > 1)
|
||||
printf("\t * @since %d\n", entry->since);
|
||||
if (entry->deprecated_since > 0)
|
||||
printf("\t * @deprecated Deprecated since version %d\n",
|
||||
entry->deprecated_since);
|
||||
printf("\t */\n");
|
||||
}
|
||||
printf("\t%s_%s_%s = %s,\n",
|
||||
|
|
@ -1403,6 +1493,9 @@ emit_enumerations(struct interface *interface)
|
|||
|
||||
printf("#endif /* %s_%s_ENUM */\n\n",
|
||||
interface->uppercase_name, e->uppercase_name);
|
||||
|
||||
if (with_validators)
|
||||
emit_validator(interface, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1444,9 +1537,11 @@ emit_structs(struct wl_list *message_list, struct interface *interface, enum sid
|
|||
printf("\t * @param %s %s\n", a->name,
|
||||
a->summary);
|
||||
}
|
||||
if (m->since > 1) {
|
||||
if (m->since > 1)
|
||||
printf("\t * @since %d\n", m->since);
|
||||
}
|
||||
if (m->deprecated_since > 0)
|
||||
printf("\t * @deprecated Deprecated since version %d\n",
|
||||
m->deprecated_since);
|
||||
printf("\t */\n");
|
||||
printf("\tvoid (*%s)(", m->name);
|
||||
|
||||
|
|
@ -1677,7 +1772,7 @@ emit_header(struct protocol *protocol, enum side side)
|
|||
|
||||
wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) {
|
||||
|
||||
emit_enumerations(i);
|
||||
emit_enumerations(i, side == SERVER);
|
||||
|
||||
if (side == SERVER) {
|
||||
emit_structs(&i->request_list, i, side);
|
||||
|
|
@ -1703,6 +1798,35 @@ emit_header(struct protocol *protocol, enum side side)
|
|||
"#endif\n");
|
||||
}
|
||||
|
||||
static void
|
||||
emit_enum_header(struct protocol *protocol)
|
||||
{
|
||||
struct interface *i, *i_next;
|
||||
|
||||
printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
|
||||
|
||||
printf("#ifndef %s_ENUM_PROTOCOL_H\n"
|
||||
"#define %s_ENUM_PROTOCOL_H\n"
|
||||
"\n"
|
||||
"#ifdef __cplusplus\n"
|
||||
"extern \"C\" {\n"
|
||||
"#endif\n\n",
|
||||
protocol->uppercase_name,
|
||||
protocol->uppercase_name);
|
||||
|
||||
wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) {
|
||||
emit_enumerations(i, false);
|
||||
|
||||
free_interface(i);
|
||||
}
|
||||
|
||||
printf("#ifdef __cplusplus\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#endif\n");
|
||||
}
|
||||
|
||||
static void
|
||||
emit_null_run(struct protocol *protocol)
|
||||
{
|
||||
|
|
@ -1820,7 +1944,8 @@ emit_code(struct protocol *protocol, enum visibility vis)
|
|||
if (protocol->copyright)
|
||||
format_text_to_comment(protocol->copyright, true);
|
||||
|
||||
printf("#include <stdlib.h>\n"
|
||||
printf("#include <stdbool.h>\n"
|
||||
"#include <stdlib.h>\n"
|
||||
"#include <stdint.h>\n"
|
||||
"#include \"wayland-util.h\"\n\n");
|
||||
|
||||
|
|
@ -1923,6 +2048,7 @@ int main(int argc, char *argv[])
|
|||
enum {
|
||||
CLIENT_HEADER,
|
||||
SERVER_HEADER,
|
||||
ENUM_HEADER,
|
||||
PRIVATE_CODE,
|
||||
PUBLIC_CODE,
|
||||
CODE,
|
||||
|
|
@ -1976,6 +2102,8 @@ int main(int argc, char *argv[])
|
|||
mode = CLIENT_HEADER;
|
||||
else if (strcmp(argv[0], "server-header") == 0)
|
||||
mode = SERVER_HEADER;
|
||||
else if (strcmp(argv[0], "enum-header") == 0)
|
||||
mode = ENUM_HEADER;
|
||||
else if (strcmp(argv[0], "private-code") == 0)
|
||||
mode = PRIVATE_CODE;
|
||||
else if (strcmp(argv[0], "public-code") == 0)
|
||||
|
|
@ -2067,6 +2195,9 @@ int main(int argc, char *argv[])
|
|||
case SERVER_HEADER:
|
||||
emit_header(&protocol, SERVER);
|
||||
break;
|
||||
case ENUM_HEADER:
|
||||
emit_enum_header(&protocol);
|
||||
break;
|
||||
case PRIVATE_CODE:
|
||||
emit_code(&protocol, PRIVATE);
|
||||
break;
|
||||
|
|
|
|||
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" {
|
||||
#endif
|
||||
|
||||
struct timespec;
|
||||
|
||||
/** \class wl_proxy
|
||||
*
|
||||
* \brief Represents a protocol object on the client side.
|
||||
|
|
@ -120,7 +122,7 @@ struct wl_display;
|
|||
struct wl_event_queue;
|
||||
|
||||
/** Destroy proxy after marshalling
|
||||
* @ingroup wl_proxy
|
||||
* \relates wl_proxy
|
||||
*/
|
||||
#define WL_MARSHAL_FLAG_DESTROY (1 << 0)
|
||||
|
||||
|
|
@ -219,9 +221,21 @@ wl_proxy_get_tag(struct wl_proxy *proxy);
|
|||
const char *
|
||||
wl_proxy_get_class(struct wl_proxy *proxy);
|
||||
|
||||
const struct wl_interface *
|
||||
wl_proxy_get_interface(struct wl_proxy *proxy);
|
||||
|
||||
struct wl_display *
|
||||
wl_proxy_get_display(struct wl_proxy *proxy);
|
||||
|
||||
void
|
||||
wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue);
|
||||
|
||||
struct wl_event_queue *
|
||||
wl_proxy_get_queue(const struct wl_proxy *proxy);
|
||||
|
||||
const char *
|
||||
wl_event_queue_get_name(const struct wl_event_queue *queue);
|
||||
|
||||
struct wl_display *
|
||||
wl_display_connect(const char *name);
|
||||
|
||||
|
|
@ -241,13 +255,29 @@ int
|
|||
wl_display_dispatch_queue(struct wl_display *display,
|
||||
struct wl_event_queue *queue);
|
||||
|
||||
int
|
||||
wl_display_dispatch_timeout(struct wl_display *display,
|
||||
const struct timespec *timeout);
|
||||
|
||||
int
|
||||
wl_display_dispatch_queue_timeout(struct wl_display *display,
|
||||
struct wl_event_queue *queue,
|
||||
const struct timespec *timeout);
|
||||
|
||||
int
|
||||
wl_display_dispatch_queue_pending(struct wl_display *display,
|
||||
struct wl_event_queue *queue);
|
||||
|
||||
int
|
||||
wl_display_dispatch_queue_pending_single(struct wl_display *display,
|
||||
struct wl_event_queue *queue);
|
||||
|
||||
int
|
||||
wl_display_dispatch_pending(struct wl_display *display);
|
||||
|
||||
int
|
||||
wl_display_dispatch_pending_single(struct wl_display *display);
|
||||
|
||||
int
|
||||
wl_display_get_error(struct wl_display *display);
|
||||
|
||||
|
|
@ -269,6 +299,10 @@ wl_display_roundtrip(struct wl_display *display);
|
|||
struct wl_event_queue *
|
||||
wl_display_create_queue(struct wl_display *display);
|
||||
|
||||
struct wl_event_queue *
|
||||
wl_display_create_queue_with_name(struct wl_display *display,
|
||||
const char *name);
|
||||
|
||||
int
|
||||
wl_display_prepare_read_queue(struct wl_display *display,
|
||||
struct wl_event_queue *queue);
|
||||
|
|
@ -285,6 +319,10 @@ wl_display_read_events(struct wl_display *display);
|
|||
void
|
||||
wl_log_set_handler_client(wl_log_func_t handler);
|
||||
|
||||
void
|
||||
wl_display_set_max_buffer_size(struct wl_display *display,
|
||||
size_t max_buffer_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
|
|
@ -46,6 +45,7 @@
|
|||
#include "wayland-os.h"
|
||||
#include "wayland-client.h"
|
||||
#include "wayland-private.h"
|
||||
#include "timespec-util.h"
|
||||
|
||||
/** \cond */
|
||||
|
||||
|
|
@ -77,6 +77,7 @@ struct wl_event_queue {
|
|||
struct wl_list event_list;
|
||||
struct wl_list proxy_list; /**< struct wl_proxy::queue_link */
|
||||
struct wl_display *display;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct wl_display {
|
||||
|
|
@ -114,6 +115,7 @@ struct wl_display {
|
|||
/** \endcond */
|
||||
|
||||
static int debug_client = 0;
|
||||
static int debug_color = 0;
|
||||
|
||||
/**
|
||||
* This helper function wakes up all threads that are
|
||||
|
|
@ -220,23 +222,30 @@ display_protocol_error(struct wl_display *display, uint32_t code,
|
|||
}
|
||||
|
||||
static void
|
||||
wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
|
||||
wl_event_queue_init(struct wl_event_queue *queue,
|
||||
struct wl_display *display,
|
||||
const char *name)
|
||||
{
|
||||
wl_list_init(&queue->event_list);
|
||||
wl_list_init(&queue->proxy_list);
|
||||
queue->display = display;
|
||||
if (name)
|
||||
queue->name = strdup(name);
|
||||
}
|
||||
|
||||
static void
|
||||
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)
|
||||
return;
|
||||
|
||||
/* If we get here, the client must have explicitly requested
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
@ -253,8 +262,8 @@ validate_closure_objects(struct wl_closure *closure)
|
|||
for (i = 0; i < count; i++) {
|
||||
signature = get_next_argument(signature, &arg);
|
||||
switch (arg.type) {
|
||||
case 'n':
|
||||
case 'o':
|
||||
case WL_ARG_NEW_ID:
|
||||
case WL_ARG_OBJECT:
|
||||
proxy = (struct wl_proxy *) closure->args[i].o;
|
||||
if (proxy && proxy->flags & WL_PROXY_FLAG_DESTROYED)
|
||||
closure->args[i].o = NULL;
|
||||
|
|
@ -281,8 +290,8 @@ destroy_queued_closure(struct wl_closure *closure)
|
|||
for (i = 0; i < count; i++) {
|
||||
signature = get_next_argument(signature, &arg);
|
||||
switch (arg.type) {
|
||||
case 'n':
|
||||
case 'o':
|
||||
case WL_ARG_NEW_ID:
|
||||
case WL_ARG_OBJECT:
|
||||
proxy = (struct wl_proxy *) closure->args[i].o;
|
||||
if (proxy)
|
||||
wl_proxy_unref(proxy);
|
||||
|
|
@ -305,14 +314,21 @@ wl_event_queue_release(struct wl_event_queue *queue)
|
|||
struct wl_proxy *proxy, *tmp;
|
||||
|
||||
if (queue != &queue->display->default_queue) {
|
||||
wl_log("warning: queue %p destroyed while proxies "
|
||||
"still attached:\n", queue);
|
||||
if (queue->name) {
|
||||
wl_log("warning: queue \"%s\" "
|
||||
"%p destroyed while proxies "
|
||||
"still attached:\n", queue->name, queue);
|
||||
} else {
|
||||
wl_log("warning: queue "
|
||||
"%p destroyed while proxies "
|
||||
"still attached:\n", queue);
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_for_each_safe(proxy, tmp, &queue->proxy_list,
|
||||
queue_link) {
|
||||
if (queue != &queue->display->default_queue) {
|
||||
wl_log(" %s@%u still attached\n",
|
||||
wl_log(" %s#%u still attached\n",
|
||||
proxy->object.interface->name,
|
||||
proxy->object.id);
|
||||
}
|
||||
|
|
@ -350,6 +366,7 @@ wl_event_queue_destroy(struct wl_event_queue *queue)
|
|||
|
||||
pthread_mutex_lock(&display->mutex);
|
||||
wl_event_queue_release(queue);
|
||||
free(queue->name);
|
||||
free(queue);
|
||||
pthread_mutex_unlock(&display->mutex);
|
||||
}
|
||||
|
|
@ -371,7 +388,30 @@ wl_display_create_queue(struct wl_display *display)
|
|||
if (queue == NULL)
|
||||
return NULL;
|
||||
|
||||
wl_event_queue_init(queue, display);
|
||||
wl_event_queue_init(queue, display, NULL);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
/** Create a new event queue for this display and give it a name
|
||||
*
|
||||
* \param display The display context object
|
||||
* \param name A human readable queue name
|
||||
* \return A new event queue associated with this display or NULL on
|
||||
* failure.
|
||||
*
|
||||
* \memberof wl_display
|
||||
*/
|
||||
WL_EXPORT struct wl_event_queue *
|
||||
wl_display_create_queue_with_name(struct wl_display *display, const char *name)
|
||||
{
|
||||
struct wl_event_queue *queue;
|
||||
|
||||
queue = zalloc(sizeof *queue);
|
||||
if (queue == NULL)
|
||||
return NULL;
|
||||
|
||||
wl_event_queue_init(queue, display, name);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
|
@ -385,7 +425,7 @@ message_count_fds(const char *signature)
|
|||
count = arg_count_for_signature(signature);
|
||||
for (i = 0; i < count; i++) {
|
||||
signature = get_next_argument(signature, &arg);
|
||||
if (arg.type == 'h')
|
||||
if (arg.type == WL_ARG_FD)
|
||||
fds++;
|
||||
}
|
||||
|
||||
|
|
@ -635,6 +675,9 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
|
|||
* This function is useful in clients with multiple listeners on the same
|
||||
* interface to allow the identification of which code to execute.
|
||||
*
|
||||
* If \ref wl_proxy_add_dispatcher was used, this function returns the
|
||||
* dispatcher_data pointer instead.
|
||||
*
|
||||
* \memberof wl_proxy
|
||||
*/
|
||||
WL_EXPORT const void *
|
||||
|
|
@ -697,16 +740,14 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
|
|||
count = arg_count_for_signature(signature);
|
||||
for (i = 0; i < count; i++) {
|
||||
signature = get_next_argument(signature, &arg);
|
||||
if (arg.type != WL_ARG_NEW_ID)
|
||||
continue;
|
||||
|
||||
switch (arg.type) {
|
||||
case 'n':
|
||||
new_proxy = proxy_create(proxy, interface, version);
|
||||
if (new_proxy == NULL)
|
||||
return NULL;
|
||||
new_proxy = proxy_create(proxy, interface, version);
|
||||
if (new_proxy == NULL)
|
||||
return NULL;
|
||||
|
||||
args[i].o = &new_proxy->object;
|
||||
break;
|
||||
}
|
||||
args[i].o = &new_proxy->object;
|
||||
}
|
||||
|
||||
return new_proxy;
|
||||
|
|
@ -880,16 +921,29 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
|
|||
|
||||
closure = wl_closure_marshal(&proxy->object, opcode, args, message);
|
||||
if (closure == NULL) {
|
||||
wl_log("Error marshalling request: %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);
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
if (debug_client)
|
||||
wl_closure_print(closure, &proxy->object, true, false, NULL);
|
||||
if (debug_client) {
|
||||
struct wl_event_queue *queue;
|
||||
const char *queue_name = NULL;
|
||||
|
||||
queue = wl_proxy_get_queue(proxy);
|
||||
if (queue)
|
||||
queue_name = wl_event_queue_get_name(queue);
|
||||
|
||||
wl_closure_print(closure, &proxy->object, true, false, NULL,
|
||||
queue_name, debug_color);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1045,7 +1099,7 @@ display_handle_error(void *data,
|
|||
const struct wl_interface *interface;
|
||||
|
||||
if (proxy) {
|
||||
wl_log("%s@%u: error %d: %s\n",
|
||||
wl_log("%s#%u: error %d: %s\n",
|
||||
proxy->object.interface->name,
|
||||
proxy->object.id,
|
||||
code, message);
|
||||
|
|
@ -1133,7 +1187,8 @@ connect_to_socket(const char *name)
|
|||
"%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 (!path_is_absolute) {
|
||||
wl_log("error: socket path \"%s/%s\" plus null terminator"
|
||||
|
|
@ -1175,10 +1230,23 @@ wl_display_connect_to_fd(int fd)
|
|||
{
|
||||
struct wl_display *display;
|
||||
const char *debug;
|
||||
const char *no_color;
|
||||
const char *force_color;
|
||||
|
||||
no_color = getenv("NO_COLOR");
|
||||
force_color = getenv("FORCE_COLOR");
|
||||
debug = getenv("WAYLAND_DEBUG");
|
||||
if (debug && (strstr(debug, "client") || strstr(debug, "1")))
|
||||
if (debug && (wl_check_env_token(debug, "client") || wl_check_env_token(debug, "1"))) {
|
||||
debug_client = 1;
|
||||
if (isatty(fileno(stderr)))
|
||||
debug_color = 1;
|
||||
}
|
||||
|
||||
if (force_color && force_color[0] != '\0')
|
||||
debug_color = 1;
|
||||
|
||||
if (no_color && no_color[0] != '\0')
|
||||
debug_color = 0;
|
||||
|
||||
display = zalloc(sizeof *display);
|
||||
if (display == NULL) {
|
||||
|
|
@ -1188,8 +1256,8 @@ wl_display_connect_to_fd(int fd)
|
|||
|
||||
display->fd = fd;
|
||||
wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE);
|
||||
wl_event_queue_init(&display->default_queue, display);
|
||||
wl_event_queue_init(&display->display_queue, display);
|
||||
wl_event_queue_init(&display->default_queue, display, "Default Queue");
|
||||
wl_event_queue_init(&display->display_queue, display, "Display Queue");
|
||||
pthread_mutex_init(&display->mutex, NULL);
|
||||
pthread_cond_init(&display->reader_cond, NULL);
|
||||
display->reader_count = 0;
|
||||
|
|
@ -1230,7 +1298,7 @@ wl_display_connect_to_fd(int fd)
|
|||
*/
|
||||
display->proxy.version = 0;
|
||||
|
||||
display->connection = wl_connection_create(display->fd);
|
||||
display->connection = wl_connection_create(display->fd, 0);
|
||||
if (display->connection == NULL)
|
||||
goto err_connection;
|
||||
|
||||
|
|
@ -1321,7 +1389,9 @@ wl_display_disconnect(struct wl_display *display)
|
|||
wl_map_for_each(&display->objects, free_zombies, NULL);
|
||||
wl_map_release(&display->objects);
|
||||
wl_event_queue_release(&display->default_queue);
|
||||
free(display->default_queue.name);
|
||||
wl_event_queue_release(&display->display_queue);
|
||||
free(display->display_queue.name);
|
||||
pthread_mutex_destroy(&display->mutex);
|
||||
pthread_cond_destroy(&display->reader_cond);
|
||||
close(display->fd);
|
||||
|
|
@ -1446,22 +1516,19 @@ create_proxies(struct wl_proxy *sender, struct wl_closure *closure)
|
|||
count = arg_count_for_signature(signature);
|
||||
for (i = 0; i < count; i++) {
|
||||
signature = get_next_argument(signature, &arg);
|
||||
switch (arg.type) {
|
||||
case 'n':
|
||||
id = closure->args[i].n;
|
||||
if (id == 0) {
|
||||
closure->args[i].o = NULL;
|
||||
break;
|
||||
}
|
||||
proxy = wl_proxy_create_for_id(sender, id,
|
||||
closure->message->types[i]);
|
||||
if (proxy == NULL)
|
||||
return -1;
|
||||
closure->args[i].o = (struct wl_object *)proxy;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (arg.type != WL_ARG_NEW_ID)
|
||||
continue;
|
||||
|
||||
id = closure->args[i].n;
|
||||
if (id == 0) {
|
||||
closure->args[i].o = NULL;
|
||||
continue;
|
||||
}
|
||||
proxy = wl_proxy_create_for_id(sender, id,
|
||||
closure->message->types[i]);
|
||||
if (proxy == NULL)
|
||||
return -1;
|
||||
closure->args[i].o = (struct wl_object *)proxy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1480,8 +1547,8 @@ increase_closure_args_refcount(struct wl_closure *closure)
|
|||
for (i = 0; i < count; i++) {
|
||||
signature = get_next_argument(signature, &arg);
|
||||
switch (arg.type) {
|
||||
case 'n':
|
||||
case 'o':
|
||||
case WL_ARG_NEW_ID:
|
||||
case WL_ARG_OBJECT:
|
||||
proxy = (struct wl_proxy *) closure->args[i].o;
|
||||
if (proxy)
|
||||
proxy->refcount++;
|
||||
|
|
@ -1511,6 +1578,28 @@ queue_event(struct wl_display *display, int len)
|
|||
id = p[0];
|
||||
opcode = p[1] & 0xffff;
|
||||
size = p[1] >> 16;
|
||||
|
||||
/*
|
||||
* If the message is larger than the maximum size of the
|
||||
* connection buffer, the connection buffer will fill to
|
||||
* its max size and stay there, with no message ever
|
||||
* successfully being processed. If the user of
|
||||
* libwayland-client uses a level-triggered event loop,
|
||||
* this will cause the client to enter a loop that
|
||||
* consumes CPU. To avoid this, immediately drop the
|
||||
* connection. Since the maximum size of a message should
|
||||
* not depend on the max buffer size chosen by the client,
|
||||
* always compare the message size against the
|
||||
* limit enforced by libwayland 1.22 and below (4096),
|
||||
* rather than the actual value the client chose.
|
||||
*/
|
||||
if (size > WL_MAX_MESSAGE_SIZE) {
|
||||
wl_log("Message length %u exceeds limit %d\n",
|
||||
size, WL_MAX_MESSAGE_SIZE);
|
||||
errno = E2BIG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len < size)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1525,12 +1614,16 @@ queue_event(struct wl_display *display, int len)
|
|||
if (debug_client) {
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
|
||||
|
||||
fprintf(stderr, "[%7u.%03u] discarded [%s]@%d.[event %d]"
|
||||
fprintf(stderr, "%s[%7u.%03u] %sdiscarded %s[%s]%s#%u%s.[event %d]%s"
|
||||
"(%d fd, %d byte)\n",
|
||||
debug_color ? WL_DEBUG_COLOR_GREEN : "",
|
||||
time / 1000, time % 1000,
|
||||
debug_color ? WL_DEBUG_COLOR_RED : "",
|
||||
debug_color ? WL_DEBUG_COLOR_BLUE : "",
|
||||
zombie ? "zombie" : "unknown",
|
||||
id, opcode,
|
||||
debug_color ? WL_DEBUG_COLOR_MAGENTA : "", id,
|
||||
debug_color ? WL_DEBUG_COLOR_BLUE : "", opcode,
|
||||
debug_color ? WL_DEBUG_COLOR_RESET : "",
|
||||
num_zombie_fds, size);
|
||||
}
|
||||
if (num_zombie_fds > 0)
|
||||
|
|
@ -1609,9 +1702,16 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
|
|||
validate_closure_objects(closure);
|
||||
proxy = closure->proxy;
|
||||
proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED);
|
||||
|
||||
if (debug_client) {
|
||||
bool discarded = proxy_destroyed ||
|
||||
!(proxy->dispatcher || proxy->object.implementation);
|
||||
|
||||
wl_closure_print(closure, &proxy->object, false, discarded,
|
||||
id_from_object, queue->name, debug_color);
|
||||
}
|
||||
|
||||
if (proxy_destroyed) {
|
||||
if (debug_client)
|
||||
wl_closure_print(closure, &proxy->object, false, true, id_from_object);
|
||||
destroy_queued_closure(closure);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1619,15 +1719,9 @@ dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
|
|||
pthread_mutex_unlock(&display->mutex);
|
||||
|
||||
if (proxy->dispatcher) {
|
||||
if (debug_client)
|
||||
wl_closure_print(closure, &proxy->object, false, false, id_from_object);
|
||||
|
||||
wl_closure_dispatch(closure, proxy->dispatcher,
|
||||
&proxy->object, opcode);
|
||||
} else if (proxy->object.implementation) {
|
||||
if (debug_client)
|
||||
wl_closure_print(closure, &proxy->object, false, false, id_from_object);
|
||||
|
||||
wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
|
||||
&proxy->object, opcode, proxy->user_data);
|
||||
}
|
||||
|
|
@ -1788,6 +1882,34 @@ err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dispatch_queue_single(struct wl_display *display, struct wl_event_queue *queue)
|
||||
{
|
||||
if (display->last_error)
|
||||
goto err;
|
||||
|
||||
while (!wl_list_empty(&display->display_queue.event_list)) {
|
||||
dispatch_event(display, &display->display_queue);
|
||||
if (display->last_error)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!wl_list_empty(&queue->event_list)) {
|
||||
dispatch_event(display, queue);
|
||||
if (display->last_error)
|
||||
goto err;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
err:
|
||||
errno = display->last_error;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Prepare to read events from the display's file descriptor to a queue
|
||||
*
|
||||
* \param display The display context object
|
||||
|
|
@ -1903,20 +2025,142 @@ wl_display_cancel_read(struct wl_display *display)
|
|||
}
|
||||
|
||||
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;
|
||||
struct pollfd pfd[1];
|
||||
struct timespec now;
|
||||
struct timespec deadline = {0};
|
||||
struct timespec result;
|
||||
struct timespec *remaining_timeout = NULL;
|
||||
|
||||
if (timeout) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
timespec_add(&deadline, &now, timeout);
|
||||
}
|
||||
|
||||
pfd[0].fd = display->fd;
|
||||
pfd[0].events = events;
|
||||
do {
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Dispatch events in an event queue with a timeout
|
||||
*
|
||||
* \param display The display context object
|
||||
* \param queue The event queue to dispatch
|
||||
* \param timeout A timeout describing how long the call should block trying to
|
||||
* dispatch events
|
||||
* \return The number of dispatched events on success, -1 on failure
|
||||
*
|
||||
* This function behaves identical to wl_display_dispatch_queue() except
|
||||
* that it also takes a timeout and returns 0 if the timeout elapsed.
|
||||
*
|
||||
* Passing NULL as a timeout means an infinite timeout. An empty timespec
|
||||
* causes wl_display_dispatch_queue_timeout() to return immediately even if no
|
||||
* events have been dispatched.
|
||||
*
|
||||
* If a timeout is passed to wl_display_dispatch_queue_timeout() it is updated
|
||||
* to the remaining time.
|
||||
*
|
||||
* \sa wl_display_dispatch_queue()
|
||||
*
|
||||
* \memberof wl_display
|
||||
*/
|
||||
WL_EXPORT int
|
||||
wl_display_dispatch_queue_timeout(struct wl_display *display,
|
||||
struct wl_event_queue *queue,
|
||||
const struct timespec *timeout)
|
||||
{
|
||||
int ret;
|
||||
struct timespec now;
|
||||
struct timespec deadline = {0};
|
||||
struct timespec result;
|
||||
struct timespec *remaining_timeout = NULL;
|
||||
|
||||
if (timeout) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
timespec_add(&deadline, &now, timeout);
|
||||
}
|
||||
|
||||
if (wl_display_prepare_read_queue(display, queue) == -1)
|
||||
return wl_display_dispatch_queue_pending(display, queue);
|
||||
|
||||
while (true) {
|
||||
ret = wl_display_flush(display);
|
||||
|
||||
if (ret != -1 || errno != EAGAIN)
|
||||
break;
|
||||
|
||||
if (timeout) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
timespec_sub_saturate(&result, &deadline, &now);
|
||||
remaining_timeout = &result;
|
||||
}
|
||||
ret = wl_display_poll(display, POLLOUT, remaining_timeout);
|
||||
|
||||
if (ret <= 0) {
|
||||
wl_display_cancel_read(display);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't stop if flushing hits an EPIPE; continue so we can read any
|
||||
* protocol error that may have triggered it. */
|
||||
if (ret < 0 && errno != EPIPE) {
|
||||
wl_display_cancel_read(display);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (timeout) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
timespec_sub_saturate(&result, &deadline, &now);
|
||||
remaining_timeout = &result;
|
||||
}
|
||||
|
||||
ret = wl_display_poll(display, POLLIN, remaining_timeout);
|
||||
if (ret <= 0) {
|
||||
wl_display_cancel_read(display);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = wl_display_read_events(display);
|
||||
if (ret == -1)
|
||||
break;
|
||||
|
||||
ret = wl_display_dispatch_queue_pending(display, queue);
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
||||
/* We managed to read data from the display but there is no
|
||||
* complete event to dispatch yet. Try reading again. */
|
||||
if (wl_display_prepare_read_queue(display, queue) == -1)
|
||||
return wl_display_dispatch_queue_pending(display, queue);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
wl_display_dispatch_timeout(struct wl_display *display,
|
||||
const struct timespec *timeout)
|
||||
{
|
||||
return wl_display_dispatch_queue_timeout(display,
|
||||
&display->default_queue,
|
||||
timeout);
|
||||
}
|
||||
|
||||
/** Dispatch events in an event queue
|
||||
*
|
||||
* \param display The display context object
|
||||
|
|
@ -1948,8 +2192,8 @@ wl_display_poll(struct wl_display *display, short int events)
|
|||
* \note Since Wayland 1.5 the display has an extra queue
|
||||
* for its own events (i. e. delete_id). This queue is dispatched always,
|
||||
* no matter what queue we passed as an argument to this function.
|
||||
* That means that this function can return non-0 value even when it
|
||||
* haven't dispatched any event for the given queue.
|
||||
* That means that this function can return even when it has not dispatched any
|
||||
* event for the given queue.
|
||||
*
|
||||
* \sa wl_display_dispatch(), wl_display_dispatch_pending(),
|
||||
* wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue()
|
||||
|
|
@ -1962,37 +2206,10 @@ wl_display_dispatch_queue(struct wl_display *display,
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (wl_display_prepare_read_queue(display, queue) == -1)
|
||||
return wl_display_dispatch_queue_pending(display, queue);
|
||||
ret = wl_display_dispatch_queue_timeout(display, queue, NULL);
|
||||
assert(ret == -1 || ret > 0);
|
||||
|
||||
while (true) {
|
||||
ret = wl_display_flush(display);
|
||||
|
||||
if (ret != -1 || errno != EAGAIN)
|
||||
break;
|
||||
|
||||
if (wl_display_poll(display, POLLOUT) == -1) {
|
||||
wl_display_cancel_read(display);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't stop if flushing hits an EPIPE; continue so we can read any
|
||||
* protocol error that may have triggered it. */
|
||||
if (ret < 0 && errno != EPIPE) {
|
||||
wl_display_cancel_read(display);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wl_display_poll(display, POLLIN) == -1) {
|
||||
wl_display_cancel_read(display);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wl_display_read_events(display) == -1)
|
||||
return -1;
|
||||
|
||||
return wl_display_dispatch_queue_pending(display, queue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Dispatch pending events in an event queue
|
||||
|
|
@ -2023,6 +2240,34 @@ wl_display_dispatch_queue_pending(struct wl_display *display,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/** Dispatch at most one pending event in an event queue
|
||||
*
|
||||
* \param display The display context object
|
||||
* \param queue The event queue to dispatch
|
||||
* \return The number of dispatched events (0 or 1) on success or -1 on failure
|
||||
*
|
||||
* Dispatch at most one pending event for objects assigned to the given
|
||||
* event queue. On failure -1 is returned and errno set appropriately.
|
||||
* If there are no events queued, this function returns immediately.
|
||||
*
|
||||
* \memberof wl_display
|
||||
* \since 1.25.0
|
||||
*/
|
||||
WL_EXPORT int
|
||||
wl_display_dispatch_queue_pending_single(struct wl_display *display,
|
||||
struct wl_event_queue *queue)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pthread_mutex_lock(&display->mutex);
|
||||
|
||||
ret = dispatch_queue_single(display, queue);
|
||||
|
||||
pthread_mutex_unlock(&display->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Process incoming events
|
||||
*
|
||||
* \param display The display context object
|
||||
|
|
@ -2083,6 +2328,25 @@ wl_display_dispatch_pending(struct wl_display *display)
|
|||
&display->default_queue);
|
||||
}
|
||||
|
||||
/** Dispatch at most one pending event in the default event queue.
|
||||
*
|
||||
* \param display The display context object
|
||||
* \return The number of dispatched events (0 or 1) on success or -1 on failure
|
||||
*
|
||||
* Dispatch at most one pending event for objects assigned to the default
|
||||
* event queue. On failure -1 is returned and errno set appropriately.
|
||||
* If there are no events queued, this function returns immediately.
|
||||
*
|
||||
* \memberof wl_display
|
||||
* \since 1.25.0
|
||||
*/
|
||||
WL_EXPORT int
|
||||
wl_display_dispatch_pending_single(struct wl_display *display)
|
||||
{
|
||||
return wl_display_dispatch_queue_pending_single(display,
|
||||
&display->default_queue);
|
||||
}
|
||||
|
||||
/** Retrieve the last error that occurred on a display
|
||||
*
|
||||
* \param display The display context object
|
||||
|
|
@ -2197,6 +2461,32 @@ wl_display_flush(struct wl_display *display)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/** Adjust the maximum size of the client connection buffers
|
||||
*
|
||||
* \param display The display context object
|
||||
* \param max_buffer_size The maximum size of the connection buffers
|
||||
*
|
||||
* Client buffers are unbounded by default. This function sets a limit to the
|
||||
* size of the connection buffers.
|
||||
*
|
||||
* A value of 0 for \a max_buffer_size requests the buffers to be unbounded.
|
||||
*
|
||||
* The actual size of the connection buffers is a power of two, the requested
|
||||
* \a max_buffer_size is therefore rounded up to the nearest power of two value.
|
||||
*
|
||||
* Lowering the maximum size may not take effect immediately if the current
|
||||
* content of the buffer does not fit within the new size limit.
|
||||
*
|
||||
* \memberof wl_display
|
||||
* \since 1.22.90
|
||||
*/
|
||||
WL_EXPORT void
|
||||
wl_display_set_max_buffer_size(struct wl_display *display,
|
||||
size_t max_buffer_size)
|
||||
{
|
||||
wl_connection_set_max_buffer_size(display->connection, max_buffer_size);
|
||||
}
|
||||
|
||||
/** Set the user data associated with a proxy
|
||||
*
|
||||
* \param proxy The proxy object
|
||||
|
|
@ -2338,6 +2628,34 @@ wl_proxy_get_class(struct wl_proxy *proxy)
|
|||
return proxy->object.interface->name;
|
||||
}
|
||||
|
||||
/** Get the interface of a proxy object
|
||||
*
|
||||
* \param proxy The proxy object
|
||||
* \return The interface of the object associated with the proxy
|
||||
*
|
||||
* \memberof wl_proxy
|
||||
* \since 1.24
|
||||
*/
|
||||
WL_EXPORT const struct wl_interface *
|
||||
wl_proxy_get_interface(struct wl_proxy *proxy)
|
||||
{
|
||||
return proxy->object.interface;
|
||||
}
|
||||
|
||||
/** Get the display of a proxy object
|
||||
*
|
||||
* \param proxy The proxy object
|
||||
* \return The wl_display the proxy is associated with
|
||||
*
|
||||
* \memberof wl_proxy
|
||||
* \since 1.23
|
||||
*/
|
||||
WL_EXPORT struct wl_display *
|
||||
wl_proxy_get_display(struct wl_proxy *proxy)
|
||||
{
|
||||
return proxy->display;
|
||||
}
|
||||
|
||||
/** Assign a proxy to an event queue
|
||||
*
|
||||
* \param proxy The proxy object
|
||||
|
|
@ -2374,7 +2692,9 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
|
|||
wl_list_remove(&proxy->queue_link);
|
||||
|
||||
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;
|
||||
} else {
|
||||
proxy->queue = &proxy->display->default_queue;
|
||||
|
|
@ -2385,6 +2705,34 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
|
|||
pthread_mutex_unlock(&proxy->display->mutex);
|
||||
}
|
||||
|
||||
/** Get a proxy's event queue
|
||||
*
|
||||
* \param proxy The proxy to query
|
||||
*
|
||||
* Return the event queue
|
||||
*/
|
||||
WL_EXPORT struct wl_event_queue *
|
||||
wl_proxy_get_queue(const struct wl_proxy *proxy)
|
||||
{
|
||||
return proxy->queue;
|
||||
|
||||
}
|
||||
/** Get the name of an event queue
|
||||
*
|
||||
* \param queue The queue to query
|
||||
*
|
||||
* Return the human readable name for the event queue
|
||||
*
|
||||
* This may be NULL if no name has been set.
|
||||
*
|
||||
* \memberof wl_proxy
|
||||
*/
|
||||
WL_EXPORT const char *
|
||||
wl_event_queue_get_name(const struct wl_event_queue *queue)
|
||||
{
|
||||
return queue->name;
|
||||
}
|
||||
|
||||
/** Create a proxy wrapper for making queue assignments thread-safe
|
||||
*
|
||||
* \param proxy The proxy object to be wrapped
|
||||
|
|
@ -2474,7 +2822,8 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper)
|
|||
wl_abort("Tried to destroy non-wrapper proxy with "
|
||||
"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);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@
|
|||
|
||||
#include "wayland-os.h"
|
||||
|
||||
/* used by tests */
|
||||
int (*wl_fcntl)(int fildes, int cmd, ...) = fcntl;
|
||||
int (*wl_socket)(int domain, int type, int protocol) = socket;
|
||||
ssize_t (*wl_recvmsg)(int socket, struct msghdr *message, int flags) = recvmsg;
|
||||
int (*wl_epoll_create1)(int flags) = epoll_create1;
|
||||
|
||||
static int
|
||||
set_cloexec_or_close(int fd)
|
||||
{
|
||||
|
|
@ -50,11 +56,11 @@ set_cloexec_or_close(int fd)
|
|||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
flags = wl_fcntl(fd, F_GETFD);
|
||||
if (flags == -1)
|
||||
goto err;
|
||||
|
||||
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||
if (wl_fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||
goto err;
|
||||
|
||||
return fd;
|
||||
|
|
@ -69,13 +75,13 @@ wl_os_socket_cloexec(int domain, int type, int protocol)
|
|||
{
|
||||
int fd;
|
||||
|
||||
fd = socket(domain, type | SOCK_CLOEXEC, protocol);
|
||||
fd = wl_socket(domain, type | SOCK_CLOEXEC, protocol);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
|
||||
fd = socket(domain, type, protocol);
|
||||
fd = wl_socket(domain, type, protocol);
|
||||
return set_cloexec_or_close(fd);
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +111,11 @@ int
|
|||
wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
|
||||
{
|
||||
socklen_t len;
|
||||
#if defined(__OpenBSD__)
|
||||
struct sockpeercred ucred;
|
||||
#else
|
||||
struct ucred ucred;
|
||||
#endif
|
||||
|
||||
len = sizeof(ucred);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0)
|
||||
|
|
@ -124,13 +134,13 @@ wl_os_dupfd_cloexec(int fd, int minfd)
|
|||
{
|
||||
int newfd;
|
||||
|
||||
newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
|
||||
newfd = wl_fcntl(fd, F_DUPFD_CLOEXEC, minfd);
|
||||
if (newfd >= 0)
|
||||
return newfd;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
|
||||
newfd = fcntl(fd, F_DUPFD, minfd);
|
||||
newfd = wl_fcntl(fd, F_DUPFD, minfd);
|
||||
return set_cloexec_or_close(newfd);
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +153,7 @@ recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags)
|
|||
int *fd;
|
||||
int *end;
|
||||
|
||||
len = recvmsg(sockfd, msg, flags);
|
||||
len = wl_recvmsg(sockfd, msg, flags);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
|
|
@ -179,7 +189,7 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
|
|||
#else
|
||||
ssize_t len;
|
||||
|
||||
len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
|
||||
len = wl_recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
|
||||
if (len >= 0)
|
||||
return len;
|
||||
if (errno != EINVAL)
|
||||
|
|
@ -194,7 +204,7 @@ wl_os_epoll_create_cloexec(void)
|
|||
int fd;
|
||||
|
||||
#ifdef EPOLL_CLOEXEC
|
||||
fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
fd = wl_epoll_create1(EPOLL_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
if (errno != EINVAL)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,33 @@
|
|||
#define WL_SERVER_ID_START 0xff000000
|
||||
#define WL_MAP_MAX_OBJECTS 0x00f00000
|
||||
#define WL_CLOSURE_MAX_ARGS 20
|
||||
#define WL_BUFFER_DEFAULT_SIZE_POT 12
|
||||
#define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT)
|
||||
#if WL_BUFFER_DEFAULT_MAX_SIZE < WL_MAX_MESSAGE_SIZE
|
||||
# error default buffer cannot hold maximum-sized message
|
||||
#endif
|
||||
|
||||
#define WL_DEBUG_COLOR_RESET "\e[0m"
|
||||
#define WL_DEBUG_COLOR_RED "\e[31m"
|
||||
#define WL_DEBUG_COLOR_GREEN "\e[32m"
|
||||
#define WL_DEBUG_COLOR_YELLOW "\e[33m"
|
||||
#define WL_DEBUG_COLOR_BLUE "\e[34m"
|
||||
#define WL_DEBUG_COLOR_MAGENTA "\e[35m"
|
||||
#define WL_DEBUG_COLOR_CYAN "\e[36m"
|
||||
|
||||
/**
|
||||
* Argument types used in signatures.
|
||||
*/
|
||||
enum wl_arg_type {
|
||||
WL_ARG_INT = 'i',
|
||||
WL_ARG_UINT = 'u',
|
||||
WL_ARG_FIXED = 'f',
|
||||
WL_ARG_STRING = 's',
|
||||
WL_ARG_OBJECT = 'o',
|
||||
WL_ARG_NEW_ID = 'n',
|
||||
WL_ARG_ARRAY = 'a',
|
||||
WL_ARG_FD = 'h',
|
||||
};
|
||||
|
||||
struct wl_object {
|
||||
const struct wl_interface *interface;
|
||||
|
|
@ -106,7 +133,7 @@ void
|
|||
wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data);
|
||||
|
||||
struct wl_connection *
|
||||
wl_connection_create(int fd);
|
||||
wl_connection_create(int fd, size_t max_buffer_size);
|
||||
|
||||
int
|
||||
wl_connection_destroy(struct wl_connection *connection);
|
||||
|
|
@ -149,7 +176,7 @@ struct wl_closure {
|
|||
};
|
||||
|
||||
struct argument_details {
|
||||
char type;
|
||||
enum wl_arg_type type;
|
||||
int nullable;
|
||||
};
|
||||
|
||||
|
|
@ -210,10 +237,14 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection);
|
|||
int
|
||||
wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
|
||||
|
||||
bool
|
||||
wl_check_env_token(const char *env, const char *token);
|
||||
|
||||
void
|
||||
wl_closure_print(struct wl_closure *closure,
|
||||
struct wl_object *target, int send, int discarded,
|
||||
uint32_t (*n_parse)(union wl_argument *arg));
|
||||
uint32_t (*n_parse)(union wl_argument *arg),
|
||||
const char *queue_name, int color);
|
||||
|
||||
void
|
||||
wl_closure_destroy(struct wl_closure *closure);
|
||||
|
|
@ -237,4 +268,8 @@ zalloc(size_t s)
|
|||
void
|
||||
wl_connection_close_fds_in(struct wl_connection *connection, int max);
|
||||
|
||||
void
|
||||
wl_connection_set_max_buffer_size(struct wl_connection *connection,
|
||||
size_t max_buffer_size);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -217,13 +217,17 @@ wl_display_flush_clients(struct wl_display *display);
|
|||
void
|
||||
wl_display_destroy_clients(struct wl_display *display);
|
||||
|
||||
void
|
||||
wl_display_set_default_max_buffer_size(struct wl_display *display,
|
||||
size_t max_buffer_size);
|
||||
|
||||
struct wl_client;
|
||||
|
||||
typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
|
||||
uint32_t version, uint32_t id);
|
||||
|
||||
uint32_t
|
||||
wl_display_get_serial(struct wl_display *display);
|
||||
wl_display_get_serial(const struct wl_display *display);
|
||||
|
||||
uint32_t
|
||||
wl_display_next_serial(struct wl_display *display);
|
||||
|
|
@ -320,7 +324,7 @@ void
|
|||
wl_client_flush(struct wl_client *client);
|
||||
|
||||
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);
|
||||
|
||||
int
|
||||
|
|
@ -365,6 +369,19 @@ wl_client_for_each_resource(struct wl_client *client,
|
|||
wl_client_for_each_resource_iterator_func_t iterator,
|
||||
void *user_data);
|
||||
|
||||
typedef void (*wl_user_data_destroy_func_t)(void *data);
|
||||
|
||||
void
|
||||
wl_client_set_user_data(struct wl_client *client,
|
||||
void *data,
|
||||
wl_user_data_destroy_func_t dtor);
|
||||
|
||||
void *
|
||||
wl_client_get_user_data(struct wl_client *client);
|
||||
|
||||
void
|
||||
wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size);
|
||||
|
||||
/** \class wl_listener
|
||||
*
|
||||
* \brief A single listener for Wayland signals
|
||||
|
|
@ -533,7 +550,10 @@ void
|
|||
wl_resource_queue_event_array(struct wl_resource *resource,
|
||||
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
|
||||
wl_resource_post_error(struct wl_resource *resource,
|
||||
uint32_t code, const char *msg, ...) WL_PRINTF(3, 4);
|
||||
|
|
@ -566,7 +586,7 @@ void
|
|||
wl_resource_destroy(struct wl_resource *resource);
|
||||
|
||||
uint32_t
|
||||
wl_resource_get_id(struct wl_resource *resource);
|
||||
wl_resource_get_id(const struct wl_resource *resource);
|
||||
|
||||
struct wl_list *
|
||||
wl_resource_get_link(struct wl_resource *resource);
|
||||
|
|
@ -587,7 +607,7 @@ void *
|
|||
wl_resource_get_user_data(struct wl_resource *resource);
|
||||
|
||||
int
|
||||
wl_resource_get_version(struct wl_resource *resource);
|
||||
wl_resource_get_version(const struct wl_resource *resource);
|
||||
|
||||
void
|
||||
wl_resource_set_destructor(struct wl_resource *resource,
|
||||
|
|
@ -597,8 +617,12 @@ int
|
|||
wl_resource_instance_of(struct wl_resource *resource,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation);
|
||||
|
||||
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
|
||||
wl_resource_add_destroy_listener(struct wl_resource *resource,
|
||||
|
|
@ -634,16 +658,22 @@ void *
|
|||
wl_shm_buffer_get_data(struct wl_shm_buffer *buffer);
|
||||
|
||||
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
|
||||
wl_shm_buffer_get_format(struct wl_shm_buffer *buffer);
|
||||
wl_shm_buffer_get_format(const struct wl_shm_buffer *buffer);
|
||||
|
||||
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
|
||||
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 *
|
||||
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer);
|
||||
|
|
@ -657,10 +687,11 @@ wl_display_init_shm(struct wl_display *display);
|
|||
uint32_t *
|
||||
wl_display_add_shm_format(struct wl_display *display, uint32_t format);
|
||||
|
||||
WL_DEPRECATED
|
||||
struct wl_shm_buffer *
|
||||
wl_shm_buffer_create(struct wl_client *client,
|
||||
uint32_t id, int32_t width, int32_t height,
|
||||
int32_t stride, uint32_t format) WL_DEPRECATED;
|
||||
int32_t stride, uint32_t format);
|
||||
|
||||
void
|
||||
wl_log_set_handler_server(wl_log_func_t handler);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <dlfcn.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/eventfd.h>
|
||||
|
|
@ -83,13 +82,15 @@ struct wl_client {
|
|||
pid_t pid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
int error;
|
||||
bool error;
|
||||
struct wl_priv_signal resource_created_signal;
|
||||
void *data;
|
||||
wl_user_data_destroy_func_t data_dtor;
|
||||
};
|
||||
|
||||
struct wl_display {
|
||||
struct wl_event_loop *loop;
|
||||
int run;
|
||||
bool run;
|
||||
|
||||
uint32_t next_global_name;
|
||||
uint32_t serial;
|
||||
|
|
@ -110,6 +111,8 @@ struct wl_display {
|
|||
|
||||
int terminate_efd;
|
||||
struct wl_event_source *term_source;
|
||||
|
||||
size_t max_buffer_size;
|
||||
};
|
||||
|
||||
struct wl_global {
|
||||
|
|
@ -146,6 +149,7 @@ struct wl_protocol_logger {
|
|||
};
|
||||
|
||||
static int debug_server = 0;
|
||||
static int debug_color = 0;
|
||||
|
||||
static void
|
||||
log_closure(struct wl_resource *resource,
|
||||
|
|
@ -157,7 +161,7 @@ log_closure(struct wl_resource *resource,
|
|||
struct wl_protocol_logger_message message;
|
||||
|
||||
if (debug_server)
|
||||
wl_closure_print(closure, object, send, false, NULL);
|
||||
wl_closure_print(closure, object, send, false, NULL, NULL, debug_color);
|
||||
|
||||
if (!wl_list_empty(&display->protocol_loggers)) {
|
||||
message.resource = resource;
|
||||
|
|
@ -189,8 +193,8 @@ verify_objects(struct wl_resource *resource, uint32_t opcode,
|
|||
for (i = 0; i < count; i++) {
|
||||
signature = get_next_argument(signature, &arg);
|
||||
switch (arg.type) {
|
||||
case 'n':
|
||||
case 'o':
|
||||
case WL_ARG_NEW_ID:
|
||||
case WL_ARG_OBJECT:
|
||||
res = (struct wl_resource *) (args[i].o);
|
||||
if (res && res->client != resource->client) {
|
||||
wl_log("compositor bug: The compositor "
|
||||
|
|
@ -200,6 +204,8 @@ verify_objects(struct wl_resource *resource, uint32_t opcode,
|
|||
object->interface->events[opcode].name);
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -217,7 +223,7 @@ handle_array(struct wl_resource *resource, uint32_t opcode,
|
|||
return;
|
||||
|
||||
if (!verify_objects(resource, opcode, args)) {
|
||||
resource->client->error = 1;
|
||||
resource->client->error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -225,14 +231,14 @@ handle_array(struct wl_resource *resource, uint32_t opcode,
|
|||
&object->interface->events[opcode]);
|
||||
|
||||
if (closure == NULL) {
|
||||
resource->client->error = 1;
|
||||
resource->client->error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
log_closure(resource, closure, true);
|
||||
|
||||
if (send_func(closure, resource->client->connection))
|
||||
resource->client->error = 1;
|
||||
resource->client->error = true;
|
||||
|
||||
wl_closure_destroy(closure);
|
||||
}
|
||||
|
|
@ -282,7 +288,16 @@ wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
|
|||
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,
|
||||
uint32_t code, const char *msg, va_list argp)
|
||||
{
|
||||
|
|
@ -303,10 +318,18 @@ wl_resource_post_error_vargs(struct wl_resource *resource,
|
|||
|
||||
wl_resource_post_event(client->display_resource,
|
||||
WL_DISPLAY_ERROR, resource, code, buffer);
|
||||
client->error = 1;
|
||||
|
||||
client->error = true;
|
||||
}
|
||||
|
||||
/** Post a protocol error
|
||||
*
|
||||
* \param resource The resource object
|
||||
* \param code The error code
|
||||
* \param msg The error message format string
|
||||
* \param ... The format string arguments
|
||||
*
|
||||
* \memberof wl_resource
|
||||
*/
|
||||
WL_EXPORT void
|
||||
wl_resource_post_error(struct wl_resource *resource,
|
||||
uint32_t code, const char *msg, ...)
|
||||
|
|
@ -375,6 +398,29 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
|||
wl_connection_copy(connection, p, sizeof p);
|
||||
opcode = p[1] & 0xffff;
|
||||
size = p[1] >> 16;
|
||||
|
||||
/*
|
||||
* If the message is larger than the maximum size of the
|
||||
* connection buffer, the connection buffer will fill to
|
||||
* its max size and stay there, with no message ever
|
||||
* successfully being processed. Since libwayland-server
|
||||
* uses level-triggered epoll, it will cause the server to
|
||||
* enter a loop that consumes CPU. To avoid this,
|
||||
* immediately disconnect the client with a protocol
|
||||
* error. Since the maximum size of a message should not
|
||||
* depend on the buffer size chosen by the compositor,
|
||||
* always compare the message size against the
|
||||
* limit enforced by libwayland 1.22 and below (4096),
|
||||
* rather than the actual value the compositor chose.
|
||||
*/
|
||||
if (size > WL_MAX_MESSAGE_SIZE) {
|
||||
wl_resource_post_error(client->display_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_METHOD,
|
||||
"message length %u exceeds %d",
|
||||
size, WL_MAX_MESSAGE_SIZE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (len < size)
|
||||
break;
|
||||
|
||||
|
|
@ -391,7 +437,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
|||
if (opcode >= object->interface->method_count) {
|
||||
wl_resource_post_error(client->display_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_METHOD,
|
||||
"invalid method %d, object %s@%u",
|
||||
"invalid method %d, object %s#%u",
|
||||
opcode,
|
||||
object->interface->name,
|
||||
object->id);
|
||||
|
|
@ -405,7 +451,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
|||
wl_resource_post_error(client->display_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_METHOD,
|
||||
"invalid method %d (since %d < %d)"
|
||||
", object %s@%u",
|
||||
", object %s#%u",
|
||||
opcode, resource->version, since,
|
||||
object->interface->name,
|
||||
object->id);
|
||||
|
|
@ -423,7 +469,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
|
|||
wl_closure_lookup_objects(closure, &client->objects) < 0) {
|
||||
wl_resource_post_error(client->display_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_METHOD,
|
||||
"invalid arguments for %s@%u.%s",
|
||||
"invalid arguments for %s#%u.%s",
|
||||
object->interface->name,
|
||||
object->id,
|
||||
message->name);
|
||||
|
|
@ -514,6 +560,11 @@ bind_display(struct wl_client *client, struct wl_display *display);
|
|||
*
|
||||
* On failure this function sets errno accordingly and returns NULL.
|
||||
*
|
||||
* On success, the new client object takes the ownership of the file
|
||||
* descriptor. On failure, the ownership of the socket endpoint file
|
||||
* descriptor is unchanged, it is the responsibility of the caller to
|
||||
* perform cleanup, e.g. call close().
|
||||
*
|
||||
* \memberof wl_display
|
||||
*/
|
||||
WL_EXPORT struct wl_client *
|
||||
|
|
@ -538,7 +589,8 @@ wl_client_create(struct wl_display *display, int fd)
|
|||
&client->pid) != 0)
|
||||
goto err_source;
|
||||
|
||||
client->connection = wl_connection_create(fd);
|
||||
client->connection = wl_connection_create(fd, display->max_buffer_size);
|
||||
|
||||
if (client->connection == NULL)
|
||||
goto err_source;
|
||||
|
||||
|
|
@ -591,7 +643,7 @@ err_client:
|
|||
* \memberof wl_client
|
||||
*/
|
||||
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)
|
||||
{
|
||||
if (pid)
|
||||
|
|
@ -717,10 +769,23 @@ resource_is_deprecated(struct wl_resource *resource)
|
|||
return false;
|
||||
}
|
||||
|
||||
/** Removes the wl_resource from the client's object map and deletes it.
|
||||
*
|
||||
* Triggers the destroy signal and destructor for the resource before
|
||||
* removing it from the client's object map and releasing the resource's
|
||||
* memory.
|
||||
*
|
||||
* This order is important to ensure listeners and destruction code can
|
||||
* find the resource before it has been destroyed whilst ensuring the
|
||||
* resource is not accessible via the object map after memory has been
|
||||
* freed.
|
||||
*/
|
||||
static enum wl_iterator_result
|
||||
destroy_resource(void *element, void *data, uint32_t flags)
|
||||
remove_and_destroy_resource(void *element, void *data, uint32_t flags)
|
||||
{
|
||||
struct wl_resource *resource = element;
|
||||
struct wl_client *client = resource->client;
|
||||
uint32_t id = resource->object.id;;
|
||||
|
||||
wl_signal_emit(&resource->deprecated_destroy_signal, resource);
|
||||
/* Don't emit the new signal for deprecated resources, as that would
|
||||
|
|
@ -731,6 +796,17 @@ destroy_resource(void *element, void *data, uint32_t flags)
|
|||
if (resource->destroy)
|
||||
resource->destroy(resource);
|
||||
|
||||
/* The resource should be cleared from the map before memory is freed. */
|
||||
if (id < WL_SERVER_ID_START) {
|
||||
if (client->display_resource) {
|
||||
wl_resource_queue_event(client->display_resource,
|
||||
WL_DISPLAY_DELETE_ID, id);
|
||||
}
|
||||
wl_map_insert_at(&client->objects, 0, id, NULL);
|
||||
} else {
|
||||
wl_map_remove(&client->objects, id);
|
||||
}
|
||||
|
||||
if (!(flags & WL_MAP_ENTRY_LEGACY))
|
||||
free(resource);
|
||||
|
||||
|
|
@ -741,26 +817,13 @@ WL_EXPORT void
|
|||
wl_resource_destroy(struct wl_resource *resource)
|
||||
{
|
||||
struct wl_client *client = resource->client;
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
uint32_t flags = wl_map_lookup_flags(&client->objects, resource->object.id);
|
||||
|
||||
id = resource->object.id;
|
||||
flags = wl_map_lookup_flags(&client->objects, id);
|
||||
destroy_resource(resource, NULL, flags);
|
||||
|
||||
if (id < WL_SERVER_ID_START) {
|
||||
if (client->display_resource) {
|
||||
wl_resource_queue_event(client->display_resource,
|
||||
WL_DISPLAY_DELETE_ID, id);
|
||||
}
|
||||
wl_map_insert_at(&client->objects, 0, id, NULL);
|
||||
} else {
|
||||
wl_map_remove(&client->objects, id);
|
||||
}
|
||||
remove_and_destroy_resource(resource, NULL, flags);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -814,7 +877,7 @@ wl_resource_get_user_data(struct wl_resource *resource)
|
|||
}
|
||||
|
||||
WL_EXPORT int
|
||||
wl_resource_get_version(struct wl_resource *resource)
|
||||
wl_resource_get_version(const struct wl_resource *resource)
|
||||
{
|
||||
return resource->version;
|
||||
}
|
||||
|
|
@ -861,11 +924,25 @@ wl_resource_get_destroy_listener(struct wl_resource *resource,
|
|||
* \memberof wl_resource
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/** 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
|
||||
*
|
||||
|
|
@ -920,20 +997,33 @@ wl_client_get_destroy_late_listener(struct wl_client *client,
|
|||
WL_EXPORT void
|
||||
wl_client_destroy(struct wl_client *client)
|
||||
{
|
||||
uint32_t serial = 0;
|
||||
|
||||
/* wl_client_destroy() should not be called twice for the same client. */
|
||||
if (wl_list_empty(&client->link)) {
|
||||
client->error = 1;
|
||||
wl_log("wl_client_destroy: encountered re-entrant client destruction.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_list_remove(&client->link);
|
||||
/* Keep the client link safe to inspect. */
|
||||
wl_list_init(&client->link);
|
||||
|
||||
wl_priv_signal_final_emit(&client->destroy_signal, client);
|
||||
|
||||
wl_client_flush(client);
|
||||
wl_map_for_each(&client->objects, destroy_resource, &serial);
|
||||
wl_map_for_each(&client->objects, remove_and_destroy_resource, NULL);
|
||||
wl_map_release(&client->objects);
|
||||
wl_event_source_remove(client->source);
|
||||
close(wl_connection_destroy(client->connection));
|
||||
|
||||
wl_priv_signal_final_emit(&client->destroy_late_signal, client);
|
||||
|
||||
wl_list_remove(&client->link);
|
||||
wl_list_remove(&client->resource_created_signal.listener_list);
|
||||
|
||||
if (client->data_dtor)
|
||||
client->data_dtor(client->data);
|
||||
|
||||
free(client);
|
||||
}
|
||||
|
||||
|
|
@ -1102,10 +1192,23 @@ wl_display_create(void)
|
|||
{
|
||||
struct wl_display *display;
|
||||
const char *debug;
|
||||
const char *no_color;
|
||||
const char *force_color;
|
||||
|
||||
no_color = getenv("NO_COLOR");
|
||||
force_color = getenv("FORCE_COLOR");
|
||||
debug = getenv("WAYLAND_DEBUG");
|
||||
if (debug && (strstr(debug, "server") || strstr(debug, "1")))
|
||||
if (debug && (wl_check_env_token(debug, "server") || wl_check_env_token(debug, "1"))) {
|
||||
debug_server = 1;
|
||||
if (isatty(fileno(stderr)))
|
||||
debug_color = 1;
|
||||
}
|
||||
|
||||
if (force_color && force_color[0] != '\0')
|
||||
debug_color = 1;
|
||||
|
||||
if (no_color && no_color[0] != '\0')
|
||||
debug_color = 0;
|
||||
|
||||
display = zalloc(sizeof *display);
|
||||
if (display == NULL)
|
||||
|
|
@ -1144,6 +1247,7 @@ wl_display_create(void)
|
|||
|
||||
display->global_filter = NULL;
|
||||
display->global_filter_data = NULL;
|
||||
display->max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE;
|
||||
|
||||
wl_array_init(&display->additional_shm_formats);
|
||||
|
||||
|
|
@ -1343,7 +1447,7 @@ wl_global_remove(struct wl_global *global)
|
|||
|
||||
if (global->removed)
|
||||
wl_abort("wl_global_remove: called twice on the same "
|
||||
"global '%s@%"PRIu32"'", global->interface->name,
|
||||
"global '%s#%"PRIu32"'", global->interface->name,
|
||||
global->name);
|
||||
|
||||
wl_list_for_each(resource, &display->registry_resource_list, link)
|
||||
|
|
@ -1443,7 +1547,7 @@ wl_global_set_user_data(struct wl_global *global, void *data)
|
|||
* \memberof wl_display
|
||||
*/
|
||||
WL_EXPORT uint32_t
|
||||
wl_display_get_serial(struct wl_display *display)
|
||||
wl_display_get_serial(const struct wl_display *display)
|
||||
{
|
||||
return display->serial;
|
||||
}
|
||||
|
|
@ -1477,20 +1581,23 @@ wl_display_terminate(struct wl_display *display)
|
|||
int ret;
|
||||
uint64_t terminate = 1;
|
||||
|
||||
display->run = 0;
|
||||
display->run = false;
|
||||
|
||||
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_display_run(struct wl_display *display)
|
||||
{
|
||||
display->run = 1;
|
||||
display->run = true;
|
||||
|
||||
while (display->run) {
|
||||
wl_display_flush_clients(display);
|
||||
wl_event_loop_dispatch(display->loop, -1);
|
||||
if (wl_event_loop_dispatch(display->loop, -1) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1550,6 +1657,37 @@ wl_display_destroy_clients(struct wl_display *display)
|
|||
}
|
||||
}
|
||||
|
||||
/** Sets the default maximum size for connection buffers of new clients
|
||||
*
|
||||
* \param display The display object
|
||||
* \param max_buffer_size The default maximum size of the connection buffers
|
||||
*
|
||||
* This function sets the default size of the internal connection buffers for
|
||||
* new clients. It doesn't change the buffer size for existing wl_client.
|
||||
*
|
||||
* The connection buffer size of an existing wl_client can be adjusted using
|
||||
* wl_client_set_max_buffer_size().
|
||||
*
|
||||
* The actual size of the connection buffers is a power of two, the requested
|
||||
* \a max_buffer_size is therefore rounded up to the nearest power of two value.
|
||||
*
|
||||
* The minimum buffer size is 4096.
|
||||
*
|
||||
* \sa wl_client_set_max_buffer_size
|
||||
*
|
||||
* \memberof wl_display
|
||||
* \since 1.22.90
|
||||
*/
|
||||
WL_EXPORT void
|
||||
wl_display_set_default_max_buffer_size(struct wl_display *display,
|
||||
size_t max_buffer_size)
|
||||
{
|
||||
if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE)
|
||||
max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE;
|
||||
|
||||
display->max_buffer_size = max_buffer_size;
|
||||
}
|
||||
|
||||
static int
|
||||
socket_data(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
|
|
@ -1644,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,
|
||||
"%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) {
|
||||
wl_log("error: socket path \"%s%s%s\" plus null terminator"
|
||||
" exceeds 108 bytes\n", runtime_dir, separator, name);
|
||||
|
|
@ -1692,6 +1831,24 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Automatically pick a Wayland display socket for the clients to connect to.
|
||||
*
|
||||
* \param display Wayland display to which the socket should be added.
|
||||
* \return The socket name if success. NULL if failed.
|
||||
*
|
||||
* This adds a Unix socket to Wayland display which can be used by clients to
|
||||
* connect to Wayland display. The name of the socket is chosen automatically
|
||||
* as the first available name in the sequence "wayland-0", "wayland-1",
|
||||
* "wayland-2", ..., "wayland-32".
|
||||
*
|
||||
* The string returned by this function is owned by the library and should
|
||||
* not be freed.
|
||||
*
|
||||
* \sa wl_display_add_socket
|
||||
*
|
||||
* \memberof wl_display
|
||||
*/
|
||||
WL_EXPORT const char *
|
||||
wl_display_add_socket_auto(struct wl_display *display)
|
||||
{
|
||||
|
|
@ -1741,6 +1898,9 @@ wl_display_add_socket_auto(struct wl_display *display)
|
|||
* The fd must be properly set to CLOEXEC and bound to a socket file
|
||||
* with both bind() and listen() already called.
|
||||
*
|
||||
* On success, the socket fd ownership is transferred to libwayland:
|
||||
* libwayland will close the socket when the display is destroyed.
|
||||
*
|
||||
* \memberof wl_display
|
||||
*/
|
||||
WL_EXPORT int
|
||||
|
|
@ -1969,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 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
|
||||
*
|
||||
|
|
@ -2245,6 +2405,34 @@ wl_signal_emit_mutable(struct wl_signal *signal, void *data)
|
|||
wl_list_remove(&end.link);
|
||||
}
|
||||
|
||||
/** Adjust the maximum size of the client connection buffers
|
||||
*
|
||||
* \param client The client object
|
||||
* \param max_buffer_size The maximum size of the connection buffers
|
||||
*
|
||||
* The actual size of the connection buffers is a power of two, the requested
|
||||
* \a max_buffer_size is therefore rounded up to the nearest power of two value.
|
||||
*
|
||||
* Lowering the maximum size may not take effect immediately if the current content
|
||||
* of the buffer does not fit within the new size limit.
|
||||
*
|
||||
* The minimum buffer size is 4096. The default buffers size can be set using
|
||||
* wl_display_set_default_max_buffer_size().
|
||||
*
|
||||
* \sa wl_display_set_default_max_buffer_size()
|
||||
*
|
||||
* \memberof wl_client
|
||||
* \since 1.22.90
|
||||
*/
|
||||
WL_EXPORT void
|
||||
wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size)
|
||||
{
|
||||
if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE)
|
||||
max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE;
|
||||
|
||||
wl_connection_set_max_buffer_size(client->connection, max_buffer_size);
|
||||
}
|
||||
|
||||
/** \cond INTERNAL */
|
||||
|
||||
/** Initialize a wl_priv_signal object
|
||||
|
|
@ -2382,9 +2570,10 @@ wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data)
|
|||
|
||||
/** \cond */ /* Deprecated functions below. */
|
||||
|
||||
WL_DEPRECATED
|
||||
uint32_t
|
||||
wl_client_add_resource(struct wl_client *client,
|
||||
struct wl_resource *resource) WL_DEPRECATED;
|
||||
struct wl_resource *resource);
|
||||
|
||||
WL_EXPORT uint32_t
|
||||
wl_client_add_resource(struct wl_client *client,
|
||||
|
|
@ -2413,11 +2602,12 @@ wl_client_add_resource(struct wl_client *client,
|
|||
return resource->object.id;
|
||||
}
|
||||
|
||||
WL_DEPRECATED
|
||||
struct wl_resource *
|
||||
wl_client_add_object(struct wl_client *client,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation,
|
||||
uint32_t id, void *data) WL_DEPRECATED;
|
||||
uint32_t id, void *data);
|
||||
|
||||
WL_EXPORT struct wl_resource *
|
||||
wl_client_add_object(struct wl_client *client,
|
||||
|
|
@ -2436,10 +2626,11 @@ wl_client_add_object(struct wl_client *client,
|
|||
return resource;
|
||||
}
|
||||
|
||||
WL_DEPRECATED
|
||||
struct wl_resource *
|
||||
wl_client_new_object(struct wl_client *client,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation, void *data) WL_DEPRECATED;
|
||||
const void *implementation, void *data);
|
||||
|
||||
WL_EXPORT struct wl_resource *
|
||||
wl_client_new_object(struct wl_client *client,
|
||||
|
|
@ -2458,10 +2649,51 @@ wl_client_new_object(struct wl_client *client,
|
|||
return resource;
|
||||
}
|
||||
|
||||
/** Set the client's user data
|
||||
*
|
||||
* User data is whatever the caller wants to store. Use dtor if
|
||||
* the user data needs freeing as the very last step of destroying
|
||||
* the client.
|
||||
*
|
||||
* \param client The client object
|
||||
* \param data The user data pointer
|
||||
* \param dtor Destroy function to be called after all resources have been
|
||||
* destroyed and all destroy listeners have been called. Can be NULL.
|
||||
*
|
||||
* The argument to the destroy function is the user data pointer. If the
|
||||
* destroy function is not NULL, it will be called even if user data is NULL.
|
||||
*
|
||||
* \since 1.22.90
|
||||
* \sa wl_client_get_user_data
|
||||
*/
|
||||
WL_EXPORT void
|
||||
wl_client_set_user_data(struct wl_client *client,
|
||||
void *data,
|
||||
wl_user_data_destroy_func_t dtor)
|
||||
{
|
||||
client->data = data;
|
||||
client->data_dtor = dtor;
|
||||
}
|
||||
|
||||
/** Get the client's user data
|
||||
*
|
||||
* \param client The client object
|
||||
* \return The user data pointer
|
||||
*
|
||||
* \since 1.22.90
|
||||
* \sa wl_client_set_user_data
|
||||
*/
|
||||
WL_EXPORT void *
|
||||
wl_client_get_user_data(struct wl_client *client)
|
||||
{
|
||||
return client->data;
|
||||
}
|
||||
|
||||
WL_DEPRECATED
|
||||
struct wl_global *
|
||||
wl_display_add_global(struct wl_display *display,
|
||||
const struct wl_interface *interface,
|
||||
void *data, wl_global_bind_func_t bind) WL_DEPRECATED;
|
||||
void *data, wl_global_bind_func_t bind);
|
||||
|
||||
WL_EXPORT struct wl_global *
|
||||
wl_display_add_global(struct wl_display *display,
|
||||
|
|
@ -2471,9 +2703,10 @@ wl_display_add_global(struct wl_display *display,
|
|||
return wl_global_create(display, interface, interface->version, data, bind);
|
||||
}
|
||||
|
||||
WL_DEPRECATED
|
||||
void
|
||||
wl_display_remove_global(struct wl_display *display,
|
||||
struct wl_global *global) WL_DEPRECATED;
|
||||
struct wl_global *global);
|
||||
|
||||
WL_EXPORT void
|
||||
wl_display_remove_global(struct wl_display *display, struct wl_global *global)
|
||||
|
|
|
|||
|
|
@ -70,30 +70,35 @@ struct wl_resource {
|
|||
void *data;
|
||||
};
|
||||
|
||||
WL_DEPRECATED
|
||||
uint32_t
|
||||
wl_client_add_resource(struct wl_client *client,
|
||||
struct wl_resource *resource) WL_DEPRECATED;
|
||||
struct wl_resource *resource);
|
||||
|
||||
WL_DEPRECATED
|
||||
struct wl_resource *
|
||||
wl_client_add_object(struct wl_client *client,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation,
|
||||
uint32_t id, void *data) WL_DEPRECATED;
|
||||
uint32_t id, void *data);
|
||||
|
||||
WL_DEPRECATED
|
||||
struct wl_resource *
|
||||
wl_client_new_object(struct wl_client *client,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation, void *data) WL_DEPRECATED;
|
||||
const void *implementation, void *data);
|
||||
|
||||
WL_DEPRECATED
|
||||
struct wl_global *
|
||||
wl_display_add_global(struct wl_display *display,
|
||||
const struct wl_interface *interface,
|
||||
void *data,
|
||||
wl_global_bind_func_t bind) WL_DEPRECATED;
|
||||
wl_global_bind_func_t bind);
|
||||
|
||||
WL_DEPRECATED
|
||||
void
|
||||
wl_display_remove_global(struct wl_display *display,
|
||||
struct wl_global *global) WL_DEPRECATED;
|
||||
struct wl_global *global);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@
|
|||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -85,6 +84,10 @@ struct wl_shm_pool {
|
|||
*/
|
||||
struct wl_shm_buffer {
|
||||
struct wl_resource *resource;
|
||||
int internal_refcount;
|
||||
int external_refcount;
|
||||
struct wl_client *client;
|
||||
struct wl_listener client_destroy_listener;
|
||||
int32_t width, height;
|
||||
int32_t stride;
|
||||
uint32_t format;
|
||||
|
|
@ -144,12 +147,16 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external)
|
|||
{
|
||||
if (external) {
|
||||
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)
|
||||
shm_pool_finish_resize(pool);
|
||||
} else {
|
||||
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)
|
||||
|
|
@ -162,13 +169,38 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external)
|
|||
free(pool);
|
||||
}
|
||||
|
||||
static void
|
||||
shm_buffer_unref(struct wl_shm_buffer *buffer, bool external)
|
||||
{
|
||||
if (external) {
|
||||
buffer->external_refcount--;
|
||||
if (buffer->external_refcount < 0) {
|
||||
wl_abort("Requested to unref an external reference to "
|
||||
"buffer but none found\n");
|
||||
}
|
||||
} else {
|
||||
buffer->internal_refcount--;
|
||||
if (buffer->internal_refcount < 0) {
|
||||
wl_abort("Requested to unref an internal reference to "
|
||||
"buffer but none found\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer->internal_refcount + buffer->external_refcount > 0)
|
||||
return;
|
||||
|
||||
if (buffer->client)
|
||||
wl_list_remove(&buffer->client_destroy_listener.link);
|
||||
shm_pool_unref(buffer->pool, false);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_buffer(struct wl_resource *resource)
|
||||
{
|
||||
struct wl_shm_buffer *buffer = wl_resource_get_user_data(resource);
|
||||
|
||||
shm_pool_unref(buffer->pool, false);
|
||||
free(buffer);
|
||||
shm_buffer_unref(buffer, false);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -202,6 +234,17 @@ format_is_supported(struct wl_client *client, uint32_t format)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
shm_buffer_client_destroy_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wl_shm_buffer *buffer =
|
||||
wl_container_of(listener, buffer, client_destroy_listener);
|
||||
|
||||
buffer->client = NULL;
|
||||
wl_list_remove(&buffer->client_destroy_listener.link);
|
||||
}
|
||||
|
||||
static void
|
||||
shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, int32_t offset,
|
||||
|
|
@ -234,6 +277,14 @@ shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
|||
return;
|
||||
}
|
||||
|
||||
buffer->client = client;
|
||||
buffer->client_destroy_listener.notify =
|
||||
shm_buffer_client_destroy_notify;
|
||||
wl_client_add_destroy_listener(buffer->client,
|
||||
&buffer->client_destroy_listener);
|
||||
|
||||
buffer->internal_refcount = 1;
|
||||
buffer->external_refcount = 0;
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
buffer->format = format;
|
||||
|
|
@ -310,6 +361,7 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource,
|
|||
int seals;
|
||||
int prot;
|
||||
int flags;
|
||||
uint32_t version;
|
||||
|
||||
if (size <= 0) {
|
||||
wl_resource_post_error(resource,
|
||||
|
|
@ -358,8 +410,10 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource,
|
|||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
|
||||
version = wl_resource_get_version(resource);
|
||||
pool->resource =
|
||||
wl_resource_create(client, &wl_shm_pool_interface, 1, id);
|
||||
wl_resource_create(client, &wl_shm_pool_interface, version, id);
|
||||
if (!pool->resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
munmap(pool->data, pool->size);
|
||||
|
|
@ -379,8 +433,15 @@ err_close:
|
|||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
shm_release(struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct wl_shm_interface shm_interface = {
|
||||
shm_create_pool
|
||||
shm_create_pool,
|
||||
shm_release,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -392,7 +453,7 @@ bind_shm(struct wl_client *client,
|
|||
struct wl_array *additional_formats;
|
||||
uint32_t *p;
|
||||
|
||||
resource = wl_resource_create(client, &wl_shm_interface, 1, id);
|
||||
resource = wl_resource_create(client, &wl_shm_interface, version, id);
|
||||
if (!resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
|
|
@ -411,7 +472,7 @@ bind_shm(struct wl_client *client,
|
|||
WL_EXPORT int
|
||||
wl_display_init_shm(struct wl_display *display)
|
||||
{
|
||||
if (!wl_global_create(display, &wl_shm_interface, 1, NULL, bind_shm))
|
||||
if (!wl_global_create(display, &wl_shm_interface, 2, NULL, bind_shm))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
|
@ -431,7 +492,7 @@ wl_shm_buffer_get(struct wl_resource *resource)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -448,8 +509,8 @@ wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer)
|
|||
* SIGBUS signals. This can happen if the client claims that the
|
||||
* buffer is larger than it is or if something truncates the
|
||||
* underlying file. To prevent this signal from causing the compositor
|
||||
* to crash you should call wl_shm_buffer_begin_access and
|
||||
* wl_shm_buffer_end_access around code that reads from the memory.
|
||||
* to crash you should call wl_shm_buffer_begin_access() and
|
||||
* wl_shm_buffer_end_access() around code that reads from the memory.
|
||||
*
|
||||
* \memberof wl_shm_buffer
|
||||
*/
|
||||
|
|
@ -465,23 +526,62 @@ wl_shm_buffer_get_data(struct wl_shm_buffer *buffer)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** Reference a shm_buffer
|
||||
*
|
||||
* \param buffer The buffer object
|
||||
*
|
||||
* Returns a pointer to the buffer and increases the refcount.
|
||||
*
|
||||
* The compositor must remember to call wl_shm_buffer_unref() when
|
||||
* it no longer needs the reference to ensure proper destruction
|
||||
* of the buffer.
|
||||
*
|
||||
* \memberof wl_shm_buffer
|
||||
* \sa wl_shm_buffer_unref
|
||||
*/
|
||||
WL_EXPORT struct wl_shm_buffer *
|
||||
wl_shm_buffer_ref(struct wl_shm_buffer *buffer)
|
||||
{
|
||||
buffer->external_refcount++;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/** Unreference a shm_buffer
|
||||
*
|
||||
* \param buffer The buffer object
|
||||
*
|
||||
* Drops a reference to a buffer object.
|
||||
*
|
||||
* This is only necessary if the compositor has explicitly
|
||||
* taken a reference with wl_shm_buffer_ref(), otherwise
|
||||
* the buffer will be automatically destroyed when appropriate.
|
||||
*
|
||||
* \memberof wl_shm_buffer
|
||||
* \sa wl_shm_buffer_ref
|
||||
*/
|
||||
WL_EXPORT void
|
||||
wl_shm_buffer_unref(struct wl_shm_buffer *buffer)
|
||||
{
|
||||
shm_buffer_unref(buffer, true);
|
||||
}
|
||||
|
||||
/** Get a reference to a shm_buffer's shm_pool
|
||||
*
|
||||
* \param buffer The buffer object
|
||||
|
|
@ -489,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
|
||||
* shm_pool refcount.
|
||||
*
|
||||
* The compositor must remember to call wl_shm_pool_unref when
|
||||
* The compositor must remember to call wl_shm_pool_unref() when
|
||||
* it no longer needs the reference to ensure proper destruction
|
||||
* of the pool.
|
||||
*
|
||||
|
|
@ -499,9 +599,6 @@ wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
|
|||
WL_EXPORT struct wl_shm_pool *
|
||||
wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer)
|
||||
{
|
||||
assert(buffer->pool->internal_refcount +
|
||||
buffer->pool->external_refcount);
|
||||
|
||||
buffer->pool->external_refcount++;
|
||||
return buffer->pool;
|
||||
}
|
||||
|
|
@ -603,7 +700,7 @@ init_sigbus_data_key(void)
|
|||
* In order to make the compositor robust against clients that change
|
||||
* the size of the underlying file or lie about its size, you should
|
||||
* protect access to the buffer by calling this function before
|
||||
* reading from the memory and call wl_shm_buffer_end_access
|
||||
* reading from the memory and call wl_shm_buffer_end_access()
|
||||
* afterwards. This will install a signal handler for SIGBUS which
|
||||
* will prevent the compositor from crashing.
|
||||
*
|
||||
|
|
@ -614,15 +711,15 @@ init_sigbus_data_key(void)
|
|||
*
|
||||
* If a SIGBUS signal is received for an address within the range of
|
||||
* the SHM pool of the given buffer then the client will be sent an
|
||||
* error event when wl_shm_buffer_end_access is called. If the signal
|
||||
* error event when wl_shm_buffer_end_access() is called. If the signal
|
||||
* is for an address outside that range then the signal handler will
|
||||
* reraise the signal which would will likely cause the compositor to
|
||||
* terminate.
|
||||
*
|
||||
* It is safe to nest calls to these functions as long as the nested
|
||||
* calls are all accessing the same buffer. The number of calls to
|
||||
* wl_shm_buffer_end_access must match the number of calls to
|
||||
* wl_shm_buffer_begin_access. These functions are thread-safe and it
|
||||
* calls are all accessing the same pool. The number of calls to
|
||||
* wl_shm_buffer_end_access() must match the number of calls to
|
||||
* wl_shm_buffer_begin_access(). These functions are thread-safe and it
|
||||
* is allowed to simultaneously access different buffers or the same
|
||||
* buffer from multiple threads.
|
||||
*
|
||||
|
|
@ -648,18 +745,19 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
|
|||
pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data);
|
||||
}
|
||||
|
||||
assert(sigbus_data->current_pool == NULL ||
|
||||
sigbus_data->current_pool == pool);
|
||||
if (!(sigbus_data->current_pool == NULL ||
|
||||
sigbus_data->current_pool == pool))
|
||||
wl_abort("Incorrect pool passed for current thread\n");
|
||||
|
||||
sigbus_data->current_pool = pool;
|
||||
sigbus_data->access_count++;
|
||||
}
|
||||
|
||||
/** Ends the access to a buffer started by wl_shm_buffer_begin_access
|
||||
/** Ends the access to a buffer started by wl_shm_buffer_begin_access()
|
||||
*
|
||||
* \param buffer The SHM buffer
|
||||
*
|
||||
* This should be called after wl_shm_buffer_begin_access once the
|
||||
* This should be called after wl_shm_buffer_begin_access() once the
|
||||
* buffer is no longer being accessed. If a SIGBUS signal was
|
||||
* generated in-between these two calls then the resource for the
|
||||
* given buffer will be sent an error.
|
||||
|
|
@ -676,13 +774,22 @@ wl_shm_buffer_end_access(struct wl_shm_buffer *buffer)
|
|||
return;
|
||||
|
||||
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->fallback_mapping_used) {
|
||||
wl_resource_post_error(buffer->resource,
|
||||
WL_SHM_ERROR_INVALID_FD,
|
||||
"error accessing SHM buffer");
|
||||
if (buffer->resource) {
|
||||
wl_resource_post_error(buffer->resource,
|
||||
WL_SHM_ERROR_INVALID_FD,
|
||||
"error accessing SHM buffer");
|
||||
} else if (buffer->client) {
|
||||
wl_client_post_implementation_error(buffer->client,
|
||||
"Error accessing SHM buffer of a "
|
||||
"wl_buffer resource which has "
|
||||
"already been destroyed");
|
||||
}
|
||||
sigbus_data->fallback_mapping_used = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -174,9 +174,23 @@ union map_entry {
|
|||
void *data;
|
||||
};
|
||||
|
||||
#define map_entry_is_free(entry) ((entry).next & 0x1)
|
||||
#define map_entry_get_data(entry) ((void *)((entry).next & ~(uintptr_t)0x3))
|
||||
#define map_entry_get_flags(entry) (((entry).next >> 1) & 0x1)
|
||||
static inline bool
|
||||
map_entry_is_free(union map_entry entry)
|
||||
{
|
||||
return entry.next & 0x1;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
map_entry_get_data(union map_entry entry)
|
||||
{
|
||||
return (void *)(entry.next & ~(uintptr_t)0x3);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
map_entry_get_flags(union map_entry entry)
|
||||
{
|
||||
return (entry.next >> 1) & 0x1;
|
||||
}
|
||||
|
||||
void
|
||||
wl_map_init(struct wl_map *map, uint32_t side)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/** Deprecated attribute */
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || (defined(__cplusplus) && __cplusplus >= 201402L)
|
||||
#define WL_DEPRECATED [[deprecated]]
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define WL_DEPRECATED __attribute__ ((deprecated))
|
||||
#else
|
||||
#define WL_DEPRECATED
|
||||
|
|
@ -68,6 +70,12 @@ extern "C" {
|
|||
#define WL_PRINTF(x, y)
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
|
||||
#define WL_TYPEOF(expr) typeof(expr)
|
||||
#else
|
||||
#define WL_TYPEOF(expr) __typeof__(expr)
|
||||
#endif
|
||||
|
||||
/** \class wl_object
|
||||
*
|
||||
* \brief A protocol object.
|
||||
|
|
@ -82,6 +90,14 @@ extern "C" {
|
|||
*/
|
||||
struct wl_object;
|
||||
|
||||
/**
|
||||
* The maximum size of a protocol message.
|
||||
*
|
||||
* If a message size exceeds this value, the connection will be dropped.
|
||||
* Servers will send an invalid_method error before disconnecting.
|
||||
*/
|
||||
#define WL_MAX_MESSAGE_SIZE 4096
|
||||
|
||||
/**
|
||||
* Protocol message signature
|
||||
*
|
||||
|
|
@ -406,8 +422,8 @@ wl_list_insert_list(struct wl_list *list, struct wl_list *other);
|
|||
* \return The container for the specified pointer
|
||||
*/
|
||||
#define wl_container_of(ptr, sample, member) \
|
||||
(__typeof__(sample))((char *)(ptr) - \
|
||||
offsetof(__typeof__(*sample), member))
|
||||
(WL_TYPEOF(sample))((char *)(ptr) - \
|
||||
offsetof(WL_TYPEOF(*sample), member))
|
||||
|
||||
/**
|
||||
* Iterates over a list.
|
||||
|
|
@ -590,6 +606,7 @@ wl_array_copy(struct wl_array *array, struct wl_array *source);
|
|||
*/
|
||||
#define wl_array_for_each(pos, array) \
|
||||
for (pos = (array)->data; \
|
||||
(array)->size != 0 && \
|
||||
(const char *) pos < ((const char *) (array)->data + (array)->size); \
|
||||
(pos)++)
|
||||
|
||||
|
|
@ -613,14 +630,7 @@ typedef int32_t wl_fixed_t;
|
|||
static inline double
|
||||
wl_fixed_to_double(wl_fixed_t f)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
int64_t i;
|
||||
} u;
|
||||
|
||||
u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f;
|
||||
|
||||
return u.d - (3LL << 43);
|
||||
return f / 256.0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -633,14 +643,7 @@ wl_fixed_to_double(wl_fixed_t f)
|
|||
static inline wl_fixed_t
|
||||
wl_fixed_from_double(double d)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
int64_t i;
|
||||
} u;
|
||||
|
||||
u.d = d + (3LL << (51 - 8));
|
||||
|
||||
return (wl_fixed_t)u.i;
|
||||
return (wl_fixed_t) (round(d * 256.0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -80,12 +80,21 @@ client_late_destroy_notify(struct wl_listener *l, void *data)
|
|||
listener->late_done = true;
|
||||
}
|
||||
|
||||
static void
|
||||
client_user_data_destroy(void *data)
|
||||
{
|
||||
bool *user_data_destroyed = data;
|
||||
|
||||
*user_data_destroyed = true;
|
||||
}
|
||||
|
||||
TEST(client_destroy_listener)
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct wl_client *client;
|
||||
struct wl_resource *resource;
|
||||
struct client_destroy_listener a, b;
|
||||
bool user_data_destroyed = false;
|
||||
int s[2];
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
|
|
@ -94,6 +103,9 @@ TEST(client_destroy_listener)
|
|||
client = wl_client_create(display, s[0]);
|
||||
assert(client);
|
||||
|
||||
wl_client_set_user_data(client, &user_data_destroyed, client_user_data_destroy);
|
||||
assert(wl_client_get_user_data(client) == &user_data_destroyed);
|
||||
|
||||
resource = wl_resource_create(client, &wl_callback_interface, 1, 0);
|
||||
assert(resource);
|
||||
|
||||
|
|
@ -128,6 +140,8 @@ TEST(client_destroy_listener)
|
|||
wl_list_remove(&a.resource_listener.link);
|
||||
wl_list_remove(&a.late_listener.link);
|
||||
|
||||
assert(!user_data_destroyed);
|
||||
|
||||
wl_client_destroy(client);
|
||||
|
||||
assert(!a.done);
|
||||
|
|
@ -136,6 +150,7 @@ TEST(client_destroy_listener)
|
|||
assert(b.done);
|
||||
assert(b.resource_done);
|
||||
assert(b.late_done);
|
||||
assert(user_data_destroyed);
|
||||
|
||||
close(s[0]);
|
||||
close(s[1]);
|
||||
|
|
@ -143,3 +158,50 @@ TEST(client_destroy_listener)
|
|||
wl_display_destroy(display);
|
||||
}
|
||||
|
||||
static void
|
||||
client_destroy_remove_link_notify(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct wl_client *client = data;
|
||||
struct client_destroy_listener *listener =
|
||||
wl_container_of(l, listener, listener);
|
||||
|
||||
/* The client destruction signal should not be emitted more than once. */
|
||||
assert(!listener->done);
|
||||
listener->done = true;
|
||||
|
||||
/* The client should have been removed from the display's list. */
|
||||
assert(wl_list_empty(wl_client_get_link(client)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests that wl_client_destroy() will remove the client from the display's
|
||||
* client list to prevent client access during destruction.
|
||||
*/
|
||||
TEST(client_destroy_removes_link)
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct wl_client *client;
|
||||
struct client_destroy_listener destroy_listener;
|
||||
int s[2];
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
assert(client);
|
||||
|
||||
destroy_listener.listener.notify = client_destroy_remove_link_notify;
|
||||
destroy_listener.done = false;
|
||||
wl_client_add_destroy_listener(client, &destroy_listener.listener);
|
||||
|
||||
assert(wl_client_get_destroy_listener(client,
|
||||
client_destroy_remove_link_notify) == &destroy_listener.listener);
|
||||
|
||||
wl_client_destroy(client);
|
||||
assert(destroy_listener.done);
|
||||
|
||||
close(s[0]);
|
||||
close(s[1]);
|
||||
|
||||
wl_display_destroy(display);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ setup(int *s)
|
|||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
|
||||
connection = wl_connection_create(s[0]);
|
||||
connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(connection);
|
||||
|
||||
return connection;
|
||||
|
|
@ -183,9 +183,11 @@ setup_marshal_data(struct marshal_data *data)
|
|||
{
|
||||
assert(socketpair(AF_UNIX,
|
||||
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
||||
data->read_connection = wl_connection_create(data->s[0]);
|
||||
data->read_connection = wl_connection_create(data->s[0],
|
||||
WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->read_connection);
|
||||
data->write_connection = wl_connection_create(data->s[1]);
|
||||
data->write_connection = wl_connection_create(data->s[1],
|
||||
WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->write_connection);
|
||||
}
|
||||
|
||||
|
|
@ -277,6 +279,25 @@ expected_fail_marshal(int expected_error, const char *format, ...)
|
|||
assert(errno == expected_error);
|
||||
}
|
||||
|
||||
static void
|
||||
marshal_send(struct marshal_data *data, const char *format, ...)
|
||||
{
|
||||
struct wl_closure *closure;
|
||||
static const uint32_t opcode = 4444;
|
||||
static struct wl_object sender = { NULL, NULL, 1234 };
|
||||
struct wl_message message = { "test", format, NULL };
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
|
||||
va_end(ap);
|
||||
|
||||
assert(closure);
|
||||
assert(wl_closure_send(closure, data->write_connection) == 0);
|
||||
|
||||
wl_closure_destroy(closure);
|
||||
}
|
||||
|
||||
static void
|
||||
expected_fail_marshal_send(struct marshal_data *data, int expected_error,
|
||||
const char *format, ...)
|
||||
|
|
@ -644,6 +665,46 @@ TEST(connection_marshal_too_big)
|
|||
free(big_string);
|
||||
}
|
||||
|
||||
TEST(connection_marshal_big_enough)
|
||||
{
|
||||
struct marshal_data data;
|
||||
char *big_string = malloc(5000);
|
||||
|
||||
assert(big_string);
|
||||
|
||||
memset(big_string, ' ', 4999);
|
||||
big_string[4999] = '\0';
|
||||
|
||||
setup_marshal_data(&data);
|
||||
wl_connection_set_max_buffer_size(data.write_connection, 5120);
|
||||
|
||||
marshal_send(&data, "s", big_string);
|
||||
|
||||
release_marshal_data(&data);
|
||||
free(big_string);
|
||||
}
|
||||
|
||||
TEST(connection_marshal_unbounded_boundary_size)
|
||||
{
|
||||
/* A string of length 8178 requires a buffer size of exactly 2^13. */
|
||||
struct marshal_data data;
|
||||
char *big_string = malloc(8178);
|
||||
assert(big_string);
|
||||
|
||||
memset(big_string, ' ', 8177);
|
||||
big_string[8177] = '\0';
|
||||
|
||||
setup_marshal_data(&data);
|
||||
|
||||
/* Set the max size to 0 (unbounded). */
|
||||
wl_connection_set_max_buffer_size(data.write_connection, 0);
|
||||
|
||||
marshal_send(&data, "s", big_string);
|
||||
|
||||
release_marshal_data(&data);
|
||||
free(big_string);
|
||||
}
|
||||
|
||||
static void
|
||||
marshal_helper(const char *format, void *handler, ...)
|
||||
{
|
||||
|
|
|
|||
3
tests/data/README.md
Normal file
3
tests/data/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
To re-generate the test data, run:
|
||||
|
||||
ninja -C build/ gen-scanner-test
|
||||
83
tests/data/empty-client.h
Normal file
83
tests/data/empty-client.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* SCANNER TEST */
|
||||
|
||||
#ifndef EMPTY_CLIENT_PROTOCOL_H
|
||||
#define EMPTY_CLIENT_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "wayland-client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page page_empty The empty protocol
|
||||
* @section page_ifaces_empty Interfaces
|
||||
* - @subpage page_iface_empty -
|
||||
*/
|
||||
struct empty;
|
||||
|
||||
#ifndef EMPTY_INTERFACE
|
||||
#define EMPTY_INTERFACE
|
||||
/**
|
||||
* @page page_iface_empty empty
|
||||
* @section page_iface_empty_api API
|
||||
* See @ref iface_empty.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_empty The empty interface
|
||||
*/
|
||||
extern const struct wl_interface empty_interface;
|
||||
#endif
|
||||
|
||||
#define EMPTY_EMPTY 0
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup iface_empty
|
||||
*/
|
||||
#define EMPTY_EMPTY_SINCE_VERSION 1
|
||||
|
||||
/** @ingroup iface_empty */
|
||||
static inline void
|
||||
empty_set_user_data(struct empty *empty, void *user_data)
|
||||
{
|
||||
wl_proxy_set_user_data((struct wl_proxy *) empty, user_data);
|
||||
}
|
||||
|
||||
/** @ingroup iface_empty */
|
||||
static inline void *
|
||||
empty_get_user_data(struct empty *empty)
|
||||
{
|
||||
return wl_proxy_get_user_data((struct wl_proxy *) empty);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
empty_get_version(struct empty *empty)
|
||||
{
|
||||
return wl_proxy_get_version((struct wl_proxy *) empty);
|
||||
}
|
||||
|
||||
/** @ingroup iface_empty */
|
||||
static inline void
|
||||
empty_destroy(struct empty *empty)
|
||||
{
|
||||
wl_proxy_destroy((struct wl_proxy *) empty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_empty
|
||||
*/
|
||||
static inline void
|
||||
empty_empty(struct empty *empty)
|
||||
{
|
||||
wl_proxy_marshal_flags((struct wl_proxy *) empty,
|
||||
EMPTY_EMPTY, NULL, wl_proxy_get_version((struct wl_proxy *) empty), 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
21
tests/data/empty-code.c
Normal file
21
tests/data/empty-code.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* SCANNER TEST */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
||||
|
||||
static const struct wl_interface *empty_types[] = {
|
||||
};
|
||||
|
||||
static const struct wl_message empty_requests[] = {
|
||||
{ "empty", "", empty_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface empty_interface = {
|
||||
"empty", 1,
|
||||
1, empty_requests,
|
||||
0, NULL,
|
||||
};
|
||||
|
||||
58
tests/data/empty-server.h
Normal file
58
tests/data/empty-server.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* SCANNER TEST */
|
||||
|
||||
#ifndef EMPTY_SERVER_PROTOCOL_H
|
||||
#define EMPTY_SERVER_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "wayland-server.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct wl_client;
|
||||
struct wl_resource;
|
||||
|
||||
/**
|
||||
* @page page_empty The empty protocol
|
||||
* @section page_ifaces_empty Interfaces
|
||||
* - @subpage page_iface_empty -
|
||||
*/
|
||||
struct empty;
|
||||
|
||||
#ifndef EMPTY_INTERFACE
|
||||
#define EMPTY_INTERFACE
|
||||
/**
|
||||
* @page page_iface_empty empty
|
||||
* @section page_iface_empty_api API
|
||||
* See @ref iface_empty.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_empty The empty interface
|
||||
*/
|
||||
extern const struct wl_interface empty_interface;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup iface_empty
|
||||
* @struct empty_interface
|
||||
*/
|
||||
struct empty_interface {
|
||||
/**
|
||||
*/
|
||||
void (*empty)(struct wl_client *client,
|
||||
struct wl_resource *resource);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup iface_empty
|
||||
*/
|
||||
#define EMPTY_EMPTY_SINCE_VERSION 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
7
tests/data/empty.xml
Normal file
7
tests/data/empty.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="empty">
|
||||
<interface name="empty" version="1">
|
||||
<request name="empty">
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
|
|
|||
836
tests/data/example-enum.h
Normal file
836
tests/data/example-enum.h
Normal file
|
|
@ -0,0 +1,836 @@
|
|||
/* SCANNER TEST */
|
||||
|
||||
#ifndef WAYLAND_ENUM_PROTOCOL_H
|
||||
#define WAYLAND_ENUM_PROTOCOL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef WL_DISPLAY_ERROR_ENUM
|
||||
#define WL_DISPLAY_ERROR_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_display
|
||||
* global error values
|
||||
*
|
||||
* These errors are global and can be emitted in response to any
|
||||
* server request.
|
||||
*/
|
||||
enum wl_display_error {
|
||||
/**
|
||||
* server couldn't find object
|
||||
*/
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT = 0,
|
||||
/**
|
||||
* method doesn't exist on the specified interface
|
||||
*/
|
||||
WL_DISPLAY_ERROR_INVALID_METHOD = 1,
|
||||
/**
|
||||
* server is out of memory
|
||||
*/
|
||||
WL_DISPLAY_ERROR_NO_MEMORY = 2,
|
||||
};
|
||||
#endif /* WL_DISPLAY_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SHM_ERROR_ENUM
|
||||
#define WL_SHM_ERROR_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_shm
|
||||
* wl_shm error values
|
||||
*
|
||||
* These errors can be emitted in response to wl_shm requests.
|
||||
*/
|
||||
enum wl_shm_error {
|
||||
/**
|
||||
* buffer format is not known
|
||||
*/
|
||||
WL_SHM_ERROR_INVALID_FORMAT = 0,
|
||||
/**
|
||||
* invalid size or stride during pool or buffer creation
|
||||
*/
|
||||
WL_SHM_ERROR_INVALID_STRIDE = 1,
|
||||
/**
|
||||
* mmapping the file descriptor failed
|
||||
*/
|
||||
WL_SHM_ERROR_INVALID_FD = 2,
|
||||
};
|
||||
#endif /* WL_SHM_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SHM_FORMAT_ENUM
|
||||
#define WL_SHM_FORMAT_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_shm
|
||||
* pixel formats
|
||||
*
|
||||
* This describes the memory layout of an individual pixel.
|
||||
*
|
||||
* All renderers should support argb8888 and xrgb8888 but any other
|
||||
* formats are optional and may not be supported by the particular
|
||||
* renderer in use.
|
||||
*
|
||||
* The drm format codes match the macros defined in drm_fourcc.h.
|
||||
* The formats actually supported by the compositor will be
|
||||
* reported by the format event.
|
||||
*/
|
||||
enum wl_shm_format {
|
||||
/**
|
||||
* 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ARGB8888 = 0,
|
||||
/**
|
||||
* 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XRGB8888 = 1,
|
||||
/**
|
||||
* 8-bit color index format, [7:0] C
|
||||
*/
|
||||
WL_SHM_FORMAT_C8 = 0x20203843,
|
||||
/**
|
||||
* 8-bit RGB format, [7:0] R:G:B 3:3:2
|
||||
*/
|
||||
WL_SHM_FORMAT_RGB332 = 0x38424752,
|
||||
/**
|
||||
* 8-bit BGR format, [7:0] B:G:R 2:3:3
|
||||
*/
|
||||
WL_SHM_FORMAT_BGR233 = 0x38524742,
|
||||
/**
|
||||
* 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XRGB4444 = 0x32315258,
|
||||
/**
|
||||
* 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XBGR4444 = 0x32314258,
|
||||
/**
|
||||
* 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBX4444 = 0x32315852,
|
||||
/**
|
||||
* 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRX4444 = 0x32315842,
|
||||
/**
|
||||
* 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ARGB4444 = 0x32315241,
|
||||
/**
|
||||
* 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ABGR4444 = 0x32314241,
|
||||
/**
|
||||
* 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBA4444 = 0x32314152,
|
||||
/**
|
||||
* 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRA4444 = 0x32314142,
|
||||
/**
|
||||
* 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XRGB1555 = 0x35315258,
|
||||
/**
|
||||
* 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XBGR1555 = 0x35314258,
|
||||
/**
|
||||
* 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBX5551 = 0x35315852,
|
||||
/**
|
||||
* 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRX5551 = 0x35315842,
|
||||
/**
|
||||
* 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ARGB1555 = 0x35315241,
|
||||
/**
|
||||
* 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ABGR1555 = 0x35314241,
|
||||
/**
|
||||
* 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBA5551 = 0x35314152,
|
||||
/**
|
||||
* 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRA5551 = 0x35314142,
|
||||
/**
|
||||
* 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGB565 = 0x36314752,
|
||||
/**
|
||||
* 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGR565 = 0x36314742,
|
||||
/**
|
||||
* 24-bit RGB format, [23:0] R:G:B little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGB888 = 0x34324752,
|
||||
/**
|
||||
* 24-bit BGR format, [23:0] B:G:R little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGR888 = 0x34324742,
|
||||
/**
|
||||
* 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XBGR8888 = 0x34324258,
|
||||
/**
|
||||
* 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBX8888 = 0x34325852,
|
||||
/**
|
||||
* 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRX8888 = 0x34325842,
|
||||
/**
|
||||
* 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ABGR8888 = 0x34324241,
|
||||
/**
|
||||
* 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBA8888 = 0x34324152,
|
||||
/**
|
||||
* 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRA8888 = 0x34324142,
|
||||
/**
|
||||
* 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XRGB2101010 = 0x30335258,
|
||||
/**
|
||||
* 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_XBGR2101010 = 0x30334258,
|
||||
/**
|
||||
* 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBX1010102 = 0x30335852,
|
||||
/**
|
||||
* 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRX1010102 = 0x30335842,
|
||||
/**
|
||||
* 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ARGB2101010 = 0x30335241,
|
||||
/**
|
||||
* 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ABGR2101010 = 0x30334241,
|
||||
/**
|
||||
* 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGBA1010102 = 0x30334152,
|
||||
/**
|
||||
* 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGRA1010102 = 0x30334142,
|
||||
/**
|
||||
* packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_YUYV = 0x56595559,
|
||||
/**
|
||||
* packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_YVYU = 0x55595659,
|
||||
/**
|
||||
* packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_UYVY = 0x59565955,
|
||||
/**
|
||||
* packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_VYUY = 0x59555956,
|
||||
/**
|
||||
* packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_AYUV = 0x56555941,
|
||||
/**
|
||||
* 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane
|
||||
*/
|
||||
WL_SHM_FORMAT_NV12 = 0x3231564e,
|
||||
/**
|
||||
* 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane
|
||||
*/
|
||||
WL_SHM_FORMAT_NV21 = 0x3132564e,
|
||||
/**
|
||||
* 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane
|
||||
*/
|
||||
WL_SHM_FORMAT_NV16 = 0x3631564e,
|
||||
/**
|
||||
* 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane
|
||||
*/
|
||||
WL_SHM_FORMAT_NV61 = 0x3136564e,
|
||||
/**
|
||||
* 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YUV410 = 0x39565559,
|
||||
/**
|
||||
* 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YVU410 = 0x39555659,
|
||||
/**
|
||||
* 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YUV411 = 0x31315559,
|
||||
/**
|
||||
* 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YVU411 = 0x31315659,
|
||||
/**
|
||||
* 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YUV420 = 0x32315559,
|
||||
/**
|
||||
* 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YVU420 = 0x32315659,
|
||||
/**
|
||||
* 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YUV422 = 0x36315559,
|
||||
/**
|
||||
* 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YVU422 = 0x36315659,
|
||||
/**
|
||||
* 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YUV444 = 0x34325559,
|
||||
/**
|
||||
* 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes
|
||||
*/
|
||||
WL_SHM_FORMAT_YVU444 = 0x34325659,
|
||||
};
|
||||
#endif /* WL_SHM_FORMAT_ENUM */
|
||||
|
||||
#ifndef WL_DATA_OFFER_ERROR_ENUM
|
||||
#define WL_DATA_OFFER_ERROR_ENUM
|
||||
enum wl_data_offer_error {
|
||||
/**
|
||||
* finish request was called untimely
|
||||
*/
|
||||
WL_DATA_OFFER_ERROR_INVALID_FINISH = 0,
|
||||
/**
|
||||
* action mask contains invalid values
|
||||
*/
|
||||
WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1,
|
||||
/**
|
||||
* action argument has an invalid value
|
||||
*/
|
||||
WL_DATA_OFFER_ERROR_INVALID_ACTION = 2,
|
||||
/**
|
||||
* offer doesn't accept this request
|
||||
*/
|
||||
WL_DATA_OFFER_ERROR_INVALID_OFFER = 3,
|
||||
};
|
||||
#endif /* WL_DATA_OFFER_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_DATA_SOURCE_ERROR_ENUM
|
||||
#define WL_DATA_SOURCE_ERROR_ENUM
|
||||
enum wl_data_source_error {
|
||||
/**
|
||||
* action mask contains invalid values
|
||||
*/
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0,
|
||||
/**
|
||||
* source doesn't accept this request
|
||||
*/
|
||||
WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1,
|
||||
};
|
||||
#endif /* WL_DATA_SOURCE_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_DATA_DEVICE_ERROR_ENUM
|
||||
#define WL_DATA_DEVICE_ERROR_ENUM
|
||||
enum wl_data_device_error {
|
||||
/**
|
||||
* given wl_surface has another role
|
||||
*/
|
||||
WL_DATA_DEVICE_ERROR_ROLE = 0,
|
||||
};
|
||||
#endif /* WL_DATA_DEVICE_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
|
||||
#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_data_device_manager
|
||||
* drag and drop actions
|
||||
*
|
||||
* This is a bitmask of the available/preferred actions in a
|
||||
* drag-and-drop operation.
|
||||
*
|
||||
* In the compositor, the selected action is a result of matching the
|
||||
* actions offered by the source and destination sides. "action" events
|
||||
* with a "none" action will be sent to both source and destination if
|
||||
* there is no match. All further checks will effectively happen on
|
||||
* (source actions ∩ destination actions).
|
||||
*
|
||||
* In addition, compositors may also pick different actions in
|
||||
* reaction to key modifiers being pressed. One common design that
|
||||
* is used in major toolkits (and the behavior recommended for
|
||||
* compositors) is:
|
||||
*
|
||||
* - If no modifiers are pressed, the first match (in bit order)
|
||||
* will be used.
|
||||
* - Pressing Shift selects "move", if enabled in the mask.
|
||||
* - Pressing Control selects "copy", if enabled in the mask.
|
||||
*
|
||||
* Behavior beyond that is considered implementation-dependent.
|
||||
* Compositors may for example bind other modifiers (like Alt/Meta)
|
||||
* or drags initiated with other buttons than BTN_LEFT to specific
|
||||
* actions (e.g. "ask").
|
||||
*/
|
||||
enum wl_data_device_manager_dnd_action {
|
||||
/**
|
||||
* no action
|
||||
*/
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0,
|
||||
/**
|
||||
* copy action
|
||||
*/
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1,
|
||||
/**
|
||||
* move action
|
||||
*/
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2,
|
||||
/**
|
||||
* ask action
|
||||
*/
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4,
|
||||
};
|
||||
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_ERROR_ENUM
|
||||
#define WL_SHELL_ERROR_ENUM
|
||||
enum wl_shell_error {
|
||||
/**
|
||||
* given wl_surface has another role
|
||||
*/
|
||||
WL_SHELL_ERROR_ROLE = 0,
|
||||
};
|
||||
#endif /* WL_SHELL_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_RESIZE_ENUM
|
||||
#define WL_SHELL_SURFACE_RESIZE_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_shell_surface
|
||||
* edge values for resizing
|
||||
*
|
||||
* These values are used to indicate which edge of a surface
|
||||
* is being dragged in a resize operation. The server may
|
||||
* use this information to adapt its behavior, e.g. choose
|
||||
* an appropriate cursor image.
|
||||
*/
|
||||
enum wl_shell_surface_resize {
|
||||
/**
|
||||
* no edge
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_NONE = 0,
|
||||
/**
|
||||
* top edge
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_TOP = 1,
|
||||
/**
|
||||
* bottom edge
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_BOTTOM = 2,
|
||||
/**
|
||||
* left edge
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_LEFT = 4,
|
||||
/**
|
||||
* top and left edges
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5,
|
||||
/**
|
||||
* bottom and left edges
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6,
|
||||
/**
|
||||
* right edge
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_RIGHT = 8,
|
||||
/**
|
||||
* top and right edges
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9,
|
||||
/**
|
||||
* bottom and right edges
|
||||
*/
|
||||
WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10,
|
||||
};
|
||||
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
|
||||
#define WL_SHELL_SURFACE_TRANSIENT_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_shell_surface
|
||||
* details of transient behaviour
|
||||
*
|
||||
* These flags specify details of the expected behaviour
|
||||
* of transient surfaces. Used in the set_transient request.
|
||||
*/
|
||||
enum wl_shell_surface_transient {
|
||||
/**
|
||||
* do not set keyboard focus
|
||||
*/
|
||||
WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1,
|
||||
};
|
||||
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
||||
#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_shell_surface
|
||||
* different method to set the surface fullscreen
|
||||
*
|
||||
* Hints to indicate to the compositor how to deal with a conflict
|
||||
* between the dimensions of the surface and the dimensions of the
|
||||
* output. The compositor is free to ignore this parameter.
|
||||
*/
|
||||
enum wl_shell_surface_fullscreen_method {
|
||||
/**
|
||||
* no preference, apply default policy
|
||||
*/
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0,
|
||||
/**
|
||||
* scale, preserve the surface's aspect ratio and center on output
|
||||
*/
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1,
|
||||
/**
|
||||
* switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch
|
||||
*/
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2,
|
||||
/**
|
||||
* no upscaling, center on output and add black borders to compensate size mismatch
|
||||
*/
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3,
|
||||
};
|
||||
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
|
||||
|
||||
#ifndef WL_SURFACE_ERROR_ENUM
|
||||
#define WL_SURFACE_ERROR_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_surface
|
||||
* wl_surface error values
|
||||
*
|
||||
* These errors can be emitted in response to wl_surface requests.
|
||||
*/
|
||||
enum wl_surface_error {
|
||||
/**
|
||||
* buffer scale value is invalid
|
||||
*/
|
||||
WL_SURFACE_ERROR_INVALID_SCALE = 0,
|
||||
/**
|
||||
* buffer transform value is invalid
|
||||
*/
|
||||
WL_SURFACE_ERROR_INVALID_TRANSFORM = 1,
|
||||
};
|
||||
#endif /* WL_SURFACE_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SEAT_CAPABILITY_ENUM
|
||||
#define WL_SEAT_CAPABILITY_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_seat
|
||||
* seat capability bitmask
|
||||
*
|
||||
* This is a bitmask of capabilities this seat has; if a member is
|
||||
* set, then it is present on the seat.
|
||||
*/
|
||||
enum wl_seat_capability {
|
||||
/**
|
||||
* the seat has pointer devices
|
||||
*/
|
||||
WL_SEAT_CAPABILITY_POINTER = 1,
|
||||
/**
|
||||
* the seat has one or more keyboards
|
||||
*/
|
||||
WL_SEAT_CAPABILITY_KEYBOARD = 2,
|
||||
/**
|
||||
* the seat has touch devices
|
||||
*/
|
||||
WL_SEAT_CAPABILITY_TOUCH = 4,
|
||||
};
|
||||
#endif /* WL_SEAT_CAPABILITY_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_ERROR_ENUM
|
||||
#define WL_POINTER_ERROR_ENUM
|
||||
enum wl_pointer_error {
|
||||
/**
|
||||
* given wl_surface has another role
|
||||
*/
|
||||
WL_POINTER_ERROR_ROLE = 0,
|
||||
};
|
||||
#endif /* WL_POINTER_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_BUTTON_STATE_ENUM
|
||||
#define WL_POINTER_BUTTON_STATE_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* physical button state
|
||||
*
|
||||
* Describes the physical state of a button that produced the button
|
||||
* event.
|
||||
*/
|
||||
enum wl_pointer_button_state {
|
||||
/**
|
||||
* the button is not pressed
|
||||
*/
|
||||
WL_POINTER_BUTTON_STATE_RELEASED = 0,
|
||||
/**
|
||||
* the button is pressed
|
||||
*/
|
||||
WL_POINTER_BUTTON_STATE_PRESSED = 1,
|
||||
};
|
||||
#endif /* WL_POINTER_BUTTON_STATE_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_AXIS_ENUM
|
||||
#define WL_POINTER_AXIS_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* axis types
|
||||
*
|
||||
* Describes the axis types of scroll events.
|
||||
*/
|
||||
enum wl_pointer_axis {
|
||||
/**
|
||||
* vertical axis
|
||||
*/
|
||||
WL_POINTER_AXIS_VERTICAL_SCROLL = 0,
|
||||
/**
|
||||
* horizontal axis
|
||||
*/
|
||||
WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1,
|
||||
};
|
||||
#endif /* WL_POINTER_AXIS_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_AXIS_SOURCE_ENUM
|
||||
#define WL_POINTER_AXIS_SOURCE_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* axis source types
|
||||
*
|
||||
* Describes the source types for axis events. This indicates to the
|
||||
* client how an axis event was physically generated; a client may
|
||||
* adjust the user interface accordingly. For example, scroll events
|
||||
* from a "finger" source may be in a smooth coordinate space with
|
||||
* kinetic scrolling whereas a "wheel" source may be in discrete steps
|
||||
* of a number of lines.
|
||||
*/
|
||||
enum wl_pointer_axis_source {
|
||||
/**
|
||||
* a physical wheel rotation
|
||||
*/
|
||||
WL_POINTER_AXIS_SOURCE_WHEEL = 0,
|
||||
/**
|
||||
* finger on a touch surface
|
||||
*/
|
||||
WL_POINTER_AXIS_SOURCE_FINGER = 1,
|
||||
/**
|
||||
* continuous coordinate space
|
||||
*
|
||||
* A device generating events in a continuous coordinate space,
|
||||
* but using something other than a finger. One example for this
|
||||
* source is button-based scrolling where the vertical motion of a
|
||||
* device is converted to scroll events while a button is held
|
||||
* down.
|
||||
*/
|
||||
WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2,
|
||||
/**
|
||||
* a physical wheel tilt
|
||||
*
|
||||
* Indicates that the actual device is a wheel but the scroll
|
||||
* event is not caused by a rotation but a (usually sideways) tilt
|
||||
* of the wheel.
|
||||
* @since 6
|
||||
*/
|
||||
WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
*/
|
||||
#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
|
||||
#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
|
||||
|
||||
#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM
|
||||
#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_keyboard
|
||||
* keyboard mapping format
|
||||
*
|
||||
* This specifies the format of the keymap provided to the
|
||||
* client with the wl_keyboard.keymap event.
|
||||
*/
|
||||
enum wl_keyboard_keymap_format {
|
||||
/**
|
||||
* no keymap; client must understand how to interpret the raw keycode
|
||||
*/
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0,
|
||||
/**
|
||||
* libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode
|
||||
*/
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1,
|
||||
};
|
||||
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
|
||||
|
||||
#ifndef WL_KEYBOARD_KEY_STATE_ENUM
|
||||
#define WL_KEYBOARD_KEY_STATE_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_keyboard
|
||||
* physical key state
|
||||
*
|
||||
* Describes the physical state of a key that produced the key event.
|
||||
*/
|
||||
enum wl_keyboard_key_state {
|
||||
/**
|
||||
* key is not pressed
|
||||
*/
|
||||
WL_KEYBOARD_KEY_STATE_RELEASED = 0,
|
||||
/**
|
||||
* key is pressed
|
||||
*/
|
||||
WL_KEYBOARD_KEY_STATE_PRESSED = 1,
|
||||
};
|
||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
|
||||
|
||||
#ifndef WL_OUTPUT_SUBPIXEL_ENUM
|
||||
#define WL_OUTPUT_SUBPIXEL_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_output
|
||||
* subpixel geometry information
|
||||
*
|
||||
* This enumeration describes how the physical
|
||||
* pixels on an output are laid out.
|
||||
*/
|
||||
enum wl_output_subpixel {
|
||||
/**
|
||||
* unknown geometry
|
||||
*/
|
||||
WL_OUTPUT_SUBPIXEL_UNKNOWN = 0,
|
||||
/**
|
||||
* no geometry
|
||||
*/
|
||||
WL_OUTPUT_SUBPIXEL_NONE = 1,
|
||||
/**
|
||||
* horizontal RGB
|
||||
*/
|
||||
WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2,
|
||||
/**
|
||||
* horizontal BGR
|
||||
*/
|
||||
WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3,
|
||||
/**
|
||||
* vertical RGB
|
||||
*/
|
||||
WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4,
|
||||
/**
|
||||
* vertical BGR
|
||||
*/
|
||||
WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5,
|
||||
};
|
||||
#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
|
||||
|
||||
#ifndef WL_OUTPUT_TRANSFORM_ENUM
|
||||
#define WL_OUTPUT_TRANSFORM_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_output
|
||||
* transform from framebuffer to output
|
||||
*
|
||||
* This describes the transform that a compositor will apply to a
|
||||
* surface to compensate for the rotation or mirroring of an
|
||||
* output device.
|
||||
*
|
||||
* The flipped values correspond to an initial flip around a
|
||||
* vertical axis followed by rotation.
|
||||
*
|
||||
* The purpose is mainly to allow clients to render accordingly and
|
||||
* tell the compositor, so that for fullscreen surfaces, the
|
||||
* compositor will still be able to scan out directly from client
|
||||
* surfaces.
|
||||
*/
|
||||
enum wl_output_transform {
|
||||
/**
|
||||
* no transform
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_NORMAL = 0,
|
||||
/**
|
||||
* 90 degrees counter-clockwise
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_90 = 1,
|
||||
/**
|
||||
* 180 degrees counter-clockwise
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_180 = 2,
|
||||
/**
|
||||
* 270 degrees counter-clockwise
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_270 = 3,
|
||||
/**
|
||||
* 180 degree flip around a vertical axis
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED = 4,
|
||||
/**
|
||||
* flip and rotate 90 degrees counter-clockwise
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5,
|
||||
/**
|
||||
* flip and rotate 180 degrees counter-clockwise
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6,
|
||||
/**
|
||||
* flip and rotate 270 degrees counter-clockwise
|
||||
*/
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7,
|
||||
};
|
||||
#endif /* WL_OUTPUT_TRANSFORM_ENUM */
|
||||
|
||||
#ifndef WL_OUTPUT_MODE_ENUM
|
||||
#define WL_OUTPUT_MODE_ENUM
|
||||
/**
|
||||
* @ingroup iface_wl_output
|
||||
* mode information
|
||||
*
|
||||
* These flags describe properties of an output mode.
|
||||
* They are used in the flags bitfield of the mode event.
|
||||
*/
|
||||
enum wl_output_mode {
|
||||
/**
|
||||
* indicates this is the current mode
|
||||
*/
|
||||
WL_OUTPUT_MODE_CURRENT = 0x1,
|
||||
/**
|
||||
* indicates this is the preferred mode
|
||||
*/
|
||||
WL_OUTPUT_MODE_PREFERRED = 0x2,
|
||||
};
|
||||
#endif /* WL_OUTPUT_MODE_ENUM */
|
||||
|
||||
#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM
|
||||
#define WL_SUBCOMPOSITOR_ERROR_ENUM
|
||||
enum wl_subcompositor_error {
|
||||
/**
|
||||
* the to-be sub-surface is invalid
|
||||
*/
|
||||
WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0,
|
||||
};
|
||||
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SUBSURFACE_ERROR_ENUM
|
||||
#define WL_SUBSURFACE_ERROR_ENUM
|
||||
enum wl_subsurface_error {
|
||||
/**
|
||||
* wl_surface is not a sibling or the parent
|
||||
*/
|
||||
WL_SUBSURFACE_ERROR_BAD_SURFACE = 0,
|
||||
};
|
||||
#endif /* WL_SUBSURFACE_ERROR_ENUM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -903,6 +903,30 @@ enum wl_display_error {
|
|||
};
|
||||
#endif /* WL_DISPLAY_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_DISPLAY_ERROR_ENUM_IS_VALID
|
||||
#define WL_DISPLAY_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_display
|
||||
* Validate a wl_display error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_display_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_display_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_DISPLAY_ERROR_INVALID_OBJECT:
|
||||
return version >= 1;
|
||||
case WL_DISPLAY_ERROR_INVALID_METHOD:
|
||||
return version >= 1;
|
||||
case WL_DISPLAY_ERROR_NO_MEMORY:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_DISPLAY_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_display
|
||||
* @struct wl_display_interface
|
||||
|
|
@ -1176,6 +1200,30 @@ enum wl_shm_error {
|
|||
};
|
||||
#endif /* WL_SHM_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SHM_ERROR_ENUM_IS_VALID
|
||||
#define WL_SHM_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_shm
|
||||
* Validate a wl_shm error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_shm_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_shm_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_SHM_ERROR_INVALID_FORMAT:
|
||||
return version >= 1;
|
||||
case WL_SHM_ERROR_INVALID_STRIDE:
|
||||
return version >= 1;
|
||||
case WL_SHM_ERROR_INVALID_FD:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_SHM_ERROR_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_SHM_FORMAT_ENUM
|
||||
#define WL_SHM_FORMAT_ENUM
|
||||
/**
|
||||
|
|
@ -1428,6 +1476,140 @@ enum wl_shm_format {
|
|||
};
|
||||
#endif /* WL_SHM_FORMAT_ENUM */
|
||||
|
||||
#ifndef WL_SHM_FORMAT_ENUM_IS_VALID
|
||||
#define WL_SHM_FORMAT_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_shm
|
||||
* Validate a wl_shm format value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_shm_format
|
||||
*/
|
||||
static inline bool
|
||||
wl_shm_format_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_C8:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGB332:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGR233:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XRGB4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XBGR4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBX4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRX4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_ARGB4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_ABGR4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBA4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRA4444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XRGB1555:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XBGR1555:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBX5551:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRX5551:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_ARGB1555:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_ABGR1555:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBA5551:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRA5551:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGB565:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGR565:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGB888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGR888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XBGR8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBX8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRX8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_ABGR8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBA8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRA8888:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XRGB2101010:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_XBGR2101010:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBX1010102:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRX1010102:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_ARGB2101010:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_ABGR2101010:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_RGBA1010102:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_BGRA1010102:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YUYV:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YVYU:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_UYVY:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_VYUY:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_AYUV:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_NV12:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_NV21:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_NV16:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_NV61:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YUV410:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YVU410:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YUV411:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YVU411:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YUV420:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YVU420:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YUV422:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YVU422:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YUV444:
|
||||
return version >= 1;
|
||||
case WL_SHM_FORMAT_YVU444:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_SHM_FORMAT_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_shm
|
||||
* @struct wl_shm_interface
|
||||
|
|
@ -1538,6 +1720,32 @@ enum wl_data_offer_error {
|
|||
};
|
||||
#endif /* WL_DATA_OFFER_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_DATA_OFFER_ERROR_ENUM_IS_VALID
|
||||
#define WL_DATA_OFFER_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_data_offer
|
||||
* Validate a wl_data_offer error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_data_offer_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_data_offer_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_DATA_OFFER_ERROR_INVALID_FINISH:
|
||||
return version >= 1;
|
||||
case WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK:
|
||||
return version >= 1;
|
||||
case WL_DATA_OFFER_ERROR_INVALID_ACTION:
|
||||
return version >= 1;
|
||||
case WL_DATA_OFFER_ERROR_INVALID_OFFER:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_DATA_OFFER_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_data_offer
|
||||
* @struct wl_data_offer_interface
|
||||
|
|
@ -1750,6 +1958,28 @@ enum wl_data_source_error {
|
|||
};
|
||||
#endif /* WL_DATA_SOURCE_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_DATA_SOURCE_ERROR_ENUM_IS_VALID
|
||||
#define WL_DATA_SOURCE_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_data_source
|
||||
* Validate a wl_data_source error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_data_source_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_data_source_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK:
|
||||
return version >= 1;
|
||||
case WL_DATA_SOURCE_ERROR_INVALID_SOURCE:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_DATA_SOURCE_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_data_source
|
||||
* @struct wl_data_source_interface
|
||||
|
|
@ -1922,6 +2152,26 @@ enum wl_data_device_error {
|
|||
};
|
||||
#endif /* WL_DATA_DEVICE_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_DATA_DEVICE_ERROR_ENUM_IS_VALID
|
||||
#define WL_DATA_DEVICE_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_data_device
|
||||
* Validate a wl_data_device error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_data_device_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_data_device_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_DATA_DEVICE_ERROR_ROLE:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_DATA_DEVICE_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_data_device
|
||||
* @struct wl_data_device_interface
|
||||
|
|
@ -2163,6 +2413,30 @@ enum wl_data_device_manager_dnd_action {
|
|||
};
|
||||
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
|
||||
|
||||
#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID
|
||||
#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_data_device_manager
|
||||
* Validate a wl_data_device_manager dnd_action value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_data_device_manager_dnd_action
|
||||
*/
|
||||
static inline bool
|
||||
wl_data_device_manager_dnd_action_is_valid(uint32_t value, uint32_t version) {
|
||||
uint32_t valid = 0;
|
||||
if (version >= 1)
|
||||
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
||||
if (version >= 1)
|
||||
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
if (version >= 1)
|
||||
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
|
||||
if (version >= 1)
|
||||
valid |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
return (value & ~valid) == 0;
|
||||
}
|
||||
#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_data_device_manager
|
||||
* @struct wl_data_device_manager_interface
|
||||
|
|
@ -2210,6 +2484,26 @@ enum wl_shell_error {
|
|||
};
|
||||
#endif /* WL_SHELL_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_ERROR_ENUM_IS_VALID
|
||||
#define WL_SHELL_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_shell
|
||||
* Validate a wl_shell error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_shell_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_shell_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_SHELL_ERROR_ROLE:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_SHELL_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_shell
|
||||
* @struct wl_shell_interface
|
||||
|
|
@ -2289,6 +2583,40 @@ enum wl_shell_surface_resize {
|
|||
};
|
||||
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID
|
||||
#define WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_shell_surface
|
||||
* Validate a wl_shell_surface resize value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_shell_surface_resize
|
||||
*/
|
||||
static inline bool
|
||||
wl_shell_surface_resize_is_valid(uint32_t value, uint32_t version) {
|
||||
uint32_t valid = 0;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_NONE;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_TOP;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_LEFT;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_RIGHT;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
|
||||
return (value & ~valid) == 0;
|
||||
}
|
||||
#endif /* WL_SHELL_SURFACE_RESIZE_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
|
||||
#define WL_SHELL_SURFACE_TRANSIENT_ENUM
|
||||
/**
|
||||
|
|
@ -2306,6 +2634,24 @@ enum wl_shell_surface_transient {
|
|||
};
|
||||
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID
|
||||
#define WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_shell_surface
|
||||
* Validate a wl_shell_surface transient value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_shell_surface_transient
|
||||
*/
|
||||
static inline bool
|
||||
wl_shell_surface_transient_is_valid(uint32_t value, uint32_t version) {
|
||||
uint32_t valid = 0;
|
||||
if (version >= 1)
|
||||
valid |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
|
||||
return (value & ~valid) == 0;
|
||||
}
|
||||
#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
||||
#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
|
||||
/**
|
||||
|
|
@ -2336,6 +2682,32 @@ enum wl_shell_surface_fullscreen_method {
|
|||
};
|
||||
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
|
||||
|
||||
#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID
|
||||
#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_shell_surface
|
||||
* Validate a wl_shell_surface fullscreen_method value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_shell_surface_fullscreen_method
|
||||
*/
|
||||
static inline bool
|
||||
wl_shell_surface_fullscreen_method_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
|
||||
return version >= 1;
|
||||
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
|
||||
return version >= 1;
|
||||
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
|
||||
return version >= 1;
|
||||
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_shell_surface
|
||||
* @struct wl_shell_surface_interface
|
||||
|
|
@ -2668,6 +3040,28 @@ enum wl_surface_error {
|
|||
};
|
||||
#endif /* WL_SURFACE_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SURFACE_ERROR_ENUM_IS_VALID
|
||||
#define WL_SURFACE_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_surface
|
||||
* Validate a wl_surface error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_surface_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_surface_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_SURFACE_ERROR_INVALID_SCALE:
|
||||
return version >= 1;
|
||||
case WL_SURFACE_ERROR_INVALID_TRANSFORM:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_SURFACE_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_surface
|
||||
* @struct wl_surface_interface
|
||||
|
|
@ -3127,6 +3521,28 @@ enum wl_seat_capability {
|
|||
};
|
||||
#endif /* WL_SEAT_CAPABILITY_ENUM */
|
||||
|
||||
#ifndef WL_SEAT_CAPABILITY_ENUM_IS_VALID
|
||||
#define WL_SEAT_CAPABILITY_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_seat
|
||||
* Validate a wl_seat capability value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_seat_capability
|
||||
*/
|
||||
static inline bool
|
||||
wl_seat_capability_is_valid(uint32_t value, uint32_t version) {
|
||||
uint32_t valid = 0;
|
||||
if (version >= 1)
|
||||
valid |= WL_SEAT_CAPABILITY_POINTER;
|
||||
if (version >= 1)
|
||||
valid |= WL_SEAT_CAPABILITY_KEYBOARD;
|
||||
if (version >= 1)
|
||||
valid |= WL_SEAT_CAPABILITY_TOUCH;
|
||||
return (value & ~valid) == 0;
|
||||
}
|
||||
#endif /* WL_SEAT_CAPABILITY_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_seat
|
||||
* @struct wl_seat_interface
|
||||
|
|
@ -3251,6 +3667,26 @@ enum wl_pointer_error {
|
|||
};
|
||||
#endif /* WL_POINTER_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_ERROR_ENUM_IS_VALID
|
||||
#define WL_POINTER_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* Validate a wl_pointer error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_pointer_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_pointer_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_POINTER_ERROR_ROLE:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_POINTER_ERROR_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_POINTER_BUTTON_STATE_ENUM
|
||||
#define WL_POINTER_BUTTON_STATE_ENUM
|
||||
/**
|
||||
|
|
@ -3272,6 +3708,28 @@ enum wl_pointer_button_state {
|
|||
};
|
||||
#endif /* WL_POINTER_BUTTON_STATE_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_BUTTON_STATE_ENUM_IS_VALID
|
||||
#define WL_POINTER_BUTTON_STATE_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* Validate a wl_pointer button_state value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_pointer_button_state
|
||||
*/
|
||||
static inline bool
|
||||
wl_pointer_button_state_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_POINTER_BUTTON_STATE_RELEASED:
|
||||
return version >= 1;
|
||||
case WL_POINTER_BUTTON_STATE_PRESSED:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_POINTER_BUTTON_STATE_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_POINTER_AXIS_ENUM
|
||||
#define WL_POINTER_AXIS_ENUM
|
||||
/**
|
||||
|
|
@ -3292,6 +3750,28 @@ enum wl_pointer_axis {
|
|||
};
|
||||
#endif /* WL_POINTER_AXIS_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_AXIS_ENUM_IS_VALID
|
||||
#define WL_POINTER_AXIS_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* Validate a wl_pointer axis value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_pointer_axis
|
||||
*/
|
||||
static inline bool
|
||||
wl_pointer_axis_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||
return version >= 1;
|
||||
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_POINTER_AXIS_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_POINTER_AXIS_SOURCE_ENUM
|
||||
#define WL_POINTER_AXIS_SOURCE_ENUM
|
||||
/**
|
||||
|
|
@ -3340,6 +3820,32 @@ enum wl_pointer_axis_source {
|
|||
#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
|
||||
#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
|
||||
|
||||
#ifndef WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID
|
||||
#define WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* Validate a wl_pointer axis_source value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_pointer_axis_source
|
||||
*/
|
||||
static inline bool
|
||||
wl_pointer_axis_source_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_POINTER_AXIS_SOURCE_WHEEL:
|
||||
return version >= 1;
|
||||
case WL_POINTER_AXIS_SOURCE_FINGER:
|
||||
return version >= 1;
|
||||
case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
|
||||
return version >= 1;
|
||||
case WL_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
return version >= 6;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_POINTER_AXIS_SOURCE_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_pointer
|
||||
* @struct wl_pointer_interface
|
||||
|
|
@ -3601,6 +4107,28 @@ enum wl_keyboard_keymap_format {
|
|||
};
|
||||
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
|
||||
|
||||
#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID
|
||||
#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_keyboard
|
||||
* Validate a wl_keyboard keymap_format value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_keyboard_keymap_format
|
||||
*/
|
||||
static inline bool
|
||||
wl_keyboard_keymap_format_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP:
|
||||
return version >= 1;
|
||||
case WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_KEYBOARD_KEY_STATE_ENUM
|
||||
#define WL_KEYBOARD_KEY_STATE_ENUM
|
||||
/**
|
||||
|
|
@ -3621,6 +4149,28 @@ enum wl_keyboard_key_state {
|
|||
};
|
||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
|
||||
|
||||
#ifndef WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID
|
||||
#define WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_keyboard
|
||||
* Validate a wl_keyboard key_state value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_keyboard_key_state
|
||||
*/
|
||||
static inline bool
|
||||
wl_keyboard_key_state_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_KEYBOARD_KEY_STATE_RELEASED:
|
||||
return version >= 1;
|
||||
case WL_KEYBOARD_KEY_STATE_PRESSED:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_KEYBOARD_KEY_STATE_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_keyboard
|
||||
* @struct wl_keyboard_interface
|
||||
|
|
@ -3947,6 +4497,36 @@ enum wl_output_subpixel {
|
|||
};
|
||||
#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
|
||||
|
||||
#ifndef WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID
|
||||
#define WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_output
|
||||
* Validate a wl_output subpixel value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_output_subpixel
|
||||
*/
|
||||
static inline bool
|
||||
wl_output_subpixel_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_OUTPUT_SUBPIXEL_UNKNOWN:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_SUBPIXEL_NONE:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_OUTPUT_SUBPIXEL_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_OUTPUT_TRANSFORM_ENUM
|
||||
#define WL_OUTPUT_TRANSFORM_ENUM
|
||||
/**
|
||||
|
|
@ -4001,6 +4581,40 @@ enum wl_output_transform {
|
|||
};
|
||||
#endif /* WL_OUTPUT_TRANSFORM_ENUM */
|
||||
|
||||
#ifndef WL_OUTPUT_TRANSFORM_ENUM_IS_VALID
|
||||
#define WL_OUTPUT_TRANSFORM_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_output
|
||||
* Validate a wl_output transform value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_output_transform
|
||||
*/
|
||||
static inline bool
|
||||
wl_output_transform_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
return version >= 1;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_OUTPUT_TRANSFORM_ENUM_IS_VALID */
|
||||
|
||||
#ifndef WL_OUTPUT_MODE_ENUM
|
||||
#define WL_OUTPUT_MODE_ENUM
|
||||
/**
|
||||
|
|
@ -4022,6 +4636,26 @@ enum wl_output_mode {
|
|||
};
|
||||
#endif /* WL_OUTPUT_MODE_ENUM */
|
||||
|
||||
#ifndef WL_OUTPUT_MODE_ENUM_IS_VALID
|
||||
#define WL_OUTPUT_MODE_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_output
|
||||
* Validate a wl_output mode value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_output_mode
|
||||
*/
|
||||
static inline bool
|
||||
wl_output_mode_is_valid(uint32_t value, uint32_t version) {
|
||||
uint32_t valid = 0;
|
||||
if (version >= 1)
|
||||
valid |= WL_OUTPUT_MODE_CURRENT;
|
||||
if (version >= 1)
|
||||
valid |= WL_OUTPUT_MODE_PREFERRED;
|
||||
return (value & ~valid) == 0;
|
||||
}
|
||||
#endif /* WL_OUTPUT_MODE_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_output
|
||||
* @struct wl_output_interface
|
||||
|
|
@ -4190,6 +4824,26 @@ enum wl_subcompositor_error {
|
|||
};
|
||||
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID
|
||||
#define WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_subcompositor
|
||||
* Validate a wl_subcompositor error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_subcompositor_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_subcompositor_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_subcompositor
|
||||
* @struct wl_subcompositor_interface
|
||||
|
|
@ -4245,6 +4899,26 @@ enum wl_subsurface_error {
|
|||
};
|
||||
#endif /* WL_SUBSURFACE_ERROR_ENUM */
|
||||
|
||||
#ifndef WL_SUBSURFACE_ERROR_ENUM_IS_VALID
|
||||
#define WL_SUBSURFACE_ERROR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_wl_subsurface
|
||||
* Validate a wl_subsurface error value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref wl_subsurface_error
|
||||
*/
|
||||
static inline bool
|
||||
wl_subsurface_error_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case WL_SUBSURFACE_ERROR_BAD_SURFACE:
|
||||
return version >= 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* WL_SUBSURFACE_ERROR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_subsurface
|
||||
* @struct wl_subsurface_interface
|
||||
|
|
|
|||
|
|
@ -80,13 +80,55 @@ enum intf_A_foo {
|
|||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_THIRD = 2,
|
||||
/**
|
||||
* this is a negative value
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_NEGATIVE = -1,
|
||||
/**
|
||||
* this is a deprecated value
|
||||
* @since 2
|
||||
* @deprecated Deprecated since version 3
|
||||
*/
|
||||
INTF_A_FOO_DEPRECATED = 3,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_THIRD_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
||||
#endif /* INTF_A_FOO_ENUM */
|
||||
|
||||
#ifndef INTF_A_BAR_ENUM
|
||||
#define INTF_A_BAR_ENUM
|
||||
enum intf_A_bar {
|
||||
/**
|
||||
* this is the first
|
||||
*/
|
||||
INTF_A_BAR_FIRST = 0x01,
|
||||
/**
|
||||
* this is the second
|
||||
*/
|
||||
INTF_A_BAR_SECOND = 0x02,
|
||||
/**
|
||||
* this is the third
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_BAR_THIRD = 0x04,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
|
||||
#endif /* INTF_A_BAR_ENUM */
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* @struct intf_A_listener
|
||||
|
|
@ -96,6 +138,12 @@ struct intf_A_listener {
|
|||
*/
|
||||
void (*hey)(void *data,
|
||||
struct intf_A *intf_A);
|
||||
/**
|
||||
* @since 2
|
||||
* @deprecated Deprecated since version 3
|
||||
*/
|
||||
void (*yo)(void *data,
|
||||
struct intf_A *intf_A);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -117,6 +165,10 @@ intf_A_add_listener(struct intf_A *intf_A,
|
|||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_HEY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_YO_SINCE_VERSION 2
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
|
|
|
|||
|
|
@ -80,13 +80,55 @@ enum intf_A_foo {
|
|||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_THIRD = 2,
|
||||
/**
|
||||
* this is a negative value
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_NEGATIVE = -1,
|
||||
/**
|
||||
* this is a deprecated value
|
||||
* @since 2
|
||||
* @deprecated Deprecated since version 3
|
||||
*/
|
||||
INTF_A_FOO_DEPRECATED = 3,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_THIRD_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
||||
#endif /* INTF_A_FOO_ENUM */
|
||||
|
||||
#ifndef INTF_A_BAR_ENUM
|
||||
#define INTF_A_BAR_ENUM
|
||||
enum intf_A_bar {
|
||||
/**
|
||||
* this is the first
|
||||
*/
|
||||
INTF_A_BAR_FIRST = 0x01,
|
||||
/**
|
||||
* this is the second
|
||||
*/
|
||||
INTF_A_BAR_SECOND = 0x02,
|
||||
/**
|
||||
* this is the third
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_BAR_THIRD = 0x04,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
|
||||
#endif /* INTF_A_BAR_ENUM */
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* @struct intf_A_listener
|
||||
|
|
@ -96,6 +138,12 @@ struct intf_A_listener {
|
|||
*/
|
||||
void (*hey)(void *data,
|
||||
struct intf_A *intf_A);
|
||||
/**
|
||||
* @since 2
|
||||
* @deprecated Deprecated since version 3
|
||||
*/
|
||||
void (*yo)(void *data,
|
||||
struct intf_A *intf_A);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -117,6 +165,10 @@ intf_A_add_listener(struct intf_A *intf_A,
|
|||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_HEY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_YO_SINCE_VERSION 2
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
|
@ -51,11 +52,12 @@ static const struct wl_message intf_A_requests[] = {
|
|||
|
||||
static const struct wl_message intf_A_events[] = {
|
||||
{ "hey", "", small_test_types + 0 },
|
||||
{ "yo", "2", small_test_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface intf_A_interface = {
|
||||
"intf_A", 3,
|
||||
3, intf_A_requests,
|
||||
1, intf_A_events,
|
||||
2, intf_A_events,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
|
@ -51,11 +52,12 @@ static const struct wl_message intf_A_requests[] = {
|
|||
|
||||
static const struct wl_message intf_A_events[] = {
|
||||
{ "hey", "", small_test_types + 0 },
|
||||
{ "yo", "2", small_test_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface intf_A_interface = {
|
||||
"intf_A", 3,
|
||||
3, intf_A_requests,
|
||||
1, intf_A_events,
|
||||
2, intf_A_events,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
|
@ -61,11 +62,12 @@ static const struct wl_message intf_A_requests[] = {
|
|||
|
||||
static const struct wl_message intf_A_events[] = {
|
||||
{ "hey", "", small_test_types + 0 },
|
||||
{ "yo", "2", small_test_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface intf_A_interface = {
|
||||
"intf_A", 3,
|
||||
3, intf_A_requests,
|
||||
1, intf_A_events,
|
||||
2, intf_A_events,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -83,13 +83,105 @@ enum intf_A_foo {
|
|||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_THIRD = 2,
|
||||
/**
|
||||
* this is a negative value
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_NEGATIVE = -1,
|
||||
/**
|
||||
* this is a deprecated value
|
||||
* @since 2
|
||||
* @deprecated Deprecated since version 3
|
||||
*/
|
||||
INTF_A_FOO_DEPRECATED = 3,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_THIRD_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
||||
#endif /* INTF_A_FOO_ENUM */
|
||||
|
||||
#ifndef INTF_A_FOO_ENUM_IS_VALID
|
||||
#define INTF_A_FOO_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* Validate a intf_A foo value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref intf_A_foo
|
||||
*/
|
||||
static inline bool
|
||||
intf_A_foo_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case INTF_A_FOO_FIRST:
|
||||
return version >= 1;
|
||||
case INTF_A_FOO_SECOND:
|
||||
return version >= 1;
|
||||
case INTF_A_FOO_THIRD:
|
||||
return version >= 2;
|
||||
case (uint32_t)INTF_A_FOO_NEGATIVE:
|
||||
return version >= 2;
|
||||
case INTF_A_FOO_DEPRECATED:
|
||||
return version >= 2;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* INTF_A_FOO_ENUM_IS_VALID */
|
||||
|
||||
#ifndef INTF_A_BAR_ENUM
|
||||
#define INTF_A_BAR_ENUM
|
||||
enum intf_A_bar {
|
||||
/**
|
||||
* this is the first
|
||||
*/
|
||||
INTF_A_BAR_FIRST = 0x01,
|
||||
/**
|
||||
* this is the second
|
||||
*/
|
||||
INTF_A_BAR_SECOND = 0x02,
|
||||
/**
|
||||
* this is the third
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_BAR_THIRD = 0x04,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
|
||||
#endif /* INTF_A_BAR_ENUM */
|
||||
|
||||
#ifndef INTF_A_BAR_ENUM_IS_VALID
|
||||
#define INTF_A_BAR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* Validate a intf_A bar value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref intf_A_bar
|
||||
*/
|
||||
static inline bool
|
||||
intf_A_bar_is_valid(uint32_t value, uint32_t version) {
|
||||
uint32_t valid = 0;
|
||||
if (version >= 1)
|
||||
valid |= INTF_A_BAR_FIRST;
|
||||
if (version >= 1)
|
||||
valid |= INTF_A_BAR_SECOND;
|
||||
if (version >= 2)
|
||||
valid |= INTF_A_BAR_THIRD;
|
||||
return (value & ~valid) == 0;
|
||||
}
|
||||
#endif /* INTF_A_BAR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* @struct intf_A_interface
|
||||
|
|
@ -120,11 +212,16 @@ struct intf_A_interface {
|
|||
};
|
||||
|
||||
#define INTF_A_HEY 0
|
||||
#define INTF_A_YO 1
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_HEY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_YO_SINCE_VERSION 2
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
|
|
@ -150,6 +247,17 @@ intf_A_send_hey(struct wl_resource *resource_)
|
|||
wl_resource_post_event(resource_, INTF_A_HEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* Sends an yo event to the client owning the resource.
|
||||
* @param resource_ The client's resource
|
||||
*/
|
||||
static inline void
|
||||
intf_A_send_yo(struct wl_resource *resource_)
|
||||
{
|
||||
wl_resource_post_event(resource_, INTF_A_YO);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -83,13 +83,105 @@ enum intf_A_foo {
|
|||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_THIRD = 2,
|
||||
/**
|
||||
* this is a negative value
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_FOO_NEGATIVE = -1,
|
||||
/**
|
||||
* this is a deprecated value
|
||||
* @since 2
|
||||
* @deprecated Deprecated since version 3
|
||||
*/
|
||||
INTF_A_FOO_DEPRECATED = 3,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_THIRD_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_NEGATIVE_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_FOO_DEPRECATED_SINCE_VERSION 2
|
||||
#endif /* INTF_A_FOO_ENUM */
|
||||
|
||||
#ifndef INTF_A_FOO_ENUM_IS_VALID
|
||||
#define INTF_A_FOO_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* Validate a intf_A foo value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref intf_A_foo
|
||||
*/
|
||||
static inline bool
|
||||
intf_A_foo_is_valid(uint32_t value, uint32_t version) {
|
||||
switch (value) {
|
||||
case INTF_A_FOO_FIRST:
|
||||
return version >= 1;
|
||||
case INTF_A_FOO_SECOND:
|
||||
return version >= 1;
|
||||
case INTF_A_FOO_THIRD:
|
||||
return version >= 2;
|
||||
case (uint32_t)INTF_A_FOO_NEGATIVE:
|
||||
return version >= 2;
|
||||
case INTF_A_FOO_DEPRECATED:
|
||||
return version >= 2;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* INTF_A_FOO_ENUM_IS_VALID */
|
||||
|
||||
#ifndef INTF_A_BAR_ENUM
|
||||
#define INTF_A_BAR_ENUM
|
||||
enum intf_A_bar {
|
||||
/**
|
||||
* this is the first
|
||||
*/
|
||||
INTF_A_BAR_FIRST = 0x01,
|
||||
/**
|
||||
* this is the second
|
||||
*/
|
||||
INTF_A_BAR_SECOND = 0x02,
|
||||
/**
|
||||
* this is the third
|
||||
* @since 2
|
||||
*/
|
||||
INTF_A_BAR_THIRD = 0x04,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_BAR_THIRD_SINCE_VERSION 2
|
||||
#endif /* INTF_A_BAR_ENUM */
|
||||
|
||||
#ifndef INTF_A_BAR_ENUM_IS_VALID
|
||||
#define INTF_A_BAR_ENUM_IS_VALID
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* Validate a intf_A bar value.
|
||||
*
|
||||
* @return true on success, false on error.
|
||||
* @ref intf_A_bar
|
||||
*/
|
||||
static inline bool
|
||||
intf_A_bar_is_valid(uint32_t value, uint32_t version) {
|
||||
uint32_t valid = 0;
|
||||
if (version >= 1)
|
||||
valid |= INTF_A_BAR_FIRST;
|
||||
if (version >= 1)
|
||||
valid |= INTF_A_BAR_SECOND;
|
||||
if (version >= 2)
|
||||
valid |= INTF_A_BAR_THIRD;
|
||||
return (value & ~valid) == 0;
|
||||
}
|
||||
#endif /* INTF_A_BAR_ENUM_IS_VALID */
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* @struct intf_A_interface
|
||||
|
|
@ -120,11 +212,16 @@ struct intf_A_interface {
|
|||
};
|
||||
|
||||
#define INTF_A_HEY 0
|
||||
#define INTF_A_YO 1
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_HEY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
*/
|
||||
#define INTF_A_YO_SINCE_VERSION 2
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
|
|
@ -150,6 +247,17 @@ intf_A_send_hey(struct wl_resource *resource_)
|
|||
wl_resource_post_event(resource_, INTF_A_HEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_intf_A
|
||||
* Sends an yo event to the client owning the resource.
|
||||
* @param resource_ The client's resource
|
||||
*/
|
||||
static inline void
|
||||
intf_A_send_yo(struct wl_resource *resource_)
|
||||
{
|
||||
wl_resource_post_event(resource_, INTF_A_YO);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -49,10 +49,21 @@
|
|||
|
||||
<event name="hey"/>
|
||||
|
||||
<event name="yo" since="2" deprecated-since="3"/>
|
||||
|
||||
<enum name="foo">
|
||||
<entry name="first" value="0" summary="this is the first"/>
|
||||
<entry name="second" value="1" summary="this is the second"/>
|
||||
<entry name="third" value="2" since="2" summary="this is the third"/>
|
||||
<entry name="negative" value="-1" since="2" summary="this is a negative value"/>
|
||||
<entry name="deprecated" value="3" since="2" deprecated-since="3" summary="this is a deprecated value"/>
|
||||
</enum>
|
||||
|
||||
<enum name="bar" bitfield="true">
|
||||
<entry name="first" value="0x01" summary="this is the first"/>
|
||||
<entry name="second" value="0x02" summary="this is the second"/>
|
||||
<entry name="third" value="0x04" since="2" summary="this is the third"/>
|
||||
</enum>
|
||||
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
|
|||
|
|
@ -924,7 +924,7 @@ TEST(versions)
|
|||
}
|
||||
|
||||
static void
|
||||
check_error_on_destroyed_object(void *data)
|
||||
check_error_on_destroyed_object(void)
|
||||
{
|
||||
struct client *c;
|
||||
struct wl_seat *seat;
|
||||
|
|
@ -1043,7 +1043,7 @@ TEST(filtered_global_is_hidden)
|
|||
1, d, bind_data_offer);
|
||||
wl_display_set_global_filter(d->wl_display, global_filter, NULL);
|
||||
|
||||
client_create_noarg(d, get_globals);
|
||||
client_create(d, get_globals, NULL);
|
||||
display_run(d);
|
||||
|
||||
wl_global_destroy(g);
|
||||
|
|
@ -1052,13 +1052,13 @@ TEST(filtered_global_is_hidden)
|
|||
}
|
||||
|
||||
static void
|
||||
get_dynamic_globals(void *data)
|
||||
get_dynamic_globals(void)
|
||||
{
|
||||
struct client *c = client_connect();
|
||||
struct wl_registry *registry;
|
||||
|
||||
registry = wl_display_get_registry(c->wl_display);
|
||||
wl_registry_add_listener(registry, ®istry_listener_filtered, data);
|
||||
wl_registry_add_listener(registry, ®istry_listener_filtered, NULL);
|
||||
wl_display_roundtrip(c->wl_display);
|
||||
|
||||
/* Wait for the server to create a new global */
|
||||
|
|
@ -1206,7 +1206,7 @@ static const struct wl_registry_listener zombie_fd_registry_listener = {
|
|||
};
|
||||
|
||||
static void
|
||||
zombie_client(void *data)
|
||||
zombie_client(void)
|
||||
{
|
||||
struct client *c = client_connect();
|
||||
struct wl_registry *registry;
|
||||
|
|
@ -1376,7 +1376,7 @@ static const struct wl_registry_listener double_zombie_fd_registry_listener = {
|
|||
};
|
||||
|
||||
static void
|
||||
double_zombie_client(void *data)
|
||||
double_zombie_client(void)
|
||||
{
|
||||
struct client *c = client_connect();
|
||||
struct wl_registry *registry;
|
||||
|
|
@ -1436,7 +1436,7 @@ static const struct wl_registry_listener bind_interface_mismatch_registry_listen
|
|||
};
|
||||
|
||||
static void
|
||||
registry_bind_interface_mismatch_client(void *data)
|
||||
registry_bind_interface_mismatch_client(void)
|
||||
{
|
||||
struct client *c = client_connect();
|
||||
struct wl_registry *registry;
|
||||
|
|
@ -1492,6 +1492,10 @@ send_overflow_client(void *data)
|
|||
char tmp = '\0';
|
||||
int sock, optval = 16384;
|
||||
|
||||
/* By default, client buffers are now unbounded, set a limit to cause
|
||||
* an overflow, otherwise the client buffers will grow indefinitely. */
|
||||
wl_display_set_max_buffer_size(c->wl_display, 4096);
|
||||
|
||||
/* Limit the send buffer size for the display socket to guarantee
|
||||
* that the test will cause an overflow. */
|
||||
sock = wl_display_get_fd(c->wl_display);
|
||||
|
|
@ -1505,6 +1509,7 @@ send_overflow_client(void *data)
|
|||
* within <=4096 iterations. */
|
||||
for (i = 0; i < 1000000; i++) {
|
||||
noop_request(c);
|
||||
fprintf(stderr, "Send loop %i\n", i);
|
||||
err = wl_display_get_error(c->wl_display);
|
||||
if (err)
|
||||
break;
|
||||
|
|
@ -1514,9 +1519,9 @@ send_overflow_client(void *data)
|
|||
* check verifies that the initial/final FD counts are the same */
|
||||
assert(write(pipes[1], &tmp, sizeof(tmp)) == (ssize_t)sizeof(tmp));
|
||||
|
||||
/* Expect an error */
|
||||
/* Expect an error - ring_buffer_ensure_space() returns E2BIG */
|
||||
fprintf(stderr, "Send loop failed on try %d, err = %d, %s\n", i, err, strerror(err));
|
||||
assert(err == EAGAIN);
|
||||
assert(err == EAGAIN || err == E2BIG);
|
||||
|
||||
client_disconnect_nocheck(c);
|
||||
}
|
||||
|
|
@ -1593,7 +1598,7 @@ static const struct wl_registry_listener global_remove_before_registry_listener
|
|||
};
|
||||
|
||||
static void
|
||||
global_remove_before_client(void *data)
|
||||
global_remove_before_client(void)
|
||||
{
|
||||
struct client *c = client_connect();
|
||||
struct wl_registry *registry;
|
||||
|
|
@ -1643,7 +1648,7 @@ static const struct wl_registry_listener global_remove_after_registry_listener =
|
|||
};
|
||||
|
||||
static void
|
||||
global_remove_after_client(void *data)
|
||||
global_remove_after_client(void)
|
||||
{
|
||||
struct client *c = client_connect();
|
||||
struct wl_registry *registry;
|
||||
|
|
@ -1690,6 +1695,75 @@ TEST(global_remove)
|
|||
display_destroy(d);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_single_read_events(struct wl_display *d)
|
||||
{
|
||||
if (wl_display_prepare_read(d) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = wl_display_flush(d);
|
||||
} while (ret < 0 && (errno == EINTR || errno == EAGAIN));
|
||||
assert(ret >= 0);
|
||||
|
||||
struct pollfd pfd[1];
|
||||
pfd[0].fd = wl_display_get_fd(d);
|
||||
pfd[0].events = POLLIN;
|
||||
|
||||
do {
|
||||
ret = poll(pfd, 1, -1);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
assert(ret > 0);
|
||||
|
||||
wl_display_read_events(d);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_single_client(void)
|
||||
{
|
||||
struct client *c = client_connect();
|
||||
|
||||
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
|
||||
|
||||
struct wl_registry *registry = wl_display_get_registry(c->wl_display);
|
||||
|
||||
dispatch_single_read_events(c->wl_display);
|
||||
|
||||
// [1815110.061] {Default Queue} wl_registry#3.global(1, "test", 1)
|
||||
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
|
||||
|
||||
dispatch_single_read_events(c->wl_display);
|
||||
|
||||
// [1815110.067] {Default Queue} wl_registry#3.global(2, "wl_seat", 1)
|
||||
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
|
||||
|
||||
// No more events
|
||||
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
|
||||
|
||||
wl_registry_destroy(registry);
|
||||
|
||||
client_disconnect(c);
|
||||
}
|
||||
|
||||
TEST(dispatch_single)
|
||||
{
|
||||
struct display *d = display_create();
|
||||
|
||||
struct wl_global *global = wl_global_create(d->wl_display,
|
||||
&wl_seat_interface,
|
||||
1, d, bind_seat);
|
||||
|
||||
client_create_noarg(d, dispatch_single_client);
|
||||
|
||||
display_run(d);
|
||||
|
||||
wl_global_destroy(global);
|
||||
|
||||
display_destroy(d);
|
||||
}
|
||||
|
||||
static void
|
||||
terminate_display(void *arg)
|
||||
{
|
||||
|
|
|
|||
28
tests/enum-validator-test.c
Normal file
28
tests/enum-validator-test.c
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include <assert.h>
|
||||
#include "data/small-server-core.h"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
assert(intf_A_foo_is_valid(INTF_A_FOO_FIRST, 1));
|
||||
assert(intf_A_foo_is_valid(INTF_A_FOO_FIRST, 2));
|
||||
|
||||
assert(!intf_A_foo_is_valid(INTF_A_FOO_THIRD, 1));
|
||||
assert(intf_A_foo_is_valid(INTF_A_FOO_THIRD, 2));
|
||||
|
||||
assert(intf_A_foo_is_valid(INTF_A_FOO_NEGATIVE, 2));
|
||||
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST, 1));
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST, 2));
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_SECOND, 1));
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_SECOND, 2));
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_SECOND, 1));
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_SECOND, 2));
|
||||
|
||||
assert(!intf_A_bar_is_valid(INTF_A_BAR_THIRD, 1));
|
||||
assert(!intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_THIRD, 1));
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_THIRD, 2));
|
||||
assert(intf_A_bar_is_valid(INTF_A_BAR_FIRST | INTF_A_BAR_THIRD, 2));
|
||||
|
||||
assert(!intf_A_bar_is_valid(0xFF, 1));
|
||||
assert(!intf_A_bar_is_valid(0xFF, 2));
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2012 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "wayland-private.h"
|
||||
|
||||
volatile double global_d;
|
||||
|
||||
static void
|
||||
noop_conversion(void)
|
||||
{
|
||||
wl_fixed_t f;
|
||||
union {
|
||||
int64_t i;
|
||||
double d;
|
||||
} u;
|
||||
|
||||
for (f = 0; f < INT32_MAX; f++) {
|
||||
u.i = f;
|
||||
global_d = u.d;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
magic_conversion(void)
|
||||
{
|
||||
wl_fixed_t f;
|
||||
|
||||
for (f = 0; f < INT32_MAX; f++)
|
||||
global_d = wl_fixed_to_double(f);
|
||||
}
|
||||
|
||||
static void
|
||||
mul_conversion(void)
|
||||
{
|
||||
wl_fixed_t f;
|
||||
|
||||
/* This will get optimized into multiplication by 1/256 */
|
||||
for (f = 0; f < INT32_MAX; f++)
|
||||
global_d = f / 256.0;
|
||||
}
|
||||
|
||||
double factor = 256.0;
|
||||
|
||||
static void
|
||||
div_conversion(void)
|
||||
{
|
||||
wl_fixed_t f;
|
||||
|
||||
for (f = 0; f < INT32_MAX; f++)
|
||||
global_d = f / factor;
|
||||
}
|
||||
|
||||
static void
|
||||
benchmark(const char *s, void (*f)(void))
|
||||
{
|
||||
struct timespec start, stop, elapsed;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
f();
|
||||
clock_gettime(CLOCK_MONOTONIC, &stop);
|
||||
|
||||
elapsed.tv_sec = stop.tv_sec - start.tv_sec;
|
||||
elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
|
||||
if (elapsed.tv_nsec < 0) {
|
||||
elapsed.tv_nsec += 1000000000;
|
||||
elapsed.tv_sec--;
|
||||
}
|
||||
printf("benchmarked %s:\t%ld.%09lds\n",
|
||||
s, elapsed.tv_sec, elapsed.tv_nsec);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
benchmark("noop", noop_conversion);
|
||||
benchmark("magic", magic_conversion);
|
||||
benchmark("div", div_conversion);
|
||||
benchmark("mul", mul_conversion);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -54,16 +54,7 @@ tests_protocol_c = custom_target(
|
|||
output: 'tests-protocol.c'
|
||||
)
|
||||
|
||||
benchmark(
|
||||
'fixed-benchmark',
|
||||
executable(
|
||||
'fixed-benchmark',
|
||||
'fixed-benchmark.c',
|
||||
dependencies: [ test_runner_dep, rt_dep ]
|
||||
)
|
||||
)
|
||||
|
||||
executable(
|
||||
exec_fd_leak_checker = executable(
|
||||
'exec-fd-leak-checker',
|
||||
'exec-fd-leak-checker.c',
|
||||
dependencies: test_runner_dep
|
||||
|
|
@ -84,86 +75,137 @@ endif
|
|||
sed_path = find_program('sed').full_path()
|
||||
|
||||
if get_option('scanner')
|
||||
scanner_test_env = [
|
||||
'TEST_DATA_DIR=@0@/data'.format(meson.current_source_dir()),
|
||||
'TEST_OUTPUT_DIR=@0@/output'.format(meson.current_build_dir()),
|
||||
'SED=@0@'.format(sed_path),
|
||||
'WAYLAND_SCANNER=@0@'.format(wayland_scanner.full_path()),
|
||||
]
|
||||
|
||||
test(
|
||||
'scanner-test',
|
||||
find_program('scanner-test.sh'),
|
||||
env: [
|
||||
'TEST_DATA_DIR=@0@/data'.format(meson.current_source_dir()),
|
||||
'TEST_OUTPUT_DIR=@0@/output'.format(meson.current_build_dir()),
|
||||
'SED=@0@'.format(sed_path),
|
||||
'WAYLAND_SCANNER=@0@'.format(wayland_scanner.full_path()),
|
||||
],
|
||||
env: scanner_test_env,
|
||||
)
|
||||
|
||||
run_target(
|
||||
'gen-scanner-test',
|
||||
command: find_program('scanner-test-gen.sh'),
|
||||
env: scanner_test_env,
|
||||
)
|
||||
endif
|
||||
|
||||
tests = {
|
||||
'array-test': [],
|
||||
'client-test': [ wayland_server_protocol_h ],
|
||||
'display-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
tests_server_protocol_h,
|
||||
tests_client_protocol_c,
|
||||
tests_protocol_c,
|
||||
],
|
||||
'connection-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'event-loop-test': [ wayland_server_protocol_h ],
|
||||
'fixed-test': [],
|
||||
'interface-test': [ wayland_client_protocol_h ],
|
||||
'list-test': [],
|
||||
'map-test': [],
|
||||
'sanity-test' : [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'socket-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'queue-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'signal-test': [ wayland_server_protocol_h ],
|
||||
'newsignal-test': [
|
||||
# wayland-server.c is needed here to access wl_priv_* functions
|
||||
files('../src/wayland-server.c'),
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'resources-test': [ wayland_server_protocol_h ],
|
||||
'message-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'compositor-introspection-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'protocol-logger-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'headers-test': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
'headers-protocol-test.c',
|
||||
wayland_client_protocol_core_h,
|
||||
wayland_server_protocol_core_h,
|
||||
'headers-protocol-core-test.c',
|
||||
],
|
||||
'os-wrappers-test': [],
|
||||
'array-test': {},
|
||||
'client-test': {
|
||||
'extra_sources': [ wayland_server_protocol_h ],
|
||||
},
|
||||
'display-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
tests_server_protocol_h,
|
||||
tests_client_protocol_c,
|
||||
tests_protocol_c,
|
||||
],
|
||||
},
|
||||
'connection-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'event-loop-test': {
|
||||
'extra_sources': [ wayland_server_protocol_h ],
|
||||
},
|
||||
'fixed-test': {},
|
||||
'interface-test': {
|
||||
'extra_sources': [ wayland_client_protocol_h ],
|
||||
},
|
||||
'list-test': {},
|
||||
'map-test': {},
|
||||
'sanity-test' : {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
'runtime_deps': [ exec_fd_leak_checker ],
|
||||
},
|
||||
'socket-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'queue-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'signal-test': {
|
||||
'extra_sources': [ wayland_server_protocol_h ],
|
||||
},
|
||||
'newsignal-test': {
|
||||
'extra_sources': [
|
||||
# wayland-server.c is needed here to access wl_priv_* functions
|
||||
files('../src/wayland-server.c'),
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'resources-test': {
|
||||
'extra_sources': [ wayland_server_protocol_h ],
|
||||
},
|
||||
'message-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'compositor-introspection-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'protocol-logger-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'headers-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
'headers-protocol-test.c',
|
||||
wayland_client_protocol_core_h,
|
||||
wayland_server_protocol_core_h,
|
||||
'headers-protocol-core-test.c',
|
||||
],
|
||||
},
|
||||
'os-wrappers-test': {
|
||||
'runtime_deps': [ exec_fd_leak_checker ],
|
||||
},
|
||||
'proxy-test': {
|
||||
'extra_sources': [
|
||||
wayland_client_protocol_h,
|
||||
wayland_server_protocol_h,
|
||||
],
|
||||
},
|
||||
'enum-validator-test': {},
|
||||
}
|
||||
|
||||
foreach test_name, test_extra_sources: tests
|
||||
foreach test_name, test_extras : tests
|
||||
test_extra_sources = test_extras.get('extra_sources', [])
|
||||
test_runtime_deps = test_extras.get('runtime_deps', [])
|
||||
test_sources = [ test_name + '.c' ] + test_extra_sources
|
||||
test_deps = [test_runner_dep, epoll_dep]
|
||||
bin = executable(test_name, test_sources, dependencies: test_deps)
|
||||
test(
|
||||
test_name,
|
||||
bin,
|
||||
depends: test_runtime_deps,
|
||||
env: [
|
||||
'TEST_SRC_DIR=@0@'.format(meson.current_source_dir()),
|
||||
'TEST_BUILD_DIR=@0@'.format(meson.current_build_dir()),
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -45,50 +44,20 @@
|
|||
#include "test-runner.h"
|
||||
#include "wayland-os.h"
|
||||
|
||||
extern int (*wl_socket)(int domain, int type, int protocol);
|
||||
extern int (*wl_fcntl)(int fildes, int cmd, ...);
|
||||
extern ssize_t (*wl_recvmsg)(int socket, struct msghdr *message, int flags);
|
||||
extern int (*wl_epoll_create1)(int flags);
|
||||
|
||||
static int fall_back;
|
||||
|
||||
/* Play nice with sanitizers
|
||||
*
|
||||
* Sanitizers need to intercept syscalls in the compiler run-time library. As
|
||||
* this isn't a separate ELF object, the usual dlsym(RTLD_NEXT) approach won't
|
||||
* work: there can only be one function named "socket" etc. To support this, the
|
||||
* sanitizer library names its interceptors with the prefix __interceptor_ ("__"
|
||||
* being reserved for the implementation) and then weakly aliases it to the real
|
||||
* function. The functions we define below will override the weak alias, and we
|
||||
* can call them by the __interceptor_ name directly. This allows the sanitizer
|
||||
* to do its work before calling the next version of the function via dlsym.
|
||||
*
|
||||
* However! We also don't know which of these functions the sanitizer actually
|
||||
* wants to override, so we have to declare our own weak symbols for
|
||||
* __interceptor_ and check at run time if they linked to anything or not.
|
||||
*/
|
||||
static int wrapped_calls_socket = 0;
|
||||
static int wrapped_calls_fcntl = 0;
|
||||
static int wrapped_calls_recvmsg = 0;
|
||||
static int wrapped_calls_epoll_create1 = 0;
|
||||
|
||||
#define DECL(ret_type, func, ...) \
|
||||
ret_type __interceptor_ ## func(__VA_ARGS__) __attribute__((weak)); \
|
||||
static ret_type (*real_ ## func)(__VA_ARGS__); \
|
||||
static int wrapped_calls_ ## func;
|
||||
|
||||
#define REAL(func) (__interceptor_ ## func) ? \
|
||||
__interceptor_ ## func : \
|
||||
(__typeof__(&__interceptor_ ## func))dlsym(RTLD_NEXT, #func)
|
||||
|
||||
DECL(int, socket, int, int, int);
|
||||
DECL(int, fcntl, int, int, ...);
|
||||
DECL(ssize_t, recvmsg, int, struct msghdr *, int);
|
||||
DECL(int, epoll_create1, int);
|
||||
|
||||
static void
|
||||
init_fallbacks(int do_fallbacks)
|
||||
{
|
||||
fall_back = do_fallbacks;
|
||||
real_socket = REAL(socket);
|
||||
real_fcntl = REAL(fcntl);
|
||||
real_recvmsg = REAL(recvmsg);
|
||||
real_epoll_create1 = REAL(epoll_create1);
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default"))) int
|
||||
socket(int domain, int type, int protocol)
|
||||
static int
|
||||
socket_wrapper(int domain, int type, int protocol)
|
||||
{
|
||||
wrapped_calls_socket++;
|
||||
|
||||
|
|
@ -97,11 +66,11 @@ socket(int domain, int type, int protocol)
|
|||
return -1;
|
||||
}
|
||||
|
||||
return real_socket(domain, type, protocol);
|
||||
return socket(domain, type, protocol);
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default"))) int
|
||||
(fcntl)(int fd, int cmd, ...)
|
||||
static int
|
||||
fcntl_wrapper(int fd, int cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int arg;
|
||||
|
|
@ -131,13 +100,13 @@ __attribute__ ((visibility("default"))) int
|
|||
}
|
||||
|
||||
if (has_arg) {
|
||||
return real_fcntl(fd, cmd, arg);
|
||||
return fcntl(fd, cmd, arg);
|
||||
}
|
||||
return real_fcntl(fd, cmd);
|
||||
return fcntl(fd, cmd);
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default"))) ssize_t
|
||||
recvmsg(int sockfd, struct msghdr *msg, int flags)
|
||||
static ssize_t
|
||||
recvmsg_wrapper(int sockfd, struct msghdr *msg, int flags)
|
||||
{
|
||||
wrapped_calls_recvmsg++;
|
||||
|
||||
|
|
@ -146,11 +115,11 @@ recvmsg(int sockfd, struct msghdr *msg, int flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
return real_recvmsg(sockfd, msg, flags);
|
||||
return recvmsg(sockfd, msg, flags);
|
||||
}
|
||||
|
||||
__attribute__ ((visibility("default"))) int
|
||||
epoll_create1(int flags)
|
||||
static int
|
||||
epoll_create1_wrapper(int flags)
|
||||
{
|
||||
wrapped_calls_epoll_create1++;
|
||||
|
||||
|
|
@ -160,7 +129,17 @@ epoll_create1(int flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
return real_epoll_create1(flags);
|
||||
return epoll_create1(flags);
|
||||
}
|
||||
|
||||
static void
|
||||
init_fallbacks(int do_fallbacks)
|
||||
{
|
||||
fall_back = do_fallbacks;
|
||||
wl_fcntl = fcntl_wrapper;
|
||||
wl_socket = socket_wrapper;
|
||||
wl_recvmsg = recvmsg_wrapper;
|
||||
wl_epoll_create1 = epoll_create1_wrapper;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -256,10 +235,12 @@ setup_marshal_data(struct marshal_data *data)
|
|||
assert(socketpair(AF_UNIX,
|
||||
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
||||
|
||||
data->read_connection = wl_connection_create(data->s[0]);
|
||||
data->read_connection = wl_connection_create(data->s[0],
|
||||
WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->read_connection);
|
||||
|
||||
data->write_connection = wl_connection_create(data->s[1]);
|
||||
data->write_connection = wl_connection_create(data->s[1],
|
||||
WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->write_connection);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ TEST(proxy_tag)
|
|||
wl_proxy_set_tag((struct wl_proxy *) client.callback_b,
|
||||
&tag_b);
|
||||
|
||||
assert(wl_proxy_get_display((struct wl_proxy *) client.callback_b) == client.display);
|
||||
|
||||
wl_display_flush(client.display);
|
||||
|
||||
while (server.sync_count < 2) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "wayland-server.h"
|
||||
#include "test-runner.h"
|
||||
#include "test-compositor.h"
|
||||
#include "../src/timespec-util.h"
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
|
|
@ -383,7 +384,7 @@ client_test_queue_destroy_with_attached_proxies(void)
|
|||
/* Check that the log contains some information about the attached
|
||||
* wl_callback proxy. */
|
||||
log = map_file(client_log_fd, &log_len);
|
||||
ret = snprintf(callback_name, sizeof(callback_name), "wl_callback@%u",
|
||||
ret = snprintf(callback_name, sizeof(callback_name), "wl_callback#%u",
|
||||
wl_proxy_get_id((struct wl_proxy *) callback));
|
||||
assert(ret > 0 && ret < (int)sizeof(callback_name) &&
|
||||
"callback name creation failed (possibly truncated)");
|
||||
|
|
@ -456,7 +457,7 @@ client_test_queue_destroy_default_with_attached_proxies(void)
|
|||
/* Check that the log does not contain any warning about the attached
|
||||
* wl_callback proxy. */
|
||||
log = maybe_map_file(client_log_fd, &log_len);
|
||||
ret = snprintf(callback_name, sizeof(callback_name), "wl_callback@%u",
|
||||
ret = snprintf(callback_name, sizeof(callback_name), "wl_callback#%u",
|
||||
wl_proxy_get_id((struct wl_proxy *) callback));
|
||||
assert(ret > 0 && ret < (int)sizeof(callback_name) &&
|
||||
"callback name creation failed (possibly truncated)");
|
||||
|
|
@ -471,6 +472,168 @@ client_test_queue_destroy_default_with_attached_proxies(void)
|
|||
free(callback);
|
||||
}
|
||||
|
||||
static void
|
||||
check_queue_name(struct wl_proxy *proxy, const char *name)
|
||||
{
|
||||
struct wl_event_queue *queue;
|
||||
const char *queue_name;
|
||||
|
||||
queue = wl_proxy_get_queue(proxy);
|
||||
queue_name = wl_event_queue_get_name(queue);
|
||||
if (!name)
|
||||
assert(!queue_name);
|
||||
else
|
||||
assert(strcmp(queue_name, name) == 0);
|
||||
}
|
||||
|
||||
static struct wl_callback *
|
||||
roundtrip_named_queue_nonblock(struct wl_display *display,
|
||||
struct wl_event_queue *queue,
|
||||
const char *name)
|
||||
{
|
||||
struct wl_callback *callback;
|
||||
struct wl_display *wrapped_display = NULL;
|
||||
|
||||
if (queue) {
|
||||
wrapped_display = wl_proxy_create_wrapper(display);
|
||||
assert(wrapped_display);
|
||||
wl_proxy_set_queue((struct wl_proxy *) wrapped_display, queue);
|
||||
check_queue_name((struct wl_proxy *) wrapped_display, name);
|
||||
|
||||
callback = wl_display_sync(wrapped_display);
|
||||
} else
|
||||
callback = wl_display_sync(display);
|
||||
|
||||
check_queue_name((struct wl_proxy *) callback, name);
|
||||
|
||||
if (wrapped_display)
|
||||
wl_proxy_wrapper_destroy(wrapped_display);
|
||||
|
||||
assert(callback != NULL);
|
||||
|
||||
return callback;
|
||||
}
|
||||
|
||||
static void
|
||||
client_test_queue_names(void)
|
||||
{
|
||||
struct wl_event_queue *queue1, *queue2, *queue3;
|
||||
struct wl_display *display;
|
||||
struct wl_callback *callback1, *callback2, *callback3, *callback4;
|
||||
struct wl_event_queue *default_queue;
|
||||
char *log;
|
||||
size_t log_len;
|
||||
const char *default_queue_name;
|
||||
|
||||
display = wl_display_connect(NULL);
|
||||
assert(display);
|
||||
|
||||
default_queue = wl_proxy_get_queue((struct wl_proxy *) display);
|
||||
default_queue_name = wl_event_queue_get_name(default_queue);
|
||||
assert(strcmp(default_queue_name, "Default Queue") == 0);
|
||||
|
||||
/* Create some event queues both with and without names. */
|
||||
queue1 = wl_display_create_queue_with_name(display, "First");
|
||||
assert(queue1);
|
||||
|
||||
queue2 = wl_display_create_queue_with_name(display, "Second");
|
||||
assert(queue2);
|
||||
|
||||
queue3 = wl_display_create_queue(display);
|
||||
assert(queue3);
|
||||
|
||||
/* Create some requests and ensure their queues have the expected
|
||||
* names.
|
||||
*/
|
||||
callback1 = roundtrip_named_queue_nonblock(display, queue1, "First");
|
||||
callback2 = roundtrip_named_queue_nonblock(display, queue2, "Second");
|
||||
callback3 = roundtrip_named_queue_nonblock(display, queue3, NULL);
|
||||
callback4 = roundtrip_named_queue_nonblock(display, NULL, "Default Queue");
|
||||
|
||||
/* Destroy one queue with proxies still attached so we can verify
|
||||
* that the queue name is in the log message. */
|
||||
wl_event_queue_destroy(queue2);
|
||||
log = map_file(client_log_fd, &log_len);
|
||||
assert(strstr(log, "Second"));
|
||||
|
||||
/* There's no reason for the First queue name to be present. */
|
||||
assert(!strstr(log, "First"));
|
||||
|
||||
munmap(log, log_len);
|
||||
|
||||
wl_callback_destroy(callback1);
|
||||
wl_callback_destroy(callback2);
|
||||
wl_callback_destroy(callback3);
|
||||
wl_callback_destroy(callback4);
|
||||
|
||||
wl_event_queue_destroy(queue1);
|
||||
wl_event_queue_destroy(queue3);
|
||||
|
||||
wl_display_disconnect(display);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_timeout_sync_callback(void *data, struct wl_callback *callback,
|
||||
uint32_t serial)
|
||||
{
|
||||
bool *done = data;
|
||||
|
||||
*done = true;
|
||||
wl_callback_destroy(callback);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener dispatch_timeout_sync_listener = {
|
||||
dispatch_timeout_sync_callback
|
||||
};
|
||||
|
||||
static void
|
||||
client_test_queue_dispatch_simple(void)
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct timespec timeout;
|
||||
struct wl_callback *callback;
|
||||
bool done = false;
|
||||
int ret = 0;
|
||||
|
||||
display = wl_display_connect(NULL);
|
||||
assert(display);
|
||||
|
||||
callback = wl_display_sync(display);
|
||||
assert(callback != NULL);
|
||||
wl_callback_add_listener(callback, &dispatch_timeout_sync_listener, &done);
|
||||
|
||||
timespec_from_msec(&timeout, 1000);
|
||||
|
||||
while (!done) {
|
||||
ret = wl_display_dispatch_timeout(display, &timeout);
|
||||
assert(ret > 0);
|
||||
}
|
||||
|
||||
wl_display_disconnect(display);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
client_test_queue_dispatch_timeout(void)
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct timespec timeout;
|
||||
int ret = 0;
|
||||
|
||||
display = wl_display_connect(NULL);
|
||||
assert(display);
|
||||
|
||||
timespec_from_msec(&timeout, 100);
|
||||
|
||||
ret = wl_display_dispatch_timeout(display, &timeout);
|
||||
assert(ret == 0);
|
||||
|
||||
wl_display_disconnect(display);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
dummy_bind(struct wl_client *client,
|
||||
void *data, uint32_t version, uint32_t id)
|
||||
|
|
@ -597,3 +760,39 @@ TEST(queue_destroy_default_with_attached_proxies)
|
|||
|
||||
display_destroy(d);
|
||||
}
|
||||
|
||||
TEST(queue_names)
|
||||
{
|
||||
struct display *d = display_create();
|
||||
|
||||
test_set_timeout(2);
|
||||
|
||||
client_create_noarg(d, client_test_queue_names);
|
||||
display_run(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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,3 +206,60 @@ TEST(free_without_remove)
|
|||
assert(a.link.next == a.link.prev && a.link.next == NULL);
|
||||
assert(b.link.next == b.link.prev && b.link.next == NULL);
|
||||
}
|
||||
|
||||
static enum wl_iterator_result
|
||||
client_resource_check(struct wl_resource* resource, void* data)
|
||||
{
|
||||
/* Ensure there is no iteration over already freed resources. */
|
||||
assert(!wl_resource_get_user_data(resource));
|
||||
return WL_ITERATOR_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
resource_destroy_notify(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct wl_resource* resource = data;
|
||||
struct wl_client* client = resource->client;
|
||||
|
||||
wl_client_for_each_resource(client, client_resource_check, NULL);
|
||||
|
||||
/* Set user data to flag the resource has been deleted. The resource should
|
||||
* not be accessible from this point forward. */
|
||||
wl_resource_set_user_data(resource, client);
|
||||
}
|
||||
|
||||
TEST(resource_destroy_iteration)
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct wl_client *client;
|
||||
struct wl_resource *resource1;
|
||||
struct wl_resource *resource2;
|
||||
int s[2];
|
||||
|
||||
struct wl_listener destroy_listener1 = {
|
||||
.notify = &resource_destroy_notify
|
||||
};
|
||||
struct wl_listener destroy_listener2 = {
|
||||
.notify = &resource_destroy_notify
|
||||
};
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
display = wl_display_create();
|
||||
assert(display);
|
||||
client = wl_client_create(display, s[0]);
|
||||
assert(client);
|
||||
resource1 = wl_resource_create(client, &wl_callback_interface, 1, 0);
|
||||
resource2 = wl_resource_create(client, &wl_callback_interface, 1, 0);
|
||||
assert(resource1);
|
||||
assert(resource2);
|
||||
|
||||
wl_resource_add_destroy_listener(resource1, &destroy_listener1);
|
||||
wl_resource_add_destroy_listener(resource2, &destroy_listener2);
|
||||
|
||||
wl_client_destroy(client);
|
||||
|
||||
close(s[0]);
|
||||
close(s[1]);
|
||||
|
||||
wl_display_destroy(display);
|
||||
}
|
||||
|
|
|
|||
26
tests/scanner-test-gen.sh
Executable file
26
tests/scanner-test-gen.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh -eu
|
||||
|
||||
generate() {
|
||||
"$WAYLAND_SCANNER" $1 < "$TEST_DATA_DIR/$2" > "$TEST_DATA_DIR/$3"
|
||||
"$SED" -i -e 's/Generated by wayland-scanner [0-9.]*/SCANNER TEST/' \
|
||||
"$TEST_DATA_DIR/$3"
|
||||
}
|
||||
|
||||
generate "code" "example.xml" "example-code.c"
|
||||
generate "client-header" "example.xml" "example-client.h"
|
||||
generate "server-header" "example.xml" "example-server.h"
|
||||
generate "enum-header" "example.xml" "example-enum.h"
|
||||
|
||||
generate "code" "small.xml" "small-code.c"
|
||||
generate "client-header" "small.xml" "small-client.h"
|
||||
generate "server-header" "small.xml" "small-server.h"
|
||||
|
||||
generate "-c code" "small.xml" "small-code-core.c"
|
||||
generate "-c client-header" "small.xml" "small-client-core.h"
|
||||
generate "-c server-header" "small.xml" "small-server-core.h"
|
||||
|
||||
generate "private-code" "small.xml" "small-private-code.c"
|
||||
|
||||
generate "code" "empty.xml" "empty-code.c"
|
||||
generate "client-header" "empty.xml" "empty-client.h"
|
||||
generate "server-header" "empty.xml" "empty-server.h"
|
||||
|
|
@ -53,6 +53,7 @@ verify_error() {
|
|||
generate_and_compare "code" "example.xml" "example-code.c"
|
||||
generate_and_compare "client-header" "example.xml" "example-client.h"
|
||||
generate_and_compare "server-header" "example.xml" "example-server.h"
|
||||
generate_and_compare "enum-header" "example.xml" "example-enum.h"
|
||||
|
||||
generate_and_compare "code" "small.xml" "small-code.c"
|
||||
generate_and_compare "client-header" "small.xml" "small-client.h"
|
||||
|
|
@ -67,6 +68,10 @@ generate_and_compare "code" "small.xml" "small-code.c"
|
|||
generate_and_compare "public-code" "small.xml" "small-code.c"
|
||||
generate_and_compare "private-code" "small.xml" "small-private-code.c"
|
||||
|
||||
generate_and_compare "code" "empty.xml" "empty-code.c"
|
||||
generate_and_compare "client-header" "empty.xml" "empty-client.h"
|
||||
generate_and_compare "server-header" "empty.xml" "empty-server.h"
|
||||
|
||||
verify_error "bad-identifier-arg.xml" "bad-identifier-arg.log" 7
|
||||
verify_error "bad-identifier-entry.xml" "bad-identifier-entry.log" 8
|
||||
verify_error "bad-identifier-enum.xml" "bad-identifier-enum.log" 6
|
||||
|
|
|
|||
|
|
@ -103,26 +103,23 @@ handle_client_destroy(void *data)
|
|||
{
|
||||
struct client_info *ci = data;
|
||||
struct display *d;
|
||||
siginfo_t status;
|
||||
int status;
|
||||
|
||||
d = ci->display;
|
||||
|
||||
assert(waitid(P_PID, ci->pid, &status, WEXITED) != -1);
|
||||
assert(waitpid(ci->pid, &status, 0) != -1);
|
||||
|
||||
switch (status.si_code) {
|
||||
case CLD_KILLED:
|
||||
case CLD_DUMPED:
|
||||
if (WIFSIGNALED(status)) {
|
||||
fprintf(stderr, "Client '%s' was killed by signal %d\n",
|
||||
ci->name, status.si_status);
|
||||
ci->kill_code = status.si_status;
|
||||
break;
|
||||
case CLD_EXITED:
|
||||
if (status.si_status != EXIT_SUCCESS)
|
||||
fprintf(stderr, "Client '%s' exited with code %d\n",
|
||||
ci->name, status.si_status);
|
||||
ci->name, WTERMSIG(status));
|
||||
ci->kill_code = WTERMSIG(status);
|
||||
|
||||
ci->exit_code = status.si_status;
|
||||
break;
|
||||
} else if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status) != EXIT_SUCCESS)
|
||||
fprintf(stderr, "Client '%s' exited with code %d\n",
|
||||
ci->name, WEXITSTATUS(status));
|
||||
|
||||
ci->exit_code = WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
++d->clients_terminated_no;
|
||||
|
|
@ -510,7 +507,7 @@ static const struct wl_registry_listener registry_listener =
|
|||
NULL
|
||||
};
|
||||
|
||||
struct client *client_connect()
|
||||
struct client *client_connect(void)
|
||||
{
|
||||
struct wl_registry *reg;
|
||||
struct client *c = calloc(1, sizeof *c);
|
||||
|
|
|
|||
|
|
@ -118,5 +118,17 @@ struct client_info *client_create_with_name(struct display *d,
|
|||
void *data,
|
||||
const char *name);
|
||||
#define client_create(d, c, data) client_create_with_name((d), (c), data, (#c))
|
||||
static inline void noarg_cb(void *data)
|
||||
{
|
||||
void (*cb)(void) = data;
|
||||
cb();
|
||||
}
|
||||
static inline struct client_info *client_create_with_name_noarg(struct display *d,
|
||||
void (*client_main)(void),
|
||||
const char *name)
|
||||
{
|
||||
return client_create_with_name(d, noarg_cb, client_main, name);
|
||||
}
|
||||
|
||||
#define client_create_noarg(d, c) \
|
||||
client_create_with_name((d), (void(*)(void *)) (c), NULL, (#c))
|
||||
client_create_with_name_noarg((d), (c), (#c))
|
||||
|
|
|
|||
|
|
@ -61,6 +61,33 @@ count_open_fds(void)
|
|||
assert(error == 0 && "sysctl KERN_PROC_NFDS failed.");
|
||||
return nfds;
|
||||
}
|
||||
#elif defined(__OpenBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
/*
|
||||
* On OpenBSD, get file descriptor information using sysctl()
|
||||
*/
|
||||
int
|
||||
count_open_fds(void)
|
||||
{
|
||||
int error;
|
||||
int mib[6];
|
||||
size_t size;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_FILE;
|
||||
mib[2] = KERN_FILE_BYPID;
|
||||
mib[3] = getpid();
|
||||
mib[4] = sizeof(struct kinfo_file);
|
||||
mib[5] = 0;
|
||||
|
||||
/* find the size required to store all the entries */
|
||||
error = sysctl(mib, 6, NULL, &size, NULL, 0);
|
||||
assert(error != -1 && "sysctl KERN_FILE_BYPID failed.");
|
||||
|
||||
/* return the current number of entries */
|
||||
return size / sizeof(struct kinfo_file);
|
||||
}
|
||||
#else
|
||||
int
|
||||
count_open_fds(void)
|
||||
|
|
|
|||
|
|
@ -308,6 +308,13 @@ is_debugger_attached(void)
|
|||
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
is_debugger_attached(void)
|
||||
{
|
||||
/* 0=debugger can't be determined */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
@ -315,7 +322,7 @@ int main(int argc, char *argv[])
|
|||
const struct test *t;
|
||||
pid_t pid;
|
||||
int total, pass;
|
||||
siginfo_t info;
|
||||
int info;
|
||||
|
||||
if (isatty(fileno(stderr)))
|
||||
is_atty = 1;
|
||||
|
|
@ -358,37 +365,32 @@ int main(int argc, char *argv[])
|
|||
if (pid == 0)
|
||||
run_test(t); /* never returns */
|
||||
|
||||
if (waitid(P_PID, pid, &info, WEXITED)) {
|
||||
if (waitpid(pid, &info, 0) == -1) {
|
||||
stderr_set_color(RED);
|
||||
fprintf(stderr, "waitid failed: %s\n",
|
||||
fprintf(stderr, "waitpid failed: %s\n",
|
||||
strerror(errno));
|
||||
stderr_reset_color();
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
switch (info.si_code) {
|
||||
case CLD_EXITED:
|
||||
if (info.si_status == EXIT_SUCCESS)
|
||||
if (WIFEXITED(info)) {
|
||||
if (WEXITSTATUS(info) == EXIT_SUCCESS)
|
||||
success = !t->must_fail;
|
||||
else
|
||||
success = t->must_fail;
|
||||
|
||||
stderr_set_color(success ? GREEN : RED);
|
||||
fprintf(stderr, "test \"%s\":\texit status %d",
|
||||
t->name, info.si_status);
|
||||
t->name, WEXITSTATUS(info));
|
||||
|
||||
break;
|
||||
case CLD_KILLED:
|
||||
case CLD_DUMPED:
|
||||
} else if (WIFSIGNALED(info)) {
|
||||
if (t->must_fail)
|
||||
success = 1;
|
||||
|
||||
stderr_set_color(success ? GREEN : RED);
|
||||
fprintf(stderr, "test \"%s\":\tsignal %d",
|
||||
t->name, info.si_status);
|
||||
|
||||
break;
|
||||
t->name, WTERMSIG(info));
|
||||
}
|
||||
|
||||
if (success) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue