6 #include <libweston-test/weston-test-client-helper.h>
7 #include <libweston-test/weston-test-fixture-compositor.h>
9 #include "agl-shell-client-protocol.h"
10 #include "xdg-shell-client-protocol.h"
11 #include "agl-screenshooter-client-protocol.h"
13 #define WINDOW_WIDTH_SIZE 200
14 #define WINDOW_HEIGHT_SIZE 200
24 pixman_color_t bg_color = {
31 pixman_color_t panel_top_color = {
38 pixman_color_t panel_bottom_color = {
46 struct agl_shell *agl_shell;
47 struct xdg_wm_base *wm_base;
48 struct agl_screenshooter *screenshooter;
49 struct client *client;
50 struct wl_list win_list;
51 bool buffer_copy_done;
55 struct display *display;
56 struct xdg_toplevel *xdg_toplevel;
57 struct xdg_surface *xdg_surface;
58 struct wl_surface *surface;
59 struct buffer *buffer;
61 bool wait_for_configure;
67 enum window_type w_type;
72 static struct buffer *
73 agl_capture_screenshot_of_output(void *data);
75 static enum test_result_code
76 fixture_setup(struct weston_test_harness *harness)
78 struct compositor_setup setup;
80 compositor_setup_defaults(&setup);
81 setup.renderer = RENDERER_PIXMAN;
84 setup.shell = SHELL_EMBEDDED;
85 setup.extra_args = "--debug";
87 return weston_test_harness_execute_as_client(harness, &setup);
90 DECLARE_FIXTURE_SETUP(fixture_setup);
92 static struct window *
93 create_window(int width, int height)
95 struct window *window = calloc(1, sizeof(*window));
97 window->width = width;
98 window->height = height;
103 static struct display *
104 create_display(struct client *client, struct xdg_wm_base *wm_base,
105 struct agl_shell *agl_shell, struct agl_screenshooter *screenshooter)
107 struct display *display = calloc(1, sizeof(*display));
109 display->client = client;
110 display->wm_base = wm_base;
111 display->agl_shell = agl_shell;
112 display->screenshooter = screenshooter;
118 xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
120 xdg_wm_base_pong(shell, serial);
123 static const struct xdg_wm_base_listener xdg_wm_base_listener = {
128 draw(struct window *window, pixman_color_t color)
130 struct client *client = window->display->client;
132 testlog("Creating a buffer with %dx%d\n", window->width, window->height);
134 create_shm_buffer_a8r8g8b8(client, window->width, window->height);
135 fill_image_with_color(window->buffer->image, &color);
137 wl_surface_attach(window->surface, window->buffer->proxy, 0, 0);
138 wl_surface_damage(window->surface, 0, 0, window->width, window->height);
140 wl_surface_commit(window->surface);
144 handle_xdg_surface_configure(void *data, struct xdg_surface *surface, uint32_t serial)
146 struct window *window = data;
147 xdg_surface_ack_configure(surface, serial);
149 if (window->wait_for_configure) {
150 switch (window->w_type) {
152 draw(window, bg_color);
155 draw(window, panel_top_color);
158 draw(window, panel_bottom_color);
164 window->wait_for_configure = false;
168 static const struct xdg_surface_listener xdg_surface_listener = {
169 handle_xdg_surface_configure,
173 handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
174 int32_t width, int32_t height, struct wl_array *states)
176 struct window *window = data;
179 window->fullscreen = 0;
180 window->maximized = 0;
182 wl_array_for_each(p, states) {
185 case XDG_TOPLEVEL_STATE_FULLSCREEN:
186 window->fullscreen = 1;
188 case XDG_TOPLEVEL_STATE_MAXIMIZED:
189 window->maximized = 1;
194 if (width > 0 && height > 0) {
195 if (!window->fullscreen && !window->maximized) {
196 window->width = width;
197 window->height = height;
199 window->width = width;
200 window->height = height;
201 } else if (!window->fullscreen && !window->maximized) {
203 window->width = WINDOW_WIDTH_SIZE;
205 window->width = width;
208 window->height = WINDOW_HEIGHT_SIZE;
210 window->height = height;
213 /* if we've been resized set wait_for_configure to adjust the fb size
214 * in the frame callback handler, which will also clear this up */
215 if ((window->width > 0 && window->width != WINDOW_WIDTH_SIZE) &&
216 (window->height > 0 && window->height != WINDOW_HEIGHT_SIZE)) {
217 window->wait_for_configure = true;
222 handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
226 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
227 handle_xdg_toplevel_configure,
228 handle_xdg_toplevel_close,
232 static struct window *
233 setup_agl_shell_client_bg(struct display *display)
235 struct window *window;
236 window = create_window(200, 200);
238 window->display = display;
240 xdg_wm_base_add_listener(display->wm_base, &xdg_wm_base_listener, display);
243 wl_compositor_create_surface(display->client->wl_compositor);
244 window->xdg_surface =
245 xdg_wm_base_get_xdg_surface(display->wm_base, window->surface);
246 assert(window->xdg_surface);
248 xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window);
249 window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
250 assert(window->xdg_toplevel);
252 xdg_toplevel_add_listener(window->xdg_toplevel, &xdg_toplevel_listener, window);
254 xdg_toplevel_set_title(window->xdg_toplevel, "bg");
255 xdg_toplevel_set_app_id(window->xdg_toplevel, "bg");
257 wl_surface_commit(window->surface);
259 window->wait_for_configure = true;
261 agl_shell_set_background(display->agl_shell, window->surface,
262 display->client->output->wl_output);
264 window->w_type = BACKGROUND;
268 static struct window *
269 setup_agl_shell_client_panel(struct display *display, enum agl_shell_edge edge)
271 struct window *window;
272 window = create_window(200, 200);
274 window->display = display;
276 xdg_wm_base_add_listener(display->wm_base,
277 &xdg_wm_base_listener, display);
280 wl_compositor_create_surface(display->client->wl_compositor);
281 window->xdg_surface =
282 xdg_wm_base_get_xdg_surface(display->wm_base, window->surface);
283 assert(window->xdg_surface);
285 xdg_surface_add_listener(window->xdg_surface,
286 &xdg_surface_listener, window);
287 window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
288 assert(window->xdg_toplevel);
290 xdg_toplevel_add_listener(window->xdg_toplevel,
291 &xdg_toplevel_listener, window);
294 case AGL_SHELL_EDGE_TOP:
295 xdg_toplevel_set_title(window->xdg_toplevel, "panel top");
296 xdg_toplevel_set_app_id(window->xdg_toplevel, "panel top");
298 case AGL_SHELL_EDGE_BOTTOM:
299 xdg_toplevel_set_title(window->xdg_toplevel, "panel bottom");
300 xdg_toplevel_set_app_id(window->xdg_toplevel, "panel bottom");
302 case AGL_SHELL_EDGE_LEFT:
303 case AGL_SHELL_EDGE_RIGHT:
307 wl_surface_commit(window->surface);
309 window->wait_for_configure = true;
311 agl_shell_set_panel(display->agl_shell, window->surface,
312 display->client->output->wl_output, edge);
314 window->w_type = (enum window_type) edge;
319 screenshot_done(void *data, struct agl_screenshooter *screenshooter, uint32_t status)
321 struct display *display = data;
322 display->buffer_copy_done = true;
325 static const struct agl_screenshooter_listener screenshooter_listener = {
329 static struct buffer *
330 agl_capture_screenshot_of_output(void *data)
332 struct display *display = data;
333 struct client *client = display->client;
334 struct buffer *buffer;
336 buffer = create_shm_buffer_a8r8g8b8(client,
337 client->output->width,
338 client->output->height);
340 display->buffer_copy_done = false;
341 agl_screenshooter_take_shot(display->screenshooter,
342 client->output->wl_output,
345 while (display->buffer_copy_done == false)
346 assert(wl_display_dispatch(client->wl_display) >= 0);
351 static struct display *
352 setup_agl_shell_client(struct client *client)
354 struct display *display;
355 struct agl_shell *agl_shell;
356 struct xdg_wm_base *wm_base;
357 struct agl_screenshooter *screenshooter;
359 setenv("WESTON_TEST_REFERENCE_PATH", "../tests/reference", 1);
360 wm_base = bind_to_singleton_global(client, &xdg_wm_base_interface, 1);
363 agl_shell = bind_to_singleton_global(client, &agl_shell_interface, 1);
366 screenshooter = bind_to_singleton_global(client, &agl_screenshooter_interface, 1);
367 assert(screenshooter);
369 display = create_display(client, wm_base, agl_shell, screenshooter);
370 wl_list_init(&display->win_list);
372 client_set_screenshoot(client, agl_capture_screenshot_of_output, display);
373 agl_screenshooter_add_listener(screenshooter, &screenshooter_listener, display);
375 struct window *win_bg = setup_agl_shell_client_bg(display);
376 wl_list_insert(&display->win_list, &win_bg->link);
378 struct window *win_panel_top =
379 setup_agl_shell_client_panel(display, AGL_SHELL_EDGE_TOP);
380 wl_list_insert(&display->win_list, &win_panel_top->link);
382 struct window *win_panel_bottom =
383 setup_agl_shell_client_panel(display, AGL_SHELL_EDGE_BOTTOM);
384 wl_list_insert(&display->win_list, &win_panel_bottom->link);
386 client_roundtrip(client);
389 agl_shell_ready(agl_shell);
394 display_destroy(struct display *display)
396 struct window *win, *win_next;
398 wl_list_for_each_safe(win, win_next, &display->win_list, link) {
399 wl_list_remove(&win->link);
404 TEST(agl_client_shell)
406 struct display *display;
407 struct client *client = create_client();
412 /* Create the client */
413 testlog("Creating client shell for agl-shell\n");
414 display = setup_agl_shell_client(client);
416 client_roundtrip(client);
418 /* take a screenshot and compare it with reference ->
419 * agl-shell client shell works */
420 match = verify_screen_content(client, "agl_client_shell", 0, NULL, 0);
423 client_destroy(client);
424 display_destroy(display);