1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#include "../../src/platform/wayland/clipboard.c"
#include "common/loop.h"
#include <assert.h>
struct received {
int count;
size_t len;
uint64_t request_id;
enum yasl_transfer_status status;
struct clipboard *clipboard;
bool forget_on_receive;
char text[32];
};
static void receive(const char *text, size_t len, bool uri_list,
struct wl_surface *surface, uint64_t request_id,
enum yasl_transfer_status status, void *ud)
{
(void)surface;
struct received *r = ud;
assert(!uri_list && len < sizeof(r->text));
if (status == YASL_TRANSFER_OK) {
assert(text);
memcpy(r->text, text, len);
r->text[len] = '\0';
} else {
assert(!text && len == 0);
}
r->len = len;
r->request_id = request_id;
r->status = status;
r->count++;
if (r->forget_on_receive) {
r->forget_on_receive = false;
clipboard_forget_surface(r->clipboard, surface);
}
}
int main(void)
{
struct received received = {0};
struct clipboard c = {.loop = yasl_loop_create(), .receive = receive, .ud = &received};
received.clipboard = &c;
assert(c.loop);
const struct { const char *bytes; size_t len; bool valid; } cases[] = {
{"é字😀", sizeof("é字😀") - 1, true},
{"", 0, true},
{"\xff", 1, false},
{"\xf0\x9f\x98", 3, false}, /* Incomplete non-BMP character. */
};
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
received = (struct received){0};
received.clipboard = &c;
int fds[2];
assert(pipe(fds) == 0);
struct transfer *transfer = start_transfer_text(&c, fds[0], false, false, c.text);
assert(transfer);
yasl_timer_id timeout_id = transfer->timeout;
assert(timeout_id && yasl_loop_timer_armed(c.loop, timeout_id));
transfer->paste = true;
transfer->request_id = 42;
assert(write(fds[1], cases[i].bytes, cases[i].len) == (ssize_t)cases[i].len);
close(fds[1]);
for (int steps = 0; c.transfers && steps < 10; steps++)
assert(yasl_loop_step(c.loop, 0) >= 0);
assert(!c.transfers);
assert(!yasl_loop_timer_armed(c.loop, timeout_id));
assert(received.count == 1);
assert(received.request_id == 42);
assert(received.status == (cases[i].valid ? YASL_TRANSFER_OK : YASL_TRANSFER_FAILED));
if (cases[i].valid) {
assert(received.len == cases[i].len);
assert(memcmp(received.text, cases[i].bytes, received.len) == 0);
}
}
received = (struct received){0};
received.clipboard = &c;
int cancel_fds[2];
assert(pipe(cancel_fds) == 0);
struct transfer *pending = start_transfer_text(&c, cancel_fds[0], false, false, NULL);
assert(pending);
yasl_timer_id cancel_timeout_id = pending->timeout;
assert(cancel_timeout_id && yasl_loop_timer_armed(c.loop, cancel_timeout_id));
pending->paste = true;
pending->request_id = 99;
struct wl_surface *target = (struct wl_surface *)(uintptr_t)1;
pending->drop_surface = target;
clipboard_forget_surface(&c, target);
close(cancel_fds[1]);
assert(!c.transfers && received.count == 0);
assert(!yasl_loop_timer_armed(c.loop, cancel_timeout_id));
received.forget_on_receive = true;
int timeout_fds[2];
assert(pipe(timeout_fds) == 0);
struct transfer *timed = start_transfer_text(&c, timeout_fds[0], false, false, NULL);
assert(timed && timed->timeout);
timed->paste = true;
timed->request_id = 100;
struct wl_surface *timeout_target = (struct wl_surface *)(uintptr_t)2;
timed->drop_surface = timeout_target;
yasl_timer_id timeout_id = timed->timeout;
assert(yasl_loop_del_timer(c.loop, timeout_id));
(void)transfer_timeout(timed, timeout_id, CLIPBOARD_TRANSFER_TIMEOUT_NS);
close(timeout_fds[1]);
assert(!c.transfers && received.count == 1);
assert(received.request_id == 100 && received.status == YASL_TRANSFER_FAILED);
yasl_loop_destroy(c.loop);
return 0;
}
|