Compare commits

...

11 commits

Author SHA1 Message Date
Lu YaNing
69a4b80dfa protocol: add wl_pointer.warp event
The original wl_pointer.button event does not contain the position information.
In some scenarios, the client cannot obtain the correct position information.
For example, when the mouse focus is on a button and the mouse does not move
but the window size changes, the client cannot update the position information
through the motion event, resulting in incorrect mouse position.

Therefore, This event should be sent when the local coordinates of a pointer
change as a result of surface being moved/resized/fullscreened.

Signed-off-by: Lu YaNing <luyaning@uniontech.com>
2025-10-16 10:22:34 +08:00
Daniel Stone
c626ab736c NOTE! Default branch is now main
To update your local repository to use the new default branch, these
commands may help:

$ git fetch origin
$ git checkout master
$ git branch -m main
$ git branch --set-upstream-to=origin/main

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 10:22:34 +08:00
Isaac Freund
d81525a235 client: add wl_display_dispatch_pending_single
As well as wl_display_dispatch_queue_pending_single.

The motivation is writing libwayland bindings for a dynamic language
with exceptions/non-local returns. Since it is invalid for a
wl_dispatcher_func_t callback provided to libwayland to not return,
there is no way to prevent dispatching of further events in the case of
an exception in the dynamic language event handler.

Furthermore, since creating/destroying Wayland objects in an event
handler affects the dispatching of subsequent events by libwayland,
it is not possible to collect Wayland events in a queue outside
libwayland and dispatch them one-by-one after
wl_display_dispatch_pending() returns.

Adding libwayland API to dispatch at most one pending event solves this
problem cleanly. The bindings can have libwayland dispatch a single
event, wait for wl_display_dispatch_pending_single() to return, run the
dynamic language event handler (which may longjmp away), and continue
the loop for as long as there are more events to dispatch.

References: https://codeberg.org/ifreund/janet-wayland
Signed-off-by: Isaac Freund <mail@isaacfreund.com>
2025-09-16 11:48:33 +03:00
Kyle Brenneman
4673ef7e9c connection: Add a thread ID to WAYLAND_DEBUG output.
If WAYLAND_DEBUG contains the token "thread_id", and gettid() is
available, then include the current thread ID in the output from
wl_closure_print.

If multiple threads are sending requests, then those requests can get
interleaved. That's usually fine, but for wl_surface requests and
commits, that can cause problems ranging from incorrect behavior to
protocol errors.

Being able to see which requests are sent by different threads would
make such problems much easier to diagnose.

Signed-off-by: Kyle Brenneman <kbrenneman@nvidia.com>
2025-09-15 14:45:53 +01:00
Kyle Brenneman
77730f10a0 connection: Add a function to parse WAYLAND_DEBUG tokens
Add a new function, wl_check_env_token, to scan for a token in a
comma-separated string.

Change wl_display_create in wayland-server.c and
wl_display_connect_to_fd in wayland-client.c to use that instead of a
simple substring search.

This means that WAYLAND_DEBUG will accept a value like "client,server"
but not "clientserver". But, this will make it easier to add other
tokens without worrying about overlap between them.

Signed-off-by: Kyle Brenneman <kbrenneman@nvidia.com>
2025-09-15 14:45:53 +01:00
YaoBing Xiao
264da6a92b cursor: Free theme when size check fails to avoid memory leak
Signed-off-by: YaoBing Xiao <xiaoyaobing@uniontech.com>
2025-08-03 11:36:34 +00:00
ykla
cd0d1543c0 ci: upgrade FreeBSD to 14.3
Signed-off-by: ykla yklaxds@gmail.com
2025-07-20 02:09:35 +00:00
ykla
90187031e6
ci: upgrade FreeBSD to 14.2
Signed-off-by: ykla <yklaxds@gmail.com>
2025-06-25 07:18:28 +08:00
Simon Ser
eecf3f7635 build: re-open main branch for regular development
Signed-off-by: Simon Ser <contact@emersion.fr>
2025-06-21 13:38:28 +02:00
Demi Marie Obenour
adf84614ca connection: Do not busy-loop if a message exceeds the buffer size
If the length of a message exceeds the maximum length of the buffer, the
buffer size will reach its maximum value and stay there forever, with no
message ever being successfully processed.  Since libwayland uses
level-triggered epoll, this will cause the compositor to loop forever
and consume CPU time.  In libwayland 1.22 and below, there was an
explicit check that caused messages exceeding 4096 bytes to result in an
EOVERFLOW error, preventing the loop.  However, this check was removed
between d074d52902 ("connection: Dynamically resize connection buffers").

To prevent this problem, always limit the size of messages to 4096 bytes.
Since the default and minimum buffer size is 4096 bytes, this ensures
that a single message will always fit in the buffer.  It would be
possible to allow larger messages if the buffer size was larger, but the
maximum size of a message should not depend on the buffer size chosen by
the compositor.

