2 * Copyright © 2012 Intel Corporation
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.
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.
25 #include <sys/socket.h>
30 #include "test-runner.h"
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 */
41 static size_t state_size = sizeof(struct state);
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 */
50 struct wl_array states;
54 resize(struct context *context, int w, int h)
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) {
60 weston_surface_configure(context->surface,
61 context->surface->geometry.x,
62 context->surface->geometry.y,
64 weston_surface_update_transform(context->surface);
65 weston_surface_damage(context->surface);
67 fprintf(stderr, "resize surface: %d %d\n",
68 context->surface->geometry.width,
69 context->surface->geometry.height);
74 move(struct context *context, int x, int y)
76 /* move the surface only if x or y is different */
77 if (context->surface->geometry.x != x ||
78 context->surface->geometry.y != y) {
80 weston_surface_configure(context->surface,
82 context->surface->geometry.width,
83 context->surface->geometry.height);
84 weston_surface_update_transform(context->surface);
85 weston_surface_damage(context->surface);
87 fprintf(stderr, "move surface: %f %f\n",
88 context->surface->geometry.x,
89 context->surface->geometry.y);
94 contains(struct context *context, int x, int y)
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;
105 move_pointer(struct context *context, int x, int y)
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));
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));
118 /* update server expected pointer location */
119 context->pointer_x = x;
120 context->pointer_y = y;
122 fprintf(stderr, "move pointer: %d %d\n", x, y);
126 check_pointer(struct context *context, int cx, int cy)
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.
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));
140 assert(gx == context->pointer_x);
141 assert(gy == context->pointer_y);
146 check_visible(struct context *context, int visible)
149 * Check whether the client reported surface visibility matches
150 * the servers expected surface visibility
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;
159 const int expect = sx < ow && sy < oh && sx + sw > 0 && sy + sh > 0;
161 assert(visible == expect);
165 handle_state(struct test_client *);
168 set_state(struct test_client *client)
171 struct context *context = client->data;
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;
180 test_client_send(client, "send-state\n");
181 client->handle = handle_state;
183 test_client_send(client, "bye\n");
184 client->handle = NULL;
189 handle_state(struct test_client *client)
191 struct context *context = client->data;
195 assert(sscanf(client->buf, "%d %d %d", &x, &y, &visible) == 3);
197 check_pointer(context, wl_fixed_to_int(x), wl_fixed_to_int(y));
198 check_visible(context, visible);
204 add_state(struct context *context, int px, int py, int sx, int sy,
207 struct state *state = wl_array_add(&context->states,
208 sizeof(struct state));
221 initialize_states(struct test_client *client)
223 struct context *context = client->data;
224 struct weston_surface *surface = context->surface;
226 int x = surface->geometry.x;
227 int y = surface->geometry.y;
228 int w = surface->geometry.width;
229 int h = surface->geometry.height;
231 wl_array_init(&context->states);
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);
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);
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);
273 add_state(context, 0, 0, 0, -h, w, h);
275 add_state(context, 0, 0, 0, -h+1, w, h);
277 add_state(context, 0, 0, 0, context->surface->output->height, w, h);
279 add_state(context, 0, 0, 0, context->surface->output->height - 1, w, h);
281 add_state(context, 0, 0, -w, 0, w, h);
283 add_state(context, 0, 0, -w+1, 0, w, h);
285 add_state(context, 0, 0, context->surface->output->width, 0, w, h);
287 add_state(context, 0, 0, context->surface->output->width - 1, 0, w, h);
293 handle_surface(struct test_client *client)
296 struct context *context = client->data;
297 struct wl_resource *resource;
298 struct wl_list *seat_list;
300 assert(sscanf(client->buf, "surface %u", &id) == 1);
301 fprintf(stderr, "server: got surface id %u\n", id);
302 resource = wl_client_get_object(client->client, id);
304 assert(strcmp(resource->object.interface->name, "wl_surface") == 0);
306 context->surface = (struct weston_surface *) resource;
307 weston_surface_set_color(context->surface, 0.0, 0.0, 0.0, 1.0);
309 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);
316 seat_list = &client->compositor->seat_list;
317 assert(wl_list_length(seat_list) == 1);
318 context->seat = container_of(seat_list->next, struct weston_seat, link);
320 client->compositor->focus = 1; /* Make it work even if pointer is
321 * outside X window. */
323 resize(context, 100, 100);
324 move(context, 100, 100);
325 move_pointer(context, 150, 150);
327 test_client_send(client, "send-state\n");
328 client->handle = initialize_states;
333 struct context *context;
334 struct test_client *client;
336 client = test_client_launch(compositor, "test-client");
337 client->terminate = 1;
339 test_client_send(client, "create-surface\n");
340 client->handle = handle_surface;
342 context = calloc(1, sizeof *context);
344 client->data = context;