mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Compare commits
3 commits
1b34f6a192
...
e6f39b7082
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6f39b7082 | ||
|
|
d81525a235 | ||
|
|
3872a9362e |
7 changed files with 346 additions and 57 deletions
|
|
@ -268,9 +268,16 @@ int
|
||||||
wl_display_dispatch_queue_pending(struct wl_display *display,
|
wl_display_dispatch_queue_pending(struct wl_display *display,
|
||||||
struct wl_event_queue *queue);
|
struct wl_event_queue *queue);
|
||||||
|
|
||||||
|
int
|
||||||
|
wl_display_dispatch_queue_pending_single(struct wl_display *display,
|
||||||
|
struct wl_event_queue *queue);
|
||||||
|
|
||||||
int
|
int
|
||||||
wl_display_dispatch_pending(struct wl_display *display);
|
wl_display_dispatch_pending(struct wl_display *display);
|
||||||
|
|
||||||
|
int
|
||||||
|
wl_display_dispatch_pending_single(struct wl_display *display);
|
||||||
|
|
||||||
int
|
int
|
||||||
wl_display_get_error(struct wl_display *display);
|
wl_display_get_error(struct wl_display *display);
|
||||||
|
|
||||||
|
|
|
||||||
83
src/wayland-client-private.h
Normal file
83
src/wayland-client-private.h
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2008-2012 Kristian Høgsberg
|
||||||
|
* Copyright © 2010-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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Struct definintions shared by the client code and test suite. */
|
||||||
|
|
||||||
|
/** \cond */
|
||||||
|
|
||||||
|
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_proxy {
|
||||||
|
struct wl_object object;
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_event_queue *queue;
|
||||||
|
uint32_t flags;
|
||||||
|
int refcount;
|
||||||
|
void *user_data;
|
||||||
|
wl_dispatcher_func_t dispatcher;
|
||||||
|
uint32_t version;
|
||||||
|
const char * const *tag;
|
||||||
|
struct wl_list queue_link; /**< in struct wl_event_queue::proxy_list */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wl_display {
|
||||||
|
struct wl_proxy proxy;
|
||||||
|
struct wl_connection *connection;
|
||||||
|
|
||||||
|
/* errno of the last wl_display error */
|
||||||
|
int last_error;
|
||||||
|
|
||||||
|
/* When display gets an error event from some object, it stores
|
||||||
|
* information about it here, so that client can get this
|
||||||
|
* information afterwards */
|
||||||
|
struct {
|
||||||
|
/* Code of the error. It can be compared to
|
||||||
|
* the interface's errors enumeration. */
|
||||||
|
uint32_t code;
|
||||||
|
/* interface (protocol) in which the error occurred */
|
||||||
|
const struct wl_interface *interface;
|
||||||
|
/* id of the proxy that caused the error. There's no warranty
|
||||||
|
* that the proxy is still valid. It's up to client how it will
|
||||||
|
* use it */
|
||||||
|
uint32_t id;
|
||||||
|
} protocol_error;
|
||||||
|
int fd;
|
||||||
|
struct wl_map objects;
|
||||||
|
struct wl_event_queue display_queue;
|
||||||
|
struct wl_event_queue default_queue;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
int reader_count;
|
||||||
|
uint32_t read_serial;
|
||||||
|
pthread_cond_t reader_cond;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \endcond */
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
#include "wayland-client.h"
|
#include "wayland-client.h"
|
||||||
#include "wayland-private.h"
|
#include "wayland-private.h"
|
||||||
#include "timespec-util.h"
|
#include "timespec-util.h"
|
||||||
|
#include "wayland-client-private.h"
|
||||||
|
|
||||||
/** \cond */
|
/** \cond */
|
||||||
|
|
||||||
|
|
@ -60,58 +61,6 @@ struct wl_zombie {
|
||||||
int *fd_count;
|
int *fd_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wl_proxy {
|
|
||||||
struct wl_object object;
|
|
||||||
struct wl_display *display;
|
|
||||||
struct wl_event_queue *queue;
|
|
||||||
uint32_t flags;
|
|
||||||
int refcount;
|
|
||||||
void *user_data;
|
|
||||||
wl_dispatcher_func_t dispatcher;
|
|
||||||
uint32_t version;
|
|
||||||
const char * const *tag;
|
|
||||||
struct wl_list queue_link; /**< in struct wl_event_queue::proxy_list */
|
|
||||||
};
|
|
||||||
|
|
||||||
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 {
|
|
||||||
struct wl_proxy proxy;
|
|
||||||
struct wl_connection *connection;
|
|
||||||
|
|
||||||
/* errno of the last wl_display error */
|
|
||||||
int last_error;
|
|
||||||
|
|
||||||
/* When display gets an error event from some object, it stores
|
|
||||||
* information about it here, so that client can get this
|
|
||||||
* information afterwards */
|
|
||||||
struct {
|
|
||||||
/* Code of the error. It can be compared to
|
|
||||||
* the interface's errors enumeration. */
|
|
||||||
uint32_t code;
|
|
||||||
/* interface (protocol) in which the error occurred */
|
|
||||||
const struct wl_interface *interface;
|
|
||||||
/* id of the proxy that caused the error. There's no warranty
|
|
||||||
* that the proxy is still valid. It's up to client how it will
|
|
||||||
* use it */
|
|
||||||
uint32_t id;
|
|
||||||
} protocol_error;
|
|
||||||
int fd;
|
|
||||||
struct wl_map objects;
|
|
||||||
struct wl_event_queue display_queue;
|
|
||||||
struct wl_event_queue default_queue;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
|
|
||||||
int reader_count;
|
|
||||||
uint32_t read_serial;
|
|
||||||
pthread_cond_t reader_cond;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \endcond */
|
/** \endcond */
|
||||||
|
|
||||||
static int debug_client = 0;
|
static int debug_client = 0;
|
||||||
|
|
@ -1882,6 +1831,34 @@ err:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
dispatch_queue_single(struct wl_display *display, struct wl_event_queue *queue)
|
||||||
|
{
|
||||||
|
if (display->last_error)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while (!wl_list_empty(&display->display_queue.event_list)) {
|
||||||
|
dispatch_event(display, &display->display_queue);
|
||||||
|
if (display->last_error)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wl_list_empty(&queue->event_list)) {
|
||||||
|
dispatch_event(display, queue);
|
||||||
|
if (display->last_error)
|
||||||
|
goto err;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
errno = display->last_error;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/** Prepare to read events from the display's file descriptor to a queue
|
/** Prepare to read events from the display's file descriptor to a queue
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
@ -2212,6 +2189,34 @@ wl_display_dispatch_queue_pending(struct wl_display *display,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Dispatch at most one pending event in an event queue
|
||||||
|
*
|
||||||
|
* \param display The display context object
|
||||||
|
* \param queue The event queue to dispatch
|
||||||
|
* \return The number of dispatched events (0 or 1) on success or -1 on failure
|
||||||
|
*
|
||||||
|
* Dispatch at most one pending event for objects assigned to the given
|
||||||
|
* event queue. On failure -1 is returned and errno set appropriately.
|
||||||
|
* If there are no events queued, this function returns immediately.
|
||||||
|
*
|
||||||
|
* \memberof wl_display
|
||||||
|
* \since 1.25.0
|
||||||
|
*/
|
||||||
|
WL_EXPORT int
|
||||||
|
wl_display_dispatch_queue_pending_single(struct wl_display *display,
|
||||||
|
struct wl_event_queue *queue)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&display->mutex);
|
||||||
|
|
||||||
|
ret = dispatch_queue_single(display, queue);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&display->mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/** Process incoming events
|
/** Process incoming events
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
@ -2272,6 +2277,25 @@ wl_display_dispatch_pending(struct wl_display *display)
|
||||||
&display->default_queue);
|
&display->default_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Dispatch at most one pending event in the default event queue.
|
||||||
|
*
|
||||||
|
* \param display The display context object
|
||||||
|
* \return The number of dispatched events (0 or 1) on success or -1 on failure
|
||||||
|
*
|
||||||
|
* Dispatch at most one pending event for objects assigned to the default
|
||||||
|
* event queue. On failure -1 is returned and errno set appropriately.
|
||||||
|
* If there are no events queued, this function returns immediately.
|
||||||
|
*
|
||||||
|
* \memberof wl_display
|
||||||
|
* \since 1.25.0
|
||||||
|
*/
|
||||||
|
WL_EXPORT int
|
||||||
|
wl_display_dispatch_pending_single(struct wl_display *display)
|
||||||
|
{
|
||||||
|
return wl_display_dispatch_queue_pending_single(display,
|
||||||
|
&display->default_queue);
|
||||||
|
}
|
||||||
|
|
||||||
/** Retrieve the last error that occurred on a display
|
/** Retrieve the last error that occurred on a display
|
||||||
*
|
*
|
||||||
* \param display The display context object
|
* \param display The display context object
|
||||||
|
|
|
||||||
|
|
@ -807,6 +807,51 @@ leak_after_error(void)
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
too_long_message(void *arg)
|
||||||
|
{
|
||||||
|
#define TOO_LONG ((size_t)(4096 - 12 + 1))
|
||||||
|
void *buf = malloc(TOO_LONG);
|
||||||
|
assert(buf);
|
||||||
|
memset(buf, 0, TOO_LONG);
|
||||||
|
struct client *c = client_connect();
|
||||||
|
struct wl_array arr = { TOO_LONG - 1, TOO_LONG, buf };
|
||||||
|
set_buffer_size(c, *(uint32_t *)arg);
|
||||||
|
long_request(c, &arr);
|
||||||
|
wl_display_roundtrip(c->wl_display);
|
||||||
|
assert(wl_display_get_error(c->wl_display) == 0);
|
||||||
|
arr.size += 1;
|
||||||
|
long_request(c, &arr);
|
||||||
|
wl_display_dispatch(c->wl_display);
|
||||||
|
assert(wl_display_get_error(c->wl_display) == EINVAL);
|
||||||
|
wl_proxy_destroy((struct wl_proxy *) c->tc);
|
||||||
|
wl_display_disconnect(c->wl_display);
|
||||||
|
free(c);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(overlong_message_small_buffer)
|
||||||
|
{
|
||||||
|
struct display *d = display_create();
|
||||||
|
|
||||||
|
uint32_t size = 4096;
|
||||||
|
client_create(d, too_long_message, &size);
|
||||||
|
display_run(d);
|
||||||
|
|
||||||
|
display_destroy(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(overlong_message_long_buffer)
|
||||||
|
{
|
||||||
|
struct display *d = display_create();
|
||||||
|
|
||||||
|
uint32_t size = 8192;
|
||||||
|
client_create(d, too_long_message, &size);
|
||||||
|
display_run(d);
|
||||||
|
|
||||||
|
display_destroy(d);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(closure_leaks_after_error)
|
TEST(closure_leaks_after_error)
|
||||||
{
|
{
|
||||||
struct display *d = display_create();
|
struct display *d = display_create();
|
||||||
|
|
|
||||||
|
|
@ -1695,6 +1695,75 @@ TEST(global_remove)
|
||||||
display_destroy(d);
|
display_destroy(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatch_single_read_events(struct wl_display *d)
|
||||||
|
{
|
||||||
|
if (wl_display_prepare_read(d) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
do {
|
||||||
|
ret = wl_display_flush(d);
|
||||||
|
} while (ret < 0 && (errno == EINTR || errno == EAGAIN));
|
||||||
|
assert(ret >= 0);
|
||||||
|
|
||||||
|
struct pollfd pfd[1];
|
||||||
|
pfd[0].fd = wl_display_get_fd(d);
|
||||||
|
pfd[0].events = POLLIN;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = poll(pfd, 1, -1);
|
||||||
|
} while (ret < 0 && errno == EINTR);
|
||||||
|
assert(ret > 0);
|
||||||
|
|
||||||
|
wl_display_read_events(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatch_single_client(void)
|
||||||
|
{
|
||||||
|
struct client *c = client_connect();
|
||||||
|
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
|
||||||
|
|
||||||
|
struct wl_registry *registry = wl_display_get_registry(c->wl_display);
|
||||||
|
|
||||||
|
dispatch_single_read_events(c->wl_display);
|
||||||
|
|
||||||
|
// [1815110.061] {Default Queue} wl_registry#3.global(1, "test", 1)
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
|
||||||
|
|
||||||
|
dispatch_single_read_events(c->wl_display);
|
||||||
|
|
||||||
|
// [1815110.067] {Default Queue} wl_registry#3.global(2, "wl_seat", 1)
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 1);
|
||||||
|
|
||||||
|
// No more events
|
||||||
|
assert(wl_display_dispatch_pending_single(c->wl_display) == 0);
|
||||||
|
|
||||||
|
wl_registry_destroy(registry);
|
||||||
|
|
||||||
|
client_disconnect(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(dispatch_single)
|
||||||
|
{
|
||||||
|
struct display *d = display_create();
|
||||||
|
|
||||||
|
struct wl_global *global = wl_global_create(d->wl_display,
|
||||||
|
&wl_seat_interface,
|
||||||
|
1, d, bind_seat);
|
||||||
|
|
||||||
|
client_create_noarg(d, dispatch_single_client);
|
||||||
|
|
||||||
|
display_run(d);
|
||||||
|
|
||||||
|
wl_global_destroy(global);
|
||||||
|
|
||||||
|
display_destroy(d);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
terminate_display(void *arg)
|
terminate_display(void *arg)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include "wayland-private.h"
|
||||||
#define WL_HIDE_DEPRECATED
|
#include "wayland-client-private.h"
|
||||||
|
|
||||||
#include "test-runner.h"
|
#include "test-runner.h"
|
||||||
#include "test-compositor.h"
|
#include "test-compositor.h"
|
||||||
|
|
@ -49,6 +49,8 @@ static const struct wl_message tc_requests[] = {
|
||||||
/* this request serves as a barrier for synchronizing*/
|
/* this request serves as a barrier for synchronizing*/
|
||||||
{ "stop_display", "u", NULL },
|
{ "stop_display", "u", NULL },
|
||||||
{ "noop", "", NULL },
|
{ "noop", "", NULL },
|
||||||
|
{ "long_request", "a", NULL },
|
||||||
|
{ "set_buffer_size", "u", NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct wl_message tc_events[] = {
|
static const struct wl_message tc_events[] = {
|
||||||
|
|
@ -57,7 +59,7 @@ static const struct wl_message tc_events[] = {
|
||||||
|
|
||||||
const struct wl_interface test_compositor_interface = {
|
const struct wl_interface test_compositor_interface = {
|
||||||
"test", 1,
|
"test", 1,
|
||||||
2, tc_requests,
|
4, tc_requests,
|
||||||
1, tc_events
|
1, tc_events
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -67,6 +69,12 @@ struct test_compositor_interface {
|
||||||
uint32_t num);
|
uint32_t num);
|
||||||
void (*noop)(struct wl_client *client,
|
void (*noop)(struct wl_client *client,
|
||||||
struct wl_resource *resource);
|
struct wl_resource *resource);
|
||||||
|
void (*handle_long_request)(struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
struct wl_array *array);
|
||||||
|
void (*handle_set_buffer_size)(struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
uint32_t buffer_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct test_compositor_listener {
|
struct test_compositor_listener {
|
||||||
|
|
@ -76,11 +84,13 @@ struct test_compositor_listener {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STOP_DISPLAY = 0,
|
STOP_DISPLAY = 0,
|
||||||
TEST_NOOP = 1
|
TEST_NOOP = 1,
|
||||||
|
LONG_REQUEST = 2,
|
||||||
|
SET_BUFFER_SIZE = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DISPLAY_RESUMED = 0
|
DISPLAY_RESUMED = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Since tests can run parallelly, we need unique socket names
|
/* Since tests can run parallelly, we need unique socket names
|
||||||
|
|
@ -338,9 +348,29 @@ handle_noop(struct wl_client *client, struct wl_resource *resource)
|
||||||
(void)resource;
|
(void)resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_long_request(struct wl_client *client, struct wl_resource *resource, struct wl_array *array)
|
||||||
|
{
|
||||||
|
(void)client;
|
||||||
|
(void)resource;
|
||||||
|
(void)array;
|
||||||
|
/* This request should be rejected before the handler is called. */
|
||||||
|
assert(array->size <= 4096 - 12 &&
|
||||||
|
"overlong message not rejected sooner");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_set_buffer_size(struct wl_client *client, struct wl_resource *resource, uint32_t buffer_size)
|
||||||
|
{
|
||||||
|
(void)resource;
|
||||||
|
wl_client_set_max_buffer_size(client, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct test_compositor_interface tc_implementation = {
|
static const struct test_compositor_interface tc_implementation = {
|
||||||
handle_stop_display,
|
handle_stop_display,
|
||||||
handle_noop,
|
handle_noop,
|
||||||
|
handle_long_request,
|
||||||
|
handle_set_buffer_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -583,3 +613,32 @@ noop_request(struct client *c)
|
||||||
{
|
{
|
||||||
wl_proxy_marshal((struct wl_proxy *) c->tc, TEST_NOOP);
|
wl_proxy_marshal((struct wl_proxy *) c->tc, TEST_NOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_buffer_size(struct client *c, uint32_t size)
|
||||||
|
{
|
||||||
|
wl_proxy_marshal((struct wl_proxy *) c->tc, SET_BUFFER_SIZE, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
long_request(struct client *c, struct wl_array *array)
|
||||||
|
{
|
||||||
|
/* 12 is 8 bytes for the header and 4 bytes for the array length. */
|
||||||
|
|
||||||
|
/* Ensure that the array can validly be encoded in a message. */
|
||||||
|
assert(array->size <= (UINT16_MAX & ~UINT16_C(3)) - 12 && "overlong wl_array");
|
||||||
|
|
||||||
|
struct wl_proxy *proxy = (struct wl_proxy *)c->tc;
|
||||||
|
if (array->size > WL_MAX_MESSAGE_SIZE - 12) {
|
||||||
|
size_t size = 12 + ((array->size + 3) & ~3);
|
||||||
|
uint32_t buf[2];
|
||||||
|
|
||||||
|
/* The server will post an error after getting
|
||||||
|
* the header, so don't send the request body. */
|
||||||
|
buf[0] = wl_proxy_get_id(proxy);
|
||||||
|
buf[1] = size << 16 | LONG_REQUEST;
|
||||||
|
assert(wl_connection_write(proxy->display->connection, buf, sizeof(buf)) == 0);
|
||||||
|
} else {
|
||||||
|
wl_proxy_marshal(proxy, LONG_REQUEST, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ struct client *client_connect(void);
|
||||||
void client_disconnect(struct client *);
|
void client_disconnect(struct client *);
|
||||||
int stop_display(struct client *, int);
|
int stop_display(struct client *, int);
|
||||||
void noop_request(struct client *);
|
void noop_request(struct client *);
|
||||||
|
void long_request(struct client *c, struct wl_array *a);
|
||||||
|
void set_buffer_size(struct client *c, uint32_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usual workflow:
|
* Usual workflow:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue