From fc46cee8bd30744496b56843f5d3b79aa505300f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 21 Apr 2021 14:14:23 -0400 Subject: [PATCH] Fix keyboard layouts getting out of sync in anaconda --- ...ls-Log-when-executing-deferred-tasks.patch | 116 ++++ ...nager-Fix-overzealous-rename-mistake.patch | 4 +- ...signal-for-reporting-X-server-events.patch | 6 +- ...nager-Add-function-to-load-input-sou.patch | 219 ------- ...nager-Support-libxklavier-managed-ke.patch | 532 +++++++++++++----- gnome-kiosk.spec | 11 +- 6 files changed, 515 insertions(+), 373 deletions(-) create mode 100644 0001-gobject-utils-Log-when-executing-deferred-tasks.patch rename 0001-compositor-Add-signal-for-reporting-X-server-events.patch => 0003-compositor-Add-signal-for-reporting-X-server-events.patch (98%) delete mode 100644 0003-input-sources-manager-Add-function-to-load-input-sou.patch rename 0004-wip-Better-support-libxklavier.patch => 0004-input-sources-manager-Support-libxklavier-managed-ke.patch (72%) diff --git a/0001-gobject-utils-Log-when-executing-deferred-tasks.patch b/0001-gobject-utils-Log-when-executing-deferred-tasks.patch new file mode 100644 index 0000000..a83c690 --- /dev/null +++ b/0001-gobject-utils-Log-when-executing-deferred-tasks.patch @@ -0,0 +1,116 @@ +From ab8482bab7981321f0f2fbd401907ac34028bb1a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 20 Apr 2021 09:27:01 -0400 +Subject: [PATCH 1/4] gobject-utils: Log when executing deferred tasks + +At the moment, the code defers execution until "later" in +various parts of the code to ensure a flood of related events +doesn't lead to a flood of duplicated work. + +But, its on the called code to log at the moment. + +This commit adds logging to the generic part of the code to +for clarity. +--- + compositor/kiosk-gobject-utils.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/compositor/kiosk-gobject-utils.c b/compositor/kiosk-gobject-utils.c +index a0dfcd8..c38db7e 100644 +--- a/compositor/kiosk-gobject-utils.c ++++ b/compositor/kiosk-gobject-utils.c +@@ -1,83 +1,87 @@ + #include "config.h" + #include "kiosk-gobject-utils.h" + + #define COALESCE_INTERVAL 250 /* milliseconds */ + + static void + on_task_wait_complete (GObject *self, + GTask *task) + { + KioskObjectCallback callback; + gpointer user_data; + gboolean completed; + g_autofree char *data_key = NULL; + ++ g_debug ("KioskGObjectUtils: Executing deferred task '%s'", g_task_get_name (task)); ++ + callback = g_object_get_data (G_OBJECT (task), "callback"); + user_data = g_object_get_data (G_OBJECT (task), "user-data"); + + completed = g_task_propagate_boolean (task, NULL); + + if (completed) { + callback (self, user_data); + } + + data_key = g_strdup_printf ("kiosk-gobject-utils-%p-%p-task", + callback, user_data); + + g_object_set_data (G_OBJECT (self), data_key, NULL); + } + + static gboolean + on_coalesce_timeout (GTask *task) + { + if (!g_task_return_error_if_cancelled (task)) { + g_task_return_boolean (task, TRUE); + } + + return G_SOURCE_REMOVE; + } + + void + kiosk_gobject_utils_queue_defer_callback (GObject *self, + const char *name, + GCancellable *cancellable, + KioskObjectCallback callback, + gpointer user_data) + { + g_autofree char *data_key = NULL; + g_autoptr (GSource) timeout_source = NULL; + GTask *task; + + g_return_if_fail (G_IS_OBJECT (self)); + g_return_if_fail (callback != NULL); + + data_key = g_strdup_printf ("kiosk-gobject-utils-%p-%p-task", + callback, user_data); + + task = g_object_get_data (G_OBJECT (self), data_key); + + if (task != NULL) { + return; + } + + timeout_source = g_timeout_source_new (COALESCE_INTERVAL); + +- if (name != NULL) { +- g_source_set_name (timeout_source, name); +- } +- + task = g_task_new (self, + cancellable, + (GAsyncReadyCallback) on_task_wait_complete, + NULL); ++ ++ if (name != NULL) { ++ g_task_set_name (task, name); ++ g_debug ("KioskGObjectUtils: Deferring task '%s' for %dms", name, COALESCE_INTERVAL); ++ } ++ + g_task_attach_source (task, timeout_source, G_SOURCE_FUNC (on_coalesce_timeout)); + + g_object_set_data (G_OBJECT (task), "callback", callback); + g_object_set_data (G_OBJECT (task), "user-data", user_data); + + g_object_set_data_full (G_OBJECT (self), + data_key, + task, + (GDestroyNotify) + g_object_unref); + } +-- +2.30.2 + diff --git a/0002-input-sources-manager-Fix-overzealous-rename-mistake.patch b/0002-input-sources-manager-Fix-overzealous-rename-mistake.patch index fb0dc80..4eda3ca 100644 --- a/0002-input-sources-manager-Fix-overzealous-rename-mistake.patch +++ b/0002-input-sources-manager-Fix-overzealous-rename-mistake.patch @@ -1,4 +1,4 @@ -From 83e38979f48829d4498b2df6ea62aafa34c1975b Mon Sep 17 00:00:00 2001 +From f553708a756682d625f51e7c0f3d2a31f39442bb Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 15 Apr 2021 14:39:55 -0400 Subject: [PATCH 2/4] input-sources-manager: Fix overzealous rename mistake @@ -184,5 +184,5 @@ index 58d7a4c..a1a4cfa 100644 old_input_source_group = kiosk_input_sources_manager_get_selected_input_source_group (self); -- -2.31.1 +2.30.2 diff --git a/0001-compositor-Add-signal-for-reporting-X-server-events.patch b/0003-compositor-Add-signal-for-reporting-X-server-events.patch similarity index 98% rename from 0001-compositor-Add-signal-for-reporting-X-server-events.patch rename to 0003-compositor-Add-signal-for-reporting-X-server-events.patch index 9233f6a..8a9cb41 100644 --- a/0001-compositor-Add-signal-for-reporting-X-server-events.patch +++ b/0003-compositor-Add-signal-for-reporting-X-server-events.patch @@ -1,7 +1,7 @@ -From db59d653751018f9b79c2a38a996fc7f0692d6b5 Mon Sep 17 00:00:00 2001 +From a944f0d27a42028ec18edb17f65957780c400104 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 15 Apr 2021 13:28:00 -0400 -Subject: [PATCH 1/4] compositor: Add signal for reporting X server events +Subject: [PATCH 3/4] compositor: Add signal for reporting X server events The keyboard layout handling code currently doesn't notice when the keyboard layout is changed using libxklavier, out from @@ -225,5 +225,5 @@ index dad7776..14f5de3 100644 return KIOSK_SERVICE (self->service); -- -2.31.1 +2.30.2 diff --git a/0003-input-sources-manager-Add-function-to-load-input-sou.patch b/0003-input-sources-manager-Add-function-to-load-input-sou.patch deleted file mode 100644 index 8c79451..0000000 --- a/0003-input-sources-manager-Add-function-to-load-input-sou.patch +++ /dev/null @@ -1,219 +0,0 @@ -From 60e52b132e9957452004c85a0999b37a2e46ff55 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 15 Apr 2021 14:41:41 -0400 -Subject: [PATCH 3/4] input-sources-manager: Add function to load input sources - from strings - -kiosk_input_sources_manager_set_input_sources_from_system_settings -currently has code to load fetch the strings from localed and then -use them. - -This commit moves the "use them" part to its own function so it can -be reused in a subsequent commit for something else. ---- - compositor/kiosk-input-sources-manager.c | 73 ++++++++++++++++-------- - 1 file changed, 48 insertions(+), 25 deletions(-) - -diff --git a/compositor/kiosk-input-sources-manager.c b/compositor/kiosk-input-sources-manager.c -index a1a4cfa..4b4ef62 100644 ---- a/compositor/kiosk-input-sources-manager.c -+++ b/compositor/kiosk-input-sources-manager.c -@@ -793,147 +793,170 @@ kiosk_input_sources_manager_add_layout (KioskInputSourcesManager *self, - input_source_group = kiosk_input_sources_manager_add_new_input_source_group (self, options); - } - - mapping_full = !kiosk_input_source_group_add_layout (input_source_group, xkb_layout, xkb_variant); - - if (mapping_full) { - g_debug ("KioskInputSourcesManager: Keyboard mapping full, starting another one"); - - input_source_group = kiosk_input_sources_manager_add_new_input_source_group (self, options); - - kiosk_input_source_group_add_layout (input_source_group, xkb_layout, xkb_variant); - } - } - - void - kiosk_input_sources_manager_add_input_engine (KioskInputSourcesManager *self, - const char *engine_name, - const char *options) - { - KioskInputSourceGroup *input_source_group = NULL; - - g_debug ("KioskInputSourcesManager: Adding input engine '%s'", engine_name); - - input_source_group = kiosk_input_sources_manager_add_new_input_source_group (self, options); - - kiosk_input_source_group_set_input_engine (input_source_group, engine_name); - kiosk_input_source_group_set_options (input_source_group, options); - } - - --gboolean --kiosk_input_sources_manager_set_input_sources_from_system_configuration (KioskInputSourcesManager *self) -+static gboolean -+kiosk_input_sources_manager_set_input_sources_from_strings (KioskInputSourcesManager *self, -+ const char *layouts_string, -+ const char *variants_string, -+ const char *options_string) - { - KioskInputSourceGroup *old_input_source_group; - g_autofree char *old_input_engine = NULL; - g_autofree char *old_selected_layout = NULL; - -- const char *layouts_string = NULL; - g_auto (GStrv) layouts = NULL; - size_t number_of_layouts = 0; - -- const char *variants_string = NULL; - g_auto (GStrv) variants = NULL; - size_t number_of_variants = 0; - -- const char *options = NULL; - size_t i, j; - -- gboolean input_source_group_active; -+ gboolean input_sources_active; - - g_return_val_if_fail (KIOSK_IS_INPUT_SOURCES_MANAGER (self), FALSE); - -- if (self->locale_proxy == NULL) { -- return FALSE; -- } -- -- g_debug ("KioskInputSourcesManager: Setting keymap from system configuration"); -- -- layouts_string = sd_locale1_get_x11_layout (self->locale_proxy); -- g_debug ("KioskInputSourcesManager: System layout is '%s'", layouts_string); -- - layouts = g_strsplit (layouts_string, ",", -1); - number_of_layouts = g_strv_length (layouts); - -- options = sd_locale1_get_x11_options (self->locale_proxy); -- g_debug ("KioskInputSourcesManager: System layout options are '%s'", options); -- -- variants_string = sd_locale1_get_x11_variant (self->locale_proxy); -- g_debug ("KioskInputSourcesManager: System layout variant is '%s'", variants_string); - variants = g_strsplit (variants_string, ",", -1); - number_of_variants = g_strv_length (variants); - - if (number_of_layouts < number_of_variants) { - g_debug ("KioskInputSourcesManager: There is a layout variant mismatch"); - return FALSE; - } - - old_input_source_group = kiosk_input_sources_manager_get_selected_input_source_group (self); - - if (old_input_source_group != NULL) { - old_input_engine = g_strdup (kiosk_input_source_group_get_input_engine (old_input_source_group)); - old_selected_layout = kiosk_input_source_group_get_selected_layout (old_input_source_group); - } - - kiosk_input_sources_manager_clear_input_sources (self); - - for (i = 0, j = 0; layouts[i] != NULL; i++) { - char *id = NULL; - const char *layout = layouts[i]; - const char *variant = ""; - - if (variants[j] != NULL) { - variant = variants[j++]; - } - - if (variant[0] == '\0') { - id = g_strdup (layout); - } else { - id = g_strdup_printf ("%s+%s", layout, variant); - } - -- kiosk_input_sources_manager_add_layout (self, id, options); -+ kiosk_input_sources_manager_add_layout (self, id, options_string); - } - -- input_source_group_active = activate_best_available_input_source_group (self, old_input_engine, old_selected_layout); -+ input_sources_active = activate_best_available_input_source_group (self, old_input_engine, old_selected_layout); - -- if (!input_source_group_active) { -+ if (!input_sources_active) { -+ return FALSE; -+ } -+ -+ sync_dbus_service (self); -+ -+ return TRUE; -+} -+ -+gboolean -+kiosk_input_sources_manager_set_input_sources_from_system_configuration (KioskInputSourcesManager *self) -+{ -+ const char *layouts_string = NULL; -+ const char *variants_string = NULL; -+ const char *options = NULL; -+ -+ gboolean input_sources_active; -+ -+ g_return_val_if_fail (KIOSK_IS_INPUT_SOURCES_MANAGER (self), FALSE); -+ -+ if (self->locale_proxy == NULL) { -+ return FALSE; -+ } -+ -+ g_debug ("KioskInputSourcesManager: Setting keymap from system configuration"); -+ -+ layouts_string = sd_locale1_get_x11_layout (self->locale_proxy); -+ g_debug ("KioskInputSourcesManager: System layout is '%s'", layouts_string); -+ -+ options = sd_locale1_get_x11_options (self->locale_proxy); -+ g_debug ("KioskInputSourcesManager: System layout options are '%s'", options); -+ -+ variants_string = sd_locale1_get_x11_variant (self->locale_proxy); -+ g_debug ("KioskInputSourcesManager: System layout variant is '%s'", variants_string); -+ -+ input_sources_active = kiosk_input_sources_manager_set_input_sources_from_strings (self, layouts_string, variants_string, options); -+ -+ if (!input_sources_active) { - const char * const *locales; - - locales = sd_locale1_get_locale (self->locale_proxy); -- input_source_group_active = kiosk_input_sources_manager_set_input_sources_from_locales (self, locales, options); -+ input_sources_active = kiosk_input_sources_manager_set_input_sources_from_locales (self, locales, options); - } - - sync_dbus_service (self); - self->overriding_configuration = FALSE; - -- if (!input_source_group_active) { -+ if (!input_sources_active) { - g_debug ("KioskInputSourcesManager: System has no valid configured input sources"); - return FALSE; - } - - return TRUE; - } - - static void - on_session_input_configuration_changed (KioskInputSourcesManager *self) - { - g_debug ("KioskInputSourcesManager: Session input sources configuration changed"); - - if (self->overriding_configuration) { - g_debug ("KioskInputSourcesManager: Ignoring change, because keymap is overriden"); - return; - } - - kiosk_input_sources_manager_set_input_sources_from_session_configuration (self); - } - - static void - on_session_input_sources_setting_changed (KioskInputSourcesManager *self) - { - kiosk_gobject_utils_queue_defer_callback (G_OBJECT (self), - "[kiosk-input-sources-manager] on_session_input_configuration_changed", - self->cancellable, - KIOSK_OBJECT_CALLBACK (on_session_input_configuration_changed), - NULL); - } - --- -2.31.1 - diff --git a/0004-wip-Better-support-libxklavier.patch b/0004-input-sources-manager-Support-libxklavier-managed-ke.patch similarity index 72% rename from 0004-wip-Better-support-libxklavier.patch rename to 0004-input-sources-manager-Support-libxklavier-managed-ke.patch index f13a86e..e365d28 100644 --- a/0004-wip-Better-support-libxklavier.patch +++ b/0004-input-sources-manager-Support-libxklavier-managed-ke.patch @@ -1,29 +1,100 @@ -From c99306e0efcf3113d592bc963b4dfac6504b724d Mon Sep 17 00:00:00 2001 +From 5b23d5f86f554373d4207d4f95c50bc86892e634 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 15 Apr 2021 14:43:17 -0400 -Subject: [PATCH 4/4] wip! Better support libxklavier +Subject: [PATCH 4/4] input-sources-manager: Support libxklavier managed + keyboard layouts -Mutter currently doesn't allow libxklavier to change the group out from +Mutter currently doesn't allow libxklavier to change the layout out from under it. -This commit fixes that, but also makes sure that current layout state -stays in sync with X server state. +This commit fixes that on X being careful to make sure the current layout +state, as gnome-kiosk sees it, stays in sync with X server state. --- - compositor/kiosk-input-source-group.c | 17 + + compositor/kiosk-input-source-group.c | 47 +- compositor/kiosk-input-source-group.h | 5 +- - compositor/kiosk-input-sources-manager.c | 142 ++++++ - compositor/kiosk-x-keyboard-manager.c | 579 +++++++++++++++++++++++ - compositor/kiosk-x-keyboard-manager.h | 22 + + compositor/kiosk-input-sources-manager.c | 143 ++++++ + compositor/kiosk-input-sources-manager.h | 2 + + compositor/kiosk-x-keyboard-manager.c | 565 +++++++++++++++++++++++ + compositor/kiosk-x-keyboard-manager.h | 29 ++ meson.build | 1 + - 6 files changed, 765 insertions(+), 1 deletion(-) + 7 files changed, 786 insertions(+), 6 deletions(-) create mode 100644 compositor/kiosk-x-keyboard-manager.c create mode 100644 compositor/kiosk-x-keyboard-manager.h diff --git a/compositor/kiosk-input-source-group.c b/compositor/kiosk-input-source-group.c -index a0c924e..6e2712f 100644 +index a0c924e..c33ca05 100644 --- a/compositor/kiosk-input-source-group.c +++ b/compositor/kiosk-input-source-group.c -@@ -213,60 +213,66 @@ kiosk_input_source_group_set_input_engine (KioskInputSourceGroup *self, +@@ -1,67 +1,67 @@ + #include "config.h" + #include "kiosk-input-source-group.h" + + #include + #include + + #include + + #include + + #define GNOME_DESKTOP_USE_UNSTABLE_API + #include + #include + + #include "kiosk-gobject-utils.h" + #include "kiosk-input-sources-manager.h" + + #define KIOSK_INPUT_SOURCE_GROUP_MAX_LAYOUTS 3 + + struct _KioskInputSourceGroup + { + GObject parent; + + /* weak references */ + KioskInputSourcesManager *input_sources_manager; + KioskInputEngineManager *input_engine_manager; ++ KioskXKeyboardManager *x_keyboard_manager; + + /* strong references */ + char *input_engine_name; + GPtrArray *layouts; + GPtrArray *variants; + char *options; + + /* state */ + xkb_layout_index_t layout_index; + }; +- + enum + { + PROP_INPUT_SOURCES_MANAGER = 1, + NUMBER_OF_PROPERTIES + }; + + static GParamSpec *kiosk_input_source_group_properties[NUMBER_OF_PROPERTIES] = { NULL, }; + + G_DEFINE_TYPE (KioskInputSourceGroup, kiosk_input_source_group, G_TYPE_OBJECT) + + static void kiosk_input_source_group_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *param_spec); + static void kiosk_input_source_group_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *param_spec); + + static void kiosk_input_source_group_constructed (GObject *object); + static void kiosk_input_source_group_dispose (GObject *object); + + KioskInputSourceGroup * + kiosk_input_source_group_new (KioskInputSourcesManager *input_sources_manager) + { + GObject *object; + + object = g_object_new (KIOSK_TYPE_INPUT_SOURCE_GROUP, + "input-sources-manager", input_sources_manager, + NULL); +@@ -213,121 +213,156 @@ kiosk_input_source_group_set_input_engine (KioskInputSourceGroup *self, const char *engine_name) { g_debug ("KioskInputSourceGroup: Setting input engine to '%s'", engine_name); @@ -66,6 +137,8 @@ index a0c924e..6e2712f 100644 size_t number_of_layouts; g_autofree char *layouts = NULL; g_autofree char *variants = NULL; ++ gboolean keymap_already_set = FALSE; ++ gboolean layout_group_already_locked = FALSE; g_debug ("KioskInputSourceGroup: Activating input source"); @@ -90,16 +163,36 @@ index a0c924e..6e2712f 100644 if (!activated) { g_debug ("KioskInputSourceGroup: Could not activate input engine '%s'", self->input_engine_name); return FALSE; -@@ -274,60 +280,71 @@ kiosk_input_source_group_activate (KioskInputSourceGroup *self) + } } else { kiosk_input_engine_manager_activate_engine (self->input_engine_manager, NULL); } - g_debug ("KioskInputSourceGroup: Setting keyboard mapping to [%s] (%s) [%s]", - layouts, variants, self->options); +- g_debug ("KioskInputSourceGroup: Setting keyboard mapping to [%s] (%s) [%s]", +- layouts, variants, self->options); ++ if (self->x_keyboard_manager != NULL) { ++ keymap_already_set = kiosk_x_keyboard_manager_keymap_is_active (self->x_keyboard_manager, (const char * const *) self->layouts->pdata, (const char * const *) self->variants->pdata, self->options); ++ layout_group_already_locked = kiosk_x_keyboard_manager_layout_group_is_locked (self->x_keyboard_manager, self->layout_index); - meta_backend_set_keymap (meta_get_backend (), layouts, variants, self->options); - meta_backend_lock_layout_group (meta_get_backend (), self->layout_index); +- meta_backend_set_keymap (meta_get_backend (), layouts, variants, self->options); +- meta_backend_lock_layout_group (meta_get_backend (), self->layout_index); ++ } ++ ++ if (!keymap_already_set) { ++ g_debug ("KioskInputSourceGroup: Setting keyboard mapping to [%s] (%s) [%s]", ++ layouts, variants, self->options); ++ ++ meta_backend_set_keymap (meta_get_backend (), layouts, variants, self->options); ++ } ++ ++ if (!layout_group_already_locked) { ++ g_debug ("KioskInputSourceGroup: Locking layout to index %d", self->layout_index); ++ meta_backend_lock_layout_group (meta_get_backend (), self->layout_index); ++ } ++ ++ if (keymap_already_set && layout_group_already_locked) { ++ g_debug ("KioskInputSourceGroup: Input source already active"); ++ } return TRUE; } @@ -162,6 +255,58 @@ index a0c924e..6e2712f 100644 void kiosk_input_source_group_switch_to_first_layout (KioskInputSourceGroup *self) { +@@ -492,49 +527,51 @@ kiosk_input_source_group_get_property (GObject *object, + GValue *value, + GParamSpec *param_spec) + { + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec); + break; + } + } + + static void + kiosk_input_source_group_init (KioskInputSourceGroup *self) + { + g_debug ("KioskInputSourceGroup: Initializing"); + + self->layouts = g_ptr_array_new_full (KIOSK_INPUT_SOURCE_GROUP_MAX_LAYOUTS + 1, g_free); + self->variants = g_ptr_array_new_full (KIOSK_INPUT_SOURCE_GROUP_MAX_LAYOUTS + 1, g_free); + + g_ptr_array_add (self->layouts, NULL); + g_ptr_array_add (self->variants, NULL); + } + + static void + kiosk_input_source_group_constructed (GObject *object) + { + KioskInputSourceGroup *self = KIOSK_INPUT_SOURCE_GROUP (object); + + G_OBJECT_CLASS (kiosk_input_source_group_parent_class)->constructed (object); + + g_set_weak_pointer (&self->input_engine_manager, kiosk_input_sources_manager_get_input_engine_manager (self->input_sources_manager)); ++ g_set_weak_pointer (&self->x_keyboard_manager, kiosk_input_sources_manager_get_x_keyboard_manager (self->input_sources_manager)); + } + + static void + kiosk_input_source_group_dispose (GObject *object) + { + KioskInputSourceGroup *self = KIOSK_INPUT_SOURCE_GROUP (object); + + g_debug ("KioskInputSourceGroup: Disposing"); + + g_clear_pointer (&self->options, g_free); + + g_clear_pointer (&self->variants, g_ptr_array_unref); + g_clear_pointer (&self->layouts, g_ptr_array_unref); + ++ g_clear_weak_pointer (&self->x_keyboard_manager); + g_clear_weak_pointer (&self->input_engine_manager); + g_clear_weak_pointer (&self->input_sources_manager); + + G_OBJECT_CLASS (kiosk_input_source_group_parent_class)->dispose (object); + } diff --git a/compositor/kiosk-input-source-group.h b/compositor/kiosk-input-source-group.h index cec8b2f..d255da4 100644 --- a/compositor/kiosk-input-source-group.h @@ -210,10 +355,10 @@ index cec8b2f..d255da4 100644 gboolean kiosk_input_source_group_switch_to_previous_layout (KioskInputSourceGroup *input_sources); G_END_DECLS diff --git a/compositor/kiosk-input-sources-manager.c b/compositor/kiosk-input-sources-manager.c -index 4b4ef62..c6c8c91 100644 +index a1a4cfa..7bb67b0 100644 --- a/compositor/kiosk-input-sources-manager.c +++ b/compositor/kiosk-input-sources-manager.c -@@ -1,83 +1,88 @@ +@@ -1,83 +1,85 @@ #include "config.h" #include "kiosk-input-sources-manager.h" @@ -227,9 +372,6 @@ index 4b4ef62..c6c8c91 100644 #include #include -+#include -+ -+#include #define GNOME_DESKTOP_USE_UNSTABLE_API #include @@ -302,7 +444,74 @@ index 4b4ef62..c6c8c91 100644 guint property_id, GValue *value, GParamSpec *param_spec); -@@ -1363,60 +1368,189 @@ on_input_engine_manager_active_engine_changed (KioskInputSourcesManager *self) +@@ -690,60 +692,66 @@ on_dbus_service_handle_select_input_source (KioskInputSourcesManager *self, + static gboolean + on_dbus_service_handle_select_next_input_source (KioskInputSourcesManager *self, + GDBusMethodInvocation *invocation) + { + g_debug ("KioskService: Handling SelectNextInputSource() call"); + + kiosk_input_sources_manager_switch_to_next_input_source (self); + kiosk_dbus_input_sources_manager_complete_select_next_input_source (self->dbus_service, invocation); + + return TRUE; + } + + static gboolean + on_dbus_service_handle_select_previous_input_source (KioskInputSourcesManager *self, + GDBusMethodInvocation *invocation) + { + g_debug ("KioskService: Handling SelectPreviousInputSource() call"); + + kiosk_input_sources_manager_switch_to_previous_input_source (self); + kiosk_dbus_input_sources_manager_complete_select_previous_input_source (self->dbus_service, invocation); + + return TRUE; + } + + KioskInputEngineManager * + kiosk_input_sources_manager_get_input_engine_manager (KioskInputSourcesManager *self) + { + return self->input_engine_manager; + } + ++KioskXKeyboardManager * ++kiosk_input_sources_manager_get_x_keyboard_manager (KioskInputSourcesManager *self) ++{ ++ return self->x_keyboard_manager; ++} ++ + void + kiosk_input_sources_manager_clear_input_sources (KioskInputSourcesManager *self) + { + g_debug ("KioskInputSourcesManager: Clearing selected keyboard mappings"); + + g_ptr_array_set_size (self->input_source_groups, 0); + self->input_source_groups_index = 0; + } + + static void + kiosk_input_sources_manager_add_input_source_group (KioskInputSourcesManager *self, + KioskInputSourceGroup *input_source_group) + { + g_ptr_array_add (self->input_source_groups, g_object_ref (input_source_group)); + } + + static KioskInputSourceGroup * + kiosk_input_sources_manager_add_new_input_source_group (KioskInputSourcesManager *self, + const char *options) + { + g_autoptr (KioskInputSourceGroup) input_source_group = NULL; + + g_debug ("KioskInputSourcesManager: Adding new, empty keyboard mapping with options '%s'", + options); + + input_source_group = kiosk_input_source_group_new (self); + kiosk_input_source_group_set_options (input_source_group, options); + + kiosk_input_sources_manager_add_input_source_group (self, input_source_group); + +@@ -1340,60 +1348,180 @@ on_input_engine_manager_active_engine_changed (KioskInputSourcesManager *self) active_input_engine = kiosk_input_engine_manager_get_active_engine (self->input_engine_manager); @@ -336,24 +545,27 @@ index 4b4ef62..c6c8c91 100644 +static void +process_x_keyboard_manager_selected_layout_change (KioskInputSourcesManager *self) +{ -+ const char *selected_layout; ++ const char *selected_layout; + -+ selected_layout = kiosk_x_keyboard_manager_get_selected_layout (self->x_keyboard_manager); ++ selected_layout = kiosk_x_keyboard_manager_get_selected_layout (self->x_keyboard_manager); + -+ if (selected_layout == NULL) { -+ return; -+ } ++ if (selected_layout == NULL) { ++ return; ++ } + -+ g_debug ("KioskInputSourcesManager: X server changed active layout to %s", selected_layout); ++ g_debug ("KioskInputSourcesManager: X server changed active layout to %s", selected_layout); + -+ activate_input_source_group_with_layout (self, selected_layout); ++ activate_input_source_group_with_layout (self, selected_layout); + -+ sync_dbus_service (self); ++ sync_dbus_service (self); +} + +static void +on_x_keyboard_manager_selected_layout_changed (KioskInputSourcesManager *self) +{ ++ /* We defer processing the layout change for a bit, because often in practice there is more than ++ * one layout change at the same time, and only the last one is the desired one ++ */ + kiosk_gobject_utils_queue_defer_callback (G_OBJECT (self), + "[kiosk-input-sources-manager] process_x_keyboard_manager_selected_layout_change", + self->cancellable, @@ -400,7 +612,7 @@ index 4b4ef62..c6c8c91 100644 +} + +static void -+process_x_keyboard_manager_layouts_change (KioskInputSourcesManager *self) ++on_x_keyboard_manager_layouts_changed (KioskInputSourcesManager *self) +{ + const char * const *new_layouts; + const char *selected_layout; @@ -433,23 +645,11 @@ index 4b4ef62..c6c8c91 100644 +} + +static void -+on_x_keyboard_manager_layouts_changed (KioskInputSourcesManager *self) -+{ -+ kiosk_gobject_utils_queue_defer_callback (G_OBJECT (self), -+ "[kiosk-input-sources-manager] process_x_keyboard_manager_layouts_change", -+ self->cancellable, -+ KIOSK_OBJECT_CALLBACK (process_x_keyboard_manager_layouts_change), -+ NULL); -+} -+ -+static void +kiosk_input_source_manager_start_x_keyboard_manager (KioskInputSourcesManager *self) +{ -+ if (meta_is_wayland_compositor ()) { -+ return; -+ } -+ ++ g_debug ("KioskInputSourcesManager: Starting X Keyboard Manager"); + self->x_keyboard_manager = kiosk_x_keyboard_manager_new (self->compositor); ++ + g_signal_connect_object (G_OBJECT (self->x_keyboard_manager), + "notify::selected-layout", + G_CALLBACK (on_x_keyboard_manager_selected_layout_changed), @@ -492,7 +692,7 @@ index 4b4ef62..c6c8c91 100644 G_CALLBACK (on_dbus_service_handle_select_input_source), self, G_CONNECT_SWAPPED); -@@ -1430,63 +1564,71 @@ kiosk_input_sources_manager_handle_dbus_service (KioskInputSourcesManager *self) +@@ -1407,63 +1535,78 @@ kiosk_input_sources_manager_handle_dbus_service (KioskInputSourcesManager *self) G_CALLBACK (on_dbus_service_handle_select_previous_input_source), self, G_CONNECT_SWAPPED); @@ -524,11 +724,19 @@ index 4b4ef62..c6c8c91 100644 kiosk_input_sources_manager_set_input_sources_from_session_configuration (self); + -+ kiosk_gobject_utils_queue_defer_callback (G_OBJECT (self), -+ "[kiosk-input-sources-manager] kiosk_input_source_manager_start_x_keyboard_manager", -+ self->cancellable, -+ KIOSK_OBJECT_CALLBACK (kiosk_input_source_manager_start_x_keyboard_manager ), -+ NULL); ++ /* We start the X keyboard manager after we've already loaded and locked in ++ * GSettings etc, so the session settings take precedence over xorg.conf ++ */ ++ if (!meta_is_wayland_compositor ()) { ++ g_debug ("KioskInputSourcesManager: Will start X keyboard manager shortly"); ++ kiosk_gobject_utils_queue_defer_callback (G_OBJECT (self), ++ "[kiosk-input-sources-manager] kiosk_input_source_manager_start_x_keyboard_manager", ++ self->cancellable, ++ KIOSK_OBJECT_CALLBACK (kiosk_input_source_manager_start_x_keyboard_manager), ++ NULL); ++ } else { ++ g_debug ("KioskInputSourcesManager: Won't start X keyboard manager on wayland"); ++ } } static void @@ -558,18 +766,59 @@ index 4b4ef62..c6c8c91 100644 kiosk_input_sources_manager_remove_key_bindings (self); g_clear_weak_pointer (&self->dbus_service); g_clear_weak_pointer (&self->dbus_object_manager); -+ g_clear_weak_pointer (&self->display); g_clear_weak_pointer (&self->compositor); G_OBJECT_CLASS (kiosk_input_sources_manager_parent_class)->dispose (object); } +diff --git a/compositor/kiosk-input-sources-manager.h b/compositor/kiosk-input-sources-manager.h +index 0b1a738..8a44c3a 100644 +--- a/compositor/kiosk-input-sources-manager.h ++++ b/compositor/kiosk-input-sources-manager.h +@@ -1,35 +1,37 @@ + #pragma once + + #include + + #include "kiosk-input-source-group.h" + #include "kiosk-input-engine-manager.h" ++#include "kiosk-x-keyboard-manager.h" + + typedef struct _KioskCompositor KioskCompositor; + + G_BEGIN_DECLS + + #define KIOSK_TYPE_INPUT_SOURCES_MANAGER (kiosk_input_sources_manager_get_type ()) + + G_DECLARE_FINAL_TYPE (KioskInputSourcesManager, + kiosk_input_sources_manager, + KIOSK, INPUT_SOURCES_MANAGER, + GObject) + + KioskInputSourcesManager *kiosk_input_sources_manager_new (KioskCompositor *compositor); + KioskInputEngineManager *kiosk_input_sources_manager_get_input_engine_manager (KioskInputSourcesManager *manager); ++KioskXKeyboardManager *kiosk_input_sources_manager_get_x_keyboard_manager (KioskInputSourcesManager *manager); + + void kiosk_input_sources_manager_clear_input_sources (KioskInputSourcesManager *self); + gboolean kiosk_input_sources_manager_set_input_sources_from_locales (KioskInputSourcesManager *self, + const char * const *locales, + const char *options); + gboolean kiosk_input_sources_manager_set_input_sources_from_session_configuration (KioskInputSourcesManager *manager); + + void kiosk_input_sources_manager_add_layout (KioskInputSourcesManager *self, + const char *layout, + const char *options); + void kiosk_input_sources_manager_add_input_engine (KioskInputSourcesManager *self, + const char *engine_name, + const char *options); + + G_END_DECLS diff --git a/compositor/kiosk-x-keyboard-manager.c b/compositor/kiosk-x-keyboard-manager.c new file mode 100644 -index 0000000..d5c64fb +index 0000000..ad18d39 --- /dev/null +++ b/compositor/kiosk-x-keyboard-manager.c -@@ -0,0 +1,579 @@ +@@ -0,0 +1,565 @@ +#include "config.h" +#include "kiosk-x-keyboard-manager.h" + @@ -597,7 +846,6 @@ index 0000000..d5c64fb + KioskCompositor *compositor; + MetaBackend *backend; + MetaDisplay *display; -+ MetaX11Display *x11_display; + Display *x_server_display; + + /* strong references */ @@ -612,10 +860,10 @@ index 0000000..d5c64fb + int xkb_event_base; + + size_t layout_index; ++ ssize_t pending_layout_index; + + /* flags */ -+ guint32 watching_x_server_root_window : 1; -+ guint32 disallow_layout_selection: 1; ++ guint32 xkb_rules_names_data_changed: 1; +}; + +enum @@ -775,18 +1023,6 @@ index 0000000..d5c64fb +} + +static void -+kiosk_x_keyboard_manager_disallow_layout_selection (KioskXKeyboardManager *self) -+{ -+ self->disallow_layout_selection = TRUE; -+} -+ -+static void -+kiosk_x_keyboard_manager_allow_layout_selection (KioskXKeyboardManager *self) -+{ -+ self->disallow_layout_selection = FALSE; -+} -+ -+static void +kiosk_x_keyboard_manager_set_layout_index (KioskXKeyboardManager *self, + size_t layout_index) +{ @@ -809,23 +1045,21 @@ index 0000000..d5c64fb + g_object_notify (G_OBJECT (self), "selected-layout"); +} + -+static void ++static gboolean +kiosk_x_keyboard_manager_read_current_layout_index (KioskXKeyboardManager *self) +{ + XkbStateRec xkb_state = { 0 }; + int status; + -+ meta_x11_error_trap_push (self->x11_display); + status = XkbGetState (self->x_server_display, XkbUseCoreKbd, &xkb_state); -+ meta_x11_error_trap_pop (self->x11_display); + + if (status != Success) { + g_debug ("KioskXKeyboardManager: Could not read current layout index"); -+ return; ++ return FALSE; + } -+ g_debug ("KioskXKeyboardManager: Current layout index: %u", xkb_state.locked_group); + + kiosk_x_keyboard_manager_set_layout_index (self, xkb_state.locked_group); ++ return FALSE; +} + +static gboolean @@ -855,7 +1089,7 @@ index 0000000..d5c64fb + OPTIONS + } property_value_index; + -+ kiosk_x_keyboard_manager_allow_layout_selection (self); ++ self->xkb_rules_names_data_changed = TRUE; + + g_debug ("KioskXKeyboardManager: Reading active keyboard layouts from X server"); + @@ -886,14 +1120,6 @@ index 0000000..d5c64fb + (GDestroyNotify) XFree, + NULL); + -+ if (self->xkb_rules_names_data != NULL && g_bytes_equal (self->xkb_rules_names_data, new_xkb_rules_names_data)) { -+ g_debug ("KioskXKeyboardManager: XKB rules names data is unchanged"); -+ return FALSE; -+ } -+ -+ g_clear_pointer (&self->xkb_rules_names_data, g_bytes_unref); -+ self->xkb_rules_names_data = g_steal_pointer (&new_xkb_rules_names_data); -+ + property_value_index = 0; + for (i = 0; i < number_of_bytes_read; i++) { + g_autofree char *value = g_strdup ((char *) property_values + i); @@ -912,8 +1138,8 @@ index 0000000..d5c64fb + g_debug ("KioskXKeyboardManager: Read variants '%s'", variants_string); + break; + case OPTIONS: -+ g_debug ("KioskXKeyboardManager: Read options '%s'", options); + options = g_steal_pointer (&value); ++ g_debug ("KioskXKeyboardManager: Read options '%s'", options); + break; + } + @@ -921,6 +1147,14 @@ index 0000000..d5c64fb + property_value_index++; + } + ++ if (self->xkb_rules_names_data != NULL && g_bytes_equal (self->xkb_rules_names_data, new_xkb_rules_names_data)) { ++ g_debug ("KioskXKeyboardManager: XKB rules names data is unchanged"); ++ return FALSE; ++ } ++ ++ g_clear_pointer (&self->xkb_rules_names_data, g_bytes_unref); ++ self->xkb_rules_names_data = g_steal_pointer (&new_xkb_rules_names_data); ++ + layouts = g_strsplit (layouts_string, ",", -1); + variants = g_strsplit (variants_string, ",", -1); + @@ -951,32 +1185,22 @@ index 0000000..d5c64fb +} + +static void -+on_x_server_xkb_rules_names_data_changed (KioskXKeyboardManager *self) -+{ -+ g_debug ("KioskXKeyboardManager: X server keyboard layouts changed"); -+ -+ kiosk_x_keyboard_manager_read_xkb_rules_names_data (self); -+} -+ -+static void -+monitor_x_server_display_for_property_changes (KioskXKeyboardManager *self, -+ Display *x_server_display) ++monitor_x_server_display_for_changes (KioskXKeyboardManager *self) +{ ++ int major = XkbMajorVersion; ++ int minor = XkbMinorVersion; + XWindowAttributes attributes; + -+ if (self->watching_x_server_root_window) { -+ return; -+ } -+ -+ XGetWindowAttributes (x_server_display, self->x_server_root_window, &attributes); ++ XGetWindowAttributes (self->x_server_display, self->x_server_root_window, &attributes); + + if (!(attributes.your_event_mask & PropertyChangeMask)) { -+ XSelectInput (x_server_display, ++ XSelectInput (self->x_server_display, + self->x_server_root_window, + attributes.your_event_mask | PropertyChangeMask); + } + -+ self->watching_x_server_root_window = TRUE; ++ XkbQueryExtension (self->x_server_display, NULL, &self->xkb_event_base, NULL, &major, &minor); ++ self->xkb_rules_names_atom = XInternAtom (self->x_server_display, "_XKB_RULES_NAMES", False); +} + +static void @@ -991,17 +1215,8 @@ index 0000000..d5c64fb + return; + } + -+ g_debug ("KioskXKeyboardManager: XKB rules names data changed in X server"); -+ -+ /* We block layout index changes until we have a chance to figure out what the new layouts are -+ */ -+ kiosk_x_keyboard_manager_disallow_layout_selection (self); -+ -+ kiosk_gobject_utils_queue_defer_callback (G_OBJECT (self), -+ "[kiosk-input-sources-manager] on_x_server_xkb_rules_names_data_changed", -+ self->cancellable, -+ KIOSK_OBJECT_CALLBACK (on_x_server_xkb_rules_names_data_changed), -+ NULL); ++ g_debug ("KioskXKeyboardManager: XKB rules names property changed in X server"); ++ kiosk_x_keyboard_manager_read_xkb_rules_names_data (self); +} + +static void @@ -1016,12 +1231,19 @@ index 0000000..d5c64fb + if (!(x_server_event->state.changed & XkbGroupStateMask)) { + return; + } -+ if (self->disallow_layout_selection) { -+ g_debug ("KioskXKeyboardManager: Ignoring layout change request to group %lu", layout_index); ++ ++ /* Mutter immediately reverts all layout changes coming from ++ * the outside, so we hide the event from it. ++ */ ++ x_server_event->state.changed &= ~XkbGroupLockMask; ++ ++ if (self->xkb_rules_names_data_changed) { ++ g_debug ("KioskXKeyboardManager: Ignoring spurious group change following layout change"); ++ self->xkb_rules_names_data_changed = FALSE; + return; ++ + } + g_debug ("KioskXKeyboardManager: Approving keyboard group change to group %lu", layout_index); -+ meta_backend_lock_layout_group (self->backend, layout_index); + kiosk_x_keyboard_manager_set_layout_index (self, layout_index); + break; + } @@ -1031,7 +1253,12 @@ index 0000000..d5c64fb +on_x_server_event (KioskXKeyboardManager *self, + XEvent *x_server_event) +{ -+ monitor_x_server_display_for_property_changes (self, x_server_event->xany.display); ++ ++ if (self->x_server_display == NULL) { ++ self->x_server_display = x_server_event->xany.display; ++ self->x_server_root_window = DefaultRootWindow (self->x_server_display); ++ monitor_x_server_display_for_changes (self); ++ } + + switch (x_server_event->type) { + case PropertyNotify: @@ -1062,6 +1289,8 @@ index 0000000..d5c64fb + return NULL; + } + ++ g_debug ("KioskXKeyboardManager: Selected layout is '%s'", self->layouts[self->layout_index]); ++ + return self->layouts[self->layout_index]; +} + @@ -1073,20 +1302,41 @@ index 0000000..d5c64fb + return self->options; +} + -+static void -+kiosk_x_keyboard_manager_init (KioskXKeyboardManager *self) ++gboolean ++kiosk_x_keyboard_manager_keymap_is_active (KioskXKeyboardManager *self, ++ const char * const *layouts, ++ const char * const *variants, ++ const char *options) +{ ++ g_auto (GStrv) qualified_layouts = NULL; ++ ++ if (g_strcmp0 (options, self->options) != 0) { ++ return FALSE; ++ } ++ ++ qualified_layouts = qualify_layouts_with_variants (self, layouts, variants); ++ ++ if (qualified_layouts == NULL) { ++ return FALSE; ++ } ++ ++ if (!g_strv_equal ((const char * const *) qualified_layouts, (const char * const *) self->layouts)) { ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++kiosk_x_keyboard_manager_layout_group_is_locked (KioskXKeyboardManager *self, ++ xkb_layout_index_t layout_index) ++{ ++ return self->layout_index == layout_index; +} + +static void -+kiosk_x_keyboard_manager_initialize_xkb_extension (KioskXKeyboardManager *self) ++kiosk_x_keyboard_manager_init (KioskXKeyboardManager *self) +{ -+ int major = XkbMajorVersion; -+ int minor = XkbMinorVersion; -+ -+ XkbQueryExtension (self->x_server_display, NULL, &self->xkb_event_base, NULL, &major, &minor); -+ -+ self->xkb_rules_names_atom = XInternAtom (self->x_server_display, "_XKB_RULES_NAMES", False); +} + +static void @@ -1102,15 +1352,8 @@ index 0000000..d5c64fb + + g_set_weak_pointer (&self->backend, meta_get_backend ()); + g_set_weak_pointer (&self->display, meta_plugin_get_display (META_PLUGIN (self->compositor))); -+ g_set_weak_pointer (&self->x11_display, meta_display_get_x11_display (self->display)); + -+ self->x_server_display = meta_x11_display_get_xdisplay (self->x11_display); -+ g_object_add_weak_pointer (G_OBJECT (self->x11_display), (gpointer *) &self->x_server_display); -+ -+ self->x_server_root_window = meta_x11_display_get_xroot (self->x11_display); -+ g_object_add_weak_pointer (G_OBJECT (self->x11_display), (gpointer *) &self->x_server_root_window); -+ -+ kiosk_x_keyboard_manager_initialize_xkb_extension (self); ++ self->pending_layout_index = -1; + + g_signal_connect_object (G_OBJECT (self->compositor), + "x-server-event", @@ -1135,14 +1378,6 @@ index 0000000..d5c64fb + g_clear_pointer (&self->layouts, g_strfreev); + g_clear_pointer (&self->options, g_free); + -+ if (self->x11_display != NULL) { -+ g_object_remove_weak_pointer (G_OBJECT (self->x11_display), -+ (gpointer *) &self->x_server_display); -+ g_object_remove_weak_pointer (G_OBJECT (self->x11_display), -+ (gpointer *) &self->x_server_root_window); -+ } -+ g_clear_weak_pointer (&self->x11_display); -+ + g_clear_weak_pointer (&self->display); + g_clear_weak_pointer (&self->backend); + g_clear_weak_pointer (&self->compositor); @@ -1151,13 +1386,14 @@ index 0000000..d5c64fb +} diff --git a/compositor/kiosk-x-keyboard-manager.h b/compositor/kiosk-x-keyboard-manager.h new file mode 100644 -index 0000000..b402465 +index 0000000..bae498f --- /dev/null +++ b/compositor/kiosk-x-keyboard-manager.h -@@ -0,0 +1,22 @@ +@@ -0,0 +1,29 @@ +#pragma once + +#include ++#include + +typedef struct _KioskCompositor KioskCompositor; + @@ -1175,6 +1411,12 @@ index 0000000..b402465 +const char * const *kiosk_x_keyboard_manager_get_layouts (KioskXKeyboardManager *manager); +const char *kiosk_x_keyboard_manager_get_selected_layout (KioskXKeyboardManager *manager); +const char *kiosk_x_keyboard_manager_get_options (KioskXKeyboardManager *manager); ++gboolean kiosk_x_keyboard_manager_keymap_is_active (KioskXKeyboardManager *manager, ++ const char * const *layouts, ++ const char * const *variants, ++ const char *options); ++gboolean kiosk_x_keyboard_manager_layout_group_is_locked (KioskXKeyboardManager *manager, ++ xkb_layout_index_t layout_index); + +G_END_DECLS diff --git a/meson.build b/meson.build @@ -1244,5 +1486,5 @@ index 2b5640a..44afcea 100644 type: 'desktop' ) -- -2.31.1 +2.30.2 diff --git a/gnome-kiosk.spec b/gnome-kiosk.spec index 4101f5b..9fc9613 100644 --- a/gnome-kiosk.spec +++ b/gnome-kiosk.spec @@ -12,7 +12,7 @@ Name: gnome-kiosk Version: 40~alpha -Release: 4%{?dist} +Release: 5%{?dist} Summary: Window management and application launching for GNOME License: GPLv2+ @@ -41,10 +41,10 @@ Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas Patch10001: 0001-compositor-Be-less-aggressive-about-full-screening-w.patch # https://gitlab.gnome.org/halfline/gnome-kiosk/-/merge_requests/2 -Patch20001: 0001-compositor-Add-signal-for-reporting-X-server-events.patch +Patch20001: 0001-gobject-utils-Log-when-executing-deferred-tasks.patch Patch20002: 0002-input-sources-manager-Fix-overzealous-rename-mistake.patch -Patch20003: 0003-input-sources-manager-Add-function-to-load-input-sou.patch -Patch20004: 0004-wip-Better-support-libxklavier.patch +Patch20003: 0003-compositor-Add-signal-for-reporting-X-server-events.patch +Patch20004: 0004-input-sources-manager-Support-libxklavier-managed-ke.patch %description GNOME Kiosk provides a desktop enviroment suitable for fixed purpose, or @@ -88,6 +88,9 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Kiosk.Searc %{_datadir}/wayland-sessions/org.gnome.Kiosk.SearchApp.Session.desktop %changelog +* Wed Apr 21 2021 Ray Strode - 40~alpha-5 +- Fix keyboard layouts getting out of sync in anaconda + * Tue Apr 20 2021 Ray Strode - 40~alpha-4 - Fix infinite loop