[mutter] tests/screen-cast: Add input injection tests to screen cast client



commit 1914f533b81dbb83852a344a43865635ad82ad88
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Mar 2 11:54:38 2022 +0100

    tests/screen-cast: Add input injection tests to screen cast client
    
    This tests that cursor metadata are handled properly, and that the
    display server handles input events correctly, including ones that are
    sent too early.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2270>

 src/tests/screen-cast-client.c | 86 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 85 insertions(+), 1 deletion(-)
---
diff --git a/src/tests/screen-cast-client.c b/src/tests/screen-cast-client.c
index 84ce891320..cdf0d7dcf5 100644
--- a/src/tests/screen-cast-client.c
+++ b/src/tests/screen-cast-client.c
@@ -31,6 +31,23 @@
 #include "meta-dbus-remote-desktop.h"
 #include "meta-dbus-screen-cast.h"
 
+#define assert_cursor_position(stream, x, y) \
+{ \
+  g_assert_cmpint (stream->cursor_x, ==, (x)); \
+  g_assert_cmpint (stream->cursor_y, ==, (y)); \
+}
+
+#define CURSOR_META_SIZE(width, height) \
+ (sizeof(struct spa_meta_cursor) + \
+  sizeof(struct spa_meta_bitmap) + width * height * 4)
+
+enum
+  {
+    CURSOR_MODE_HIDDEN = 0,
+    CURSOR_MODE_EMBEDDED = 1,
+    CURSOR_MODE_METADATA = 2,
+  };
+
 typedef struct _Stream
 {
   MetaDBusScreenCastStream *proxy;
@@ -43,6 +60,9 @@ typedef struct _Stream
 
   int target_width;
   int target_height;
+
+  int cursor_x;
+  int cursor_y;
 } Stream;
 
 typedef struct _Session
@@ -209,7 +229,7 @@ on_stream_param_changed (void                 *user_data,
   Stream *stream = user_data;
   uint8_t params_buffer[1024];
   struct spa_pod_builder pod_builder;
-  const struct spa_pod *params[2];
+  const struct spa_pod *params[3];
 
   if (!format || id != SPA_PARAM_Format)
     return;
@@ -233,10 +253,37 @@ on_stream_param_changed (void                 *user_data,
     SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_header)),
     0);
 
+  params[2] = spa_pod_builder_add_object (
+    &pod_builder,
+    SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
+    SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor),
+    SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int (CURSOR_META_SIZE (384, 384),
+                                                   CURSOR_META_SIZE (1, 1),
+                                                   CURSOR_META_SIZE (384, 384)),
+    0);
+
   pw_stream_update_params (stream->pipewire_stream,
                            params, G_N_ELEMENTS (params));
 }
 
+static void
+process_buffer_metadata (Stream            *stream,
+                         struct spa_buffer *buffer)
+{
+  struct spa_meta_cursor *spa_meta_cursor;
+
+  spa_meta_cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor,
+                                               sizeof *spa_meta_cursor);
+  if (!spa_meta_cursor)
+    return;
+
+  if (!spa_meta_cursor_is_valid (spa_meta_cursor))
+    return;
+
+  stream->cursor_x = spa_meta_cursor->position.x;
+  stream->cursor_y = spa_meta_cursor->position.y;
+}
+
 static void
 sanity_check_memfd (struct spa_buffer *buffer)
 {
@@ -265,6 +312,8 @@ static void
 process_buffer (Stream            *stream,
                 struct spa_buffer *buffer)
 {
+  process_buffer_metadata (stream, buffer);
+
   if (buffer->datas[0].chunk->size == 0)
     g_assert_not_reached ();
   else if (buffer->datas[0].type == SPA_DATA_MemFd)
@@ -366,6 +415,16 @@ stream_wait_for_node (Stream *stream)
     g_main_context_iteration (NULL, TRUE);
 }
 
+static void
+stream_wait_for_cursor_position (Stream *stream,
+                                 int     x,
+                                 int     y)
+{
+  while (stream->cursor_x != x &&
+         stream->cursor_y != y)
+    g_main_context_iteration (NULL, TRUE);
+}
+
 static G_GNUC_UNUSED void
 stream_wait_for_streaming (Stream *stream)
 {
@@ -455,6 +514,21 @@ stream_free (Stream *stream)
   g_free (stream);
 }
 
+static void
+session_notify_absolute_pointer (Session *session,
+                                 Stream  *stream,
+                                 double   x,
+                                 double   y)
+{
+  GError *error = NULL;
+
+  if (!meta_dbus_remote_desktop_session_call_notify_pointer_motion_absolute_sync (
+        session->remote_desktop_session_proxy,
+        g_dbus_proxy_get_object_path (G_DBUS_PROXY (stream->proxy)),
+        x, y, NULL, &error))
+    g_error ("Failed to send absolute pointer motion event: %s", error->message);
+}
+
 static void
 session_start (Session *session)
 {
@@ -491,6 +565,9 @@ session_record_virtual (Session *session,
   Stream *stream;
 
   g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}"));
+  g_variant_builder_add (&properties_builder, "{sv}",
+                         "cursor-mode",
+                         g_variant_new_uint32 (CURSOR_MODE_METADATA));
   properties_variant = g_variant_builder_end (&properties_builder);
 
   if (!meta_dbus_screen_cast_session_call_record_virtual_sync (
@@ -664,11 +741,18 @@ main (int    argc,
 
   session_start (session);
 
+  /* Check that the display server handles events being emitted too early. */
+  session_notify_absolute_pointer (session, stream, 2, 3);
+
   /* Check that we receive the initial frame */
 
   stream_wait_for_node (stream);
+  stream_wait_for_render (stream);
   stream_wait_for_streaming (stream);
+  session_notify_absolute_pointer (session, stream, 6, 5);
+  session_notify_absolute_pointer (session, stream, 5, 6);
   stream_wait_for_render (stream);
+  stream_wait_for_cursor_position (stream, 5, 6);
   g_assert_cmpint (stream->spa_format.size.width, ==, 50);
   g_assert_cmpint (stream->spa_format.size.height, ==, 40);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]