Don't let language page proceed until it has committed its changes

This commit is contained in:
Ray Strode 2023-09-08 11:28:32 -04:00
parent e7c2420c22
commit f74e718d60
13 changed files with 4536 additions and 15 deletions

View File

@ -1,7 +1,7 @@
From 7dcd4e1b699a84d14de3c2686d0c6fbea64b2914 Mon Sep 17 00:00:00 2001
From 3f92d2daa436aaf90c4aabfb2cd8031ad32b4d91 Mon Sep 17 00:00:00 2001
From: Michael Catanzaro <mcatanzaro@redhat.com>
Date: Tue, 22 Aug 2023 12:58:50 -0500
Subject: [PATCH 01/11] keyboard: stop setting 'current' input source
Subject: [PATCH 01/12] keyboard: stop setting 'current' input source
This setting is deprecated and ignored since 3.22. We don't need to set
it anymore because nothing uses it. See:
@ -78,5 +78,5 @@ index fa41230f..693bb117 100644
const gchar *sid = l->data;
gchar **lv = g_strsplit (sid, "+", -1);
--
2.41.0.rc2
2.41.0

View File

@ -1,7 +1,7 @@
From 6dbb638f3bda4d345e280f64c9739fd4026ef78f Mon Sep 17 00:00:00 2001
From 22667605630041bb654782773182b60d60a039cd Mon Sep 17 00:00:00 2001
From: Michael Catanzaro <mcatanzaro@redhat.com>
Date: Thu, 24 Aug 2023 13:03:07 -0500
Subject: [PATCH 02/11] keyboard: write to mru-sources setting if it has never
Subject: [PATCH 02/12] keyboard: write to mru-sources setting if it has never
been set before
This is a port of:
@ -156,5 +156,5 @@ index 693bb117..ad48d933 100644
if (!g_str_equal (LAYOUT (lv), layout) ||
--
2.41.0.rc2
2.41.0

View File

@ -0,0 +1,295 @@
From 99f56c244ed41bb63e9873dbbadfbadaa7e24c15 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/12] 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
@@ -29,181 +29,204 @@
#define GNOME_SYSTEM_LOCALE_DIR "org.gnome.system.locale"
#define REGION_KEY "region"
#include "config.h"
#include "language-resources.h"
#include "gis-welcome-widget.h"
#include "cc-language-chooser.h"
#include "gis-language-page.h"
#include <act/act-user-manager.h>
#include <polkit/polkit.h>
#include <locale.h>
#include <gtk/gtk.h>
struct _GisLanguagePagePrivate
{
GtkWidget *logo;
GtkWidget *welcome_widget;
GtkWidget *language_chooser;
GDBusProxy *localed;
GPermission *permission;
const gchar *new_locale_id;
GCancellable *cancellable;
};
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)
{
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (self);
GVariantBuilder *b;
gchar *s;
b = g_variant_builder_new (G_VARIANT_TYPE ("as"));
s = g_strconcat ("LANG=", priv->new_locale_id, NULL);
g_variant_builder_add (b, "s", s);
g_free (s);
g_dbus_proxy_call (priv->localed,
"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);
}
static void
change_locale_permission_acquired (GObject *source,
GAsyncResult *res,
gpointer data)
{
GisLanguagePage *page = GIS_LANGUAGE_PAGE (data);
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
GError *error = NULL;
gboolean allowed;
allowed = g_permission_acquire_finish (priv->permission, res, &error);
if (error) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to acquire permission: %s", error->message);
g_error_free (error);
return;
}
if (allowed)
set_localed_locale (page);
}
static void
user_loaded (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
gchar *new_locale_id = user_data;
act_user_set_language (ACT_USER (object), new_locale_id);
g_free (new_locale_id);
}
static void
language_changed (CcLanguageChooser *chooser,
GParamSpec *pspec,
GisLanguagePage *page)
{
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
GisDriver *driver;
GSettings *region_settings;
ActUser *user;
priv->new_locale_id = cc_language_chooser_get_language (chooser);
driver = GIS_PAGE (page)->driver;
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) {
+
+ gis_page_set_complete (GIS_PAGE (page), FALSE);
+
if (g_permission_get_allowed (priv->permission)) {
set_localed_locale (page);
}
else if (g_permission_get_can_acquire (priv->permission)) {
g_permission_acquire_async (priv->permission,
NULL,
change_locale_permission_acquired,
page);
}
}
/* Ensure we won't override the selected language for format strings */
region_settings = g_settings_new (GNOME_SYSTEM_LOCALE_DIR);
g_settings_reset (region_settings, REGION_KEY);
g_object_unref (region_settings);
user = act_user_manager_get_user (act_user_manager_get_default (),
g_get_user_name ());
if (act_user_is_loaded (user))
act_user_set_language (user, priv->new_locale_id);
else
g_signal_connect (user,
"notify::is-loaded",
G_CALLBACK (user_loaded),
g_strdup (priv->new_locale_id));
gis_welcome_widget_show_locale (GIS_WELCOME_WIDGET (priv->welcome_widget),
priv->new_locale_id);
}
static void
localed_proxy_ready (GObject *source,
GAsyncResult *res,
gpointer data)
{
GisLanguagePage *self = data;
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (self);
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;
}
priv->localed = proxy;
+ gis_page_set_complete (GIS_PAGE (self), TRUE);
}
static void
update_distro_logo (GisLanguagePage *page)
{
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
g_autofree char *id = g_get_os_info (G_OS_INFO_KEY_ID);
gsize i;
static const struct {
const char *id;
const char *logo;
} id_to_logo[] = {
{ "debian", "emblem-debian" },
{ "fedora", "fedora-logo-icon" },
{ "ubuntu", "ubuntu-logo-icon" },
{ "openSUSE Tumbleweed", "opensuse-logo-icon" },
{ "openSUSE Leap", "opensuse-logo-icon" },
{ "SLED", "suse-logo-icon" },
{ "SLES", "suse-logo-icon" },
};
for (i = 0; i < G_N_ELEMENTS (id_to_logo); i++)
{
if (g_strcmp0 (id, id_to_logo[i].id) == 0)
{
g_object_set (priv->logo, "icon-name", id_to_logo[i].logo, NULL);
break;
}
}
@@ -224,62 +247,64 @@ gis_language_page_constructed (GObject *object)
GDBusConnection *bus;
g_type_ensure (CC_TYPE_LANGUAGE_CHOOSER);
G_OBJECT_CLASS (gis_language_page_parent_class)->constructed (object);
update_distro_logo (page);
g_signal_connect (priv->language_chooser, "notify::language",
G_CALLBACK (language_changed), page);
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)
{
priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, NULL);
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
g_dbus_proxy_new (bus,
G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
NULL,
"org.freedesktop.locale1",
"/org/freedesktop/locale1",
"org.freedesktop.locale1",
priv->cancellable,
(GAsyncReadyCallback) localed_proxy_ready,
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);
}
static void
gis_language_page_locale_changed (GisPage *page)
{
gis_page_set_title (GIS_PAGE (page), _("Welcome"));
}
static void
gis_language_page_dispose (GObject *object)
{
GisLanguagePage *page = GIS_LANGUAGE_PAGE (object);
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
g_clear_object (&priv->permission);
g_clear_object (&priv->localed);
g_clear_object (&priv->cancellable);
G_OBJECT_CLASS (gis_language_page_parent_class)->dispose (object);
}
static void
gis_language_page_class_init (GisLanguagePageClass *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-language-page.ui");
--
2.41.0

View File

@ -0,0 +1,646 @@
From 63e7d5728b5eb333504d1e3df9a802b1d9046310 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/12] 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 | 312 ++++++------------
1 file changed, 107 insertions(+), 205 deletions(-)
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
index ad48d933..39cb7db6 100644
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
@@ -18,510 +18,412 @@
* Michael Wood <michael.g.wood@intel.com>
*
* Based on gnome-control-center cc-region-panel.c
*/
#define PAGE_ID "keyboard"
#include "config.h"
#include <locale.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <polkit/polkit.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-languages.h>
#include "gis-keyboard-page.h"
#include "keyboard-resources.h"
#include "cc-input-chooser.h"
#include "cc-common-language.h"
#include "gis-page-header.h"
#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;
GDBusProxy *localed;
GCancellable *cancellable;
GPermission *permission;
GSettings *input_settings;
+ char **default_input_source_ids;
+ char **default_input_source_types;
+ char **default_input_options;
- GSList *system_sources;
+ gboolean should_skip;
};
typedef struct _GisKeyboardPagePrivate GisKeyboardPagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GisKeyboardPage, gis_keyboard_page, GIS_TYPE_PAGE);
static void
gis_keyboard_page_finalize (GObject *object)
{
GisKeyboardPage *self = GIS_KEYBOARD_PAGE (object);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
if (priv->cancellable)
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
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_input_options, g_strfreev);
G_OBJECT_CLASS (gis_keyboard_page_parent_class)->finalize (object);
}
static void
-set_input_settings (GisKeyboardPage *self)
+set_input_settings (GisKeyboardPage *self,
+ const char *type,
+ const char *id)
{
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- const gchar *type;
- const gchar *id;
- GVariantBuilder builder;
- GSList *l;
+
+ GVariantBuilder input_source_builder;
+ GVariantBuilder input_options_builder;
+ size_t i;
+ gboolean has_latin_layout = FALSE;
gboolean is_xkb_source = FALSE;
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));
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
+ g_variant_builder_init (&input_source_builder, G_VARIANT_TYPE ("a(ss)"));
+ g_variant_builder_init (&input_options_builder, G_VARIANT_TYPE ("as"));
- if (g_str_equal (type, "xkb")) {
- g_variant_builder_add (&builder, "(ss)", type, id);
- is_xkb_source = TRUE;
- }
+ if (type != NULL && id != NULL) {
+ has_latin_layout = !gnome_input_source_is_non_latin (type, id);
+ if (g_str_equal (type, "xkb")) {
+ g_variant_builder_add (&input_source_builder, "(ss)", type, id);
- for (l = priv->system_sources; l; l = l->next) {
- const gchar *sid = l->data;
+ is_xkb_source = TRUE;
+ }
+ }
- if (g_str_equal (id, sid) && g_str_equal (type, "xkb"))
+ for (i = 0; priv->default_input_source_ids && priv->default_input_source_ids[i] != NULL; i++) {
+ if (g_str_equal (id, priv->default_input_source_ids[i]) && g_str_equal (type, priv->default_input_source_types[i]))
continue;
- g_variant_builder_add (&builder, "(ss)", "xkb", sid);
+ g_variant_builder_add (&input_source_builder, "(ss)", priv->default_input_source_types[i], priv->default_input_source_ids[i]);
+
+ if (!gnome_input_source_is_non_latin (priv->default_input_source_types[i], priv->default_input_source_ids[i]))
+ has_latin_layout = TRUE;
+ }
+
+ if (type != NULL && id != NULL) {
+ if (!is_xkb_source) {
+ g_variant_builder_add (&input_source_builder, "(ss)", type, id);
+ }
+ }
+
+ if (!has_latin_layout) {
+ g_variant_builder_add (&input_source_builder, "(ss)", "xkb", "us");
}
- if (!is_xkb_source)
- g_variant_builder_add (&builder, "(ss)", type, id);
+ for (i = 0; priv->default_input_options[i] != NULL; i++) {
+ g_variant_builder_add (&input_options_builder, "s", priv->default_input_options[i]);
+ }
if (type != NULL && 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, id);
g_settings_set_value (priv->input_settings, KEY_MRU_SOURCES, g_variant_builder_end (&mru_input_source_builder));
}
- g_settings_set_value (priv->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
-
+ g_settings_set_value (priv->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&input_source_builder));
+ g_settings_set_value (priv->input_settings, KEY_INPUT_OPTIONS, g_variant_builder_end (&input_options_builder));
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;
+ size_t i;
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);
+ for (i = 0; priv->default_input_source_ids && priv->default_input_source_ids[i] != NULL; i++) {
+ const gchar *sid = priv->default_input_source_ids[i];
+ g_auto (GStrv) lv = NULL;
+
+ if (!g_str_equal (priv->default_input_source_types[i], "xkb"))
+ continue;
+
+ 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
g_dbus_proxy_call (priv->localed,
"SetX11Keyboard",
g_variant_new ("(ssssbb)", layouts->str, "", variants->str, "", TRUE, TRUE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, NULL, NULL);
g_string_free (layouts, TRUE);
g_string_free (variants, TRUE);
}
static void
change_locale_permission_acquired (GObject *source,
GAsyncResult *res,
gpointer data)
{
GisKeyboardPage *page = GIS_KEYBOARD_PAGE (data);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (page);
GError *error = NULL;
gboolean allowed;
allowed = g_permission_acquire_finish (priv->permission, res, &error);
if (error) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to acquire permission: %s", error->message);
g_error_free (error);
return;
}
if (allowed)
set_localed_input (GIS_KEYBOARD_PAGE (data));
}
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)) {
set_localed_input (self);
} else if (g_permission_get_can_acquire (priv->permission)) {
g_permission_acquire_async (priv->permission,
NULL,
change_locale_permission_acquired,
self);
}
}
}
static gboolean
gis_keyboard_page_apply (GisPage *page,
GCancellable *cancellable)
{
update_input (GIS_KEYBOARD_PAGE (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)
-{
- 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)
+add_default_input_sources (GisKeyboardPage *self)
{
- 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
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;
-
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);
-
- 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");
- }
- 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
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);
gis_page_set_complete (GIS_PAGE (self), complete);
}
static void
localed_proxy_ready (GObject *source,
GAsyncResult *res,
gpointer data)
{
GisKeyboardPage *self = data;
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
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;
}
priv->localed = proxy;
-
- preselect_input_source (self);
- update_page_complete (self);
+ update_page_complete (self);
}
static void
input_confirmed (CcInputChooser *chooser,
GisKeyboardPage *self)
{
gis_assistant_next_page (gis_driver_get_assistant (GIS_PAGE (self)->driver));
}
static void
input_changed (CcInputChooser *chooser,
GisKeyboardPage *self)
{
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_input_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)
{
GisKeyboardPage *self = GIS_KEYBOARD_PAGE (object);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
G_OBJECT_CLASS (gis_keyboard_page_parent_class)->constructed (object);
g_signal_connect (priv->input_chooser, "confirm",
G_CALLBACK (input_confirmed), self);
g_signal_connect (priv->input_chooser, "changed",
G_CALLBACK (input_changed), self);
priv->input_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
g_settings_delay (priv->input_settings);
priv->cancellable = g_cancellable_new ();
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) 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);
update_page_complete (self);
gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
}
static void
gis_keyboard_page_locale_changed (GisPage *page)
{
gis_page_set_title (GIS_PAGE (page), _("Typing"));
}
static void
gis_keyboard_page_class_init (GisKeyboardPageClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GisPageClass * page_class = GIS_PAGE_CLASS (klass);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/initial-setup/gis-keyboard-page.ui");
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisKeyboardPage, input_chooser);
page_class->page_id = PAGE_ID;
page_class->apply = gis_keyboard_page_apply;
page_class->skip = gis_keyboard_page_skip;
page_class->locale_changed = gis_keyboard_page_locale_changed;
object_class->constructed = gis_keyboard_page_constructed;
--
2.41.0