Rejecting messages that exceed 4092 bytes seems to have the advantage of
reserving 4 bits, not 3, in the size field for future use.  However,
message sizes in the range [0x0, 0x7] are invalid, so one can obtain a
fourth bit by negating the meaning of bit 12 if bits 0 through 11
(inclusive) are 0.  Allowing 4096-byte messages provides the far more
important advantage that regressions compared to 1.22 are impossible
and regressions compared to 1.23 are extremely unlikely.  The only case
where a regression is possible is:

- The receiving side is using libwayland 1.23.
- The sending side is either using libwayland 1.23 or is not using
  libwayland.
- The sender sends a message exceeding 4096 bytes.
- If the sender of the large message is the client, the server has
  increased the buffer size from the default value.

This combination is considered extremely unlikely, as libwayland 1.22
and below would disconnect upon receiving such a large message.
4096-byte messages, however, have always worked, so there was no reason
to avoid sending them.

Fixes: d074d52902 ("connection: Dynamically resize connection buffers").
Fixes: #494
Signed-off-by: Demi Marie Obenour <demi@invisiblethingslab.com>
2025-06-21 11:29:04 +00:00
Pekka Paalanen
ba9f9a446f doc: add a section on color management
I think the docbook deserves an introduction to how color management is
designed in Wayland, aimed at people who are familiar with pixels but
new to the topic.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-12 14:37:32 +03:00
14 changed files with 447 additions and 14 deletions

View file

@ -43,7 +43,7 @@ include:
# API changes. If you need new features from ci-templates you must bump
# this to the current SHA you require from the ci-templates repo, however
# be aware that you may need to account for API changes when doing so.
ref: f210ea84576f756816da37908771edcee14ef7e6
ref: 48c2c583a865bd59be21e8938df247faf460099c
file:
- '/templates/debian.yml'
- '/templates/freebsd.yml'
@ -306,11 +306,11 @@ armv7-release-debian-build:
.os-freebsd:
variables:
BUILD_OS: freebsd
FDO_DISTRIBUTION_VERSION: "13.2"
FDO_DISTRIBUTION_VERSION: "14.3"
FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2'
# bump this tag every time you change something which requires rebuilding the
# base image
FDO_DISTRIBUTION_TAG: "2023-08-02.0"
FDO_DISTRIBUTION_TAG: "2025-07-20.0"
# Don't build documentation since installing the required tools massively
# increases the VM image (and therefore container) size.
MESON_ARGS: "--fatal-meson-warnings -Dwerror=true -Ddocumentation=false"

View file

@ -398,7 +398,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
return NULL;
if (size < 0 || (size > 0 && INT_MAX / size / 4 < size))
return NULL;
goto err;
if (!name)
name = "default";
@ -409,7 +409,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
theme->pool = shm_pool_create(shm, size * size * 4);
if (!theme->pool)
goto out_error_pool;
goto err;
xcursor_load_theme(name, size, load_callback, theme);
@ -421,7 +421,7 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
return theme;
out_error_pool:
err:
free(theme);
return NULL;
}

View 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>

View file

@ -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"/>

View file

@ -54,6 +54,7 @@ publican_sources = [
'Protocol.xml',
'Xwayland.xml',
'Compositors.xml',
'Color.xml',
'Client.xml',
'Server.xml'
]

View file

@ -1,6 +1,6 @@
project(
'wayland', 'c',
version: '1.23.91',
version: '1.24.90',
license: 'MIT',
meson_version: '>= 0.57.0',
default_options: [
@ -46,6 +46,7 @@ have_funcs = [
'memfd_create',
'mremap',
'strndup',
'gettid',
]
foreach f: have_funcs
config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))

View file

@ -1886,7 +1886,7 @@
</event>
</interface>
<interface name="wl_seat" version="10">
<interface name="wl_seat" version="11">
<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
@ -2020,7 +2020,7 @@
</interface>
<interface name="wl_pointer" version="10">
<interface name="wl_pointer" version="11">
<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
@ -2130,8 +2130,9 @@
<description summary="pointer button event">
Mouse button click and release notifications.
The location of the click is given by the last motion or
The location of the click is given by the last motion, warp or
enter event.
The time argument is a timestamp with millisecond
granularity, with an undefined base.
@ -2431,9 +2432,30 @@
<arg name="direction" type="uint" enum="axis_relative_direction"
summary="physical direction relative to axis motion"/>
</event>
<!-- Version 11 additions -->
<event name="warp" since="11">
<description summary="pointer warp event">
Notification of pointer location change within a surface.
This location change is not due to events on the input device,
but because either the surface under the pointer was moved and
thus the relative position of the pointer changed, or because
the compositor changed the pointer position in response to
an event like pointer confinement being exited. The arguments
surface_x and surface_y are the location relative to the
focused surface.
This event must not occur in the same wl_pointer.frame as a
wl_pointer.enter or wl_pointer.motion event.
</description>
<arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
<arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
</event>
</interface>
<interface name="wl_keyboard" version="10">
<interface name="wl_keyboard" version="11">
<description summary="keyboard input device">
The wl_keyboard interface represents one or more keyboards
associated with a seat.
@ -2614,7 +2636,7 @@
</event>
</interface>
<interface name="wl_touch" version="10">
<interface name="wl_touch" version="11">
<description summary="touchscreen input device">
The wl_touch interface represents a touchscreen
associated with a seat.

