summaryrefslogtreecommitdiff
path: root/tests/wayland
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
commit76073fe5fad8799e5850805f2f090af2cb62c741 (patch)
tree9658019babe4760a3634bdab4da0731a10e42e68 /tests/wayland
parentdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (diff)
Simplify the public event and CPU API
Applications now need far less ceremony: hello.c is a 20-line loop that handles REFRESH, CLOSE and QUIT and draws into the surface's own pixels. - Fold GEOMETRY, STATE and FOCUS into one WINDOW event carrying size, scale and state; unchanged values send nothing. - Guarantee REFRESH once a window has a size and after every resize, never at size zero. - Merge DROP_HOVER into DROP with over/leave/data actions and give drag and drop actions enums. - Keep event strings valid until the next wait and drop yasl_event_release; empty or failed waits report NONE. - Replace copy-in presentation with a lent pixel buffer: yasl_cpu_pixels and yasl_cpu_present. - Remove yasl_poll_event, yasl_cpu_read_pixels, unused event fields and comments that restated names. - Wayland: resize floating windows in request_size instead of reporting it unsupported, and stop marking new GPU surfaces as Vulkan so yasl_vulkan_create_surface no longer fails with NATIVE_WINDOW_IN_USE. Also includes the in-progress public API refactor that was uncommitted in the tree (removal of the app/loop layer, new surface, GL and Vulkan entry points). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/wayland')
-rw-r--r--tests/wayland/test_app_input.c174
-rw-r--r--tests/wayland/test_clipboard.c32
-rw-r--r--tests/wayland/test_cursor.c30
-rw-r--r--tests/wayland/test_input.c59
-rw-r--r--tests/wayland/test_keyboard.c63
-rw-r--r--tests/wayland/test_popup_positioner.c93
-rw-r--r--tests/wayland/test_relative_pointer.c30
-rw-r--r--tests/wayland/test_state.c61
-rw-r--r--tests/wayland/test_tablet.c115
9 files changed, 420 insertions, 237 deletions
diff --git a/tests/wayland/test_app_input.c b/tests/wayland/test_app_input.c
index 7e0e9a0..c8e4d2b 100644
--- a/tests/wayland/test_app_input.c
+++ b/tests/wayland/test_app_input.c
@@ -1,132 +1,78 @@
-/* An input event callback that destroys its own surface. The app runner
- * must not touch the surface's entry after the callback, and must not
- * deliver the surface's remaining input. Needs a Wayland compositor. */
-#include "platform/wayland/internal.h"
-#include "yasl/app.h"
+/* The public event queue must retain FIFO order and discard events targeted
+ * at a surface when that surface is destroyed. Native input is injected
+ * through the backend queue, without requiring a compositor. */
+#include "yasl/yasl.h"
+#include "common/backend.h"
#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
+#include <string.h>
-struct test_state {
- bool initialized;
- int keys;
- int buttons, motions, resets;
- int end;
+static struct input_queue *surface_queue(struct yasl_surface *s)
+{
+ return &s->input;
+}
+
+static const struct yasl_private_backend_ops test_ops = {
+ .surface_input_queue = surface_queue,
};
-static void push_key(struct yasl_surface *s)
+static void setup(struct yasl_private_display *display, struct yasl_surface *surface)
{
- struct yasl_event ev = {
- .surface = s,
- .type = YASL_EVENT_KEY,
- .key = { .key = YASL_KEY_A, .action = YASL_KEY_PRESS },
- };
- assert(input_queue_push(&((struct wayland_surface *)s)->input, &ev));
+ *display = (struct yasl_private_display){.ops = &test_ops};
+ *surface = (struct yasl_surface){.display = display, .scale_120 = 120};
+ assert(yasl_private_events_open(display));
+ assert(yasl_private_events_register(surface));
}
-static enum yasl_app_result on_init(void *ud, struct yasl_display *d)
+static void destroy_surface(struct yasl_surface *surface)
{
- struct test_state *state = ud;
- state->initialized = true;
- if (state->end == 3) {
- /* With no event callback, a close request alone stops the runner. */
- struct yasl_surface *s = yasl_surface_create_toplevel(d,
- &(struct yasl_window_spec){ .title = "App Close Test", .size = {64, 64} });
- assert(s);
- yasl_surface_notify_close(s);
- return YASL_APP_CONTINUE;
- }
- if (state->end) {
- if (state->end == 1)
- yasl_display_notify_event(d, YASL_EVENT_DISPLAY_QUIT);
- else
- yasl_display_notify_event(d, YASL_EVENT_DISPLAY_LOST);
- return YASL_APP_CONTINUE;
- }
- struct yasl_surface *s = yasl_surface_create_toplevel(d,
- &(struct yasl_window_spec){ .title = "App Input Test", .size = {64, 64} });
- assert(s);
- struct input_queue *queue = &((struct wayland_surface *)s)->input;
- input_queue_clear(queue);
- struct yasl_event event = {.surface = s, .type = YASL_EVENT_POINTER_DOWN,
- .pointer = {.device = YASL_PTR_DEV_ERASER, .button = YASL_BUTTON_PRIMARY,
- .pos = {12, 34}, .pen = {.pressure = 50000, .tilt_x = -20, .tilt_y = 30}}};
- assert(input_queue_push(queue, &event));
- event.type = YASL_EVENT_POINTER_MOTION;
- event.pointer.pos = (struct yasl_vector2i){15, 39};
- assert(input_queue_push(queue, &event));
- struct yasl_event reset = {.surface = s, .type = YASL_EVENT_INPUT_RESET};
- assert(input_queue_push(queue, &reset));
- event.pointer.device = YASL_PTR_DEV_PEN;
- event.pointer.pos = (struct yasl_vector2i){100, 200};
- assert(input_queue_push(queue, &event));
- push_key(s);
- push_key(s);
- return YASL_APP_CONTINUE;
+ yasl_private_events_unregister(surface);
+ input_queue_clear(&surface->input);
}
-static enum yasl_app_result on_event(void *ud, const struct yasl_event *ev)
+static void test_fifo_and_destroy(void)
{
- struct test_state *state = ud;
- if (ev->type == YASL_EVENT_POINTER_DOWN) {
- assert(ev->pointer.device == YASL_PTR_DEV_ERASER);
- assert(ev->pointer.button == YASL_BUTTON_PRIMARY);
- assert(ev->pointer.pos.x == 12 && ev->pointer.pos.y == 34);
- assert(ev->pointer.pen.pressure == 50000);
- assert(ev->pointer.pen.tilt_x == -20 && ev->pointer.pen.tilt_y == 30);
- state->buttons++;
- } else if (ev->type == YASL_EVENT_POINTER_MOTION) {
- if (!state->motions) {
- assert(ev->pointer.device == YASL_PTR_DEV_ERASER);
- assert(ev->pointer.delta.x == 3 && ev->pointer.delta.y == 5);
- } else {
- assert(ev->pointer.device == YASL_PTR_DEV_PEN);
- assert(!ev->pointer.delta.x && !ev->pointer.delta.y);
- }
- assert(ev->pointer.pen.pressure == 50000);
- state->motions++;
- } else if (ev->type == YASL_EVENT_INPUT_RESET) {
- state->resets++;
- } else if (ev->type == YASL_EVENT_KEY) {
- state->keys++;
- yasl_surface_destroy(ev->surface);
- }
- return YASL_APP_CONTINUE;
+ struct yasl_private_display display;
+ struct yasl_surface surface;
+ setup(&display, &surface);
+
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_KEY,
+ .surface = &surface,
+ .key = {.key = YASL_KEY_A, .action = YASL_KEY_PRESS},
+ }));
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_TEXT,
+ .surface = &surface,
+ .text = {.data = "hello", .len = 5},
+ }));
+
+ struct yasl_private_event event;
+ assert(yasl_private_display_poll_event(&display, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_KEY && event.key.key == YASL_KEY_A);
+ assert(yasl_private_display_poll_event(&display, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_TEXT && event.text.len == 5);
+ assert(!strcmp(event.text.data, "hello"));
+
+ /* Queue multiple events, then destroy the target before consumption. */
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_KEY, .surface = &surface,
+ .key = {.key = YASL_KEY_B, .action = YASL_KEY_PRESS},
+ }));
+ assert(input_queue_push(&surface.input, &(struct yasl_private_event){
+ .type = YASL_PRIVATE_EVENT_TEXT, .surface = &surface,
+ .text = {.data = "discard", .len = 7},
+ }));
+ destroy_surface(&surface);
+ assert(!yasl_private_display_poll_event(&display, &event));
+ yasl_private_events_close(&display);
+
+ /* Public event names remain the event stream consumed by applications. */
+ assert(YASL_EVENT_KEY != YASL_EVENT_TEXT);
}
int main(void)
{
- if (!getenv("WAYLAND_DISPLAY"))
- return 77;
- struct test_state state = {0};
- int res = yasl_run(&(struct yasl_app_desc){
- .app_id = "org.yasl.test.app-input",
- .backend = YASL_BACKEND_WAYLAND,
- .userdata = &state,
- .init = on_init,
- .event = on_event,
- });
- /* A display variable may exist even when the test sandbox cannot connect
- * to that compositor. Keep this as an integration test in that case. */
- if (res < 0 && !state.initialized &&
- (errno == EACCES || errno == EPERM || errno == ENOENT ||
- errno == ECONNREFUSED || errno == ENODEV))
- return 77;
- assert(res == 0);
- assert(state.keys == 1);
- assert(state.buttons == 1 && state.motions == 2 && state.resets == 1);
- for (int end = 1; end <= 2; end++) {
- state = (struct test_state){.end = end};
- res = yasl_run(&(struct yasl_app_desc){
- .backend = YASL_BACKEND_WAYLAND, .userdata = &state, .init = on_init,
- });
- assert(end == 1 ? res == 0 : res < 0);
- }
- state = (struct test_state){.end = 3};
- res = yasl_run(&(struct yasl_app_desc){
- .backend = YASL_BACKEND_WAYLAND, .userdata = &state, .init = on_init,
- });
- assert(res == 0);
+ test_fifo_and_destroy();
return 0;
}
diff --git a/tests/wayland/test_clipboard.c b/tests/wayland/test_clipboard.c
index 1778ad2..0ee74b6 100644
--- a/tests/wayland/test_clipboard.c
+++ b/tests/wayland/test_clipboard.c
@@ -6,7 +6,7 @@ struct received {
int count;
size_t len;
uint64_t request_id;
- enum yasl_transfer_status status;
+ enum yasl_private_transfer_status status;
struct clipboard *clipboard;
bool forget_on_receive;
char text[32];
@@ -14,12 +14,12 @@ struct received {
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)
+ enum yasl_private_transfer_status status, void *ud)
{
(void)surface;
struct received *r = ud;
assert(!uri_list && len < sizeof(r->text));
- if (status == YASL_TRANSFER_OK) {
+ if (status == YASL_PRIVATE_TRANSFER_OK) {
assert(text);
memcpy(r->text, text, len);
r->text[len] = '\0';
@@ -39,7 +39,7 @@ static void receive(const char *text, size_t len, bool uri_list,
int main(void)
{
struct received received = {0};
- struct clipboard c = {.loop = yasl_loop_create(), .receive = receive, .ud = &received};
+ struct clipboard c = {.loop = yasl_private_loop_create(), .receive = receive, .ud = &received};
received.clipboard = &c;
assert(c.loop);
const struct { const char *bytes; size_t len; bool valid; } cases[] = {
@@ -55,19 +55,19 @@ int main(void)
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));
+ yasl_private_timer_id timeout_id = transfer->timeout;
+ assert(timeout_id && yasl_private_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(yasl_private_loop_step(c.loop, 0) >= 0);
assert(!c.transfers);
- assert(!yasl_loop_timer_armed(c.loop, timeout_id));
+ assert(!yasl_private_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));
+ assert(received.status == (cases[i].valid ? YASL_PRIVATE_TRANSFER_OK : YASL_PRIVATE_TRANSFER_FAILED));
if (cases[i].valid) {
assert(received.len == cases[i].len);
assert(memcmp(received.text, cases[i].bytes, received.len) == 0);
@@ -79,8 +79,8 @@ int main(void)
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));
+ yasl_private_timer_id cancel_timeout_id = pending->timeout;
+ assert(cancel_timeout_id && yasl_private_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;
@@ -88,7 +88,7 @@ int main(void)
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));
+ assert(!yasl_private_loop_timer_armed(c.loop, cancel_timeout_id));
received.forget_on_receive = true;
int timeout_fds[2];
@@ -99,12 +99,12 @@ int main(void)
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));
+ yasl_private_timer_id timeout_id = timed->timeout;
+ assert(yasl_private_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);
+ assert(received.request_id == 100 && received.status == YASL_PRIVATE_TRANSFER_FAILED);
+ yasl_private_loop_destroy(c.loop);
return 0;
}
diff --git a/tests/wayland/test_cursor.c b/tests/wayland/test_cursor.c
index eb729a3..3425821 100644
--- a/tests/wayland/test_cursor.c
+++ b/tests/wayland/test_cursor.c
@@ -51,9 +51,9 @@ static uint32_t pointer_version(struct wl_pointer *pointer)
int main(void)
{
- struct wayland_display display = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display display = {.base.ops = &yasl_private_wayland_backend};
struct wayland_surface surface = {.base.display = &display.base, .conn = &display,
- .scale_factor = 1, .cursor = YASL_CURSOR_TEXT};
+ .scale_factor = 1, .cursor = YASL_PRIVATE_CURSOR_TEXT};
surface.surface = (struct wl_surface *)&surface;
wl_surface_set_user_data(surface.surface, &surface);
display.surfaces = &surface;
@@ -64,7 +64,7 @@ int main(void)
tool.proxy = (struct zwp_tablet_tool_v2 *)&tool;
/* The example selects hidden before either input device has entered. */
- yasl_surface_set_cursor(&surface.base, YASL_CURSOR_HIDDEN);
+ yasl_private_surface_set_cursor(&surface.base, YASL_PRIVATE_CURSOR_HIDDEN);
assert(!pointer_hides && !tool_hides);
pointer_enter(&seat, seat.pointer, 10, surface.surface, 0, 0);
assert(pointer_hides == 1 && pointer_serial == 10);
@@ -76,14 +76,16 @@ int main(void)
pointer_frame(&seat, seat.pointer);
tablet_tool_motion(&tool, tool.proxy, wl_fixed_from_int(56), wl_fixed_from_int(78));
tool_frame(&tool, tool.proxy, 0);
- struct yasl_event event;
- assert(yasl_surface_poll_event(&surface.base, &event));
- assert(event.type == YASL_EVENT_POINTER_MOTION && event.pointer.device == YASL_PTR_DEV_MOUSE);
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&surface.base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION && event.pointer.device == YASL_PRIVATE_PTR_DEV_MOUSE);
assert(event.pointer.pos.x == 12 && event.pointer.pos.y == 34);
- assert(yasl_surface_poll_event(&surface.base, &event));
- assert(event.type == YASL_EVENT_POINTER_MOTION && event.pointer.device == YASL_PTR_DEV_PEN);
+ assert(yasl_private_surface_poll_event(&surface.base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_PEN && event.pen.action == YASL_PRIVATE_PEN_ENTER);
+ assert(yasl_private_surface_poll_event(&surface.base, &event));
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION && event.pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
assert(event.pointer.pos.x == 56 && event.pointer.pos.y == 78);
- assert(!yasl_surface_poll_event(&surface.base, &event));
+ assert(!yasl_private_surface_poll_event(&surface.base, &event));
/* Each new entry needs a request with its own serial. */
pointer_leave(&seat, seat.pointer, 12, surface.surface);
@@ -98,20 +100,20 @@ int main(void)
/* Restore a visible shape on both currently focused devices. */
pointer_device = seat.cursor_shape_dev = (struct wp_cursor_shape_device_v1 *)&seat;
tool.shape_dev = (struct wp_cursor_shape_device_v1 *)&tool;
- yasl_surface_set_cursor(&surface.base, YASL_CURSOR_ARROW);
+ yasl_private_surface_set_cursor(&surface.base, YASL_PRIVATE_CURSOR_ARROW);
assert(pointer_shapes == 1 && tool_shapes == 1);
assert(pointer_shape == WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
assert(tool_shape == WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
- yasl_surface_set_cursor(&surface.base, YASL_CURSOR_HIDDEN);
+ yasl_private_surface_set_cursor(&surface.base, YASL_PRIVATE_CURSOR_HIDDEN);
assert(pointer_hides == 3 && tool_hides == 3);
assert(pointer_shapes == 1 && tool_shapes == 1);
/* Updating an unfocused surface must not alter the active cursor. */
struct wayland_surface other = {.base.display = &display.base, .conn = &display};
- yasl_surface_set_cursor(&other.base, YASL_CURSOR_CROSSHAIR);
+ yasl_private_surface_set_cursor(&other.base, YASL_PRIVATE_CURSOR_CROSSHAIR);
assert(pointer_shapes == 1 && tool_shapes == 1);
- yasl_surface_set_cursor(&surface.base, (enum yasl_cursor)-1);
- yasl_surface_set_cursor(&surface.base, (enum yasl_cursor)(YASL_CURSOR_HIDDEN + 1));
+ yasl_private_surface_set_cursor(&surface.base, (enum yasl_private_cursor)-1);
+ yasl_private_surface_set_cursor(&surface.base, (enum yasl_private_cursor)(YASL_PRIVATE_CURSOR_HIDDEN + 1));
assert(pointer_hides == 3 && tool_hides == 3);
assert(pointer_shapes == 1 && tool_shapes == 1);
input_queue_clear(&surface.input);
diff --git a/tests/wayland/test_input.c b/tests/wayland/test_input.c
index f6112b6..2b5592a 100644
--- a/tests/wayland/test_input.c
+++ b/tests/wayland/test_input.c
@@ -1,17 +1,35 @@
#include "platform/wayland/internal.h"
#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+static void test_ime_capability(void)
+{
+ struct wayland_display display = {0};
+ struct wayland_surface w = {.conn = &display};
+ assert(!(wayland_display_caps(&display) & YASL_PRIVATE_CAP_TEXT_INPUT));
+ errno = 0;
+ assert(!wayland_surface_update_text_input(&w) && errno == ENOTSUP);
+ display.text_input_mgr = (struct zwp_text_input_manager_v3 *)&display;
+ assert(wayland_display_caps(&display) & YASL_PRIVATE_CAP_TEXT_INPUT);
+ w.base.text_input_active = true;
+ w.base.text_purpose = 1; /* Public YASL_TEXT_PASSWORD. */
+ /* A supported compositor can accept the requested state before a seat
+ * or keyboard focus has arrived. The enter callback applies it later. */
+ assert(wayland_surface_update_text_input(&w));
+}
static void test_popup_bounds(void)
{
struct seat seat = {.input_serial = 1};
- struct wayland_display d = {.base.ops = &yasl_wayland_backend, .seats = &seat};
+ struct wayland_display d = {.base.ops = &yasl_private_wayland_backend, .seats = &seat};
struct wayland_surface w = {.base.display = &d.base, .conn = &d};
w.parent = &w;
w.content.x = w.content.y = 1;
/* Invalid bounds must be rejected before accessing any protocol object. */
w.xdg_surface = (struct xdg_surface *)&w;
w.popup = (struct xdg_popup *)&w;
- struct yasl_popup_spec specs[] = {
+ struct yasl_private_popup_spec specs[] = {
{.size = {100, 100}, .content_offset = {INT_MAX, 0}, .content_size = {1, 0}},
{.size = {100, 100}, .content_offset = {0, INT_MAX}, .content_size = {0, 1}},
{.size = {100, 100}, .content_offset = {1, 0}, .content_size = {INT_MAX, 0}},
@@ -20,16 +38,18 @@ static void test_popup_bounds(void)
{.size = {100, 100}, .anchor = {0, INT_MIN, 1, 1}},
};
for (size_t i = 0; i < sizeof(specs) / sizeof(specs[0]); i++) {
- assert(!yasl_surface_create_popup(&w.base, &specs[i]));
- assert(!yasl_surface_popup_reposition(&w.base, &specs[i]));
+ assert(!yasl_private_surface_create_popup(&w.base, &specs[i]));
+ assert(!yasl_private_surface_popup_reposition(&w.base, &specs[i]));
}
}
int main(void)
{
+ test_ime_capability();
test_popup_bounds();
struct wayland_surface w = {0};
struct seat seat = {.ime_focus = &w};
+ w.base.text_input_active = true;
wayland_surface_set_callbacks(&w, NULL, NULL);
for (int i = 0; i < 600; i++) {
char text[32];
@@ -41,11 +61,38 @@ int main(void)
for (int i = 0; i < 600; i++) {
char text[32];
snprintf(text, sizeof(text), "commit-%d", i);
- struct yasl_event event;
+ struct yasl_private_event event;
assert(wayland_surface_poll_event(&w, &event));
- assert(event.type == YASL_EVENT_TEXT && event.surface == &w.base);
+ assert(event.type == YASL_PRIVATE_EVENT_TEXT && event.surface == &w.base);
assert(strcmp(event.text.data, text) == 0);
}
+ w.base.text_input_active = true;
+ w.base.text_surrounding = strdup("ab\xf0\x9f\x98\x80" "cd");
+ w.base.text_length = 8;
+ w.base.text_begin = 2;
+ w.base.text_end = 6;
+ w.base.text_revision = 41;
+ w.base.text_generation = 9;
+ text_input_listener.delete_surrounding_text(&seat, NULL, 2, 2);
+ text_input_listener.commit_string(&seat, NULL, "X");
+ text_input_listener.done(&seat, NULL, 601);
+ struct yasl_private_event edit;
+ assert(wayland_surface_poll_event(&w, &edit));
+ assert(edit.type == YASL_PRIVATE_EVENT_TEXT_EDIT && edit.surface == &w.base);
+ assert(strcmp(edit.text_edit.data, "X") == 0 && edit.text_edit.len == 1);
+ assert(edit.text_edit.begin == 2 && edit.text_edit.end == 8);
+ assert(edit.text_edit.revision == 41 && edit.text_edit.generation == 9);
+ struct yasl_private_event committed;
+ assert(!wayland_surface_poll_event(&w, &committed));
+
+ /* Deletion without a commit replaces the range with the empty string. */
+ text_input_listener.delete_surrounding_text(&seat, NULL, 2, 2);
+ text_input_listener.done(&seat, NULL, 602);
+ assert(wayland_surface_poll_event(&w, &edit));
+ assert(edit.type == YASL_PRIVATE_EVENT_TEXT_EDIT && edit.text_edit.len == 0);
+ assert(edit.text_edit.data[0] == '\0' && edit.text_edit.begin == 2 && edit.text_edit.end == 8);
+ assert(!wayland_surface_poll_event(&w, &committed));
input_queue_clear(&w.input);
+ free(w.base.text_surrounding);
return 0;
}
diff --git a/tests/wayland/test_keyboard.c b/tests/wayland/test_keyboard.c
index bce0a0c..ae4647f 100644
--- a/tests/wayland/test_keyboard.c
+++ b/tests/wayland/test_keyboard.c
@@ -1,18 +1,18 @@
#include "../../src/platform/wayland/keyboard.c"
#include <assert.h>
-static struct yasl_event next(struct wayland_surface *w, enum yasl_event_type type)
+static struct yasl_private_event next(struct wayland_surface *w, enum yasl_private_event_type type)
{
- struct yasl_event ev;
- assert(yasl_surface_poll_event(&w->base, &ev));
+ struct yasl_private_event ev;
+ assert(yasl_private_surface_poll_event(&w->base, &ev));
assert(ev.type == type && ev.surface == &w->base);
return ev;
}
static void empty(struct wayland_surface *w)
{
- struct yasl_event ev;
- assert(!yasl_surface_poll_event(&w->base, &ev));
+ struct yasl_private_event ev;
+ assert(!yasl_private_surface_poll_event(&w->base, &ev));
}
static void layout(struct seat *s, const char *name, const char *variant)
@@ -43,7 +43,7 @@ static void key(struct seat *s, uint32_t code, bool down)
int main(void)
{
- struct wayland_display d = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display d = {.base.ops = &yasl_private_wayland_backend};
d.xkb_ctx = xkb_context_new(0);
assert(d.xkb_ctx);
struct wayland_surface w = {.base.display = &d.base, .conn = &d};
@@ -59,65 +59,66 @@ int main(void)
xkb_compose_table_unref(table);
layout(&s, "us", NULL);
key(&s, KEY_A, true);
- struct yasl_event ev = next(&w, YASL_EVENT_KEY);
+ struct yasl_private_event ev = next(&w, YASL_PRIVATE_EVENT_KEY);
assert(ev.key.key == YASL_KEY_A && ev.key.native_code == KEY_A);
assert(ev.key.codepoint == 'a' && ev.key.shifted == 'A' && !ev.key.mods);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "a") == 0);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "a") == 0);
modifiers(&s, XKB_MOD_NAME_SHIFT);
key(&s, KEY_A, false); /* Modifier changes cannot change physical identity. */
- ev = next(&w, YASL_EVENT_KEY);
+ ev = next(&w, YASL_PRIVATE_EVENT_KEY);
assert(ev.key.key == YASL_KEY_A && ev.key.action == YASL_KEY_RELEASE);
- assert(ev.key.mods == YASL_MOD_SHIFT);
+ assert(ev.key.mods == YASL_PRIVATE_MOD_SHIFT);
empty(&w);
key(&s, KEY_A, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "A") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "A") == 0);
modifiers(&s, XKB_MOD_NAME_CAPS);
key(&s, KEY_A, true);
- assert(next(&w, YASL_EVENT_KEY).key.mods == YASL_MOD_CAPS);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "A") == 0);
+ assert(next(&w, YASL_PRIVATE_EVENT_KEY).key.mods == YASL_PRIVATE_MOD_CAPS);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "A") == 0);
const char *shortcuts[] = {XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_LOGO};
for (size_t i = 0; i < sizeof(shortcuts)/sizeof(shortcuts[0]); i++) {
modifiers(&s, shortcuts[i]);
key(&s, KEY_A, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
empty(&w); /* Shortcut characters never leak into committed text. */
}
layout(&s, "fr", NULL);
key(&s, KEY_A, true);
- ev = next(&w, YASL_EVENT_KEY);
+ ev = next(&w, YASL_PRIVATE_EVENT_KEY);
assert(ev.key.key == YASL_KEY_A && ev.key.codepoint == 'q');
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "q") == 0);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "q") == 0);
layout(&s, "de", NULL);
modifiers(&s, "Mod5"); /* AltGr is text input, not an Alt shortcut. */
key(&s, KEY_E, true);
- assert(next(&w, YASL_EVENT_KEY).key.key == YASL_KEY_E);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "€") == 0);
+ assert(next(&w, YASL_PRIVATE_EVENT_KEY).key.key == YASL_KEY_E);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "€") == 0);
layout(&s, "us", "intl");
key(&s, KEY_APOSTROPHE, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
empty(&w);
key(&s, KEY_E, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "é") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "é") == 0);
assert(keyboard_dispatch_key(&s, &w, KEY_E, YASL_KEY_REPEAT));
- assert(next(&w, YASL_EVENT_KEY).key.action == YASL_KEY_REPEAT);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "e") == 0);
+ assert(next(&w, YASL_PRIVATE_EVENT_KEY).key.action == YASL_KEY_REPEAT);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "e") == 0);
key(&s, KEY_APOSTROPHE, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
keyboard_reset_keys(&s, &w);
key(&s, KEY_E, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "e") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "e") == 0);
key(&s, KEY_APOSTROPHE, true);
- next(&w, YASL_EVENT_KEY);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
s.ime_focus = &w;
+ w.base.text_input_active = true;
text_input_listener.commit_string(&s, NULL, "字");
text_input_listener.done(&s, NULL, 0);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "字") == 0);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "字") == 0);
key(&s, KEY_E, true);
- next(&w, YASL_EVENT_KEY);
- assert(strcmp(next(&w, YASL_EVENT_TEXT).text.data, "e") == 0);
+ next(&w, YASL_PRIVATE_EVENT_KEY);
+ assert(strcmp(next(&w, YASL_PRIVATE_EVENT_TEXT).text.data, "e") == 0);
empty(&w);
xkb_compose_state_unref(s.compose);
xkb_state_unref(s.xkb_state);
diff --git a/tests/wayland/test_popup_positioner.c b/tests/wayland/test_popup_positioner.c
new file mode 100644
index 0000000..86778f6
--- /dev/null
+++ b/tests/wayland/test_popup_positioner.c
@@ -0,0 +1,93 @@
+/* Capture xdg_positioner requests to verify explicit placement and the legacy
+ * beside mapping without requiring a compositor. */
+#include "platform/wayland/internal.h"
+#include <assert.h>
+
+struct recorded_positioner {
+ int width, height;
+ int rect_x, rect_y, rect_width, rect_height;
+ uint32_t anchor, gravity, constraints;
+ bool reactive;
+};
+
+static struct recorded_positioner record;
+static uint64_t fake_positioner_storage[8];
+#define FAKE_POSITIONER ((struct xdg_positioner *)fake_positioner_storage)
+static struct xdg_positioner *fake_create(struct xdg_wm_base *base)
+{ (void)base; record = (struct recorded_positioner){0}; return FAKE_POSITIONER; }
+static void fake_size(struct xdg_positioner *pos, int32_t width, int32_t height)
+{ assert(pos == FAKE_POSITIONER); record.width = width; record.height = height; }
+static void fake_rect(struct xdg_positioner *pos, int32_t x, int32_t y, int32_t width, int32_t height)
+{ assert(pos == FAKE_POSITIONER); record.rect_x=x; record.rect_y=y; record.rect_width=width; record.rect_height=height; }
+static void fake_anchor(struct xdg_positioner *pos, uint32_t value)
+{ assert(pos == FAKE_POSITIONER); record.anchor = value; }
+static void fake_gravity(struct xdg_positioner *pos, uint32_t value)
+{ assert(pos == FAKE_POSITIONER); record.gravity = value; }
+static void fake_constraints(struct xdg_positioner *pos, uint32_t value)
+{ assert(pos == FAKE_POSITIONER); record.constraints = value; }
+static uint32_t fake_version(struct xdg_positioner *pos)
+{ assert(pos == FAKE_POSITIONER); return XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION; }
+static void fake_reactive(struct xdg_positioner *pos)
+{ assert(pos == FAKE_POSITIONER); record.reactive = true; }
+
+#define xdg_wm_base_create_positioner fake_create
+#define xdg_positioner_set_size fake_size
+#define xdg_positioner_set_anchor_rect fake_rect
+#define xdg_positioner_set_anchor fake_anchor
+#define xdg_positioner_set_gravity fake_gravity
+#define xdg_positioner_set_constraint_adjustment fake_constraints
+#define xdg_positioner_get_version fake_version
+#define xdg_positioner_set_reactive fake_reactive
+#include "../../src/platform/wayland/popup.c"
+
+int main(void)
+{
+ struct wayland_display display = {.wm_base = (struct xdg_wm_base *)&record};
+ struct wayland_surface parent = {
+ .scale_120 = 120,
+ .content = {.x = 3, .y = 4},
+ };
+ struct wayland_surface popup = {
+ .conn = &display,
+ .parent = &parent,
+ .scale_120 = 120,
+ .content = {.width = 48, .height = 36},
+ };
+ struct yasl_private_popup_spec spec = {
+ .size = {64, 48},
+ .anchor = {13, 24, 8, 6},
+ .beside = true,
+ };
+
+ struct xdg_positioner *positioner = popup_positioner(&popup, &spec);
+ assert(positioner == FAKE_POSITIONER);
+ assert(record.width == 48 && record.height == 36);
+ assert(record.rect_x == 10 && record.rect_y == 20 &&
+ record.rect_width == 8 && record.rect_height == 6);
+ assert(record.anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT);
+ assert(record.gravity == XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
+ assert(record.constraints == (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y));
+ assert(record.reactive);
+
+ spec.positioner_explicit = true;
+ spec.anchor_edges = XDG_POSITIONER_ANCHOR_NONE;
+ spec.gravity = XDG_POSITIONER_GRAVITY_RIGHT;
+ spec.constraints = XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y;
+ assert(popup_spec_valid(&parent, &spec));
+ positioner = popup_positioner(&popup, &spec);
+ assert(positioner == FAKE_POSITIONER);
+ assert(record.anchor == XDG_POSITIONER_ANCHOR_NONE);
+ assert(record.gravity == XDG_POSITIONER_GRAVITY_RIGHT);
+ assert(record.constraints == spec.constraints);
+
+ spec.anchor_edges = XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT + 1;
+ assert(!popup_spec_valid(&parent, &spec));
+ spec.anchor_edges = XDG_POSITIONER_ANCHOR_NONE;
+ spec.constraints = 1u << 9;
+ assert(!popup_spec_valid(&parent, &spec));
+ return 0;
+}
diff --git a/tests/wayland/test_relative_pointer.c b/tests/wayland/test_relative_pointer.c
index bcc41e3..d44238d 100644
--- a/tests/wayland/test_relative_pointer.c
+++ b/tests/wayland/test_relative_pointer.c
@@ -65,10 +65,10 @@ static void shape_device_destroy(struct wp_cursor_shape_device_v1 *device) { ass
#define wl_pointer_release pointer_release
#include "../../src/platform/wayland/pointer.c"
-static struct yasl_event next_event(struct wayland_surface *w)
+static struct yasl_private_event next_event(struct wayland_surface *w)
{
- struct yasl_event event;
- assert(yasl_surface_poll_event(&w->base, &event));
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&w->base, &event));
return event;
}
@@ -85,9 +85,9 @@ static void relative_move(struct seat *s, double dx, double dy)
int main(void)
{
- struct wayland_display display = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display display = {.base.ops = &yasl_private_wayland_backend};
struct wayland_surface surface = {.base.display = &display.base, .conn = &display,
- .scale_factor = 2, .cursor = YASL_CURSOR_TEXT};
+ .scale_factor = 2, .cursor = YASL_PRIVATE_CURSOR_TEXT};
surface.surface = (struct wl_surface *)&surface;
wl_surface_set_user_data(surface.surface, &surface);
display.surfaces = &surface;
@@ -95,10 +95,10 @@ int main(void)
seat.pointer = (struct wl_pointer *)&seat;
seat.cursor_shape_dev = (struct wp_cursor_shape_device_v1 *)&seat;
display.seats = &seat;
- struct yasl_event event;
+ struct yasl_private_event event;
/* Without both protocols the surface stays in absolute mode. */
- assert(!yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_RELATIVE));
+ assert(!yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_RELATIVE));
assert(!surface.relative && !locks);
display.relative_pointer_mgr = (struct zwp_relative_pointer_manager_v1 *)&display;
display.pointer_constraints = (struct zwp_pointer_constraints_v1 *)&display;
@@ -107,10 +107,10 @@ int main(void)
pointer_frame(&seat, seat.pointer);
assert(pointer_shapes == 1);
event = next_event(&surface);
- assert(event.type == YASL_EVENT_POINTER_MOTION && event.pointer.pos.x == 10);
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION && event.pointer.pos.x == 10);
/* Relative mode locks persistently on the pointer's seat and hides the cursor. */
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_RELATIVE));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_RELATIVE));
assert(locks == 1 && locked_surface == surface.surface && locked_wl_pointer == seat.pointer);
assert(lock_lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
assert(pointer_hides == 1 && surface.lock_seat == &seat);
@@ -121,14 +121,14 @@ int main(void)
event = next_event(&surface);
assert(event.pointer.pos.x == 14 && event.pointer.pos.y == 10);
assert(event.pointer.delta.x == 4 && event.pointer.delta.y == 0);
- assert(!yasl_surface_poll_event(&surface.base, &event));
+ assert(!yasl_private_surface_poll_event(&surface.base, &event));
/* Locked: relative samples in device pixels, position frozen at the lock. */
pointer_locked(&surface, surface.pointer_lock);
relative_move(&seat, 3.5, -2);
relative_move(&seat, 1000, 0);
event = next_event(&surface);
- assert(event.type == YASL_EVENT_POINTER_MOTION);
+ assert(event.type == YASL_PRIVATE_EVENT_POINTER_MOTION);
assert(event.pointer.pos.x == 14 && event.pointer.pos.y == 10);
assert(event.pointer.delta.x == 7 && event.pointer.delta.y == -4);
event = next_event(&surface);
@@ -137,7 +137,7 @@ int main(void)
/* Deactivation (e.g. focus loss) returns to absolute motion without unlocking. */
pointer_unlocked(&surface, surface.pointer_lock);
relative_move(&seat, 5, 5);
- assert(!yasl_surface_poll_event(&surface.base, &event));
+ assert(!yasl_private_surface_poll_event(&surface.base, &event));
move_to(&seat, 8, 5);
event = next_event(&surface);
assert(event.pointer.delta.x == 2 && event.pointer.delta.y == 0);
@@ -145,12 +145,12 @@ int main(void)
pointer_locked(&surface, surface.pointer_lock);
/* Returning to normal destroys the lock and restores the chosen cursor. */
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_NORMAL));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_NORMAL));
assert(unlocks == 1 && !surface.pointer_lock && !surface.input.relative);
assert(pointer_shapes == 2);
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_NORMAL));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_NORMAL));
assert(unlocks == 1);
- assert(yasl_surface_set_pointer_mode(&surface.base, YASL_POINTER_RELATIVE));
+ assert(yasl_private_surface_set_pointer_mode(&surface.base, YASL_PRIVATE_POINTER_RELATIVE));
assert(locks == 2 && pointer_hides == 2);
pointer_locked(&surface, surface.pointer_lock);
diff --git a/tests/wayland/test_state.c b/tests/wayland/test_state.c
index 2da26e5..1ce9189 100644
--- a/tests/wayland/test_state.c
+++ b/tests/wayland/test_state.c
@@ -1,6 +1,20 @@
-#include "../../src/platform/wayland/shell.c"
+#include "platform/wayland/internal.h"
#include <assert.h>
+static uint32_t acknowledged_serial;
+static unsigned acknowledge_count;
+static void test_ack_configure(struct xdg_surface *surface, uint32_t serial);
+#define xdg_surface_ack_configure test_ack_configure
+#include "../../src/platform/wayland/shell.c"
+#undef xdg_surface_ack_configure
+
+static void test_ack_configure(struct xdg_surface *surface, uint32_t serial)
+{
+ (void)surface;
+ acknowledged_serial = serial;
+ acknowledge_count++;
+}
+
struct notifications {
int count;
uint32_t state;
@@ -9,7 +23,7 @@ struct notifications {
static void state_changed(struct yasl_surface *surface, uint32_t state, void *ud)
{
struct notifications *notifications = ud;
- assert(yasl_surface_state(surface) == state);
+ assert(yasl_private_surface_state(surface) == state);
notifications->count++;
notifications->state = state;
}
@@ -24,33 +38,33 @@ static void configure(struct wayland_surface *surface, uint32_t *states, size_t
int main(void)
{
struct notifications notifications = {0};
- struct wayland_surface surface = {.base.state = YASL_STATE_CSD};
- wayland_surface_set_callbacks(&surface, &(struct yasl_window_cbs){
+ struct wayland_surface surface = {.base.state = YASL_PRIVATE_STATE_CSD};
+ wayland_surface_set_callbacks(&surface, &(struct yasl_private_window_cbs){
.state = state_changed}, &notifications);
- assert(yasl_surface_state(&surface.base) == YASL_STATE_CSD);
+ assert(yasl_private_surface_state(&surface.base) == YASL_PRIVATE_STATE_CSD);
uint32_t fullscreen[] = {XDG_TOPLEVEL_STATE_FULLSCREEN,
XDG_TOPLEVEL_STATE_ACTIVATED, XDG_TOPLEVEL_STATE_FULLSCREEN, 31, UINT32_MAX};
configure(&surface, fullscreen, sizeof(fullscreen) / sizeof(*fullscreen));
assert(notifications.count == 1);
- assert(notifications.state == (YASL_STATE_CSD | YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
configure(&surface, fullscreen, sizeof(fullscreen) / sizeof(*fullscreen));
assert(notifications.count == 1);
/* Decoration changes preserve the other flags and do not notify twice. */
toplevel_decoration_configure(&surface, NULL, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
assert(notifications.count == 2);
- assert(notifications.state == (YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
toplevel_decoration_configure(&surface, NULL, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
assert(notifications.count == 2);
uint32_t maximized[] = {XDG_TOPLEVEL_STATE_MAXIMIZED, XDG_TOPLEVEL_STATE_SUSPENDED};
configure(&surface, maximized, sizeof(maximized) / sizeof(*maximized));
assert(notifications.count == 3);
- assert(notifications.state == (YASL_STATE_MAXIMIZED | YASL_STATE_SUSPENDED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_SUSPENDED));
toplevel_decoration_configure(&surface, NULL, ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
assert(notifications.count == 4);
- assert(notifications.state == (YASL_STATE_CSD | YASL_STATE_MAXIMIZED | YASL_STATE_SUSPENDED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_SUSPENDED));
/* Each tiled edge maps to the same portable flag; changing edges alone
* leaves the reported state unchanged. */
@@ -59,17 +73,38 @@ int main(void)
for (size_t i = 0; i < sizeof(edges) / sizeof(*edges); i++) {
configure(&surface, &edges[i], 1);
assert(notifications.count == 5);
- assert(notifications.state == (YASL_STATE_CSD | YASL_STATE_TILED));
+ assert(notifications.state == (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_TILED));
}
configure(&surface, edges, 0);
assert(notifications.count == 6);
- assert(notifications.state == YASL_STATE_CSD);
+ assert(notifications.state == YASL_PRIVATE_STATE_CSD);
/* State still advances when applications have not installed callbacks. */
wayland_surface_set_callbacks(&surface, NULL, NULL);
configure(&surface, fullscreen, sizeof(fullscreen) / sizeof(*fullscreen));
- assert(yasl_surface_state(&surface.base) ==
- (YASL_STATE_CSD | YASL_STATE_FULLSCREEN | YASL_STATE_ACTIVATED));
+ assert(yasl_private_surface_state(&surface.base) ==
+ (YASL_PRIVATE_STATE_CSD | YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_ACTIVATED));
assert(notifications.count == 6);
+
+ /* External presentation has no SHM commit callback to acknowledge xdg
+ * configures. Apply geometry and acknowledge before renderer submission. */
+ struct wayland_surface gpu = {
+ .base.presenter = YASL_PRIVATE_PRESENTER_VULKAN,
+ .width = 0, .height = 0,
+ .logical_width = 64, .logical_height = 64,
+ .req_width = 64, .req_height = 64,
+ .scale_120 = YASL_PRIVATE_SCALE_UNIT,
+ .pending_scale_120 = 180,
+ };
+ acknowledge_count = 0;
+ xdg_surface_configure(&gpu, (struct xdg_surface *)&gpu, 1234);
+ assert(acknowledge_count == 1 && acknowledged_serial == 1234);
+ assert(!gpu.has_pending_serial && !gpu.size_pending);
+ assert(gpu.configured && gpu.width == 96 && gpu.height == 96);
+
+ /* CPU presentation keeps its existing deferred ack with the SHM commit. */
+ struct wayland_surface cpu = {.base.presenter = YASL_PRIVATE_PRESENTER_CPU};
+ xdg_surface_configure(&cpu, (struct xdg_surface *)&cpu, 5678);
+ assert(acknowledge_count == 1 && cpu.has_pending_serial && cpu.want_draw);
return 0;
}
diff --git a/tests/wayland/test_tablet.c b/tests/wayland/test_tablet.c
index c76ddf8..f47fbfa 100644
--- a/tests/wayland/test_tablet.c
+++ b/tests/wayland/test_tablet.c
@@ -1,63 +1,101 @@
#include "../../src/platform/wayland/pointer.c"
#include <assert.h>
-static struct yasl_event next(struct wayland_surface *surface)
+static struct yasl_private_event next_raw(struct wayland_surface *surface)
{
- struct yasl_event event;
- assert(yasl_surface_poll_event(&surface->base, &event));
+ struct yasl_private_event event;
+ assert(yasl_private_surface_poll_event(&surface->base, &event));
assert(event.surface == &surface->base);
return event;
}
+static struct yasl_private_event next_pointer(struct wayland_surface *surface)
+{
+ struct yasl_private_event event;
+ do { event = next_raw(surface); } while (event.type == YASL_PRIVATE_EVENT_PEN);
+ return event;
+}
+
int main(void)
{
- struct wayland_display display = {.base.ops = &yasl_wayland_backend};
+ struct wayland_display display = {.base.ops = &yasl_private_wayland_backend};
struct wayland_surface surface = {.base.display = &display.base, .conn = &display,
.scale_factor = 1.5};
struct seat seat = {.conn = &display, .tablet_focus = &surface};
- struct tablet_tool tool = {.seat = &seat};
+ struct tablet_tool tool = {.seat = &seat, .device_id = 77, .tool_id = 88, .kind = 1};
seat.tool = &tool;
tablet_tool_motion(&tool, NULL, wl_fixed_from_int(100), wl_fixed_from_int(120));
tool_pressure(&tool, NULL, 32768);
tool_tilt(&tool, NULL, wl_fixed_from_int(-35), wl_fixed_from_int(42));
+ tool_distance(&tool, NULL, 16384);
+ tool_rotation(&tool, NULL, wl_fixed_from_int(17));
+ tool_slider(&tool, NULL, -32768);
+ pen_action_push(&tool, YASL_PRIVATE_PEN_ENTER, 0);
tablet_tool_down(&tool, NULL, 1);
tool_frame(&tool, NULL, 0);
- struct yasl_event ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_MOTION && ev.pointer.device == YASL_PTR_DEV_PEN);
+ struct yasl_private_event pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_ENTER && !pen.pen.in_contact);
+ assert(pen.pen.device_id == 77 && pen.pen.tool_id == 88);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN);
+ assert(pen.pen.action == YASL_PRIVATE_PEN_DOWN && pen.pen.in_contact);
+ assert(pen.pen.buttons & YASL_PRIVATE_BUTTON_BIT(YASL_PRIVATE_BUTTON_PRIMARY));
+ assert(pen.pen.x == 150 && pen.pen.y == 180);
+ assert(fabs(pen.pen.pressure - (32768.0 / 65535.0)) < 0.00001);
+ assert(pen.pen.axes_valid == (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT |
+ YASL_PRIVATE_PEN_DISTANCE | YASL_PRIVATE_PEN_ROTATION | YASL_PRIVATE_PEN_TANGENTIAL));
+ assert(pen.pen.axes_changed == pen.pen.axes_valid);
+ assert(fabs(pen.pen.distance - 16384.0 / 65535.0) < 0.00001);
+ assert(pen.pen.rotation == 17 && pen.pen.tangential == -32768.0 / 65535.0);
+ struct yasl_private_event ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_MOTION && ev.pointer.device == YASL_PRIVATE_PTR_DEV_PEN);
assert(ev.pointer.pos.x == 150 && ev.pointer.pos.y == 180 && ev.pointer.pen.pressure == 32768);
assert(ev.pointer.pen.tilt_x == -35 && ev.pointer.pen.tilt_y == 42);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_DOWN && ev.pointer.button == YASL_BUTTON_PRIMARY && ev.pointer.pen.pressure == 32768);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_DOWN && ev.pointer.button == YASL_PRIVATE_BUTTON_PRIMARY && ev.pointer.pen.pressure == 32768);
/* Stationary pressure and tilt changes are still motion samples. */
tool_pressure(&tool, NULL, 100000);
tool_tilt(&tool, NULL, wl_fixed_from_int(-120), wl_fixed_from_int(120));
tool_frame(&tool, NULL, 0);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.action == YASL_PRIVATE_PEN_MOVE);
+ assert(pen.pen.axes_changed == (YASL_PRIVATE_PEN_PRESSURE | YASL_PRIVATE_PEN_TILT));
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_MOTION && ev.pointer.pen.pressure == 65535);
assert(ev.pointer.pos.x == 150 && ev.pointer.pos.y == 180);
assert(ev.pointer.pen.tilt_x == -90 && ev.pointer.pen.tilt_y == 90);
tablet_tool_up(&tool, NULL);
tool_frame(&tool, NULL, 0);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_UP && ev.pointer.button == YASL_BUTTON_PRIMARY && !ev.pointer.pen.pressure);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.action == YASL_PRIVATE_PEN_UP);
+ assert(!pen.pen.in_contact && pen.pen.pressure == 0);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_UP && ev.pointer.button == YASL_PRIVATE_BUTTON_PRIMARY && !ev.pointer.pen.pressure);
tool_type(&tool, NULL, ZWP_TABLET_TOOL_V2_TYPE_ERASER);
tool_pressure(&tool, NULL, 22000);
tool_frame(&tool, NULL, 0);
- assert(next(&surface).pointer.device == YASL_PTR_DEV_ERASER);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.tool == 2);
+ assert(next_pointer(&surface).pointer.device == YASL_PRIVATE_PTR_DEV_ERASER);
tool_wheel(&tool, NULL, 0, 1);
tool_frame(&tool, NULL, 0);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PTR_DEV_ERASER);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.axes_changed == YASL_PRIVATE_PEN_WHEEL);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER);
assert(ev.pointer.scroll.x == 0 && ev.pointer.scroll.y == 1);
tablet_tool_proximity_out(&tool, NULL);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_LEAVE && ev.pointer.device == YASL_PTR_DEV_ERASER && !ev.pointer.pen.pressure);
+ pen = next_raw(&surface);
+ assert(pen.type == YASL_PRIVATE_EVENT_PEN && pen.pen.action == YASL_PRIVATE_PEN_LEAVE);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_LEAVE && ev.pointer.device == YASL_PRIVATE_PTR_DEV_ERASER && !ev.pointer.pen.pressure);
assert(!seat.tool && !seat.tablet_focus && !seat.tool_buttons);
- assert(!(yasl_display_caps(&display.base) & YASL_CAP_TABLET));
+ assert(!(yasl_private_display_caps(&display.base) & YASL_PRIVATE_CAP_TABLET));
display.tablet_mgr = (void *)&display; /* Capability depends on protocol availability. */
- assert(yasl_display_caps(&display.base) & YASL_CAP_TABLET);
+ assert(yasl_private_display_caps(&display.base) & YASL_PRIVATE_CAP_TABLET);
seat.pointer_focus = &surface;
/* A compositor may describe the same detent in three ways. value120 wins,
@@ -67,13 +105,32 @@ int main(void)
pointer_axis_value120(&seat, NULL, WL_POINTER_AXIS_VERTICAL_SCROLL, 30);
pointer_axis_value120(&seat, NULL, WL_POINTER_AXIS_HORIZONTAL_SCROLL, -60);
pointer_frame(&seat, NULL);
- ev = next(&surface);
- assert(ev.type == YASL_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PTR_DEV_MOUSE);
+ ev = next_pointer(&surface);
+ assert(ev.type == YASL_PRIVATE_EVENT_POINTER_SCROLL && ev.pointer.device == YASL_PRIVATE_PTR_DEV_MOUSE);
assert(ev.pointer.scroll.x == -0.5 && ev.pointer.scroll.y == 0.25);
- struct yasl_event unused;
- assert(!yasl_surface_poll_event(&surface.base, &unused));
+ assert(ev.pointer.scroll_valid == 1);
+ assert(ev.pointer.scroll_source == 1 && ev.pointer.scroll_phase == 0);
+ struct yasl_private_event unused;
+ assert(!yasl_private_surface_poll_event(&surface.base, &unused));
+ pointer_frame(&seat, NULL);
+ assert(!yasl_private_surface_poll_event(&surface.base, &unused));
+
+ /* Finger scrolling carries pixel offsets and coherent gesture phases. */
+ pointer_axis_source(&seat, NULL, WL_POINTER_AXIS_SOURCE_FINGER);
+ pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(1.25));
+ pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(-2.5));
+ pointer_frame(&seat, NULL);
+ ev = next_pointer(&surface);
+ assert(ev.pointer.scroll_phase == 1 && ev.pointer.scroll_source == 2);
+ assert(ev.pointer.pixel_scroll.x == -3.75 && ev.pointer.pixel_scroll.y == 1.875);
+ pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_double(1.25));
+ pointer_frame(&seat, NULL);
+ ev = next_pointer(&surface);
+ assert(ev.pointer.scroll_phase == 2 && ev.pointer.scroll.y == 0.125);
+ pointer_axis_stop(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL);
pointer_frame(&seat, NULL);
- assert(!yasl_surface_poll_event(&surface.base, &unused));
+ ev = next_pointer(&surface);
+ assert(ev.pointer.scroll_phase == 3 && ev.pointer.scroll.x == 0 && ev.pointer.scroll.y == 0);
/* Stops preserve offsets from the same frame. Repeated tiny movements
* must be visible immediately rather than held until a whole detent. */
@@ -83,17 +140,19 @@ int main(void)
pointer_axis(&seat, NULL, 0, WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_double(-2.5));
pointer_axis_stop(&seat, NULL, 0, WL_POINTER_AXIS_VERTICAL_SCROLL);
pointer_frame(&seat, NULL);
- ev = next(&surface);
+ ev = next_pointer(&surface);
assert(ev.pointer.scroll.x == -0.25 && ev.pointer.scroll.y == 0.125);
+ assert(ev.pointer.scroll_source == 2 && ev.pointer.scroll_phase == 3);
+ assert(ev.pointer.pixel_scroll.x == -3.75 && ev.pointer.pixel_scroll.y == 1.875);
}
pointer_axis_discrete(&seat, NULL, WL_POINTER_AXIS_HORIZONTAL_SCROLL, 2);
pointer_frame(&seat, NULL);
- ev = next(&surface);
+ ev = next_pointer(&surface);
assert(ev.pointer.scroll.x == 2 && ev.pointer.scroll.y == 0);
pointer_axis_value120(&seat, NULL, WL_POINTER_AXIS_VERTICAL_SCROLL, 60);
seat_pointer_reset(&seat);
pointer_frame(&seat, NULL);
- assert(!yasl_surface_poll_event(&surface.base, &unused));
+ assert(!yasl_private_surface_poll_event(&surface.base, &unused));
input_queue_clear(&surface.input);
return 0;
}