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 /", 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 ||