mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Compare commits
5 commits
c15497bde8
...
a9d13ecd4d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9d13ecd4d | ||
|
|
d81525a235 | ||
|
|
4673ef7e9c | ||
|
|
77730f10a0 | ||
|
|
0853304bc9 |
8 changed files with 249 additions and 12 deletions
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_data_offer" version="3">
|
||||
<interface name="wl_data_offer" version="4">
|
||||
<description summary="offer to transfer data">
|
||||
A wl_data_offer represents a piece of data offered for transfer
|
||||
by another client (the source client). It is used by the
|
||||
|
|
@ -711,7 +711,7 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_data_source" version="3">
|
||||
<interface name="wl_data_source" version="4">
|
||||
<description summary="offer to transfer data">
|
||||
The wl_data_source object is the source side of a wl_data_offer.
|
||||
It is created by the source client in a data transfer and
|
||||
|
|
@ -866,7 +866,7 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_data_device" version="3">
|
||||
<interface name="wl_data_device" version="4">
|
||||
<description summary="data transfer device">
|
||||
There is one wl_data_device per seat which can be obtained
|
||||
from the global wl_data_device_manager singleton.
|
||||
|
|
@ -1006,13 +1006,12 @@
|
|||
data_device.data_offer and the data_offer.offer events are
|
||||
sent out immediately before this event to introduce the data
|
||||
offer object. The selection event is sent to a client
|
||||
immediately before receiving keyboard focus and when a new
|
||||
selection is set while the client has keyboard focus. The
|
||||
immediately before receiving data device focus and when a new
|
||||
selection is set while the client has data device focus. The
|
||||
data_offer is valid until a new data_offer or NULL is received
|
||||
or until the client loses keyboard focus. Switching surface with
|
||||
keyboard focus within the same client doesn't mean a new selection
|
||||
will be sent. The client must destroy the previous selection
|
||||
data_offer, if any, upon receiving this event.
|
||||
or until the client loses data device focus. The client must
|
||||
destroy the previous selection data_offer, if any, upon receiving
|
||||
this event.
|
||||
</description>
|
||||
<arg name="id" type="object" interface="wl_data_offer" allow-null="true"
|
||||
summary="selection data_offer object"/>
|
||||
|
|
@ -1025,9 +1024,33 @@
|
|||
This request destroys the data device.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
|
||||
<event name="enter" since="4">
|
||||
<description summary="focus gained">
|
||||
Notification that this seat's data device has gained focus.
|
||||
|
||||
The compositor must send the wl_data_device.selection event before this
|
||||
event.
|
||||
|
||||
Before version 4, data device focus was indicated by keyboard focus.
|
||||
Switching surface with keyboard focus within the same client didn't mean
|
||||
a new selection event was sent.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="leave" since="4">
|
||||
<description summary="focus lost">
|
||||
Notification that this seat's data device has lost focus.
|
||||
|
||||
The client will stop receiving selection events until the next enter
|
||||
event.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_data_device_manager" version="3">
|
||||
<interface name="wl_data_device_manager" version="4">
|
||||
<description summary="data transfer interface">
|
||||
The wl_data_device_manager is a singleton global object that
|
||||
provides access to inter-client data transfer mechanisms such as
|
||||
|
|
|
|||
|
|
@ -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 : "",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1198,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;
|
||||
|
|
|
|||
|
|
@ -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