From 01258ed010b8a897d8db26cbe61e8ff3cb378030 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Thu, 5 Mar 2026 15:35:07 +0100 Subject: [PATCH] Backport fix for initial window state, size and position Resolves: https://issues.redhat.com/browse/RHEL-153250 --- ...d-window-description-to-debug-messag.patch | 64 ++++++++ ...eck-for-fullscreen-only-on-normal-wi.patch | 47 ++++++ ...ximized-or-fullscreen-windows-may-be.patch | 41 +++++ ...w-config-Do-not-check-our-own-window.patch | 40 +++++ ...-not-use-meta_window_config_get_is_i.patch | 107 +++++++++++++ ...onfig-Move-the-checks-for-fullscreen.patch | 62 ++++++++ ...sure-initial-window-state-size-and-p.patch | 149 ++++++++++++++++++ gnome-kiosk.spec | 9 ++ 8 files changed, 519 insertions(+) create mode 100644 0001-window-config-Add-window-description-to-debug-messag.patch create mode 100644 0002-window-config-Check-for-fullscreen-only-on-normal-wi.patch create mode 100644 0003-window-config-Maximized-or-fullscreen-windows-may-be.patch create mode 100644 0004-window-config-Do-not-check-our-own-window.patch create mode 100644 0005-window-config-Do-not-use-meta_window_config_get_is_i.patch create mode 100644 0006-window-config-Move-the-checks-for-fullscreen.patch create mode 100644 0007-window-config-Ensure-initial-window-state-size-and-p.patch diff --git a/0001-window-config-Add-window-description-to-debug-messag.patch b/0001-window-config-Add-window-description-to-debug-messag.patch new file mode 100644 index 0000000..9fc8c35 --- /dev/null +++ b/0001-window-config-Add-window-description-to-debug-messag.patch @@ -0,0 +1,64 @@ +From 67969eaf86ad25a0cda554d286c6409edd64fb3c Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 10 Feb 2026 11:46:33 +0100 +Subject: [PATCH 1/7] window-config: Add window description to debug messages + +When deciding whether a window should be made fullscreen by default or +not, include the window description in the debug messages, that will +help with making sense of what GNOME Kiosk does. + +Part-of: +(cherry picked from commit af7073b1151e08c030a3019e54acf29190f31d7b) +--- + compositor/kiosk-window-config.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/compositor/kiosk-window-config.c b/compositor/kiosk-window-config.c +index 8f01ae9..88fa91a 100644 +--- a/compositor/kiosk-window-config.c ++++ b/compositor/kiosk-window-config.c +@@ -471,19 +471,22 @@ kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, + GList *node; + + if (!meta_window_allows_resize (window)) { +- g_debug ("KioskWindowConfig: Window does not allow resizes"); ++ g_debug ("KioskWindowConfig: Window '%s' does not allow resizes", ++ meta_window_get_description (window)); + return FALSE; + } + + if (meta_window_is_override_redirect (window)) { +- g_debug ("KioskWindowConfig: Window is override redirect"); ++ g_debug ("KioskWindowConfig: Window '%s' is override redirect", ++ meta_window_get_description (window)); + return FALSE; + } + + window_type = meta_window_get_window_type (window); + + if (window_type != META_WINDOW_NORMAL) { +- g_debug ("KioskWindowConfig: Window is not normal"); ++ g_debug ("KioskWindowConfig: Window '%s' is not normal", ++ meta_window_get_description (window)); + return FALSE; + } + +@@ -493,10 +496,15 @@ kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, + MetaWindow *existing_window = node->data; + + if (meta_window_is_monitor_sized (existing_window)) { ++ g_debug ("KioskWindowConfig: Another window '%s' is already fullscreen", ++ meta_window_get_description (existing_window)); + return FALSE; + } + } + ++ g_debug ("KioskWindowConfig: Should make window '%s' fullscreen by default", ++ meta_window_get_description (window)); ++ + return TRUE; + } + +-- +2.53.0 + diff --git a/0002-window-config-Check-for-fullscreen-only-on-normal-wi.patch b/0002-window-config-Check-for-fullscreen-only-on-normal-wi.patch new file mode 100644 index 0000000..ce68f68 --- /dev/null +++ b/0002-window-config-Check-for-fullscreen-only-on-normal-wi.patch @@ -0,0 +1,47 @@ +From 068608f2b199d98b477c61dcff8944ba6505f63d Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 11 Feb 2026 11:19:35 +0100 +Subject: [PATCH 2/7] window-config: Check for fullscreen only on normal + windows + +When a new window is mapped initially, GNOME Kiosk will try to guess +whether that window should be fullscreen (unless of course, this is +explicitly requested in the configuration file). + +To do that, it checks every window in the list to see if it's already +mapped the size of the monitor. + +The list it uses for checking the existing windows is based on the +META_TAB_LIST_NORMAL_ALL MetaTabList filter which includes all windows. + +That logic is defeated with apps such as xwaylandvideobridge which map a +window the size of the monitor, but won't show anything on screen. As +xwaylandvideobridge gets started automatically, the first actual window +won't end up being fullscreen as expected. + +To avoid that issue, restrict the MetaTabList to a stricter bare +META_TAB_LIST_NORMAL list, which excludes windows which are not +focusable or who skip the taskbar. + +Part-of: +(cherry picked from commit 8769adbdf280c0cc83e76ce9f472cab72e7e2563) +--- + compositor/kiosk-window-config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/compositor/kiosk-window-config.c b/compositor/kiosk-window-config.c +index 88fa91a..5fa9da6 100644 +--- a/compositor/kiosk-window-config.c ++++ b/compositor/kiosk-window-config.c +@@ -490,7 +490,7 @@ kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, + return FALSE; + } + +- windows = meta_display_get_tab_list (self->display, META_TAB_LIST_NORMAL_ALL, NULL); ++ windows = meta_display_get_tab_list (self->display, META_TAB_LIST_NORMAL, NULL); + + for (node = windows; node != NULL; node = node->next) { + MetaWindow *existing_window = node->data; +-- +2.53.0 + diff --git a/0003-window-config-Maximized-or-fullscreen-windows-may-be.patch b/0003-window-config-Maximized-or-fullscreen-windows-may-be.patch new file mode 100644 index 0000000..d0b4c07 --- /dev/null +++ b/0003-window-config-Maximized-or-fullscreen-windows-may-be.patch @@ -0,0 +1,41 @@ +From 4b866795b4a4bb8ba4e4afca7684b6857b0c6baa Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Thu, 12 Feb 2026 13:42:11 +0100 +Subject: [PATCH 3/7] window-config: Maximized or fullscreen windows may be + resizable + +The mutter API meta_window_allows_resize() is too restrictive for what +we need here, as it will return FALSE if the window is maximized or +fullscreen. + +As a result, if a client (e.g. Firefox trying to restore its previous +state) has set the maximized state prior to reach that code in GNOME +Kiosk, the window won't be toggled fullscreen as expected. + +Only consider windows as "not resizable" if they are also neither +maximized not fullscreen. + +Part-of: +(cherry picked from commit 8eb6589424398c41acffdac6d84adb72ada73f73) +--- + compositor/kiosk-window-config.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/compositor/kiosk-window-config.c b/compositor/kiosk-window-config.c +index 5fa9da6..07d8514 100644 +--- a/compositor/kiosk-window-config.c ++++ b/compositor/kiosk-window-config.c +@@ -470,7 +470,9 @@ kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, + g_autoptr (GList) windows = NULL; + GList *node; + +- if (!meta_window_allows_resize (window)) { ++ if (!meta_window_allows_resize (window) && ++ !meta_window_is_maximized (window) && ++ !meta_window_is_fullscreen (window)) { + g_debug ("KioskWindowConfig: Window '%s' does not allow resizes", + meta_window_get_description (window)); + return FALSE; +-- +2.53.0 + diff --git a/0004-window-config-Do-not-check-our-own-window.patch b/0004-window-config-Do-not-check-our-own-window.patch new file mode 100644 index 0000000..5f39d96 --- /dev/null +++ b/0004-window-config-Do-not-check-our-own-window.patch @@ -0,0 +1,40 @@ +From 31560903b3724ccb10fa7093d0058467b51313a2 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Thu, 12 Feb 2026 15:00:20 +0100 +Subject: [PATCH 4/7] window-config: Do not check our own window + +The new window may already be listed in the meta_display_get_tab_list(). + +If that window is the size of the monitor (as with Firefox trying to +restore its previous size), that would defeat the logic: + + | gnome-kiosk[]: KioskWindowConfig: configure window: W9 (Mozilla Firefox) + | gnome-kiosk[]: KioskWindowConfig: Another window 'W9 (Mozilla Firefox)' is + | already fullscreen + +Just skip our own window when checking other windows. + +Part-of: +(cherry picked from commit 9509c71e447a48187be6958977aaeeac430d57af) +--- + compositor/kiosk-window-config.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/compositor/kiosk-window-config.c b/compositor/kiosk-window-config.c +index 07d8514..037a330 100644 +--- a/compositor/kiosk-window-config.c ++++ b/compositor/kiosk-window-config.c +@@ -497,6 +497,10 @@ kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, + for (node = windows; node != NULL; node = node->next) { + MetaWindow *existing_window = node->data; + ++ /* Don't check our own window */ ++ if (existing_window == window) ++ continue; ++ + if (meta_window_is_monitor_sized (existing_window)) { + g_debug ("KioskWindowConfig: Another window '%s' is already fullscreen", + meta_window_get_description (existing_window)); +-- +2.53.0 + diff --git a/0005-window-config-Do-not-use-meta_window_config_get_is_i.patch b/0005-window-config-Do-not-use-meta_window_config_get_is_i.patch new file mode 100644 index 0000000..22a2540 --- /dev/null +++ b/0005-window-config-Do-not-use-meta_window_config_get_is_i.patch @@ -0,0 +1,107 @@ +From a8d5782b5e1de226c8e6718b43963d109a155718 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Thu, 12 Feb 2026 11:24:23 +0100 +Subject: [PATCH 5/7] window-config: Do not use + meta_window_config_get_is_initial() + +We do not actually need mutter telling whether the first window-config +signal we get is the initial configuration. + +Let's stop using that API and apply our initial setup on the first +window-config we get, that is more reliable. + +This also allows for the next change. + +Part-of: +(cherry picked from commit 080b8a50c2fae9352954e47c31458ca5c82afb45) +--- + compositor/kiosk-window-config.c | 31 ++++++++++++++++++++++++++++++- + 1 file changed, 30 insertions(+), 1 deletion(-) + +diff --git a/compositor/kiosk-window-config.c b/compositor/kiosk-window-config.c +index 037a330..19b8233 100644 +--- a/compositor/kiosk-window-config.c ++++ b/compositor/kiosk-window-config.c +@@ -34,6 +34,8 @@ struct _KioskWindowConfig + + /* Strong references */ + GKeyFile *config_key_file; ++ /* Set of */ ++ GHashTable *window_initial_config; + }; + + enum +@@ -109,6 +111,27 @@ out: + return TRUE; + } + ++static void ++kiosk_window_config_set_initial (KioskWindowConfig *kiosk_window_config, ++ MetaWindow *window) ++{ ++ g_hash_table_add (kiosk_window_config->window_initial_config, window); ++} ++ ++static void ++kiosk_window_config_unset_initial (KioskWindowConfig *kiosk_window_config, ++ MetaWindow *window) ++{ ++ g_hash_table_remove (kiosk_window_config->window_initial_config, window); ++} ++ ++static gboolean ++kiosk_window_config_is_initial (KioskWindowConfig *kiosk_window_config, ++ MetaWindow *window) ++{ ++ return g_hash_table_contains (kiosk_window_config->window_initial_config, window); ++} ++ + static void + kiosk_window_config_on_window_configure (MetaWindow *window, + MetaWindowConfig *window_config, +@@ -117,7 +140,7 @@ kiosk_window_config_on_window_configure (MetaWindow *window, + KioskWindowConfig *self = KIOSK_WINDOW_CONFIG (user_data); + gboolean fullscreen; + +- if (!meta_window_config_get_is_initial (window_config)) { ++ if (!kiosk_window_config_is_initial (self, window)) { + g_debug ("KioskWindowConfig: Ignoring configure for window: %s", + meta_window_get_description (window)); + return; +@@ -145,6 +168,8 @@ kiosk_window_config_on_window_unmanaged (MetaWindow *window, + g_signal_handlers_disconnect_by_func (window, + G_CALLBACK (kiosk_window_config_on_window_unmanaged), + self); ++ ++ kiosk_window_config_unset_initial (self, window); + } + + static void +@@ -163,6 +188,8 @@ kiosk_window_config_on_window_created (MetaDisplay *display, + "unmanaged", + G_CALLBACK (kiosk_window_config_on_window_unmanaged), + self); ++ ++ kiosk_window_config_set_initial (self, window); + } + + static void +@@ -172,6 +199,7 @@ kiosk_window_config_constructed (GObject *object) + + g_set_weak_pointer (&self->display, meta_plugin_get_display (META_PLUGIN (self->compositor))); + g_set_weak_pointer (&self->context, meta_display_get_context (self->display)); ++ self->window_initial_config = g_hash_table_new (g_direct_hash, g_direct_equal); + + g_signal_connect (self->display, + "window-created", +@@ -210,6 +238,7 @@ kiosk_window_config_finalize (GObject *object) + KioskWindowConfig *self = KIOSK_WINDOW_CONFIG (object); + + g_clear_pointer (&self->config_key_file, g_key_file_free); ++ g_clear_pointer (&self->window_initial_config, g_hash_table_destroy); + + G_OBJECT_CLASS (kiosk_window_config_parent_class)->finalize (object); + } +-- +2.53.0 + diff --git a/0006-window-config-Move-the-checks-for-fullscreen.patch b/0006-window-config-Move-the-checks-for-fullscreen.patch new file mode 100644 index 0000000..1093606 --- /dev/null +++ b/0006-window-config-Move-the-checks-for-fullscreen.patch @@ -0,0 +1,62 @@ +From 06ed44aef94a9412348db4692301e455a04649b3 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Thu, 12 Feb 2026 16:19:40 +0100 +Subject: [PATCH 6/7] window-config: Move the checks for fullscreen + +Move the preliminary checks to verify that a window can be made +fullscreen to its own function. + +No functional change, this is preparation work for the next commit. + +Part-of: +(cherry picked from commit 1acb27cdf3b0fd19c0f75431c6b04f5581d7558f) +--- + compositor/kiosk-window-config.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +diff --git a/compositor/kiosk-window-config.c b/compositor/kiosk-window-config.c +index 19b8233..09b7d9c 100644 +--- a/compositor/kiosk-window-config.c ++++ b/compositor/kiosk-window-config.c +@@ -491,14 +491,10 @@ kiosk_window_config_match_window (KioskWindowConfig *kiosk_window_config, + #undef VALUE_OR_EMPTY + + static gboolean +-kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, +- MetaWindow *window) ++kiosk_window_config_can_make_fullscreen (MetaWindow *window) + { + MetaWindowType window_type; + +- g_autoptr (GList) windows = NULL; +- GList *node; +- + if (!meta_window_allows_resize (window) && + !meta_window_is_maximized (window) && + !meta_window_is_fullscreen (window)) { +@@ -521,6 +517,22 @@ kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, + return FALSE; + } + ++ return TRUE; ++} ++ ++static gboolean ++kiosk_window_config_wants_window_fullscreen (KioskWindowConfig *self, ++ MetaWindow *window) ++{ ++ g_autoptr (GList) windows = NULL; ++ GList *node; ++ ++ if (!kiosk_window_config_can_make_fullscreen (window)) { ++ g_debug ("KioskWindowConfig: Window '%s' cannot be made fullscreen", ++ meta_window_get_description (window)); ++ return FALSE; ++ } ++ + windows = meta_display_get_tab_list (self->display, META_TAB_LIST_NORMAL, NULL); + + for (node = windows; node != NULL; node = node->next) { +-- +2.53.0 + diff --git a/0007-window-config-Ensure-initial-window-state-size-and-p.patch b/0007-window-config-Ensure-initial-window-state-size-and-p.patch new file mode 100644 index 0000000..a0322a2 --- /dev/null +++ b/0007-window-config-Ensure-initial-window-state-size-and-p.patch @@ -0,0 +1,149 @@ +From 1c6e9f4bf8151601681b4bd197fcd84167b25ba1 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Thu, 12 Feb 2026 11:37:29 +0100 +Subject: [PATCH 7/7] window-config: Ensure initial window state, size and + position + +The initial window configuration, using Mutter's MetaWindowConfig from +the configure signal may not be applied or is racy, as Wayland clients +may update their buffer size or even change their state using the +xdg_toplevel protocol before the window is mapped on screen. + +As a result, the specified size, position or fullscreen state might be +ignored. + +To avoid that issue, make sure the specified size, location and the +fullscreen state get applied on the initial mapping if the initial +configuration wasn't applied already. + +Part-of: +(cherry picked from commit 4f2793915e8ec814f9ba0bb2ad35242bd96e751f) +--- + compositor/kiosk-window-config.c | 105 +++++++++++++++++++++++++++++++ + 1 file changed, 105 insertions(+) + +diff --git a/compositor/kiosk-window-config.c b/compositor/kiosk-window-config.c +index 09b7d9c..7de3e0f 100644 +--- a/compositor/kiosk-window-config.c ++++ b/compositor/kiosk-window-config.c +@@ -730,12 +730,117 @@ kiosk_window_config_update_window (KioskWindowConfig *kiosk_window_config, + } + } + ++static void ++kiosk_window_config_on_window_configure_initial (KioskWindowConfig *self, ++ MetaWindow *window, ++ MetaWindowConfig *window_config) ++{ ++ gboolean fullscreen; ++ ++ g_debug ("KioskWindowConfig: configure window: %s", meta_window_get_description (window)); ++ ++ fullscreen = kiosk_window_config_wants_window_fullscreen (self, window); ++ meta_window_config_set_is_fullscreen (window_config, fullscreen); ++ kiosk_window_config_update_window (self, ++ window, ++ window_config); ++} ++ ++static void ++kiosk_window_config_ensure_window_state (KioskWindowConfig *kiosk_window_config, ++ MetaWindow *window, ++ MetaWindowConfig *window_config) ++{ ++ gboolean want_fullscreen; ++ ++ want_fullscreen = meta_window_config_get_is_fullscreen (window_config); ++ if (want_fullscreen == meta_window_is_fullscreen (window)) { ++ g_debug ("KioskWindowConfig: Window '%s' state is already %s", ++ meta_window_get_description (window), ++ want_fullscreen ? "fullscreen" : "un-fullscreen"); ++ return; ++ } ++ ++ if (want_fullscreen) { ++ if (kiosk_window_config_can_make_fullscreen (window)) { ++ meta_window_make_fullscreen (window); ++ g_debug ("KioskWindowConfig: Made window '%s' fullscreen", ++ meta_window_get_description (window)); ++ } else { ++ g_debug ("KioskWindowConfig: Cannot make window '%s' fullscreen", ++ meta_window_get_description (window)); ++ } ++ } else { ++ meta_window_unmake_fullscreen (window); ++ g_debug ("KioskWindowConfig: Made window '%s' un-fullscreen", ++ meta_window_get_description (window)); ++ } ++} ++ ++static void ++kiosk_window_config_ensure_window_size_and_position (KioskWindowConfig *kiosk_window_config, ++ MetaWindow *window, ++ MetaWindowConfig *window_config) ++{ ++ MtkRectangle config_rect; ++ MtkRectangle frame_rect; ++ ++ config_rect = meta_window_config_get_rect (window_config); ++ meta_window_get_frame_rect (window, &frame_rect); ++ ++ if (mtk_rectangle_equal (&config_rect, &frame_rect)) { ++ g_debug ("KioskWindowConfig: Window '%s' already at (%i,%i) [%ix%i]", ++ meta_window_get_description (window), ++ config_rect.x, config_rect.y, config_rect.width, config_rect.height); ++ return; ++ } ++ ++ meta_window_move_resize_frame (window, FALSE, config_rect.x, config_rect.y, config_rect.width, config_rect.height); ++ g_debug ("KioskWindowConfig: Fixed window '%s' size and position to (%i,%i) [%ix%i]", ++ meta_window_get_description (window), ++ config_rect.x, config_rect.y, config_rect.width, config_rect.height); ++} ++ ++static MetaWindowConfig * ++kiosk_window_config_create_from_window (MetaWindow *window) ++{ ++ MetaWindowConfig *window_config; ++ MtkRectangle rect; ++ gboolean is_fullscreen; ++ ++ window_config = meta_window_config_new (); ++ ++ meta_window_get_frame_rect (window, &rect); ++ meta_window_config_set_rect (window_config, rect); ++ ++ is_fullscreen = meta_window_is_fullscreen (window); ++ meta_window_config_set_is_fullscreen (window_config, is_fullscreen); ++ ++ return window_config; ++} ++ + void + kiosk_window_config_apply_initial_config (KioskWindowConfig *kiosk_window_config, + MetaWindow *window) + { + int monitor; + MetaWindowType window_type; ++ g_autoptr (MetaWindowConfig) temp_config = NULL; ++ ++ /* If the initial config was not applied on configure, apply it now! */ ++ if (kiosk_window_config_is_initial (kiosk_window_config, window)) { ++ temp_config = kiosk_window_config_create_from_window (window); ++ kiosk_window_config_on_window_configure_initial (kiosk_window_config, ++ window, ++ temp_config); ++ kiosk_window_config_ensure_window_size_and_position (kiosk_window_config, ++ window, ++ temp_config); ++ kiosk_window_config_ensure_window_state (kiosk_window_config, ++ window, ++ temp_config); ++ kiosk_window_config_unset_initial (kiosk_window_config, window); ++ } + + if (!meta_window_is_fullscreen (window)) { + if (kiosk_window_config_wants_window_above (kiosk_window_config, window)) { +-- +2.53.0 + diff --git a/gnome-kiosk.spec b/gnome-kiosk.spec index 08de269..0adeef6 100644 --- a/gnome-kiosk.spec +++ b/gnome-kiosk.spec @@ -72,6 +72,15 @@ Patch: 0001-sessions-Do-not-pretend-we-register-the-session.patch # https://issues.redhat.com/browse/RHEL-153249 Patch: 0001-compositor-Add-new-option-to-hide-the-cursor.patch +# https://issues.redhat.com/browse/RHEL-153250 +Patch: 0001-window-config-Add-window-description-to-debug-messag.patch +Patch: 0002-window-config-Check-for-fullscreen-only-on-normal-wi.patch +Patch: 0003-window-config-Maximized-or-fullscreen-windows-may-be.patch +Patch: 0004-window-config-Do-not-check-our-own-window.patch +Patch: 0005-window-config-Do-not-use-meta_window_config_get_is_i.patch +Patch: 0006-window-config-Move-the-checks-for-fullscreen.patch +Patch: 0007-window-config-Ensure-initial-window-state-size-and-p.patch + %description GNOME Kiosk provides a desktop enviroment suitable for fixed purpose, or single application deployments like wall displays and point-of-sale systems.