View File

@ -0,0 +1,150 @@
From 5803c34ad2fd10ad637392fefb9aad8d013c6d01 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Aug 2023 10:53:41 -0400
Subject: [PATCH 05/12] gnome-initial-setup: Bump GLib required version to 2.70
This gives us GStrvBuilder
---
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..d0ad5ff8 100644
--- a/gnome-initial-setup/meson.build
+++ b/gnome-initial-setup/meson.build
@@ -25,61 +25,61 @@ sources += [
'gis-driver.h',
'gis-keyring.h'
]
geocode_glib_2_dep = dependency(
'geocode-glib-2.0',
fallback: ['geocode-glib', 'geocode_glib_dep'],
default_options: [
'enable-gtk-doc=false',
'enable-installed-tests=false',
'enable-introspection=false',
'soup2=false',
],
)
gweather_dep = dependency('gweather4')
subdir('pages')
dependencies = [
dependency ('libnm', version: '>= 1.2'),
dependency ('libnma-gtk4', version: '>= 1.0'),
dependency ('polkit-gobject-1', version: '>= 0.103'),
dependency ('accountsservice'),
geocode_glib_2_dep,
dependency ('gnome-desktop-4'),
dependency ('gsettings-desktop-schemas', version: '>= 3.37.1'),
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.70.0'),
dependency ('gio-unix-2.0', version: '>= 2.53.0'),
dependency ('gdm', version: '>= 3.8.3'),
gweather_dep,
dependency ('libgeoclue-2.0', version: '>= 2.3.1'),
cc.find_library('m', required: false),
dependency ('pango', version: '>= 1.32.5'),
dependency ('json-glib-1.0'),
dependency ('krb5'),
dependency ('libsecret-1', version: '>= 0.18.8'),
dependency ('pwquality'),
dependency ('rest-1.0'),
ibus_dep,
libmalcontent_dep,
libmalcontent_ui_dep,
libadwaita_dep,
webkitgtk_dep
]
executable(
'gnome-initial-setup',
sources,
include_directories: config_h_dir,
dependencies: dependencies,
install: true,
install_dir: get_option('libexecdir')
)
executable(
'gnome-initial-setup-copy-worker',
['gnome-initial-setup-copy-worker.c'],
diff --git a/meson.build b/meson.build
index a1057988..28cf7998 100644
--- a/meson.build
+++ b/meson.build
@@ -3,62 +3,62 @@ project('gnome-initial-setup',
version: '45.beta',
license: 'GPL-2.0-or-later',
meson_version: '>= 0.53.0',
)
cc = meson.get_compiler('c')
gnome = import('gnome')
i18n = import('i18n')
prefix = get_option('prefix')
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'))
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())
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('PKGSYSCONFDIR', pkgsysconf_dir)
conf.set_quoted('SYSCONFDIR', sysconf_dir)
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_70')
+conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_70')
enable_systemd = get_option('systemd')
if enable_systemd
systemd_dep = dependency('systemd', version: '>= 242', required: false)
assert(systemd_dep.found(), 'Systemd support explicitly required, but systemd not found')
systemd_userunitdir = systemd_dep.get_variable(pkgconfig: 'systemduserunitdir',
pkgconfig_define: ['prefix', prefix])
systemd_sysusersdir = systemd_dep.get_variable(pkgconfig: 'sysusersdir',
pkgconfig_define: ['prefix', prefix])
endif
vendor_conf_file = get_option('vendor-conf-file')
if vendor_conf_file != ''
conf.set_quoted('VENDOR_CONF_FILE', vendor_conf_file)
endif
# Needed for the 'keyboard' page
ibus_dep = dependency ('ibus-1.0',
version: '>= 1.4.99',
required: get_option('ibus'))
have_ibus = ibus_dep.found()
conf.set('HAVE_IBUS', have_ibus)
# Check for libadwaita before malcontent-ui, otherwise Meson may search and
# find an older version of libadwaita in the host system, cache it, and fail
# to fallback to a submodule.
libadwaita_dep = dependency(
'libadwaita-1',
version: '>= 1.2.alpha',
--
2.41.0

View File

@ -0,0 +1,633 @@
From 211fcba0a78b4c7474be5fb698c90d1a6b70393f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 13 Aug 2023 09:09:56 -0400
Subject: [PATCH 06/12] 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
@@ -9,75 +9,74 @@
*
* 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/>.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "gnome-initial-setup.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#ifdef HAVE_WEBKITGTK_6_0
#include <webkit/webkit.h>
#else
#include <webkit2/webkit2.h>
#endif
#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
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;
}
enum {
REBUILD_PAGES,
LOCALE_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL];
typedef enum {
PROP_MODE = 1,
PROP_USERNAME,
PROP_SMALL_SCREEN,
PROP_PARENTAL_CONTROLS_ENABLED,
PROP_FULL_NAME,
PROP_AVATAR,
} GisDriverProperty;
static GParamSpec *obj_props[PROP_AVATAR + 1];
struct _GisDriver {
AdwApplication parent_instance;
GtkWindow *main_window;
GisAssistant *assistant;
GdmClient *client;
@@ -624,61 +623,61 @@ gis_driver_get_property (GObject *object,
break;
case PROP_SMALL_SCREEN:
g_value_set_boolean (value, driver->small_screen);
break;
case PROP_PARENTAL_CONTROLS_ENABLED:
g_value_set_boolean (value, driver->parental_controls_enabled);
break;
case PROP_FULL_NAME:
g_value_set_string (value, driver->full_name);
break;
case PROP_AVATAR:
g_value_set_object (value, driver->avatar);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gis_driver_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GisDriver *driver = GIS_DRIVER (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);
driver->username = g_value_dup_string (value);
break;
case PROP_PARENTAL_CONTROLS_ENABLED:
gis_driver_set_parental_controls_enabled (driver, g_value_get_boolean (value));
break;
case PROP_FULL_NAME:
gis_driver_set_full_name (driver, g_value_get_string (value));
break;
case PROP_AVATAR:
gis_driver_set_avatar (driver, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gis_driver_activate (GApplication *app)
{
GisDriver *driver = GIS_DRIVER (app);
G_APPLICATION_CLASS (gis_driver_parent_class)->activate (app);
gtk_window_present (GTK_WINDOW (driver->main_window));
}
@@ -826,64 +825,64 @@ gis_driver_init (GisDriver *driver)
static void
gis_driver_class_init (GisDriverClass *klass)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gis_driver_get_property;
gobject_class->set_property = gis_driver_set_property;
gobject_class->dispose = gis_driver_dispose;
gobject_class->finalize = gis_driver_finalize;
application_class->startup = gis_driver_startup;
application_class->activate = gis_driver_activate;
signals[REBUILD_PAGES] =
g_signal_new ("rebuild-pages",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[LOCALE_CHANGED] =
g_signal_new ("locale-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL, NULL,
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", "", "",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
obj_props[PROP_SMALL_SCREEN] =
g_param_spec_boolean ("small-screen", "", "",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* GisDriver:parental-controls-enabled:
*
* Whether parental controls are enabled for the main user. If this is %TRUE,
* two user accounts will be created when this page is saved: one for the main
* user (a child) which will be a standard account; and one for the parent
* which will be an administrative account.
*
* Since: 3.36
*/
obj_props[PROP_PARENTAL_CONTROLS_ENABLED] =
g_param_spec_boolean ("parental-controls-enabled",
"Parental Controls Enabled",
"Whether parental controls are enabled for the main user.",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GisDriver:full-name: (nullable)
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
@@ -4,74 +4,78 @@
*
* 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/>.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __GIS_DRIVER_H__
#define __GIS_DRIVER_H__
#include "gis-assistant.h"
#include "gis-page.h"
#include <act/act-user-manager.h>
#include <gdm/gdm-client.h>
#include <adwaita.h>
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)
typedef enum {
UM_LOCAL,
UM_ENTERPRISE,
NUM_MODES,
} 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,
ActUser *user,
const gchar *password);
void gis_driver_get_user_permissions (GisDriver *driver,
ActUser **user,
const gchar **password);
void gis_driver_set_parent_permissions (GisDriver *driver,
ActUser *parent,
const gchar *password);
void gis_driver_get_parent_permissions (GisDriver *driver,
ActUser **parent,
const gchar **password);
void gis_driver_set_account_mode (GisDriver *driver,
UmAccountMode mode);
UmAccountMode gis_driver_get_account_mode (GisDriver *driver);
void gis_driver_set_parental_controls_enabled (GisDriver *driver,
gboolean parental_controls_enabled);
gboolean gis_driver_get_parental_controls_enabled (GisDriver *driver);
void gis_driver_set_user_language (GisDriver *driver,
const gchar *lang_id,
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
@@ -29,228 +29,258 @@
#include <stdlib.h>
#include <glib/gi18n.h>
#include "pages/welcome/gis-welcome-page.h"
#include "pages/language/gis-language-page.h"
#include "pages/keyboard/gis-keyboard-page.h"
#include "pages/network/gis-network-page.h"
#include "pages/timezone/gis-timezone-page.h"
#include "pages/privacy/gis-privacy-page.h"
#include "pages/software/gis-software-page.h"
#include "pages/goa/gis-goa-page.h"
#include "pages/account/gis-account-pages.h"
#include "pages/parental-controls/gis-parental-controls-page.h"
#include "pages/password/gis-password-page.h"
#include "pages/summary/gis-summary-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"
static gboolean force_existing_user_mode;
static GPtrArray *skipped_pages;
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 },
};
#undef PAGE
static gboolean
should_skip_page (const gchar *page_id,
gchar **skip_pages)
{
guint i = 0;
/* special case welcome. We only want to show it if language
* is skipped
*/
if (strcmp (page_id, "welcome") == 0)
return !should_skip_page ("language", skip_pages);
/* check through our skip pages list for pages we don't want */
if (skip_pages) {
while (skip_pages[i]) {
if (g_strcmp0 (skip_pages[i], page_id) == 0)
return TRUE;
i++;
}
}
return FALSE;
}
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:
* - 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
*
+ * 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
destroy_pages_after (GisAssistant *assistant,
GisPage *page)
{
GList *pages, *l, *next;
pages = gis_assistant_get_all_pages (assistant);
for (l = pages; l != NULL; l = l->next)
if (l->data == page)
break;
l = l->next;
for (; l != NULL; l = next) {
next = l->next;
gis_assistant_remove_page (assistant, l->data);
}
}
static void
destroy_page (gpointer data)
{
GtkWidget *assistant;
GisPage *page;
page = data;
assistant = gtk_widget_get_ancestor (GTK_WIDGET (page), GIS_TYPE_ASSISTANT);
if (assistant)
gis_assistant_remove_page (GIS_ASSISTANT (assistant), page);
}
static void
rebuild_pages_cb (GisDriver *driver)
{
PageData *page_data;
GisPage *page;
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);
page_data = page_table;
g_ptr_array_free (skipped_pages, TRUE);
skipped_pages = g_ptr_array_new_with_free_func (destroy_page);
if (current_page != NULL) {
destroy_pages_after (assistant, current_page);
for (page_data = page_table; page_data->page_id != NULL; ++page_data)
if (g_str_equal (page_data->page_id, GIS_PAGE_GET_CLASS (current_page)->page_id))
break;
++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;
page = page_data->prepare_page_func (driver);
if (!page)
continue;
if (skipped) {
gis_page_skip (page);
g_ptr_array_add (skipped_pages, page);
} else {
gis_driver_add_page (driver, page);
}
}
g_strfreev (skip_pages);
}
static GisDriverMode
get_mode (void)
{
if (force_existing_user_mode)
return GIS_DRIVER_MODE_EXISTING_USER;
else
return GIS_DRIVER_MODE_NEW_USER;
}
static gboolean
initial_setup_disabled_by_anaconda (void)
{
--
2.41.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,540 @@
From 03ab26b4301240b8f6de3d61f9cfa77676995e6e 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/12] 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
@@ -103,30 +103,36 @@ if enable_systemd
install_data('gnome-initial-setup.conf', install_dir: systemd_sysusersdir)
endif
rules_dir = join_paths(data_dir, 'polkit-1', 'rules.d')
configure_file(
input: '20-gnome-initial-setup.rules.in',
output: '20-gnome-initial-setup.rules',
install: true,
install_dir: rules_dir,
configuration: data_conf,
)
session_dir = join_paths(data_dir, 'gnome-session', 'sessions')
configure_file(
input: '@0@.session.in'.format(meson.project_name()),
output: '@BASENAME@',
configuration: {
'this_component': meson.project_name(),
'gnome_session_required_components': ';'.join([
gis_shell_component,
meson.project_name(),
] +
gis_gnome_session_required_components),
},
install_dir: session_dir,
)
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
@@ -80,90 +80,93 @@ struct _GisDriver {
GtkWindow *main_window;
GisAssistant *assistant;
GdmClient *client;
GdmGreeter *greeter;
GdmUserVerifier *user_verifier;
ActUser *user_account;
gchar *user_password;
ActUser *parent_account; /* (owned) (nullable) */
gchar *parent_password; /* (owned) (nullable) */
gboolean parental_controls_enabled;
gchar *lang_id;
gchar *username;
gchar *full_name; /* (owned) (nullable) */
GdkPaintable *avatar; /* (owned) (nullable) */
GisDriverMode mode;
UmAccountMode account_mode;
gboolean small_screen;
locale_t locale;
const gchar *vendor_conf_file_path;
GKeyFile *vendor_conf_file;
+
+ GKeyFile *state_file;
};
G_DEFINE_TYPE (GisDriver, gis_driver, ADW_TYPE_APPLICATION)
static void
gis_driver_dispose (GObject *object)
{
GisDriver *driver = GIS_DRIVER (object);
g_clear_object (&driver->user_verifier);
g_clear_object (&driver->greeter);
g_clear_object (&driver->client);
G_OBJECT_CLASS (gis_driver_parent_class)->dispose (object);
}
static void
gis_driver_finalize (GObject *object)
{
GisDriver *driver = GIS_DRIVER (object);
g_free (driver->lang_id);
g_free (driver->username);
g_free (driver->full_name);
g_free (driver->user_password);
g_clear_object (&driver->avatar);
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);
if (driver->locale != (locale_t) 0)
{
uselocale (LC_GLOBAL_LOCALE);
freelocale (driver->locale);
}
G_OBJECT_CLASS (gis_driver_parent_class)->finalize (object);
}
static void
assistant_page_changed (GtkScrolledWindow *sw)
{
gtk_adjustment_set_value (gtk_scrolled_window_get_vadjustment (sw), 0);
}
static void
prepare_main_window (GisDriver *driver)
{
GtkWidget *child, *sw;
child = gtk_window_get_child (GTK_WINDOW (driver->main_window));
g_object_ref (child);
gtk_window_set_child (GTK_WINDOW (driver->main_window), NULL);
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (driver->main_window), sw);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child);
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
@@ -22,60 +22,62 @@
#include "config.h"
#include "gnome-initial-setup.h"
#include <adwaita.h>
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
#include <glib/gi18n.h>
#include "pages/welcome/gis-welcome-page.h"
#include "pages/language/gis-language-page.h"
#include "pages/keyboard/gis-keyboard-page.h"
#include "pages/network/gis-network-page.h"
#include "pages/timezone/gis-timezone-page.h"
#include "pages/privacy/gis-privacy-page.h"
#include "pages/software/gis-software-page.h"
#include "pages/goa/gis-goa-page.h"
#include "pages/account/gis-account-pages.h"
#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"
+#define STATE_FILE GIS_WORKING_DIR "/state"
+
static gboolean force_existing_user_mode;
static gboolean force_live_user_mode;
static GPtrArray *skipped_pages;
typedef GisPage *(*PreparePage) (GisDriver *driver);
typedef struct {
const gchar *page_id;
PreparePage prepare_page_func;
GisDriverMode modes;
} PageData;
#define PAGE(name, modes) { #name, gis_prepare_ ## name ## _page, modes }
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_ALL),
PAGE (privacy, 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),
/* 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),
@@ -94,60 +96,61 @@ should_skip_page (const gchar *page_id,
guint i = 0;
/* special case welcome. We only want to show it if language
* is skipped
*/
if (strcmp (page_id, "welcome") == 0)
return !should_skip_page ("language", skip_pages);
/* check through our skip pages list for pages we don't want */
if (skip_pages) {
while (skip_pages[i]) {
if (g_strcmp0 (skip_pages[i], page_id) == 0)
return TRUE;
i++;
}
}
return FALSE;
}
static gchar **
pages_to_skip_from_file (GisDriver *driver)
{
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;
+ 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:
* - skip (optional): list of pages to be skipped always
* - 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:
* - 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);
if (skip_pages != NULL)
{
@@ -162,60 +165,80 @@ pages_to_skip_from_file (GisDriver *driver)
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;
}
}
+ /* 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);
}
static void
destroy_pages_after (GisAssistant *assistant,
GisPage *page)
{
GList *pages, *l, *next;
pages = gis_assistant_get_all_pages (assistant);
for (l = pages; l != NULL; l = l->next)
if (l->data == page)
break;
l = l->next;
for (; l != NULL; l = next) {
next = l->next;
gis_assistant_remove_page (assistant, l->data);
}
}
static void
destroy_page (gpointer data)
{
GtkWidget *assistant;
GisPage *page;
page = data;
assistant = gtk_widget_get_ancestor (GTK_WIDGET (page), GIS_TYPE_ASSISTANT);
@@ -371,59 +394,101 @@ main (int argc, char *argv[])
* it does in new-user mode, disable Initial Setup for existing users.
*
* https://gitlab.gnome.org/GNOME/gnome-initial-setup/-/issues/120#note_1019004
* https://gitlab.gnome.org/GNOME/gnome-initial-setup/-/issues/12
*/
if (mode == GIS_DRIVER_MODE_EXISTING_USER) {
g_message ("Skipping gnome-initial-setup for existing user");
gis_ensure_stamp_files (driver);
exit (EXIT_SUCCESS);
}
/* We only do this in existing-user mode, because if gdm launches us
* in new-user mode and we just exit, gdm's special g-i-s session
* never terminates. */
if (initial_setup_disabled_by_anaconda () &&
mode == GIS_DRIVER_MODE_EXISTING_USER) {
gis_ensure_stamp_files (driver);
exit (EXIT_SUCCESS);
}
g_signal_connect (driver, "rebuild-pages", G_CALLBACK (rebuild_pages_cb), NULL);
status = g_application_run (G_APPLICATION (driver), argc, argv);
g_ptr_array_free (skipped_pages, TRUE);
g_object_unref (driver);
g_option_context_free (context);
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)
{
g_autofree gchar *done_file = NULL;
g_autoptr(GError) error = NULL;
done_file = g_build_filename (g_get_user_config_dir (), "gnome-initial-setup-done", NULL);
if (!g_file_set_contents (done_file, "yes", -1, &error)) {
g_warning ("Unable to create %s: %s", done_file, error->message);
g_clear_error (&error);
}
+
+ write_state (driver);
}
/**
* gis_get_mock_mode:
*
* Gets whether gnome-initial-setup has been built for development, and hence
* shouldnt permanently change any system configuration.
*
* By default, mock mode is enabled when running in a build environment. This
* heuristic may be changed in future.
*
* Returns: %TRUE if in mock mode, %FALSE otherwise
*/
gboolean
gis_get_mock_mode (void)
{
return (g_getenv ("UNDER_JHBUILD") != NULL);
}
diff --git a/meson.build b/meson.build
index 28cf7998..4c294dfe 100644
--- a/meson.build
+++ b/meson.build
@@ -1,59 +1,63 @@
project('gnome-initial-setup',
['c'],
version: '45.beta',
license: 'GPL-2.0-or-later',
meson_version: '>= 0.53.0',
)
cc = meson.get_compiler('c')
gnome = import('gnome')
i18n = import('i18n')
prefix = get_option('prefix')
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)
conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_70')
conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_70')
enable_systemd = get_option('systemd')
if enable_systemd
systemd_dep = dependency('systemd', version: '>= 242', required: false)
assert(systemd_dep.found(), 'Systemd support explicitly required, but systemd not found')
systemd_userunitdir = systemd_dep.get_variable(pkgconfig: 'systemduserunitdir',
pkgconfig_define: ['prefix', prefix])
systemd_sysusersdir = systemd_dep.get_variable(pkgconfig: 'sysusersdir',
pkgconfig_define: ['prefix', prefix])
endif
vendor_conf_file = get_option('vendor-conf-file')
if vendor_conf_file != ''
conf.set_quoted('VENDOR_CONF_FILE', vendor_conf_file)
endif
# Needed for the 'keyboard' page
ibus_dep = dependency ('ibus-1.0',
version: '>= 1.4.99',
required: get_option('ibus'))
have_ibus = ibus_dep.found()
conf.set('HAVE_IBUS', have_ibus)
# Check for libadwaita before malcontent-ui, otherwise Meson may search and
--
2.41.0

