summaryrefslogtreecommitdiff
path: root/tests/wayland/test_cursor.c
blob: eb729a37dbaf15e42f2b5b3cbe800e8dcaf10d6d (plain)
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
111
112
113
114
115
116
117
118
119
#include "platform/wayland/internal.h"
#include <assert.h>

/* Record cursor requests without a compositor or tablet hardware. */
static int pointer_hides, tool_hides, pointer_shapes, tool_shapes;
static uint32_t pointer_serial, tool_serial, pointer_shape, tool_shape;
static struct wp_cursor_shape_device_v1 *pointer_device;

static void pointer_cursor(struct wl_pointer *pointer, uint32_t serial,
                           struct wl_surface *surface, int32_t x, int32_t y)
{
    assert(pointer && !surface && !x && !y);
    pointer_hides++;
    pointer_serial = serial;
}

static void tool_cursor(struct zwp_tablet_tool_v2 *tool, uint32_t serial,
                        struct wl_surface *surface, int32_t x, int32_t y)
{
    assert(tool && !surface && !x && !y);
    tool_hides++;
    tool_serial = serial;
}

static void cursor_shape(struct wp_cursor_shape_device_v1 *device,
                         uint32_t serial, uint32_t shape)
{
    if (device == pointer_device) {
        pointer_shapes++;
        pointer_serial = serial;
        pointer_shape = shape;
    } else {
        assert(device);
        tool_shapes++;
        tool_serial = serial;
        tool_shape = shape;
    }
}

static uint32_t pointer_version(struct wl_pointer *pointer)
{
    assert(pointer);
    return WL_POINTER_FRAME_SINCE_VERSION;
}

#define wl_pointer_set_cursor pointer_cursor
#define zwp_tablet_tool_v2_set_cursor tool_cursor
#define wp_cursor_shape_device_v1_set_shape cursor_shape
#define wl_pointer_get_version pointer_version
#include "../../src/platform/wayland/pointer.c"

int main(void)
{
    struct wayland_display display = {.base.ops = &yasl_wayland_backend};
    struct wayland_surface surface = {.base.display = &display.base, .conn = &display,
        .scale_factor = 1, .cursor = YASL_CURSOR_TEXT};
    surface.surface = (struct wl_surface *)&surface;
    wl_surface_set_user_data(surface.surface, &surface);
    display.surfaces = &surface;
    struct seat seat = {.conn = &display};
    seat.pointer = (struct wl_pointer *)&seat;
    display.seats = &seat;
    struct tablet_tool tool = {.seat = &seat};
    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);
    assert(!pointer_hides && !tool_hides);
    pointer_enter(&seat, seat.pointer, 10, surface.surface, 0, 0);
    assert(pointer_hides == 1 && pointer_serial == 10);
    tablet_tool_proximity_in(&tool, tool.proxy, 11, NULL, surface.surface);
    assert(tool_hides == 1 && tool_serial == 11);

    /* Hiding also works with no cursor-shape protocol, and preserves input. */
    pointer_motion(&seat, seat.pointer, 0, wl_fixed_from_int(12), wl_fixed_from_int(34));
    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);
    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(event.pointer.pos.x == 56 && event.pointer.pos.y == 78);
    assert(!yasl_surface_poll_event(&surface.base, &event));

    /* Each new entry needs a request with its own serial. */
    pointer_leave(&seat, seat.pointer, 12, surface.surface);
    pointer_frame(&seat, seat.pointer);
    tablet_tool_proximity_out(&tool, tool.proxy);
    pointer_enter(&seat, seat.pointer, 13, surface.surface, 0, 0);
    tool.eraser = true;
    tablet_tool_proximity_in(&tool, tool.proxy, 14, NULL, surface.surface);
    assert(pointer_hides == 2 && pointer_serial == 13);
    assert(tool_hides == 2 && tool_serial == 14);

    /* 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);
    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);
    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);
    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));
    assert(pointer_hides == 3 && tool_hides == 3);
    assert(pointer_shapes == 1 && tool_shapes == 1);
    input_queue_clear(&surface.input);
    return 0;
}