blob: 59e6970e3af8f93aa341eb133bf9ef9ac10a02ca [file] [log] [blame]
Kristian Høgsberg3018b442012-04-27 15:02:56 -04001/*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <sys/socket.h>
26#include <assert.h>
27#include <unistd.h>
Kristian Høgsberg3018b442012-04-27 15:02:56 -040028#include <string.h>
29
30#include "test-runner.h"
31
U. Artie Eoff1ae298f2012-09-28 06:39:30 -070032struct state {
33 int px; /* pointer x */
34 int py; /* pointer y */
35 int sx; /* surface x */
36 int sy; /* surface y */
37 int sw; /* surface width */
38 int sh; /* surface height */
39};
40
41static size_t state_size = sizeof(struct state);
42
43struct context {
44 struct weston_layer *layer;
45 struct weston_seat *seat;
46 struct weston_surface *surface;
47 int pointer_x; /* server pointer x */
48 int pointer_y; /* server pointer y */
49 size_t index;
50 struct wl_array states;
51};
52
53static void
54resize(struct context *context, int w, int h)
55{
56 /* resize the surface only if the width or height is different */
57 if (context->surface->geometry.width != w ||
58 context->surface->geometry.height != h) {
59
60 weston_surface_configure(context->surface,
61 context->surface->geometry.x,
62 context->surface->geometry.y,
63 w, h);
64 weston_surface_update_transform(context->surface);
65 weston_surface_damage(context->surface);
66
67 fprintf(stderr, "resize surface: %d %d\n",
68 context->surface->geometry.width,
69 context->surface->geometry.height);
70 }
71}
72
73static void
74move(struct context *context, int x, int y)
75{
76 /* move the surface only if x or y is different */
77 if (context->surface->geometry.x != x ||
78 context->surface->geometry.y != y) {
79
80 weston_surface_configure(context->surface,
81 x, y,
82 context->surface->geometry.width,
83 context->surface->geometry.height);
84 weston_surface_update_transform(context->surface);
85 weston_surface_damage(context->surface);
86
87 fprintf(stderr, "move surface: %f %f\n",
88 context->surface->geometry.x,
89 context->surface->geometry.y);
90 }
91}
92
93static int
94contains(struct context *context, int x, int y)
95{
96 /* test whether a global x,y point is contained in the surface */
97 int sx = context->surface->geometry.x;
98 int sy = context->surface->geometry.y;
99 int sw = context->surface->geometry.width;
100 int sh = context->surface->geometry.height;
101 return x >= sx && y >= sy && x < sx + sw && y < sy + sh;
102}
103
104static void
105move_pointer(struct context *context, int x, int y)
106{
107 if (contains(context, context->pointer_x, context->pointer_y)) {
108 /* pointer is currently on the surface */
109 notify_motion(context->seat, 100,
110 wl_fixed_from_int(x), wl_fixed_from_int(y));
111 } else {
112 /* pointer is not currently on the surface */
113 notify_pointer_focus(context->seat, context->surface->output,
114 wl_fixed_from_int(x),
115 wl_fixed_from_int(y));
116 }
117
118 /* update server expected pointer location */
119 context->pointer_x = x;
120 context->pointer_y = y;
121
122 fprintf(stderr, "move pointer: %d %d\n", x, y);
123}
124
125static void
126check_pointer(struct context *context, int cx, int cy)
127{
128 /*
129 * Check whether the client reported pointer position matches
130 * the server expected pointer position. The client
131 * reports -1,-1 when the pointer is not on its surface and
132 * a surface relative x,y otherwise.
133 */
134 int gx = context->surface->geometry.x + cx;
135 int gy = context->surface->geometry.y + cy;
136 if (!contains(context, gx, gy)) {
137 assert(!contains(context, context->pointer_x,
138 context->pointer_y));
139 } else {
140 assert(gx == context->pointer_x);
141 assert(gy == context->pointer_y);
142 }
143}
144
145static void
146check_visible(struct context *context, int visible)
147{
148 /*
149 * Check whether the client reported surface visibility matches
150 * the servers expected surface visibility
151 */
152 int ow = context->surface->output->width;
153 int oh = context->surface->output->height;
154 int sx = context->surface->geometry.x;
155 int sy = context->surface->geometry.y;
156 int sw = context->surface->geometry.width;
157 int sh = context->surface->geometry.height;
158
159 const int expect = sx < ow && sy < oh && sx + sw > 0 && sy + sh > 0;
160
161 assert(visible == expect);
162}
163
164static void
165handle_state(struct test_client *);
166
167static void
168set_state(struct test_client *client)
169{
170 struct state* state;
171 struct context *context = client->data;
172
173 if (context->index < context->states.size) {
174 state = context->states.data + context->index;
175 resize(context, state->sw, state->sh);
176 move(context, state->sx, state->sy);
177 move_pointer(context, state->px, state->py);
178 context->index += state_size;
179
180 test_client_send(client, "send-state\n");
181 client->handle = handle_state;
182 } else {
183 test_client_send(client, "bye\n");
184 client->handle = NULL;
185 }
186}
187
188static void
189handle_state(struct test_client *client)
190{
191 struct context *context = client->data;
192 wl_fixed_t x, y;
193 int visible;
194
195 assert(sscanf(client->buf, "%d %d %d", &x, &y, &visible) == 3);
196
197 check_pointer(context, wl_fixed_to_int(x), wl_fixed_to_int(y));
198 check_visible(context, visible);
199
200 set_state(client);
201}
202
203static void
204add_state(struct context *context, int px, int py, int sx, int sy,
205 int sw, int sh)
206{
207 struct state *state = wl_array_add(&context->states,
208 sizeof(struct state));
209
210 assert(state);
211
212 state->px = px;
213 state->py = py;
214 state->sx = sx;
215 state->sy = sy;
216 state->sw = sw;
217 state->sh = sh;
218}
219
220static void
221initialize_states(struct test_client *client)
222{
223 struct context *context = client->data;
224 struct weston_surface *surface = context->surface;
225
226 int x = surface->geometry.x;
227 int y = surface->geometry.y;
228 int w = surface->geometry.width;
229 int h = surface->geometry.height;
230
231 wl_array_init(&context->states);
232
233 /* move pointer outside top left */
234 add_state(context, x - 1, y - 1, x, y, w, h);
235 /* move pointer on top left */
236 add_state(context, x, y, x, y, w, h);
237 /* move pointer outside bottom left */
238 add_state(context, x - 1, y + h, x, y, w, h);
239 /* move pointer on bottom left */
240 add_state(context, x, y + h - 1, x, y, w, h);
241 /* move pointer outside top right */
242 add_state(context, x + w, y - 1, x, y, w, h);
243 /* move pointer on top right */
244 add_state(context, x + w - 1, y, x, y, w, h);
245 /* move pointer outside bottom right */
246 add_state(context, x + w, y + h, x, y, w, h);
247 /* move pointer on bottom right */
248 add_state(context, x + w - 1, y + h - 1, x, y, w, h);
249
250 /* move pointer outside top center */
251 add_state(context, x + w/2, y - 1, x, y, w, h);
252 /* move pointer on top center */
253 add_state(context, x + w/2, y, x, y, w, h);
254 /* move pointer outside bottom center */
255 add_state(context, x + w/2, y + h, x, y, w, h);
256 /* move pointer on bottom center */
257 add_state(context, x + w/2, y + h - 1, x, y, w, h);
258 /* move pointer outside left center */
259 add_state(context, x - 1, y + h/2, x, y, w, h);
260 /* move pointer on left center */
261 add_state(context, x, y + h/2, x, y, w, h);
262 /* move pointer outside right center */
263 add_state(context, x + w, y + h/2, x, y, w, h);
264 /* move pointer on right center */
265 add_state(context, x + w - 1, y + h/2, x, y, w, h);
266
267 /* move pointer outside of client */
268 add_state(context, 50, 50, x, y, w, h);
269 /* move client center to pointer */
270 add_state(context, 50, 50, 0, 0, w, h);
271
272 /* not visible */
273 add_state(context, 0, 0, 0, -h, w, h);
274 /* visible */
275 add_state(context, 0, 0, 0, -h+1, w, h);
276 /* not visible */
277 add_state(context, 0, 0, 0, context->surface->output->height, w, h);
278 /* visible */
279 add_state(context, 0, 0, 0, context->surface->output->height - 1, w, h);
280 /* not visible */
281 add_state(context, 0, 0, -w, 0, w, h);
282 /* visible */
283 add_state(context, 0, 0, -w+1, 0, w, h);
284 /* not visible */
285 add_state(context, 0, 0, context->surface->output->width, 0, w, h);
286 /* visible */
287 add_state(context, 0, 0, context->surface->output->width - 1, 0, w, h);
288
289 set_state(client);
290}
291
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400292static void
293handle_surface(struct test_client *client)
294{
295 uint32_t id;
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700296 struct context *context = client->data;
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400297 struct wl_resource *resource;
Philipp Brüschweiler468262b2012-08-14 14:46:38 +0200298 struct wl_list *seat_list;
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400299
300 assert(sscanf(client->buf, "surface %u", &id) == 1);
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700301 fprintf(stderr, "server: got surface id %u\n", id);
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400302 resource = wl_client_get_object(client->client, id);
303 assert(resource);
304 assert(strcmp(resource->object.interface->name, "wl_surface") == 0);
305
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700306 context->surface = (struct weston_surface *) resource;
307 weston_surface_set_color(context->surface, 0.0, 0.0, 0.0, 1.0);
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400308
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700309 context->layer = malloc(sizeof *context->layer);
310 assert(context->layer);
311 weston_layer_init(context->layer,
312 &client->compositor->cursor_layer.link);
313 wl_list_insert(&context->layer->surface_list,
314 &context->surface->layer_link);
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400315
Philipp Brüschweiler468262b2012-08-14 14:46:38 +0200316 seat_list = &client->compositor->seat_list;
317 assert(wl_list_length(seat_list) == 1);
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700318 context->seat = container_of(seat_list->next, struct weston_seat, link);
319
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400320 client->compositor->focus = 1; /* Make it work even if pointer is
321 * outside X window. */
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400322
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700323 resize(context, 100, 100);
324 move(context, 100, 100);
325 move_pointer(context, 150, 150);
326
327 test_client_send(client, "send-state\n");
328 client->handle = initialize_states;
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400329}
330
331TEST(event_test)
332{
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700333 struct context *context;
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400334 struct test_client *client;
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400335
Jan Arne Petersen6f83d0d2012-08-21 18:28:48 +0200336 client = test_client_launch(compositor, "test-client");
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400337 client->terminate = 1;
338
339 test_client_send(client, "create-surface\n");
340 client->handle = handle_surface;
341
U. Artie Eoff1ae298f2012-09-28 06:39:30 -0700342 context = calloc(1, sizeof *context);
343 assert(context);
344 client->data = context;
Kristian Høgsberg3018b442012-04-27 15:02:56 -0400345}