View File

@ -0,0 +1,103 @@
From 4a9511328fa095de8c3709b380f175755e845175 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sat, 19 Aug 2023 15:31:03 -0400
Subject: [PATCH 09/12] keyboard: Don't add default input sources if input
sources already set
If the keyboard page gets skipped, it adds default input sources derived
from the users locale.
That is all fine and good, but may stomp on existiing site or distro configuration.
This commit checks for that kind of thing first, and skips adding the
default in that case.
---
gnome-initial-setup/pages/keyboard/gis-keyboard-page.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
index ac15bcc7..f477bd5c 100644
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
@@ -63,70 +63,77 @@ struct _GisKeyboardPagePrivate {
typedef struct _GisKeyboardPagePrivate GisKeyboardPagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GisKeyboardPage, gis_keyboard_page, GIS_TYPE_PAGE);
static void
gis_keyboard_page_finalize (GObject *object)
{
GisKeyboardPage *self = GIS_KEYBOARD_PAGE (object);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
if (priv->cancellable)
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
g_clear_object (&priv->permission);
g_clear_object (&priv->localed);
g_clear_object (&priv->input_settings);
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_input_options, g_strfreev);
G_OBJECT_CLASS (gis_keyboard_page_parent_class)->finalize (object);
}
static void
set_input_settings (GisKeyboardPage *self,
const char *type,
const char *id)
{
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
-
+ g_autoptr(GVariant) default_value = NULL;
+ g_autoptr(GVariant) value = NULL;
GVariantBuilder input_source_builder;
GVariantBuilder input_options_builder;
size_t i;
gboolean has_latin_layout = FALSE;
gboolean is_xkb_source = FALSE;
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));
+ default_value = g_settings_get_default_value (priv->input_settings, KEY_INPUT_SOURCES);
+ value = g_settings_get_value (priv->input_settings, KEY_INPUT_SOURCES);
+
+ if (!g_variant_equal (default_value, value))
+ return;
+
g_variant_builder_init (&input_source_builder, G_VARIANT_TYPE ("a(ss)"));
g_variant_builder_init (&input_options_builder, G_VARIANT_TYPE ("as"));
if (type != NULL && id != NULL) {
has_latin_layout = !gnome_input_source_is_non_latin (type, id);
if (g_str_equal (type, "xkb")) {
g_variant_builder_add (&input_source_builder, "(ss)", type, id);
is_xkb_source = TRUE;
}
}
for (i = 0; priv->default_input_source_ids && priv->default_input_source_ids[i] != NULL; i++) {
if (g_str_equal (id, priv->default_input_source_ids[i]) && g_str_equal (type, priv->default_input_source_types[i]))
continue;
g_variant_builder_add (&input_source_builder, "(ss)", priv->default_input_source_types[i], priv->default_input_source_ids[i]);
if (!gnome_input_source_is_non_latin (priv->default_input_source_types[i], priv->default_input_source_ids[i]))
has_latin_layout = TRUE;
}
if (type != NULL && id != NULL) {
if (!is_xkb_source) {
g_variant_builder_add (&input_source_builder, "(ss)", type, id);
}
}
if (!has_latin_layout) {
g_variant_builder_add (&input_source_builder, "(ss)", "xkb", "us");
--
2.41.0

View File

@ -0,0 +1,350 @@
From 775b9c5547f51679b7da05af170aa040d706b242 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 13 Aug 2023 10:30:11 -0400
Subject: [PATCH 10/12] gnome-initial-setup: Add OEM mode
OEM mode is designed to get run when a site has imaged a bunch
of machines, and handed them off to the user.
In this scenario, the user never saw the installer, so we need to
ask the user questions that the installer would have normally
asked them already.
For example, the installer likely asks language, but if the user
never saw the installer, then we need to ask language again.
---
gnome-initial-setup/gis-driver.c | 1 +
gnome-initial-setup/gis-driver.h | 5 +++--
gnome-initial-setup/gnome-initial-setup.c | 22 ++++++++++++++--------
3 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
index 41cd6e38..55b2493c 100644
--- a/gnome-initial-setup/gis-driver.c
+++ b/gnome-initial-setup/gis-driver.c
@@ -20,60 +20,61 @@
*/
#include "config.h"
#include "gnome-initial-setup.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#ifdef HAVE_WEBKITGTK_6_0
#include <webkit/webkit.h>
#else
#include <webkit2/webkit2.h>
#endif
#include "cc-common-language.h"
#include "gis-assistant.h"
/* Statically include this for now. Maybe later
* we'll generate this from glib-mkenums. */
GType
gis_driver_mode_get_type (void) {
static GType enum_type_id = 0;
if (G_UNLIKELY (!enum_type_id))
{
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_OEM, "GIS_DRIVER_MODE_OEM", "oem" },
{ GIS_DRIVER_MODE_SYSTEM, "GIS_DRIVER_MODE_SYSTEM", "system" },
{ GIS_DRIVER_MODE_ALL, "GIS_DRIVER_MODE_ALL", "all" },
{ 0, NULL, NULL }
};
enum_type_id = g_flags_register_static("GisDriverMode", values);
}
return enum_type_id;
}
enum {
REBUILD_PAGES,
LOCALE_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL];
typedef enum {
PROP_MODE = 1,
PROP_USERNAME,
PROP_SMALL_SCREEN,
PROP_PARENTAL_CONTROLS_ENABLED,
PROP_FULL_NAME,
PROP_AVATAR,
} GisDriverProperty;
static GParamSpec *obj_props[PROP_AVATAR + 1];
struct _GisDriver {
AdwApplication parent_instance;
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
index aedb9a73..49639bef 100644
--- a/gnome-initial-setup/gis-driver.h
+++ b/gnome-initial-setup/gis-driver.h
@@ -18,62 +18,63 @@
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __GIS_DRIVER_H__
#define __GIS_DRIVER_H__
#include "gis-assistant.h"
#include "gis-page.h"
#include <act/act-user-manager.h>
#include <gdm/gdm-client.h>
#include <adwaita.h>
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)
typedef enum {
UM_LOCAL,
UM_ENTERPRISE,
NUM_MODES,
} UmAccountMode;
typedef enum {
GIS_DRIVER_MODE_NEW_USER = 1 << 0,
GIS_DRIVER_MODE_EXISTING_USER = 1 << 1,
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),
+ GIS_DRIVER_MODE_OEM = 1 << 3,
+ GIS_DRIVER_MODE_SYSTEM = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER | GIS_DRIVER_MODE_OEM),
+ GIS_DRIVER_MODE_ALL = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_LIVE_USER | GIS_DRIVER_MODE_OEM),
} GisDriverMode;
GType gis_driver_mode_get_type (void);
GisAssistant *gis_driver_get_assistant (GisDriver *driver);
void gis_driver_set_user_permissions (GisDriver *driver,
ActUser *user,
const gchar *password);
void gis_driver_get_user_permissions (GisDriver *driver,
ActUser **user,
const gchar **password);
void gis_driver_set_parent_permissions (GisDriver *driver,
ActUser *parent,
const gchar *password);
void gis_driver_get_parent_permissions (GisDriver *driver,
ActUser **parent,
const gchar **password);
void gis_driver_set_account_mode (GisDriver *driver,
UmAccountMode mode);
UmAccountMode gis_driver_get_account_mode (GisDriver *driver);
void gis_driver_set_parental_controls_enabled (GisDriver *driver,
gboolean parental_controls_enabled);
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
index 2bd2d375..6fe57017 100644
--- a/gnome-initial-setup/gnome-initial-setup.c
+++ b/gnome-initial-setup/gnome-initial-setup.c
@@ -26,90 +26,91 @@
#include <adwaita.h>
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
#include <glib/gi18n.h>
#include "pages/welcome/gis-welcome-page.h"
#include "pages/language/gis-language-page.h"
#include "pages/keyboard/gis-keyboard-page.h"
#include "pages/network/gis-network-page.h"
#include "pages/timezone/gis-timezone-page.h"
#include "pages/privacy/gis-privacy-page.h"
#include "pages/software/gis-software-page.h"
#include "pages/goa/gis-goa-page.h"
#include "pages/account/gis-account-pages.h"
#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"
#define STATE_FILE GIS_WORKING_DIR "/state"
static gboolean force_existing_user_mode;
static gboolean force_live_user_mode;
+static gboolean force_oem_mode;
static GPtrArray *skipped_pages;
typedef GisPage *(*PreparePage) (GisDriver *driver);
typedef struct {
const gchar *page_id;
PreparePage prepare_page_func;
GisDriverMode modes;
} PageData;
#define PAGE(name, modes) { #name, gis_prepare_ ## name ## _page, modes }
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_ALL),
- PAGE (privacy, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (privacy, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_OEM),
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 (software, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_OEM),
+ PAGE (goa, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_OEM),
/* 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),
+ PAGE (account, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER | GIS_DRIVER_MODE_OEM),
+ PAGE (password, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER | GIS_DRIVER_MODE_OEM),
#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),
+ PAGE (parental_controls, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_OEM),
+ PAGE (parent_password, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_OEM),
#endif
- PAGE (summary, GIS_DRIVER_MODE_NEW_USER),
+ PAGE (summary, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_OEM),
PAGE (install, GIS_DRIVER_MODE_LIVE_USER),
{ NULL },
};
#undef PAGE
static gboolean
should_skip_page (const gchar *page_id,
gchar **skip_pages)
{
guint i = 0;
/* special case welcome. We only want to show it if language
* is skipped
*/
if (strcmp (page_id, "welcome") == 0)
return !should_skip_page ("language", skip_pages);
/* check through our skip pages list for pages we don't want */
if (skip_pages) {
while (skip_pages[i]) {
if (g_strcmp0 (skip_pages[i], page_id) == 0)
return TRUE;
i++;
}
}
return FALSE;
}
@@ -315,81 +316,86 @@ static gboolean
initial_setup_disabled_by_anaconda (void)
{
const gchar *file_name = SYSCONFDIR "/sysconfig/anaconda";
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) key_file = g_key_file_new ();
if (!g_key_file_load_from_file (key_file, file_name, G_KEY_FILE_NONE, &error)) {
if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
g_warning ("Could not read %s: %s", file_name, error->message);
}
return FALSE;
}
return g_key_file_get_boolean (key_file, "General", "post_install_tools_disabled", NULL);
}
int
main (int argc, char *argv[])
{
GisDriver *driver;
int status;
GOptionContext *context;
GisDriverMode mode;
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 },
+ { "oem", 0, 0, G_OPTION_ARG_NONE, &force_oem_mode,
+ _("Force OEM mode"), NULL },
{ NULL }
};
g_unsetenv ("GIO_USE_VFS");
/* By default, libadwaita reads settings from the Settings portal, which causes
* the portal to be started, which causes gnome-keyring to be started. This
* interferes with our attempt below to manually start gnome-keyring and set
* the login keyring password to a well-known value, which we overwrite with
* the user's password once they choose one.
*/
g_setenv ("ADW_DISABLE_PORTAL", "1", TRUE);
context = g_option_context_new (_("— GNOME initial setup"));
g_option_context_add_main_entries (context, entries, NULL);
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;
+ if (gis_kernel_command_line_has_argument ((const char *[]) { "gnome.oem_mode", NULL }))
+ force_oem_mode = TRUE;
+
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
g_message ("Starting gnome-initial-setup");
if (gis_get_mock_mode ())
g_message ("Mock mode: changes will not be saved to disk");
else
g_message ("Production mode: changes will be saved to disk");
skipped_pages = g_ptr_array_new_with_free_func (destroy_page);
mode = get_mode ();
/* When we are running as the gnome-initial-setup user we
* dont have a normal user session and need to initialize
* the keyring manually so that we can pass the credentials
* along to the new user in the handoff.
*/
if ((mode & GIS_DRIVER_MODE_SYSTEM) && !gis_get_mock_mode ())
gis_ensure_login_keyring ();
driver = gis_driver_new (mode);
adw_style_manager_set_color_scheme (adw_style_manager_get_default (),
ADW_COLOR_SCHEME_PREFER_LIGHT);
/* On first login, GNOME Shell offers to run a tour. If we also run Initial
* Setup, the two immovable, centred windows will sit atop one another.
* Until we have the ability to run Initial Setup in the "kiosk" mode, like
* it does in new-user mode, disable Initial Setup for existing users.
*
--
2.41.0

View File

@ -0,0 +1,51 @@
From a2a113bfebe80f6652ba5581647ee38d7a16a202 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 13 Aug 2023 16:33:49 -0400
Subject: [PATCH 11/12] 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
@@ -1,30 +1,31 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// DO NOT EDIT THIS FILE, it will be overwritten on update.
//
// Allow the gnome-initial-setup user to do certain actions without
// being interrupted by password dialogs
polkit.addRule(function(action, subject) {
if (subject.user !== 'gnome-initial-setup')
return undefined;
var actionMatches = (action.id.indexOf('org.freedesktop.hostname1.') === 0 ||
action.id.indexOf('org.freedesktop.NetworkManager.') === 0 ||
action.id.indexOf('org.freedesktop.locale1.') === 0 ||
action.id.indexOf('org.freedesktop.accounts.') === 0 ||
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.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)
return 'yes';
else
return 'auth_admin';
}
return undefined;
});
--
2.41.0

View File

@ -0,0 +1,117 @@
From a8942b1eec8e538f0a37d3862d1fa9bbe2370de7 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 22 Aug 2023 13:51:40 -0400
Subject: [PATCH 12/12] 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 6fe57017..f9b3923f 100644
--- a/gnome-initial-setup/gnome-initial-setup.c
+++ b/gnome-initial-setup/gnome-initial-setup.c
@@ -172,72 +172,95 @@ pages_to_skip_from_file (GisDriver *driver)
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;
}
}
/* 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;
+ 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);
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);
}
}
+
+ 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);
}
static void
destroy_pages_after (GisAssistant *assistant,
GisPage *page)
{
GList *pages, *l, *next;
pages = gis_assistant_get_all_pages (assistant);
for (l = pages; l != NULL; l = l->next)
if (l->data == page)
break;
l = l->next;
for (; l != NULL; l = next) {
next = l->next;
gis_assistant_remove_page (assistant, l->data);
}
}
static void
destroy_page (gpointer data)
{
GtkWidget *assistant;
GisPage *page;
--
2.41.0

View File

@ -19,15 +19,16 @@ Source1: vendor.conf
Patch: 0001-keyboard-stop-setting-current-input-source.patch
Patch: 0002-keyboard-write-to-mru-sources-setting-if-it-has-neve.patch
Patch: 0003-keyboard-Get-default-input-sources-from-gnome-deskto.patch
Patch: 0004-gnome-initial-setup-Bump-GLib-required-version-to-2..patch
Patch: 0005-driver-Specify-mode-via-flags-instead-of-boolean.patch
Patch: 0006-gnome-initial-setup-Add-live-user-mode.patch
Patch: 0007-initial-setup-Don-t-show-duplicated-pages-between-mo.patch
Patch: 0008-keyboard-Don-t-add-default-input-sources-if-input-so.patch
Patch: 0009-gnome-initial-setup-Add-OEM-mode.patch
Patch: 0010-polkit-Add-fedora-specfic-rules.patch
Patch: 0011-gnome-initial-setup-Read-etc-sysconfig-anaconda.patch
Patch: 0003-language-Don-t-proceed-until-localed-has-set-locale.patch
Patch: 0004-keyboard-Get-default-input-sources-from-gnome-deskto.patch
Patch: 0005-gnome-initial-setup-Bump-GLib-required-version-to-2..patch
Patch: 0006-driver-Specify-mode-via-flags-instead-of-boolean.patch
Patch: 0007-gnome-initial-setup-Add-live-user-mode.patch
Patch: 0008-initial-setup-Don-t-show-duplicated-pages-between-mo.patch
Patch: 0009-keyboard-Don-t-add-default-input-sources-if-input-so.patch
Patch: 0010-gnome-initial-setup-Add-OEM-mode.patch
Patch: 0011-polkit-Add-fedora-specfic-rules.patch
Patch: 0012-gnome-initial-setup-Read-etc-sysconfig-anaconda.patch
BuildRequires: desktop-file-utils
BuildRequires: gcc