2 * Copyright © 2012 Intel Corporation
3 * Copyright © 2013 TOYOTA MOTOR CORPORATION
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no representations
12 * about the suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * @brief Wayland Application for unit test of Weston(Wayland) IVI plugins
35 #include <wayland-client.h>
36 #include <linux/input.h>
37 #include "ico_window_mgr-client-protocol.h"
38 #include "ico_input_mgr-client-protocol.h"
39 #include "test-common.h"
41 #define MAX_CON_NAME 127
44 struct wl_display *display;
45 struct wl_registry *registry;
46 struct wl_compositor *compositor;
47 struct wl_shell *shell;
48 struct ico_window_mgr *ico_window_mgr;
49 struct ico_exinput *ico_exinput;
51 struct output *output;
52 struct surface *surface;
57 char connect[MAX_CON_NAME+1];
61 struct display *display;
63 struct wl_pointer *pointer;
64 struct wl_keyboard *keyboard;
65 struct wl_touch *touch;
68 struct surface *pointer_focus;
69 struct surface *keyboard_focus;
70 uint32_t last_key, last_key_state;
74 struct display *display;
75 struct wl_output *output;
81 struct display *display;
82 struct wl_surface *surface;
83 struct wl_shell_surface *shell_surface;
84 struct output *output;
88 EGLSurface egl_surface;
91 static void clear_surface(struct display *display);
94 pointer_handle_enter(void *data, struct wl_pointer *pointer,
95 uint32_t serial, struct wl_surface *surface,
96 wl_fixed_t x, wl_fixed_t y)
98 struct input *input = data;
100 input->pointer_focus = wl_surface_get_user_data(surface);
101 input->x = wl_fixed_to_double(x);
102 input->y = wl_fixed_to_double(y);
103 print_log("CLIENT: got pointer enter (%d,%d)=(%d,%d), surface %p",
104 x, y, (int)input->x, (int)input->y, surface);
108 pointer_handle_leave(void *data, struct wl_pointer *pointer,
109 uint32_t serial, struct wl_surface *surface)
111 struct input *input = data;
113 input->pointer_focus = NULL;
115 print_log("CLIENT: got pointer leave, surface %p", surface);
119 pointer_handle_motion(void *data, struct wl_pointer *pointer,
120 uint32_t time, wl_fixed_t x, wl_fixed_t y)
122 struct input *input = data;
124 input->x = wl_fixed_to_double(x);
125 input->y = wl_fixed_to_double(y);
127 print_log("CLIENT: got pointer motion (%d,%d)=(%d,%d)",
128 x, y, (int)input->x, (int)input->y);
132 pointer_handle_button(void *data, struct wl_pointer *pointer,
133 uint32_t serial, uint32_t time, uint32_t button, uint32_t state_w)
135 struct input *input = data;
137 enum wl_pointer_button_state state = state_w;
139 bit = 1 << (button - BTN_LEFT);
140 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
141 input->button_mask |= bit;
143 input->button_mask &= ~bit;
144 print_log("CLIENT: got pointer button %u %u", button, state_w);
148 pointer_handle_axis(void *data, struct wl_pointer *pointer,
149 uint32_t time, uint32_t axis, wl_fixed_t value)
151 fprintf(stderr, "CLIENT: got pointer axis %u %d\n", axis, value);
155 keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
156 uint32_t format, int fd, uint32_t size)
159 print_log("CLIENT: got keyboard keymap");
163 keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
164 uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
166 struct input *input = data;
168 input->keyboard_focus = wl_surface_get_user_data(surface);
169 print_log("CLIENT: got keyboard enter, surface %p", surface);
173 keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
174 uint32_t serial, struct wl_surface *surface)
176 struct input *input = data;
178 input->keyboard_focus = NULL;
179 print_log("CLIENT: got keyboard leave, surface %p", surface);
183 keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
184 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
186 struct input *input = data;
188 input->last_key = key;
189 input->last_key_state = state;
191 print_log("CLIENT: got keyboard key %u %u", key, state);
195 keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
196 uint32_t serial, uint32_t mods_depressed,
197 uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
199 print_log("CLIENT: got keyboard modifier");
203 touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time,
204 struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
206 print_log("CLIENT: got touch down %d (%d,%d)", id, x/256, y/256);
210 touch_handle_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time,
213 print_log("CLIENT: got touch up %d", id);
217 touch_handle_motion(void *data, struct wl_touch *wl_touch, uint32_t time,
218 int32_t id, wl_fixed_t x, wl_fixed_t y)
220 print_log("CLIENT: got touch motion %d (%d,%d)", id, x/256, y/256);
224 touch_handle_frame(void *data, struct wl_touch *wl_touch)
226 print_log("CLIENT: got touch frame");
230 touch_handle_cancel(void *data, struct wl_touch *wl_touch)
232 print_log("CLIENT: got touch cancel");
235 static const struct wl_pointer_listener pointer_listener = {
236 pointer_handle_enter,
237 pointer_handle_leave,
238 pointer_handle_motion,
239 pointer_handle_button,
243 static const struct wl_keyboard_listener keyboard_listener = {
244 keyboard_handle_keymap,
245 keyboard_handle_enter,
246 keyboard_handle_leave,
248 keyboard_handle_modifiers,
251 static const struct wl_touch_listener touch_listener = {
260 seat_handle_capabilities(void *data, struct wl_seat *seat,
261 enum wl_seat_capability caps)
263 struct input *input = data;
265 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
266 input->pointer = wl_seat_get_pointer(seat);
267 wl_pointer_set_user_data(input->pointer, input);
268 wl_pointer_add_listener(input->pointer, &pointer_listener, input);
270 else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
271 wl_pointer_destroy(input->pointer);
272 input->pointer = NULL;
275 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
276 input->keyboard = wl_seat_get_keyboard(seat);
277 wl_keyboard_set_user_data(input->keyboard, input);
278 wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input);
280 else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
281 wl_keyboard_destroy(input->keyboard);
282 input->keyboard = NULL;
285 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
286 input->touch = wl_seat_get_touch(seat);
287 wl_touch_set_user_data(input->touch, input);
288 wl_touch_add_listener(input->touch, &touch_listener, input);
290 else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) {
291 wl_touch_destroy(input->touch);
296 static const struct wl_seat_listener seat_listener = {
297 seat_handle_capabilities,
301 output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
302 int physical_width, int physical_height, int subpixel,
303 const char *make, const char *model, int32_t transform)
305 struct output *output = data;
307 print_log("CLIENT: Event[handle_geometry] x/y=%d/%d p.w/h=%d/%d trans=%d",
308 x, y, physical_width, physical_height, transform);
315 output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
316 int width, int height, int refresh)
318 struct output *output = data;
320 print_log("CLIENT: Event[handle_mode] %08x x/y=%d/%d flags=%08x refresh=%d",
321 (int)wl_output, width, height, flags, refresh);
323 if (flags & WL_OUTPUT_MODE_CURRENT) {
324 output->width = width;
325 output->height = height;
329 static const struct wl_output_listener output_listener = {
330 output_handle_geometry,
335 cb_input_capabilities(void *data, struct ico_exinput *ico_exinput,
336 const char *device, int32_t type, const char *swname, int32_t input,
337 const char *codename, int32_t code)
339 print_log("CLIENT: Event[input_capabilities] device=%s type=%d sw=%s input=%d "
340 "code=%s[%d]", device, type, swname, input, codename, code);
344 cb_input_code(void *data, struct ico_exinput *ico_exinput,
345 const char *device, int32_t input, const char *codename, int32_t code)
347 print_log("CLIENT: Event[input_code] device=%s input=%d code=%s[%d]",
348 device, input, codename, code);
352 cb_input_input(void *data, struct ico_exinput *ico_exinput, uint32_t time,
353 const char *device, int32_t input, int32_t code, int32_t state)
355 print_log("CLIENT: Event[input_input] device=%s input=%d code=%d state=%d",
356 device, input, code, state);
359 static const struct ico_exinput_listener exinput_listener = {
360 cb_input_capabilities,
366 shell_surface_ping(void *data, struct wl_shell_surface *wl_shell_surface, uint32_t serial)
368 print_log("CLIENT: shell_surface_ping: surface=%08x serial=%d",
369 (int)wl_shell_surface, serial);
373 shell_surface_configure(void *data, struct wl_shell_surface *wl_shell_surface,
374 uint32_t edges, int32_t width, int32_t height)
376 print_log("CLIENT: shell_surface_configure: surface=%08x edg=%x, width=%d height=%d",
377 (int)wl_shell_surface, edges, width, height);
381 shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
383 print_log("CLIENT: shell_surface_popup_done: surface=%08x", (int)wl_shell_surface);
386 static const struct wl_shell_surface_listener shell_surface_listener = {
388 shell_surface_configure,
389 shell_surface_popup_done
393 handle_global(void *data, struct wl_registry *registry, uint32_t id,
394 const char *interface, uint32_t version)
396 struct display *display = data;
398 struct output *output;
400 print_log("CLIENT: handle_global: interface=<%s> id=%d", interface, (int)id);
402 if (strcmp(interface, "wl_compositor") == 0) {
403 display->compositor = wl_registry_bind(display->registry, id,
404 &wl_compositor_interface, 1);
406 else if (strcmp(interface, "wl_seat") == 0) {
407 input = calloc(1, sizeof *input);
408 input->display = display;
409 input->seat = wl_registry_bind(display->registry, id, &wl_seat_interface, 1);
410 input->pointer_focus = NULL;
411 input->keyboard_focus = NULL;
413 wl_seat_add_listener(input->seat, &seat_listener, input);
414 display->input = input;
416 else if (strcmp(interface, "wl_output") == 0) {
417 output = malloc(sizeof *output);
418 output->display = display;
419 output->output = wl_registry_bind(display->registry, id, &wl_output_interface, 1);
420 wl_output_add_listener(output->output,
421 &output_listener, output);
422 display->output = output;
424 print_log("CLIENT: created output global %p", display->output);
426 else if (strcmp(interface, "wl_shell") == 0) {
427 display->shell = wl_registry_bind(display->registry, id, &wl_shell_interface, 1);
429 else if (strcmp(interface, "ico_window_mgr") == 0) {
430 display->ico_window_mgr = wl_registry_bind(display->registry, id,
431 &ico_window_mgr_interface, 1);
432 print_log("CLIENT: created window_mgr global %p", display->ico_window_mgr);
434 else if (strcmp(interface, "ico_exinput") == 0) {
435 display->ico_exinput = wl_registry_bind(display->registry, id,
436 &ico_exinput_interface, 1);
437 ico_exinput_add_listener(display->ico_exinput, &exinput_listener, display);
438 print_log("CLIENT: created exinput global %p", display->ico_exinput);
442 static const struct wl_registry_listener registry_listener = {
447 surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output)
449 struct surface *surface = data;
451 surface->output = wl_output_get_user_data(output);
453 print_log("CLIENT: got surface enter, output %p", surface->output);
457 surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *output)
459 struct surface *surface = data;
461 surface->output = NULL;
463 print_log("CLIENT: got surface leave, output %p", wl_output_get_user_data(output));
466 static const struct wl_surface_listener surface_listener = {
472 send_keyboard_state(struct display *display)
474 int focus = display->input->keyboard_focus != NULL;
477 assert(display->input->keyboard_focus == display->surface);
480 wl_display_flush(display->display);
482 print_log("CLIENT: keyboard_state %u %u %d",
483 display->input->last_key, display->input->last_key_state, focus);
485 wl_display_roundtrip(display->display);
489 send_button_state(struct display *display)
491 wl_display_roundtrip(display->display);
493 print_log("CLIENT: button_state %u", display->input->button_mask);
495 wl_display_roundtrip(display->display);
499 send_state(struct display* display)
501 int visible = display->surface->output != NULL;
502 wl_fixed_t x = wl_fixed_from_int(-1);
503 wl_fixed_t y = wl_fixed_from_int(-1);
505 if (display->input->pointer_focus != NULL) {
506 assert(display->input->pointer_focus == display->surface);
507 x = wl_fixed_from_double(display->input->x);
508 y = wl_fixed_from_double(display->input->y);
512 /* FIXME: this fails on multi-display setup */
513 /* assert(display->surface->output == display->output); */
516 wl_display_flush(display->display);
518 print_log("CLIENT: state %d %d %d", x, y, visible);
520 wl_display_roundtrip(display->display);
524 create_surface(struct display *display, const char *title)
526 struct surface *surface;
528 surface = malloc(sizeof *surface);
530 surface->display = display;
531 display->surface = surface;
532 surface->surface = wl_compositor_create_surface(display->compositor);
533 wl_surface_add_listener(surface->surface, &surface_listener, surface);
535 if (display->shell) {
536 surface->shell_surface =
537 wl_shell_get_shell_surface(display->shell, surface->surface);
538 if (surface->shell_surface) {
539 wl_shell_surface_add_listener(surface->shell_surface,
540 &shell_surface_listener, display);
541 wl_shell_surface_set_toplevel(surface->shell_surface);
542 wl_shell_surface_set_title(surface->shell_surface, title);
545 wl_display_flush(display->display);
547 print_log("CLIENT: create surface %d shell=%08x",
548 wl_proxy_get_id((struct wl_proxy *) surface->surface),
549 (int)surface->shell_surface);
551 poll(NULL, 0, 100); /* Wait for next frame where we'll get events. */
553 wl_display_roundtrip(display->display);
555 surface->dpy = opengl_init(display->display, &surface->conf, &surface->ctx);
557 surface->egl_surface = opengl_create_window(display->display, surface->surface,
558 surface->dpy, surface->conf,
559 surface->ctx, display->init_width,
560 display->init_height,
561 display->init_color);
562 clear_surface(display);
563 print_log("CLIENT: created egl_surface %08x", (int)surface->egl_surface);
568 clear_surface(struct display *display)
570 if (! display->surface) {
571 create_surface(display, "test-client");
574 opengl_clear_window(display->init_color);
575 opengl_swap_buffer(display->display,
576 display->surface->dpy, display->surface->egl_surface);
581 set_region(struct display *display, char *buf)
585 int x, y, width, height;
587 int c_x, c_y, c_width, c_height;
589 narg = pars_command(buf, args, 10);
591 x = strtol(args[1], (char **)0, 0);
592 y = strtol(args[2], (char **)0, 0);
593 width = strtol(args[3], (char **)0, 0);
594 height = strtol(args[4], (char **)0, 0);
595 hot_x = x + (width / 2);
596 hot_y = y + (height / 2);
599 c_width = width - 10;
600 if (c_width <= 0) c_width = 2;
601 c_height = height - 10;
602 if (c_height <= 0) c_height = 2;
603 print_log("CLIENT: ico_exinput_set_input_region(%s,%d,%d-%d,%d,"
604 "hot=%d,%d,cur=%d,%d-%d,%d,attr=0)",
605 args[0] ? args[0] : "(null)", x, y, width, height,
606 hot_x, hot_y, c_x, c_y, c_width, c_height);
607 if (strcasecmp(args[0], "NULL") == 0) {
608 ico_exinput_set_input_region(display->ico_exinput, "", x, y,
609 width, height, hot_x, hot_y, c_x, c_y,
610 c_width, c_height, 0);
613 ico_exinput_set_input_region(display->ico_exinput, args[0], x, y,
614 width, height, hot_x, hot_y, c_x, c_y,
615 c_width, c_height, 0);
619 print_log("CLIENT: set_region command[set_region winname@appid x y "
620 "width height] has no argument");
625 unset_region(struct display *display, char *buf)
629 int x, y, width, height;
631 narg = pars_command(buf, args, 10);
634 x = strtol(args[1], (char **)0, 0);
635 y = strtol(args[2], (char **)0, 0);
636 width = strtol(args[3], (char **)0, 0);
637 height = strtol(args[4], (char **)0, 0);
645 print_log("CLIENT: ico_exinput_unset_input_region(%s,08x,%d,%d-%d,%d)",
646 args[0] ? args[0] : "(null)", x, y, width, height);
647 if (strcasecmp(args[0], "NULL") == 0) {
648 ico_exinput_unset_input_region(display->ico_exinput, "", x, y,
652 ico_exinput_unset_input_region(display->ico_exinput, args[0],
653 x, y, width, height);
657 print_log("CLIENT: unset_region command[unset_region winname@appid x y "
658 "width height] has no argument");
662 int main(int argc, char *argv[])
664 struct display *display;
670 display = malloc(sizeof *display);
672 memset((char *)display, 0, sizeof *display);
674 display->init_width = 640;
675 display->init_height = 480;
676 display->init_color = 0xA0A08020;
677 for (fd = 1; fd < argc; fd++ ) {
678 if (argv[fd][0] == '-') {
679 if (strncasecmp(argv[fd], "-color=", 7) == 0) {
680 display->init_color = strtoul(&argv[fd][7], (char **)0, 0);
682 else if (strncasecmp(argv[fd], "-width=", 7) == 0) {
683 display->init_width = strtol(&argv[fd][7], (char **)0, 0);
685 else if (strncasecmp(argv[fd], "-height=", 8) == 0) {
686 display->init_height = strtol(&argv[fd][8], (char **)0, 0);
688 else if (strncasecmp(argv[fd], "-display=", 9) == 0) {
689 strncpy(display->connect, &argv[fd][9], MAX_CON_NAME);
691 else if (strncasecmp(argv[fd], "-postsleep=", 11) == 0) {
692 postsec = sec_str_2_value(&argv[fd][11]);
694 else if (strncasecmp(argv[fd], "-prompt=", 8) == 0) {
695 if (argv[fd][8] == 0) {
696 display->prompt = argv[fd][8] & 1;
705 if (display->connect[0]) {
706 display->display = wl_display_connect(display->connect);
709 display->display = wl_display_connect(NULL);
711 assert(display->display);
713 display->registry = wl_display_get_registry(display->display);
714 wl_registry_add_listener(display->registry,
715 ®istry_listener, display);
716 wl_display_dispatch(display->display);
717 sleep_with_wayland(display->display, 1000);
722 sleep_with_wayland(display->display, 20);
723 if (display->prompt) {
724 printf("CLIENT> "); fflush(stdout);
726 ret = getdata(display->ico_window_mgr, "CLIENT> ", fd, buf, sizeof(buf));
728 fprintf(stderr, "CLIENT: read error: fd %d, %m\n",
732 if (ret == 0) continue;
733 wl_display_flush(display->display);
735 if ((strncasecmp(buf, "bye", 3) == 0) ||
736 (strncasecmp(buf, "quit", 4) == 0) ||
737 (strncasecmp(buf, "end", 3) == 0)) {
738 /* Exit, end of test */
741 else if (strncasecmp(buf, "create-surface", ret) == 0) {
742 create_surface(display, "test-client");
744 else if (strncasecmp(buf, "clear-surface", 13) == 0) {
745 display->init_color = strtoul(&buf[14], (char **)0, 0);
746 clear_surface(display);
748 else if (strncasecmp(buf, "set_region", 10) == 0) {
749 /* set input region */
750 set_region(display, &buf[10]);
752 else if (strncasecmp(buf, "unset_region", 12) == 0) {
753 /* unset input region */
754 unset_region(display, &buf[12]);
756 else if (strncasecmp(buf, "send-state", ret) == 0) {
759 else if (strncasecmp(buf, "send-button-state", ret) == 0) {
760 send_button_state(display);
762 else if (strncasecmp(buf, "send-keyboard-state", ret) == 0) {
763 send_keyboard_state(display);
765 else if (strncasecmp(buf, "sleep", 5) == 0) {
766 msec = sec_str_2_value(&buf[6]);
767 sleep_with_wayland(display->display, msec);
770 print_log("CLIENT: unknown command[%s]", buf);
775 sleep_with_wayland(display->display, postsec);