blob: 606eda3bedbcb641637cb125c6ed3358e947ce89 [file] [log] [blame]
Alexandros Frantzis6ee80ec2021-06-09 11:01:07 +03001/*
2 * Copyright 2021 Collabora Ltd
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26#include "config.h"
27
28#include <stdio.h>
29#include <string.h>
30#include <sys/mman.h>
31
32#include "shared/timespec-util.h"
33#include "weston-test-client-helper.h"
34#include "weston-test-fixture-compositor.h"
35
36struct setup_args {
37 struct fixture_metadata meta;
38 enum renderer_type renderer;
39};
40
41static const struct setup_args my_setup_args[] = {
42 {
43 .renderer = RENDERER_PIXMAN,
44 .meta.name = "pixman"
45 },
46 {
47 .renderer = RENDERER_GL,
48 .meta.name = "GL"
49 },
50};
51
52static enum test_result_code
53fixture_setup(struct weston_test_harness *harness, const struct setup_args *arg)
54{
55 struct compositor_setup setup;
56
57 compositor_setup_defaults(&setup);
58 setup.renderer = arg->renderer;
59 setup.width = 320;
60 setup.height = 240;
61 setup.shell = SHELL_TEST_DESKTOP;
62
63 return weston_test_harness_execute_as_client(harness, &setup);
64}
65DECLARE_FIXTURE_SETUP_WITH_ARG(fixture_setup, my_setup_args, meta);
66
67static const struct timespec t0 = { .tv_sec = 0, .tv_nsec = 0 };
68static const struct timespec t1 = { .tv_sec = 1, .tv_nsec = 0 };
69static const struct timespec t2 = { .tv_sec = 2, .tv_nsec = 0 };
70static const struct timespec t3 = { .tv_sec = 3, .tv_nsec = 0 };
71
72static void
73send_motion(struct client *client, const struct timespec *time, int x, int y)
74{
75 uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
76
77 timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
78 weston_test_move_pointer(client->test->weston_test, tv_sec_hi, tv_sec_lo,
79 tv_nsec, x, y);
80 client_roundtrip(client);
81}
82
83static struct buffer *
Pekka Paalanenee1c1772021-06-15 16:49:02 +030084surface_commit_color(struct client *client, struct surface *surface,
Alexandros Frantzis6ee80ec2021-06-09 11:01:07 +030085 pixman_color_t *color, int width, int height)
86{
87 struct buffer *buf;
88
89 buf = create_shm_buffer_a8r8g8b8(client, width, height);
90 fill_image_with_color(buf->image, color);
Pekka Paalanenee1c1772021-06-15 16:49:02 +030091 wl_surface_attach(surface->wl_surface, buf->proxy, 0, 0);
92 wl_surface_damage(surface->wl_surface, 0, 0, width, height);
93 wl_surface_commit(surface->wl_surface);
94
95 assert(!surface->buffer);
96 surface->buffer = buf;
Alexandros Frantzis6ee80ec2021-06-09 11:01:07 +030097
98 return buf;
99}
100
101TEST(pointer_cursor_retains_committed_buffer_after_reenter)
102{
103 struct client *client;
104 pixman_color_t red;
105 pixman_color_t green;
106 pixman_color_t gray;
107 pixman_color_t magenta;
108 bool match;
109 struct surface *main_surface;
110 struct surface *back_surface;
111 struct surface *main_cursor_surface;
112 struct surface *back_cursor_surface;
113
114 color_rgb888(&red, 255, 0, 0);
115 color_rgb888(&green, 0, 255, 0);
116 color_rgb888(&gray, 127, 127, 127);
117 color_rgb888(&magenta, 255, 0, 255);
118
119 client = create_client();
120
121 /* Move the cursor out of the way of the main surface */
122 send_motion(client, &t0, 0, 0);
123
124 /* Create all surfaces. */
125 main_surface = create_test_surface(client);
126 back_surface = create_test_surface(client);
127 main_cursor_surface = create_test_surface(client);
128 back_cursor_surface = create_test_surface(client);
129
130 /* Commit buffers for cursors. */
Pekka Paalanenee1c1772021-06-15 16:49:02 +0300131 surface_commit_color(client, main_cursor_surface, &green, 25, 25);
132 surface_commit_color(client, back_cursor_surface, &magenta, 25, 25);
Alexandros Frantzis6ee80ec2021-06-09 11:01:07 +0300133
134 /* We need our own background surface so that we are able to change the cursor
135 * when the pointer leaves the main surface.
136 */
137 weston_test_move_surface(client->test->weston_test, back_surface->wl_surface, 0, 0);
Pekka Paalanenee1c1772021-06-15 16:49:02 +0300138 surface_commit_color(client, back_surface, &gray, 320, 240);
Alexandros Frantzis6ee80ec2021-06-09 11:01:07 +0300139
140 /* Set up the main surface. */
141 client->surface = main_surface;
142 client->surface->buffer = create_shm_buffer_a8r8g8b8(client, 100, 100);
143 fill_image_with_color(client->surface->buffer->image, &red);
144 move_client(client, 50, 50);
145
146 /* Move the pointer into the main surface. */
147 send_motion(client, &t1, 100, 100);
148 wl_pointer_set_cursor(client->input->pointer->wl_pointer,
149 client->input->pointer->serial,
150 main_cursor_surface->wl_surface, 0, 0);
151 match = verify_screen_content(client, "pointer_cursor_reenter", 0,
152 NULL, 0);
153 assert(match);
154
155 /* Move the cursor just outside the main surface. */
156 send_motion(client, &t2, 150, 150);
157 wl_pointer_set_cursor(client->input->pointer->wl_pointer,
158 client->input->pointer->serial,
159 back_cursor_surface->wl_surface, 0, 0);
160 match = verify_screen_content(client, "pointer_cursor_reenter", 1,
161 NULL, 1);
162 assert(match);
163
164 /* And back in the main surface again. */
165 send_motion(client, &t3, 149, 149);
166 wl_pointer_set_cursor(client->input->pointer->wl_pointer,
167 client->input->pointer->serial,
168 main_cursor_surface->wl_surface, 0, 0);
169 match = verify_screen_content(client, "pointer_cursor_reenter", 2,
170 NULL, 2);
171 assert(match);
172
173 surface_destroy(back_cursor_surface);
174 surface_destroy(main_cursor_surface);
175 surface_destroy(back_surface);
176 /* main_surface is destroyed when destroying the client. */
177 client_destroy(client);
178}