AtlatestRepositorysigil-wm

sigil-wm / tree / testbackend-pointer.c

1/* SPDX-License-Identifier: BSD-3-Clause
2 * Test-owned input on the backend event loop; no product input rule changes. */
3#define _GNU_SOURCE
4#include <dlfcn.h>
5#include <inttypes.h>
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <time.h>
10#include <unistd.h>
11#include <wayland-server-core.h>
12#include <wlr/backend/headless.h>
13#include <wlr/interfaces/wlr_pointer.h>
15struct pointer_fixture {
16 struct wlr_backend *backend;
17 struct wl_event_source *timer;
18 struct wl_listener destroy;
19 struct wlr_pointer pointer;
20 bool initialized;
21};
22static const struct wlr_pointer_impl pointer_impl = {.name = "backend-input-test"};
24static int poll_input(void *data) {
25 struct pointer_fixture *fixture = data;
26 const char *control = getenv("SIGIL_WM_BACKEND_POINTER_CONTROL");
27 if (control && unlink(control) == 0) {
28 if (!fixture->initialized) {
29 wlr_pointer_init(&fixture->pointer, &pointer_impl, "Backend input test");
30 fixture->initialized = true;
31 wl_signal_emit_mutable(&fixture->backend->events.new_input, &fixture->pointer.base);
32 }
33 uintptr_t tag = (uintptr_t)fixture->pointer.base.data;
34 if ((tag & 1) || !(tag >> 1)) abort();
35 struct timespec now;
36 if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) abort();
37 struct wlr_pointer_motion_event event = {
38 .pointer = &fixture->pointer,
39 .time_msec = (uint32_t)((uint64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000),
40 .delta_x = 1, .unaccel_dx = 1,
41 };
42 wl_signal_emit_mutable(&fixture->pointer.events.motion, &event);
43 wl_signal_emit_mutable(&fixture->pointer.events.frame, NULL);
44 fprintf(stderr, "BACKEND_POINTER_ACTIVITY=PASS origin=0 device=%" PRIuPTR "\n", tag >> 1);
45 fflush(stderr);
46 }
47 return wl_event_source_timer_update(fixture->timer, 50);
50static void destroy_fixture(struct wl_listener *listener, void *data) {
51 (void)data;
52 struct pointer_fixture *fixture = wl_container_of(listener, fixture, destroy);
53 wl_list_remove(&fixture->destroy.link);
54 wl_event_source_remove(fixture->timer);
55 if (fixture->initialized) wlr_pointer_finish(&fixture->pointer);
56 free(fixture);
59struct wlr_backend *wlr_headless_backend_create(struct wl_event_loop *loop) {
60 typedef struct wlr_backend *(*create_fn)(struct wl_event_loop *);
61 create_fn create = (create_fn)dlsym(RTLD_NEXT, "wlr_headless_backend_create");
62 if (!create) abort();
63 struct wlr_backend *backend = create(loop);
64 if (!backend || !getenv("SIGIL_WM_BACKEND_POINTER_CONTROL")) return backend;
65 struct pointer_fixture *fixture = calloc(1, sizeof(*fixture));
66 if (!fixture) abort();
67 fixture->backend = backend;
68 fixture->destroy.notify = destroy_fixture;
69 wl_signal_add(&backend->events.destroy, &fixture->destroy);
70 fixture->timer = wl_event_loop_add_timer(loop, poll_input, fixture);
71 if (!fixture->timer || wl_event_source_timer_update(fixture->timer, 50) != 0) abort();
72 return backend;