2481 lines
91 KiB
Diff
2481 lines
91 KiB
Diff
|
From e51d40084fe304ba78404354e9aed00396954bdd Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Tue, 15 Aug 2023 10:53:41 -0400
|
||
|
Subject: [PATCH 01/10] gnome-initial-setup: Bump GLib required version to 2.76
|
||
|
|
||
|
This gives us GStrvBuilder, g_ptr_array_sort_values, etc
|
||
|
---
|
||
|
gnome-initial-setup/meson.build | 2 +-
|
||
|
meson.build | 4 ++--
|
||
|
2 files changed, 3 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/gnome-initial-setup/meson.build b/gnome-initial-setup/meson.build
|
||
|
index a6a014d1..64fa834a 100644
|
||
|
--- a/gnome-initial-setup/meson.build
|
||
|
+++ b/gnome-initial-setup/meson.build
|
||
|
@@ -52,7 +52,7 @@ dependencies = [
|
||
|
dependency ('fontconfig'),
|
||
|
dependency ('goa-1.0'),
|
||
|
dependency ('gtk4', version: '>= 4.6'),
|
||
|
- dependency ('glib-2.0', version: '>= 2.63.1'),
|
||
|
+ dependency ('glib-2.0', version: '>= 2.76.0'),
|
||
|
dependency ('gio-unix-2.0', version: '>= 2.53.0'),
|
||
|
dependency ('gdm', version: '>= 3.8.3'),
|
||
|
gweather_dep,
|
||
|
diff --git a/meson.build b/meson.build
|
||
|
index 2e40a2e2..fba4d96a 100644
|
||
|
--- a/meson.build
|
||
|
+++ b/meson.build
|
||
|
@@ -30,8 +30,8 @@ conf.set_quoted('LIBEXECDIR', libexec_dir)
|
||
|
conf.set('SECRET_API_SUBJECT_TO_CHANGE', true)
|
||
|
conf.set_quoted('G_LOG_DOMAIN', 'InitialSetup')
|
||
|
conf.set('G_LOG_USE_STRUCTURED', true)
|
||
|
-conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_64')
|
||
|
-conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_64')
|
||
|
+conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_76')
|
||
|
+conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_76')
|
||
|
|
||
|
enable_systemd = get_option('systemd')
|
||
|
if enable_systemd
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From b729f698befddefb9618aa8399ade5306486dd9f Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Sat, 9 Sep 2023 17:07:46 -0400
|
||
|
Subject: [PATCH 02/10] keyboard: Don't require localed for existing user mode
|
||
|
|
||
|
If we're in existing user mode, the user may not have
|
||
|
permission to set the system keymap.
|
||
|
|
||
|
This commit makes sure that lack of permission doesn't
|
||
|
prevent the keyboard page from completing.
|
||
|
---
|
||
|
gnome-initial-setup/pages/keyboard/gis-keyboard-page.c | 9 +++++++--
|
||
|
1 file changed, 7 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
index fa41230f..da384495 100644
|
||
|
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
@@ -415,8 +415,13 @@ update_page_complete (GisKeyboardPage *self)
|
||
|
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
gboolean complete;
|
||
|
|
||
|
- complete = (priv->localed != NULL &&
|
||
|
- cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser)) != NULL);
|
||
|
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
|
||
|
+ complete = (priv->localed != NULL &&
|
||
|
+ cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser)) != NULL);
|
||
|
+ } else {
|
||
|
+ complete = cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser)) != NULL;
|
||
|
+ }
|
||
|
+
|
||
|
gis_page_set_complete (GIS_PAGE (self), complete);
|
||
|
}
|
||
|
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 2f5bf8a8203c0b12937c8be0fb536dd8f28f2fca Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Fri, 8 Sep 2023 11:02:39 -0400
|
||
|
Subject: [PATCH 03/10] language: Don't proceed until localed has set locale
|
||
|
|
||
|
In sysmte modes, the keyboard page requires reading the locale from
|
||
|
localed, so we need to make sure the setting has been applied before
|
||
|
proceeding to the keyboard page from the language page.
|
||
|
|
||
|
This commit changes the Next button to desensitize if a set locale
|
||
|
operation is pending.
|
||
|
---
|
||
|
.../pages/language/gis-language-page.c | 31 +++++++++++++++++--
|
||
|
1 file changed, 28 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/gnome-initial-setup/pages/language/gis-language-page.c b/gnome-initial-setup/pages/language/gis-language-page.c
|
||
|
index 87b9f2d8..26a01257 100644
|
||
|
--- a/gnome-initial-setup/pages/language/gis-language-page.c
|
||
|
+++ b/gnome-initial-setup/pages/language/gis-language-page.c
|
||
|
@@ -56,6 +56,23 @@ typedef struct _GisLanguagePagePrivate GisLanguagePagePrivate;
|
||
|
|
||
|
G_DEFINE_TYPE_WITH_PRIVATE (GisLanguagePage, gis_language_page, GIS_TYPE_PAGE);
|
||
|
|
||
|
+static void
|
||
|
+on_locale_set (GDBusProxy *proxy,
|
||
|
+ GAsyncResult *result,
|
||
|
+ GisLanguagePage *self)
|
||
|
+{
|
||
|
+ g_autoptr(GError) error = NULL;
|
||
|
+ g_autoptr(GVariant) call_result = NULL;
|
||
|
+
|
||
|
+ call_result = g_dbus_proxy_call_finish (proxy, result, &error);
|
||
|
+
|
||
|
+ if (error != NULL) {
|
||
|
+ g_warning ("Could not set system locale: %s", error->message);
|
||
|
+ }
|
||
|
+
|
||
|
+ gis_page_set_complete (GIS_PAGE (self), TRUE);
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
set_localed_locale (GisLanguagePage *self)
|
||
|
{
|
||
|
@@ -72,7 +89,9 @@ set_localed_locale (GisLanguagePage *self)
|
||
|
"SetLocale",
|
||
|
g_variant_new ("(asb)", b, TRUE),
|
||
|
G_DBUS_CALL_FLAGS_NONE,
|
||
|
- -1, NULL, NULL, NULL);
|
||
|
+ -1, priv->cancellable,
|
||
|
+ (GAsyncReadyCallback) on_locale_set,
|
||
|
+ self);
|
||
|
g_variant_builder_unref (b);
|
||
|
}
|
||
|
|
||
|
@@ -127,6 +146,9 @@ language_changed (CcLanguageChooser *chooser,
|
||
|
gtk_widget_set_default_direction (gtk_get_locale_direction ());
|
||
|
|
||
|
if (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER) {
|
||
|
+
|
||
|
+ gis_page_set_complete (GIS_PAGE (page), FALSE);
|
||
|
+
|
||
|
if (g_permission_get_allowed (priv->permission)) {
|
||
|
set_localed_locale (page);
|
||
|
}
|
||
|
@@ -177,6 +199,7 @@ localed_proxy_ready (GObject *source,
|
||
|
}
|
||
|
|
||
|
priv->localed = proxy;
|
||
|
+ gis_page_set_complete (GIS_PAGE (self), TRUE);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -251,8 +274,10 @@ gis_language_page_constructed (GObject *object)
|
||
|
object);
|
||
|
g_object_unref (bus);
|
||
|
}
|
||
|
-
|
||
|
- gis_page_set_complete (GIS_PAGE (page), TRUE);
|
||
|
+ else
|
||
|
+ {
|
||
|
+ gis_page_set_complete (GIS_PAGE (page), TRUE);
|
||
|
+ }
|
||
|
gtk_widget_set_visible (GTK_WIDGET (page), TRUE);
|
||
|
}
|
||
|
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 4ac881f55d46bc45e09a831aa5ab9ae2ba173477 Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Thu, 24 Aug 2023 21:19:40 -0400
|
||
|
Subject: [PATCH 04/10] keyboard: Get default input sources from gnome-desktop
|
||
|
|
||
|
Right now, we figure out the default input sources ourselves,
|
||
|
based on the current locale and layout information coming from
|
||
|
localed.
|
||
|
|
||
|
This logic needs to be duplicated in several components, so its
|
||
|
now provided by gnome-desktop.
|
||
|
|
||
|
This commit changes it over to use gnome-desktop APIs.
|
||
|
|
||
|
The same time if leverages a gnome-desktop API to fix a bug
|
||
|
where cyrillic layouts were getting added without a latin
|
||
|
counterpart.
|
||
|
---
|
||
|
.../pages/keyboard/gis-keyboard-page.c | 475 +++++++++---------
|
||
|
1 file changed, 239 insertions(+), 236 deletions(-)
|
||
|
|
||
|
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
index da384495..f2bfe164 100644
|
||
|
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
@@ -44,6 +44,8 @@
|
||
|
#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
|
||
|
#define KEY_CURRENT_INPUT_SOURCE "current"
|
||
|
#define KEY_INPUT_SOURCES "sources"
|
||
|
+#define KEY_MRU_SOURCES "mru-sources"
|
||
|
+#define KEY_INPUT_OPTIONS "xkb-options"
|
||
|
|
||
|
struct _GisKeyboardPagePrivate {
|
||
|
GtkWidget *input_chooser;
|
||
|
@@ -52,8 +54,14 @@ struct _GisKeyboardPagePrivate {
|
||
|
GCancellable *cancellable;
|
||
|
GPermission *permission;
|
||
|
GSettings *input_settings;
|
||
|
-
|
||
|
- GSList *system_sources;
|
||
|
+ char **default_input_source_ids;
|
||
|
+ char **default_input_source_types;
|
||
|
+ char **default_options;
|
||
|
+ char **system_layouts;
|
||
|
+ char **system_variants;
|
||
|
+ char **system_options;
|
||
|
+
|
||
|
+ gboolean should_skip;
|
||
|
};
|
||
|
typedef struct _GisKeyboardPagePrivate GisKeyboardPagePrivate;
|
||
|
|
||
|
@@ -72,98 +80,191 @@ gis_keyboard_page_finalize (GObject *object)
|
||
|
g_clear_object (&priv->permission);
|
||
|
g_clear_object (&priv->localed);
|
||
|
g_clear_object (&priv->input_settings);
|
||
|
-
|
||
|
- g_slist_free_full (priv->system_sources, g_free);
|
||
|
+ g_clear_pointer (&priv->default_input_source_ids, g_strfreev);
|
||
|
+ g_clear_pointer (&priv->default_input_source_types, g_strfreev);
|
||
|
+ g_clear_pointer (&priv->default_options, g_strfreev);
|
||
|
+ g_clear_pointer (&priv->system_layouts, g_strfreev);
|
||
|
+ g_clear_pointer (&priv->system_variants, g_strfreev);
|
||
|
+ g_clear_pointer (&priv->system_options, g_strfreev);
|
||
|
|
||
|
G_OBJECT_CLASS (gis_keyboard_page_parent_class)->finalize (object);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
-set_input_settings (GisKeyboardPage *self)
|
||
|
+add_defaults_to_variant_builder (GisKeyboardPage *self,
|
||
|
+ const char *already_added_type,
|
||
|
+ const char *already_added_id,
|
||
|
+ GVariantBuilder *input_source_builder,
|
||
|
+ char **default_layout)
|
||
|
+
|
||
|
{
|
||
|
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
- const gchar *type;
|
||
|
- const gchar *id;
|
||
|
- GVariantBuilder builder;
|
||
|
- GSList *l;
|
||
|
- gboolean is_xkb_source = FALSE;
|
||
|
+ size_t i;
|
||
|
|
||
|
- type = cc_input_chooser_get_input_type (CC_INPUT_CHOOSER (priv->input_chooser));
|
||
|
- id = cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser));
|
||
|
+ for (i = 0; priv->default_input_source_ids && priv->default_input_source_ids[i] != NULL; i++) {
|
||
|
+ if (g_strcmp0 (already_added_id, priv->default_input_source_ids[i]) == 0 && g_strcmp0 (already_added_type, priv->default_input_source_types[i]) == 0) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
|
||
|
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
|
||
|
+ g_variant_builder_add (input_source_builder, "(ss)", priv->default_input_source_types[i], priv->default_input_source_ids[i]);
|
||
|
|
||
|
- if (g_str_equal (type, "xkb")) {
|
||
|
- g_variant_builder_add (&builder, "(ss)", type, id);
|
||
|
- is_xkb_source = TRUE;
|
||
|
+ if (*default_layout != NULL) {
|
||
|
+ if (!gnome_input_source_is_non_latin (priv->default_input_source_types[i], priv->default_input_source_ids[i])) {
|
||
|
+ *default_layout = g_strdup (priv->default_input_source_ids[i]);
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
+}
|
||
|
|
||
|
- for (l = priv->system_sources; l; l = l->next) {
|
||
|
- const gchar *sid = l->data;
|
||
|
|
||
|
- if (g_str_equal (id, sid) && g_str_equal (type, "xkb"))
|
||
|
- continue;
|
||
|
+static void
|
||
|
+add_input_source_to_arrays (GisKeyboardPage *self,
|
||
|
+ const char *type,
|
||
|
+ const char *id,
|
||
|
+ GPtrArray *layouts_array,
|
||
|
+ GPtrArray *variants_array)
|
||
|
+{
|
||
|
+ g_auto(GStrv) layout_and_variant = NULL;
|
||
|
+ const char *layout, *variant;
|
||
|
+
|
||
|
+ if (!g_str_equal (type, "xkb")) {
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ layout_and_variant = g_strsplit (id, "+", -1);
|
||
|
+
|
||
|
+ layout = layout_and_variant[0];
|
||
|
+ variant = layout_and_variant[1]?: "";
|
||
|
+
|
||
|
+ if (g_ptr_array_find_with_equal_func (layouts_array, layout, g_str_equal, NULL) &&
|
||
|
+ g_ptr_array_find_with_equal_func (variants_array, variant, g_str_equal, NULL)) {
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ g_ptr_array_add (layouts_array, g_strdup (layout));
|
||
|
+ g_ptr_array_add (variants_array, g_strdup (variant));
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+add_defaults_to_arrays (GisKeyboardPage *self,
|
||
|
+ GPtrArray *layouts_array,
|
||
|
+ GPtrArray *variants_array)
|
||
|
+{
|
||
|
+ GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
+ size_t i;
|
||
|
+
|
||
|
+ for (i = 0; priv->default_input_source_ids && priv->default_input_source_ids[i] != NULL; i++) {
|
||
|
+ add_input_source_to_arrays (self, priv->default_input_source_types[i], priv->default_input_source_ids[i], layouts_array, variants_array);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+set_input_settings (GisKeyboardPage *self,
|
||
|
+ const char *type,
|
||
|
+ const char *id)
|
||
|
+{
|
||
|
+ GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
+ g_autofree char *layout = NULL;
|
||
|
+ g_autofree char *variant = NULL;
|
||
|
+ g_autoptr(GVariant) default_input_sources = NULL;
|
||
|
+ g_autoptr(GVariant) input_sources = NULL;
|
||
|
+ g_autoptr(GPtrArray) layouts_array = NULL;
|
||
|
+ g_autoptr(GPtrArray) variants_array = NULL;
|
||
|
+ GVariantBuilder input_source_builder;
|
||
|
+ GVariantBuilder input_options_builder;
|
||
|
+ g_autoptr(GVariant) input_options = NULL;
|
||
|
+ gboolean is_system_mode;
|
||
|
+ size_t i;
|
||
|
+ g_autofree char *default_input_source_id = NULL;
|
||
|
+
|
||
|
+ default_input_sources = g_settings_get_default_value (priv->input_settings, KEY_INPUT_SOURCES);
|
||
|
+ input_sources = g_settings_get_value (priv->input_settings, KEY_INPUT_SOURCES);
|
||
|
+
|
||
|
+ if (!g_variant_equal (default_input_sources, input_sources))
|
||
|
+ return;
|
||
|
+
|
||
|
+ g_clear_pointer (&input_sources, g_variant_unref);
|
||
|
+
|
||
|
+ g_variant_builder_init (&input_options_builder, G_VARIANT_TYPE ("as"));
|
||
|
+
|
||
|
+ is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER;
|
||
|
+
|
||
|
+ layouts_array = g_ptr_array_new ();
|
||
|
+ variants_array = g_ptr_array_new ();
|
||
|
+
|
||
|
+ /* Notice the added latin layout (if relevant) gets put first for gsettings
|
||
|
+ * (input_source_builder and last for localed (layouts_array/variants_array)
|
||
|
+ * This ensures we get a cyrillic layout on ttys, but a latin layout by default
|
||
|
+ * in the UI.
|
||
|
+ */
|
||
|
+ g_variant_builder_init (&input_source_builder, G_VARIANT_TYPE ("a(ss)"));
|
||
|
+ if (type != NULL && id != NULL) {
|
||
|
+ add_input_source_to_arrays (self, type, id, layouts_array, variants_array);
|
||
|
+
|
||
|
+ if (gnome_input_source_is_non_latin (type, id)) {
|
||
|
+ default_input_source_id = g_strdup ("us");
|
||
|
+ add_input_source_to_arrays (self, "xkb", default_input_source_id, layouts_array, variants_array);
|
||
|
+ g_variant_builder_add (&input_source_builder, "(ss)", "xkb", default_input_source_id);
|
||
|
+ } else {
|
||
|
+ default_input_source_id = g_strdup (id);
|
||
|
+ }
|
||
|
|
||
|
- g_variant_builder_add (&builder, "(ss)", "xkb", sid);
|
||
|
+ g_variant_builder_add (&input_source_builder, "(ss)", type, id);
|
||
|
}
|
||
|
|
||
|
- if (!is_xkb_source)
|
||
|
- g_variant_builder_add (&builder, "(ss)", type, id);
|
||
|
+ if (default_input_source_id == NULL || !is_system_mode) {
|
||
|
+ add_defaults_to_variant_builder (self, type, id, &input_source_builder, &default_input_source_id);
|
||
|
+ }
|
||
|
+ input_sources = g_variant_builder_end (&input_source_builder);
|
||
|
+
|
||
|
+ for (i = 0; priv->default_options[i] != NULL; i++) {
|
||
|
+ g_variant_builder_add (&input_options_builder, "s", priv->default_options[i]);
|
||
|
+ }
|
||
|
+ input_options = g_variant_builder_end (&input_options_builder);
|
||
|
+
|
||
|
+ add_defaults_to_arrays (self, layouts_array, variants_array);
|
||
|
+ g_ptr_array_add (layouts_array, NULL);
|
||
|
+ g_ptr_array_add (variants_array, NULL);
|
||
|
+
|
||
|
+ priv->system_layouts = (char **) g_ptr_array_steal (layouts_array, NULL);
|
||
|
+ priv->system_variants = (char **) g_ptr_array_steal (variants_array, NULL);
|
||
|
|
||
|
- g_settings_set_value (priv->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
|
||
|
- g_settings_set_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE, 0);
|
||
|
+ g_variant_get (input_options, "^as", &priv->system_options);
|
||
|
+
|
||
|
+ g_settings_set_value (priv->input_settings, KEY_INPUT_SOURCES, g_steal_pointer (&input_sources));
|
||
|
+ g_settings_set_value (priv->input_settings, KEY_INPUT_OPTIONS, g_steal_pointer (&input_options));
|
||
|
+
|
||
|
+ if (default_input_source_id != NULL) {
|
||
|
+ GVariantBuilder mru_input_source_builder;
|
||
|
+
|
||
|
+ g_variant_builder_init (&mru_input_source_builder, G_VARIANT_TYPE ("a(ss)"));
|
||
|
+ g_variant_builder_add (&mru_input_source_builder, "(ss)", type, default_input_source_id);
|
||
|
+ g_settings_set_value (priv->input_settings, KEY_MRU_SOURCES, g_variant_builder_end (&mru_input_source_builder));
|
||
|
+ }
|
||
|
|
||
|
- g_settings_apply (priv->input_settings);
|
||
|
+ g_settings_apply (priv->input_settings);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
set_localed_input (GisKeyboardPage *self)
|
||
|
{
|
||
|
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
- const gchar *layout, *variant;
|
||
|
- GString *layouts;
|
||
|
- GString *variants;
|
||
|
- GSList *l;
|
||
|
+ g_autofree char *layouts = NULL;
|
||
|
+ g_autofree char *variants = NULL;
|
||
|
+ g_autofree char *options = NULL;
|
||
|
|
||
|
if (!priv->localed)
|
||
|
return;
|
||
|
|
||
|
- cc_input_chooser_get_layout (CC_INPUT_CHOOSER (priv->input_chooser), &layout, &variant);
|
||
|
- if (layout == NULL)
|
||
|
- layout = "";
|
||
|
- if (variant == NULL)
|
||
|
- variant = "";
|
||
|
-
|
||
|
- layouts = g_string_new (layout);
|
||
|
- variants = g_string_new (variant);
|
||
|
-
|
||
|
-#define LAYOUT(a) (a[0])
|
||
|
-#define VARIANT(a) (a[1] ? a[1] : "")
|
||
|
- for (l = priv->system_sources; l; l = l->next) {
|
||
|
- const gchar *sid = l->data;
|
||
|
- gchar **lv = g_strsplit (sid, "+", -1);
|
||
|
-
|
||
|
- if (!g_str_equal (LAYOUT (lv), layout) ||
|
||
|
- !g_str_equal (VARIANT (lv), variant)) {
|
||
|
- if (layouts->str[0]) {
|
||
|
- g_string_append_c (layouts, ',');
|
||
|
- g_string_append_c (variants, ',');
|
||
|
- }
|
||
|
- g_string_append (layouts, LAYOUT (lv));
|
||
|
- g_string_append (variants, VARIANT (lv));
|
||
|
- }
|
||
|
- g_strfreev (lv);
|
||
|
- }
|
||
|
-#undef LAYOUT
|
||
|
-#undef VARIANT
|
||
|
+ layouts = g_strjoinv (",", priv->system_layouts);
|
||
|
+ variants = g_strjoinv (",", priv->system_variants);
|
||
|
+ options = g_strjoinv (",", priv->system_options);
|
||
|
|
||
|
g_dbus_proxy_call (priv->localed,
|
||
|
"SetX11Keyboard",
|
||
|
- g_variant_new ("(ssssbb)", layouts->str, "", variants->str, "", TRUE, TRUE),
|
||
|
+ g_variant_new ("(ssssbb)", layouts, "", variants, options, TRUE, TRUE),
|
||
|
G_DBUS_CALL_FLAGS_NONE,
|
||
|
-1, NULL, NULL, NULL);
|
||
|
- g_string_free (layouts, TRUE);
|
||
|
- g_string_free (variants, TRUE);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -192,8 +293,13 @@ static void
|
||
|
update_input (GisKeyboardPage *self)
|
||
|
{
|
||
|
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
+ const gchar *type;
|
||
|
+ const gchar *id;
|
||
|
|
||
|
- set_input_settings (self);
|
||
|
+ type = cc_input_chooser_get_input_type (CC_INPUT_CHOOSER (priv->input_chooser));
|
||
|
+ id = cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser));
|
||
|
+
|
||
|
+ set_input_settings (self, type, id);
|
||
|
|
||
|
if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
|
||
|
if (g_permission_get_allowed (priv->permission)) {
|
||
|
@@ -215,119 +321,10 @@ gis_keyboard_page_apply (GisPage *page,
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
-static GSList *
|
||
|
-get_localed_input (GDBusProxy *proxy)
|
||
|
-{
|
||
|
- GVariant *v;
|
||
|
- const gchar *s;
|
||
|
- gchar *id;
|
||
|
- guint i, n;
|
||
|
- gchar **layouts = NULL;
|
||
|
- gchar **variants = NULL;
|
||
|
- GSList *sources = NULL;
|
||
|
-
|
||
|
- v = g_dbus_proxy_get_cached_property (proxy, "X11Layout");
|
||
|
- if (v) {
|
||
|
- s = g_variant_get_string (v, NULL);
|
||
|
- layouts = g_strsplit (s, ",", -1);
|
||
|
- g_variant_unref (v);
|
||
|
- }
|
||
|
-
|
||
|
- v = g_dbus_proxy_get_cached_property (proxy, "X11Variant");
|
||
|
- if (v) {
|
||
|
- s = g_variant_get_string (v, NULL);
|
||
|
- if (s && *s)
|
||
|
- variants = g_strsplit (s, ",", -1);
|
||
|
- g_variant_unref (v);
|
||
|
- }
|
||
|
-
|
||
|
- if (variants && variants[0])
|
||
|
- n = MIN (g_strv_length (layouts), g_strv_length (variants));
|
||
|
- else if (layouts && layouts[0])
|
||
|
- n = g_strv_length (layouts);
|
||
|
- else
|
||
|
- n = 0;
|
||
|
-
|
||
|
- for (i = 0; i < n && layouts[i][0]; i++) {
|
||
|
- if (variants && variants[i] && variants[i][0])
|
||
|
- id = g_strdup_printf ("%s+%s", layouts[i], variants[i]);
|
||
|
- else
|
||
|
- id = g_strdup (layouts[i]);
|
||
|
- sources = g_slist_prepend (sources, id);
|
||
|
- }
|
||
|
-
|
||
|
- g_strfreev (variants);
|
||
|
- g_strfreev (layouts);
|
||
|
-
|
||
|
- return sources;
|
||
|
-}
|
||
|
-
|
||
|
static void
|
||
|
-add_default_keyboard_layout (GDBusProxy *proxy,
|
||
|
- GVariantBuilder *builder)
|
||
|
+add_default_input_sources (GisKeyboardPage *self)
|
||
|
{
|
||
|
- GSList *sources = get_localed_input (proxy);
|
||
|
- sources = g_slist_reverse (sources);
|
||
|
-
|
||
|
- for (; sources; sources = sources->next)
|
||
|
- g_variant_builder_add (builder, "(ss)", "xkb",
|
||
|
- (const gchar *) sources->data);
|
||
|
-
|
||
|
- g_slist_free_full (sources, g_free);
|
||
|
-}
|
||
|
-
|
||
|
-static void
|
||
|
-add_default_input_sources (GisKeyboardPage *self,
|
||
|
- GDBusProxy *proxy)
|
||
|
-{
|
||
|
- const gchar *type;
|
||
|
- const gchar *id;
|
||
|
- gchar *language;
|
||
|
- GVariantBuilder builder;
|
||
|
- GSettings *input_settings;
|
||
|
-
|
||
|
- input_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
|
||
|
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
|
||
|
-
|
||
|
- add_default_keyboard_layout (proxy, &builder);
|
||
|
-
|
||
|
- /* add other input sources */
|
||
|
- language = cc_common_language_get_current_language ();
|
||
|
- if (gnome_get_input_source_from_locale (language, &type, &id)) {
|
||
|
- if (!g_str_equal (type, "xkb"))
|
||
|
- g_variant_builder_add (&builder, "(ss)", type, id);
|
||
|
- }
|
||
|
- g_free (language);
|
||
|
-
|
||
|
- g_settings_delay (input_settings);
|
||
|
- g_settings_set_value (input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
|
||
|
- g_settings_set_uint (input_settings, KEY_CURRENT_INPUT_SOURCE, 0);
|
||
|
- g_settings_apply (input_settings);
|
||
|
-
|
||
|
- g_object_unref (input_settings);
|
||
|
-}
|
||
|
-
|
||
|
-static void
|
||
|
-skip_proxy_ready (GObject *source,
|
||
|
- GAsyncResult *res,
|
||
|
- gpointer data)
|
||
|
-{
|
||
|
- GisKeyboardPage *self = data;
|
||
|
- GDBusProxy *proxy;
|
||
|
- GError *error = NULL;
|
||
|
-
|
||
|
- proxy = g_dbus_proxy_new_finish (res, &error);
|
||
|
-
|
||
|
- if (!proxy) {
|
||
|
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||
|
- g_warning ("Failed to contact localed: %s", error->message);
|
||
|
- g_error_free (error);
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- add_default_input_sources (self, proxy);
|
||
|
-
|
||
|
- g_object_unref (proxy);
|
||
|
+ set_input_settings (self, NULL, NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -336,77 +333,49 @@ gis_keyboard_page_skip (GisPage *page)
|
||
|
GisKeyboardPage *self = GIS_KEYBOARD_PAGE (page);
|
||
|
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
|
||
|
- g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||
|
- G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
|
||
|
- NULL,
|
||
|
- "org.freedesktop.locale1",
|
||
|
- "/org/freedesktop/locale1",
|
||
|
- "org.freedesktop.locale1",
|
||
|
- priv->cancellable,
|
||
|
- (GAsyncReadyCallback) skip_proxy_ready,
|
||
|
- self);
|
||
|
+ priv->should_skip = TRUE;
|
||
|
+
|
||
|
+ if (priv->default_input_source_ids != NULL)
|
||
|
+ add_default_input_sources (self);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
preselect_input_source (GisKeyboardPage *self)
|
||
|
{
|
||
|
- const gchar *type;
|
||
|
- const gchar *id;
|
||
|
- gchar *language;
|
||
|
- gboolean desktop_got_something;
|
||
|
- gboolean desktop_got_input_method;
|
||
|
+ const char *language = NULL;
|
||
|
|
||
|
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
- GSList *sources = get_localed_input (priv->localed);
|
||
|
-
|
||
|
- /* These will be added silently after the user selection when
|
||
|
- * writing out the settings. */
|
||
|
- g_slist_free_full (priv->system_sources, g_free);
|
||
|
- priv->system_sources = g_slist_reverse (sources);
|
||
|
-
|
||
|
- /* We have two potential sources of information as to which
|
||
|
- * source to pre-select here: the keyboard layout that is
|
||
|
- * configured system-wide (read from priv->system_sources),
|
||
|
- * and a gnome-desktop function that lets us look up a default
|
||
|
- * input source for a given language.
|
||
|
- *
|
||
|
- * An important limitation here is that there is no system-wide
|
||
|
- * configuration for input methods, so if the best choice for the
|
||
|
- * language is an input method, we will only find it from the
|
||
|
- * gnome-desktop lookup. But if both sources give us keyboard layouts,
|
||
|
- * we want to prefer the one that's configured system-wide over the one
|
||
|
- * from gnome-desktop.
|
||
|
- *
|
||
|
- * So we first do the gnome-desktop lookup, and keep track of what we
|
||
|
- * got.
|
||
|
- *
|
||
|
- * - If we got an input method, we preselect that, and we're done.
|
||
|
- * - If we got a keyboard layout, and there's no system-wide keyboard
|
||
|
- * layout set, we preselect the layout we got from gnome-desktop.
|
||
|
- * - If we didn't get an input method from gnome-desktop and there
|
||
|
- * is a system-wide keyboard layout set, we preselect that.
|
||
|
- * - If we got nothing from gnome-desktop and there's no system-wide
|
||
|
- * keyboard layout set, we don't preselect anything.
|
||
|
- *
|
||
|
- * See:
|
||
|
- * - https://bugzilla.gnome.org/show_bug.cgi?id=776189
|
||
|
- * - https://gitlab.gnome.org/GNOME/gnome-initial-setup/-/issues/104
|
||
|
- */
|
||
|
- language = cc_common_language_get_current_language ();
|
||
|
|
||
|
- desktop_got_something = gnome_get_input_source_from_locale (language, &type, &id);
|
||
|
- desktop_got_input_method = (desktop_got_something && g_strcmp0 (type, "xkb") != 0);
|
||
|
+ language = cc_common_language_get_current_language ();
|
||
|
|
||
|
- if (desktop_got_something && (desktop_got_input_method || !priv->system_sources)) {
|
||
|
- cc_input_chooser_set_input (CC_INPUT_CHOOSER (priv->input_chooser),
|
||
|
- id, type);
|
||
|
- } else if (priv->system_sources) {
|
||
|
- cc_input_chooser_set_input (CC_INPUT_CHOOSER (priv->input_chooser),
|
||
|
- (const gchar *) priv->system_sources->data,
|
||
|
- "xkb");
|
||
|
+ /* We deduce the initial input source from language if we're in a system mode
|
||
|
+ * (where preexisting system configuration may be stale) or if the language
|
||
|
+ * requires an input method (because there is no way for system configuration
|
||
|
+ * to denote the need for an input method)
|
||
|
+ *
|
||
|
+ * If it's a non-system mode we can trust the system configuration is probably
|
||
|
+ * a better bet than a heuristic based on locale.
|
||
|
+ */
|
||
|
+ if (language != NULL) {
|
||
|
+ gboolean got_input_source;
|
||
|
+ const char *id, *type;
|
||
|
+
|
||
|
+ got_input_source = gnome_get_input_source_from_locale (language, &type, &id);
|
||
|
+
|
||
|
+ if (got_input_source) {
|
||
|
+ gboolean is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER;
|
||
|
+ if (is_system_mode || g_str_equal (type, "ibus")) {
|
||
|
+ cc_input_chooser_set_input (CC_INPUT_CHOOSER (priv->input_chooser),
|
||
|
+ id,
|
||
|
+ type);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
- g_free (language);
|
||
|
+ cc_input_chooser_set_input (CC_INPUT_CHOOSER (priv->input_chooser),
|
||
|
+ priv->default_input_source_ids[0],
|
||
|
+ priv->default_input_source_types[0]);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -445,9 +414,7 @@ localed_proxy_ready (GObject *source,
|
||
|
}
|
||
|
|
||
|
priv->localed = proxy;
|
||
|
-
|
||
|
- preselect_input_source (self);
|
||
|
- update_page_complete (self);
|
||
|
+ update_page_complete (self);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -464,6 +431,40 @@ input_changed (CcInputChooser *chooser,
|
||
|
update_page_complete (self);
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+on_got_default_sources (GObject *source,
|
||
|
+ GAsyncResult *res,
|
||
|
+ gpointer data)
|
||
|
+{
|
||
|
+ GisKeyboardPage *self = data;
|
||
|
+ GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
+ g_autoptr (GError) error = NULL;
|
||
|
+ gboolean success = FALSE;
|
||
|
+ g_auto (GStrv) ids = NULL;
|
||
|
+ g_auto (GStrv) types = NULL;
|
||
|
+ g_auto (GStrv) options = NULL;
|
||
|
+
|
||
|
+ success = gnome_get_default_input_sources_finish (res, &ids, &types, &options, &error);
|
||
|
+
|
||
|
+ if (!success) {
|
||
|
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||
|
+ g_warning ("Failed to fetch default input sources: %s", error->message);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ priv->default_input_source_ids = g_steal_pointer (&ids);
|
||
|
+ priv->default_input_source_types = g_steal_pointer (&types);
|
||
|
+ priv->default_options = g_steal_pointer (&options);
|
||
|
+
|
||
|
+ if (priv->should_skip) {
|
||
|
+ add_default_input_sources (self);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ preselect_input_source (self);
|
||
|
+ update_page_complete (self);
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
gis_keyboard_page_constructed (GObject *object)
|
||
|
{
|
||
|
@@ -492,6 +493,8 @@ gis_keyboard_page_constructed (GObject *object)
|
||
|
(GAsyncReadyCallback) localed_proxy_ready,
|
||
|
self);
|
||
|
|
||
|
+ gnome_get_default_input_sources (priv->cancellable, on_got_default_sources, self);
|
||
|
+
|
||
|
/* If we're in new user mode then we're manipulating system settings */
|
||
|
if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER)
|
||
|
priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-keyboard", NULL, NULL, NULL);
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From b67c0d9a551891e88b969981d8cfcaa36eb8fed2 Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Sun, 13 Aug 2023 09:09:56 -0400
|
||
|
Subject: [PATCH 05/10] driver: Specify mode via flags instead of boolean
|
||
|
|
||
|
At the moment we just have system mode and new user mode,
|
||
|
but we're actually going to want other modes (such as
|
||
|
live user mode) as well.
|
||
|
|
||
|
Currently the code distinguishes between its two available
|
||
|
modes using a boolean `is_new_user`. That isn't extensible beyond
|
||
|
two modes, so this commit changes it use bit flags instead.
|
||
|
---
|
||
|
gnome-initial-setup/gis-driver.c | 17 ++-
|
||
|
gnome-initial-setup/gis-driver.h | 8 +-
|
||
|
gnome-initial-setup/gnome-initial-setup.c | 128 +++++++++++++---------
|
||
|
3 files changed, 93 insertions(+), 60 deletions(-)
|
||
|
|
||
|
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
|
||
|
index 98b4fc3e..d3013063 100644
|
||
|
--- a/gnome-initial-setup/gis-driver.c
|
||
|
+++ b/gnome-initial-setup/gis-driver.c
|
||
|
@@ -36,8 +36,6 @@
|
||
|
#include "cc-common-language.h"
|
||
|
#include "gis-assistant.h"
|
||
|
|
||
|
-#define GIS_TYPE_DRIVER_MODE (gis_driver_mode_get_type ())
|
||
|
-
|
||
|
/* Statically include this for now. Maybe later
|
||
|
* we'll generate this from glib-mkenums. */
|
||
|
GType
|
||
|
@@ -45,12 +43,13 @@ gis_driver_mode_get_type (void) {
|
||
|
static GType enum_type_id = 0;
|
||
|
if (G_UNLIKELY (!enum_type_id))
|
||
|
{
|
||
|
- static const GEnumValue values[] = {
|
||
|
+ static const GFlagsValue values[] = {
|
||
|
{ GIS_DRIVER_MODE_NEW_USER, "GIS_DRIVER_MODE_NEW_USER", "new_user" },
|
||
|
{ GIS_DRIVER_MODE_EXISTING_USER, "GIS_DRIVER_MODE_EXISTING_USER", "existing_user" },
|
||
|
+ { GIS_DRIVER_MODE_ALL, "GIS_DRIVER_MODE_ALL", "all" },
|
||
|
{ 0, NULL, NULL }
|
||
|
};
|
||
|
- enum_type_id = g_enum_register_static("GisDriverMode", values);
|
||
|
+ enum_type_id = g_flags_register_static("GisDriverMode", values);
|
||
|
}
|
||
|
return enum_type_id;
|
||
|
}
|
||
|
@@ -651,7 +650,7 @@ gis_driver_set_property (GObject *object,
|
||
|
switch ((GisDriverProperty) prop_id)
|
||
|
{
|
||
|
case PROP_MODE:
|
||
|
- driver->mode = g_value_get_enum (value);
|
||
|
+ driver->mode = g_value_get_flags (value);
|
||
|
break;
|
||
|
case PROP_USERNAME:
|
||
|
g_free (driver->username);
|
||
|
@@ -853,10 +852,10 @@ gis_driver_class_init (GisDriverClass *klass)
|
||
|
G_TYPE_NONE, 0);
|
||
|
|
||
|
obj_props[PROP_MODE] =
|
||
|
- g_param_spec_enum ("mode", "", "",
|
||
|
- GIS_TYPE_DRIVER_MODE,
|
||
|
- GIS_DRIVER_MODE_EXISTING_USER,
|
||
|
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||
|
+ g_param_spec_flags ("mode", "", "",
|
||
|
+ GIS_TYPE_DRIVER_MODE,
|
||
|
+ GIS_DRIVER_MODE_EXISTING_USER,
|
||
|
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||
|
|
||
|
obj_props[PROP_USERNAME] =
|
||
|
g_param_spec_string ("username", "", "",
|
||
|
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
|
||
|
index 9b935e24..b57db2e2 100644
|
||
|
--- a/gnome-initial-setup/gis-driver.h
|
||
|
+++ b/gnome-initial-setup/gis-driver.h
|
||
|
@@ -31,6 +31,7 @@
|
||
|
G_BEGIN_DECLS
|
||
|
|
||
|
#define GIS_TYPE_DRIVER (gis_driver_get_type ())
|
||
|
+#define GIS_TYPE_DRIVER_MODE (gis_driver_mode_get_type ())
|
||
|
|
||
|
G_DECLARE_FINAL_TYPE (GisDriver, gis_driver, GIS, DRIVER, AdwApplication)
|
||
|
|
||
|
@@ -41,10 +42,13 @@ typedef enum {
|
||
|
} UmAccountMode;
|
||
|
|
||
|
typedef enum {
|
||
|
- GIS_DRIVER_MODE_NEW_USER,
|
||
|
- GIS_DRIVER_MODE_EXISTING_USER,
|
||
|
+ GIS_DRIVER_MODE_NEW_USER = 1 << 0,
|
||
|
+ GIS_DRIVER_MODE_EXISTING_USER = 1 << 1,
|
||
|
+ GIS_DRIVER_MODE_ALL = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
} GisDriverMode;
|
||
|
|
||
|
+GType gis_driver_mode_get_type (void);
|
||
|
+
|
||
|
GisAssistant *gis_driver_get_assistant (GisDriver *driver);
|
||
|
|
||
|
void gis_driver_set_user_permissions (GisDriver *driver,
|
||
|
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
index 113ded36..59955779 100644
|
||
|
--- a/gnome-initial-setup/gnome-initial-setup.c
|
||
|
+++ b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
@@ -56,27 +56,27 @@ typedef GisPage *(*PreparePage) (GisDriver *driver);
|
||
|
typedef struct {
|
||
|
const gchar *page_id;
|
||
|
PreparePage prepare_page_func;
|
||
|
- gboolean new_user_only;
|
||
|
+ GisDriverMode modes;
|
||
|
} PageData;
|
||
|
|
||
|
-#define PAGE(name, new_user_only) { #name, gis_prepare_ ## name ## _page, new_user_only }
|
||
|
+#define PAGE(name, modes) { #name, gis_prepare_ ## name ## _page, modes }
|
||
|
|
||
|
static PageData page_table[] = {
|
||
|
- PAGE (welcome, FALSE),
|
||
|
- PAGE (language, FALSE),
|
||
|
- PAGE (keyboard, FALSE),
|
||
|
- PAGE (network, FALSE),
|
||
|
- PAGE (privacy, FALSE),
|
||
|
- PAGE (timezone, TRUE),
|
||
|
- PAGE (software, TRUE),
|
||
|
- PAGE (goa, FALSE),
|
||
|
- PAGE (account, TRUE),
|
||
|
- PAGE (password, TRUE),
|
||
|
+ PAGE (welcome, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (language, GIS_DRIVER_MODE_ALL),
|
||
|
+ PAGE (keyboard, GIS_DRIVER_MODE_ALL),
|
||
|
+ PAGE (network, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (privacy, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (timezone, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (software, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (goa, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (account, GIS_DRIVER_MODE_NEW_USER),
|
||
|
+ PAGE (password, GIS_DRIVER_MODE_NEW_USER),
|
||
|
#ifdef HAVE_PARENTAL_CONTROLS
|
||
|
- PAGE (parental_controls, TRUE),
|
||
|
- PAGE (parent_password, TRUE),
|
||
|
+ PAGE (parental_controls, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (parent_password, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
#endif
|
||
|
- PAGE (summary, FALSE),
|
||
|
+ PAGE (summary, GIS_DRIVER_MODE_NEW_USER),
|
||
|
{ NULL },
|
||
|
};
|
||
|
|
||
|
@@ -107,26 +107,15 @@ should_skip_page (const gchar *page_id,
|
||
|
}
|
||
|
|
||
|
static gchar **
|
||
|
-strv_append (gchar **a,
|
||
|
- gchar **b)
|
||
|
+pages_to_skip_from_file (GisDriver *driver)
|
||
|
{
|
||
|
- guint n = g_strv_length (a);
|
||
|
- guint m = g_strv_length (b);
|
||
|
-
|
||
|
- a = g_renew (gchar *, a, n + m + 1);
|
||
|
- for (guint i = 0; i < m; i++)
|
||
|
- a[n + i] = g_strdup (b[i]);
|
||
|
- a[n + m] = NULL;
|
||
|
-
|
||
|
- return a;
|
||
|
-}
|
||
|
-
|
||
|
-static gchar **
|
||
|
-pages_to_skip_from_file (GisDriver *driver,
|
||
|
- gboolean is_new_user)
|
||
|
-{
|
||
|
- GStrv skip_pages = NULL;
|
||
|
- GStrv additional_skip_pages = NULL;
|
||
|
+ GisDriverMode driver_mode;
|
||
|
+ GisDriverMode other_modes;
|
||
|
+ g_autoptr(GStrvBuilder) builder = g_strv_builder_new();
|
||
|
+ g_auto (GStrv) skip_pages = NULL;
|
||
|
+ g_autofree char *mode_group = NULL;
|
||
|
+ g_autoptr (GFlagsClass) driver_mode_flags_class = NULL;
|
||
|
+ const GFlagsValue *driver_mode_flags = NULL;
|
||
|
|
||
|
/* This code will read the keyfile containing vendor customization options and
|
||
|
* look for options under the "pages" group, and supports the following keys:
|
||
|
@@ -134,28 +123,68 @@ pages_to_skip_from_file (GisDriver *driver,
|
||
|
* - new_user_only (optional): list of pages to be skipped in existing user mode
|
||
|
* - existing_user_only (optional): list of pages to be skipped in new user mode
|
||
|
*
|
||
|
+ * In addition it will look for options under the "{mode} pages" group where {mode} is the
|
||
|
+ * current driver mode for the following keys:
|
||
|
+ * - skip (optional): list of pages to be skipped for the current mode
|
||
|
+ *
|
||
|
* This is how this file might look on a vendor image:
|
||
|
*
|
||
|
* [pages]
|
||
|
* skip=timezone
|
||
|
+ *
|
||
|
+ * [new_user pages]
|
||
|
+ * skip=language;keyboard
|
||
|
+ *
|
||
|
+ * Older files might look like so:
|
||
|
+ *
|
||
|
+ * [pages]
|
||
|
+ * skip=timezone
|
||
|
* existing_user_only=language;keyboard
|
||
|
*/
|
||
|
|
||
|
skip_pages = gis_driver_conf_get_string_list (driver, VENDOR_PAGES_GROUP,
|
||
|
VENDOR_SKIP_KEY, NULL);
|
||
|
- additional_skip_pages =
|
||
|
- gis_driver_conf_get_string_list (driver, VENDOR_PAGES_GROUP,
|
||
|
- is_new_user ? VENDOR_EXISTING_USER_ONLY_KEY : VENDOR_NEW_USER_ONLY_KEY,
|
||
|
- NULL);
|
||
|
-
|
||
|
- if (!skip_pages && additional_skip_pages) {
|
||
|
- skip_pages = additional_skip_pages;
|
||
|
- } else if (skip_pages && additional_skip_pages) {
|
||
|
- skip_pages = strv_append (skip_pages, additional_skip_pages);
|
||
|
- g_strfreev (additional_skip_pages);
|
||
|
+ if (skip_pages != NULL)
|
||
|
+ {
|
||
|
+ g_strv_builder_addv (builder, (const char **) skip_pages);
|
||
|
+ g_clear_pointer (&skip_pages, g_strfreev);
|
||
|
+ }
|
||
|
+
|
||
|
+ driver_mode_flags_class = g_type_class_ref (GIS_TYPE_DRIVER_MODE);
|
||
|
+
|
||
|
+ driver_mode = gis_driver_get_mode (driver);
|
||
|
+ driver_mode_flags = g_flags_get_first_value (driver_mode_flags_class, driver_mode);
|
||
|
+
|
||
|
+ mode_group = g_strdup_printf ("%s pages", driver_mode_flags->value_nick);
|
||
|
+ skip_pages = gis_driver_conf_get_string_list (driver, mode_group,
|
||
|
+ VENDOR_SKIP_KEY, NULL);
|
||
|
+ if (skip_pages != NULL)
|
||
|
+ {
|
||
|
+ g_strv_builder_addv (builder, (const char **) skip_pages);
|
||
|
+ g_clear_pointer (&skip_pages, g_strfreev);
|
||
|
+ }
|
||
|
+
|
||
|
+ other_modes = GIS_DRIVER_MODE_ALL & ~driver_mode;
|
||
|
+ while (other_modes) {
|
||
|
+ const GFlagsValue *other_mode_flags = g_flags_get_first_value (driver_mode_flags_class, other_modes);
|
||
|
+
|
||
|
+ if (other_mode_flags != NULL) {
|
||
|
+ g_autofree char *vendor_key = g_strdup_printf ("%s_only", other_mode_flags->value_nick);
|
||
|
+
|
||
|
+ skip_pages = gis_driver_conf_get_string_list (driver, VENDOR_PAGES_GROUP,
|
||
|
+ vendor_key, NULL);
|
||
|
+
|
||
|
+ if (skip_pages != NULL)
|
||
|
+ {
|
||
|
+ g_strv_builder_addv (builder, (const char **) skip_pages);
|
||
|
+ g_clear_pointer (&skip_pages, g_strfreev);
|
||
|
+ }
|
||
|
+
|
||
|
+ other_modes &= ~other_mode_flags->value;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
- return skip_pages;
|
||
|
+ return g_strv_builder_end (builder);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -198,7 +227,8 @@ rebuild_pages_cb (GisDriver *driver)
|
||
|
GisAssistant *assistant;
|
||
|
GisPage *current_page;
|
||
|
gchar **skip_pages;
|
||
|
- gboolean is_new_user, skipped;
|
||
|
+ GisDriverMode driver_mode;
|
||
|
+ gboolean skipped;
|
||
|
|
||
|
assistant = gis_driver_get_assistant (driver);
|
||
|
current_page = gis_assistant_get_current_page (assistant);
|
||
|
@@ -217,13 +247,13 @@ rebuild_pages_cb (GisDriver *driver)
|
||
|
++page_data;
|
||
|
}
|
||
|
|
||
|
- is_new_user = (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER);
|
||
|
- skip_pages = pages_to_skip_from_file (driver, is_new_user);
|
||
|
+ driver_mode = gis_driver_get_mode (driver);
|
||
|
+ skip_pages = pages_to_skip_from_file (driver);
|
||
|
|
||
|
for (; page_data->page_id != NULL; ++page_data) {
|
||
|
skipped = FALSE;
|
||
|
|
||
|
- if ((page_data->new_user_only && !is_new_user) ||
|
||
|
+ if (((page_data->modes & driver_mode) == 0) ||
|
||
|
(should_skip_page (page_data->page_id, skip_pages)))
|
||
|
skipped = TRUE;
|
||
|
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 5d02f9f885d370e587f5620d03820cce4118d340 Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Wed, 30 Aug 2023 15:08:23 -0400
|
||
|
Subject: [PATCH 06/10] assistant: Show Back button on summary page
|
||
|
|
||
|
commit f60b4622350468f7ef17f79d9bc6679bf8cce7b9 changed the
|
||
|
assistant to no longer show the back and forward buttons on the
|
||
|
last page.
|
||
|
|
||
|
Hiding the forward button makes sense: there's no more pages go
|
||
|
to.
|
||
|
|
||
|
Hiding the back button doesn't really make sense: there are a
|
||
|
bunch of pages the user could potentially want to revisit.
|
||
|
|
||
|
This commit shows the back button on the last page (either
|
||
|
the summary page or the install page).
|
||
|
---
|
||
|
gnome-initial-setup/gis-assistant.c | 14 +++++++++-----
|
||
|
.../pages/summary/gis-summary-page.c | 16 +++++++++-------
|
||
|
2 files changed, 18 insertions(+), 12 deletions(-)
|
||
|
|
||
|
diff --git a/gnome-initial-setup/gis-assistant.c b/gnome-initial-setup/gis-assistant.c
|
||
|
index a3122b71..8a7fc52b 100644
|
||
|
--- a/gnome-initial-setup/gis-assistant.c
|
||
|
+++ b/gnome-initial-setup/gis-assistant.c
|
||
|
@@ -59,6 +59,8 @@ struct _GisAssistant
|
||
|
|
||
|
GList *pages;
|
||
|
GisPage *current_page;
|
||
|
+
|
||
|
+ gboolean data_saved;
|
||
|
};
|
||
|
|
||
|
G_DEFINE_TYPE (GisAssistant, gis_assistant, GTK_TYPE_BOX)
|
||
|
@@ -182,6 +184,7 @@ update_navigation_buttons (GisAssistant *assistant)
|
||
|
{
|
||
|
GisPage *page = assistant->current_page;
|
||
|
GList *l;
|
||
|
+ gboolean is_first_page;
|
||
|
gboolean is_last_page;
|
||
|
|
||
|
if (page == NULL)
|
||
|
@@ -189,11 +192,13 @@ update_navigation_buttons (GisAssistant *assistant)
|
||
|
|
||
|
l = g_list_find (assistant->pages, page);
|
||
|
|
||
|
+ is_first_page = (l->prev == NULL);
|
||
|
is_last_page = (l->next == NULL);
|
||
|
|
||
|
+ gtk_widget_set_visible (assistant->back, !is_first_page && !assistant->data_saved);
|
||
|
+
|
||
|
if (is_last_page)
|
||
|
{
|
||
|
- gtk_widget_set_visible (assistant->back, FALSE);
|
||
|
gtk_widget_set_visible (assistant->forward, FALSE);
|
||
|
gtk_widget_set_visible (assistant->skip, FALSE);
|
||
|
gtk_widget_set_visible (assistant->cancel, FALSE);
|
||
|
@@ -201,12 +206,8 @@ update_navigation_buttons (GisAssistant *assistant)
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- gboolean is_first_page;
|
||
|
GtkWidget *next_widget;
|
||
|
|
||
|
- is_first_page = (l->prev == NULL);
|
||
|
- gtk_widget_set_visible (assistant->back, !is_first_page);
|
||
|
-
|
||
|
if (gis_page_get_needs_accept (page))
|
||
|
next_widget = assistant->accept;
|
||
|
else
|
||
|
@@ -418,6 +419,9 @@ gis_assistant_save_data (GisAssistant *assistant,
|
||
|
{
|
||
|
GList *l;
|
||
|
|
||
|
+ assistant->data_saved = TRUE;
|
||
|
+ gtk_widget_set_visible (assistant->back, FALSE);
|
||
|
+
|
||
|
for (l = assistant->pages; l != NULL; l = l->next)
|
||
|
{
|
||
|
if (!gis_page_save_data (l->data, error))
|
||
|
diff --git a/gnome-initial-setup/pages/summary/gis-summary-page.c b/gnome-initial-setup/pages/summary/gis-summary-page.c
|
||
|
index 0aee2dad..8a526b64 100644
|
||
|
--- a/gnome-initial-setup/pages/summary/gis-summary-page.c
|
||
|
+++ b/gnome-initial-setup/pages/summary/gis-summary-page.c
|
||
|
@@ -180,6 +180,15 @@ log_user_in (GisSummaryPage *page)
|
||
|
static void
|
||
|
done_cb (GtkButton *button, GisSummaryPage *page)
|
||
|
{
|
||
|
+ g_autoptr (GError) error = NULL;
|
||
|
+
|
||
|
+ if (!gis_driver_save_data (GIS_PAGE (page)->driver, &error))
|
||
|
+ {
|
||
|
+ /* FIXME: This should probably be shown to the user and some options
|
||
|
+ * provided to them. */
|
||
|
+ g_warning ("Error saving data: %s", error->message);
|
||
|
+ }
|
||
|
+
|
||
|
gis_ensure_stamp_files (GIS_PAGE (page)->driver);
|
||
|
|
||
|
switch (gis_driver_get_mode (GIS_PAGE (page)->driver))
|
||
|
@@ -202,13 +211,6 @@ gis_summary_page_shown (GisPage *page)
|
||
|
GisSummaryPagePrivate *priv = gis_summary_page_get_instance_private (summary);
|
||
|
g_autoptr(GError) local_error = NULL;
|
||
|
|
||
|
- if (!gis_driver_save_data (GIS_PAGE (page)->driver, &local_error))
|
||
|
- {
|
||
|
- /* FIXME: This should probably be shown to the user and some options
|
||
|
- * provided to them. */
|
||
|
- g_warning ("Error saving data: %s", local_error->message);
|
||
|
- }
|
||
|
-
|
||
|
gis_driver_get_user_permissions (GIS_PAGE (page)->driver,
|
||
|
&priv->user_account,
|
||
|
&priv->user_password);
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From af751585cd5d124e7de19ab9e1b08d4cd925c6c3 Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Sun, 13 Aug 2023 09:39:07 -0400
|
||
|
Subject: [PATCH 07/10] gnome-initial-setup: Add live user mode
|
||
|
|
||
|
This commit adds a new "live user" mode meant to be run in live image
|
||
|
environments.
|
||
|
|
||
|
It asks questions the user should answer before the installer is
|
||
|
started, and provides a way for the user to initiate the installer
|
||
|
or just jump into the live session instead.
|
||
|
---
|
||
|
data/20-gnome-initial-setup.rules.in | 3 +-
|
||
|
gnome-initial-setup/gis-driver.c | 4 +-
|
||
|
gnome-initial-setup/gis-driver.h | 4 +-
|
||
|
gnome-initial-setup/gis-util.c | 122 ++++++
|
||
|
gnome-initial-setup/gis-util.h | 4 +
|
||
|
gnome-initial-setup/gnome-initial-setup.c | 26 +-
|
||
|
.../pages/account/gis-account-pages.c | 21 +
|
||
|
.../pages/install/gis-install-page.c | 382 ++++++++++++++++++
|
||
|
.../pages/install/gis-install-page.css | 11 +
|
||
|
.../pages/install/gis-install-page.h | 52 +++
|
||
|
.../pages/install/gis-install-page.ui | 51 +++
|
||
|
.../pages/install/install.gresource.xml | 8 +
|
||
|
gnome-initial-setup/pages/install/meson.build | 9 +
|
||
|
.../pages/keyboard/gis-keyboard-page.c | 10 +-
|
||
|
.../pages/language/gis-language-page.c | 5 +-
|
||
|
gnome-initial-setup/pages/meson.build | 1 +
|
||
|
.../pages/password/gis-password-page.c | 6 +
|
||
|
17 files changed, 701 insertions(+), 18 deletions(-)
|
||
|
create mode 100644 gnome-initial-setup/pages/install/gis-install-page.c
|
||
|
create mode 100644 gnome-initial-setup/pages/install/gis-install-page.css
|
||
|
create mode 100644 gnome-initial-setup/pages/install/gis-install-page.h
|
||
|
create mode 100644 gnome-initial-setup/pages/install/gis-install-page.ui
|
||
|
create mode 100644 gnome-initial-setup/pages/install/install.gresource.xml
|
||
|
create mode 100644 gnome-initial-setup/pages/install/meson.build
|
||
|
|
||
|
diff --git a/data/20-gnome-initial-setup.rules.in b/data/20-gnome-initial-setup.rules.in
|
||
|
index 02fd21d0..881efde9 100644
|
||
|
--- a/data/20-gnome-initial-setup.rules.in
|
||
|
+++ b/data/20-gnome-initial-setup.rules.in
|
||
|
@@ -16,7 +16,8 @@ polkit.addRule(function(action, subject) {
|
||
|
action.id.indexOf('org.freedesktop.timedate1.') === 0 ||
|
||
|
action.id.indexOf('org.freedesktop.realmd.') === 0 ||
|
||
|
action.id.indexOf('com.endlessm.ParentalControls.') === 0 ||
|
||
|
- action.id.indexOf('org.fedoraproject.thirdparty.') === 0);
|
||
|
+ action.id.indexOf('org.fedoraproject.thirdparty.') === 0 ||
|
||
|
+ action.id.indexOf('org.freedesktop.login1.reboot') === 0);
|
||
|
|
||
|
if (actionMatches) {
|
||
|
if (subject.local)
|
||
|
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
|
||
|
index d3013063..b18a3808 100644
|
||
|
--- a/gnome-initial-setup/gis-driver.c
|
||
|
+++ b/gnome-initial-setup/gis-driver.c
|
||
|
@@ -46,6 +46,8 @@ gis_driver_mode_get_type (void) {
|
||
|
static const GFlagsValue values[] = {
|
||
|
{ GIS_DRIVER_MODE_NEW_USER, "GIS_DRIVER_MODE_NEW_USER", "new_user" },
|
||
|
{ GIS_DRIVER_MODE_EXISTING_USER, "GIS_DRIVER_MODE_EXISTING_USER", "existing_user" },
|
||
|
+ { GIS_DRIVER_MODE_LIVE_USER, "GIS_DRIVER_MODE_LIVE_USER", "live_user" },
|
||
|
+ { GIS_DRIVER_MODE_SYSTEM, "GIS_DRIVER_MODE_SYSTEM", "system" },
|
||
|
{ GIS_DRIVER_MODE_ALL, "GIS_DRIVER_MODE_ALL", "all" },
|
||
|
{ 0, NULL, NULL }
|
||
|
};
|
||
|
@@ -791,7 +793,7 @@ gis_driver_startup (GApplication *app)
|
||
|
webkit_web_context_set_sandbox_enabled (context, TRUE);
|
||
|
#endif
|
||
|
|
||
|
- if (driver->mode == GIS_DRIVER_MODE_NEW_USER)
|
||
|
+ if (driver->mode & GIS_DRIVER_MODE_SYSTEM)
|
||
|
connect_to_gdm (driver);
|
||
|
|
||
|
driver->main_window = g_object_new (GTK_TYPE_APPLICATION_WINDOW,
|
||
|
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
|
||
|
index b57db2e2..aedb9a73 100644
|
||
|
--- a/gnome-initial-setup/gis-driver.h
|
||
|
+++ b/gnome-initial-setup/gis-driver.h
|
||
|
@@ -44,7 +44,9 @@ typedef enum {
|
||
|
typedef enum {
|
||
|
GIS_DRIVER_MODE_NEW_USER = 1 << 0,
|
||
|
GIS_DRIVER_MODE_EXISTING_USER = 1 << 1,
|
||
|
- GIS_DRIVER_MODE_ALL = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ GIS_DRIVER_MODE_LIVE_USER = 1 << 2,
|
||
|
+ GIS_DRIVER_MODE_SYSTEM = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER),
|
||
|
+ GIS_DRIVER_MODE_ALL = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_LIVE_USER),
|
||
|
} GisDriverMode;
|
||
|
|
||
|
GType gis_driver_mode_get_type (void);
|
||
|
diff --git a/gnome-initial-setup/gis-util.c b/gnome-initial-setup/gis-util.c
|
||
|
index ac153fc1..424c26d7 100644
|
||
|
--- a/gnome-initial-setup/gis-util.c
|
||
|
+++ b/gnome-initial-setup/gis-util.c
|
||
|
@@ -31,3 +31,125 @@ gis_add_style_from_resource (const char *resource_path)
|
||
|
GTK_STYLE_PROVIDER (provider),
|
||
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||
|
}
|
||
|
+
|
||
|
+gboolean
|
||
|
+gis_kernel_command_line_has_argument (const char *arguments[])
|
||
|
+{
|
||
|
+ GError *error = NULL;
|
||
|
+ g_autofree char *contents = NULL;
|
||
|
+ g_autoptr (GString) pattern = NULL;
|
||
|
+ gboolean has_argument = FALSE;
|
||
|
+ size_t i;
|
||
|
+
|
||
|
+ if (!g_file_get_contents ("/proc/cmdline", &contents, NULL, &error)) {
|
||
|
+ g_error_free (error);
|
||
|
+ return FALSE;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Build up the pattern by iterating through the alternatives,
|
||
|
+ * escaping all dots so they don't match any character but period,
|
||
|
+ * and adding word boundary specifiers around the arguments so
|
||
|
+ * substrings don't get matched.
|
||
|
+ *
|
||
|
+ * Also, add a | between each alternative.
|
||
|
+ */
|
||
|
+ pattern = g_string_new (NULL);
|
||
|
+ for (i = 0; arguments[i] != NULL; i++) {
|
||
|
+ g_autofree char *escaped_argument = g_regex_escape_string (arguments[i], -1);
|
||
|
+
|
||
|
+ if (i > 0) {
|
||
|
+ g_string_append (pattern, "|");
|
||
|
+ }
|
||
|
+
|
||
|
+ g_string_append (pattern, "\\b");
|
||
|
+
|
||
|
+ g_string_append (pattern, escaped_argument);
|
||
|
+
|
||
|
+ g_string_append (pattern, "\\b");
|
||
|
+ }
|
||
|
+
|
||
|
+ has_argument = g_regex_match_simple (pattern->str, contents, 0, 0);
|
||
|
+
|
||
|
+ return has_argument;
|
||
|
+}
|
||
|
+
|
||
|
+static gboolean
|
||
|
+is_valid_shell_identifier_character (char c,
|
||
|
+ gboolean first)
|
||
|
+{
|
||
|
+ return (!first && g_ascii_isdigit (c)) ||
|
||
|
+ c == '_' ||
|
||
|
+ g_ascii_isalpha (c);
|
||
|
+}
|
||
|
+
|
||
|
+void
|
||
|
+gis_substitute_variables_in_text (char **text,
|
||
|
+ GisVariableLookupFunc lookup_func,
|
||
|
+ gpointer user_data)
|
||
|
+{
|
||
|
+ GString *s = g_string_new ("");
|
||
|
+ const char *p, *start;
|
||
|
+ char c;
|
||
|
+
|
||
|
+ p = *text;
|
||
|
+ while (*p) {
|
||
|
+ c = *p;
|
||
|
+ if (c == '\\') {
|
||
|
+ p++;
|
||
|
+ c = *p;
|
||
|
+ if (c != '\0') {
|
||
|
+ p++;
|
||
|
+ switch (c) {
|
||
|
+ case '\\':
|
||
|
+ g_string_append_c (s, '\\');
|
||
|
+ break;
|
||
|
+ case '$':
|
||
|
+ g_string_append_c (s, '$');
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ g_string_append_c (s, '\\');
|
||
|
+ g_string_append_c (s, c);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } else if (c == '$') {
|
||
|
+ gboolean brackets = FALSE;
|
||
|
+ p++;
|
||
|
+ if (*p == '{') {
|
||
|
+ brackets = TRUE;
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+ start = p;
|
||
|
+ while (*p != '\0' &&
|
||
|
+ is_valid_shell_identifier_character (*p, p == start)) {
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+ if (p == start || (brackets && *p != '}')) {
|
||
|
+ g_string_append_c (s, '$');
|
||
|
+ if (brackets)
|
||
|
+ g_string_append_c (s, '{');
|
||
|
+ g_string_append_len (s, start, p - start);
|
||
|
+ } else {
|
||
|
+ g_autofree char *variable = NULL;
|
||
|
+ g_autofree char *value = NULL;
|
||
|
+
|
||
|
+ variable = g_strndup (start, p - start);
|
||
|
+
|
||
|
+ if (brackets && *p == '}')
|
||
|
+ p++;
|
||
|
+
|
||
|
+ if (lookup_func)
|
||
|
+ value = lookup_func (variable, user_data);
|
||
|
+ if (value) {
|
||
|
+ g_string_append (s, value);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ p++;
|
||
|
+ g_string_append_c (s, c);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ g_free (*text);
|
||
|
+ *text = g_string_free (s, FALSE);
|
||
|
+}
|
||
|
+
|
||
|
diff --git a/gnome-initial-setup/gis-util.h b/gnome-initial-setup/gis-util.h
|
||
|
index 5041bddd..80d4f9a0 100644
|
||
|
--- a/gnome-initial-setup/gis-util.h
|
||
|
+++ b/gnome-initial-setup/gis-util.h
|
||
|
@@ -17,3 +17,7 @@
|
||
|
#pragma once
|
||
|
|
||
|
void gis_add_style_from_resource (const char *path);
|
||
|
+gboolean gis_kernel_command_line_has_argument (const char *arguments[]);
|
||
|
+
|
||
|
+typedef char * (* GisVariableLookupFunc) (const char *key, gpointer user_data);
|
||
|
+void gis_substitute_variables_in_text (char **text, GisVariableLookupFunc lookup_func, gpointer user_data);
|
||
|
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
index 59955779..bc7a4ee9 100644
|
||
|
--- a/gnome-initial-setup/gnome-initial-setup.c
|
||
|
+++ b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
@@ -41,13 +41,16 @@
|
||
|
#include "pages/parental-controls/gis-parental-controls-page.h"
|
||
|
#include "pages/password/gis-password-page.h"
|
||
|
#include "pages/summary/gis-summary-page.h"
|
||
|
+#include "pages/install/gis-install-page.h"
|
||
|
|
||
|
#define VENDOR_PAGES_GROUP "pages"
|
||
|
#define VENDOR_SKIP_KEY "skip"
|
||
|
#define VENDOR_NEW_USER_ONLY_KEY "new_user_only"
|
||
|
#define VENDOR_EXISTING_USER_ONLY_KEY "existing_user_only"
|
||
|
+#define VENDOR_LIVE_USER_ONLY_KEY "live_user_only"
|
||
|
|
||
|
static gboolean force_existing_user_mode;
|
||
|
+static gboolean force_live_user_mode;
|
||
|
|
||
|
static GPtrArray *skipped_pages;
|
||
|
|
||
|
@@ -65,18 +68,20 @@ static PageData page_table[] = {
|
||
|
PAGE (welcome, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
PAGE (language, GIS_DRIVER_MODE_ALL),
|
||
|
PAGE (keyboard, GIS_DRIVER_MODE_ALL),
|
||
|
- PAGE (network, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (network, GIS_DRIVER_MODE_ALL),
|
||
|
PAGE (privacy, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
- PAGE (timezone, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
+ PAGE (timezone, GIS_DRIVER_MODE_ALL),
|
||
|
PAGE (software, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
PAGE (goa, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
- PAGE (account, GIS_DRIVER_MODE_NEW_USER),
|
||
|
- PAGE (password, GIS_DRIVER_MODE_NEW_USER),
|
||
|
+ /* In live user mode, the account page isn't displayed, it just quietly creates the live user */
|
||
|
+ PAGE (account, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER),
|
||
|
+ PAGE (password, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER),
|
||
|
#ifdef HAVE_PARENTAL_CONTROLS
|
||
|
PAGE (parental_controls, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
PAGE (parent_password, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
|
||
|
#endif
|
||
|
PAGE (summary, GIS_DRIVER_MODE_NEW_USER),
|
||
|
+ PAGE (install, GIS_DRIVER_MODE_LIVE_USER),
|
||
|
{ NULL },
|
||
|
};
|
||
|
|
||
|
@@ -120,8 +125,8 @@ pages_to_skip_from_file (GisDriver *driver)
|
||
|
/* This code will read the keyfile containing vendor customization options and
|
||
|
* look for options under the "pages" group, and supports the following keys:
|
||
|
* - skip (optional): list of pages to be skipped always
|
||
|
- * - new_user_only (optional): list of pages to be skipped in existing user mode
|
||
|
- * - existing_user_only (optional): list of pages to be skipped in new user mode
|
||
|
+ * - new_user_only (optional): list of pages to be skipped for modes other than new_user
|
||
|
+ * - existing_user_only (optional): list of pages to be skipped for modes other than existing_user
|
||
|
*
|
||
|
* In addition it will look for options under the "{mode} pages" group where {mode} is the
|
||
|
* current driver mode for the following keys:
|
||
|
@@ -277,6 +282,8 @@ get_mode (void)
|
||
|
{
|
||
|
if (force_existing_user_mode)
|
||
|
return GIS_DRIVER_MODE_EXISTING_USER;
|
||
|
+ else if (force_live_user_mode)
|
||
|
+ return GIS_DRIVER_MODE_LIVE_USER;
|
||
|
else
|
||
|
return GIS_DRIVER_MODE_NEW_USER;
|
||
|
}
|
||
|
@@ -310,6 +317,8 @@ main (int argc, char *argv[])
|
||
|
GOptionEntry entries[] = {
|
||
|
{ "existing-user", 0, 0, G_OPTION_ARG_NONE, &force_existing_user_mode,
|
||
|
_("Force existing user mode"), NULL },
|
||
|
+ { "live-user", 0, 0, G_OPTION_ARG_NONE, &force_live_user_mode,
|
||
|
+ _("Force live user mode"), NULL },
|
||
|
{ NULL }
|
||
|
};
|
||
|
|
||
|
@@ -328,6 +337,9 @@ main (int argc, char *argv[])
|
||
|
|
||
|
g_option_context_parse (context, &argc, &argv, NULL);
|
||
|
|
||
|
+ if (gis_kernel_command_line_has_argument ((const char *[]) { "rd.live.image", "endless.live_boot", NULL }))
|
||
|
+ force_live_user_mode = TRUE;
|
||
|
+
|
||
|
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||
|
textdomain (GETTEXT_PACKAGE);
|
||
|
@@ -346,7 +358,7 @@ main (int argc, char *argv[])
|
||
|
* the keyring manually so that we can pass the credentials
|
||
|
* along to the new user in the handoff.
|
||
|
*/
|
||
|
- if (mode == GIS_DRIVER_MODE_NEW_USER && !gis_get_mock_mode ())
|
||
|
+ if ((mode & GIS_DRIVER_MODE_SYSTEM) && !gis_get_mock_mode ())
|
||
|
gis_ensure_login_keyring ();
|
||
|
|
||
|
driver = gis_driver_new (mode);
|
||
|
diff --git a/gnome-initial-setup/pages/account/gis-account-pages.c b/gnome-initial-setup/pages/account/gis-account-pages.c
|
||
|
index d9cc8d9f..8b0d8e99 100644
|
||
|
--- a/gnome-initial-setup/pages/account/gis-account-pages.c
|
||
|
+++ b/gnome-initial-setup/pages/account/gis-account-pages.c
|
||
|
@@ -26,6 +26,27 @@
|
||
|
GisPage *
|
||
|
gis_prepare_account_page (GisDriver *driver)
|
||
|
{
|
||
|
+ GisDriverMode driver_mode;
|
||
|
+
|
||
|
+ driver_mode = gis_driver_get_mode (driver);
|
||
|
+
|
||
|
+ if (driver_mode == GIS_DRIVER_MODE_LIVE_USER && !gis_kernel_command_line_has_argument ((const char *[]) { "rd.live.overlay", NULL })) {
|
||
|
+ ActUserManager *act_client = act_user_manager_get_default ();
|
||
|
+ const char *username = "liveuser";
|
||
|
+ g_autoptr(ActUser) user = NULL;
|
||
|
+ g_autoptr(GError) error = NULL;
|
||
|
+
|
||
|
+ user = act_user_manager_create_user (act_client, username, username, ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR, &error);
|
||
|
+
|
||
|
+ if (user != NULL) {
|
||
|
+ act_user_set_password_mode (user, ACT_USER_PASSWORD_MODE_NONE);
|
||
|
+ gis_driver_set_username (driver, username);
|
||
|
+ gis_driver_set_account_mode (driver, UM_LOCAL);
|
||
|
+ gis_driver_set_user_permissions (driver, user, NULL);
|
||
|
+ }
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
return g_object_new (GIS_TYPE_ACCOUNT_PAGE,
|
||
|
"driver", driver,
|
||
|
NULL);
|
||
|
diff --git a/gnome-initial-setup/pages/install/gis-install-page.c b/gnome-initial-setup/pages/install/gis-install-page.c
|
||
|
new file mode 100644
|
||
|
index 00000000..36ed7539
|
||
|
--- /dev/null
|
||
|
+++ b/gnome-initial-setup/pages/install/gis-install-page.c
|
||
|
@@ -0,0 +1,382 @@
|
||
|
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||
|
+/*
|
||
|
+ * Copyright (C) 2023 Red Hat
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or
|
||
|
+ * modify it under the terms of the GNU General Public License as
|
||
|
+ * published by the Free Software Foundation; either version 2 of the
|
||
|
+ * License, or (at your option) any later version.
|
||
|
+ *
|
||
|
+ * This program is distributed in the hope that it will be useful, but
|
||
|
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ * General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
|
+ */
|
||
|
+
|
||
|
+/* Install page {{{1 */
|
||
|
+
|
||
|
+#define PAGE_ID "install"
|
||
|
+
|
||
|
+#include "config.h"
|
||
|
+#include "cc-common-language.h"
|
||
|
+#include "gis-install-page.h"
|
||
|
+#include "gis-pkexec.h"
|
||
|
+
|
||
|
+#include <glib/gstdio.h>
|
||
|
+#include <glib/gi18n.h>
|
||
|
+#include <gio/gio.h>
|
||
|
+#include <gio/gdesktopappinfo.h>
|
||
|
+#include <stdlib.h>
|
||
|
+#include <errno.h>
|
||
|
+
|
||
|
+#include <act/act-user-manager.h>
|
||
|
+
|
||
|
+#define SERVICE_NAME "gdm-password"
|
||
|
+#define VENDOR_INSTALLER_GROUP "install"
|
||
|
+#define VENDOR_APPLICATION_KEY "application"
|
||
|
+
|
||
|
+struct _GisInstallPagePrivate {
|
||
|
+ GtkWidget *try_button;
|
||
|
+ GtkWidget *install_button;
|
||
|
+ AdwStatusPage *status_page;
|
||
|
+ GDesktopAppInfo *installer;
|
||
|
+
|
||
|
+ ActUser *user_account;
|
||
|
+ const gchar *user_password;
|
||
|
+};
|
||
|
+typedef struct _GisInstallPagePrivate GisInstallPagePrivate;
|
||
|
+
|
||
|
+G_DEFINE_TYPE_WITH_PRIVATE (GisInstallPage, gis_install_page, GIS_TYPE_PAGE);
|
||
|
+
|
||
|
+static void
|
||
|
+request_info_query (GisInstallPage *page,
|
||
|
+ GdmUserVerifier *user_verifier,
|
||
|
+ const char *question,
|
||
|
+ gboolean is_secret)
|
||
|
+{
|
||
|
+ /* TODO: pop up modal dialog */
|
||
|
+ g_debug ("user verifier asks%s question: %s",
|
||
|
+ is_secret ? " secret" : "",
|
||
|
+ question);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_info (GdmUserVerifier *user_verifier,
|
||
|
+ const char *service_name,
|
||
|
+ const char *info,
|
||
|
+ GisInstallPage *page)
|
||
|
+{
|
||
|
+ g_debug ("PAM module info: %s", info);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_problem (GdmUserVerifier *user_verifier,
|
||
|
+ const char *service_name,
|
||
|
+ const char *problem,
|
||
|
+ GisInstallPage *page)
|
||
|
+{
|
||
|
+ g_warning ("PAM module error: %s", problem);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_info_query (GdmUserVerifier *user_verifier,
|
||
|
+ const char *service_name,
|
||
|
+ const char *question,
|
||
|
+ GisInstallPage *page)
|
||
|
+{
|
||
|
+ request_info_query (page, user_verifier, question, FALSE);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_secret_info_query (GdmUserVerifier *user_verifier,
|
||
|
+ const char *service_name,
|
||
|
+ const char *question,
|
||
|
+ GisInstallPage *page)
|
||
|
+{
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
|
||
|
+ gboolean should_send_password = priv->user_password != NULL;
|
||
|
+
|
||
|
+ g_debug ("PAM module secret info query: %s", question);
|
||
|
+ if (should_send_password) {
|
||
|
+ g_debug ("sending password\n");
|
||
|
+ gdm_user_verifier_call_answer_query (user_verifier,
|
||
|
+ service_name,
|
||
|
+ priv->user_password,
|
||
|
+ NULL, NULL, NULL);
|
||
|
+ priv->user_password = NULL;
|
||
|
+ } else {
|
||
|
+ request_info_query (page, user_verifier, question, TRUE);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_session_opened (GdmGreeter *greeter,
|
||
|
+ const char *service_name,
|
||
|
+ GisInstallPage *page)
|
||
|
+{
|
||
|
+ gdm_greeter_call_start_session_when_ready_sync (greeter, service_name,
|
||
|
+ TRUE, NULL, NULL);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+log_user_in (GisInstallPage *page)
|
||
|
+{
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
|
||
|
+ g_autoptr(GError) error = NULL;
|
||
|
+ GdmGreeter *greeter = NULL;
|
||
|
+ GdmUserVerifier *user_verifier = NULL;
|
||
|
+
|
||
|
+ if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver,
|
||
|
+ &greeter, &user_verifier)) {
|
||
|
+ g_warning ("No GDM connection; not initiating login");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ g_signal_connect (user_verifier, "info",
|
||
|
+ G_CALLBACK (on_info), page);
|
||
|
+ g_signal_connect (user_verifier, "problem",
|
||
|
+ G_CALLBACK (on_problem), page);
|
||
|
+ g_signal_connect (user_verifier, "info-query",
|
||
|
+ G_CALLBACK (on_info_query), page);
|
||
|
+ g_signal_connect (user_verifier, "secret-info-query",
|
||
|
+ G_CALLBACK (on_secret_info_query), page);
|
||
|
+
|
||
|
+ g_signal_connect (greeter, "session-opened",
|
||
|
+ G_CALLBACK (on_session_opened), page);
|
||
|
+
|
||
|
+ gdm_user_verifier_call_begin_verification_for_user_sync (user_verifier,
|
||
|
+ SERVICE_NAME,
|
||
|
+ act_user_get_user_name (priv->user_account),
|
||
|
+ NULL, &error);
|
||
|
+
|
||
|
+ if (error != NULL)
|
||
|
+ g_warning ("Could not begin verification: %s", error->message);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_try_button_clicked (GtkButton *button,
|
||
|
+ GisInstallPage *page)
|
||
|
+{
|
||
|
+
|
||
|
+ g_autoptr (GError) error = NULL;
|
||
|
+
|
||
|
+ if (!gis_driver_save_data (GIS_PAGE (page)->driver, &error))
|
||
|
+ g_warning ("Error saving data: %s", error->message);
|
||
|
+
|
||
|
+ gis_ensure_stamp_files (GIS_PAGE (page)->driver);
|
||
|
+
|
||
|
+ gis_driver_hide_window (GIS_PAGE (page)->driver);
|
||
|
+ log_user_in (page);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_installer_exited (GPid pid,
|
||
|
+ int exit_status,
|
||
|
+ gpointer user_data)
|
||
|
+{
|
||
|
+ g_autoptr (GError) error = NULL;
|
||
|
+ g_autoptr(GSubprocessLauncher) launcher = NULL;
|
||
|
+ g_autoptr(GSubprocess) subprocess = NULL;
|
||
|
+ gboolean started_to_reboot;
|
||
|
+
|
||
|
+ launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP);
|
||
|
+
|
||
|
+ g_subprocess_launcher_unsetenv (launcher, "SHELL");
|
||
|
+
|
||
|
+ subprocess = g_subprocess_launcher_spawn (launcher, &error, "systemctl", "reboot", NULL);
|
||
|
+
|
||
|
+ if (subprocess == NULL) {
|
||
|
+ g_warning ("Failed to initiate reboot: %s\n", error->message);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ started_to_reboot = g_subprocess_wait (subprocess, NULL, &error);
|
||
|
+
|
||
|
+ if (!started_to_reboot) {
|
||
|
+ g_warning ("Failed to reboot: %s\n", error->message);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_installer_started (GDesktopAppInfo *appinfo,
|
||
|
+ GPid pid,
|
||
|
+ gpointer user_data)
|
||
|
+{
|
||
|
+ g_child_watch_add (pid, on_installer_exited, user_data);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+run_installer (GisInstallPage *page)
|
||
|
+{
|
||
|
+ g_autoptr (GError) error = NULL;
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
|
||
|
+ gboolean installer_launched;
|
||
|
+ g_autoptr (GAppLaunchContext) launch_context = NULL;
|
||
|
+ g_autofree char *language = NULL;
|
||
|
+
|
||
|
+ if (!gis_driver_save_data (GIS_PAGE (page)->driver, &error))
|
||
|
+ g_warning ("Error saving data: %s", error->message);
|
||
|
+
|
||
|
+ gis_ensure_stamp_files (GIS_PAGE (page)->driver);
|
||
|
+
|
||
|
+ launch_context = g_app_launch_context_new ();
|
||
|
+
|
||
|
+ g_app_launch_context_unsetenv (launch_context, "SHELL");
|
||
|
+
|
||
|
+ language = cc_common_language_get_current_language ();
|
||
|
+
|
||
|
+ if (language != NULL)
|
||
|
+ g_app_launch_context_setenv (launch_context, "LANG", language);
|
||
|
+
|
||
|
+ installer_launched = g_desktop_app_info_launch_uris_as_manager (priv->installer,
|
||
|
+ NULL,
|
||
|
+ launch_context,
|
||
|
+ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_CHILD_INHERITS_STDERR | G_SPAWN_CHILD_INHERITS_STDOUT | G_SPAWN_SEARCH_PATH,
|
||
|
+ NULL,
|
||
|
+ NULL,
|
||
|
+ on_installer_started,
|
||
|
+ page,
|
||
|
+ &error);
|
||
|
+
|
||
|
+ if (!installer_launched)
|
||
|
+ g_warning ("Could not launch installer: %s", error->message);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+on_install_button_clicked (GtkButton *button,
|
||
|
+ GisInstallPage *page)
|
||
|
+{
|
||
|
+ gis_driver_hide_window (GIS_PAGE (page)->driver);
|
||
|
+ run_installer (page);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+gis_install_page_shown (GisPage *page)
|
||
|
+{
|
||
|
+ GisInstallPage *install = GIS_INSTALL_PAGE (page);
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (install);
|
||
|
+ g_autoptr(GError) local_error = NULL;
|
||
|
+
|
||
|
+ gis_driver_get_user_permissions (GIS_PAGE (page)->driver,
|
||
|
+ &priv->user_account,
|
||
|
+ &priv->user_password);
|
||
|
+
|
||
|
+ gtk_widget_grab_focus (priv->install_button);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+update_distro_name (GisInstallPage *page)
|
||
|
+{
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
|
||
|
+ g_autofree char *text = NULL;
|
||
|
+
|
||
|
+ text = g_strdup (adw_status_page_get_description (priv->status_page));
|
||
|
+ gis_substitute_variables_in_text (&text, (GisVariableLookupFunc) g_get_os_info, NULL);
|
||
|
+ adw_status_page_set_description (priv->status_page, text);
|
||
|
+ g_clear_pointer (&text, g_free);
|
||
|
+
|
||
|
+ text = g_strdup (gtk_button_get_label (GTK_BUTTON (priv->try_button)));
|
||
|
+ gis_substitute_variables_in_text (&text, (GisVariableLookupFunc) g_get_os_info, NULL);
|
||
|
+ gtk_button_set_label (GTK_BUTTON (priv->try_button), text);
|
||
|
+ g_clear_pointer (&text, g_free);
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static void
|
||
|
+apply_stylesheet (GisInstallPage *page)
|
||
|
+{
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
|
||
|
+ g_autoptr (GtkCssProvider) css_provider = gtk_css_provider_new();
|
||
|
+
|
||
|
+ gtk_widget_add_css_class (GTK_WIDGET (priv->status_page), "override-icon-size");
|
||
|
+ gtk_widget_add_css_class (GTK_WIDGET (priv->status_page), "override-button-line-height");
|
||
|
+
|
||
|
+ gtk_css_provider_load_from_resource (css_provider, "/org/gnome/initial-setup/gis-install-page.css");
|
||
|
+
|
||
|
+ gtk_style_context_add_provider_for_display (gtk_widget_get_display (GTK_WIDGET (priv->status_page)),
|
||
|
+ GTK_STYLE_PROVIDER (css_provider),
|
||
|
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||
|
+}
|
||
|
+
|
||
|
+static gboolean
|
||
|
+find_installer (GisInstallPage *page)
|
||
|
+{
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
|
||
|
+ g_autofree char *desktop_file = NULL;
|
||
|
+
|
||
|
+ desktop_file = gis_driver_conf_get_string (GIS_PAGE (page)->driver,
|
||
|
+ VENDOR_INSTALLER_GROUP,
|
||
|
+ VENDOR_APPLICATION_KEY);
|
||
|
+
|
||
|
+ if (!desktop_file)
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
+ priv->installer = g_desktop_app_info_new (desktop_file);
|
||
|
+
|
||
|
+ return priv->installer != NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+gis_install_page_constructed (GObject *object)
|
||
|
+{
|
||
|
+ GisInstallPage *page = GIS_INSTALL_PAGE (object);
|
||
|
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
|
||
|
+
|
||
|
+ G_OBJECT_CLASS (gis_install_page_parent_class)->constructed (object);
|
||
|
+
|
||
|
+ if (!find_installer (page))
|
||
|
+ gtk_widget_set_sensitive (priv->install_button, FALSE);
|
||
|
+
|
||
|
+ apply_stylesheet (page);
|
||
|
+ update_distro_name (page);
|
||
|
+ g_signal_connect (priv->try_button, "clicked", G_CALLBACK (on_try_button_clicked), page);
|
||
|
+ g_signal_connect (priv->install_button, "clicked", G_CALLBACK (on_install_button_clicked), page);
|
||
|
+
|
||
|
+ gis_page_set_complete (GIS_PAGE (page), TRUE);
|
||
|
+
|
||
|
+ gtk_widget_set_visible (GTK_WIDGET (page), TRUE);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+gis_install_page_locale_changed (GisPage *page)
|
||
|
+{
|
||
|
+ g_autofree char *title = g_strdup (_("Install ${PRETTY_NAME}"));
|
||
|
+ gis_substitute_variables_in_text (&title, (GisVariableLookupFunc) g_get_os_info, NULL);
|
||
|
+ gis_page_set_title (page, title);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+gis_install_page_class_init (GisInstallPageClass *klass)
|
||
|
+{
|
||
|
+ GisPageClass *page_class = GIS_PAGE_CLASS (klass);
|
||
|
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
|
+
|
||
|
+ gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/initial-setup/gis-install-page.ui");
|
||
|
+
|
||
|
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisInstallPage, try_button);
|
||
|
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisInstallPage, install_button);
|
||
|
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisInstallPage, status_page);
|
||
|
+
|
||
|
+ page_class->page_id = PAGE_ID;
|
||
|
+ page_class->locale_changed = gis_install_page_locale_changed;
|
||
|
+ page_class->shown = gis_install_page_shown;
|
||
|
+ object_class->constructed = gis_install_page_constructed;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+gis_install_page_init (GisInstallPage *page)
|
||
|
+{
|
||
|
+ gtk_widget_init_template (GTK_WIDGET (page));
|
||
|
+}
|
||
|
+
|
||
|
+GisPage *
|
||
|
+gis_prepare_install_page (GisDriver *driver)
|
||
|
+{
|
||
|
+ return g_object_new (GIS_TYPE_INSTALL_PAGE,
|
||
|
+ "driver", driver,
|
||
|
+ NULL);
|
||
|
+}
|
||
|
diff --git a/gnome-initial-setup/pages/install/gis-install-page.css b/gnome-initial-setup/pages/install/gis-install-page.css
|
||
|
new file mode 100644
|
||
|
index 00000000..f3583b33
|
||
|
--- /dev/null
|
||
|
+++ b/gnome-initial-setup/pages/install/gis-install-page.css
|
||
|
@@ -0,0 +1,11 @@
|
||
|
+.override-icon-size image {
|
||
|
+ -gtk-icon-size: 70px;
|
||
|
+}
|
||
|
+
|
||
|
+.override-button-line-height button {
|
||
|
+ line-height: 1.75;
|
||
|
+}
|
||
|
+
|
||
|
+.description {
|
||
|
+ line-height: 1.25;
|
||
|
+}
|
||
|
diff --git a/gnome-initial-setup/pages/install/gis-install-page.h b/gnome-initial-setup/pages/install/gis-install-page.h
|
||
|
new file mode 100644
|
||
|
index 00000000..292427d8
|
||
|
--- /dev/null
|
||
|
+++ b/gnome-initial-setup/pages/install/gis-install-page.h
|
||
|
@@ -0,0 +1,52 @@
|
||
|
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||
|
+/*
|
||
|
+ * Copyright (C) 2023 Red Hat
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or
|
||
|
+ * modify it under the terms of the GNU General Public License as
|
||
|
+ * published by the Free Software Foundation; either version 2 of the
|
||
|
+ * License, or (at your option) any later version.
|
||
|
+ *
|
||
|
+ * This program is distributed in the hope that it will be useful, but
|
||
|
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ * General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
|
+ */
|
||
|
+
|
||
|
+#ifndef __GIS_INSTALL_PAGE_H__
|
||
|
+#define __GIS_INSTALL_PAGE_H__
|
||
|
+
|
||
|
+#include "gnome-initial-setup.h"
|
||
|
+
|
||
|
+G_BEGIN_DECLS
|
||
|
+
|
||
|
+#define GIS_TYPE_INSTALL_PAGE (gis_install_page_get_type ())
|
||
|
+#define GIS_INSTALL_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_INSTALL_PAGE, GisInstallPage))
|
||
|
+#define GIS_INSTALL_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_INSTALL_PAGE, GisInstallPageClass))
|
||
|
+#define GIS_IS_INSTALL_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_INSTALL_PAGE))
|
||
|
+#define GIS_IS_INSTALL_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_INSTALL_PAGE))
|
||
|
+#define GIS_INSTALL_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_INSTALL_PAGE, GisInstallPageClass))
|
||
|
+
|
||
|
+typedef struct _GisInstallPage GisInstallPage;
|
||
|
+typedef struct _GisInstallPageClass GisInstallPageClass;
|
||
|
+
|
||
|
+struct _GisInstallPage
|
||
|
+{
|
||
|
+ GisPage parent;
|
||
|
+};
|
||
|
+
|
||
|
+struct _GisInstallPageClass
|
||
|
+{
|
||
|
+ GisPageClass parent_class;
|
||
|
+};
|
||
|
+
|
||
|
+GType gis_install_page_get_type (void);
|
||
|
+
|
||
|
+GisPage *gis_prepare_install_page (GisDriver *driver);
|
||
|
+
|
||
|
+G_END_DECLS
|
||
|
+
|
||
|
+#endif /* __GIS_INSTALL_PAGE_H__ */
|
||
|
diff --git a/gnome-initial-setup/pages/install/gis-install-page.ui b/gnome-initial-setup/pages/install/gis-install-page.ui
|
||
|
new file mode 100644
|
||
|
index 00000000..c9ed5c88
|
||
|
--- /dev/null
|
||
|
+++ b/gnome-initial-setup/pages/install/gis-install-page.ui
|
||
|
@@ -0,0 +1,51 @@
|
||
|
+<?xml version="1.0" encoding="UTF-8"?>
|
||
|
+<interface>
|
||
|
+ <template class="GisInstallPage" parent="GisPage">
|
||
|
+ <child>
|
||
|
+ <object class="AdwStatusPage" id="status_page">
|
||
|
+ <property name="icon-name">document-save-symbolic</property>
|
||
|
+ <property name="title" translatable="yes">Try or Install?</property>
|
||
|
+ <property name="description" translatable="yes">You can try a temporary version of ${NAME} without making changes to the computer. If you decide to install later, just launch the installer from the Activities view.
|
||
|
+
|
||
|
+ Alternatively, choose install to launch the installer.</property>
|
||
|
+
|
||
|
+ <child>
|
||
|
+ <object class="GtkButton" id="start_button">
|
||
|
+ <property name="use_underline">True</property>
|
||
|
+ <property name="halign">center</property>
|
||
|
+ <style>
|
||
|
+ <class name="suggested-action"/>
|
||
|
+ <class name="pill"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ </child>
|
||
|
+
|
||
|
+ <child>
|
||
|
+ <object class="GtkBox" id="button_box">
|
||
|
+ <property name="orientation">horizontal</property>
|
||
|
+ <property name="homogeneous">True</property>
|
||
|
+ <property name="spacing">24</property>
|
||
|
+ <property name="halign">center</property>
|
||
|
+ <child>
|
||
|
+ <object class="GtkButton" id="try_button">
|
||
|
+ <property name="label" translatable="yes">Try ${NAME}</property>
|
||
|
+ <style>
|
||
|
+ <class name="pill"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ </child>
|
||
|
+ <child>
|
||
|
+ <object class="GtkButton" id="install_button">
|
||
|
+ <property name="label" translatable="yes">Install to Disk…</property>
|
||
|
+ <style>
|
||
|
+ <class name="suggested-action"/>
|
||
|
+ <class name="pill"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ </child>
|
||
|
+ </object>
|
||
|
+ </child>
|
||
|
+ </object>
|
||
|
+ </child>
|
||
|
+ </template>
|
||
|
+</interface>
|
||
|
diff --git a/gnome-initial-setup/pages/install/install.gresource.xml b/gnome-initial-setup/pages/install/install.gresource.xml
|
||
|
new file mode 100644
|
||
|
index 00000000..15391108
|
||
|
--- /dev/null
|
||
|
+++ b/gnome-initial-setup/pages/install/install.gresource.xml
|
||
|
@@ -0,0 +1,8 @@
|
||
|
+<?xml version="1.0" encoding="UTF-8"?>
|
||
|
+<gresources>
|
||
|
+ <gresource prefix="/org/gnome/initial-setup">
|
||
|
+ <file preprocess="xml-stripblanks" alias="gis-install-page.ui">gis-install-page.ui</file>
|
||
|
+ <file alias="gis-install-page.css">gis-install-page.css</file>
|
||
|
+ </gresource>
|
||
|
+</gresources>
|
||
|
+
|
||
|
diff --git a/gnome-initial-setup/pages/install/meson.build b/gnome-initial-setup/pages/install/meson.build
|
||
|
new file mode 100644
|
||
|
index 00000000..e5084e5e
|
||
|
--- /dev/null
|
||
|
+++ b/gnome-initial-setup/pages/install/meson.build
|
||
|
@@ -0,0 +1,9 @@
|
||
|
+sources += gnome.compile_resources(
|
||
|
+ 'install-resources',
|
||
|
+ files('install.gresource.xml'),
|
||
|
+ c_name: 'install'
|
||
|
+)
|
||
|
+sources += files(
|
||
|
+ 'gis-install-page.c',
|
||
|
+ 'gis-install-page.h'
|
||
|
+)
|
||
|
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
index f2bfe164..7801667c 100644
|
||
|
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
|
||
|
@@ -187,7 +187,7 @@ set_input_settings (GisKeyboardPage *self,
|
||
|
|
||
|
g_variant_builder_init (&input_options_builder, G_VARIANT_TYPE ("as"));
|
||
|
|
||
|
- is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER;
|
||
|
+ is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM;
|
||
|
|
||
|
layouts_array = g_ptr_array_new ();
|
||
|
variants_array = g_ptr_array_new ();
|
||
|
@@ -301,7 +301,7 @@ update_input (GisKeyboardPage *self)
|
||
|
|
||
|
set_input_settings (self, type, id);
|
||
|
|
||
|
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
|
||
|
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM) {
|
||
|
if (g_permission_get_allowed (priv->permission)) {
|
||
|
set_localed_input (self);
|
||
|
} else if (g_permission_get_can_acquire (priv->permission)) {
|
||
|
@@ -363,7 +363,7 @@ preselect_input_source (GisKeyboardPage *self)
|
||
|
got_input_source = gnome_get_input_source_from_locale (language, &type, &id);
|
||
|
|
||
|
if (got_input_source) {
|
||
|
- gboolean is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER;
|
||
|
+ gboolean is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM;
|
||
|
if (is_system_mode || g_str_equal (type, "ibus")) {
|
||
|
cc_input_chooser_set_input (CC_INPUT_CHOOSER (priv->input_chooser),
|
||
|
id,
|
||
|
@@ -384,7 +384,7 @@ update_page_complete (GisKeyboardPage *self)
|
||
|
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
|
||
|
gboolean complete;
|
||
|
|
||
|
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
|
||
|
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM) {
|
||
|
complete = (priv->localed != NULL &&
|
||
|
cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser)) != NULL);
|
||
|
} else {
|
||
|
@@ -496,7 +496,7 @@ gis_keyboard_page_constructed (GObject *object)
|
||
|
gnome_get_default_input_sources (priv->cancellable, on_got_default_sources, self);
|
||
|
|
||
|
/* If we're in new user mode then we're manipulating system settings */
|
||
|
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER)
|
||
|
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM)
|
||
|
priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-keyboard", NULL, NULL, NULL);
|
||
|
|
||
|
update_page_complete (self);
|
||
|
diff --git a/gnome-initial-setup/pages/language/gis-language-page.c b/gnome-initial-setup/pages/language/gis-language-page.c
|
||
|
index 26a01257..17117fa1 100644
|
||
|
--- a/gnome-initial-setup/pages/language/gis-language-page.c
|
||
|
+++ b/gnome-initial-setup/pages/language/gis-language-page.c
|
||
|
@@ -145,7 +145,7 @@ language_changed (CcLanguageChooser *chooser,
|
||
|
gis_driver_set_user_language (driver, priv->new_locale_id, TRUE);
|
||
|
gtk_widget_set_default_direction (gtk_get_locale_direction ());
|
||
|
|
||
|
- if (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER) {
|
||
|
+ if (gis_driver_get_mode (driver) & GIS_DRIVER_MODE_SYSTEM) {
|
||
|
|
||
|
gis_page_set_complete (GIS_PAGE (page), FALSE);
|
||
|
|
||
|
@@ -257,8 +257,7 @@ gis_language_page_constructed (GObject *object)
|
||
|
g_signal_connect (priv->language_chooser, "confirm",
|
||
|
G_CALLBACK (language_confirmed), page);
|
||
|
|
||
|
- /* If we're in new user mode then we're manipulating system settings */
|
||
|
- if (gis_driver_get_mode (GIS_PAGE (page)->driver) == GIS_DRIVER_MODE_NEW_USER)
|
||
|
+ if (gis_driver_get_mode (GIS_PAGE (page)->driver) & GIS_DRIVER_MODE_SYSTEM)
|
||
|
{
|
||
|
priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, NULL);
|
||
|
|
||
|
diff --git a/gnome-initial-setup/pages/meson.build b/gnome-initial-setup/pages/meson.build
|
||
|
index 32305018..5ac4a80d 100644
|
||
|
--- a/gnome-initial-setup/pages/meson.build
|
||
|
+++ b/gnome-initial-setup/pages/meson.build
|
||
|
@@ -1,5 +1,6 @@
|
||
|
pages = [
|
||
|
'account',
|
||
|
+ 'install',
|
||
|
'language',
|
||
|
'keyboard',
|
||
|
'network',
|
||
|
diff --git a/gnome-initial-setup/pages/password/gis-password-page.c b/gnome-initial-setup/pages/password/gis-password-page.c
|
||
|
index 6c12ca38..3d648c48 100644
|
||
|
--- a/gnome-initial-setup/pages/password/gis-password-page.c
|
||
|
+++ b/gnome-initial-setup/pages/password/gis-password-page.c
|
||
|
@@ -491,6 +491,12 @@ gis_password_page_init (GisPasswordPage *page)
|
||
|
GisPage *
|
||
|
gis_prepare_password_page (GisDriver *driver)
|
||
|
{
|
||
|
+ GisDriverMode driver_mode;
|
||
|
+
|
||
|
+ driver_mode = gis_driver_get_mode (driver);
|
||
|
+ if (driver_mode == GIS_DRIVER_MODE_LIVE_USER && !gis_kernel_command_line_has_argument ((const char *[]) { "rd.live.overlay", NULL }))
|
||
|
+ return NULL;
|
||
|
+
|
||
|
return g_object_new (GIS_TYPE_PASSWORD_PAGE,
|
||
|
"driver", driver,
|
||
|
NULL);
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 8c4075568fc25c5bb98e8e69e8b2a976541e5577 Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Wed, 16 Aug 2023 10:47:13 -0400
|
||
|
Subject: [PATCH 08/10] initial-setup: Don't show duplicated pages between
|
||
|
modes
|
||
|
|
||
|
It's possible a user just got asked questions in live mode
|
||
|
before install that they'll then get asked again on first
|
||
|
boot when the initial user is created.
|
||
|
|
||
|
This commit tracks that information so it doesn't get reasked.
|
||
|
---
|
||
|
data/meson.build | 6 +++
|
||
|
gnome-initial-setup/gis-driver.c | 3 ++
|
||
|
gnome-initial-setup/gnome-initial-setup.c | 65 +++++++++++++++++++++++
|
||
|
meson.build | 4 ++
|
||
|
4 files changed, 78 insertions(+)
|
||
|
|
||
|
diff --git a/data/meson.build b/data/meson.build
|
||
|
index 6a4ef7df..0bfccf56 100644
|
||
|
--- a/data/meson.build
|
||
|
+++ b/data/meson.build
|
||
|
@@ -130,3 +130,9 @@ configure_file(
|
||
|
|
||
|
mode_dir = join_paths(data_dir, 'gnome-shell', 'modes')
|
||
|
install_data('initial-setup.json', install_dir: mode_dir)
|
||
|
+
|
||
|
+install_subdir(
|
||
|
+ 'gnome-initial-setup',
|
||
|
+ install_dir : working_dir,
|
||
|
+ strip_directory : true
|
||
|
+)
|
||
|
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
|
||
|
index b18a3808..41cd6e38 100644
|
||
|
--- a/gnome-initial-setup/gis-driver.c
|
||
|
+++ b/gnome-initial-setup/gis-driver.c
|
||
|
@@ -107,6 +107,8 @@ struct _GisDriver {
|
||
|
|
||
|
const gchar *vendor_conf_file_path;
|
||
|
GKeyFile *vendor_conf_file;
|
||
|
+
|
||
|
+ GKeyFile *state_file;
|
||
|
};
|
||
|
|
||
|
G_DEFINE_TYPE (GisDriver, gis_driver, ADW_TYPE_APPLICATION)
|
||
|
@@ -137,6 +139,7 @@ gis_driver_finalize (GObject *object)
|
||
|
|
||
|
g_clear_object (&driver->user_account);
|
||
|
g_clear_pointer (&driver->vendor_conf_file, g_key_file_free);
|
||
|
+ g_clear_pointer (&driver->state_file, g_key_file_free);
|
||
|
|
||
|
g_clear_object (&driver->parent_account);
|
||
|
g_free (driver->parent_password);
|
||
|
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
index bc7a4ee9..2bd2d375 100644
|
||
|
--- a/gnome-initial-setup/gnome-initial-setup.c
|
||
|
+++ b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
@@ -49,6 +49,8 @@
|
||
|
#define VENDOR_EXISTING_USER_ONLY_KEY "existing_user_only"
|
||
|
#define VENDOR_LIVE_USER_ONLY_KEY "live_user_only"
|
||
|
|
||
|
+#define STATE_FILE GIS_WORKING_DIR "/state"
|
||
|
+
|
||
|
static gboolean force_existing_user_mode;
|
||
|
static gboolean force_live_user_mode;
|
||
|
|
||
|
@@ -121,6 +123,7 @@ pages_to_skip_from_file (GisDriver *driver)
|
||
|
g_autofree char *mode_group = NULL;
|
||
|
g_autoptr (GFlagsClass) driver_mode_flags_class = NULL;
|
||
|
const GFlagsValue *driver_mode_flags = NULL;
|
||
|
+ g_autoptr (GError) error = NULL;
|
||
|
|
||
|
/* This code will read the keyfile containing vendor customization options and
|
||
|
* look for options under the "pages" group, and supports the following keys:
|
||
|
@@ -189,6 +192,26 @@ pages_to_skip_from_file (GisDriver *driver)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ /* Also, if this is a system mode, we check if the user already answered questions earlier in
|
||
|
+ * a different system mode, and skip those pages too.
|
||
|
+ */
|
||
|
+ if (driver_mode & GIS_DRIVER_MODE_NEW_USER) {
|
||
|
+ g_autoptr(GKeyFile) state = NULL;
|
||
|
+ gboolean state_loaded;
|
||
|
+
|
||
|
+ state = g_key_file_new ();
|
||
|
+ state_loaded = g_key_file_load_from_file (state, STATE_FILE, G_KEY_FILE_NONE, &error);
|
||
|
+
|
||
|
+ if (state_loaded) {
|
||
|
+ skip_pages = g_key_file_get_string_list (state, VENDOR_PAGES_GROUP, VENDOR_SKIP_KEY, NULL, NULL);
|
||
|
+
|
||
|
+ if (skip_pages != NULL) {
|
||
|
+ g_strv_builder_addv (builder, (const char **) skip_pages);
|
||
|
+ g_clear_pointer (&skip_pages, g_strfreev);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
return g_strv_builder_end (builder);
|
||
|
}
|
||
|
|
||
|
@@ -398,6 +421,46 @@ main (int argc, char *argv[])
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+write_state (GisDriver *driver)
|
||
|
+{
|
||
|
+ g_autoptr(GKeyFile) state = NULL;
|
||
|
+ g_autoptr(GError) error = NULL;
|
||
|
+ g_autoptr(GStrvBuilder) builder = NULL;
|
||
|
+ g_auto(GStrv) visited_pages = NULL;
|
||
|
+ GisAssistant *assistant;
|
||
|
+ GList *pages, *node;
|
||
|
+
|
||
|
+ assistant = gis_driver_get_assistant (driver);
|
||
|
+
|
||
|
+ if (assistant == NULL)
|
||
|
+ return;
|
||
|
+
|
||
|
+ state = g_key_file_new ();
|
||
|
+
|
||
|
+ builder = g_strv_builder_new ();
|
||
|
+
|
||
|
+ pages = gis_assistant_get_all_pages (assistant);
|
||
|
+ for (node = pages; node != NULL; node = node->next) {
|
||
|
+ GisPage *page = node->data;
|
||
|
+ g_strv_builder_add (builder, GIS_PAGE_GET_CLASS (page)->page_id);
|
||
|
+ }
|
||
|
+
|
||
|
+ visited_pages = g_strv_builder_end (builder);
|
||
|
+
|
||
|
+ g_key_file_set_string_list (state,
|
||
|
+ VENDOR_PAGES_GROUP,
|
||
|
+ VENDOR_SKIP_KEY,
|
||
|
+ (const char * const *)
|
||
|
+ visited_pages,
|
||
|
+ g_strv_length (visited_pages));
|
||
|
+
|
||
|
+ if (!g_key_file_save_to_file (state, STATE_FILE, &error)) {
|
||
|
+ g_warning ("Unable to save state to %s: %s", STATE_FILE, error->message);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
gis_ensure_stamp_files (GisDriver *driver)
|
||
|
{
|
||
|
@@ -409,6 +472,8 @@ gis_ensure_stamp_files (GisDriver *driver)
|
||
|
g_warning ("Unable to create %s: %s", done_file, error->message);
|
||
|
g_clear_error (&error);
|
||
|
}
|
||
|
+
|
||
|
+ write_state (driver);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
diff --git a/meson.build b/meson.build
|
||
|
index fba4d96a..6997a2ee 100644
|
||
|
--- a/meson.build
|
||
|
+++ b/meson.build
|
||
|
@@ -14,19 +14,23 @@ po_dir = join_paths(meson.current_source_dir(), 'po')
|
||
|
bin_dir = join_paths(prefix, get_option('bindir'))
|
||
|
data_dir = join_paths(prefix, get_option('datadir'))
|
||
|
locale_dir = join_paths(prefix, get_option('localedir'))
|
||
|
+localstate_dir = join_paths(prefix, get_option('localstatedir'))
|
||
|
libexec_dir = join_paths(prefix, get_option('libexecdir'))
|
||
|
sysconf_dir = join_paths(prefix, get_option('sysconfdir'))
|
||
|
pkgdata_dir = join_paths(data_dir, meson.project_name())
|
||
|
pkgsysconf_dir = join_paths(sysconf_dir, meson.project_name())
|
||
|
+working_dir = join_paths(localstate_dir, 'lib', 'gnome-initial-setup')
|
||
|
|
||
|
conf = configuration_data()
|
||
|
conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
|
||
|
conf.set_quoted('GNOMELOCALEDIR', locale_dir)
|
||
|
conf.set_quoted('PKGDATADIR', pkgdata_dir)
|
||
|
conf.set_quoted('DATADIR', data_dir)
|
||
|
+conf.set_quoted('LOCALSTATEDIR', localstate_dir)
|
||
|
conf.set_quoted('PKGSYSCONFDIR', pkgsysconf_dir)
|
||
|
conf.set_quoted('SYSCONFDIR', sysconf_dir)
|
||
|
conf.set_quoted('LIBEXECDIR', libexec_dir)
|
||
|
+conf.set_quoted('GIS_WORKING_DIR', working_dir)
|
||
|
conf.set('SECRET_API_SUBJECT_TO_CHANGE', true)
|
||
|
conf.set_quoted('G_LOG_DOMAIN', 'InitialSetup')
|
||
|
conf.set('G_LOG_USE_STRUCTURED', true)
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From fdb66eea4df5e81bbd1f0b312e994d1bff338cfc Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Sun, 13 Aug 2023 16:33:49 -0400
|
||
|
Subject: [PATCH 09/10] polkit: Add fedora specfic rules
|
||
|
|
||
|
We should probably add some way to check vendor.conf for the policy
|
||
|
updates instead of a hardcoded list.
|
||
|
---
|
||
|
data/20-gnome-initial-setup.rules.in | 3 ++-
|
||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/data/20-gnome-initial-setup.rules.in b/data/20-gnome-initial-setup.rules.in
|
||
|
index 881efde9..f5b7d981 100644
|
||
|
--- a/data/20-gnome-initial-setup.rules.in
|
||
|
+++ b/data/20-gnome-initial-setup.rules.in
|
||
|
@@ -17,7 +17,8 @@ polkit.addRule(function(action, subject) {
|
||
|
action.id.indexOf('org.freedesktop.realmd.') === 0 ||
|
||
|
action.id.indexOf('com.endlessm.ParentalControls.') === 0 ||
|
||
|
action.id.indexOf('org.fedoraproject.thirdparty.') === 0 ||
|
||
|
- action.id.indexOf('org.freedesktop.login1.reboot') === 0);
|
||
|
+ action.id.indexOf('org.freedesktop.login1.reboot') === 0 ||
|
||
|
+ action.id.indexOf('org.fedoraproject.pkexec.liveinst') === 0);
|
||
|
|
||
|
if (actionMatches) {
|
||
|
if (subject.local)
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 016e642c564dea43e6a95977e92553294d3a131f Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Tue, 22 Aug 2023 13:51:40 -0400
|
||
|
Subject: [PATCH 10/10] gnome-initial-setup: Read /etc/sysconfig/anaconda
|
||
|
|
||
|
Just as /var/lib/gnome-initial-setup/state may show pages the user has
|
||
|
already answered, on Fedora, /etc/sysconfig/anaconda shows pages the user has
|
||
|
already answered via Anaconda.
|
||
|
|
||
|
This commit skips those from the --new-user mode as well.
|
||
|
---
|
||
|
gnome-initial-setup/gnome-initial-setup.c | 23 +++++++++++++++++++++++
|
||
|
1 file changed, 23 insertions(+)
|
||
|
|
||
|
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
index 2bd2d375..474dfc58 100644
|
||
|
--- a/gnome-initial-setup/gnome-initial-setup.c
|
||
|
+++ b/gnome-initial-setup/gnome-initial-setup.c
|
||
|
@@ -198,6 +198,8 @@ pages_to_skip_from_file (GisDriver *driver)
|
||
|
if (driver_mode & GIS_DRIVER_MODE_NEW_USER) {
|
||
|
g_autoptr(GKeyFile) state = NULL;
|
||
|
gboolean state_loaded;
|
||
|
+ g_autoptr(GKeyFile) anaconda = NULL;
|
||
|
+ gboolean anaconda_loaded;
|
||
|
|
||
|
state = g_key_file_new ();
|
||
|
state_loaded = g_key_file_load_from_file (state, STATE_FILE, G_KEY_FILE_NONE, &error);
|
||
|
@@ -210,6 +212,27 @@ pages_to_skip_from_file (GisDriver *driver)
|
||
|
g_clear_pointer (&skip_pages, g_strfreev);
|
||
|
}
|
||
|
}
|
||
|
+
|
||
|
+ anaconda = g_key_file_new ();
|
||
|
+ anaconda_loaded = g_key_file_load_from_file (anaconda, "/etc/sysconfig/anaconda", G_KEY_FILE_NONE, NULL);
|
||
|
+
|
||
|
+ if (anaconda_loaded) {
|
||
|
+ struct {
|
||
|
+ const char *spoke_name;
|
||
|
+ const char *page_name;
|
||
|
+ } spoke_page_map[] = {
|
||
|
+ { "WelcomeLanguageSpoke", "language" },
|
||
|
+ { "DatetimeSpoke", "timezone" },
|
||
|
+ { "KeyboardSpoke", "keyboard" },
|
||
|
+ { NULL, NULL }
|
||
|
+ };
|
||
|
+ size_t i;
|
||
|
+
|
||
|
+ for (i = 0; spoke_page_map[i].spoke_name != NULL; i++) {
|
||
|
+ if (g_key_file_get_boolean (anaconda, spoke_page_map[i].spoke_name, "visited", NULL))
|
||
|
+ g_strv_builder_add (builder, spoke_page_map[i].page_name);
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
return g_strv_builder_end (builder);
|
||
|
--
|
||
|
GitLab
|
||
|
|