mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Compare commits
13 commits
1da164cd9f
...
7d5c30246a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d5c30246a | ||
|
|
d81525a235 | ||
|
|
4673ef7e9c | ||
|
|
77730f10a0 | ||
|
|
264da6a92b | ||
|
|
cd0d1543c0 | ||
|
|
3ea4b30700 | ||
|
|
bd0aa37eb9 | ||
|
|
2bd88ca4bf | ||
|
|
ac630dd3b4 | ||
|
|
568a9325f0 | ||
|
|
f00586ee5f | ||
|
|
9e9de6c9cd |
9 changed files with 366 additions and 37 deletions
|
|
@ -43,7 +43,7 @@ include:
|
|||
# API changes. If you need new features from ci-templates you must bump
|
||||
# this to the current SHA you require from the ci-templates repo, however
|
||||
# be aware that you may need to account for API changes when doing so.
|
||||
ref: 32afe5644697e503af18a736587c8619fa036a72
|
||||
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: "14.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: "2025-06-23.1"
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
219
src/connection.c
219
src/connection.c
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -91,19 +93,45 @@ ring_buffer_mask(const struct wl_ring_buffer *b, size_t i) {
|
|||
return i & m;
|
||||
}
|
||||
|
||||
static size_t
|
||||
ring_buffer_size(struct wl_ring_buffer *b)
|
||||
{
|
||||
return b->head - b->tail;
|
||||
}
|
||||
|
||||
/* Precondition: the data will not overflow the buffer */
|
||||
static int
|
||||
ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
|
||||
{
|
||||
size_t head, size;
|
||||
size_t head, size, buffer_size, capacity;
|
||||
|
||||
if (b->head < b->tail) {
|
||||
wl_abort("ring_buffer_put: ring buffer corrupt, %zu < %zu\n",
|
||||
b->head, b->tail);
|
||||
}
|
||||
|
||||
capacity = ring_buffer_capacity(b);
|
||||
buffer_size = ring_buffer_size(b);
|
||||
if (buffer_size > capacity) {
|
||||
wl_abort("ring_buffer_put: ring buffer corrupt: "
|
||||
"%zu - %zu > %zu\n", b->head, b->tail, capacity);
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
if (capacity - buffer_size < count) {
|
||||
wl_abort("ring_buffer_put: attempt to overfill buffer: "
|
||||
"%zu - %zu < %zu\n", capacity, buffer_size, count);
|
||||
}
|
||||
|
||||
head = ring_buffer_mask(b, b->head);
|
||||
if (head + count <= ring_buffer_capacity(b)) {
|
||||
size = capacity - head;
|
||||
if (count <= size) {
|
||||
/* Enough space after head to fulfill request */
|
||||
memcpy(b->data + head, data, count);
|
||||
} else {
|
||||
size = ring_buffer_capacity(b) - head;
|
||||
/* Need to wrap around */
|
||||
memcpy(b->data + head, data, size);
|
||||
memcpy(b->data, (const char *) data + size, count - size);
|
||||
}
|
||||
|
|
@ -113,78 +141,160 @@ ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Precondition: the buffer is not full */
|
||||
static void
|
||||
ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
|
||||
{
|
||||
size_t head, tail;
|
||||
size_t head, tail, size, capacity;
|
||||
|
||||
if (b->head < b->tail) {
|
||||
wl_abort("ring_buffer_put_iov: ring buffer corrupt, %zu < %zu\n",
|
||||
b->head, b->tail);
|
||||
}
|
||||
|
||||
size = ring_buffer_size(b);
|
||||
capacity = ring_buffer_capacity(b);
|
||||
if (size >= capacity) {
|
||||
wl_abort("ring_buffer_put_iov: ring buffer full or corrupt: "
|
||||
"%zu - %zu >= %zu\n", b->head, b->tail, capacity);
|
||||
}
|
||||
|
||||
head = ring_buffer_mask(b, b->head);
|
||||
tail = ring_buffer_mask(b, b->tail);
|
||||
if (head < tail) {
|
||||
/* Buffer is like this:
|
||||
* head tail
|
||||
* | |
|
||||
* +---------+-----------------+---------+
|
||||
* | VALID | INVALID | VALID |
|
||||
* +---------+-----------------+---------+
|
||||
*/
|
||||
iov[0].iov_base = b->data + head;
|
||||
iov[0].iov_len = tail - head;
|
||||
*count = 1;
|
||||
} else if (tail == 0) {
|
||||
/* Buffer is like this:
|
||||
* tail head
|
||||
* | |
|
||||
* +---------------------------+---------+
|
||||
* | VALID | INVALID |
|
||||
* +---------------------------+---------+
|
||||
*/
|
||||
iov[0].iov_base = b->data + head;
|
||||
iov[0].iov_len = ring_buffer_capacity(b) - head;
|
||||
iov[0].iov_len = capacity - head;
|
||||
*count = 1;
|
||||
} else {
|
||||
/* Buffer is like this:
|
||||
* tail head
|
||||
* | |
|
||||
* +---------------------------+---------+
|
||||
* | INVALID | VALID | INVALID |
|
||||
* +---------------------------+---------+
|
||||
*/
|
||||
iov[0].iov_base = b->data + head;
|
||||
iov[0].iov_len = ring_buffer_capacity(b) - head;
|
||||
iov[0].iov_len = capacity - head;
|
||||
iov[1].iov_base = b->data;
|
||||
iov[1].iov_len = tail;
|
||||
*count = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Precondition: the buffer is not empty */
|
||||
static void
|
||||
ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
|
||||
{
|
||||
size_t head, tail;
|
||||
size_t head, tail, capacity;
|
||||
|
||||
if (b->head <= b->tail) {
|
||||
wl_abort("ring_buffer_get_iov(): empty or corrupt buffer: %zu <= %zu\n",
|
||||
b->head, b->tail);
|
||||
}
|
||||
|
||||
capacity = ring_buffer_capacity(b);
|
||||
if (ring_buffer_size(b) > capacity) {
|
||||
wl_abort("ring_buffer_put_iov: ring buffer corrupt: "
|
||||
"%zu - %zu > %zu\n", b->head, b->tail, capacity);
|
||||
}
|
||||
|
||||
head = ring_buffer_mask(b, b->head);
|
||||
tail = ring_buffer_mask(b, b->tail);
|
||||
if (tail < head) {
|
||||
/* Buffer is like this:
|
||||
* tail head
|
||||
* | |
|
||||
* +---------+-----------------+---------+
|
||||
* | INVALID | VALID | INVALID |
|
||||
* +---------+-----------------+---------+
|
||||
*/
|
||||
iov[0].iov_base = b->data + tail;
|
||||
iov[0].iov_len = head - tail;
|
||||
*count = 1;
|
||||
} else if (head == 0) {
|
||||
/* Buffer is like this:
|
||||
* head tail
|
||||
* | |
|
||||
* +---------------------------+---------+
|
||||
* | INVALID | VALID |
|
||||
* +---------------------------+---------+
|
||||
*/
|
||||
iov[0].iov_base = b->data + tail;
|
||||
iov[0].iov_len = ring_buffer_capacity(b) - tail;
|
||||
iov[0].iov_len = capacity - tail;
|
||||
*count = 1;
|
||||
} else {
|
||||
/* Buffer is like this:
|
||||
* head tail
|
||||
* | |
|
||||
* +-------+-------------------+---------+
|
||||
* | VALID | INVALID | VALID |
|
||||
* +---------------------------+---------+
|
||||
*/
|
||||
iov[0].iov_base = b->data + tail;
|
||||
iov[0].iov_len = ring_buffer_capacity(b) - tail;
|
||||
iov[0].iov_len = capacity - tail;
|
||||
iov[1].iov_base = b->data;
|
||||
iov[1].iov_len = head;
|
||||
*count = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Precondition: the data will not underflow the buffer */
|
||||
static void
|
||||
ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count)
|
||||
{
|
||||
size_t tail, size;
|
||||
size_t tail, size, buffer_size, capacity;
|
||||
|
||||
if (b->head < b->tail) {
|
||||
wl_abort("ring_buffer_copy(): ring buffer corrupt, %zu < %zu\n",
|
||||
b->head, b->tail);
|
||||
}
|
||||
|
||||
buffer_size = ring_buffer_size(b);
|
||||
capacity = ring_buffer_capacity(b);
|
||||
if (buffer_size > capacity) {
|
||||
wl_abort("ring_buffer_copy(): ring buffer corrupt: "
|
||||
"%zu - %zu > %zu\n", b->head, b->tail, capacity);
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
if (buffer_size < count) {
|
||||
wl_abort("ring_buffer_copy(): attempt to copy %zu bytes "
|
||||
"but buffer has %zu bytes\n",
|
||||
count, buffer_size);
|
||||
}
|
||||
|
||||
tail = ring_buffer_mask(b, b->tail);
|
||||
if (tail + count <= ring_buffer_capacity(b)) {
|
||||
size = capacity - tail;
|
||||
if (count <= size) {
|
||||
/* Enough data after the tail to fulfill the request */
|
||||
memcpy(data, b->data + tail, count);
|
||||
} else {
|
||||
size = ring_buffer_capacity(b) - tail;
|
||||
/* Must wrap buffer around */
|
||||
memcpy(data, b->data + tail, size);
|
||||
memcpy((char *) data + size, b->data, count - size);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
ring_buffer_size(struct wl_ring_buffer *b)
|
||||
{
|
||||
return b->head - b->tail;
|
||||
}
|
||||
|
||||
static char *
|
||||
ring_buffer_tail(const struct wl_ring_buffer *b)
|
||||
{
|
||||
|
|
@ -413,7 +523,7 @@ decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
|
|||
{
|
||||
struct cmsghdr *cmsg;
|
||||
size_t size, i;
|
||||
int overflow = 0;
|
||||
bool overflow = false;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
|
|
@ -424,7 +534,7 @@ decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
|
|||
size = cmsg->cmsg_len - CMSG_LEN(0);
|
||||
|
||||
if (ring_buffer_ensure_space(buffer, size) < 0 || overflow) {
|
||||
overflow = 1;
|
||||
overflow = true;
|
||||
size /= sizeof(int32_t);
|
||||
for (i = 0; i < size; i++)
|
||||
close(((int*)CMSG_DATA(cmsg))[i]);
|
||||
|
|
@ -456,6 +566,9 @@ wl_connection_flush(struct wl_connection *connection)
|
|||
|
||||
tail = connection->out.tail;
|
||||
while (ring_buffer_size(&connection->out) > 0) {
|
||||
/* Ring buffer is not empty, so this is safe. */
|
||||
ring_buffer_get_iov(&connection->out, iov, &count);
|
||||
|
||||
build_cmsg(&connection->fds_out, cmsg, &clen);
|
||||
|
||||
if (clen >= CLEN) {
|
||||
|
|
@ -530,6 +643,7 @@ wl_connection_read(struct wl_connection *connection)
|
|||
if (ring_buffer_ensure_space(&connection->in, 1) < 0)
|
||||
return -1;
|
||||
|
||||
/* Ring buffer is not full, so this is safe. */
|
||||
ring_buffer_put_iov(&connection->in, iov, &count);
|
||||
|
||||
msg.msg_name = NULL;
|
||||
|
|
@ -683,6 +797,7 @@ wl_message_get_since(const struct wl_message *message)
|
|||
{
|
||||
int since;
|
||||
|
||||
/* This is trusted input */
|
||||
since = atoi(message->signature);
|
||||
|
||||
if (since == 0)
|
||||
|
|
@ -950,14 +1065,14 @@ wl_connection_demarshal(struct wl_connection *connection,
|
|||
case WL_ARG_STRING:
|
||||
length = *p++;
|
||||
|
||||
if (length == 0 && !arg.nullable) {
|
||||
if (length == 0) {
|
||||
if (!arg.nullable) {
|
||||
wl_log("NULL string received on non-nullable "
|
||||
"type, message %s(%s)\n", message->name,
|
||||
message->signature);
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (length == 0) {
|
||||
closure->args[i].s = NULL;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1060,7 +1175,10 @@ wl_connection_demarshal(struct wl_connection *connection,
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* This ring buffer will always have a multiple of sizeof(int)
|
||||
* bytes in it. */
|
||||
ring_buffer_copy(&connection->fds_in, &fd, sizeof fd);
|
||||
/* This can wrap but that is okay. */
|
||||
connection->fds_in.tail += sizeof fd;
|
||||
closure->args[i].h = fd;
|
||||
break;
|
||||
|
|
@ -1491,11 +1609,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 +1679,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 : "",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1882,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
|
||||
|
|
@ -2212,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
|
||||
|
|
@ -2272,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
|
||||
|
|
|
|||
|
|
@ -237,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,
|
||||
|
|
|
|||
|
|
@ -740,8 +740,7 @@ wl_client_post_implementation_error(struct wl_client *client,
|
|||
WL_EXPORT void
|
||||
wl_resource_post_no_memory(struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_post_error(resource->client->display_resource,
|
||||
WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
|
||||
wl_client_post_no_memory(resource->client);
|
||||
}
|
||||
|
||||
/** Detect if a wl_resource uses the deprecated public definition.
|
||||
|
|
@ -1198,7 +1197,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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue