From 599435da066ea8676b5874b8e091ee611b414d58 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 17 May 2021 17:02:58 -0400 Subject: [PATCH] Update to 40.0 Related: #1950042 --- .gitignore | 1 + 0001-Make-the-desktop-file-valid.patch | 32 - ...ss-aggressive-about-full-screening-w.patch | 228 --- ...t-the-on-top-windows-actually-on-top.patch | 82 - ...ls-Log-when-executing-deferred-tasks.patch | 116 -- ...nager-Fail-better-if-localed-isn-t-a.patch | 109 -- ...nager-Fix-overzealous-rename-mistake.patch | 188 --- ...signal-for-reporting-X-server-events.patch | 229 --- ...nager-Support-libxklavier-managed-ke.patch | 1490 ----------------- gnome-kiosk.spec | 26 +- sources | 2 +- 11 files changed, 8 insertions(+), 2495 deletions(-) delete mode 100644 0001-Make-the-desktop-file-valid.patch delete mode 100644 0001-compositor-Be-less-aggressive-about-full-screening-w.patch delete mode 100644 0001-compositor-Put-the-on-top-windows-actually-on-top.patch delete mode 100644 0001-gobject-utils-Log-when-executing-deferred-tasks.patch delete mode 100644 0001-input-sources-manager-Fail-better-if-localed-isn-t-a.patch delete mode 100644 0002-input-sources-manager-Fix-overzealous-rename-mistake.patch delete mode 100644 0003-compositor-Add-signal-for-reporting-X-server-events.patch delete mode 100644 0004-input-sources-manager-Support-libxklavier-managed-ke.patch diff --git a/.gitignore b/.gitignore index dc3de33..058bf2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /gnome-kiosk-40.alpha.tar.xz +/gnome-kiosk-40.0.tar.xz diff --git a/0001-Make-the-desktop-file-valid.patch b/0001-Make-the-desktop-file-valid.patch deleted file mode 100644 index 42386d7..0000000 --- a/0001-Make-the-desktop-file-valid.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 342cc4adec33571e6e0d786a297f0034161dc6ee Mon Sep 17 00:00:00 2001 -From: Matthias Clasen -Date: Tue, 27 Apr 2021 16:07:13 -0400 -Subject: [PATCH] Make the desktop file valid - -desktop-file-validate was complaining about the -lack of a main category in the Categories value. -So add one. ---- - compositor/data/org.gnome.Kiosk.desktop.in.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/compositor/data/org.gnome.Kiosk.desktop.in.in b/compositor/data/org.gnome.Kiosk.desktop.in.in -index bf6ec39..bb603c8 100644 ---- a/compositor/data/org.gnome.Kiosk.desktop.in.in -+++ b/compositor/data/org.gnome.Kiosk.desktop.in.in -@@ -1,12 +1,12 @@ - [Desktop Entry] - Type=Application - Name=GNOME Kiosk - Comment=Compositor for Kiosk and Single Application deployments - Exec=@bindir@/gnome-kiosk --Categories=GNOME;GTK;Core; -+Categories=GNOME;GTK;Core;System; - OnlyShowIn=GNOME; - NoDisplay=true - X-GNOME-Autostart-Phase=DisplayServer - X-GNOME-Provides=panel;windowmanager; - X-GNOME-Autostart-Notify=true - X-GNOME-AutoRestart=false --- -2.31.1 diff --git a/0001-compositor-Be-less-aggressive-about-full-screening-w.patch b/0001-compositor-Be-less-aggressive-about-full-screening-w.patch deleted file mode 100644 index 9c5c3a6..0000000 --- a/0001-compositor-Be-less-aggressive-about-full-screening-w.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 7ea1746494f0b2e381fe8f08249f7751cd8ae578 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 15 Apr 2021 13:00:16 -0400 -Subject: [PATCH] compositor: Be less aggressive about full screening windows - -It's common for kiosk type applications to have dialogs and utility -windows that shouldn't get fullscreen. - -This commit tries to be a little less aggressive above fullscreening -windows. Now we assume only the first window is "the application" and -subsequent windows are auxillary and should be layered on top. ---- - compositor/kiosk-compositor.c | 78 +++++++++++++++++++++++++++++++---- - 1 file changed, 70 insertions(+), 8 deletions(-) - -diff --git a/compositor/kiosk-compositor.c b/compositor/kiosk-compositor.c -index b3cd10f..dad7776 100644 ---- a/compositor/kiosk-compositor.c -+++ b/compositor/kiosk-compositor.c -@@ -1,43 +1,45 @@ - #include "config.h" - #include "kiosk-compositor.h" - - #include - #include - - #include - - #include - #include -+#include - #include - #include - #include -+#include - - #include "kiosk-backgrounds.h" - #include "kiosk-input-sources-manager.h" - #include "kiosk-service.h" - - #include "org.gnome.DisplayManager.Manager.h" - - struct _KioskCompositor - { - MetaPlugin parent; - - /* weak references */ - MetaDisplay *display; - ClutterBackend *backend; - ClutterActor *stage; - - /* strong references */ - GCancellable *cancellable; - KioskBackgrounds *backgrounds; - KioskInputSourcesManager *input_sources_manager; - KioskService *service; - }; - - G_DEFINE_TYPE (KioskCompositor, kiosk_compositor, META_TYPE_PLUGIN) - - static void kiosk_compositor_dispose (GObject *object); - - static void - kiosk_compositor_dispose (GObject *object) - { -@@ -143,91 +145,151 @@ static void - kiosk_compositor_minimize (MetaPlugin *plugin, - MetaWindowActor *actor) - { - meta_plugin_minimize_completed (plugin, actor); - } - - static void - kiosk_compositor_unminimize (MetaPlugin *plugin, - MetaWindowActor *actor) - { - meta_plugin_unminimize_completed (plugin, actor); - } - - static void - kiosk_compositor_size_changed (MetaPlugin *plugin, - MetaWindowActor *actor) - { - g_assert (META_PLUGIN_CLASS (kiosk_compositor_parent_class)->size_changed == NULL); - } - - static void - kiosk_compositor_size_change (MetaPlugin *plugin, - MetaWindowActor *actor, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect) - { - g_assert (META_PLUGIN_CLASS (kiosk_compositor_parent_class)->size_change == NULL); - } - -+static gboolean -+kiosk_compositor_wants_window_fullscreen (KioskCompositor *self, -+ MetaWindow *window) -+{ -+ MetaWindowType window_type; -+ g_autoptr (GList) windows = NULL; -+ GList *node; -+ -+ if (!meta_window_allows_resize (window)) { -+ g_debug ("KioskCompositor: Window does not allow resizes"); -+ return FALSE; -+ } -+ -+ if (meta_window_is_override_redirect (window)) { -+ g_debug ("KioskCompositor: Window is override redirect"); -+ return FALSE; -+ } -+ -+ window_type = meta_window_get_window_type (window); -+ -+ if (window_type != META_WINDOW_NORMAL) { -+ g_debug ("KioskCompositor: Window is not normal"); -+ return FALSE; -+ } -+ -+ windows = meta_display_get_tab_list (self->display, META_TAB_LIST_NORMAL_ALL, NULL); -+ -+ for (node = windows; node != NULL; node = node->next) { -+ MetaWindow *existing_window = node->data; -+ -+ if (meta_window_is_fullscreen (existing_window)) { -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+static gboolean -+kiosk_compositor_wants_window_above (KioskCompositor *self, -+ MetaWindow *window) -+{ -+ if (meta_window_is_screen_sized (window)) { -+ return FALSE; -+ } -+ -+ if (meta_window_is_monitor_sized (window)) { -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ - static void - on_faded_in (KioskCompositor *self, - ClutterTransition *transition) - { - MetaWindowActor *actor = g_object_get_data (G_OBJECT (transition), "actor"); -- MetaWindow *window; -- -- window = meta_window_actor_get_meta_window (actor); -- -- if (!meta_window_allows_resize (window) && !meta_window_is_override_redirect (window)) { -- meta_window_make_above (window); -- } - - meta_plugin_map_completed (META_PLUGIN (self), actor); - } - - static void - kiosk_compositor_map (MetaPlugin *plugin, - MetaWindowActor *actor) - { - KioskCompositor *self = KIOSK_COMPOSITOR (plugin); - MetaWindow *window; - ClutterTransition *fade_in_transition; - int easing_duration; - - window = meta_window_actor_get_meta_window (actor); - -- if (meta_window_allows_resize (window)) { -+ if (kiosk_compositor_wants_window_fullscreen (self, window)) { -+ g_debug ("KioskCompositor: Mapping window that does need to be fullscreened"); - meta_window_make_fullscreen (window); - easing_duration = 3000; - } else { -+ ClutterActor *window_group; -+ -+ g_debug ("KioskCompositor: Mapping window that does not need to be fullscreened"); -+ window_group = meta_get_top_window_group_for_display (self->display); -+ -+ if (kiosk_compositor_wants_window_above (self, window)) { -+ g_object_ref (G_OBJECT (actor)); -+ clutter_actor_remove_child (clutter_actor_get_parent (CLUTTER_ACTOR (actor)), CLUTTER_ACTOR (actor)); -+ clutter_actor_add_child (window_group, CLUTTER_ACTOR (actor)); -+ clutter_actor_set_child_below_sibling (window_group, CLUTTER_ACTOR (actor), NULL); -+ g_object_unref (G_OBJECT (actor)); -+ } -+ - easing_duration = 500; - } - - clutter_actor_show (self->stage); - clutter_actor_show (CLUTTER_ACTOR (actor)); - - clutter_actor_set_opacity (CLUTTER_ACTOR (actor), 0); - - clutter_actor_save_easing_state (CLUTTER_ACTOR (actor)); - clutter_actor_set_easing_duration (CLUTTER_ACTOR (actor), easing_duration); - clutter_actor_set_easing_mode (CLUTTER_ACTOR (actor), CLUTTER_EASE_IN_OUT_QUINT); - clutter_actor_set_opacity (CLUTTER_ACTOR (actor), 255); - fade_in_transition = clutter_actor_get_transition (CLUTTER_ACTOR (actor), "opacity"); - clutter_actor_restore_easing_state (CLUTTER_ACTOR (actor)); - - g_object_set_data (G_OBJECT (fade_in_transition), "actor", actor); - - g_signal_connect_object (G_OBJECT (fade_in_transition), - "completed", - G_CALLBACK (on_faded_in), - self, - G_CONNECT_SWAPPED); - } - - static void - kiosk_compositor_destroy (MetaPlugin *plugin, - MetaWindowActor *actor) - { - KioskCompositor *self = KIOSK_COMPOSITOR (plugin); - --- -2.31.1 - diff --git a/0001-compositor-Put-the-on-top-windows-actually-on-top.patch b/0001-compositor-Put-the-on-top-windows-actually-on-top.patch deleted file mode 100644 index 7fb63e0..0000000 --- a/0001-compositor-Put-the-on-top-windows-actually-on-top.patch +++ /dev/null @@ -1,82 +0,0 @@ -From ed8dbeb00ef64faa047652ac7fc9bf029348a6df Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 6 May 2021 14:17:26 -0400 -Subject: [PATCH] compositor: Put the on top windows actually on top - -A typo in the code left me putting new windows under old ones. - -This commit fixes that. ---- - compositor/kiosk-compositor.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/compositor/kiosk-compositor.c b/compositor/kiosk-compositor.c -index 14f5de3..6753a87 100644 ---- a/compositor/kiosk-compositor.c -+++ b/compositor/kiosk-compositor.c -@@ -239,61 +239,61 @@ on_faded_in (KioskCompositor *self, - MetaWindowActor *actor = g_object_get_data (G_OBJECT (transition), "actor"); - - meta_plugin_map_completed (META_PLUGIN (self), actor); - } - - static void - kiosk_compositor_map (MetaPlugin *plugin, - MetaWindowActor *actor) - { - KioskCompositor *self = KIOSK_COMPOSITOR (plugin); - MetaWindow *window; - ClutterTransition *fade_in_transition; - int easing_duration; - - window = meta_window_actor_get_meta_window (actor); - - if (kiosk_compositor_wants_window_fullscreen (self, window)) { - g_debug ("KioskCompositor: Mapping window that does need to be fullscreened"); - meta_window_make_fullscreen (window); - easing_duration = 3000; - } else { - ClutterActor *window_group; - - g_debug ("KioskCompositor: Mapping window that does not need to be fullscreened"); - window_group = meta_get_top_window_group_for_display (self->display); - - if (kiosk_compositor_wants_window_above (self, window)) { - g_object_ref (G_OBJECT (actor)); - clutter_actor_remove_child (clutter_actor_get_parent (CLUTTER_ACTOR (actor)), CLUTTER_ACTOR (actor)); - clutter_actor_add_child (window_group, CLUTTER_ACTOR (actor)); -- clutter_actor_set_child_below_sibling (window_group, CLUTTER_ACTOR (actor), NULL); -+ clutter_actor_set_child_above_sibling (window_group, CLUTTER_ACTOR (actor), NULL); - g_object_unref (G_OBJECT (actor)); - } - - easing_duration = 500; - } - - clutter_actor_show (self->stage); - clutter_actor_show (CLUTTER_ACTOR (actor)); - - clutter_actor_set_opacity (CLUTTER_ACTOR (actor), 0); - - clutter_actor_save_easing_state (CLUTTER_ACTOR (actor)); - clutter_actor_set_easing_duration (CLUTTER_ACTOR (actor), easing_duration); - clutter_actor_set_easing_mode (CLUTTER_ACTOR (actor), CLUTTER_EASE_IN_OUT_QUINT); - clutter_actor_set_opacity (CLUTTER_ACTOR (actor), 255); - fade_in_transition = clutter_actor_get_transition (CLUTTER_ACTOR (actor), "opacity"); - clutter_actor_restore_easing_state (CLUTTER_ACTOR (actor)); - - g_object_set_data (G_OBJECT (fade_in_transition), "actor", actor); - - g_signal_connect_object (G_OBJECT (fade_in_transition), - "completed", - G_CALLBACK (on_faded_in), - self, - G_CONNECT_SWAPPED); - } - - static void - kiosk_compositor_destroy (MetaPlugin *plugin, - MetaWindowActor *actor) --- -2.31.1 - diff --git a/0001-gobject-utils-Log-when-executing-deferred-tasks.patch b/0001-gobject-utils-Log-when-executing-deferred-tasks.patch deleted file mode 100644 index a83c690..0000000 --- a/0001-gobject-utils-Log-when-executing-deferred-tasks.patch +++ /dev/null @@ -1,116 +0,0 @@ -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/0001-input-sources-manager-Fail-better-if-localed-isn-t-a.patch b/0001-input-sources-manager-Fail-better-if-localed-isn-t-a.patch deleted file mode 100644 index 0259717..0000000 --- a/0001-input-sources-manager-Fail-better-if-localed-isn-t-a.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 89b5facb7545c0423673c500343794a6c07fabfe Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 12 May 2021 15:19:26 -0400 -Subject: [PATCH] input-sources-manager: Fail better if localed isn't available - -At the moment we assumed the localed proxy will always return valid -strings. If localed exits, though, there's a small window where the -properties can return NULL. - -This commit tries to handle that transient failure better. ---- - compositor/kiosk-input-sources-manager.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/compositor/kiosk-input-sources-manager.c b/compositor/kiosk-input-sources-manager.c -index 7bb67b0..49973db 100644 ---- a/compositor/kiosk-input-sources-manager.c -+++ b/compositor/kiosk-input-sources-manager.c -@@ -807,80 +807,87 @@ kiosk_input_sources_manager_add_layout (KioskInputSourcesManager *self, - 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) - { - KioskInputSourceGroup *old_input_source_group; - g_autofree char *old_input_engine = NULL; - g_autofree char *old_selected_layout = NULL; -+ g_autofree char *localed_name_owner = 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; - - g_return_val_if_fail (KIOSK_IS_INPUT_SOURCES_MANAGER (self), FALSE); - - if (self->locale_proxy == NULL) { - return FALSE; - } - -+ localed_name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (self->locale_proxy)); -+ -+ if (localed_name_owner == 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); - --- -2.31.1 - diff --git a/0002-input-sources-manager-Fix-overzealous-rename-mistake.patch b/0002-input-sources-manager-Fix-overzealous-rename-mistake.patch deleted file mode 100644 index 4eda3ca..0000000 --- a/0002-input-sources-manager-Fix-overzealous-rename-mistake.patch +++ /dev/null @@ -1,188 +0,0 @@ -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 - -At some point during development something called -KioskInputSources got renamed to KioskInputSourceGroup. - -Unfortunately, my sed-fu was weak and I renamed things it shouldn't. - -This commit fixes the errors. ---- - compositor/kiosk-input-sources-manager.c | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/compositor/kiosk-input-sources-manager.c b/compositor/kiosk-input-sources-manager.c -index 58d7a4c..a1a4cfa 100644 ---- a/compositor/kiosk-input-sources-manager.c -+++ b/compositor/kiosk-input-sources-manager.c -@@ -1,60 +1,60 @@ - #include "config.h" - #include "kiosk-input-sources-manager.h" - - #include - #include - - #include - #include - #include - #include - - #include - #include - - #define GNOME_DESKTOP_USE_UNSTABLE_API - #include - #include - - #include "org.freedesktop.locale1.h" - #include "kiosk-compositor.h" - #include "kiosk-dbus-utils.h" - #include "kiosk-gobject-utils.h" - #include "kiosk-input-engine-manager.h" - #include "kiosk-input-source-group.h" - - #define SD_LOCALE1_BUS_NAME "org.freedesktop.locale1" - #define SD_LOCALE1_OBJECT_PATH "/org/freedesktop/locale1" - --#define KIOSK_INPUT_SOURCE_GROUP_SCHEMA "org.gnome.desktop.input-sources" --#define KIOSK_INPUT_SOURCE_GROUP_SETTING "sources" -+#define KIOSK_INPUT_SOURCES_SCHEMA "org.gnome.desktop.input-sources" -+#define KIOSK_INPUT_SOURCES_SETTING "sources" - #define KIOSK_INPUT_OPTIONS_SETTING "xkb-options" - - #define KIOSK_INPUT_SOURCE_OBJECTS_PATH_PREFIX "/org/gnome/Kiosk/InputSources" - #define KIOSK_KEYBINDINGS_SCHEMA "org.gnome.desktop.wm.keybindings" - #define KIOSK_SWITCH_INPUT_SOURCES_KEYBINDING "switch-input-source" - #define KIOSK_SWITCH_INPUT_SOURCES_BACKWARD_KEYBINDING "switch-input-source-backward" - - #define KIOSK_DBUS_INPUT_SOURCES_MANGER_INPUT_SOURCE_INTERFACE "org.gnome.Kiosk.InputSources.InputSource" - - struct _KioskInputSourcesManager - { - GObject parent; - - /* weak references */ - KioskCompositor *compositor; - MetaDisplay *display; - - KioskDBusInputSourcesManager *dbus_service; - GDBusObjectManagerServer *dbus_object_manager; - - /* strong references */ - GCancellable *cancellable; - KioskInputEngineManager *input_engine_manager; - SdLocale1 *locale_proxy; - GnomeXkbInfo *xkb_info; - GSettings *input_sources_settings; - GSettings *key_binding_settings; - GPtrArray *input_source_groups; - - /* state */ -@@ -913,94 +913,94 @@ kiosk_input_sources_manager_set_input_sources_from_system_configuration (KioskIn - - 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); - } - - gboolean - kiosk_input_sources_manager_set_input_sources_from_session_configuration (KioskInputSourcesManager *self) - { -- g_autoptr (GVariant) input_source_group = NULL; -+ g_autoptr (GVariant) input_sources = NULL; - g_auto (GStrv) options = NULL; -- gboolean input_source_group_active; -+ gboolean input_sources_active; - - g_return_val_if_fail (KIOSK_IS_INPUT_SOURCES_MANAGER (self), FALSE); - - g_debug ("KioskInputSourcesManager: Setting input sources from session configuration"); - - self->overriding_configuration = FALSE; - - if (self->input_sources_settings == NULL) { -- self->input_sources_settings = g_settings_new (KIOSK_INPUT_SOURCE_GROUP_SCHEMA); -+ self->input_sources_settings = g_settings_new (KIOSK_INPUT_SOURCES_SCHEMA); - - g_signal_connect_object (G_OBJECT (self->input_sources_settings), -- "changed::" KIOSK_INPUT_SOURCE_GROUP_SETTING, -+ "changed::" KIOSK_INPUT_SOURCES_SETTING, - G_CALLBACK (on_session_input_sources_setting_changed), - self, - G_CONNECT_SWAPPED); - g_signal_connect_object (G_OBJECT (self->input_sources_settings), - "changed::" KIOSK_INPUT_OPTIONS_SETTING, - G_CALLBACK (on_session_input_sources_setting_changed), - self, - G_CONNECT_SWAPPED); - } - - - options = g_settings_get_strv (self->input_sources_settings, KIOSK_INPUT_OPTIONS_SETTING); - -- input_source_group = g_settings_get_value (self->input_sources_settings, -- KIOSK_INPUT_SOURCE_GROUP_SETTING); -+ input_sources = g_settings_get_value (self->input_sources_settings, -+ KIOSK_INPUT_SOURCES_SETTING); - -- input_source_group_active = kiosk_input_sources_manager_set_input_sources (self, input_source_group, (const char * const *) options); -+ input_sources_active = kiosk_input_sources_manager_set_input_sources (self, input_sources, (const char * const *) options); - -- if (!input_source_group_active) { -+ if (!input_sources_active) { - g_debug ("KioskInputSourcesManager: Session has no valid configured input sources"); - return kiosk_input_sources_manager_set_input_sources_from_system_configuration (self); - } - - return TRUE; - } - - gboolean - kiosk_input_sources_manager_set_input_sources_from_locales (KioskInputSourcesManager *self, - const char * const *locales, - const char *options) - { - KioskInputSourceGroup *old_input_source_group; - g_autofree char *old_selected_layout = NULL; - g_autofree char *old_input_engine = NULL; - g_autofree char *locales_string = NULL; - gboolean input_source_group_active; - - g_return_val_if_fail (KIOSK_IS_INPUT_SOURCES_MANAGER (self), FALSE); - g_return_val_if_fail (locales != NULL, FALSE); - - locales_string = g_strjoinv (",", (GStrv) locales); - - g_debug ("KioskInputSourcesManager: Setting keymap from locales '%s'", - locales_string); - - self->overriding_configuration = TRUE; - - old_input_source_group = kiosk_input_sources_manager_get_selected_input_source_group (self); - --- -2.30.2 - diff --git a/0003-compositor-Add-signal-for-reporting-X-server-events.patch b/0003-compositor-Add-signal-for-reporting-X-server-events.patch deleted file mode 100644 index 8a9cb41..0000000 --- a/0003-compositor-Add-signal-for-reporting-X-server-events.patch +++ /dev/null @@ -1,229 +0,0 @@ -From a944f0d27a42028ec18edb17f65957780c400104 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 15 Apr 2021 13:28:00 -0400 -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 -under it. - -As a first step toward fixing that problem, this commit adds a -new signal "x-server-event" to KioskCompositor, so that the -InputSourcesManager can watch for root window property changes. ---- - compositor/kiosk-compositor.c | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/compositor/kiosk-compositor.c b/compositor/kiosk-compositor.c -index dad7776..14f5de3 100644 ---- a/compositor/kiosk-compositor.c -+++ b/compositor/kiosk-compositor.c -@@ -9,60 +9,67 @@ - #include - #include - #include - #include - #include - #include - #include - - #include "kiosk-backgrounds.h" - #include "kiosk-input-sources-manager.h" - #include "kiosk-service.h" - - #include "org.gnome.DisplayManager.Manager.h" - - struct _KioskCompositor - { - MetaPlugin parent; - - /* weak references */ - MetaDisplay *display; - ClutterBackend *backend; - ClutterActor *stage; - - /* strong references */ - GCancellable *cancellable; - KioskBackgrounds *backgrounds; - KioskInputSourcesManager *input_sources_manager; - KioskService *service; - }; - -+enum { -+ X_SERVER_EVENT, -+ NUMBER_OF_SIGNALS -+}; -+ -+static guint signals [NUMBER_OF_SIGNALS] = { 0, }; -+ - G_DEFINE_TYPE (KioskCompositor, kiosk_compositor, META_TYPE_PLUGIN) - - static void kiosk_compositor_dispose (GObject *object); - - static void - kiosk_compositor_dispose (GObject *object) - { - KioskCompositor *self = KIOSK_COMPOSITOR (object); - - if (self->cancellable != NULL) { - g_cancellable_cancel (self->cancellable); - g_clear_object (&self->cancellable); - } - - g_clear_weak_pointer (&self->stage); - g_clear_weak_pointer (&self->display); - g_clear_weak_pointer (&self->backend); - - g_clear_object (&self->backgrounds); - - G_OBJECT_CLASS (kiosk_compositor_parent_class)->dispose (object); - } - - static void - register_with_display_manager (KioskCompositor *self) - { - g_autoptr (GDBusConnection) system_bus = NULL; - g_autoptr (GdmManager) display_manager = NULL; - GVariantBuilder builder; - g_autoptr (GError) error = NULL; -@@ -329,62 +336,64 @@ kiosk_compositor_show_tile_preview (MetaPlugin *plugin, - g_assert (META_PLUGIN_CLASS (kiosk_compositor_parent_class)->show_tile_preview == NULL); - } - - static void - kiosk_compositor_hide_tile_preview (MetaPlugin *plugin) - { - g_assert (META_PLUGIN_CLASS (kiosk_compositor_parent_class)->hide_tile_preview == NULL); - } - - static void - kiosk_compositor_show_window_menu (MetaPlugin *plugin, - MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y) - { - g_assert (META_PLUGIN_CLASS (kiosk_compositor_parent_class)->show_window_menu == NULL); - } - - static void - kiosk_compositor_show_window_menu_for_rect (MetaPlugin *plugin, - MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect) - { - g_assert (META_PLUGIN_CLASS (kiosk_compositor_parent_class)->show_window_menu_for_rect == NULL); - } - - static gboolean - kiosk_compositor_xevent_filter (MetaPlugin *plugin, -- XEvent *xev) -+ XEvent *x_server_event) - { -+ KioskCompositor *self = KIOSK_COMPOSITOR (plugin); -+ g_signal_emit (G_OBJECT (self), signals[X_SERVER_EVENT], 0, x_server_event); - return FALSE; - } - - static gboolean - kiosk_compositor_keybinding_filter (MetaPlugin *plugin, - MetaKeyBinding *binding) - { - return FALSE; - } - - static void - kiosk_compositor_confirm_display_change (MetaPlugin *plugin) - { - KioskCompositor *self = KIOSK_COMPOSITOR (plugin); - - meta_plugin_complete_display_change (META_PLUGIN (self), TRUE); - } - - static const MetaPluginInfo info = { - .name = "GNOME Kiosk", - .version = VERSION, - .author = "Various", - .license = "GPLv2+", - .description = "Provides Kiosk compositor plugin for mutter" - }; - - static const MetaPluginInfo * - kiosk_compositor_plugin_info (MetaPlugin *plugin) - { - -@@ -420,60 +429,71 @@ kiosk_compositor_class_init (KioskCompositorClass *compositor_class) - - plugin_class->start = kiosk_compositor_start; - plugin_class->map = kiosk_compositor_map; - plugin_class->minimize = kiosk_compositor_minimize; - plugin_class->unminimize = kiosk_compositor_unminimize; - plugin_class->size_changed = kiosk_compositor_size_changed; - plugin_class->size_change = kiosk_compositor_size_change; - plugin_class->destroy = kiosk_compositor_destroy; - - plugin_class->switch_workspace = kiosk_compositor_switch_workspace; - - plugin_class->kill_window_effects = kiosk_compositor_kill_window_effects; - plugin_class->kill_switch_workspace = kiosk_compositor_kill_switch_workspace; - - plugin_class->show_tile_preview = kiosk_compositor_show_tile_preview; - plugin_class->hide_tile_preview = kiosk_compositor_hide_tile_preview; - plugin_class->show_window_menu = kiosk_compositor_show_window_menu; - plugin_class->show_window_menu_for_rect = kiosk_compositor_show_window_menu_for_rect; - - plugin_class->xevent_filter = kiosk_compositor_xevent_filter; - plugin_class->keybinding_filter = kiosk_compositor_keybinding_filter; - - plugin_class->confirm_display_change = kiosk_compositor_confirm_display_change; - - plugin_class->plugin_info = kiosk_compositor_plugin_info; - - plugin_class->create_close_dialog = kiosk_compositor_create_close_dialog; - plugin_class->create_inhibit_shortcuts_dialog = kiosk_compositor_create_inhibit_shortcuts_dialog; - - plugin_class->locate_pointer = kiosk_compositor_locate_pointer; -+ -+ signals [X_SERVER_EVENT] = -+ g_signal_new ("x-server-event", -+ G_TYPE_FROM_CLASS (object_class), -+ G_SIGNAL_RUN_LAST, -+ 0, -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__POINTER, -+ G_TYPE_NONE, -+ 1, G_TYPE_POINTER); - } - - static void - kiosk_compositor_init (KioskCompositor *compositor) - { - g_debug ("KioskCompositor: Initializing"); - } - - KioskBackgrounds * - kiosk_compositor_get_backgrounds (KioskCompositor *self) - { - g_return_val_if_fail (KIOSK_IS_COMPOSITOR (self), NULL); - - return KIOSK_BACKGROUNDS (self->backgrounds); - } - - KioskInputSourcesManager * - kiosk_compositor_get_input_sources_manager (KioskCompositor *self) - { - g_return_val_if_fail (KIOSK_IS_COMPOSITOR (self), NULL); - - return KIOSK_INPUT_SOURCES_MANAGER (self->input_sources_manager); - } - - KioskService * - kiosk_compositor_get_service (KioskCompositor *self) - { - g_return_val_if_fail (KIOSK_IS_COMPOSITOR (self), NULL); - - return KIOSK_SERVICE (self->service); --- -2.30.2 - diff --git a/0004-input-sources-manager-Support-libxklavier-managed-ke.patch b/0004-input-sources-manager-Support-libxklavier-managed-ke.patch deleted file mode 100644 index e365d28..0000000 --- a/0004-input-sources-manager-Support-libxklavier-managed-ke.patch +++ /dev/null @@ -1,1490 +0,0 @@ -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] input-sources-manager: Support libxklavier managed - keyboard layouts - -Mutter currently doesn't allow libxklavier to change the layout out from -under it. - -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 | 47 +- - compositor/kiosk-input-source-group.h | 5 +- - 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 + - 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..c33ca05 100644 ---- a/compositor/kiosk-input-source-group.c -+++ b/compositor/kiosk-input-source-group.c -@@ -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); - - g_free (self->input_engine_name); - self->input_engine_name = g_strdup (engine_name); - - g_ptr_array_set_size (self->layouts, 0); - g_ptr_array_set_size (self->variants, 0); - - g_ptr_array_add (self->layouts, NULL); - g_ptr_array_add (self->variants, NULL); - - return TRUE; - } - - const char * - kiosk_input_source_group_get_input_engine (KioskInputSourceGroup *self) - { - return self->input_engine_name; - } - - void - kiosk_input_source_group_set_options (KioskInputSourceGroup *self, - const char *options) - { - g_free (self->options); - self->options = g_strdup (options); - } - -+const char * -+kiosk_input_source_group_get_options (KioskInputSourceGroup *self) -+{ -+ return self->options; -+} -+ - gboolean - kiosk_input_source_group_activate (KioskInputSourceGroup *self) - { - 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"); - - if (self->input_engine_name != NULL) { - kiosk_input_source_group_ensure_layout_for_input_engine (self); - } - - number_of_layouts = kiosk_input_source_group_get_number_of_layouts (self); - - if (number_of_layouts == 0) { - return FALSE; - } - - layouts = g_strjoinv (",", (GStrv) self->layouts->pdata); - variants = g_strjoinv (",", (GStrv) self->variants->pdata); - - if (self->input_engine_name != NULL) { - gboolean activated; - - activated = kiosk_input_engine_manager_activate_engine (self->input_engine_manager, self->input_engine_name); - - if (!activated) { - g_debug ("KioskInputSourceGroup: Could not activate input engine '%s'", self->input_engine_name); - return FALSE; - } - } 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); -+ 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); -+ } -+ -+ 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; - } - - static ssize_t - get_index_of_layout (KioskInputSourceGroup *self, - const char *layout_name) - { - g_auto (GStrv) layouts; - size_t i; - - layouts = kiosk_input_source_group_get_layouts (self); - for (i = 0; layouts[i] != NULL; i++) { - if (g_strcmp0 (layout_name, layouts[i]) == 0) { - return (ssize_t) i; - } - } - - return -1; - } - -+gboolean -+kiosk_input_source_group_only_has_layouts (KioskInputSourceGroup *self, -+ const char * const *layouts_to_check) -+{ -+ g_auto (GStrv) layouts; -+ -+ layouts = kiosk_input_source_group_get_layouts (self); -+ -+ return g_strv_equal (layouts_to_check, (const char * const *) layouts); -+} -+ - gboolean - kiosk_input_source_group_switch_to_layout (KioskInputSourceGroup *self, - const char *layout_name) - { - g_autofree char *active_layout = NULL; - ssize_t layout_index; - - layout_index = get_index_of_layout (self, layout_name); - - if (layout_index < 0) { - return FALSE; - } - - g_debug ("KioskInputSourceGroup: Switching to layout %s", layout_name); - - active_layout = kiosk_input_source_group_get_selected_layout (self); - - self->layout_index = layout_index; - - g_debug ("KioskInputSourceGroup: Switching from layout '%s' to next layout '%s'", - active_layout, layout_name); - - meta_backend_lock_layout_group (meta_get_backend (), self->layout_index); - - return TRUE; - } - - 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 -+++ b/compositor/kiosk-input-source-group.h -@@ -1,38 +1,41 @@ - #pragma once - - #include - - typedef struct _KioskInputSourcesManager KioskInputSourcesManager; - - G_BEGIN_DECLS - - #define KIOSK_TYPE_INPUT_SOURCE_GROUP (kiosk_input_source_group_get_type ()) - - G_DECLARE_FINAL_TYPE (KioskInputSourceGroup, - kiosk_input_source_group, - KIOSK, INPUT_SOURCE_GROUP, - GObject) - - KioskInputSourceGroup *kiosk_input_source_group_new (KioskInputSourcesManager *manager); - gboolean kiosk_input_source_group_add_layout (KioskInputSourceGroup *input_sources, - const char *layout, - const char *variant); - char *kiosk_input_source_group_get_selected_layout (KioskInputSourceGroup *input_sources); - char **kiosk_input_source_group_get_layouts (KioskInputSourceGroup *input_sources); - - gboolean kiosk_input_source_group_set_input_engine (KioskInputSourceGroup *input_sources, - const char *engine_name); - const char *kiosk_input_source_group_get_input_engine (KioskInputSourceGroup *input_sources); - - void kiosk_input_source_group_set_options (KioskInputSourceGroup *input_sources, -- const char *options); -+ const char *options); -+const char *kiosk_input_source_group_get_options (KioskInputSourceGroup *self); - - gboolean kiosk_input_source_group_activate (KioskInputSourceGroup *input_sources); - -+gboolean kiosk_input_source_group_only_has_layouts (KioskInputSourceGroup *self, -+ const char * const *layouts_to_check); - gboolean kiosk_input_source_group_switch_to_layout (KioskInputSourceGroup *input_sources, - const char *layout_name); - void kiosk_input_source_group_switch_to_first_layout (KioskInputSourceGroup *input_sources); - void kiosk_input_source_group_switch_to_last_layout (KioskInputSourceGroup *input_sources); - gboolean kiosk_input_source_group_switch_to_next_layout (KioskInputSourceGroup *input_sources); - 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 a1a4cfa..7bb67b0 100644 ---- a/compositor/kiosk-input-sources-manager.c -+++ b/compositor/kiosk-input-sources-manager.c -@@ -1,83 +1,85 @@ - #include "config.h" - #include "kiosk-input-sources-manager.h" - - #include - #include - - #include - #include - #include - #include - - #include - #include - - #define GNOME_DESKTOP_USE_UNSTABLE_API - #include - #include - - #include "org.freedesktop.locale1.h" - #include "kiosk-compositor.h" - #include "kiosk-dbus-utils.h" - #include "kiosk-gobject-utils.h" - #include "kiosk-input-engine-manager.h" - #include "kiosk-input-source-group.h" -+#include "kiosk-x-keyboard-manager.h" - - #define SD_LOCALE1_BUS_NAME "org.freedesktop.locale1" - #define SD_LOCALE1_OBJECT_PATH "/org/freedesktop/locale1" - - #define KIOSK_INPUT_SOURCES_SCHEMA "org.gnome.desktop.input-sources" - #define KIOSK_INPUT_SOURCES_SETTING "sources" - #define KIOSK_INPUT_OPTIONS_SETTING "xkb-options" - - #define KIOSK_INPUT_SOURCE_OBJECTS_PATH_PREFIX "/org/gnome/Kiosk/InputSources" - #define KIOSK_KEYBINDINGS_SCHEMA "org.gnome.desktop.wm.keybindings" - #define KIOSK_SWITCH_INPUT_SOURCES_KEYBINDING "switch-input-source" - #define KIOSK_SWITCH_INPUT_SOURCES_BACKWARD_KEYBINDING "switch-input-source-backward" - - #define KIOSK_DBUS_INPUT_SOURCES_MANGER_INPUT_SOURCE_INTERFACE "org.gnome.Kiosk.InputSources.InputSource" - - struct _KioskInputSourcesManager - { - GObject parent; - - /* weak references */ - KioskCompositor *compositor; - MetaDisplay *display; - - KioskDBusInputSourcesManager *dbus_service; - GDBusObjectManagerServer *dbus_object_manager; - - /* strong references */ - GCancellable *cancellable; - KioskInputEngineManager *input_engine_manager; -+ KioskXKeyboardManager *x_keyboard_manager; - SdLocale1 *locale_proxy; - GnomeXkbInfo *xkb_info; - GSettings *input_sources_settings; - GSettings *key_binding_settings; - GPtrArray *input_source_groups; - - /* state */ - ssize_t input_source_groups_index; - - /* flags */ - guint32 overriding_configuration : 1; - }; - - enum - { - PROP_COMPOSITOR = 1, - NUMBER_OF_PROPERTIES - }; - static GParamSpec *kiosk_input_sources_manager_properties[NUMBER_OF_PROPERTIES] = { NULL, }; - - G_DEFINE_TYPE (KioskInputSourcesManager, kiosk_input_sources_manager, G_TYPE_OBJECT) - - static void kiosk_input_sources_manager_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *param_spec); - static void kiosk_input_sources_manager_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *param_spec); -@@ -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); - - if (active_input_engine == NULL) { - g_debug ("KioskInputSourcesManager: Input engine deactivated, activating first available input source"); - activate_first_available_input_source_group (self); - return; - } - - activate_input_source_group_with_engine (self, active_input_engine); - } - - static void - kiosk_input_sources_manager_start_input_engine_manager (KioskInputSourcesManager *self) - { - self->input_engine_manager = kiosk_input_engine_manager_new (self); - - g_signal_connect_object (G_OBJECT (self->input_engine_manager), - "notify::is-loaded", - G_CALLBACK (on_input_engine_manager_is_loaded_changed), - self, - G_CONNECT_SWAPPED); - - g_signal_connect_object (G_OBJECT (self->input_engine_manager), - "notify::active-engine", - G_CALLBACK (on_input_engine_manager_active_engine_changed), - self, - G_CONNECT_SWAPPED); - } - -+static void -+process_x_keyboard_manager_selected_layout_change (KioskInputSourcesManager *self) -+{ -+ const char *selected_layout; -+ -+ selected_layout = kiosk_x_keyboard_manager_get_selected_layout (self->x_keyboard_manager); -+ -+ if (selected_layout == NULL) { -+ return; -+ } -+ -+ g_debug ("KioskInputSourcesManager: X server changed active layout to %s", selected_layout); -+ -+ activate_input_source_group_with_layout (self, selected_layout); -+ -+ 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, -+ KIOSK_OBJECT_CALLBACK (process_x_keyboard_manager_selected_layout_change), -+ NULL); -+} -+ -+static gboolean -+layouts_match_selected_input_source_group (KioskInputSourcesManager *self, -+ const char * const *layouts, -+ const char *options) -+{ -+ KioskInputSourceGroup *input_source_group; -+ -+ g_auto (GStrv) current_layouts = NULL; -+ const char *input_source_group_options; -+ const char *input_engine_name; -+ -+ input_source_group = kiosk_input_sources_manager_get_selected_input_source_group (self); -+ -+ if (input_source_group == NULL) { -+ return FALSE; -+ } -+ -+ input_engine_name = kiosk_input_source_group_get_input_engine (input_source_group); -+ -+ if (input_engine_name != NULL) { -+ return FALSE; -+ } -+ -+ current_layouts = kiosk_input_source_group_get_layouts (input_source_group); -+ -+ if (!g_strv_equal ((const char * const *) current_layouts, layouts)) { -+ return FALSE; -+ } -+ -+ input_source_group_options = kiosk_input_source_group_get_options (input_source_group); -+ -+ if (g_strcmp0 (input_source_group_options, options) != 0) { -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+static void -+on_x_keyboard_manager_layouts_changed (KioskInputSourcesManager *self) -+{ -+ const char * const *new_layouts; -+ const char *selected_layout; -+ const char *options; -+ gboolean layouts_match; -+ size_t i; -+ -+ new_layouts = kiosk_x_keyboard_manager_get_layouts (self->x_keyboard_manager); -+ options = kiosk_x_keyboard_manager_get_options (self->x_keyboard_manager); -+ layouts_match = layouts_match_selected_input_source_group (self, new_layouts, options); -+ -+ if (layouts_match) { -+ return; -+ } -+ -+ g_debug ("KioskInputSorcesManager: X server keyboard layouts changed"); -+ -+ self->overriding_configuration = TRUE; -+ kiosk_input_sources_manager_clear_input_sources (self); -+ -+ for (i = 0; new_layouts[i] != NULL; i++) { -+ kiosk_input_sources_manager_add_layout (self, new_layouts[i], options); -+ } -+ -+ selected_layout = kiosk_x_keyboard_manager_get_selected_layout (self->x_keyboard_manager); -+ -+ if (selected_layout != NULL) { -+ activate_best_available_input_source_group (self, NULL, selected_layout); -+ } -+} -+ -+static void -+kiosk_input_source_manager_start_x_keyboard_manager (KioskInputSourcesManager *self) -+{ -+ 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), -+ self, -+ G_CONNECT_SWAPPED); -+ g_signal_connect_object (G_OBJECT (self->x_keyboard_manager), -+ "notify::layouts", -+ G_CALLBACK (on_x_keyboard_manager_layouts_changed), -+ self, -+ G_CONNECT_SWAPPED); -+} -+ - static void - kiosk_input_sources_manager_handle_dbus_service (KioskInputSourcesManager *self) - { - KioskService *service; - - service = kiosk_compositor_get_service (self->compositor); - - g_set_weak_pointer (&self->dbus_service, KIOSK_DBUS_INPUT_SOURCES_MANAGER (kiosk_service_get_input_sources_manager_skeleton (service))); - g_set_weak_pointer (&self->dbus_object_manager, kiosk_service_get_input_sources_object_manager (service)); - - g_signal_connect_object (G_OBJECT (self->dbus_service), - "handle-set-input-sources", - G_CALLBACK (on_dbus_service_handle_set_input_sources), - self, - G_CONNECT_SWAPPED); - g_signal_connect_object (G_OBJECT (self->dbus_service), - "handle-set-input-sources-from-locales", - G_CALLBACK (on_dbus_service_handle_set_input_sources_from_locales), - self, - G_CONNECT_SWAPPED); - g_signal_connect_object (G_OBJECT (self->dbus_service), - "handle-set-input-sources-from-session-configuration", - G_CALLBACK (on_dbus_service_handle_set_input_sources_from_session_configuration), - self, - G_CONNECT_SWAPPED); - g_signal_connect_object (G_OBJECT (self->dbus_service), - "handle-select-input-source", - G_CALLBACK (on_dbus_service_handle_select_input_source), - self, - G_CONNECT_SWAPPED); -@@ -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); - } - - static void - kiosk_input_sources_manager_constructed (GObject *object) - { - KioskInputSourcesManager *self = KIOSK_INPUT_SOURCES_MANAGER (object); - - g_debug ("KioskInputSourcesManager: Initializing"); - - G_OBJECT_CLASS (kiosk_input_sources_manager_parent_class)->constructed (object); - - g_set_weak_pointer (&self->display, meta_plugin_get_display (META_PLUGIN (self->compositor))); - - self->cancellable = g_cancellable_new (); - - self->xkb_info = gnome_xkb_info_new (); - self->input_source_groups = g_ptr_array_new_full (1, g_object_unref); - - kiosk_input_sources_manager_handle_dbus_service (self); - - kiosk_input_sources_manager_start_input_engine_manager (self); - - kiosk_input_sources_manager_connect_to_localed (self); - - kiosk_input_sources_manager_add_key_bindings (self); - - kiosk_input_sources_manager_set_input_sources_from_session_configuration (self); -+ -+ /* 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 - kiosk_input_sources_manager_init (KioskInputSourcesManager *self) - { - } - - static void - kiosk_input_sources_manager_dispose (GObject *object) - { - KioskInputSourcesManager *self = KIOSK_INPUT_SOURCES_MANAGER (object); - - if (self->cancellable != NULL) { - g_cancellable_cancel (self->cancellable); - g_clear_object (&self->cancellable); - } - - kiosk_input_sources_manager_clear_input_sources (self); - - g_clear_object (&self->input_engine_manager); -+ g_clear_object (&self->x_keyboard_manager); - - g_clear_object (&self->xkb_info); - - g_clear_object (&self->locale_proxy); - - 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..ad18d39 ---- /dev/null -+++ b/compositor/kiosk-x-keyboard-manager.c -@@ -0,0 +1,565 @@ -+#include "config.h" -+#include "kiosk-x-keyboard-manager.h" -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "kiosk-compositor.h" -+#include "kiosk-gobject-utils.h" -+ -+struct _KioskXKeyboardManager -+{ -+ GObject parent; -+ -+ /* weak references */ -+ KioskCompositor *compositor; -+ MetaBackend *backend; -+ MetaDisplay *display; -+ Display *x_server_display; -+ -+ /* strong references */ -+ GCancellable *cancellable; -+ GBytes *xkb_rules_names_data; -+ char **layouts; -+ char *options; -+ -+ /* state */ -+ Window x_server_root_window; -+ Atom xkb_rules_names_atom; -+ int xkb_event_base; -+ -+ size_t layout_index; -+ ssize_t pending_layout_index; -+ -+ /* flags */ -+ guint32 xkb_rules_names_data_changed: 1; -+}; -+ -+enum -+{ -+ PROP_COMPOSITOR = 1, -+ PROP_LAYOUTS, -+ PROP_SELECTED_LAYOUT, -+ NUMBER_OF_PROPERTIES -+}; -+ -+static GParamSpec *kiosk_x_keyboard_manager_properties[NUMBER_OF_PROPERTIES] = { NULL, }; -+ -+G_DEFINE_TYPE (KioskXKeyboardManager, kiosk_x_keyboard_manager, G_TYPE_OBJECT) -+ -+static void kiosk_x_keyboard_manager_set_property (GObject *object, -+ guint property_id, -+ const GValue *value, -+ GParamSpec *param_spec); -+static void kiosk_x_keyboard_manager_get_property (GObject *object, -+ guint property_id, -+ GValue *value, -+ GParamSpec *param_spec); -+ -+static void kiosk_x_keyboard_manager_constructed (GObject *object); -+static void kiosk_x_keyboard_manager_dispose (GObject *object); -+ -+KioskXKeyboardManager * -+kiosk_x_keyboard_manager_new (KioskCompositor *compositor) -+{ -+ GObject *object; -+ -+ object = g_object_new (KIOSK_TYPE_X_KEYBOARD_MANAGER, -+ "compositor", compositor, -+ NULL); -+ -+ return KIOSK_X_KEYBOARD_MANAGER (object); -+} -+ -+static void -+kiosk_x_keyboard_manager_class_init (KioskXKeyboardManagerClass *x_keyboard_manager_class) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (x_keyboard_manager_class); -+ -+ object_class->constructed = kiosk_x_keyboard_manager_constructed; -+ object_class->set_property = kiosk_x_keyboard_manager_set_property; -+ object_class->get_property = kiosk_x_keyboard_manager_get_property; -+ object_class->dispose = kiosk_x_keyboard_manager_dispose; -+ -+ kiosk_x_keyboard_manager_properties[PROP_COMPOSITOR] = g_param_spec_object ("compositor", -+ "compositor", -+ "compositor", -+ KIOSK_TYPE_COMPOSITOR, -+ G_PARAM_CONSTRUCT_ONLY -+ | G_PARAM_WRITABLE -+ | G_PARAM_STATIC_NAME -+ | G_PARAM_STATIC_NICK -+ | G_PARAM_STATIC_BLURB); -+ kiosk_x_keyboard_manager_properties[PROP_SELECTED_LAYOUT] = g_param_spec_string ("selected-layout", -+ "selected-layout", -+ "selected-layout", -+ NULL, -+ G_PARAM_READABLE -+ | G_PARAM_STATIC_NAME -+ | G_PARAM_STATIC_NICK -+ | G_PARAM_STATIC_BLURB); -+ -+ kiosk_x_keyboard_manager_properties[PROP_LAYOUTS] = g_param_spec_boxed ("layouts", -+ "layouts", -+ "layouts", -+ G_TYPE_STRV, -+ G_PARAM_READABLE -+ | G_PARAM_STATIC_NAME -+ | G_PARAM_STATIC_NICK -+ | G_PARAM_STATIC_BLURB); -+ -+ g_object_class_install_properties (object_class, NUMBER_OF_PROPERTIES, kiosk_x_keyboard_manager_properties); -+} -+ -+static void -+kiosk_x_keyboard_manager_set_property (GObject *object, -+ guint property_id, -+ const GValue *value, -+ GParamSpec *param_spec) -+{ -+ KioskXKeyboardManager *self = KIOSK_X_KEYBOARD_MANAGER (object); -+ -+ switch (property_id) { -+ case PROP_COMPOSITOR: -+ g_set_weak_pointer (&self->compositor, g_value_get_object (value)); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec); -+ break; -+ } -+} -+ -+static void -+kiosk_x_keyboard_manager_get_property (GObject *object, -+ guint property_id, -+ GValue *value, -+ GParamSpec *param_spec) -+{ -+ KioskXKeyboardManager *self = KIOSK_X_KEYBOARD_MANAGER (object); -+ -+ switch (property_id) { -+ case PROP_SELECTED_LAYOUT: -+ g_value_set_string (value, self->layouts[self->layout_index]); -+ break; -+ case PROP_LAYOUTS: -+ g_value_set_boxed (value, self->layouts); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, param_spec); -+ break; -+ } -+} -+ -+static char ** -+qualify_layouts_with_variants (KioskXKeyboardManager *self, -+ const char * const *layouts, -+ const char * const *variants) -+{ -+ size_t number_of_layouts = 0; -+ size_t number_of_variants = 0; -+ char **fully_qualified_layouts = NULL; -+ -+ size_t i, j; -+ -+ g_return_val_if_fail (KIOSK_IS_X_KEYBOARD_MANAGER (self), FALSE); -+ -+ number_of_layouts = g_strv_length ((GStrv) layouts); -+ number_of_variants = g_strv_length ((GStrv) variants); -+ -+ if (number_of_layouts < number_of_variants) { -+ g_debug ("KioskXKeyboardManager: There is a layout variant mismatch"); -+ return NULL; -+ } -+ -+ fully_qualified_layouts = g_new0 (char *, number_of_layouts + 1); -+ -+ for (i = 0, j = 0; layouts[i] != NULL; i++) { -+ const char *layout = layouts[i]; -+ const char *variant = ""; -+ -+ if (variants[j] != NULL) { -+ variant = variants[j++]; -+ } -+ -+ if (variant[0] == '\0') { -+ fully_qualified_layouts[i] = g_strdup (layout); -+ } else { -+ fully_qualified_layouts[i] = g_strdup_printf ("%s+%s", layout, variant); -+ } -+ } -+ -+ return fully_qualified_layouts; -+} -+ -+static void -+kiosk_x_keyboard_manager_set_layout_index (KioskXKeyboardManager *self, -+ size_t layout_index) -+{ -+ size_t number_of_layouts; -+ -+ if (self->layout_index == layout_index) { -+ return; -+ } -+ -+ g_debug ("KioskXKeyboardManager: X server is using layout with index %ld", -+ layout_index); -+ -+ number_of_layouts = g_strv_length (self->layouts); -+ -+ if (layout_index >= number_of_layouts) { -+ layout_index = 0; -+ } -+ -+ self->layout_index = layout_index; -+ g_object_notify (G_OBJECT (self), "selected-layout"); -+} -+ -+static gboolean -+kiosk_x_keyboard_manager_read_current_layout_index (KioskXKeyboardManager *self) -+{ -+ XkbStateRec xkb_state = { 0 }; -+ int status; -+ -+ status = XkbGetState (self->x_server_display, XkbUseCoreKbd, &xkb_state); -+ -+ if (status != Success) { -+ g_debug ("KioskXKeyboardManager: Could not read current layout index"); -+ return FALSE; -+ } -+ -+ kiosk_x_keyboard_manager_set_layout_index (self, xkb_state.locked_group); -+ return FALSE; -+} -+ -+static gboolean -+kiosk_x_keyboard_manager_read_xkb_rules_names_data (KioskXKeyboardManager *self) -+{ -+ g_autoptr (GBytes) new_xkb_rules_names_data = NULL; -+ g_autoptr (GVariant) input_source_group = NULL; -+ size_t number_of_layouts = 0; -+ g_autofree char *layouts_string = NULL; -+ g_autofree char *variants_string = NULL; -+ g_autofree char *options = NULL; -+ g_auto (GStrv) layouts = NULL; -+ g_auto (GStrv) variants = NULL; -+ g_auto (GStrv) qualified_layouts = NULL; -+ int status; -+ Atom returned_type = 0; -+ int returned_format = 0; -+ gulong number_of_bytes_read = 0; -+ gulong number_of_bytes_unread = 0; -+ guchar *property_values; -+ size_t i; -+ enum { -+ RULES_NAME = 0, -+ MODEL, -+ LAYOUTS, -+ VARIANTS, -+ OPTIONS -+ } property_value_index; -+ -+ self->xkb_rules_names_data_changed = TRUE; -+ -+ g_debug ("KioskXKeyboardManager: Reading active keyboard layouts from X server"); -+ -+ status = XGetWindowProperty (self->x_server_display, -+ self->x_server_root_window, -+ self->xkb_rules_names_atom, -+ 0, 1024, FALSE, XA_STRING, -+ &returned_type, -+ &returned_format, -+ &number_of_bytes_read, -+ &number_of_bytes_unread, -+ &property_values); -+ -+ if (status != Success) { -+ g_debug ("KioskXKeyboardManager: Could not read active keyboard layouts from X server"); -+ return FALSE; -+ } -+ -+ if (returned_type != XA_STRING || -+ returned_format != 8 || -+ number_of_bytes_unread != 0) { -+ g_debug ("KioskXKeyboardManager: Active keyboard layouts propery from X server is corrupted"); -+ return FALSE; -+ } -+ -+ new_xkb_rules_names_data = g_bytes_new_with_free_func (property_values, -+ number_of_bytes_read, -+ (GDestroyNotify) XFree, -+ NULL); -+ -+ property_value_index = 0; -+ for (i = 0; i < number_of_bytes_read; i++) { -+ g_autofree char *value = g_strdup ((char *) property_values + i); -+ size_t value_length = strlen (value); -+ -+ switch (property_value_index) { -+ case RULES_NAME: -+ case MODEL: -+ break; -+ case LAYOUTS: -+ layouts_string = g_steal_pointer (&value); -+ g_debug ("KioskXKeyboardManager: Read layouts '%s'", layouts_string); -+ break; -+ case VARIANTS: -+ variants_string = g_steal_pointer (&value); -+ g_debug ("KioskXKeyboardManager: Read variants '%s'", variants_string); -+ break; -+ case OPTIONS: -+ options = g_steal_pointer (&value); -+ g_debug ("KioskXKeyboardManager: Read options '%s'", options); -+ break; -+ } -+ -+ i += value_length; -+ 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); -+ -+ qualified_layouts = qualify_layouts_with_variants (self, (const char * const *)layouts, (const char * const *)variants); -+ -+ if (qualified_layouts == NULL) { -+ g_debug ("KioskXKeyboardManager: Unable to qualify layouts with variants"); -+ return FALSE; -+ } -+ -+ number_of_layouts = g_strv_length (qualified_layouts); -+ -+ if (number_of_layouts == 0) { -+ g_debug ("KioskXKeyboardManager: No layouts found"); -+ return FALSE; -+ } -+ -+ g_clear_pointer (&self->layouts, g_strfreev); -+ self->layouts = g_steal_pointer (&qualified_layouts); -+ self->options = g_steal_pointer (&options); -+ -+ g_object_freeze_notify (G_OBJECT (self)); -+ g_object_notify (G_OBJECT (self), "layouts"); -+ kiosk_x_keyboard_manager_read_current_layout_index (self); -+ g_object_thaw_notify (G_OBJECT (self)); -+ -+ return TRUE; -+} -+ -+static void -+monitor_x_server_display_for_changes (KioskXKeyboardManager *self) -+{ -+ int major = XkbMajorVersion; -+ int minor = XkbMinorVersion; -+ XWindowAttributes attributes; -+ -+ XGetWindowAttributes (self->x_server_display, self->x_server_root_window, &attributes); -+ -+ if (!(attributes.your_event_mask & PropertyChangeMask)) { -+ XSelectInput (self->x_server_display, -+ self->x_server_root_window, -+ attributes.your_event_mask | PropertyChangeMask); -+ } -+ -+ 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 -+kiosk_x_keyboard_manager_handle_x_server_property_notify (KioskXKeyboardManager *self, -+ XPropertyEvent *x_server_event) -+{ -+ if (x_server_event->window != self->x_server_root_window) { -+ return; -+ } -+ -+ if (x_server_event->atom != self->xkb_rules_names_atom) { -+ return; -+ } -+ -+ g_debug ("KioskXKeyboardManager: XKB rules names property changed in X server"); -+ kiosk_x_keyboard_manager_read_xkb_rules_names_data (self); -+} -+ -+static void -+kiosk_x_keyboard_manager_handle_xkb_event (KioskXKeyboardManager *self, -+ XkbEvent *x_server_event) -+{ -+ size_t layout_index; -+ -+ layout_index = XkbStateGroup (&x_server_event->state); -+ switch (x_server_event->any.xkb_type) { -+ case XkbStateNotify: -+ if (!(x_server_event->state.changed & XkbGroupStateMask)) { -+ return; -+ } -+ -+ /* 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); -+ kiosk_x_keyboard_manager_set_layout_index (self, layout_index); -+ break; -+ } -+} -+ -+static void -+on_x_server_event (KioskXKeyboardManager *self, -+ XEvent *x_server_event) -+{ -+ -+ 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: -+ kiosk_x_keyboard_manager_handle_x_server_property_notify (self, &x_server_event->xproperty); -+ break; -+ default: -+ if (x_server_event->type == self->xkb_event_base) { -+ kiosk_x_keyboard_manager_handle_xkb_event (self, (XkbEvent *) x_server_event); -+ } -+ break; -+ } -+} -+ -+const char * const * -+kiosk_x_keyboard_manager_get_layouts (KioskXKeyboardManager *self) -+{ -+ g_return_val_if_fail (KIOSK_IS_X_KEYBOARD_MANAGER (self), NULL); -+ -+ return (const char * const *) self->layouts; -+} -+ -+const char * -+kiosk_x_keyboard_manager_get_selected_layout (KioskXKeyboardManager *self) -+{ -+ g_return_val_if_fail (KIOSK_IS_X_KEYBOARD_MANAGER (self), NULL); -+ -+ if (self->layouts == NULL) { -+ return NULL; -+ } -+ -+ g_debug ("KioskXKeyboardManager: Selected layout is '%s'", self->layouts[self->layout_index]); -+ -+ return self->layouts[self->layout_index]; -+} -+ -+const char * -+kiosk_x_keyboard_manager_get_options (KioskXKeyboardManager *self) -+{ -+ g_return_val_if_fail (KIOSK_IS_X_KEYBOARD_MANAGER (self), NULL); -+ -+ return self->options; -+} -+ -+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_init (KioskXKeyboardManager *self) -+{ -+} -+ -+static void -+kiosk_x_keyboard_manager_constructed (GObject *object) -+{ -+ KioskXKeyboardManager *self = KIOSK_X_KEYBOARD_MANAGER (object); -+ -+ g_debug ("KioskXKeyboardManager: Initializing"); -+ -+ G_OBJECT_CLASS (kiosk_x_keyboard_manager_parent_class)->constructed (object); -+ -+ self->cancellable = g_cancellable_new (); -+ -+ g_set_weak_pointer (&self->backend, meta_get_backend ()); -+ g_set_weak_pointer (&self->display, meta_plugin_get_display (META_PLUGIN (self->compositor))); -+ -+ self->pending_layout_index = -1; -+ -+ g_signal_connect_object (G_OBJECT (self->compositor), -+ "x-server-event", -+ G_CALLBACK (on_x_server_event), -+ self, -+ G_CONNECT_SWAPPED); -+} -+ -+static void -+kiosk_x_keyboard_manager_dispose (GObject *object) -+{ -+ KioskXKeyboardManager *self = KIOSK_X_KEYBOARD_MANAGER (object); -+ -+ g_debug ("KioskXKeyboardManager: Disposing"); -+ -+ if (self->cancellable != NULL) { -+ g_cancellable_cancel (self->cancellable); -+ g_clear_object (&self->cancellable); -+ } -+ -+ g_clear_pointer (&self->xkb_rules_names_data, g_bytes_unref); -+ g_clear_pointer (&self->layouts, g_strfreev); -+ g_clear_pointer (&self->options, g_free); -+ -+ g_clear_weak_pointer (&self->display); -+ g_clear_weak_pointer (&self->backend); -+ g_clear_weak_pointer (&self->compositor); -+ -+ G_OBJECT_CLASS (kiosk_x_keyboard_manager_parent_class)->dispose (object); -+} -diff --git a/compositor/kiosk-x-keyboard-manager.h b/compositor/kiosk-x-keyboard-manager.h -new file mode 100644 -index 0000000..bae498f ---- /dev/null -+++ b/compositor/kiosk-x-keyboard-manager.h -@@ -0,0 +1,29 @@ -+#pragma once -+ -+#include -+#include -+ -+typedef struct _KioskCompositor KioskCompositor; -+ -+G_BEGIN_DECLS -+ -+#define KIOSK_TYPE_X_KEYBOARD_MANAGER (kiosk_x_keyboard_manager_get_type ()) -+ -+G_DECLARE_FINAL_TYPE (KioskXKeyboardManager, -+ kiosk_x_keyboard_manager, -+ KIOSK, X_KEYBOARD_MANAGER, -+ GObject) -+ -+KioskXKeyboardManager *kiosk_x_keyboard_manager_new (KioskCompositor *compositor); -+ -+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 -index 2b5640a..44afcea 100644 ---- a/meson.build -+++ b/meson.build -@@ -86,60 +86,61 @@ sources = gnome.gdbus_codegen(dbus_interface, dbus_interface_file, - namespace: 'Kiosk', - interface_prefix: 'org.gnome', - annotations: [ - [ dbus_interface, 'org.gtk.GDBus.C.Name', 'ShellDBusService' ] - ] - ) - dbus_interface_sources_map += { dbus_interface: sources } - - compositor_dependencies = [] - compositor_dependencies += c_compiler.find_library('m') - compositor_dependencies += dependency('gio-2.0') - compositor_dependencies += dependency('glib-2.0') - compositor_dependencies += dependency('gnome-desktop-3.0') - compositor_dependencies += dependency('gobject-2.0') - compositor_dependencies += dependency('ibus-1.0') - compositor_dependencies += dependency('mutter-cogl-8') - compositor_dependencies += dependency('mutter-cogl-pango-8') - compositor_dependencies += dependency('mutter-clutter-8') - compositor_dependencies += mutter_dependency - - compositor_sources = [] - compositor_sources += 'compositor/kiosk-backgrounds.c' - compositor_sources += 'compositor/kiosk-compositor.c' - compositor_sources += 'compositor/kiosk-dbus-utils.c' - compositor_sources += 'compositor/kiosk-gobject-utils.c' - compositor_sources += 'compositor/kiosk-input-sources-manager.c' - compositor_sources += 'compositor/kiosk-input-engine-manager.c' - compositor_sources += 'compositor/kiosk-input-source-group.c' - compositor_sources += 'compositor/kiosk-service.c' - compositor_sources += 'compositor/kiosk-shell-service.c' -+compositor_sources += 'compositor/kiosk-x-keyboard-manager.c' - compositor_sources += 'compositor/main.c' - - foreach dbus_interface, sources: dbus_interface_sources_map - compositor_sources += sources - endforeach - - executable('gnome-kiosk', compositor_sources, - dependencies: compositor_dependencies, - build_rpath: mutter_libdir, - install_rpath: mutter_libdir, - install: true - ) - - desktop_config_data = configuration_data() - desktop_config_data.set('bindir', bindir) - - desktop_file = configure_file( - input: 'compositor/data/org.gnome.Kiosk.desktop.in.in', - output: 'org.gnome.Kiosk.desktop.in', - configuration: desktop_config_data - ) - - i18n.merge_file('desktop', - input: desktop_file, - output: 'org.gnome.Kiosk.desktop', - po_dir: po_dir, - install: true, - install_dir: desktop_data_dir, - type: 'desktop' - ) --- -2.30.2 - diff --git a/gnome-kiosk.spec b/gnome-kiosk.spec index b1a5908..3f1ad90 100644 --- a/gnome-kiosk.spec +++ b/gnome-kiosk.spec @@ -11,8 +11,8 @@ %global gnome_settings_daemon_version 40~rc Name: gnome-kiosk -Version: 40~alpha -Release: 9%{?dist} +Version: 40.0 +Release: 1%{?dist} Summary: Window management and application launching for GNOME License: GPLv2+ @@ -39,24 +39,6 @@ BuildRequires: meson Requires: gnome-settings-daemon%{?_isa} >= %{gnome_settings_daemon_version} Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} -# https://gitlab.gnome.org/halfline/gnome-kiosk/-/merge_requests/1 -Patch10001: 0001-compositor-Be-less-aggressive-about-full-screening-w.patch - -# https://gitlab.gnome.org/halfline/gnome-kiosk/-/merge_requests/2 -Patch20001: 0001-gobject-utils-Log-when-executing-deferred-tasks.patch -Patch20002: 0002-input-sources-manager-Fix-overzealous-rename-mistake.patch -Patch20003: 0003-compositor-Add-signal-for-reporting-X-server-events.patch -Patch20004: 0004-input-sources-manager-Support-libxklavier-managed-ke.patch - -# https://gitlab.gnome.org/halfline/gnome-kiosk/-/merge_requests/3 -Patch30001: 0001-Make-the-desktop-file-valid.patch - -# https://gitlab.gnome.org/halfline/gnome-kiosk/-/merge_requests/4 -Patch40001: 0001-compositor-Put-the-on-top-windows-actually-on-top.patch - -# https://gitlab.gnome.org/halfline/gnome-kiosk/-/merge_requests/5 -Patch50001: 0001-input-sources-manager-Fail-better-if-localed-isn-t-a.patch - %description GNOME Kiosk provides a desktop enviroment suitable for fixed purpose, or single application deployments like wall displays and point-of-sale systems. @@ -99,6 +81,10 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Kiosk.Searc %{_datadir}/wayland-sessions/org.gnome.Kiosk.SearchApp.Session.desktop %changelog +* Mon May 17 2021 Ray Strode - 40.0-1 +- Update to 40.0 + Related: #1950042 + * Wed May 12 2021 Ray Strode - 40~alpha-9 - Fix crash Resolves: #1957754 diff --git a/sources b/sources index 510ea42..ce11501 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (gnome-kiosk-40.alpha.tar.xz) = c79645935438f5512b437ae19ea8016a8b2ce6fd49a4e5426956d6fc21b33d622e82d01ce3c0cb97f540c5a889c1a098b0e9e8d65d33e0669dc989e1d391f9fb +SHA512 (gnome-kiosk-40.0.tar.xz) = 2e670046b9cf9031bfa2b95969726c626d83c6d84ffb0ecc50a67414d406f05e515dbf7716b7f84c9342aec84e93369c07199ef233923cbb527d267c61374d35