View file

@ -26,6 +26,8 @@
#define _GNU_SOURCE
#include "../config.h"
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
@ -1491,11 +1493,56 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
return result;
}
bool
wl_check_env_token(const char *env, const char *token)
{
const char *ptr = env;
size_t token_len;
if (env == NULL)
return false;
token_len = strlen(token);
// Scan the string for comma-separated tokens and look for a match.
while (true) {
const char *end;
size_t len;
// Skip over any leading separators.
while (*ptr == ',')
ptr++;
if (*ptr == '\x00')
return false;
end = strchr(ptr + 1, ',');
// If there isn't another separarator, then the rest of the string
// is one token.
if (end == NULL)
return (strcmp(ptr, token) == 0);
len = end - ptr;
if (len == token_len && memcmp(ptr, token, len) == 0) {
return true;
}
// Skip to the next token.
ptr += len;
}
return false;
}
void
wl_closure_print(struct wl_closure *closure, struct wl_object *target,
int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg),
const char *queue_name, int color)
{
#if defined(HAVE_GETTID)
static int include_tid = -1;
#endif // defined(HAVE_GETTID)
int i;
struct argument_details arg;
const char *signature = closure->message->signature;
@ -1516,6 +1563,18 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target,
color ? WL_DEBUG_COLOR_GREEN : "",
time / 1000, time % 1000);
#if defined(HAVE_GETTID)
if (include_tid < 0) {
include_tid = wl_check_env_token(getenv("WAYLAND_DEBUG"), "thread_id");
}
if (include_tid) {
fprintf(f, "%sTID#%d ",
color ? WL_DEBUG_COLOR_CYAN : "",
(int) gettid());
}
#endif
if (queue_name) {
fprintf(f, "%s{%s} ",
color ? WL_DEBUG_COLOR_YELLOW : "",

View file

@ -268,9 +268,16 @@ int
wl_display_dispatch_queue_pending(struct wl_display *display,
struct wl_event_queue *queue);
int
wl_display_dispatch_queue_pending_single(struct wl_display *display,
struct wl_event_queue *queue);
int
wl_display_dispatch_pending(struct wl_display *display);
int
wl_display_dispatch_pending_single(struct wl_display *display);
int
wl_display_get_error(struct wl_display *display);

View file

@ -1236,7 +1236,7 @@ wl_display_connect_to_fd(int fd)
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;
@ -1578,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;
@ -1860,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
@ -2190,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
@ -2250,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

View file

@ -49,6 +49,9 @@
#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"
@ -234,6 +237,9 @@ 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,

View file

@ -398,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;
@ -1175,7 +1198,7 @@ wl_display_create(void)
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;

View file

@ -90,6 +90,14 @@ extern "C" {
*/
struct wl_object;
/**
* The maximum size of a protocol message.
*
* If a message size exceeds this value, the connection will be dropped.
* Servers will send an invalid_method error before disconnecting.
*/
#define WL_MAX_MESSAGE_SIZE 4096
/**
* Protocol message signature
*

View file

@ -1695,6 +1695,75 @@ TEST(global_remove)
display_destroy(d);
}
static void
dispatch_single_read_events(struct wl_display *d)
{
if (wl_display_prepare_read(d) < 0) {
return;
}
int ret = 0;
do {
ret = wl_display_flush(d);
} while (ret < 0 && (errno == EINTR || errno == EAGAIN));
assert(ret >= 0);
struct pollfd pfd[1];
pfd[0].fd = wl_display_get_fd(d);
pfd[0].events = POLLIN;
do {
ret = poll(pfd, 1, -1);
} while (ret < 0 && errno == EINTR);
assert(ret > 0);
wl_display_read_events(d);
}
static void
dispatch_single_client(void)
{
struct client *c = client_connect();
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
struct wl_registry *registry = wl_display_get_registry(c->wl_display);
dispatch_single_read_events(c->wl_display);
// [1815110.061] {Default Queue} wl_registry#3.global(1, "test", 1)
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
dispatch_single_read_events(c->wl_display);
// [1815110.067] {Default Queue} wl_registry#3.global(2, "wl_seat", 1)
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
// No more events
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
wl_registry_destroy(registry);
client_disconnect(c);
}
TEST(dispatch_single)
{
struct display *d = display_create();
struct wl_global *global = wl_global_create(d->wl_display,
&wl_seat_interface,
1, d, bind_seat);
client_create_noarg(d, dispatch_single_client);
display_run(d);
wl_global_destroy(global);
display_destroy(d);
}
static void
terminate_display(void *arg)
{