summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Glidic <sardemff7+git@sardemff7.net>2016-08-11 18:54:44 +0200
committerQuentin Glidic <sardemff7+git@sardemff7.net>2017-09-21 08:56:36 +0200
commitd0ab92717b133f59d7b266754715bbbda104cca7 (patch)
treec308d527210b063210712e572bf9e8cfd124666e
parent13404c40161c6ca432c5fa24432c991bb7850a7a (diff)
tests: Add some basic libweston-desktop shells testswip/libweston-desktop-tests
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
-rw-r--r--Makefile.am21
-rw-r--r--tests/bad-buffer-test.c4
-rw-r--r--tests/event-test.c12
-rw-r--r--tests/reference/wl_shell_toplevel-screenshot-good-00.pngbin0 -> 1644 bytes
-rw-r--r--tests/reference/wl_shell_transient-screenshot-good-00.pngbin0 -> 2911 bytes
-rw-r--r--tests/reference/xdg_shell_v5_popup-screenshot-good-00.pngbin0 -> 1494 bytes
-rw-r--r--tests/reference/xdg_shell_v5_toplevel-screenshot-good-00.pngbin0 -> 1004 bytes
-rw-r--r--tests/reference/xdg_shell_v6_toplevel-screenshot-good-00.pngbin0 -> 1004 bytes
-rw-r--r--tests/weston-test-client-helper.c25
-rw-r--r--tests/weston-test-client-helper.h8
-rw-r--r--tests/wl-shell-test.c206
-rw-r--r--tests/xdg-shell-v5-test.c281
-rw-r--r--tests/xdg-shell-v6-test.c438
13 files changed, 974 insertions, 21 deletions
diff --git a/Makefile.am b/Makefile.am
index 58a5c596..872dcc7b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1218,6 +1218,9 @@ module_tests = \
surface-global-test.la
weston_tests = \
+ xdg_shell_v6_test.weston \
+ xdg_shell_v5_test.weston \
+ wl_shell_test.weston \
bad_buffer.weston \
keyboard.weston \
event.weston \
@@ -1301,6 +1304,24 @@ weston_test_desktop_shell_la_SOURCES = \
tests/weston-test-desktop-shell.c \
shared/helpers.h
+xdg_shell_v6_test_weston_SOURCES = tests/xdg-shell-v6-test.c
+nodist_xdg_shell_v6_test_weston_SOURCES = protocol/xdg-shell-unstable-v6-protocol.c
+xdg_shell_v6_test_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
+xdg_shell_v6_test_weston_LDADD = libtest-client.la
+
+xdg_shell_v6_test.weston tests/xdg_shell_v6_test_weston-xdg-shell-v6-test.o: protocol/xdg-shell-unstable-v6-client-protocol.h
+
+xdg_shell_v5_test_weston_SOURCES = tests/xdg-shell-v5-test.c
+nodist_xdg_shell_v5_test_weston_SOURCES = protocol/xdg-shell-unstable-v5-protocol.c
+xdg_shell_v5_test_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
+xdg_shell_v5_test_weston_LDADD = libtest-client.la
+
+xdg_shell_v5_test.weston tests/xdg_shell_v5_test_weston-xdg-shell-v5-test.o: protocol/xdg-shell-unstable-v5-client-protocol.h
+
+wl_shell_test_weston_SOURCES = tests/wl-shell-test.c
+wl_shell_test_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
+wl_shell_test_weston_LDADD = libtest-client.la
+
if ENABLE_EGL
weston_test_la_CFLAGS += $(EGL_TESTS_CFLAGS)
weston_test_la_LDFLAGS += $(EGL_TESTS_LIBS)
diff --git a/tests/bad-buffer-test.c b/tests/bad-buffer-test.c
index ee7b2231..4a83210f 100644
--- a/tests/bad-buffer-test.c
+++ b/tests/bad-buffer-test.c
@@ -75,9 +75,9 @@ TEST(test_truncated_shm_file)
wl_surface_attach(surface, bad_buffer, 0, 0);
wl_surface_damage(surface, 0, 0, 200, 200);
- frame_callback_set(surface, &frame);
+ client_set_wait_frame_callback(surface, &frame);
wl_surface_commit(surface);
- frame_callback_wait_nofail(client, &frame);
+ client_wait_nofail(client, &frame);
expect_protocol_error(client, &wl_buffer_interface,
WL_SHM_ERROR_INVALID_FD);
diff --git a/tests/event-test.c b/tests/event-test.c
index 64dd7a0c..a2c577de 100644
--- a/tests/event-test.c
+++ b/tests/event-test.c
@@ -398,25 +398,25 @@ TEST(buffer_release)
wl_surface_attach(surface, buf1->proxy, 0, 0);
wl_surface_attach(surface, buf2->proxy, 0, 0);
- frame_callback_set(surface, &frame);
+ client_set_wait_frame_callback(surface, &frame);
wl_surface_commit(surface);
- frame_callback_wait(client, &frame);
+ client_wait(client, &frame);
assert(buf1_released == 0);
/* buf2 may or may not be released */
assert(buf3_released == 0);
wl_surface_attach(surface, buf3->proxy, 0, 0);
- frame_callback_set(surface, &frame);
+ client_set_wait_frame_callback(surface, &frame);
wl_surface_commit(surface);
- frame_callback_wait(client, &frame);
+ client_wait(client, &frame);
assert(buf1_released == 0);
assert(buf2_released == 1);
/* buf3 may or may not be released */
wl_surface_attach(surface, client->surface->buffer->proxy, 0, 0);
- frame_callback_set(surface, &frame);
+ client_set_wait_frame_callback(surface, &frame);
wl_surface_commit(surface);
- frame_callback_wait(client, &frame);
+ client_wait(client, &frame);
assert(buf1_released == 0);
assert(buf2_released == 1);
assert(buf3_released == 1);
diff --git a/tests/reference/wl_shell_toplevel-screenshot-good-00.png b/tests/reference/wl_shell_toplevel-screenshot-good-00.png
new file mode 100644
index 00000000..a9a5539f
--- /dev/null
+++ b/tests/reference/wl_shell_toplevel-screenshot-good-00.png
Binary files differ
diff --git a/tests/reference/wl_shell_transient-screenshot-good-00.png b/tests/reference/wl_shell_transient-screenshot-good-00.png
new file mode 100644
index 00000000..4e99a5b1
--- /dev/null
+++ b/tests/reference/wl_shell_transient-screenshot-good-00.png
Binary files differ
diff --git a/tests/reference/xdg_shell_v5_popup-screenshot-good-00.png b/tests/reference/xdg_shell_v5_popup-screenshot-good-00.png
new file mode 100644
index 00000000..7684359c
--- /dev/null
+++ b/tests/reference/xdg_shell_v5_popup-screenshot-good-00.png
Binary files differ
diff --git a/tests/reference/xdg_shell_v5_toplevel-screenshot-good-00.png b/tests/reference/xdg_shell_v5_toplevel-screenshot-good-00.png
new file mode 100644
index 00000000..f311c168
--- /dev/null
+++ b/tests/reference/xdg_shell_v5_toplevel-screenshot-good-00.png
Binary files differ
diff --git a/tests/reference/xdg_shell_v6_toplevel-screenshot-good-00.png b/tests/reference/xdg_shell_v6_toplevel-screenshot-good-00.png
new file mode 100644
index 00000000..f311c168
--- /dev/null
+++ b/tests/reference/xdg_shell_v6_toplevel-screenshot-good-00.png
Binary files differ
diff --git a/tests/weston-test-client-helper.c b/tests/weston-test-client-helper.c
index fd6d5c84..2d740fcf 100644
--- a/tests/weston-test-client-helper.c
+++ b/tests/weston-test-client-helper.c
@@ -69,7 +69,7 @@ static const struct wl_callback_listener frame_listener = {
};
struct wl_callback *
-frame_callback_set(struct wl_surface *surface, int *done)
+client_set_wait_frame_callback(struct wl_surface *surface, int *done)
{
struct wl_callback *callback;
@@ -81,7 +81,7 @@ frame_callback_set(struct wl_surface *surface, int *done)
}
int
-frame_callback_wait_nofail(struct client *client, int *done)
+client_wait_nofail(struct client *client, int *done)
{
while (!*done) {
if (wl_display_dispatch(client->wl_display) < 0)
@@ -108,11 +108,11 @@ move_client(struct client *client, int x, int y)
wl_surface_damage(surface->wl_surface, 0, 0, surface->width,
surface->height);
- frame_callback_set(surface->wl_surface, &done);
+ client_set_wait_frame_callback(surface->wl_surface, &done);
wl_surface_commit(surface->wl_surface);
- frame_callback_wait(client, &done);
+ client_wait(client, &done);
}
static void
@@ -126,12 +126,13 @@ pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
pointer->focus = wl_surface_get_user_data(wl_surface);
else
pointer->focus = NULL;
+ pointer->serial = serial;
pointer->x = wl_fixed_to_int(x);
pointer->y = wl_fixed_to_int(y);
- fprintf(stderr, "test-client: got pointer enter %d %d, surface %p\n",
- pointer->x, pointer->y, pointer->focus);
+ fprintf(stderr, "test-client: got pointer enter [%u] %d %d, surface %p\n",
+ serial, pointer->x, pointer->y, pointer->focus);
}
static void
@@ -141,9 +142,11 @@ pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
struct pointer *pointer = data;
pointer->focus = NULL;
+ pointer->serial = 0;
+ pointer->grab_serial = 0;
- fprintf(stderr, "test-client: got pointer leave, surface %p\n",
- wl_surface ? wl_surface_get_user_data(wl_surface) : NULL);
+ fprintf(stderr, "test-client: got pointer leave [%u], surface %p\n",
+ serial, wl_surface ? wl_surface_get_user_data(wl_surface) : NULL);
}
static void
@@ -166,11 +169,13 @@ pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
{
struct pointer *pointer = data;
+ pointer->serial = serial;
+ pointer->grab_serial = serial;
pointer->button = button;
pointer->state = state;
- fprintf(stderr, "test-client: got pointer button %u %u\n",
- button, state);
+ fprintf(stderr, "test-client: got pointer button [%u] %u %u\n",
+ serial, button, state);
}
static void
diff --git a/tests/weston-test-client-helper.h b/tests/weston-test-client-helper.h
index a288af7e..448d4aa9 100644
--- a/tests/weston-test-client-helper.h
+++ b/tests/weston-test-client-helper.h
@@ -86,6 +86,8 @@ struct input {
struct pointer {
struct wl_pointer *wl_pointer;
struct surface *focus;
+ uint32_t serial;
+ uint32_t grab_serial;
int x;
int y;
uint32_t button;
@@ -175,12 +177,12 @@ move_client(struct client *client, int x, int y);
} while (0)
struct wl_callback *
-frame_callback_set(struct wl_surface *surface, int *done);
+client_set_wait_frame_callback(struct wl_surface *surface, int *done);
int
-frame_callback_wait_nofail(struct client *client, int *done);
+client_wait_nofail(struct client *client, int *done);
-#define frame_callback_wait(c, d) assert(frame_callback_wait_nofail((c), (d)))
+#define client_wait(c, d) assert(client_wait_nofail((c), (d)))
void
skip(const char *fmt, ...);
diff --git a/tests/wl-shell-test.c b/tests/wl-shell-test.c
new file mode 100644
index 00000000..26c5a5f8
--- /dev/null
+++ b/tests/wl-shell-test.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "weston-test-client-helper.h"
+
+char *server_parameters="--use-pixman --width=320 --height=240 --shell=weston-test-desktop-shell.so";
+
+static struct wl_shell *
+client_get_wl_shell(struct client *client)
+{
+ struct global *global;
+
+ wl_list_for_each(global, &client->global_list, link) {
+ if (strcmp(global->interface, "wl_shell") != 0)
+ continue;
+ return wl_registry_bind(client->wl_registry, global->name,
+ &wl_shell_interface, global->version);
+ }
+ return NULL;
+}
+
+static void
+draw_stuff(pixman_image_t *image)
+{
+ int w, h;
+ int stride; /* bytes */
+ int x, y;
+ uint8_t r, g, b;
+ uint32_t *pixels;
+ uint32_t *pixel;
+ pixman_format_code_t fmt;
+
+ fmt = pixman_image_get_format(image);
+ w = pixman_image_get_width(image);
+ h = pixman_image_get_height(image);
+ stride = pixman_image_get_stride(image);
+ pixels = pixman_image_get_data(image);
+
+ assert(PIXMAN_FORMAT_BPP(fmt) == 32);
+
+ for (x = 0; x < w; x++)
+ for (y = 0; y < h; y++) {
+ r = (double) x / w * 0xff;
+ g = (double) (x+y) / (w+h) * 0xff;
+ b = (double) y / w * 0xff;
+ pixel = pixels + (y * stride / 4) + x;
+ *pixel = (255 << 24) | (r << 16) | (g << 8) | b;
+ }
+}
+
+static void
+wl_shell_test_run(char *basename, void(*run)(struct client *client, struct wl_shell *shell, struct wl_surface *surface, struct wl_shell_surface *shell_surface))
+{
+ char basename_good[100];
+ char basename_error[100];
+ char basename_result[100];
+ struct buffer *buf;
+ struct client *client;
+ struct wl_shell *shell;
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+ struct buffer *screenshot = NULL;
+ pixman_image_t *reference_good = NULL;
+ pixman_image_t *diffimg;
+ struct rectangle clip;
+ const char *fname;
+ bool match = false;
+ bool dump_all_images = true;
+
+ snprintf(basename_good, sizeof(basename_good),
+ "%s-screenshot-good", basename);
+ snprintf(basename_error, sizeof(basename_error),
+ "%s-screenshot-error", basename);
+ snprintf(basename_result, sizeof(basename_result),
+ "%s-screenshot", basename);
+
+ /* Create the client */
+ printf("Creating client for test\n");
+ client = create_client();
+ assert(client);
+ shell = client_get_wl_shell(client);
+ assert(shell);
+
+ surface = wl_compositor_create_surface(client->wl_compositor);
+ shell_surface = wl_shell_get_shell_surface(shell, surface);
+ run(client, shell, surface, shell_surface);
+
+ buf = create_shm_buffer_a8r8g8b8(client, 100, 100);
+ draw_stuff(buf->image);
+ wl_surface_attach(surface, buf->proxy, 0, 0);
+ wl_surface_damage(surface, 0, 0, 100, 100);
+ wl_surface_commit(surface);
+
+ wl_display_flush(client->wl_display);
+
+ /* Take a snapshot. Result will be in screenshot->wl_buffer. */
+ printf("Taking a screenshot\n");
+ screenshot = capture_screenshot_of_output(client);
+ assert(screenshot);
+
+ /* Load good reference image */
+ fname = screenshot_reference_filename(basename_good, 0);
+ printf("Loading good reference image %s\n", fname);
+ reference_good = load_image_from_png(fname);
+ assert(reference_good);
+
+ /* Test check_images_match() with clip.
+ * Alpha-blending and other effects can cause irrelevant discrepancies, so look only
+ * at a small portion of the solid-colored background
+ */
+ clip.x = 0;
+ clip.y = 0;
+ clip.width = 100;
+ clip.height = 100;
+ printf("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
+ match = check_images_match(screenshot->image, reference_good, &clip);
+ printf("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
+ if (!match) {
+ diffimg = visualize_image_difference(screenshot->image, reference_good, &clip);
+ fname = screenshot_output_filename(basename_error, 0);
+ write_image_as_png(diffimg, fname);
+ pixman_image_unref(diffimg);
+ }
+ pixman_image_unref(reference_good);
+
+ /* Test dumping of non-matching images */
+ if (!match || dump_all_images) {
+ fname = screenshot_output_filename(basename_result, 0);
+ write_image_as_png(screenshot->image, fname);
+ }
+
+ buffer_destroy(screenshot);
+
+ printf("Test complete\n");
+ assert(match);
+}
+
+static void
+wl_shell_toplevel_run(struct client *client, struct wl_shell *shell, struct wl_surface *surface, struct wl_shell_surface *shell_surface)
+{
+ wl_shell_surface_set_toplevel(shell_surface);
+ wl_surface_commit(surface);
+}
+
+TEST(wl_shell_toplevel)
+{
+ wl_shell_test_run("wl_shell_toplevel", wl_shell_toplevel_run);
+}
+
+static void
+wl_shell_transient_run(struct client *client, struct wl_shell *shell,
+ struct wl_surface *parent_surface,
+ struct wl_shell_surface *parent_shell_surface)
+{
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+ struct buffer *buf;
+
+ wl_shell_surface_set_toplevel(parent_shell_surface);
+ wl_surface_commit(parent_surface);
+
+ surface = wl_compositor_create_surface(client->wl_compositor);
+ shell_surface = wl_shell_get_shell_surface(shell, surface);
+ wl_shell_surface_set_transient(shell_surface, parent_surface, 25, 25,
+ WL_SHELL_SURFACE_TRANSIENT_INACTIVE);
+ wl_surface_commit(surface);
+
+ buf = create_shm_buffer_a8r8g8b8(client, 50, 50);
+ draw_stuff(buf->image);
+ wl_surface_attach(surface, buf->proxy, 0, 0);
+ wl_surface_damage(surface, 0, 0, 50, 50);
+ wl_surface_commit(surface);
+}
+
+TEST(wl_shell_transient)
+{
+ wl_shell_test_run("wl_shell_transient", wl_shell_transient_run);
+}
diff --git a/tests/xdg-shell-v5-test.c b/tests/xdg-shell-v5-test.c
new file mode 100644
index 00000000..35e6da43
--- /dev/null
+++ b/tests/xdg-shell-v5-test.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "weston-test-client-helper.h"
+#include "xdg-shell-unstable-v5-client-protocol.h"
+
+char *server_parameters="--use-pixman --width=320 --height=240 --shell=weston-test-desktop-shell.so";
+
+static void
+ping(void *data, struct xdg_shell *shell, uint32_t serial)
+{
+ xdg_shell_pong(shell, serial);
+}
+
+static struct xdg_shell_listener shell_listener = {
+ ping
+};
+
+static struct xdg_shell *
+client_get_xdg_shell_v5(struct client *client)
+{
+ struct global *global;
+ struct xdg_shell *xdg_shell_v5;
+
+ wl_list_for_each(global, &client->global_list, link) {
+ if (strcmp(global->interface, "xdg_shell") != 0)
+ continue;
+ xdg_shell_v5 = wl_registry_bind(client->wl_registry,
+ global->name,
+ &xdg_shell_interface,
+ global->version);
+ xdg_shell_use_unstable_version(xdg_shell_v5, 5);
+ xdg_shell_add_listener(xdg_shell_v5, &shell_listener, xdg_shell_v5);
+ return xdg_shell_v5;
+ }
+ return NULL;
+}
+
+static void
+draw_stuff(pixman_image_t *image, int border)
+{
+ int w, h;
+ int stride; /* bytes */
+ int x, y;
+ uint8_t a, r, g, b;
+ uint32_t *pixels;
+ uint32_t *pixel;
+ pixman_format_code_t fmt;
+
+ fmt = pixman_image_get_format(image);
+ w = pixman_image_get_width(image);
+ h = pixman_image_get_height(image);
+ stride = pixman_image_get_stride(image);
+ pixels = pixman_image_get_data(image);
+
+ assert(PIXMAN_FORMAT_BPP(fmt) == 32);
+
+ for (x = 0; x < w; x++)
+ for (y = 0; y < h; y++) {
+ a = 0xff;
+ if (x < border || x > w - border ||
+ y < border || y > h - border)
+ a = 0x80;
+ r = (double) x / w * a;
+ g = (double) (x+y) / (w+h) * a;
+ b = (double) y / w * a;
+ pixel = pixels + (y * stride / 4) + x;
+ *pixel = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+}
+
+static void
+handle_surface_configure(void *data, struct xdg_surface *xdg_surface,
+ int32_t width, int32_t height,
+ struct wl_array *states, uint32_t serial)
+{
+ xdg_surface_ack_configure(xdg_surface, serial);
+}
+
+static void
+handle_surface_delete(void *data, struct xdg_surface *xdg_surface)
+{
+ xdg_surface_destroy(xdg_surface);
+}
+
+static const struct xdg_surface_listener xdg_surface_listener = {
+ handle_surface_configure,
+ handle_surface_delete,
+};
+
+static void
+popup_done(void *data, struct xdg_popup *xdg_popup)
+{
+ int *ready = data;
+
+ xdg_popup_destroy(xdg_popup);
+ *ready = 1;
+}
+
+static const struct xdg_popup_listener xdg_popup_listener = {
+ popup_done
+};
+
+static void
+xdg_shell_v5_create_xdg_surface(struct client *client, struct xdg_shell *shell, struct wl_surface **surface, struct xdg_surface **xdg_surface, int width, int height, int border)
+{
+ struct buffer *buf;
+ int ready;
+
+ *surface = wl_compositor_create_surface(client->wl_compositor);
+ *xdg_surface = xdg_shell_get_xdg_surface(shell, *surface);
+ xdg_surface_set_window_geometry(*xdg_surface, border, border, width, height);
+ xdg_surface_add_listener(*xdg_surface, &xdg_surface_listener, NULL);
+
+ buf = create_shm_buffer_a8r8g8b8(client, width + border * 2, height + border * 2);
+ draw_stuff(buf->image, border);
+ wl_surface_attach(*surface, buf->proxy, 0, 0);
+ wl_surface_damage(*surface, 0, 0, width + border * 2, height + border * 2);
+
+ client_set_wait_frame_callback(*surface, &ready);
+ wl_surface_commit(*surface);
+ client_wait(client, &ready);
+}
+
+static void
+xdg_shell_v5_test_run(char *basename, void (*run)(struct client *client, struct xdg_shell *shell, struct wl_surface *surface, struct xdg_surface *xdg_surface))
+{
+ char basename_good[100];
+ char basename_error[100];
+ char basename_result[100];
+ int width = 200;
+ int height = 80;
+ int border = 10;
+ struct client *client;
+ struct xdg_shell *shell;
+ struct wl_surface *surface;
+ struct xdg_surface *xdg_surface;
+ struct buffer *screenshot = NULL;
+ pixman_image_t *reference_good = NULL;
+ pixman_image_t *diffimg;
+ struct rectangle clip;
+ const char *fname;
+ bool match = false;
+ bool dump_all_images = true;
+
+ snprintf(basename_good, sizeof(basename_good),
+ "%s-screenshot-good", basename);
+ snprintf(basename_error, sizeof(basename_error),
+ "%s-screenshot-error", basename);
+ snprintf(basename_result, sizeof(basename_result),
+ "%s-screenshot", basename);
+
+ /* Create the client */
+ printf("Creating client for test\n");
+ client = create_client();
+ assert(client);
+ shell = client_get_xdg_shell_v5(client);
+ assert(shell);
+
+ weston_test_move_pointer(client->test->weston_test, 100, 100);
+ xdg_shell_v5_create_xdg_surface(client, shell, &surface, &xdg_surface, width, height, border);
+ run(client, shell, surface, xdg_surface);
+
+ /* Take a snapshot. Result will be in screenshot->wl_buffer. */
+ printf("Taking a screenshot\n");
+ screenshot = capture_screenshot_of_output(client);
+ assert(screenshot);
+
+ /* Load good reference image */
+ fname = screenshot_reference_filename(basename_good, 0);
+ printf("Loading good reference image %s\n", fname);
+ reference_good = load_image_from_png(fname);
+ assert(reference_good);
+
+ /* Test check_images_match() with clip.
+ * Alpha-blending and other effects can cause irrelevant discrepancies, so look only
+ * at a small portion of the solid-colored background
+ */
+ clip.x = 0;
+ clip.y = 0;
+ clip.width = width;
+ clip.height = height;
+ printf("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
+ match = check_images_match(screenshot->image, reference_good, &clip);
+ printf("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
+ if (!match) {
+ diffimg = visualize_image_difference(screenshot->image, reference_good, &clip);
+ fname = screenshot_output_filename(basename_error, 0);
+ write_image_as_png(diffimg, fname);
+ pixman_image_unref(diffimg);
+ }
+ pixman_image_unref(reference_good);
+
+ /* Test dumping of non-matching images */
+ if (!match || dump_all_images) {
+ fname = screenshot_output_filename(basename_result, 0);
+ write_image_as_png(screenshot->image, fname);
+ }
+
+ buffer_destroy(screenshot);
+
+ printf("Test complete\n");
+ assert(match);
+}
+
+static void
+xdg_shell_v5_toplevel_run(struct client *client, struct xdg_shell *shell, struct wl_surface *surface, struct xdg_surface *xdg_surface)
+{
+}
+
+TEST(xdg_shell_v5_toplevel)
+{
+ xdg_shell_v5_test_run("xdg_shell_v5_toplevel", xdg_shell_v5_toplevel_run);
+}
+
+static void
+xdg_shell_v5_popup_run(struct client *client, struct xdg_shell *shell,
+ struct wl_surface *parent_surface,
+ struct xdg_surface *parent_xdg_surface)
+{
+ struct wl_surface *surface;
+ uint32_t serial;
+ struct xdg_popup *xdg_popup;
+ int ready;
+ struct buffer *buf;
+
+ weston_test_move_pointer(client->test->weston_test, 50, 50);
+ weston_test_send_button(client->test->weston_test, 1,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+ client_roundtrip(client);
+ serial = client->input->pointer->grab_serial;
+ assert(serial != 0);
+
+ surface = wl_compositor_create_surface(client->wl_compositor);
+ client_set_wait_frame_callback(surface, &ready);
+ xdg_popup = xdg_shell_get_xdg_popup(shell, surface, parent_surface,
+ client->input->wl_seat, serial,
+ 25, 25);
+ xdg_popup_add_listener(xdg_popup, &xdg_popup_listener, &ready);
+
+ buf = create_shm_buffer_a8r8g8b8(client, 50, 50);
+ draw_stuff(buf->image, 0);
+ wl_surface_attach(surface, buf->proxy, 0, 0);
+ wl_surface_damage(surface, 0, 0, 50, 50);
+
+ wl_surface_commit(surface);
+ client_wait(client, &ready);
+}
+
+TEST(xdg_shell_v5_popup)
+{
+ xdg_shell_v5_test_run("xdg_shell_v5_popup", xdg_shell_v5_popup_run);
+}
diff --git a/tests/xdg-shell-v6-test.c b/tests/xdg-shell-v6-test.c
new file mode 100644
index 00000000..017dddfb
--- /dev/null
+++ b/tests/xdg-shell-v6-test.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright © 2015 Samsung Electronics Co., Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "weston-test-client-helper.h"
+#include "xdg-shell-unstable-v6-client-protocol.h"
+
+char *server_parameters="--use-pixman --width=320 --height=240 --shell=weston-test-desktop-shell.so";
+
+static void
+ping(void *data, struct zxdg_shell_v6 *shell, uint32_t serial)
+{
+ zxdg_shell_v6_pong(shell, serial);
+}
+
+static struct zxdg_shell_v6_listener shell_listener = {
+ ping
+};
+
+static struct zxdg_shell_v6 *
+client_get_xdg_shell_v6(struct client *client)
+{
+ struct global *global;
+ struct zxdg_shell_v6 *xdg_shell_v6;
+
+ wl_list_for_each(global, &client->global_list, link) {
+ if (strcmp(global->interface, "zxdg_shell_v6") != 0)
+ continue;
+ xdg_shell_v6 = wl_registry_bind(client->wl_registry,
+ global->name,
+ &zxdg_shell_v6_interface,
+ global->version);
+ zxdg_shell_v6_add_listener(xdg_shell_v6, &shell_listener, xdg_shell_v6);
+ return xdg_shell_v6;
+ }
+ return NULL;
+}
+
+static void
+draw_stuff(pixman_image_t *image, int border)
+{
+ int w, h;
+ int stride; /* bytes */
+ int x, y;
+ uint8_t a, r, g, b;
+ uint32_t *pixels;
+ uint32_t *pixel;
+ pixman_format_code_t fmt;
+
+ fmt = pixman_image_get_format(image);
+ w = pixman_image_get_width(image);
+ h = pixman_image_get_height(image);
+ stride = pixman_image_get_stride(image);
+ pixels = pixman_image_get_data(image);
+
+ assert(PIXMAN_FORMAT_BPP(fmt) == 32);
+
+ for (x = 0; x < w; x++)
+ for (y = 0; y < h; y++) {
+ a = 0xff;
+ if (x < border || x > w - border ||
+ y < border || y > h - border)
+ a = 0x80;
+ r = (double) x / w * a;
+ g = (double) (x+y) / (w+h) * a;
+ b = (double) y / w * a;
+ pixel = pixels + (y * stride / 4) + x;
+ *pixel = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+}
+
+static void
+handle_surface_configure(void *data, struct zxdg_surface_v6 *xdg_surface,
+ uint32_t serial)
+{
+ int *ready = data;
+
+ zxdg_surface_v6_ack_configure(xdg_surface, serial);
+ *ready = 1;
+}
+
+static const struct zxdg_surface_v6_listener xdg_surface_listener = {
+ handle_surface_configure,
+};
+
+static void
+handle_toplevel_configure(void *data, struct zxdg_toplevel_v6 *xdg_toplevel,
+ int32_t width, int32_t height,
+ struct wl_array *states)
+{
+}
+
+static void
+handle_toplevel_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel)
+{
+ int *ready = data;
+ struct zxdg_surface_v6 *xdg_surface =
+ zxdg_toplevel_v6_get_user_data(xdg_toplevel);
+
+ zxdg_toplevel_v6_destroy(xdg_toplevel);
+ zxdg_surface_v6_destroy(xdg_surface);
+ *ready = 1;
+}
+
+static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
+ handle_toplevel_configure,
+ handle_toplevel_close,
+};
+
+static void
+handle_popup_configure(void *data, struct zxdg_popup_v6 *xdg_popup,
+ int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ int *ready = data;
+
+ *ready = 1;
+}
+
+static void
+handle_popup_done(void *data, struct zxdg_popup_v6 *xdg_popup)
+{
+ int *ready = data;
+ struct zxdg_surface_v6 *xdg_surface =
+ zxdg_popup_v6_get_user_data(xdg_popup);
+
+ zxdg_popup_v6_destroy(xdg_popup);
+ zxdg_surface_v6_destroy(xdg_surface);
+ *ready = 1;
+}
+
+static const struct zxdg_popup_v6_listener xdg_popup_listener = {
+ handle_popup_configure,
+ handle_popup_done,
+};
+
+static void *
+xdg_shell_v6_create_xdg_surface(struct client *client, struct zxdg_shell_v6 *shell,
+ int width, int height, int border,
+ void *(*setup)(struct client *client, struct zxdg_shell_v6 *shell, struct zxdg_surface_v6 *xdg_surface, int32_t width, int32_t height, int32_t border, void *data),
+ struct wl_surface **surface,
+ struct zxdg_surface_v6 **xdg_surface,
+ void *data)
+{
+ struct buffer *buf;
+ int ready = 0;
+ void *ret;
+
+ *surface = wl_compositor_create_surface(client->wl_compositor);
+ *xdg_surface = zxdg_shell_v6_get_xdg_surface(shell, *surface);
+ zxdg_surface_v6_add_listener(*xdg_surface, &xdg_surface_listener, &ready);
+ ret = setup(client, shell, *xdg_surface, width, height, border, data);
+ zxdg_surface_v6_set_window_geometry(*xdg_surface, border, border, width, height);
+ wl_surface_commit(*surface);
+
+ client_wait(client, &ready);
+
+ buf = create_shm_buffer_a8r8g8b8(client, width + border * 2, height + border * 2);
+ draw_stuff(buf->image, border);
+ wl_surface_attach(*surface, buf->proxy, 0, 0);
+ wl_surface_damage(*surface, 0, 0, width + border * 2, height + border * 2);
+
+ client_set_wait_frame_callback(*surface, &ready);
+ wl_surface_commit(*surface);
+ client_wait(client, &ready);
+
+ return ret;
+}
+
+static void *
+xdg_shell_v6_toplevel_setup(struct client *client, struct zxdg_shell_v6 *shell, struct zxdg_surface_v6 *xdg_surface, int32_t width, int32_t height, int32_t border, void *data)
+{
+ struct zxdg_toplevel_v6 *xdg_toplevel;
+
+ xdg_toplevel = zxdg_surface_v6_get_toplevel(xdg_surface);
+ zxdg_toplevel_v6_add_listener(xdg_toplevel, &xdg_toplevel_listener, data);
+
+ return xdg_toplevel;
+}
+
+static void
+xdg_shell_v6_test_run(char *basename, void (*run)(struct client *client, struct zxdg_shell_v6 *shell, struct zxdg_surface_v6 *xdg_surface))
+{
+ char basename_good[100];
+ char basename_error[100];
+ char basename_result[100];
+ int width = 200;
+ int height = 80;
+ int border = 10;
+ struct client *client;
+ struct zxdg_shell_v6 *shell;
+ struct wl_surface *surface;
+ struct zxdg_surface_v6 *xdg_surface;
+ struct buffer *screenshot = NULL;
+ pixman_image_t *reference_good = NULL;
+ pixman_image_t *diffimg;
+ struct rectangle clip;
+ const char *fname;
+ bool match = false;
+ bool dump_all_images = true;
+
+ snprintf(basename_good, sizeof(basename_good),
+ "%s-screenshot-good", basename);
+ snprintf(basename_error, sizeof(basename_error),
+ "%s-screenshot-error", basename);
+ snprintf(basename_result, sizeof(basename_result),
+ "%s-screenshot", basename);
+
+ /* Create the client */
+ printf("Creating client for test\n");
+ client = create_client();
+ assert(client);
+ shell = client_get_xdg_shell_v6(client);
+ assert(shell);
+
+ weston_test_move_pointer(client->test->weston_test, 100, 100);
+ xdg_shell_v6_create_xdg_surface(client, shell, width, height, border, xdg_shell_v6_toplevel_setup, &surface, &xdg_surface, NULL);
+ run(client, shell, xdg_surface);
+
+ /* Take a snapshot. Result will be in screenshot->wl_buffer. */
+ printf("Taking a screenshot\n");
+ screenshot = capture_screenshot_of_output(client);
+ assert(screenshot);
+
+ /* Load good reference image */
+ fname = screenshot_reference_filename(basename_good, 0);
+ printf("Loading good reference image %s\n", fname);
+ reference_good = load_image_from_png(fname);
+ assert(reference_good);
+
+ /* Test check_images_match() with clip.
+ * Alpha-blending and other effects can cause irrelevant discrepancies, so look only
+ * at a small portion of the solid-colored background
+ */
+ clip.x = 0;
+ clip.y = 0;
+ clip.width = width;
+ clip.height = height;
+ printf("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
+ match = check_images_match(screenshot->image, reference_good, &clip);
+ printf("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
+ if (!match) {
+ diffimg = visualize_image_difference(screenshot->image, reference_good, &clip);
+ fname = screenshot_output_filename(basename_error, 0);
+ write_image_as_png(diffimg, fname);
+ pixman_image_unref(diffimg);
+ }
+ pixman_image_unref(reference_good);
+
+ /* Test dumping of non-matching images */
+ if (!match || dump_all_images) {
+ fname = screenshot_output_filename(basename_result, 0);
+ write_image_as_png(screenshot->image, fname);
+ }
+
+ buffer_destroy(screenshot);
+
+ printf("Test complete\n");
+ assert(match);
+}
+
+static void
+xdg_shell_v6_test_run_error(void (*run)(struct client *client, struct zxdg_shell_v6 *shell), const struct wl_interface *intf, uint32_t code)
+{
+ struct client *client;
+ struct zxdg_shell_v6 *shell;
+
+ client = create_client();
+ assert(client);
+ shell = client_get_xdg_shell_v6(client);
+ assert(shell);
+
+ run(client, shell);
+
+ expect_protocol_error(client, intf, code);
+}
+
+static void
+xdg_shell_v6_toplevel_run(struct client *client, struct zxdg_shell_v6 *shell, struct zxdg_surface_v6 *xdg_surface)
+{
+}
+
+TEST(xdg_shell_v6_toplevel)
+{
+ xdg_shell_v6_test_run("xdg_shell_v6_toplevel", xdg_shell_v6_toplevel_run);
+}
+
+struct popup_data {
+ struct zxdg_surface_v6 *parent_xdg_surface;
+ int *ready;
+};
+
+static void *
+xdg_shell_v6_popup_setup(struct client *client, struct zxdg_shell_v6 *shell,
+ struct zxdg_surface_v6 *xdg_surface,
+ int32_t width, int32_t height, int32_t border,
+ void *data)
+{
+ struct zxdg_positioner_v6 *xdg_positioner;
+ struct zxdg_popup_v6 *xdg_popup;
+ struct popup_data *popup_data = data;
+
+ xdg_positioner = zxdg_shell_v6_create_positioner(shell);
+ zxdg_positioner_v6_set_size(xdg_positioner, width, height);
+ zxdg_positioner_v6_set_anchor_rect(xdg_positioner, 25, 25, 1, 1);
+ zxdg_positioner_v6_set_anchor(xdg_positioner, ZXDG_POSITIONER_V6_ANCHOR_TOP|ZXDG_POSITIONER_V6_ANCHOR_LEFT);
+ zxdg_positioner_v6_set_gravity(xdg_positioner, ZXDG_POSITIONER_V6_GRAVITY_BOTTOM|ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
+
+ xdg_popup = zxdg_surface_v6_get_popup(xdg_surface, popup_data->parent_xdg_surface, xdg_positioner);
+ zxdg_positioner_v6_destroy(xdg_positioner);
+
+ zxdg_popup_v6_add_listener(xdg_popup, &xdg_popup_listener, popup_data->ready);
+
+ return xdg_popup;
+}
+
+static void
+xdg_shell_v6_popup_run(struct client *client, struct zxdg_shell_v6 *shell,
+ struct zxdg_surface_v6 *parent_xdg_surface)
+{
+ struct wl_surface *surface;
+ int width = 100;
+ int height = 40;
+ int border = 5;
+ struct zxdg_surface_v6 *xdg_surface;
+ struct zxdg_popup_v6 *xdg_popup;
+ int ready = 0;
+ struct popup_data popup_data = {
+ .parent_xdg_surface = parent_xdg_surface,
+ .ready = &ready,
+ };
+
+ xdg_popup = xdg_shell_v6_create_xdg_surface(client, shell, width, height, border, xdg_shell_v6_popup_setup, &surface, &xdg_surface, &popup_data);
+ client_wait(client, &ready);
+}
+
+TEST(xdg_shell_v6_popup)
+{
+ xdg_shell_v6_test_run("xdg_shell_v6_popup", xdg_shell_v6_popup_run);
+}
+
+static void
+xdg_shell_v6_surface_no_role_error_run(struct client *client, struct zxdg_shell_v6 *shell)
+{
+ struct wl_surface *surface;
+ struct zxdg_surface_v6 *xdg_surface;
+
+ surface = wl_compositor_create_surface(client->wl_compositor);
+ xdg_surface = zxdg_shell_v6_get_xdg_surface(shell, surface);
+ wl_surface_commit(surface);
+}
+
+TEST(xdg_shell_v6_surface_errors)
+{
+ xdg_shell_v6_test_run_error(xdg_shell_v6_surface_no_role_error_run,
+ &zxdg_surface_v6_interface,
+ ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED);
+}
+
+static void
+xdg_shell_v6_positioner_invalid_size_run(struct client *client, struct zxdg_shell_v6 *shell)
+{
+ struct zxdg_positioner_v6 *xdg_positioner;
+
+ xdg_positioner = zxdg_shell_v6_create_positioner(shell);
+ zxdg_positioner_v6_set_size(xdg_positioner, -1, -1);
+}
+
+static void
+xdg_shell_v6_positioner_invalid_anchor_run(struct client *client, struct zxdg_shell_v6 *shell)
+{
+ struct zxdg_positioner_v6 *xdg_positioner;
+
+ xdg_positioner = zxdg_shell_v6_create_positioner(shell);
+ zxdg_positioner_v6_set_anchor(xdg_positioner,
+ ZXDG_POSITIONER_V6_ANCHOR_BOTTOM|ZXDG_POSITIONER_V6_ANCHOR_TOP);
+}
+
+static void
+xdg_shell_v6_positioner_invalid_anchor_rect_run(struct client *client, struct zxdg_shell_v6 *shell)
+{
+ struct zxdg_positioner_v6 *xdg_positioner;
+
+ xdg_positioner = zxdg_shell_v6_create_positioner(shell);
+ zxdg_positioner_v6_set_anchor_rect(xdg_positioner, 0, 0, 0, 0);
+}
+
+static void
+xdg_shell_v6_positioner_invalid_gravity_run(struct client *client, struct zxdg_shell_v6 *shell)
+{
+ struct zxdg_positioner_v6 *xdg_positioner;
+
+ xdg_positioner = zxdg_shell_v6_create_positioner(shell);
+ zxdg_positioner_v6_set_gravity(xdg_positioner,
+ ZXDG_POSITIONER_V6_GRAVITY_BOTTOM|ZXDG_POSITIONER_V6_GRAVITY_TOP);
+}
+
+TEST(xdg_shell_v6_positioner_errors)
+{
+ xdg_shell_v6_test_run_error(xdg_shell_v6_positioner_invalid_size_run,
+ &zxdg_positioner_v6_interface,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT);
+ xdg_shell_v6_test_run_error(xdg_shell_v6_positioner_invalid_anchor_run,
+ &zxdg_positioner_v6_interface,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT);
+ xdg_shell_v6_test_run_error(xdg_shell_v6_positioner_invalid_anchor_rect_run,
+ &zxdg_positioner_v6_interface,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT);
+ xdg_shell_v6_test_run_error(xdg_shell_v6_positioner_invalid_gravity_run,
+ &zxdg_positioner_v6_interface,
+ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT);
+}