Support Tizen 3.0
[profile/ivi/ico-uxf-weston-plugin.git] / tests / test-client.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  * Copyright © 2013 TOYOTA MOTOR CORPORATION
4  *
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.
14  *
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
21  * OF THIS SOFTWARE.
22  */
23 /**
24  * @brief   Wayland Application for unit test of Weston(Wayland) IVI plugins
25  *
26  * @date    Feb-08-2013
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <assert.h>
34 #include <poll.h>
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"
40
41 #define MAX_CON_NAME    127
42
43 struct display {
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;
50     struct input *input;
51     struct output *output;
52     struct surface *surface;
53     int    init_color;
54     int    init_width;
55     int    init_height;
56     int    prompt;
57     char   connect[MAX_CON_NAME+1];
58 };
59
60 struct input {
61     struct display *display;
62     struct wl_seat *seat;
63     struct wl_pointer *pointer;
64     struct wl_keyboard *keyboard;
65     float x, y;
66     uint32_t button_mask;
67     struct surface *pointer_focus;
68     struct surface *keyboard_focus;
69     uint32_t last_key, last_key_state;
70 };
71
72 struct output {
73     struct display *display;
74     struct wl_output *output;
75     int x, y;
76     int width, height;
77 };
78
79 struct surface {
80     struct display *display;
81     struct wl_surface *surface;
82     struct wl_shell_surface *shell_surface;
83     struct output *output;
84     EGLDisplay  dpy;
85     EGLConfig   conf;
86     EGLContext  ctx;
87     EGLSurface  egl_surface;
88 };
89
90 static void clear_surface(struct display *display);
91
92 static void
93 pointer_handle_enter(void *data, struct wl_pointer *pointer,
94                      uint32_t serial, struct wl_surface *surface,
95                      wl_fixed_t x, wl_fixed_t y)
96 {
97     struct input *input = data;
98
99     input->pointer_focus = wl_surface_get_user_data(surface);
100     input->x = wl_fixed_to_double(x);
101     input->y = wl_fixed_to_double(y);
102     print_log("CLIENT: got pointer enter (%d,%d), surface %p",
103               (int)input->x, (int)input->y, surface);
104 }
105
106 static void
107 pointer_handle_leave(void *data, struct wl_pointer *pointer,
108                      uint32_t serial, struct wl_surface *surface)
109 {
110     struct input *input = data;
111
112     input->pointer_focus = NULL;
113
114     print_log("CLIENT: got pointer leave, surface %p", surface);
115 }
116
117 static void
118 pointer_handle_motion(void *data, struct wl_pointer *pointer,
119                       uint32_t time, wl_fixed_t x, wl_fixed_t y)
120 {
121     struct input *input = data;
122
123     input->x = wl_fixed_to_double(x);
124     input->y = wl_fixed_to_double(y);
125
126     print_log("CLIENT: got pointer motion (%d,%d)", (int)input->x, (int)input->y);
127 }
128
129 static void
130 pointer_handle_button(void *data, struct wl_pointer *pointer,
131                       uint32_t serial, uint32_t time, uint32_t button, uint32_t state_w)
132 {
133     struct input *input = data;
134     uint32_t bit;
135     enum wl_pointer_button_state state = state_w;
136
137     bit = 1 << (button - BTN_LEFT);
138     if (state == WL_POINTER_BUTTON_STATE_PRESSED)
139         input->button_mask |= bit;
140     else
141         input->button_mask &= ~bit;
142     print_log("CLIENT: got pointer button %u %u", button, state_w);
143 }
144
145 static void
146 pointer_handle_axis(void *data, struct wl_pointer *pointer,
147                     uint32_t time, uint32_t axis, wl_fixed_t value)
148 {
149     fprintf(stderr, "CLIENT: got pointer axis %u %d\n", axis, value);
150 }
151
152 static void
153 keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
154                        uint32_t format, int fd, uint32_t size)
155 {
156     close(fd);
157     print_log("CLIENT: got keyboard keymap");
158 }
159
160 static void
161 keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
162                       uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
163 {
164     struct input *input = data;
165
166     input->keyboard_focus = wl_surface_get_user_data(surface);
167     print_log("CLIENT: got keyboard enter, surface %p", surface);
168 }
169
170 static void
171 keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
172                       uint32_t serial, struct wl_surface *surface)
173 {
174     struct input *input = data;
175
176     input->keyboard_focus = NULL;
177     print_log("CLIENT: got keyboard leave, surface %p", surface);
178 }
179
180 static void
181 keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
182                     uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
183 {
184     struct input *input = data;
185
186     input->last_key = key;
187     input->last_key_state = state;
188
189     print_log("CLIENT: got keyboard key %u %u", key, state);
190 }
191
192 static void
193 keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
194                           uint32_t serial, uint32_t mods_depressed,
195                           uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
196 {
197     print_log("CLIENT: got keyboard modifier");
198 }
199
200 static const struct wl_pointer_listener pointer_listener = {
201     pointer_handle_enter,
202     pointer_handle_leave,
203     pointer_handle_motion,
204     pointer_handle_button,
205     pointer_handle_axis,
206 };
207
208 static const struct wl_keyboard_listener keyboard_listener = {
209     keyboard_handle_keymap,
210     keyboard_handle_enter,
211     keyboard_handle_leave,
212     keyboard_handle_key,
213     keyboard_handle_modifiers,
214 };
215
216 static void
217 seat_handle_capabilities(void *data, struct wl_seat *seat,
218                          enum wl_seat_capability caps)
219 {
220     struct input *input = data;
221
222     if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
223         input->pointer = wl_seat_get_pointer(seat);
224         wl_pointer_set_user_data(input->pointer, input);
225         wl_pointer_add_listener(input->pointer, &pointer_listener, input);
226     }
227     else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
228         wl_pointer_destroy(input->pointer);
229         input->pointer = NULL;
230     }
231
232     if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
233         input->keyboard = wl_seat_get_keyboard(seat);
234         wl_keyboard_set_user_data(input->keyboard, input);
235         wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input);
236     }
237     else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
238         wl_keyboard_destroy(input->keyboard);
239         input->keyboard = NULL;
240     }
241 }
242
243 static const struct wl_seat_listener seat_listener = {
244     seat_handle_capabilities,
245 };
246
247 static void
248 output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
249                        int physical_width, int physical_height, int subpixel,
250                        const char *make, const char *model, int32_t transform)
251 {
252     struct output *output = data;
253
254     print_log("CLIENT: Event[handle_geometry] x/y=%d/%d p.w/h=%d/%d trans=%d",
255               x, y, physical_width, physical_height, transform);
256
257     output->x = x;
258     output->y = y;
259 }
260
261 static void
262 output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
263                    int width, int height, int refresh)
264 {
265     struct output *output = data;
266
267     print_log("CLIENT: Event[handle_mode] %08x x/y=%d/%d flags=%08x refresh=%d",
268               (int)wl_output, width, height, flags, refresh);
269
270     if (flags & WL_OUTPUT_MODE_CURRENT) {
271         output->width = width;
272         output->height = height;
273     }
274 }
275
276 static const struct wl_output_listener output_listener = {
277     output_handle_geometry,
278     output_handle_mode
279 };
280
281 static void
282 cb_input_capabilities(void *data, struct ico_exinput *ico_exinput,
283                       const char *device, int32_t type, const char *swname, int32_t input,
284                       const char *codename, int32_t code)
285 {
286     print_log("CLIENT: Event[input_capabilities] device=%s type=%d sw=%s input=%d "
287               "code=%s[%d]", device, type, swname, input, codename, code);
288 }
289
290 static void
291 cb_input_code(void *data, struct ico_exinput *ico_exinput,
292               const char *device, int32_t input, const char *codename, int32_t code)
293 {
294     print_log("CLIENT: Event[input_code] device=%s input=%d code=%s[%d]",
295               device, input, codename, code);
296 }
297
298 static void
299 cb_input_input(void *data, struct ico_exinput *ico_exinput, uint32_t time,
300                const char *device, int32_t input, int32_t code, int32_t state)
301 {
302     print_log("CLIENT: Event[input_input] device=%s input=%d code=%d state=%d",
303               device, input, code, state);
304 }
305
306 static const struct ico_exinput_listener exinput_listener = {
307     cb_input_capabilities,
308     cb_input_code,
309     cb_input_input
310 };
311
312 static void
313 shell_surface_ping(void *data, struct wl_shell_surface *wl_shell_surface, uint32_t serial)
314 {
315     print_log("CLIENT: shell_surface_ping: surface=%08x serial=%d",
316               (int)wl_shell_surface, serial);
317 }
318
319 static void
320 shell_surface_configure(void *data, struct wl_shell_surface *wl_shell_surface,
321                         uint32_t edges, int32_t width, int32_t height)
322 {
323     print_log("CLIENT: shell_surface_configure: surface=%08x edg=%x, width=%d height=%d",
324               (int)wl_shell_surface, edges, width, height);
325 }
326
327 static void
328 shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
329 {
330     print_log("CLIENT: shell_surface_popup_done: surface=%08x", (int)wl_shell_surface);
331 }
332
333 static const struct wl_shell_surface_listener shell_surface_listener = {
334     shell_surface_ping,
335     shell_surface_configure,
336     shell_surface_popup_done
337 };
338
339 static void
340 handle_global(void *data, struct wl_registry *registry, uint32_t id,
341               const char *interface, uint32_t version)
342 {
343     struct display *display = data;
344     struct input *input;
345     struct output *output;
346
347     print_log("CLIENT: handle_global: interface=<%s> id=%d", interface, (int)id);
348
349     if (strcmp(interface, "wl_compositor") == 0) {
350         display->compositor = wl_registry_bind(display->registry, id,
351                                                &wl_compositor_interface, 1);
352     }
353     else if (strcmp(interface, "wl_seat") == 0) {
354         input = calloc(1, sizeof *input);
355         input->display = display;
356         input->seat = wl_registry_bind(display->registry, id, &wl_seat_interface, 1);
357         input->pointer_focus = NULL;
358         input->keyboard_focus = NULL;
359
360         wl_seat_add_listener(input->seat, &seat_listener, input);
361         display->input = input;
362     }
363     else if (strcmp(interface, "wl_output") == 0) {
364         output = malloc(sizeof *output);
365         output->display = display;
366         output->output = wl_registry_bind(display->registry, id, &wl_output_interface, 1);
367         wl_output_add_listener(output->output,
368                        &output_listener, output);
369         display->output = output;
370
371         print_log("CLIENT: created output global %p", display->output);
372     }
373     else if (strcmp(interface, "wl_shell") == 0)    {
374         display->shell = wl_registry_bind(display->registry, id, &wl_shell_interface, 1);
375     }
376     else if (strcmp(interface, "ico_window_mgr") == 0)  {
377         display->ico_window_mgr = wl_registry_bind(display->registry, id,
378                                                    &ico_window_mgr_interface, 1);
379         print_log("CLIENT: created window_mgr global %p", display->ico_window_mgr);
380     }
381     else if (strcmp(interface, "ico_exinput") == 0)   {
382         display->ico_exinput = wl_registry_bind(display->registry, id,
383                                                 &ico_exinput_interface, 1);
384         ico_exinput_add_listener(display->ico_exinput, &exinput_listener, display);
385         print_log("CLIENT: created exinput global %p", display->ico_exinput);
386     }
387 }
388
389 static const struct wl_registry_listener registry_listener = {
390     handle_global
391 };
392
393 static void
394 surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output)
395 {
396     struct surface *surface = data;
397
398     surface->output = wl_output_get_user_data(output);
399
400     print_log("CLIENT: got surface enter, output %p", surface->output);
401 }
402
403 static void
404 surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *output)
405 {
406     struct surface *surface = data;
407
408     surface->output = NULL;
409
410     print_log("CLIENT: got surface leave, output %p", wl_output_get_user_data(output));
411 }
412
413 static const struct wl_surface_listener surface_listener = {
414     surface_enter,
415     surface_leave
416 };
417
418 static void
419 send_keyboard_state(struct display *display)
420 {
421     int focus = display->input->keyboard_focus != NULL;
422
423     if (focus) {
424         assert(display->input->keyboard_focus == display->surface);
425     }
426
427     wl_display_flush(display->display);
428
429     print_log("CLIENT: keyboard_state %u %u %d",
430               display->input->last_key, display->input->last_key_state, focus);
431
432     wl_display_roundtrip(display->display);
433 }
434
435 static void
436 send_button_state(struct display *display)
437 {
438     wl_display_roundtrip(display->display);
439
440     print_log("CLIENT: button_state %u", display->input->button_mask);
441
442     wl_display_roundtrip(display->display);
443 }
444
445 static void
446 send_state(struct display* display)
447 {
448     int visible = display->surface->output != NULL;
449     wl_fixed_t x = wl_fixed_from_int(-1);
450     wl_fixed_t y = wl_fixed_from_int(-1);
451
452     if (display->input->pointer_focus != NULL) {
453         assert(display->input->pointer_focus == display->surface);
454         x = wl_fixed_from_double(display->input->x);
455         y = wl_fixed_from_double(display->input->y);
456     }
457
458     if (visible) {
459         /* FIXME: this fails on multi-display setup */
460         /* assert(display->surface->output == display->output); */
461     }
462
463     wl_display_flush(display->display);
464
465     print_log("CLIENT: state %d %d %d", x, y, visible);
466
467     wl_display_roundtrip(display->display);
468 }
469
470 static void
471 create_surface(struct display *display, const char *title)
472 {
473     struct surface *surface;
474
475     surface = malloc(sizeof *surface);
476     assert(surface);
477     surface->display = display;
478     display->surface = surface;
479     surface->surface = wl_compositor_create_surface(display->compositor);
480     wl_surface_add_listener(surface->surface, &surface_listener, surface);
481
482     if (display->shell) {
483         surface->shell_surface =
484             wl_shell_get_shell_surface(display->shell, surface->surface);
485         if (surface->shell_surface) {
486             wl_shell_surface_add_listener(surface->shell_surface,
487                                           &shell_surface_listener, display);
488             wl_shell_surface_set_toplevel(surface->shell_surface);
489             wl_shell_surface_set_title(surface->shell_surface, title);
490         }
491     }
492     wl_display_flush(display->display);
493
494     print_log("CLIENT: create surface %d shell=%08x",
495               wl_proxy_get_id((struct wl_proxy *) surface->surface),
496               (int)surface->shell_surface);
497
498     poll(NULL, 0, 100); /* Wait for next frame where we'll get events. */
499
500     wl_display_roundtrip(display->display);
501
502     surface->dpy = opengl_init(display->display, &surface->conf, &surface->ctx);
503     if (surface->dpy)   {
504         surface->egl_surface = opengl_create_window(display->display, surface->surface,
505                                                     surface->dpy, surface->conf,
506                                                     surface->ctx, display->init_width,
507                                                     display->init_height,
508                                                     display->init_color);
509         clear_surface(display);
510         print_log("CLIENT: created egl_surface %08x", (int)surface->egl_surface);
511     }
512 }
513
514 static void
515 clear_surface(struct display *display)
516 {
517     if (! display->surface) {
518         create_surface(display, "test-client");
519     }
520     else    {
521         opengl_clear_window(display->init_color);
522         opengl_swap_buffer(display->display,
523                            display->surface->dpy, display->surface->egl_surface);
524     }
525 }
526
527 int main(int argc, char *argv[])
528 {
529     struct display *display;
530     char buf[256];
531     int ret, fd;
532     int msec;
533     int postsec = 0;
534
535     display = malloc(sizeof *display);
536     assert(display);
537     memset((char *)display, 0, sizeof *display);
538
539     display->init_width = 640;
540     display->init_height = 480;
541     display->init_color = 0xA0A08020;
542     for (fd = 1; fd < argc; fd++ )  {
543         if (argv[fd][0] == '-') {
544             if (strncasecmp(argv[fd], "-color=", 7) == 0)   {
545                 display->init_color = strtoul(&argv[fd][7], (char **)0, 0);
546             }
547             else if (strncasecmp(argv[fd], "-width=", 7) == 0)  {
548                 display->init_width = strtol(&argv[fd][7], (char **)0, 0);
549             }
550             else if (strncasecmp(argv[fd], "-height=", 8) == 0) {
551                 display->init_height = strtol(&argv[fd][8], (char **)0, 0);
552             }
553             else if (strncasecmp(argv[fd], "-display=", 9) == 0)   {
554                 strncpy(display->connect, &argv[fd][9], MAX_CON_NAME);
555             }
556             else if (strncasecmp(argv[fd], "-postsleep=", 11) == 0)   {
557                 postsec = sec_str_2_value(&argv[fd][11]);
558             }
559             else if (strncasecmp(argv[fd], "-prompt=", 8) == 0)  {
560                 if (argv[fd][8] == 0)   {
561                     display->prompt = argv[fd][8] & 1;
562                 }
563                 else    {
564                     display->prompt = 1;
565                 }
566             }
567         }
568     }
569
570     if (display->connect[0])    {
571         display->display = wl_display_connect(display->connect);
572     }
573     else    {
574         display->display = wl_display_connect(NULL);
575     }
576     assert(display->display);
577
578     display->registry = wl_display_get_registry(display->display);
579     wl_registry_add_listener(display->registry,
580                  &registry_listener, display);
581     wl_display_dispatch(display->display);
582     sleep_with_wayland(display->display, 1000);
583
584     fd = 0;
585
586     while (1) {
587         sleep_with_wayland(display->display, 20);
588         if (display->prompt)    {
589             printf("CLIENT: "); fflush(stdout);
590         }
591         ret = getdata(display->ico_window_mgr, "CLIENT: ", fd, buf, sizeof(buf));
592         if (ret < 0) {
593             fprintf(stderr, "CLIENT: read error: fd %d, %m\n",
594                 fd);
595             break;
596         }
597         if (ret == 0)   continue;
598         wl_display_flush(display->display);
599
600         if ((strncasecmp(buf, "bye", 3) == 0) ||
601             (strncasecmp(buf, "quit", 4) == 0) ||
602             (strncasecmp(buf, "end", 3) == 0))  {
603             /* Exit, end of test            */
604             break;
605         }
606         else if (strncasecmp(buf, "create-surface", ret) == 0) {
607             create_surface(display, "test-client");
608         }
609         else if (strncasecmp(buf, "clear-surface", 13) == 0) {
610             display->init_color = strtoul(&buf[14], (char **)0, 0);
611             clear_surface(display);
612         }
613         else if (strncasecmp(buf, "send-state", ret) == 0) {
614             send_state(display);
615         }
616         else if (strncasecmp(buf, "send-button-state", ret) == 0) {
617             send_button_state(display);
618         }
619         else if (strncasecmp(buf, "send-keyboard-state", ret) == 0) {
620             send_keyboard_state(display);
621         }
622         else if (strncasecmp(buf, "sleep", 5) == 0) {
623             msec = sec_str_2_value(&buf[6]);
624             sleep_with_wayland(display->display, msec);
625         }
626         else {
627             print_log("CLIENT: unknown command[%s]", buf);
628             return(-1);
629         }
630     }
631     if (postsec > 0)    {
632         sleep_with_wayland(display->display, postsec);
633     }
634
635     exit(0);
636 }
637