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.
This commit is contained in:
Jonas Ådahl 2018-07-12 10:25:16 +02:00
parent 356cad094b
commit 6d12d2eac2
3 changed files with 83 additions and 27 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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 ||