blob: c7ab4e55414901bdefe7c23f3618fd4e449be5ce [file] [log] [blame]
U. Artie Eoff1ba9b382012-12-07 13:50:32 -08001/*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
27#include <sys/mman.h>
28
29#include "../shared/os-compatibility.h"
30#include "weston-test-client-helper.h"
31
32int
33surface_contains(struct surface *surface, int x, int y)
34{
35 /* test whether a global x,y point is contained in the surface */
36 int sx = surface->x;
37 int sy = surface->y;
38 int sw = surface->width;
39 int sh = surface->height;
40 return x >= sx && y >= sy && x < sx + sw && y < sy + sh;
41}
42
Kristian Høgsbergdb6dc7d2012-12-11 21:49:13 -050043static void
44move_client_frame_handler(void *data,
45 struct wl_callback *callback, uint32_t time)
46{
47 int *done = data;
48
49 *done = 1;
50
51 wl_callback_destroy(callback);
52}
53
54static const struct wl_callback_listener frame_listener = {
55 move_client_frame_handler
56};
57
U. Artie Eoff1ba9b382012-12-07 13:50:32 -080058void
59move_client(struct client *client, int x, int y)
60{
61 struct surface *surface = client->surface;
Kristian Høgsbergdb6dc7d2012-12-11 21:49:13 -050062 struct wl_callback *callback;
63 int done;
U. Artie Eoff1ba9b382012-12-07 13:50:32 -080064
65 client->surface->x = x;
66 client->surface->y = y;
67 wl_test_move_surface(client->test->wl_test, surface->wl_surface,
68 surface->x, surface->y);
69 wl_surface_damage(surface->wl_surface, 0, 0, surface->width,
70 surface->height);
Kristian Høgsbergdb6dc7d2012-12-11 21:49:13 -050071
72 callback = wl_surface_frame(surface->wl_surface);
73 done = 0;
74 wl_callback_add_listener(callback, &frame_listener, &done);
75
U. Artie Eoff1ba9b382012-12-07 13:50:32 -080076 wl_surface_commit(surface->wl_surface);
77
Kristian Høgsbergdb6dc7d2012-12-11 21:49:13 -050078 while (!done)
79 wl_display_dispatch(client->wl_display);
U. Artie Eoff1ba9b382012-12-07 13:50:32 -080080}
81
82static void
83pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
84 uint32_t serial, struct wl_surface *wl_surface,
85 wl_fixed_t x, wl_fixed_t y)
86{
87 struct pointer *pointer = data;
88
89 pointer->focus = wl_surface_get_user_data(wl_surface);
90 pointer->x = wl_fixed_to_int(x);
91 pointer->y = wl_fixed_to_int(y);
92
93 fprintf(stderr, "test-client: got pointer enter %d %d, surface %p\n",
94 pointer->x, pointer->y, pointer->focus);
95}
96
97static void
98pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
99 uint32_t serial, struct wl_surface *wl_surface)
100{
101 struct pointer *pointer = data;
102
103 pointer->focus = NULL;
104
105 fprintf(stderr, "test-client: got pointer leave, surface %p\n",
106 wl_surface_get_user_data(wl_surface));
107}
108
109static void
110pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
111 uint32_t time, wl_fixed_t x, wl_fixed_t y)
112{
113 struct pointer *pointer = data;
114
115 pointer->x = wl_fixed_to_int(x);
116 pointer->y = wl_fixed_to_int(y);
117
118 fprintf(stderr, "test-client: got pointer motion %d %d\n",
119 pointer->x, pointer->y);
120}
121
122static void
123pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
124 uint32_t serial, uint32_t time, uint32_t button,
125 uint32_t state)
126{
127 struct pointer *pointer = data;
128
129 pointer->button = button;
130 pointer->state = state;
131
132 fprintf(stderr, "test-client: got pointer button %u %u\n",
133 button, state);
134}
135
136static void
137pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
138 uint32_t time, uint32_t axis, wl_fixed_t value)
139{
140 fprintf(stderr, "test-client: got pointer axis %u %d\n", axis, value);
141}
142
143static const struct wl_pointer_listener pointer_listener = {
144 pointer_handle_enter,
145 pointer_handle_leave,
146 pointer_handle_motion,
147 pointer_handle_button,
148 pointer_handle_axis,
149};
150
151static void
152keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
153 uint32_t format, int fd, uint32_t size)
154{
155 close(fd);
156
157 fprintf(stderr, "test-client: got keyboard keymap\n");
158}
159
160static void
161keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
162 uint32_t serial, struct wl_surface *wl_surface,
163 struct wl_array *keys)
164{
165 struct keyboard *keyboard = data;
166
167 keyboard->focus = wl_surface_get_user_data(wl_surface);
168
169 fprintf(stderr, "test-client: got keyboard enter, surface %p\n",
170 keyboard->focus);
171}
172
173static void
174keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
175 uint32_t serial, struct wl_surface *wl_surface)
176{
177 struct keyboard *keyboard = data;
178
179 keyboard->focus = NULL;
180
181 fprintf(stderr, "test-client: got keyboard leave, surface %p\n",
182 wl_surface_get_user_data(wl_surface));
183}
184
185static void
186keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
187 uint32_t serial, uint32_t time, uint32_t key,
188 uint32_t state)
189{
190 struct keyboard *keyboard = data;
191
192 keyboard->key = key;
193 keyboard->state = state;
194
195 fprintf(stderr, "test-client: got keyboard key %u %u\n", key, state);
196}
197
198static void
199keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
200 uint32_t serial, uint32_t mods_depressed,
201 uint32_t mods_latched, uint32_t mods_locked,
202 uint32_t group)
203{
204 struct keyboard *keyboard = data;
205
206 keyboard->mods_depressed = mods_depressed;
207 keyboard->mods_latched = mods_latched;
208 keyboard->mods_locked = mods_locked;
209 keyboard->group = group;
210
211 fprintf(stderr, "test-client: got keyboard modifiers %u %u %u %u\n",
212 mods_depressed, mods_latched, mods_locked, group);
213}
214
215static const struct wl_keyboard_listener keyboard_listener = {
216 keyboard_handle_keymap,
217 keyboard_handle_enter,
218 keyboard_handle_leave,
219 keyboard_handle_key,
220 keyboard_handle_modifiers,
221};
222
223static void
224surface_enter(void *data,
225 struct wl_surface *wl_surface, struct wl_output *output)
226{
227 struct surface *surface = data;
228
229 surface->output = wl_output_get_user_data(output);
230
231 fprintf(stderr, "test-client: got surface enter output %p\n",
232 surface->output);
233}
234
235static void
236surface_leave(void *data,
237 struct wl_surface *wl_surface, struct wl_output *output)
238{
239 struct surface *surface = data;
240
241 surface->output = NULL;
242
243 fprintf(stderr, "test-client: got surface leave output %p\n",
244 wl_output_get_user_data(output));
245}
246
247static const struct wl_surface_listener surface_listener = {
248 surface_enter,
249 surface_leave
250};
251
252static void
253create_shm_buffer(struct client *client)
254{
255 struct surface *surface = client->surface;
256 struct wl_shm *shm = client->wl_shm;
257 struct wl_shm_pool *pool;
258 int fd, size, stride;
259
260 stride = surface->width * 4;
261 size = stride * surface->height;
262
263 fd = os_create_anonymous_file(size);
264 assert(fd >= 0);
265
266 surface->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
267 fd, 0);
268 if (surface->data == MAP_FAILED) {
269 close(fd);
270 assert(surface->data != MAP_FAILED);
271 }
272
273 pool = wl_shm_create_pool(shm, fd, size);
274 surface->wl_buffer =
275 wl_shm_pool_create_buffer(pool, 0, surface->width,
276 surface->height, stride,
277 WL_SHM_FORMAT_ARGB8888);
278 wl_shm_pool_destroy(pool);
279
280 close(fd);
281}
282
283static void
284shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
285{
286 struct client *client = data;
287
288 if (format == WL_SHM_FORMAT_ARGB8888)
289 client->has_argb = 1;
290}
291
292struct wl_shm_listener shm_listener = {
293 shm_format
294};
295
296static void
297test_handle_pointer_position(void *data, struct wl_test *wl_test,
298 wl_fixed_t x, wl_fixed_t y)
299{
300 struct test *test = data;
301 test->pointer_x = wl_fixed_to_int(x);
302 test->pointer_y = wl_fixed_to_int(y);
303
304 fprintf(stderr, "test-client: got global pointer %d %d\n",
305 test->pointer_x, test->pointer_y);
306}
307
308static const struct wl_test_listener test_listener = {
309 test_handle_pointer_position
310};
311
312static void
313seat_handle_capabilities(void *data, struct wl_seat *seat,
314 enum wl_seat_capability caps)
315{
316 struct input *input = data;
317 struct pointer *pointer;
318 struct keyboard *keyboard;
319
320 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
321 pointer = calloc(1, sizeof *pointer);
322 pointer->wl_pointer = wl_seat_get_pointer(seat);
323 wl_pointer_set_user_data(pointer->wl_pointer, pointer);
324 wl_pointer_add_listener(pointer->wl_pointer, &pointer_listener,
325 pointer);
326 input->pointer = pointer;
327 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
328 wl_pointer_destroy(input->pointer->wl_pointer);
329 free(input->pointer);
330 input->pointer = NULL;
331 }
332
333 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
334 keyboard = calloc(1, sizeof *keyboard);
335 keyboard->wl_keyboard = wl_seat_get_keyboard(seat);
336 wl_keyboard_set_user_data(keyboard->wl_keyboard, keyboard);
337 wl_keyboard_add_listener(keyboard->wl_keyboard, &keyboard_listener,
338 keyboard);
339 input->keyboard = keyboard;
340 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
341 wl_keyboard_destroy(input->keyboard->wl_keyboard);
342 free(input->keyboard);
343 input->keyboard = NULL;
344 }
345}
346
347static const struct wl_seat_listener seat_listener = {
348 seat_handle_capabilities,
349};
350
351static void
352output_handle_geometry(void *data,
353 struct wl_output *wl_output,
354 int x, int y,
355 int physical_width,
356 int physical_height,
357 int subpixel,
358 const char *make,
359 const char *model,
360 int32_t transform)
361{
362 struct output *output = data;
363
364 output->x = x;
365 output->y = y;
366}
367
368static void
369output_handle_mode(void *data,
370 struct wl_output *wl_output,
371 uint32_t flags,
372 int width,
373 int height,
374 int refresh)
375{
376 struct output *output = data;
377
378 if (flags & WL_OUTPUT_MODE_CURRENT) {
379 output->width = width;
380 output->height = height;
381 }
382}
383
384static const struct wl_output_listener output_listener = {
385 output_handle_geometry,
386 output_handle_mode
387};
388
389static void
390handle_global(void *data, struct wl_registry *registry,
391 uint32_t id, const char *interface, uint32_t version)
392{
393 struct client *client = data;
394 struct input *input;
395 struct output *output;
396 struct test *test;
Kristian Høgsberg1cb3df42012-12-11 23:03:56 -0500397 struct global *global;
398
399 global = malloc(sizeof *global);
400 assert(global);
401 global->name = id;
402 global->interface = strdup(interface);
403 assert(interface);
404 global->version = version;
405 wl_list_insert(client->global_list.prev, &global->link);
U. Artie Eoff1ba9b382012-12-07 13:50:32 -0800406
407 if (strcmp(interface, "wl_compositor") == 0) {
408 client->wl_compositor =
409 wl_registry_bind(registry, id,
410 &wl_compositor_interface, 1);
411 } else if (strcmp(interface, "wl_seat") == 0) {
412 input = calloc(1, sizeof *input);
413 input->wl_seat =
414 wl_registry_bind(registry, id,
415 &wl_seat_interface, 1);
416 wl_seat_add_listener(input->wl_seat, &seat_listener, input);
417 client->input = input;
418 } else if (strcmp(interface, "wl_shm") == 0) {
419 client->wl_shm =
420 wl_registry_bind(registry, id,
421 &wl_shm_interface, 1);
422 wl_shm_add_listener(client->wl_shm, &shm_listener, client);
423 } else if (strcmp(interface, "wl_output") == 0) {
424 output = malloc(sizeof *output);
425 output->wl_output =
426 wl_registry_bind(registry, id,
427 &wl_output_interface, 1);
428 wl_output_add_listener(output->wl_output,
429 &output_listener, output);
430 client->output = output;
431 } else if (strcmp(interface, "wl_test") == 0) {
432 test = calloc(1, sizeof *test);
433 test->wl_test =
434 wl_registry_bind(registry, id,
435 &wl_test_interface, 1);
436 wl_test_add_listener(test->wl_test, &test_listener, test);
437 client->test = test;
438 }
439}
440
441static const struct wl_registry_listener registry_listener = {
442 handle_global
443};
444
445struct client *
446client_create(int x, int y, int width, int height)
447{
448 struct client *client;
449 struct surface *surface;
450
451 /* connect to display */
452 client = calloc(1, sizeof *client);
453 client->wl_display = wl_display_connect(NULL);
454 assert(client->wl_display);
Kristian Høgsberg1cb3df42012-12-11 23:03:56 -0500455 wl_list_init(&client->global_list);
U. Artie Eoff1ba9b382012-12-07 13:50:32 -0800456
457 /* setup registry so we can bind to interfaces */
458 client->wl_registry = wl_display_get_registry(client->wl_display);
459 wl_registry_add_listener(client->wl_registry, &registry_listener, client);
460
461 /* trigger global listener */
462 wl_display_dispatch(client->wl_display);
463 wl_display_roundtrip(client->wl_display);
464
465 /* must have WL_SHM_FORMAT_ARGB32 */
466 assert(client->has_argb);
467
468 /* must have wl_test interface */
469 assert(client->test);
470
471 /* must have an output */
472 assert(client->output);
473
474 /* initialize the client surface */
475 surface = calloc(1, sizeof *surface);
476
477 surface->wl_surface =
478 wl_compositor_create_surface(client->wl_compositor);
479 assert(surface->wl_surface);
480
481 wl_surface_add_listener(surface->wl_surface, &surface_listener,
482 surface);
483
484 client->surface = surface;
485 wl_surface_set_user_data(surface->wl_surface, surface);
486
487 surface->width = width;
488 surface->height = height;
489 create_shm_buffer(client);
490
491 memset(surface->data, 64, width * height * 4);
492 wl_surface_attach(surface->wl_surface, surface->wl_buffer, 0, 0);
493
494 move_client(client, x, y);
495
496 return client;
497}