commit 9f5602c5e3170f5deb154754108343bda4bb4b44 Author: MSVSphere Packaging Team Date: Fri Oct 25 14:52:48 2024 +0300 import gnome-initial-setup-46.alpha-10.el10 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8fc2c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/gnome-initial-setup-46.alpha.tar.xz diff --git a/.gnome-initial-setup.metadata b/.gnome-initial-setup.metadata new file mode 100644 index 0000000..2584484 --- /dev/null +++ b/.gnome-initial-setup.metadata @@ -0,0 +1 @@ +13aab9e21fccb0a12cf03f1937f5c8c4753d689f SOURCES/gnome-initial-setup-46.alpha.tar.xz diff --git a/SOURCES/0001-RHEL10-style-illustrations.patch b/SOURCES/0001-RHEL10-style-illustrations.patch new file mode 100644 index 0000000..a0604c6 --- /dev/null +++ b/SOURCES/0001-RHEL10-style-illustrations.patch @@ -0,0 +1,2119 @@ +From 66ee3493af1da7fd07c02f3da9fd25a0accfcea0 Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Tue, 20 Aug 2024 15:19:35 +0200 +Subject: [PATCH] RHEL10 style illustrations + +--- + .../pages/summary/ready-to-go.svg | 150 +- + .../pages/welcome/initial-setup-welcome.svg | 1886 +++++------------ + 2 files changed, 719 insertions(+), 1317 deletions(-) + +diff --git a/gnome-initial-setup/pages/summary/ready-to-go.svg b/gnome-initial-setup/pages/summary/ready-to-go.svg +index 9ad6af4c..d3238563 100644 +--- a/gnome-initial-setup/pages/summary/ready-to-go.svg ++++ b/gnome-initial-setup/pages/summary/ready-to-go.svg +@@ -1 +1,149 @@ +- +\ No newline at end of file ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/gnome-initial-setup/pages/welcome/initial-setup-welcome.svg b/gnome-initial-setup/pages/welcome/initial-setup-welcome.svg +index 74a7eec0..f22d1db6 100644 +--- a/gnome-initial-setup/pages/welcome/initial-setup-welcome.svg ++++ b/gnome-initial-setup/pages/welcome/initial-setup-welcome.svg +@@ -2,14 +2,36 @@ + ++ + + +@@ -319,7 +341,7 @@ + id="linearGradient58186" + x1="219.33958" + y1="85.201027" +- x2="258.7625" ++ x2="258.76251" + y2="85.201027" + gradientUnits="userSpaceOnUse" /> + + +- +- +- +- +- ++ + +- +- +- +- +- +- +- ++ d="m 0.5,0 h 1920 V 1080 H 0.5 Z" ++ transform="matrix(1.3333333,0,0,-1.3333333,18746.667,1440)" ++ id="path820" /> ++ ++ + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1212.5425,-413.30561)" ++ id="path758" /> ++ ++ + +- ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-2034.4901,-413.30561)" ++ id="path759" /> ++ ++ + +- +- +- +- +- +- +- +- +- ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1800.8155,-363.95301)" ++ id="path760" /> ++ ++ + ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1536.8673,-356.85521)" ++ id="path761" /> ++ ++ + ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1344.0865,60.252602)" ++ id="path762" /> ++ ++ + +- +- +- +- ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1447.9758,47.128576)" ++ id="path763" /> ++ ++ + ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-2166.0341,60.252602)" ++ id="path764" /> ++ ++ + ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1022.1535,-187.33658)" ++ id="path765" /> ++ ++ + ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1844.101,-187.33658)" ++ id="path766" /> ++ ++ ++ ++ ++ + ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1008.133,-20.844001)" ++ id="path768" /> ++ ++ + ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-2358.8156,-390.21271)" ++ id="path769" /> ++ ++ + +- +- ++ d="M 459.384,1182.8 H 3193.59 V -197.556 H 459.384 Z" ++ transform="translate(-1516.5483,-185.63738)" ++ id="path770" /> ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ transform="matrix(1.2317356,0,0,1.2317356,-327.6169,93.297611)" ++ style="display:inline;stroke-width:0.959464;enable-background:new" ++ id="g65" /> + +- +- +- +- +- +- ++ id="g4" ++ transform="matrix(0.61871582,0,0,0.61871582,235.77609,8.7849124)"> + +- +- +- ++ id="path533" ++ d="M 819.3578,384.4808 430.34181,600.60079 41.327153,384.4808 430.34181,168.36081" ++ style="fill:none;stroke:#ee0000;stroke-width:46.7933;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" /> + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ id="path534" ++ d="M 819.3578,742.49747 430.34181,958.61746 41.327153,742.49747 202.43382,652.99347" ++ style="fill:none;stroke:#ee0000;stroke-width:46.7933;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" /> ++ ++ ++ ++ + + ++ opacity="0.5" ++ id="g819" ++ clip-path="url(#clipPath820)" ++ transform="matrix(0.59163653,0,0,0.59163653,-10521.814,-2.1298915e-5)" ++ style="stroke-width:1.69023"> + ++ d="m 0,0 -174.068,-96.414 c -7.608,-4.213 -16.848,-4.213 -24.456,0 L -372.357,-0.13 c -9.818,5.438 -9.818,19.554 0,24.992 l 173.636,96.174 c 7.73,4.282 17.12,4.282 24.85,0 L 0,24.731 C 9.716,19.35 9.716,5.381 0,0 Z" ++ style="fill:none;stroke:#c9c9c9;stroke-width:10.1414;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0,28.7389;stroke-dashoffset:0;stroke-opacity:1;font-variation-settings:normal;opacity:1;vector-effect:none;fill-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" ++ transform="matrix(1.3333333,0,0,-1.3333333,20363.39,888.92587)" ++ clip-path="url(#clipPath758)" ++ id="path789" /> + ++ d="m 0,0 -174.068,-96.414 c -7.608,-4.213 -16.848,-4.213 -24.456,0 L -372.357,-0.13 c -9.818,5.438 -9.818,19.554 0,24.992 l 173.636,96.174 c 7.73,4.282 17.12,4.282 24.85,0 L 0,24.731 C 9.716,19.35 9.716,5.381 0,0 Z" ++ style="fill:none;stroke:#c9c9c9;stroke-width:10.1414;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0,28.7389;stroke-dashoffset:0;stroke-opacity:1;font-variation-settings:normal;opacity:1;vector-effect:none;fill-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" ++ transform="matrix(1.3333333,0,0,-1.3333333,21459.32,888.92587)" ++ clip-path="url(#clipPath759)" ++ id="path790" /> + ++ d="m 0,0 -174.068,-96.414 c -7.608,-4.213 -16.848,-4.213 -24.456,0 L -372.357,-0.13 c -9.818,5.438 -9.818,19.554 0,24.992 l 173.636,96.174 c 7.73,4.282 17.12,4.282 24.85,0 L 0,24.732 C 9.716,19.35 9.716,5.381 0,0 Z" ++ style="fill:none;stroke:#c9c9c9;stroke-width:10.1414;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;font-variation-settings:normal;opacity:1;vector-effect:none;fill-opacity:1;stroke-dashoffset:0;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" ++ transform="matrix(1.3333333,0,0,-1.3333333,21147.754,954.72933)" ++ clip-path="url(#clipPath760)" ++ id="path791" /> + +- +- +- +- +- +- ++ d="m 0,0 -234.78,-130.041 c -10.261,-5.683 -22.724,-5.683 -32.985,0 L -502.227,-0.176 c -13.243,7.335 -13.243,26.375 0,33.709 l 234.196,129.718 c 10.426,5.775 23.091,5.775 33.518,0 L 0,33.358 C 13.104,26.099 13.104,7.258 0,0 Z" ++ style="fill:none;stroke:#c9c9c9;stroke-width:10.1414;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;font-variation-settings:normal;opacity:1;vector-effect:none;fill-opacity:1;stroke-dashoffset:0;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" ++ transform="matrix(1.3333333,0,0,-1.3333333,20795.823,964.19307)" ++ clip-path="url(#clipPath761)" ++ id="path792" /> + ++ d="m 0,0 -234.78,-130.041 c -10.261,-5.683 -22.724,-5.683 -32.985,0 L -502.227,-0.176 c -13.243,7.335 -13.243,26.375 0,33.709 l 234.196,129.718 c 10.426,5.775 23.091,5.775 33.518,0 L 0,33.358 C 13.104,26.099 13.104,7.258 0,0 Z" ++ style="fill:none;stroke:#c9c9c9 icc-color(sRGB-IEC61966-2, 0.1, 0.78799438, 0.78799438, 0.78799438);stroke-width:10.1414;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" ++ transform="matrix(1.3333333,0,0,-1.3333333,20538.782,1520.3368)" ++ clip-path="url(#clipPath762)" ++ id="path793" /> + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ d="m 0,0 -132.029,-73.129 c -5.77,-3.196 -12.779,-3.196 -18.549,0 l -131.851,73.03 c -7.446,4.125 -7.446,14.832 0,18.957 l 131.701,72.946 c 5.863,3.248 12.986,3.248 18.849,0 L 0,18.759 C 7.369,14.677 7.369,4.082 0,0 Z" ++ style="fill:none;stroke:#c9c9c9 icc-color(sRGB-IEC61966-2, 0.1, 0.78799438, 0.78799438, 0.78799438);stroke-width:10.1414;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" ++ transform="matrix(1.3333333,0,0,-1.3333333,20677.301,1502.8381)" ++ clip-path="url(#clipPath763)" ++ id="path794" /> ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + ++ d="m 0,0 -195.801,-108.451 c -8.557,-4.74 -18.951,-4.74 -27.508,0 L -418.845,-0.147 c -11.044,6.117 -11.044,21.996 0,28.113 l 195.313,108.181 c 8.696,4.817 19.258,4.817 27.954,0 L 0,27.819 C 10.928,21.766 10.928,6.053 0,0 Z" ++ style="fill:none;stroke:#c9c9c9;stroke-width:10.1414;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;font-variation-settings:normal;opacity:1;vector-effect:none;fill-opacity:1;stroke-dashoffset:0;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1" ++ transform="matrix(1.3333333,0,0,-1.3333333,21706.501,336.156)" ++ clip-path="url(#clipPath788)" ++ id="path819" /> + +- +- + +-- +2.45.2 + diff --git a/SOURCES/live-user-mode.patch b/SOURCES/live-user-mode.patch new file mode 100644 index 0000000..b6a12c5 --- /dev/null +++ b/SOURCES/live-user-mode.patch @@ -0,0 +1,2870 @@ +From 575edeab57c891a7053279c676e82bebe53222d3 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 15 Aug 2023 10:53:41 -0400 +Subject: [PATCH 01/16] 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 beb96ecd..32b3fe46 100644 +--- a/gnome-initial-setup/meson.build ++++ b/gnome-initial-setup/meson.build +@@ -51,7 +51,7 @@ dependencies = [ + dependency ('gsettings-desktop-schemas', version: '>= 3.37.1'), + dependency ('fontconfig'), + 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 5d30fcd1..00e24d7b 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 +-- +2.43.0 + + +From 60a2db34bd50d561e716a63dd526ee7ff4810a29 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sat, 9 Sep 2023 17:07:46 -0400 +Subject: [PATCH 02/16] 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); + } + +-- +2.43.0 + + +From 1478cce3663bfa276066c073be3bbb65bc4b1785 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 8 Sep 2023 11:02:39 -0400 +Subject: [PATCH 03/16] 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); + } + +-- +2.43.0 + + +From e8d5b6a4c1ee9bfb3f8ed7dbe5f25053fae7a1ae Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 24 Aug 2023 21:19:40 -0400 +Subject: [PATCH 04/16] 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); +-- +2.43.0 + + +From 7b83c89d8b2fe2f9de5f7f364a7af5f2f4fcc605 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 13 Aug 2023 09:09:56 -0400 +Subject: [PATCH 05/16] 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 | 126 +++++++++++++--------- + 3 files changed, 92 insertions(+), 59 deletions(-) + +diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c +index 0b3f542f..4325b631 100644 +--- a/gnome-initial-setup/gis-driver.c ++++ b/gnome-initial-setup/gis-driver.c +@@ -30,8 +30,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 +@@ -39,12 +37,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; + } +@@ -645,7 +644,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 adb04075..a079c705 100644 +--- a/gnome-initial-setup/gnome-initial-setup.c ++++ b/gnome-initial-setup/gnome-initial-setup.c +@@ -55,26 +55,26 @@ 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 (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 (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 }, + }; + +@@ -105,26 +105,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: +@@ -132,28 +121,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 +@@ -196,7 +225,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); +@@ -215,13 +245,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; + +-- +2.43.0 + + +From 68391446ee06083a06899cdadb09ca90b4b40af3 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 30 Aug 2023 15:08:23 -0400 +Subject: [PATCH 06/16] 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); +-- +2.43.0 + + +From f1e4b58ced27b028e13dd9bb29794419dc08fb72 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 13 Aug 2023 09:39:07 -0400 +Subject: [PATCH 07/16] 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 | 24 +- + .../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, 700 insertions(+), 17 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 4325b631..6a4727cc 100644 +--- a/gnome-initial-setup/gis-driver.c ++++ b/gnome-initial-setup/gis-driver.c +@@ -40,6 +40,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 } + }; +@@ -786,7 +788,7 @@ gis_driver_startup (GApplication *app) + + G_APPLICATION_CLASS (gis_driver_parent_class)->startup (app); + +- 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 a079c705..02ca2808 100644 +--- a/gnome-initial-setup/gnome-initial-setup.c ++++ b/gnome-initial-setup/gnome-initial-setup.c +@@ -40,13 +40,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; + +@@ -64,17 +67,19 @@ 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 (account, 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), + #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 }, + }; + +@@ -118,8 +123,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: +@@ -275,6 +280,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; + } +@@ -308,6 +315,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 } + }; + +@@ -326,6 +335,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); +@@ -344,7 +356,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 . ++ */ ++ ++/* 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 . ++ */ ++ ++#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 @@ ++ ++ ++ ++ +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 @@ ++ ++ ++ ++ gis-install-page.ui ++ gis-install-page.css ++ ++ ++ +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 8d327f69..ff8406ba 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); +-- +2.43.0 + + +From 3f15601af333aeddb8e4458e69f81023a8184a8f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 16 Aug 2023 10:47:13 -0400 +Subject: [PATCH 08/16] 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 6a4727cc..78265527 100644 +--- a/gnome-initial-setup/gis-driver.c ++++ b/gnome-initial-setup/gis-driver.c +@@ -101,6 +101,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) +@@ -131,6 +133,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 02ca2808..4e2aa5af 100644 +--- a/gnome-initial-setup/gnome-initial-setup.c ++++ b/gnome-initial-setup/gnome-initial-setup.c +@@ -48,6 +48,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; + +@@ -119,6 +121,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: +@@ -187,6 +190,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); + } + +@@ -396,6 +419,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) + { +@@ -407,6 +470,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 00e24d7b..95fe8e51 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) +-- +2.43.0 + + +From 935b2cca6dd7e3ce31e2540d90e5864190885d81 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 13 Aug 2023 16:33:49 -0400 +Subject: [PATCH 09/16] 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) +-- +2.43.0 + + +From 03073bd42bf01f5d051f299860be40afd1844447 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 22 Aug 2023 13:51:40 -0400 +Subject: [PATCH 10/16] 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 4e2aa5af..2de3ecab 100644 +--- a/gnome-initial-setup/gnome-initial-setup.c ++++ b/gnome-initial-setup/gnome-initial-setup.c +@@ -196,6 +196,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); +@@ -208,6 +210,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); +-- +2.43.0 + + +From baaa29d56bbb91f3ad15f90e3db98eea446b9adb Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Wed, 17 Jan 2024 12:29:54 -0600 +Subject: [PATCH 11/16] Fix criticals in set_localed_input() + +If the default input sources do not match the current input sources, +these won't be set in set_input_settings() and we shouldn't try to use +them. + +Fixes: (gnome-initial-setup:41149): GLib-CRITICAL **: 10:09:25.599: g_strjoinv: assertion 'str_array != NULL' failed +--- + gnome-initial-setup/pages/keyboard/gis-keyboard-page.c | 4 ++-- + 1 file changed, 2 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 7801667c..3b59a0bf 100644 +--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c ++++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c +@@ -253,12 +253,12 @@ set_localed_input (GisKeyboardPage *self) + g_autofree char *variants = NULL; + g_autofree char *options = NULL; + +- if (!priv->localed) ++ if (!priv->localed || !priv->system_layouts || !priv->system_variants) + return; + + layouts = g_strjoinv (",", priv->system_layouts); + variants = g_strjoinv (",", priv->system_variants); +- options = g_strjoinv (",", priv->system_options); ++ options = priv->system_options ? g_strjoinv (",", priv->system_options) : g_strdup (""); + + g_dbus_proxy_call (priv->localed, + "SetX11Keyboard", +-- +2.43.0 + + +From b46a3d7e6df08030680c2e7aaa6408c28315e75f Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 19 Jan 2024 15:49:15 -0600 +Subject: [PATCH 12/16] assistant: assert next page exists when switching to + next page + +If there is no next page, then we should crash nicely on this assert +rather than not so nicely. +--- + gnome-initial-setup/gis-assistant.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/gnome-initial-setup/gis-assistant.c b/gnome-initial-setup/gis-assistant.c +index 8a7fc52b..c1af2943 100644 +--- a/gnome-initial-setup/gis-assistant.c ++++ b/gnome-initial-setup/gis-assistant.c +@@ -111,7 +111,9 @@ find_next_page (GisAssistant *self, + static void + switch_to_next_page (GisAssistant *assistant) + { +- switch_to (assistant, find_next_page (assistant, assistant->current_page)); ++ GisPage *next = find_next_page (assistant, assistant->current_page); ++ g_assert (next != NULL); ++ switch_to (assistant, next); + } + + static void +-- +2.43.0 + + +From deecf58106544ac8603575cb80e79ddfa1b822ba Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 19 Jan 2024 15:50:33 -0600 +Subject: [PATCH 13/16] summary: don't crash if there is no user account to + create + +--- + gnome-initial-setup/pages/summary/gis-summary-page.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/gnome-initial-setup/pages/summary/gis-summary-page.c b/gnome-initial-setup/pages/summary/gis-summary-page.c +index 8a526b64..8c005640 100644 +--- a/gnome-initial-setup/pages/summary/gis-summary-page.c ++++ b/gnome-initial-setup/pages/summary/gis-summary-page.c +@@ -151,6 +151,11 @@ log_user_in (GisSummaryPage *page) + return; + } + ++ if (!priv->user_account) { ++ g_info ("No new user account (was the account page skipped?); not initiating login"); ++ return; ++ } ++ + g_signal_connect (user_verifier, "info", + G_CALLBACK (on_info), page); + g_signal_connect (user_verifier, "problem", +-- +2.43.0 + + +From b3e54dbaa09e944e537050c7393cd69e44488384 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 19 Jan 2024 15:52:03 -0600 +Subject: [PATCH 14/16] Don't show warnings when failing to connect to gdm + +This is an expected condition. We need to log it since it might be +needed when debugging, but a warning is overkill. +--- + gnome-initial-setup/gis-driver.c | 3 ++- + gnome-initial-setup/pages/install/gis-install-page.c | 2 +- + gnome-initial-setup/pages/summary/gis-summary-page.c | 2 +- + 3 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c +index 78265527..653ba56b 100644 +--- a/gnome-initial-setup/gis-driver.c ++++ b/gnome-initial-setup/gis-driver.c +@@ -777,7 +777,8 @@ connect_to_gdm (GisDriver *driver) + driver->user_verifier = gdm_client_get_user_verifier_sync (driver->client, NULL, &error); + + if (error != NULL) { +- g_warning ("Failed to open connection to GDM: %s", error->message); ++ /* Not a warning because this is expected if running in a user session */ ++ g_message ("Failed to open connection to GDM: %s", error->message); + g_clear_object (&driver->user_verifier); + g_clear_object (&driver->greeter); + g_clear_object (&driver->client); +diff --git a/gnome-initial-setup/pages/install/gis-install-page.c b/gnome-initial-setup/pages/install/gis-install-page.c +index 36ed7539..850c8241 100644 +--- a/gnome-initial-setup/pages/install/gis-install-page.c ++++ b/gnome-initial-setup/pages/install/gis-install-page.c +@@ -131,7 +131,7 @@ log_user_in (GisInstallPage *page) + + if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver, + &greeter, &user_verifier)) { +- g_warning ("No GDM connection; not initiating login"); ++ g_info ("No GDM connection; not initiating login"); + return; + } + +diff --git a/gnome-initial-setup/pages/summary/gis-summary-page.c b/gnome-initial-setup/pages/summary/gis-summary-page.c +index 8c005640..1352cb41 100644 +--- a/gnome-initial-setup/pages/summary/gis-summary-page.c ++++ b/gnome-initial-setup/pages/summary/gis-summary-page.c +@@ -147,7 +147,7 @@ log_user_in (GisSummaryPage *page) + + if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver, + &greeter, &user_verifier)) { +- g_warning ("No GDM connection; not initiating login"); ++ g_info ("No GDM connection; not initiating login"); + return; + } + +-- +2.43.0 + + +From fa8caf710c38c41fc17f6dacc1c964a849e4c6e1 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Fri, 19 Jan 2024 15:58:09 -0600 +Subject: [PATCH 15/16] Never skip the summary page if available + +This avoids a crash when finishing the welcome page if there are no +other pages available. +--- + gnome-initial-setup/gnome-initial-setup.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c +index 2de3ecab..54bca86f 100644 +--- a/gnome-initial-setup/gnome-initial-setup.c ++++ b/gnome-initial-setup/gnome-initial-setup.c +@@ -99,6 +99,16 @@ should_skip_page (const gchar *page_id, + if (strcmp (page_id, "welcome") == 0) + return !should_skip_page ("language", skip_pages); + ++ /* We have to make sure the welcome page is not the last page because it ++ * unconditionally attempts to load the next page. So, always show the ++ * summary page. ++ * ++ * This doesn't work in existing user mode, but that's OK because we don't ++ * skip arbitrary previously-visited pages when in existing user mode. ++ */ ++ if (strcmp (page_id, "summary") == 0) ++ return FALSE; ++ + /* check through our skip pages list for pages we don't want */ + if (skip_pages) { + while (skip_pages[i]) { +-- +2.43.0 + + +From b4e51c75dce43fb8095909278122c96a32b7a62d Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Mon, 22 Jan 2024 14:07:15 -0600 +Subject: [PATCH 16/16] Fix failure to log into user account + +Currently gis_driver_get_user_permissions() is guaranteed to fail +because we call it after gis_driver_save_data(), which creates the user +account. We need to call it later at the right point. + +Also, let's own the user_password that we store on the summary and +install page. Even if it's not expected to change, it doesn't seem very +safe to rely on the GisDriver not deleting it. +--- + .../pages/install/gis-install-page.c | 41 ++++++++++++++---- + .../pages/summary/gis-summary-page.c | 42 ++++++++++++------- + 2 files changed, 59 insertions(+), 24 deletions(-) + +diff --git a/gnome-initial-setup/pages/install/gis-install-page.c b/gnome-initial-setup/pages/install/gis-install-page.c +index 850c8241..be4d6968 100644 +--- a/gnome-initial-setup/pages/install/gis-install-page.c ++++ b/gnome-initial-setup/pages/install/gis-install-page.c +@@ -43,9 +43,7 @@ struct _GisInstallPagePrivate { + GtkWidget *install_button; + AdwStatusPage *status_page; + GDesktopAppInfo *installer; +- +- ActUser *user_account; +- const gchar *user_password; ++ char *user_password; + }; + typedef struct _GisInstallPagePrivate GisInstallPagePrivate; + +@@ -128,6 +126,24 @@ log_user_in (GisInstallPage *page) + g_autoptr(GError) error = NULL; + GdmGreeter *greeter = NULL; + GdmUserVerifier *user_verifier = NULL; ++ ActUser *user_account = NULL; ++ const char *user_password = NULL; ++ ++ gis_driver_get_user_permissions (GIS_PAGE (page)->driver, ++ &user_account, ++ &user_password); ++ if (user_account == NULL) { ++ g_info ("No new user account (was the account page skipped?); not initiating login"); ++ return; ++ } ++ g_assert (priv->user_password == NULL); ++ priv->user_password = g_strdup (user_password); ++ ++ if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver, ++ &greeter, &user_verifier)) { ++ g_info ("No GDM connection; not initiating login"); ++ return; ++ } + + if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver, + &greeter, &user_verifier)) { +@@ -149,7 +165,7 @@ log_user_in (GisInstallPage *page) + + gdm_user_verifier_call_begin_verification_for_user_sync (user_verifier, + SERVICE_NAME, +- act_user_get_user_name (priv->user_account), ++ act_user_get_user_name (user_account), + NULL, &error); + + if (error != NULL) +@@ -259,11 +275,6 @@ 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); + } +@@ -341,6 +352,17 @@ gis_install_page_constructed (GObject *object) + gtk_widget_set_visible (GTK_WIDGET (page), TRUE); + } + ++static void ++gis_install_page_finalize (GObject *object) ++{ ++ GisInstallPage *page = GIS_INSTALL_PAGE (object); ++ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page); ++ ++ g_clear_pointer (&priv->user_password, g_free); ++ ++ G_OBJECT_CLASS (gis_install_page_parent_class)->finalize (object); ++} ++ + static void + gis_install_page_locale_changed (GisPage *page) + { +@@ -365,6 +387,7 @@ gis_install_page_class_init (GisInstallPageClass *klass) + page_class->locale_changed = gis_install_page_locale_changed; + page_class->shown = gis_install_page_shown; + object_class->constructed = gis_install_page_constructed; ++ object_class->finalize = gis_install_page_finalize; + } + + static void +diff --git a/gnome-initial-setup/pages/summary/gis-summary-page.c b/gnome-initial-setup/pages/summary/gis-summary-page.c +index 1352cb41..1fc14556 100644 +--- a/gnome-initial-setup/pages/summary/gis-summary-page.c ++++ b/gnome-initial-setup/pages/summary/gis-summary-page.c +@@ -40,9 +40,7 @@ + struct _GisSummaryPagePrivate { + GtkWidget *start_button; + AdwStatusPage *status_page; +- +- ActUser *user_account; +- const gchar *user_password; ++ char *user_password; + }; + typedef struct _GisSummaryPagePrivate GisSummaryPagePrivate; + +@@ -144,15 +142,22 @@ log_user_in (GisSummaryPage *page) + g_autoptr(GError) error = NULL; + GdmGreeter *greeter = NULL; + GdmUserVerifier *user_verifier = NULL; ++ ActUser *user_account = NULL; ++ const char *user_password = NULL; + +- if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver, +- &greeter, &user_verifier)) { +- g_info ("No GDM connection; not initiating login"); ++ gis_driver_get_user_permissions (GIS_PAGE (page)->driver, ++ &user_account, ++ &user_password); ++ if (user_account == NULL) { ++ g_info ("No new user account (was the account page skipped?); not initiating login"); + return; + } ++ g_assert (priv->user_password == NULL); ++ priv->user_password = g_strdup (user_password); + +- if (!priv->user_account) { +- g_info ("No new user account (was the account page skipped?); not initiating login"); ++ if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver, ++ &greeter, &user_verifier)) { ++ g_info ("No GDM connection; not initiating login"); + return; + } + +@@ -171,11 +176,11 @@ log_user_in (GisSummaryPage *page) + /* We are in NEW_USER mode and we want to make it possible for third + * parties to find out which user ID we created. + */ +- add_uid_file (act_user_get_uid (priv->user_account)); ++ add_uid_file (act_user_get_uid (user_account)); + + gdm_user_verifier_call_begin_verification_for_user_sync (user_verifier, + SERVICE_NAME, +- act_user_get_user_name (priv->user_account), ++ act_user_get_user_name (user_account), + NULL, &error); + + if (error != NULL) +@@ -214,11 +219,6 @@ gis_summary_page_shown (GisPage *page) + { + GisSummaryPage *summary = GIS_SUMMARY_PAGE (page); + GisSummaryPagePrivate *priv = gis_summary_page_get_instance_private (summary); +- 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->start_button); + } +@@ -264,6 +264,17 @@ gis_summary_page_constructed (GObject *object) + gtk_widget_set_visible (GTK_WIDGET (page), TRUE); + } + ++static void ++gis_summary_page_finalize (GObject *object) ++{ ++ GisSummaryPage *page = GIS_SUMMARY_PAGE (object); ++ GisSummaryPagePrivate *priv = gis_summary_page_get_instance_private (page); ++ ++ g_clear_pointer (&priv->user_password, g_free); ++ ++ G_OBJECT_CLASS (gis_summary_page_parent_class)->finalize (object); ++} ++ + static void + gis_summary_page_locale_changed (GisPage *page) + { +@@ -286,6 +297,7 @@ gis_summary_page_class_init (GisSummaryPageClass *klass) + page_class->locale_changed = gis_summary_page_locale_changed; + page_class->shown = gis_summary_page_shown; + object_class->constructed = gis_summary_page_constructed; ++ object_class->finalize = gis_summary_page_finalize; + } + + static void +-- +2.43.0 + diff --git a/SOURCES/vendor.conf b/SOURCES/vendor.conf new file mode 100644 index 0000000..bc78d41 --- /dev/null +++ b/SOURCES/vendor.conf @@ -0,0 +1,5 @@ +[live_user pages] +skip=privacy;timezone;software;goa;network; + +[install] +application=anaconda.desktop diff --git a/SPECS/gnome-initial-setup.spec b/SPECS/gnome-initial-setup.spec new file mode 100644 index 0000000..eba30c8 --- /dev/null +++ b/SPECS/gnome-initial-setup.spec @@ -0,0 +1,882 @@ +## START: Set by rpmautospec +## (rpmautospec version 0.6.5) +## RPMAUTOSPEC: autorelease, autochangelog +%define autorelease(e:s:pb:n) %{?-p:0.}%{lua: + release_number = 10; + base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); + print(release_number + base_release_number - 1); +}%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} +## END: Set by rpmautospec + +%global nm_version 1.2 +%global nma_version 1.0 +%global glib_required_version 2.63.1 +%global gtk_required_version 4.6 +%global geoclue_version 2.3.1 +%global gnome_desktop_version 44.0-7 + +%global tarball_version %%(echo %{version} | tr '~' '.') + +%if 0%{?rhel} +%bcond_with webkitgtk +%else +%bcond_without webkitgtk +%endif + +Name: gnome-initial-setup +Version: 46.alpha +Release: %autorelease +Summary: Bootstrapping your OS + +License: GPL-2.0-or-later +URL: https://wiki.gnome.org/Design/OS/InitialSetup +Source0: https://download.gnome.org/sources/%{name}/46/%{name}-%{tarball_version}.tar.xz +Source1: vendor.conf + +# https://gitlab.gnome.org/GNOME/gnome-initial-setup/-/merge_requests/200 +Patch: live-user-mode.patch +# Downstream branding +Patch: 0001-RHEL10-style-illustrations.patch + +BuildRequires: desktop-file-utils +BuildRequires: gcc +BuildRequires: meson +BuildRequires: pkgconfig(accountsservice) +BuildRequires: pkgconfig(fontconfig) +BuildRequires: pkgconfig(gdm) +BuildRequires: pkgconfig(geocode-glib-2.0) +BuildRequires: pkgconfig(gio-2.0) >= %{glib_required_version} +BuildRequires: pkgconfig(gio-unix-2.0) >= %{glib_required_version} +BuildRequires: pkgconfig(glib-2.0) >= %{glib_required_version} +BuildRequires: pkgconfig(gnome-desktop-4) +BuildRequires: pkgconfig(gsettings-desktop-schemas) +BuildRequires: pkgconfig(gstreamer-1.0) +BuildRequires: pkgconfig(gtk4) >= %{gtk_required_version} +BuildRequires: pkgconfig(gweather4) +BuildRequires: pkgconfig(ibus-1.0) +BuildRequires: pkgconfig(iso-codes) +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(krb5) +BuildRequires: pkgconfig(libadwaita-1) +BuildRequires: pkgconfig(libgeoclue-2.0) >= %{geoclue_version} +BuildRequires: pkgconfig(libnma-gtk4) >= %{nma_version} +BuildRequires: pkgconfig(libnm) >= %{nm_version} +BuildRequires: pkgconfig(libsecret-1) +BuildRequires: pkgconfig(packagekit-glib2) +BuildRequires: pkgconfig(pango) +BuildRequires: pkgconfig(polkit-gobject-1) +BuildRequires: pkgconfig(pwquality) +BuildRequires: pkgconfig(rest-1.0) +%if %{with webkitgtk} +BuildRequires: pkgconfig(webkitgtk-6.0) +%endif + +# gnome-initial-setup is being run by gdm +Requires: gdm +Requires: geoclue2-libs%{?_isa} >= %{geoclue_version} +Requires: glib2%{?_isa} >= %{glib_required_version} +Requires: gnome-desktop4%{?_isa} >= %{gnome_desktop_version} +# we install a rules file +Requires: polkit-js-engine +Requires: /usr/bin/tecla + +Requires(pre): shadow-utils + +Provides: user(%name) + +# https://fedoraproject.org/wiki/Changes/EncourageI686LeafRemoval +ExcludeArch: %{ix86} + +%description +GNOME Initial Setup is an alternative to firstboot, providing +a good setup experience to welcome you to your system, and walks +you through configuring it. It is integrated with gdm. + +%prep +%autosetup -p1 -n %{name}-%{tarball_version} + +%build +%meson \ + -Dparental_controls=disabled \ +%if !%{with webkitgtk} + -Dwebkitgtk=disabled \ +%endif + %{nil} +%meson_build + +%install +%meson_install + +desktop-file-validate %{buildroot}%{_sysconfdir}/xdg/autostart/gnome-initial-setup-copy-worker.desktop +desktop-file-validate %{buildroot}%{_datadir}/applications/gnome-initial-setup.desktop + +mkdir -p %{buildroot}%{_datadir}/gnome-initial-setup +cp %{SOURCE1} %{buildroot}%{_datadir}/gnome-initial-setup/ + +%find_lang %{name} + +%pre +# we do not use sysusers yet because we need /var/lib/gnome-initial-setup +# to be owned by the gnome-initial-setup user. please do not convert +# to sysusers without making sure this is handled, maybe by tmpfiles +useradd -rM -d /run/gnome-initial-setup/ -s /sbin/nologin %{name} &>/dev/null || : + +%files -f %{name}.lang +%license COPYING +%doc NEWS README.md +%attr(-, gnome-initial-setup, gnome-initial-setup) %dir %{_localstatedir}/lib/gnome-initial-setup +%ghost %{_localstatedir}/gnome-initial-setup/state +%{_libexecdir}/gnome-initial-setup +%{_libexecdir}/gnome-initial-setup-copy-worker +%{_sysconfdir}/xdg/autostart/gnome-initial-setup-copy-worker.desktop +%{_sysconfdir}/xdg/autostart/gnome-initial-setup-first-login.desktop +%{_datadir}/applications/gnome-initial-setup.desktop +%{_datadir}/dconf/profile/gnome-initial-setup +%dir %{_datadir}/gnome-initial-setup +%{_datadir}/gnome-initial-setup/initial-setup-dconf-defaults +%{_datadir}/gnome-initial-setup/vendor.conf +%{_datadir}/gnome-session/sessions/gnome-initial-setup.session +%{_datadir}/gnome-shell/modes/initial-setup.json +%{_datadir}/polkit-1/rules.d/20-gnome-initial-setup.rules +%{_sysusersdir}/gnome-initial-setup.conf +%{_userunitdir}/* + +%changelog +* Fri Oct 25 2024 MSVSphere Packaging Team - 46.alpha-10 +- Rebuilt for MSVSphere 10 + +## START: Generated by rpmautospec +* Tue Aug 20 2024 Tomas Popela - 46.alpha-10 +- Use branded illustrations + +* Thu Aug 08 2024 Tomas Pelka - 46.alpha-9 +- Add gating.yaml via API + +* Mon Jun 24 2024 Troy Dawson - 46.alpha-8 +- Bump release for June 2024 mass rebuild + +* Wed Feb 07 2024 Adam Williamson - 46.alpha-7 +- Revert "Use upstream sysusers configuration" + +* Mon Jan 22 2024 Michael Catanzaro - 46.alpha-6 +- Update live-user-mode.patch again + +* Fri Jan 19 2024 Michael Catanzaro - 46.alpha-5 +- Update live-user-mode patch + +* Thu Jan 18 2024 David King - 46.alpha-4 +- Use upstream sysusers configuration + +* Wed Jan 17 2024 Yaakov Selkowitz - 46.alpha-3 +- ExcludeArch i686 + +* Wed Jan 17 2024 Michael Catanzaro - 46.alpha-2 +- Fix URL + +* Wed Jan 17 2024 Michael Catanzaro - 46.alpha-1 +- Update to 46.alpha + +* Tue Sep 19 2023 Ray Strode - 45.0-3 +- Fix failure from bug in back button patch + +* Tue Sep 19 2023 Michael Catanzaro - 45.0-2 +- Update to 45.0 and refresh live user mode patchset + +* Tue Sep 19 2023 Michael Catanzaro - 45.0-1 +- Update to 45.0 + +* Mon Sep 11 2023 Ray Strode - 45~beta-13 +- Fix crash in new user mode + +* Sat Sep 09 2023 Ray Strode - 45~beta-12 +- Add missing patches + +* Sat Sep 09 2023 Ray Strode - 45~beta-11 +- Select US by default on Russian keyboards + +* Fri Sep 08 2023 Ray Strode - 45~beta-10 +- drop unused patches + +* Fri Sep 08 2023 Ray Strode - 45~beta-9 +- Don't let language page proceed until it has committed its changes + +* Thu Sep 07 2023 Ray Strode - 45~beta-8 +- Fix keyboard page next button that can't be buttoned + +* Mon Aug 28 2023 Ray Strode - 45~beta-7 +- More keyboard configuration updates + +* Sat Aug 26 2023 Ray Strode - 45~beta-6 +- Update to use slightly tweaked default input sources api from gnome- + desktop + +* Sat Aug 26 2023 Ray Strode - 45~beta-5 +- Clean up gnome-desktop requires + +* Sat Aug 26 2023 Ray Strode - 45~beta-4 +- Add keyboard and input method handling fixes + +* Mon Aug 21 2023 Ray Strode - 45~beta-3 +- Add liveuser mode and switch vendor.conf to accomodate it + +* Mon Aug 07 2023 Kalev Lember - 45~beta-2 +- Sort files list + +* Mon Aug 07 2023 Kalev Lember - 45~beta-1 +- Update to 45.beta +- Requiring tecla instead of gkbd-keyboard-display + +* Wed Jul 19 2023 Fedora Release Engineering - 44.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Thu Mar 23 2023 Michael Catanzaro - 44.0-2 +- Add patch to stop calling 'fedora-third-party disable' + +* Fri Mar 17 2023 David King - 44.0-1 +- Update to 44.0 + +* Thu Mar 09 2023 Michael Catanzaro - 44~rc-2 +- Rebuild for WebKitGTK 2.39.91 + +* Sat Mar 04 2023 David King - 44~rc-1 +- Update to 44.rc + +* Wed Feb 22 2023 Michael Catanzaro - 44~beta-2 +- Rebuild for WebKitGTK 2.39.90 + +* Wed Feb 15 2023 David King - 44~beta-1 +- Update to 44.beta + +* Mon Feb 06 2023 David King - 44~alpha.2-1 +- Update to 44.alpha.2 + +* Wed Feb 01 2023 Michael Catanzaro - 43.1-6 +- Rebuild for WebKitGTK 2.39.6/2.39.7 + +* Sat Jan 21 2023 Michael Catanzaro - 43.1-5 +- Build for WebKitGTK 2.39.5 + +* Thu Jan 19 2023 Fedora Release Engineering - 43.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Tue Dec 06 2022 Michael Catanzaro - 43.1-3 +- Fix WebKitGTK build dependency + +* Mon Dec 05 2022 Michael Catanzaro - 43.1-2 +- Build against webkitgtk-6.0 + +* Thu Oct 27 2022 David King - 43.1-1 +- Update to 43.1 + +* Wed Sep 21 2022 Kalev Lember - 43.0-3 +- Fix a few more issues with enterprise login + +* Fri Sep 16 2022 Kalev Lember - 43.0-2 +- Fix criticals when setting up enterprise login + +* Fri Sep 16 2022 Kalev Lember - 43.0-1 +- Update to 43.0 + +* Wed Sep 07 2022 Kalev Lember - 43~rc.1-1 +- Update to 43.rc.1 + +* Tue Sep 06 2022 Kalev Lember - 43~rc-3 +- Backport an upstream patch to fix the enterprise login dialog + +* Tue Sep 06 2022 Kalev Lember - 43~rc-2 +- Drop obsolete libhandy dep + +* Tue Sep 06 2022 Kalev Lember - 43~rc-1 +- Update to 43.rc + +* Sat Aug 13 2022 Adam Williamson - 43~beta-2 +- Backport MR#156 to fix page skipping + +* Mon Aug 08 2022 Kalev Lember - 43~beta-1 +- Update to 43.beta +- Switch to gtk4 + +* Thu Jul 21 2022 Fedora Release Engineering - 43~alpha.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Tue Jul 19 2022 Milan Crha - 43~alpha.1-1 +- Update to 43.alpha; Switch to WebKitGTK API 4.1 (using libsoup3) + +* Wed Jun 29 2022 Michael Catanzaro - 42.2-4 +- Update timezone map + +* Tue Jun 21 2022 Michael Catanzaro - 42.2-3 +- Do not manually specify vendor.conf path + +* Fri May 27 2022 David King - 42.2-1 +- Update to 42.2 + +* Thu Apr 21 2022 David King - 42.1.1-1 +- Update to 42.1.1 + +* Wed Apr 06 2022 David King - 42.1-1 +- Update to 42.1 + +* Thu Mar 24 2022 David King - 42.0.1-1 +- Update to 42.0.1 + +* Wed Mar 23 2022 Adam Williamson - 42.0-3 +- Backport proposed upstream fix for keyring issue (#2066424) + +* Mon Mar 21 2022 Adam Williamson - 42.0-2 +- Revert dark theme support to fix user keyring password (#2066424) + +* Fri Mar 18 2022 David King - 42.0-1 +- Update to 42.0 + +* Mon Mar 07 2022 David King - 42~rc-1 +- Update to 42.rc + +* Sun Feb 13 2022 David King - 42~beta-1 +- Update to 42.beta + +* Thu Jan 20 2022 Fedora Release Engineering - 42~alpha.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Wed Jan 12 2022 David King - 42~alpha.1-2 +- Rebuild against gnome-desktop4 + +* Wed Jan 12 2022 David King - 42~alpha.1-1 +- Update to 42.alpha.1 + +* Tue Dec 07 2021 Kalev Lember - 41.2-1 +- Update to 41.2 + +* Fri Sep 17 2021 Kalev Lember - 41.0-1 +- Update to 41.0 + +* Tue Sep 14 2021 Kalev Lember - 41~rc-3 +- Disable parental controls support as per Workstation WG decision (#2004259) + +* Tue Sep 14 2021 Michael Catanzaro - 41~rc-2 +- Fix new Fedora third party software page + +* Wed Sep 08 2021 Kalev Lember - 41~rc-1 +- Update to 41.rc + +* Tue Aug 24 2021 Kalev Lember - 41~beta-3 +- Rebuild + +* Tue Aug 24 2021 Kalev Lember - 41~beta-2 +- Enable parental controls support + +* Tue Aug 24 2021 Kalev Lember - 41~beta-1.1 +- Fix the polkit rule for Fedora third party setup (#1996901) + +* Mon Aug 23 2021 Kalev Lember - 41~beta-1 +- Update to 41.beta + +* Fri Aug 06 2021 Michael Catanzaro - 41~alpha-2 +- Add enterprise login patch, first user should be a local admin + +* Tue Aug 03 2021 Kalev Lember - 41~alpha-1 +- Update to 41.alpha + +* Thu Jul 22 2021 Fedora Release Engineering - 40.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Mon Jun 21 2021 Kalev Lember - 40.2-1 +- Update to 40.2 + +* Wed May 05 2021 Kalev Lember - 40.1-1 +- Update to 40.1 + +* Fri Apr 30 2021 Kalev Lember - 40.0-2 +- Drop gnome-tour dep here and move it to gnome-shell instead (#1955179) + +* Mon Mar 22 2021 Kalev Lember - 40.0-1 +- Update to 40.0 + +* Mon Mar 15 2021 Kalev Lember - 40~rc-1 +- Update to 40.rc + +* Wed Feb 17 2021 Kalev Lember - 40~beta-1 +- Update to 40.beta + +* Tue Jan 26 2021 Fedora Release Engineering - 3.38.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Sat Jan 16 2021 Kalev Lember - 3.38.3-1 +- Update to 3.38.3 + +* Wed Nov 25 2020 Kalev Lember - 3.38.2-1 +- Update to 3.38.2 + +* Mon Oct 5 2020 Kalev Lember - 3.38.1-1 +- Update to 3.38.1 + +* Fri Sep 11 2020 Ray Strode - 3.38.0-2 +- Remove weird, unnecessary g_idle_add which are triggering + some weird, not fully understood bug. + Resolves: #1875140 + +* Thu Sep 10 2020 Kalev Lember - 3.38.0-1 +- Update to 3.38.0 + +* Sun Sep 06 2020 Kalev Lember - 3.37.92-1 +- Update to 3.37.92 +- Drop upstreamed honor-firstboot-disabled.patch + +* Thu Aug 27 2020 Kalev Lember - 3.37.91.1-2 +- Require new gnome-tour package (#1873206) + +* Mon Aug 24 2020 Kalev Lember - 3.37.91.1-1 +- Update to 3.37.91.1 +- Rebase honor-firstboot-disabled.patch + +* Mon Aug 17 2020 Kalev Lember - 3.37.91-1 +- Update to 3.37.91 + +* Sat Aug 01 2020 Fedora Release Engineering - 3.37.3-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 3.37.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 20 2020 Kalev Lember - 3.37.3-1 +- Update to 3.37.3 + +* Tue Jun 23 2020 Adam Williamson - 3.37.1-3 +- Backport MR #89 to fix 'disabled' timezone page setting timezone + +* Mon May 04 2020 Adam Williamson - 3.37.1-2 +- Backport MR #83 to fix preselection of input methods + +* Thu Apr 30 2020 Kalev Lember - 3.37.1-1 +- Update to 3.37.1 + +* Mon Apr 27 2020 Kalev Lember - 3.36.2-1 +- Update to 3.36.2 + +* Sat Mar 28 2020 Kalev Lember - 3.36.1-1 +- Update to 3.36.1 + +* Fri Mar 06 2020 Kalev Lember - 3.36.0-1 +- Update to 3.36.0 + +* Mon Mar 02 2020 Kalev Lember - 3.35.92-1 +- Update to 3.35.92 + +* Mon Feb 17 2020 Kalev Lember - 3.35.91-1 +- Update to 3.35.91 + +* Tue Feb 04 2020 Kalev Lember - 3.35.90-1 +- Update to 3.35.90 + +* Tue Jan 28 2020 Fedora Release Engineering - 3.35.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 16 2020 Kalev Lember - 3.35.3-2 +- Rebuilt for libgnome-desktop soname bump + +* Tue Jan 07 2020 Kalev Lember - 3.35.3-1 +- Update to 3.35.3 + +* Tue Jan 07 2020 Kalev Lember - 3.34.3-1 +- Update to 3.34.3 + +* Mon Oct 07 2019 Kalev Lember - 3.34.1-1 +- Update to 3.34.1 + +* Mon Sep 09 2019 Benjamin Berg - 3.34.0-2 +- Fix g-i-s starting in GDM + Upstream MR https://gitlab.gnome.org/GNOME/gnome-initial-setup/merge_requests/59 +- Resolves: 1750237 + +* Mon Sep 09 2019 Kalev Lember - 3.34.0-1 +- Update to 3.34.0 + +* Wed Sep 04 2019 Benjamin Berg - 3.33.92-2 +- Include upstream patches to fix systemd support + https://gitlab.gnome.org/GNOME/gnome-initial-setup/merge_requests/58 +- Resolves: 1746563 + +* Tue Sep 03 2019 Kalev Lember - 3.33.92-1 +- Update to 3.33.92 + +* Tue Aug 20 2019 Kalev Lember - 3.33.91-1 +- Update to 3.33.91 + +* Thu Jul 25 2019 Fedora Release Engineering - 3.33.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sun Jul 21 2019 Kalev Lember - 3.33.4-2 +- Rebuilt for libgnome-desktop soname bump + +* Mon Jul 15 2019 Kalev Lember - 3.33.4-1 +- Update to 3.33.4 + +* Mon Jul 08 2019 Kalev Lember - 3.33.2-2 +- Rebuilt for libgweather soname bump + +* Tue May 21 2019 Kalev Lember - 3.33.2-1 +- Update to 3.33.2 + +* Tue Apr 16 2019 Adam Williamson - 3.32.1-2 +- Rebuild with Meson fix for #1699099 + +* Sat Apr 06 2019 Kalev Lember - 3.32.1-1 +- Update to 3.32.1 + +* Thu Apr 04 2019 Ray Strode - 3.32.0-1 +- Update to 3.32.0 + +* Thu Jan 31 2019 Fedora Release Engineering - 3.30.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Sat Sep 22 2018 Kalev Lember - 3.30.0-1 +- Update to 3.30.0 + +* Fri Sep 07 2018 Kalev Lember - 3.29.92-1 +- Update to 3.29.92 +- Drop upstreamed patches reduce-initial-setup-redundancy.patch and + allow-weak-passwords.patch +- Rebase honor-firstboot-disabled.patch + +* Fri Jul 13 2018 Fedora Release Engineering - 3.28.0-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Mon Apr 30 2018 Adam Williamson - 3.28.0-7 +- Drop unnecessary pkgconfig(NetworkManager) BuildRequire +- Run autoreconf to avoid automake version mismatch + +* Wed Apr 11 2018 Michael Catanzaro - 3.28.0-6 +- Allow setting weak passwords + +* Mon Apr 02 2018 Michael Catanzaro - 3.28.0-5 +- Move vendor.conf to /usr/share + +* Sat Mar 31 2018 Michael Catanzaro - 3.28.0-4 +- Forgot to update vendor.conf in the previous build + +* Sat Mar 31 2018 Michael Catanzaro - 3.28.0-3 +- Update reduce initial setup redundancy patch again + +* Sat Mar 31 2018 Michael Catanzaro - 3.28.0-2 +- Update reduce initial setup redundancy patches + +* Tue Mar 13 2018 Kalev Lember - 3.28.0-1 +- Update to 3.28.0 + +* Fri Feb 16 2018 Michael Catanzaro - 3.27.90-2 +- Install vendor.conf to conditionally suppress certain pages + +* Fri Feb 16 2018 Michael Catanzaro - 3.27.90-1 +- Upgrade to 3.27.90 and add reduce initial setup redundancy patches + +* Tue Feb 13 2018 Björn Esser - 3.26.0-5 +- Rebuild against newer gnome-desktop3 package + +* Wed Feb 07 2018 Fedora Release Engineering - 3.26.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Feb 05 2018 Kalev Lember - 3.26.0-3 +- Rebuilt for libgweather soname bump + +* Sat Jan 20 2018 Björn Esser - 3.26.0-2 +- Rebuilt for switch to libxcrypt + +* Thu Sep 14 2017 Kalev Lember - 3.26.0-1 +- Update to 3.26.0 + +* Thu Sep 07 2017 Kalev Lember - 3.25.92-1 +- Update to 3.25.92 + +* Mon Jul 31 2017 Kalev Lember - 3.25.4-1 +- Update to 3.25.4 + +* Wed Jul 26 2017 Fedora Release Engineering - 3.25.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sun Jun 25 2017 Kalev Lember - 3.25.3-1 +- Update to 3.25.3 + +* Wed May 10 2017 Kalev Lember - 3.24.2-1 +- Update to 3.24.2 + +* Tue Mar 21 2017 Rui Matos - 3.24.0-1 +- Update to 3.24.0 + +* Tue Mar 14 2017 Florian Müllner - 3.23.92-1 +- Update to 3.23.92 + +* Fri Feb 10 2017 Fedora Release Engineering - 3.23.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Tue Jan 31 2017 Rui Matos - 3.23.1-2 +- Honor anaconda's firstboot being disabled + +* Sun Oct 30 2016 Kalev Lember - 3.23.1-1 +- Update to 3.23.1 + +* Wed Oct 12 2016 Kalev Lember - 3.22.1-1 +- Update to 3.22.1 + +* Mon Sep 19 2016 Kalev Lember - 3.22.0-1 +- Update to 3.22.0 + +* Tue Sep 13 2016 Kalev Lember - 3.21.92-1 +- Update to 3.21.92 + +* Mon Sep 05 2016 Kalev Lember - 3.21.91-2 +- Build the software sources page + +* Sat Sep 03 2016 Kalev Lember - 3.21.91-1 +- Update to 3.21.91 +- Update project URL + +* Wed Apr 13 2016 Kalev Lember - 3.20.1-1 +- Update to 3.20.1 + +* Tue Mar 22 2016 Kalev Lember - 3.20.0-1 +- Update to 3.20.0 + +* Tue Mar 15 2016 Kalev Lember - 3.19.92-1 +- Update to 3.19.92 + +* Tue Mar 01 2016 Richard Hughes - 3.19.91-1 +- Update to 3.19.91 + +* Tue Feb 16 2016 Richard Hughes - 3.19.2-1 +- Update to 3.19.2 + +* Wed Feb 03 2016 Fedora Release Engineering - 3.19.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Oct 28 2015 Kalev Lember - 3.19.1-1 +- Update to 3.19.1 + +* Mon Sep 21 2015 Kalev Lember - 3.18.0-1 +- Update to 3.18.0 + +* Mon Aug 31 2015 Kalev Lember - 3.17.91-1 +- Update to 3.17.91 + +* Mon Aug 17 2015 Kalev Lember - 3.17.90-1 +- Update to 3.17.90 +- Use make_install macro + +* Mon Aug 17 2015 Kalev Lember - 3.17.4-2 +- Rebuilt for libcheese soname bump + +* Mon Jul 27 2015 David King - 3.17.4-1 +- Update to 3.17.4 + +* Wed Jul 22 2015 David King - 3.16.3-3 +- Bump for new gnome-desktop3 + +* Wed Jun 17 2015 Fedora Release Engineering - 3.16.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon May 18 2015 Matthias Clasen - 3.16.3-1 +- Update to 3.16.3 + +* Tue May 12 2015 Kalev Lember - 3.16.2-1 +- Update to 3.16.2 + +* Wed Apr 15 2015 Kalev Lember - 3.16.1-1 +- Update to 3.16.1 + +* Mon Mar 23 2015 Kalev Lember - 3.16.0-1 +- Update to 3.16.0 + +* Wed Mar 18 2015 Kalev Lember - 3.15.92-1 +- Update to 3.15.92 + +* Thu Mar 05 2015 Kalev Lember - 3.15.91.1-1 +- Update to 3.15.91.1 + +* Mon Mar 02 2015 Kalev Lember - 3.15.91-1 +- Update to 3.15.91 +- Use the %%license macro for the COPYING file + +* Thu Feb 19 2015 Matthias Clasen - 3.15.90.1-1 +- Update to 3.15.90.1 + +* Tue Dec 16 2014 Rui Matos - 3.14.2.1-2 +- Resolves: rhbz#1172363 + +* Tue Nov 11 2014 Rui Matos - 3.14.2.1-1 +- Update to 3.14.2.1 + +* Mon Nov 10 2014 Rui Matos - 3.14.2-1 +- Update to 3.14.2 +- Resolves: rhbz#1158442 + +* Fri Oct 31 2014 Rui Matos - 3.14.1-3 +- Resolves: rhbz#1151519 + +* Tue Oct 21 2014 Rui Matos - 3.14.1-2 +- Resolves: rhbz#1154206 + +* Sat Oct 11 2014 Kalev Lember - 3.14.1-1 +- Update to 3.14.1 + +* Tue Sep 23 2014 Kalev Lember - 3.14.0-1 +- Update to 3.14.0 + +* Wed Sep 17 2014 Kalev Lember - 3.13.7-1 +- Update to 3.13.7 + +* Tue Sep 16 2014 Kalev Lember - 3.13.6-1 +- Update to 3.13.6 + +* Mon Sep 08 2014 Adam Williamson - 3.13.5-2 +- backport upstream patch to offer full list of keyboard layouts (BGO #729208) + +* Wed Sep 03 2014 Kalev Lember - 3.13.5-1 +- Update to 3.13.5 + +* Sat Aug 16 2014 Fedora Release Engineering - 3.13.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Aug 13 2014 Matthias Clasen - 3.13.4-2 +- Drop the yelp focus patch (we've dropped the yelp patch it depends on) + +* Fri Jul 25 2014 Kalev Lember - 3.13.4-1 +- Update to 3.13.4 + +* Thu Jul 24 2014 Matthias Clasen - 3.12.1-3 +- Fix a memory corruption crash (#1116478) + +* Sat Jun 07 2014 Fedora Release Engineering - 3.12.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Thu May 15 2014 Kalev Lember - 3.12.1-1 +- Update to 3.12.1 + +* Tue Mar 25 2014 Kalev Lember - 3.12.0-1 +- Update to 3.12.0 + +* Thu Mar 20 2014 Richard Hughes - 3.11.92-1 +- Update to 3.11.92 + +* Sat Mar 08 2014 Richard Hughes - 3.11.91-1 +- Update to 3.11.91 + +* Fri Feb 28 2014 Richard Hughes - 3.11.90-1 +- Update to 3.11.90 + +* Wed Feb 19 2014 Kalev Lember - 3.10.1.1-5 +- Rebuilt for libgnome-desktop soname bump + +* Fri Nov 29 2013 Rui Matos - 3.10.1.1-4 +- Resolves: rhbz#1035548 - Disables the GOA page in new user mode + +* Thu Nov 28 2013 Rui Matos - 3.10.1.1-3 +- Resolves: rhbz#1027507 - [abrt] gnome-initial-setup-3.10.1.1-2.fc20: magazine_chain_pop_head + +* Fri Nov 1 2013 Matthias Clasen - 3.10.1.1-2 +- Fix goa add dialog to not be empty + +* Mon Oct 28 2013 Richard Hughes - 3.10.1.1-1 +- Update to 3.10.1.1 + +* Thu Sep 26 2013 Kalev Lember - 3.10.0.1-1 +- Update to 3.10.0.1 + +* Wed Sep 25 2013 Kalev Lember - 3.10.0-1 +- Update to 3.10.0 + +* Tue Sep 03 2013 Kalev Lember - 0.12-7 +- Rebuilt for libgnome-desktop soname bump + +* Fri Aug 23 2013 Kalev Lember - 0.12-6 +- Rebuilt for gnome-online-accounts soname bump + +* Fri Aug 09 2013 Kalev Lember - 0.12-5 +- Rebuilt for cogl 1.15.4 soname bump + +* Tue Aug 06 2013 Adam Williamson - 0.12-4 +- rebuild for new libgweather + +* Sat Aug 03 2013 Fedora Release Engineering - 0.12-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Fri Jun 21 2013 Kalev Lember - 0.12-2 +- Rebuilt for libgweather 3.9.3 soname bump + +* Mon Jun 17 2013 Rui Matos - 0.12-1 +- Update to 0.12 + +* Fri Jun 7 2013 Matthias Clasen - 0.11-2 +- Require polkit-js-engine + +* Tue May 28 2013 Matthias Clasen - 0.11-1 +- Update to 0.11 + +* Tue May 14 2013 Rui Matos - 0.10-1 +- Update to 0.10 +- Add BuildRequires on polkit-devel +- Update files list + +* Thu May 2 2013 Rui Matos - 0.9-2 +- Remove unused patches +- Add build requires for ibus + +* Tue Apr 16 2013 Matthias Clasen - 0.9-1 +- Update to 0.9 + +* Tue Apr 16 2013 Ray Strode 0.8-4 +- Add requires for keyboard viewer app + +* Wed Mar 20 2013 Ray Strode 0.8-3 +- Add cosimoc fix for gd page transitions + +* Wed Mar 20 2013 Ray Strode 0.8-2 +- Disable gd page transitions for now since they don't + completely work right (ask adamw). +- Fix crasher when realmd goes away + +* Tue Mar 19 2013 Matthias Clasen - 0.8-1 +- Update to 0.8 + +* Tue Mar 12 2013 Matthias Clasen - 0.7-1 +- Update to 0.7 + +* Thu Feb 21 2013 Kalev Lember - 0.6-4 +- Rebuilt for cogl soname bump + +* Wed Feb 20 2013 Kalev Lember - 0.6-3 +- Rebuilt for libgnome-desktop soname bump + +* Fri Jan 25 2013 Peter Robinson 0.6-2 +- Rebuild for new cogl + +* Wed Jan 16 2013 Matthias Clasen - 0.6-1 +- 0.6 + +* Fri Jan 11 2013 Matthias Clasen - 0.5-1 +- 0.5 + +* Fri Dec 21 2012 Kalev Lember - 0.4-2 +- Rebuilt for libgweather soname bump + +* Thu Nov 22 2012 Matthias Clasen - 0.4-1 +- 0.4 + +* Fri Oct 26 2012 Jasper St. Pierre - 0.3-3 +- Add krb5 + +* Fri Oct 26 2012 Jasper St. Pierre - 0.3-2 +- 0.3-2 + +* Thu Oct 18 2012 Matthias Clsaen - 0.3-1 +- 0.3 + +* Fri Sep 14 2012 Matthias Clasen - 0.2-2 +- Add Requires: gdm + +* Wed Aug 29 2012 Jasper St. Pierre - 0.2-1 +- Update to 0.2 + +* Fri Jun 08 2012 Jasper St. Pierre - 0.1 +- Initial packaging. + +## END: Generated by rpmautospec