diff --git a/src/core/window-private.h b/src/core/window-private.h
index 39a23b2a9..ee1225aab 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -684,8 +684,12 @@ void meta_window_resize_frame_with_gravity (MetaWindow *window,
gboolean meta_window_should_be_showing_on_workspace (MetaWindow *window,
MetaWorkspace *workspace);
+META_EXPORT_TEST
gboolean meta_window_should_be_showing (MetaWindow *window);
+META_EXPORT_TEST
+gboolean meta_window_should_show (MetaWindow *window);
+
void meta_window_update_struts (MetaWindow *window);
/* gets position we need to set to stay in current position,
diff --git a/src/core/window.c b/src/core/window.c
index edfa1ed62..d54d73d40 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -1706,6 +1706,41 @@ meta_window_is_showable (MetaWindow *window)
return TRUE;
}
+/**
+ * meta_window_should_show_on_workspace:
+ *
+ * Tells whether a window should be showing on the passed workspace, without
+ * taking into account whether it can immediately be shown. Whether it can be
+ * shown or not depends on what windowing system it was created from.
+ *
+ * Returns: %TRUE if the window should show.
+ */
+static gboolean
+meta_window_should_show_on_workspace (MetaWindow *window,
+ MetaWorkspace *workspace)
+{
+ return (meta_window_located_on_workspace (window, workspace) &&
+ meta_window_showing_on_its_workspace (window));
+}
+
+/**
+ * meta_window_should_show:
+ *
+ * Tells whether a window should be showing on the current workspace, without
+ * taking into account whether it can immediately be shown. Whether it can be
+ * shown or not depends on what windowing system it was created from.
+ *
+ * Returns: %TRUE if the window should show.
+ */
+gboolean
+meta_window_should_show (MetaWindow *window)
+{
+ MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+ MetaWorkspace *active_workspace = workspace_manager->active_workspace;
+
+ return meta_window_should_show_on_workspace (window, active_workspace);
+}
+
/**
* meta_window_should_be_showing_on_workspace:
*
@@ -1722,10 +1757,7 @@ meta_window_should_be_showing_on_workspace (MetaWindow *window,
if (!meta_window_is_showable (window))
return FALSE;
- /* Windows should be showing if they're located on the
- * workspace and they're showing on their own workspace. */
- return (meta_window_located_on_workspace (window, workspace) &&
- meta_window_showing_on_its_workspace (window));
+ return meta_window_should_show_on_workspace (window, workspace);
}
/**
diff --git a/src/tests/wayland-test-clients/meson.build b/src/tests/wayland-test-clients/meson.build
index 755e593bd..38ac799d0 100644
--- a/src/tests/wayland-test-clients/meson.build
+++ b/src/tests/wayland-test-clients/meson.build
@@ -66,6 +66,9 @@ wayland_test_clients = [
{
'name': 'subsurface-reparenting',
},
+ {
+ 'name': 'toplevel-show-states',
+ },
{
'name': 'xdg-activation',
},
diff --git a/src/tests/wayland-test-clients/toplevel-show-states.c b/src/tests/wayland-test-clients/toplevel-show-states.c
new file mode 100644
index 000000000..431436f4c
--- /dev/null
+++ b/src/tests/wayland-test-clients/toplevel-show-states.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 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 .
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "wayland-test-client-utils.h"
+
+static gboolean running;
+
+static void
+on_surface_painted (WaylandDisplay *display,
+ WaylandSurface *surface)
+{
+ test_driver_sync_point (display->test_driver, 1, NULL);
+ wl_display_roundtrip (display->display);
+ running = FALSE;
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ g_autoptr (WaylandDisplay) display = NULL;
+ g_autoptr (WaylandSurface) surface = NULL;
+
+ display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER |
+ WAYLAND_DISPLAY_CAPABILITY_XDG_SHELL_V6);
+ surface = wayland_surface_new (display, "showing-states", 100, 100, 0xffffffff);
+ wl_surface_commit (surface->wl_surface);
+
+ test_driver_sync_point (display->test_driver, 0, NULL);
+ wait_for_sync_event (display, 0);
+
+ g_signal_connect (display, "surface-painted",
+ G_CALLBACK (on_surface_painted), NULL);
+
+ running = TRUE;
+ while (running)
+ wayland_display_dispatch (display);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c
index c9f3f32e3..692b723df 100644
--- a/src/tests/wayland-unit-tests.c
+++ b/src/tests/wayland-unit-tests.c
@@ -844,6 +844,30 @@ xdg_foreign_set_parent_of (void)
meta_wayland_test_client_finish (wayland_test_client);
}
+static void
+toplevel_show_states (void)
+{
+ MetaWaylandTestClient *wayland_test_client;
+ MetaWindow *window;
+
+ wayland_test_client =
+ meta_wayland_test_client_new (test_context, "toplevel-show-states");
+
+ wait_for_sync_point (0);
+ window = find_client_window ("showing-states");
+
+ g_assert_true (meta_window_should_show (window));
+ g_assert_false (meta_window_should_be_showing (window));
+
+ meta_wayland_test_driver_emit_sync_event (test_driver, 0);
+ wait_for_sync_point (1);
+
+ g_assert_true (meta_window_should_show (window));
+ g_assert_true (meta_window_should_be_showing (window));
+
+ meta_wayland_test_client_finish (wayland_test_client);
+}
+
static void
on_before_tests (void)
{
@@ -921,6 +945,8 @@ init_tests (void)
#endif
g_test_add_func ("/wayland/xdg-foreign/set-parent-of",
xdg_foreign_set_parent_of);
+ g_test_add_func ("/wayland/toplevel/show-states",
+ toplevel_show_states);
}
int