tests/wayland-unit-tests: Add cursor shape tests

Tests error conditions, selecting a cursor shape, switching back to a
surface based cursor, and that the shape persists when the cursor shape
device is destoryed.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4307>
This commit is contained in:
Sebastian Wick 2025-02-28 00:35:34 +01:00 committed by Marge Bot
parent b18565cee6
commit 0c9a31459a
7 changed files with 196 additions and 0 deletions

View File

@ -757,6 +757,7 @@ wayland_test_cases = [
'depends': [
test_client,
test_client_executables.get('buffer-transform'),
test_client_executables.get('cursor-shape'),
test_client_executables.get('dma-buf-scanout'),
test_client_executables.get('fractional-scale'),
test_client_executables.get('fullscreen'),

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2025 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include "wayland-test-client-utils.h"
static struct wl_pointer *pointer;
static uint32_t serial;
static gboolean waiting_for_pointer_enter = FALSE;
static void
on_pointer_enter (WaylandSurface *surface,
struct wl_pointer *pointer_l,
uint32_t serial_l)
{
waiting_for_pointer_enter = FALSE;
pointer = pointer_l;
serial = serial_l;
}
static void
wait_for_pointer_enter (WaylandSurface *surface)
{
gulong handler_id;
handler_id = g_signal_connect (surface, "pointer-enter",
G_CALLBACK (on_pointer_enter), NULL);
waiting_for_pointer_enter = TRUE;
while (waiting_for_pointer_enter)
wayland_display_dispatch (surface->display);
g_clear_signal_handler (&handler_id, surface);
}
int
main (int argc,
char **argv)
{
g_autoptr (WaylandDisplay) display = NULL;
g_autoptr (WaylandSurface) surface = NULL;
struct wl_surface *cursor_surface;
struct wp_cursor_shape_device_v1 *cursor_shape_device;
WaylandDisplayCapabilities caps = WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER;
if (g_strcmp0 (argv[1], "v2-shape-on-v1") != 0)
caps |= WAYLAND_DISPLAY_CAPABILITY_CURSOR_SHAPE_V2;
display = wayland_display_new (caps);
surface = wayland_surface_new (display,
"cursor-shape",
100, 100, 0xffffffff);
xdg_toplevel_set_fullscreen (surface->xdg_toplevel, NULL);
wl_surface_commit (surface->wl_surface);
wait_for_pointer_enter (surface);
wait_for_effects_completed (display, surface->wl_surface);
cursor_surface = wl_compositor_create_surface (display->compositor);
draw_surface (display, cursor_surface, 10, 10, 0xff00ff00);
wl_surface_damage_buffer (cursor_surface, 0, 0, 10, 10);
wl_surface_commit (cursor_surface);
wl_pointer_set_cursor (pointer, serial, cursor_surface, 0, 0);
g_assert (display->cursor_shape_mgr);
cursor_shape_device =
wp_cursor_shape_manager_v1_get_pointer (display->cursor_shape_mgr, pointer);
if (g_strcmp0 (argv[1], "v2-shape-on-v1") == 0)
{
wp_cursor_shape_device_v1_set_shape (cursor_shape_device,
serial,
WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE);
if (wl_display_dispatch (display->display) != -1)
return 1;
return EXIT_SUCCESS;
}
else if (g_strcmp0 (argv[1], "bad-shape") == 0)
{
wp_cursor_shape_device_v1_set_shape (cursor_shape_device,
serial,
3333);
if (wl_display_dispatch (display->display) != -1)
return 1;
return EXIT_SUCCESS;
}
else if (g_strcmp0 (argv[1], "ref-test") == 0)
{
/* make sure the surface cursor is still visible */
wait_for_view_verified (display, 0);
/* make sure the default shape is visible */
wp_cursor_shape_device_v1_set_shape (cursor_shape_device,
serial,
WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
wait_for_view_verified (display, 1);
/* make sure switching back to the surface cursor works */
wl_pointer_set_cursor (pointer, serial, cursor_surface, 0, 0);
wait_for_view_verified (display, 0);
/* make sure another shape works */
wp_cursor_shape_device_v1_set_shape (cursor_shape_device,
serial,
WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE);
wait_for_view_verified (display, 2);
/* destroy the wp_cursor_shape_device and make sure the shape persists */
wp_cursor_shape_device_v1_set_shape (cursor_shape_device,
serial,
WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
wp_cursor_shape_device_v1_destroy (cursor_shape_device);
wait_for_view_verified (display, 1);
return EXIT_SUCCESS;
}
return 1;
}

View File

@ -21,6 +21,9 @@ wayland_test_clients = [
{
'name': 'color-management',
},
{
'name': 'cursor-shape',
},
{
'name': 'dma-buf-scanout',
},

View File

@ -53,6 +53,58 @@ find_client_window (const char *title)
return meta_find_client_window (test_context, title);
}
static void
cursor_shape (void)
{
MetaBackend *backend = meta_context_get_backend (test_context);
ClutterSeat *seat = meta_backend_get_default_seat (backend);
MetaWaylandTestClient *wayland_test_client;
virtual_pointer = clutter_seat_create_virtual_device (seat,
CLUTTER_POINTER_DEVICE);
clutter_virtual_input_device_notify_absolute_motion (virtual_pointer,
g_get_monotonic_time (),
320.0f,
240.0f);
meta_flush_input (test_context);
wayland_test_client =
meta_wayland_test_client_new_with_args (test_context,
"cursor-shape",
"v2-shape-on-v1",
NULL);
/* we wait for the window to flush out all the messages */
meta_wait_for_client_window (test_context, "cursor-shape");
g_test_expect_message ("libmutter", G_LOG_LEVEL_WARNING,
"WL: error in client communication*");
meta_wayland_test_client_finish (wayland_test_client);
g_test_assert_expected_messages ();
wayland_test_client =
meta_wayland_test_client_new_with_args (test_context,
"cursor-shape",
"bad-shape",
NULL);
/* we wait for the window to flush out all the messages */
meta_wait_for_client_window (test_context, "cursor-shape");
g_test_expect_message ("libmutter", G_LOG_LEVEL_WARNING,
"WL: error in client communication*");
meta_wayland_test_client_finish (wayland_test_client);
g_test_assert_expected_messages ();
/* FIXME workaround for a bug in native cursor renderer where just trying to
* get the cursor on a plane results in no software cursor being rendered */
meta_backend_inhibit_hw_cursor (backend);
wayland_test_client =
meta_wayland_test_client_new_with_args (test_context,
"cursor-shape",
"ref-test",
NULL);
meta_wayland_test_client_finish (wayland_test_client);
meta_backend_uninhibit_hw_cursor (backend);
}
static void
subsurface_remap_toplevel (void)
{
@ -1327,6 +1379,8 @@ init_tests (void)
toplevel_show_states);
g_test_add_func ("/wayland/toplevel/suspended",
toplevel_suspended);
g_test_add_func ("/wayland/cursor/shape",
cursor_shape);
}
int
@ -1337,6 +1391,7 @@ main (int argc,
MetaTestRunFlags test_run_flags;
g_setenv ("MUTTER_DEBUG_SESSION_MANAGEMENT_PROTOCOL", "1", TRUE);
g_setenv ("MUTTER_DEBUG_CURSOR_SHAPE_PROTOCOL", "1", TRUE);
#ifdef MUTTER_PRIVILEGED_TEST
context = meta_create_test_context (META_CONTEXT_TEST_TYPE_VKMS,