[mutter] tests: Move window-shown verification to test-runner



commit 6d12d2eac21003607182f3daebd8579bbf5bbb32
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Jul 12 10:25:16 2018 +0200

    tests: Move window-shown verification to test-runner
    
    Previously we relied on the test-client to make sure that a window was
    shown. For X11, we did not need to do anything, but for Wayland we had
    to make sure we had drawn the first frame, otherwise mutter wouldn't
    have a buffer making the window not showable.
    
    Doing it this way doesn't work anymore however, since the 'after-paint'
    event will be emitted even if we didn't actually paint anything. This is
    the case with current Gtk under Wayland, where we won't draw until the
    compositor has configured the surface. In effect, this mean we'll get a
    dummy after-paint emission before the first frame is actually painted.
    
    Instead, move the verification that a "show" command has completed by
    having the test-runner wait for a "shown" signal on the window, which is
    emitted in the end of meta_window_show(). This requires an additional
    call to gdk_display_sync() in the test-client after creating the window,
    to make sure that the window creation vents has been received in the
    compositor.

 src/core/window.c       | 18 ++++++++++++++
 src/tests/test-client.c | 26 +------------------
 src/tests/test-runner.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 83 insertions(+), 27 deletions(-)
---
diff --git a/src/core/window.c b/src/core/window.c
index 3322ffb0f..7ded9f3aa 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -195,6 +195,7 @@ enum
   UNMANAGED,
   SIZE_CHANGED,
   POSITION_CHANGED,
+  SHOWN,
 
   LAST_SIGNAL
 };
@@ -642,6 +643,20 @@ meta_window_class_init (MetaWindowClass *klass)
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
 
+  /**
+   * MetaWindow::shown:
+   * @window: a #MetaWindow
+   *
+   * This is emitted after a window has been shown.
+   */
+  window_signals[SHOWN] =
+    g_signal_new ("shown",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   /**
    * MetaWindow::size-changed:
    * @window: a #MetaWindow
@@ -2553,6 +2568,9 @@ meta_window_show (MetaWindow *window)
       g_signal_emit_by_name (window->display, "window-demands-attention",
                              window);
     }
+
+  if (did_show)
+    g_signal_emit (window, window_signals[SHOWN], 0);
 }
 
 static void
diff --git a/src/tests/test-client.c b/src/tests/test-client.c
index 583608300..0c8eafc98 100644
--- a/src/tests/test-client.c
+++ b/src/tests/test-client.c
@@ -41,16 +41,6 @@ lookup_window (const char *window_id)
   return window;
 }
 
-static void
-on_after_paint  (GdkFrameClock *clock,
-                 GMainLoop     *loop)
-{
-  g_signal_handlers_disconnect_by_func (clock,
-                                        (gpointer) on_after_paint,
-                                        loop);
-  g_main_loop_quit (loop);
-}
-
 static void
 process_line (const char *line)
 {
@@ -170,25 +160,11 @@ process_line (const char *line)
         }
 
       GtkWidget *window = lookup_window (argv[1]);
-      GdkWindow *gdk_window = gtk_widget_get_window (window);
       if (!window)
         goto out;
 
       gtk_widget_show (window);
-
-      /* When a Wayland client, we cannot be really sure that the window has
-       * been mappable until after we have painted. So, in order to have the
-       * test runner rely on the "show" command to have done what the client
-       * needs to do in order for a window to be mappable compositor side, lets
-       * wait with returning until after the first frame.
-       */
-      GdkFrameClock *frame_clock = gdk_window_get_frame_clock (gdk_window);
-      GMainLoop *loop = g_main_loop_new (NULL, FALSE);
-      g_signal_connect (frame_clock, "after-paint",
-                        G_CALLBACK (on_after_paint),
-                        loop);
-      g_main_loop_run (loop);
-      g_main_loop_unref (loop);
+      gdk_display_sync (gdk_display_get_default ());
     }
   else if (strcmp (argv[0], "hide") == 0)
     {
diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
index 7b0917f21..5c3d25bc9 100644
--- a/src/tests/test-runner.c
+++ b/src/tests/test-runner.c
@@ -327,6 +327,39 @@ test_case_check_xserver_stacking (TestCase *test,
   return *error == NULL;
 }
 
+typedef struct _WaitForShownData
+{
+  GMainLoop *loop;
+  MetaWindow *window;
+  guint shown_handler_id;
+} WaitForShownData;
+
+static void
+on_window_shown (MetaWindow       *window,
+                 WaitForShownData *data)
+{
+  g_main_loop_quit (data->loop);
+}
+
+static gboolean
+test_case_wait_for_showing_before_redraw (gpointer user_data)
+{
+  WaitForShownData *data = user_data;
+
+  if (meta_window_is_hidden (data->window))
+    {
+      data->shown_handler_id = g_signal_connect (data->window, "shown",
+                                                 G_CALLBACK (on_window_shown),
+                                                 data);
+    }
+  else
+    {
+      g_main_loop_quit (data->loop);
+    }
+
+  return FALSE;
+}
+
 static gboolean
 test_case_do (TestCase *test,
               int       argc,
@@ -407,8 +440,37 @@ test_case_do (TestCase *test,
                            NULL))
         return FALSE;
     }
-  else if (strcmp (argv[0], "show") == 0 ||
-           strcmp (argv[0], "hide") == 0 ||
+  else if (strcmp (argv[0], "show") == 0)
+    {
+      if (argc != 2)
+        BAD_COMMAND("usage: %s <client-id>/<window-id>", argv[0]);
+
+      TestClient *client;
+      const char *window_id;
+      if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
+        return FALSE;
+
+      if (!test_client_do (client, error, argv[0], window_id, NULL))
+        return FALSE;
+
+      MetaWindow *window = test_client_find_window (client, window_id, error);
+      if (!window)
+        return FALSE;
+
+      WaitForShownData data = {
+        .loop = g_main_loop_new (NULL, FALSE),
+        .window = window,
+      };
+      meta_later_add (META_LATER_BEFORE_REDRAW,
+                      test_case_wait_for_showing_before_redraw,
+                      &data,
+                      NULL);
+      g_main_loop_run (data.loop);
+      if (data.shown_handler_id)
+        g_signal_handler_disconnect (window, data.shown_handler_id);
+      g_main_loop_unref (data.loop);
+    }
+  else if (strcmp (argv[0], "hide") == 0 ||
            strcmp (argv[0], "activate") == 0 ||
            strcmp (argv[0], "raise") == 0 ||
            strcmp (argv[0], "lower") == 0 ||


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