From 3018b4431bc57b2ce3faae69e919ff713064873c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 27 Apr 2012 15:02:56 -0400 Subject: [PATCH] tests: Add event-test, which tests for a few incoming events We check that we get surface.enter_output and move the pointer into the window and make sure we get input_device.pointer_enter with the right coordinates. There's a lot of code for a very simple test here, so we need to figure out how to reuse most of the event handling and such. It's also not clear that a custom, text based protocol is practical here, we might just use a wayland extension after all. --- tests/Makefile.am | 3 +- tests/event-test.c | 79 ++++++++++++ tests/test-client.c | 298 ++++++++++++++++++++++++++++++++++++++++++-- tests/test-runner.c | 26 ++++ tests/test-runner.h | 4 + 5 files changed, 402 insertions(+), 8 deletions(-) create mode 100644 tests/event-test.c diff --git a/tests/Makefile.am b/tests/Makefile.am index d4684941..fe9698f4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -TESTS = surface-test.la client-test.la +TESTS = surface-test.la client-test.la event-test.la TESTS_ENVIRONMENT = $(SHELL) $(top_srcdir)/tests/weston-test @@ -17,6 +17,7 @@ test_runner_src = test-runner.c test-runner.h surface_test_la_SOURCES = surface-test.c $(test_runner_src) client_test_la_SOURCES = client-test.c $(test_runner_src) +event_test_la_SOURCES = event-test.c $(test_runner_src) test_client_SOURCES = test-client.c test_client_LDADD = $(SIMPLE_CLIENT_LIBS) diff --git a/tests/event-test.c b/tests/event-test.c new file mode 100644 index 00000000..737e2279 --- /dev/null +++ b/tests/event-test.c @@ -0,0 +1,79 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include + +#include "test-runner.h" + +static void +handle_surface(struct test_client *client) +{ + uint32_t id; + struct wl_resource *resource; + struct weston_surface *surface; + struct weston_layer *layer = client->data; + struct wl_input_device *device; + + assert(sscanf(client->buf, "surface %u", &id) == 1); + fprintf(stderr, "got surface id %u\n", id); + resource = wl_client_get_object(client->client, id); + assert(resource); + assert(strcmp(resource->object.interface->name, "wl_surface") == 0); + + surface = (struct weston_surface *) resource; + + weston_surface_configure(surface, 100, 100, 200, 200); + weston_surface_assign_output(surface); + weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0); + wl_list_insert(&layer->surface_list, &surface->layer_link); + weston_surface_damage(surface); + + device = client->compositor->input_device; + client->compositor->focus = 1; /* Make it work even if pointer is + * outside X window. */ + notify_motion(device, 100, 150, 150); + + test_client_send(client, "bye\n"); +} + +TEST(event_test) +{ + struct test_client *client; + struct weston_layer *layer; + + client = test_client_launch(compositor); + client->terminate = 1; + + test_client_send(client, "create-surface\n"); + client->handle = handle_surface; + + layer = malloc(sizeof *layer); + assert(layer); + weston_layer_init(layer, &compositor->cursor_layer.link); + client->data = layer; +} diff --git a/tests/test-client.c b/tests/test-client.c index 3425a7d7..1db16153 100644 --- a/tests/test-client.c +++ b/tests/test-client.c @@ -27,24 +27,306 @@ #include #include +struct display { + struct wl_display *display; + struct wl_compositor *compositor; + struct input *input; + struct output *output; +}; + +struct input { + struct wl_input_device *input_device; + int32_t x, y; + uint32_t button_mask; + struct surface *pointer_focus; + struct surface *keyboard_focus; +}; + +struct output { + struct wl_output *output; + int x, y; + int width, height; +}; + +struct surface { + struct wl_surface *surface; + struct output *output; +}; + +static void +input_handle_motion(void *data, struct wl_input_device *input_device, + uint32_t time, int32_t x, int32_t y) +{ + struct input *input = data; + + input->x = x; + input->y = y; +} + +static void +input_handle_button(void *data, + struct wl_input_device *input_device, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state) +{ + struct input *input = data; + uint32_t bit; + + bit = 1 << (button - 272); + if (state) + input->button_mask |= bit; + else + input->button_mask &= ~bit; +} + +static void +input_handle_axis(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t axis, int32_t value) +{ +} + +static void +input_handle_key(void *data, struct wl_input_device *input_device, + uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ +} + +static void +input_handle_pointer_enter(void *data, + struct wl_input_device *input_device, + uint32_t serial, struct wl_surface *surface, + int32_t x, int32_t y) +{ + struct input *input = data; + + input->pointer_focus = wl_surface_get_user_data(surface); + input->x = x; + input->y = y; +} + +static void +input_handle_pointer_leave(void *data, + struct wl_input_device *input_device, + uint32_t serial, struct wl_surface *surface) +{ + struct input *input = data; + + input->pointer_focus = NULL; +} + +static void +input_handle_keyboard_enter(void *data, + struct wl_input_device *input_device, + uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys) +{ + struct input *input = data; + + input->keyboard_focus = wl_surface_get_user_data(surface); +} + +static void +input_handle_keyboard_leave(void *data, + struct wl_input_device *input_device, + uint32_t serial, + struct wl_surface *surface) +{ + struct input *input = data; + + input->keyboard_focus = NULL; +} + +static void +input_handle_touch_down(void *data, + struct wl_input_device *wl_input_device, + uint32_t serial, uint32_t time, + struct wl_surface *surface, + int32_t id, int32_t x, int32_t y) +{ +} + +static void +input_handle_touch_up(void *data, + struct wl_input_device *wl_input_device, + uint32_t serial, uint32_t time, int32_t id) +{ +} + static void -handle_global(struct wl_display *display, uint32_t id, +input_handle_touch_motion(void *data, + struct wl_input_device *wl_input_device, + uint32_t time, int32_t id, int32_t x, int32_t y) +{ +} + +static void +input_handle_touch_frame(void *data, + struct wl_input_device *wl_input_device) +{ +} + +static void +input_handle_touch_cancel(void *data, + struct wl_input_device *wl_input_device) +{ +} + +static const struct wl_input_device_listener input_device_listener = { + input_handle_motion, + input_handle_button, + input_handle_axis, + input_handle_key, + input_handle_pointer_enter, + input_handle_pointer_leave, + input_handle_keyboard_enter, + input_handle_keyboard_leave, + input_handle_touch_down, + input_handle_touch_up, + input_handle_touch_motion, + input_handle_touch_frame, + input_handle_touch_cancel, +}; + +static void +output_handle_geometry(void *data, + struct wl_output *wl_output, + int x, int y, + int physical_width, + int physical_height, + int subpixel, + const char *make, + const char *model) +{ + struct output *output = data; + + output->x = x; + output->y = y; +} + +static void +output_handle_mode(void *data, + struct wl_output *wl_output, + uint32_t flags, + int width, + int height, + int refresh) +{ + struct output *output = data; + + if (flags & WL_OUTPUT_MODE_CURRENT) { + output->width = width; + output->height = height; + } +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, + output_handle_mode +}; + +static void +handle_global(struct wl_display *_display, uint32_t id, const char *interface, uint32_t version, void *data) { + struct display *display = data; + struct input *input; + struct output *output; + + if (strcmp(interface, "wl_compositor") == 0) { + display->compositor = + wl_display_bind(display->display, + id, &wl_compositor_interface); + } else if (strcmp(interface, "wl_input_device") == 0) { + input = malloc(sizeof *input); + input->input_device = + wl_display_bind(display->display, id, + &wl_input_device_interface); + input->pointer_focus = NULL; + input->keyboard_focus = NULL; + + wl_input_device_add_listener(input->input_device, + &input_device_listener, input); + display->input = input; + } else if (strcmp(interface, "wl_output") == 0) { + output = malloc(sizeof *output); + output->output = wl_display_bind(display->display, + id, &wl_output_interface); + wl_output_add_listener(output->output, + &output_listener, output); + display->output = output; + + fprintf(stderr, "created output global %p\n", display->output); + } +} + +static void +surface_enter(void *data, + struct wl_surface *wl_surface, struct wl_output *output) +{ + struct surface *surface = data; + + surface->output = wl_output_get_user_data(output); + + fprintf(stderr, "got surface enter, output %p\n", surface->output); +} + +static void +surface_leave(void *data, + struct wl_surface *wl_surface, struct wl_output *output) +{ + struct surface *surface = data; + + surface->output = NULL; +} + +static const struct wl_surface_listener surface_listener = { + surface_enter, + surface_leave +}; + +static void +create_surface(int fd, struct display *display) +{ + struct surface *surface; + char buf[64]; + int len; + + surface = malloc(sizeof *surface); + assert(surface); + surface->surface = wl_compositor_create_surface(display->compositor); + wl_surface_add_listener(surface->surface, &surface_listener, surface); + wl_display_flush(display->display); + + len = snprintf(buf, sizeof buf, "surface %d\n", + wl_proxy_get_id((struct wl_proxy *) surface->surface)); + assert(write(fd, buf, len) == len); + + poll(NULL, 0, 100); /* Wait for next frame where we'll get events. */ + wl_display_roundtrip(display->display); + + assert(surface->output == display->output); + assert(display->input->pointer_focus == surface); + assert(display->input->x == 50); + assert(display->input->y == 50); } int main(int argc, char *argv[]) { - struct wl_display *display; + struct display *display; char buf[256], *p; int ret, fd; - display = wl_display_connect(NULL); + display = malloc(sizeof *display); assert(display); - wl_display_add_global_listener(display, handle_global, display); - wl_display_iterate(display, WL_DISPLAY_READABLE); - wl_display_roundtrip(display); + display->display = wl_display_connect(NULL); + assert(display->display); + + wl_display_add_global_listener(display->display, + handle_global, display); + wl_display_iterate(display->display, WL_DISPLAY_READABLE); + wl_display_roundtrip(display->display); fd = 0; p = getenv("TEST_SOCKET"); @@ -58,10 +340,12 @@ int main(int argc, char *argv[]) return -1; } - fprintf(stderr, "test-client: got %.*s\n", ret - 1, buf, ret); + fprintf(stderr, "test-client: got %.*s\n", ret - 1, buf); if (strncmp(buf, "bye\n", ret) == 0) { return 0; + } else if (strncmp(buf, "create-surface\n", ret) == 0) { + create_surface(fd, display); } else { fprintf(stderr, "unknown command %.*s\n", ret, buf); return -1; diff --git a/tests/test-runner.c b/tests/test-runner.c index 9d1544ab..e60e0062 100644 --- a/tests/test-runner.c +++ b/tests/test-runner.c @@ -45,14 +45,36 @@ test_client_cleanup(struct weston_process *proc, int status) client->status = status; client->done = 1; + assert(client->status == 0); + if (client->terminate) wl_display_terminate(client->compositor->wl_display); } +static int +test_client_data(int fd, uint32_t mask, void *data) +{ + struct test_client *client = data; + struct wl_event_loop *loop; + int len; + + len = read(client->fd, client->buf, sizeof client->buf); + assert(len >= 0); + fprintf(stderr, "got %.*s from client\n", len - 1, client->buf); + assert(client->buf[len - 1] == '\n'); + client->buf[len - 1] = '\0'; + + loop = wl_display_get_event_loop(client->compositor->wl_display); + wl_event_loop_add_idle(loop, (void *) client->handle, client); + + return 1; +} + struct test_client * test_client_launch(struct weston_compositor *compositor) { struct test_client *client; + struct wl_event_loop *loop; int ret, sv[2], client_fd; char buf[256]; @@ -77,6 +99,10 @@ test_client_launch(struct weston_compositor *compositor) close(sv[0]); client->fd = sv[1]; + loop = wl_display_get_event_loop(compositor->wl_display); + wl_event_loop_add_fd(loop, client->fd, WL_EVENT_READABLE, + test_client_data, client); + return client; } diff --git a/tests/test-runner.h b/tests/test-runner.h index 97e5529e..ea353bc7 100644 --- a/tests/test-runner.h +++ b/tests/test-runner.h @@ -30,6 +30,10 @@ struct test_client { int done; int status; int terminate; + + char buf[256]; + void (*handle)(struct test_client *client); + void *data; }; struct test_client *test_client_launch(struct weston_compositor *compositor);