From 18504accb9d8d3e086b20cbcf2e3673907ef5586 Mon Sep 17 00:00:00 2001 From: Harish Rajagopal Date: Sun, 4 Aug 2024 11:22:10 +0200 Subject: [PATCH 1/4] Add config option to skip selecting user/session --- README.md | 2 ++ regreet.sample.toml | 3 +++ src/config.rs | 7 +++++++ src/gui/component.rs | 7 +++++++ src/gui/model.rs | 2 +- 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bc182e0..4953506 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ the Roboto font. All screenshots are provided under the - Allows manual entry of username and session command - Remembers the last authenticated user - Automatically selects the last used session per user +- Can also skip selecting the user/session and choose the last user and their + last used session. - Allows setting environment variables for created sessions - Supports customizing: - Background image diff --git a/regreet.sample.toml b/regreet.sample.toml index 205af59..bb77777 100644 --- a/regreet.sample.toml +++ b/regreet.sample.toml @@ -2,6 +2,9 @@ # # SPDX-License-Identifier: GPL-3.0-or-later +# Whether to skip asking for username and session, and use the last used ones. +skip_selection = false + [background] # Path to the background image/video path = "/usr/share/backgrounds/greeter.jpg" diff --git a/src/config.rs b/src/config.rs index d07a52b..b60dcc8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -130,6 +130,9 @@ fn default_greeting_msg() -> String { /// The configuration struct #[derive(Default, Deserialize)] pub struct Config { + #[serde(default)] + skip_selection: bool, + #[serde(default)] appearance: AppearanceSettings, @@ -184,4 +187,8 @@ impl Config { pub fn get_default_message(&self) -> &str { &self.appearance.greeting_msg } + + pub fn skip_selection(&self) -> bool { + self.skip_selection + } } diff --git a/src/gui/component.rs b/src/gui/component.rs index 2a05fa7..38fa61a 100644 --- a/src/gui/component.rs +++ b/src/gui/component.rs @@ -420,6 +420,13 @@ impl AsyncComponent for Greeter { // Set the default behaviour of pressing the Return key to act like the login button. root.set_default_widget(Some(&widgets.ui.login_button)); + if let Some(user) = model.cache.get_last_user() { + if model.config.skip_selection() && model.cache.has_last_session(user) { + debug!("Skipping user & session selection and using those from the cache"); + widgets.ui.login_button.emit_clicked(); + } + } + AsyncComponentParts { model, widgets } } diff --git a/src/gui/model.rs b/src/gui/model.rs index 9110101..f9a6d55 100644 --- a/src/gui/model.rs +++ b/src/gui/model.rs @@ -98,7 +98,7 @@ pub struct Greeter { pub(super) updates: Updates, /// Is it run as demo pub(super) demo: bool, - + /// The clock widget pub(super) clock: Controller, } From 9450618f0abc624c3156331730fc0a0946721de3 Mon Sep 17 00:00:00 2001 From: Harish Rajagopal Date: Thu, 7 May 2026 21:07:28 +0200 Subject: [PATCH 2/4] Prevent auto-login for passwordless users When skip_selection auto-clicks login at startup and the user has no auth configured, greetd returns Success immediately, logging them in without any chance to change user or session. Track whether this is the first login to intercept this case: cancel the session and return to the UI so the user can confirm their selection manually. --- src/gui/model.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/gui/model.rs b/src/gui/model.rs index f9a6d55..9502f83 100644 --- a/src/gui/model.rs +++ b/src/gui/model.rs @@ -100,6 +100,8 @@ pub struct Greeter { pub(super) demo: bool, /// The clock widget pub(super) clock: Controller, + /// Has the first click of the login button been handled previously? + first_login_handled: bool, } impl Greeter { @@ -141,6 +143,7 @@ impl Greeter { updates, demo, clock, + first_login_handled: false, } } @@ -300,11 +303,19 @@ impl Greeter { ) { match response { Response::Success => { - // Authentication was successful and the session may be started. - // This may happen on the first request, in which case logging in - // as the given user requires no authentication. - info!("Successfully logged in; starting session"); - self.start_session(sender).await; + if self.config.skip_selection() && !self.first_login_handled { + // This happens when the last logged-in user has no password or any other auth + // set. Since the login button is auto-clicked, it would've otherwise logged + // them in without any possibility of changing the user or session! + warn!("Preventing auto-login for user without auth: cancelling session"); + self.cancel_click_handler().await + } else { + // Authentication was successful and the session may be started. + // This may happen on the first request, in which case logging in + // as the given user requires no authentication. + info!("Successfully logged in; starting session"); + self.start_session(sender).await + } return; } Response::AuthMessage { @@ -435,6 +446,7 @@ impl Greeter { self.create_session(sender).await; } }; + self.first_login_handled = true; } /// Send the entered input for logging in. From 7ece7491c76dbca9f7ebdd8e11e04ba1fd4f6405 Mon Sep 17 00:00:00 2001 From: Harish Rajagopal Date: Thu, 7 May 2026 21:44:37 +0200 Subject: [PATCH 3/4] Fix possible race condition in skip_selection auto-login --- src/gui/component.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/gui/component.rs b/src/gui/component.rs index 38fa61a..26164d4 100644 --- a/src/gui/component.rs +++ b/src/gui/component.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use relm4::{ AsyncComponentSender, component::{AsyncComponent, AsyncComponentParts}, - gtk::prelude::*, + gtk::{glib::GString, prelude::*}, prelude::*, }; use tracing::{debug, info, warn}; @@ -423,7 +423,20 @@ impl AsyncComponent for Greeter { if let Some(user) = model.cache.get_last_user() { if model.config.skip_selection() && model.cache.has_last_session(user) { debug!("Skipping user & session selection and using those from the cache"); - widgets.ui.login_button.emit_clicked(); + // Queue up a login event after the Self::Input::UserChanged that will be fired by + // setup_users_sessions (as sender.input queues). This way we avoid any race + // conditions. Use cached values directly instead of extracting from widgets. + let user = user.to_string(); + let last_session = model.cache.get_last_session(&user).unwrap().to_string(); + sender.input(Self::Input::Login { + input: String::new(), + info: UserSessInfo { + user_id: Some(user.into()), + user_text: GString::new(), + sess_id: Some(last_session.into()), + sess_text: GString::new(), + }, + }); } } From 4f0e1c84e3f97d2242aa49f0c5c2d23bdc0c314a Mon Sep 17 00:00:00 2001 From: Harish Rajagopal Date: Thu, 7 May 2026 22:38:35 +0200 Subject: [PATCH 4/4] Show info message on selection skip --- src/gui/model.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/gui/model.rs b/src/gui/model.rs index 9502f83..c43d412 100644 --- a/src/gui/model.rs +++ b/src/gui/model.rs @@ -322,6 +322,15 @@ impl Greeter { auth_message, auth_message_type, } => { + let auto_select_msg = if self.config.skip_selection() && !self.first_login_handled { + self.sess_info + .as_ref() + .and_then(|s| s.sess_id.as_ref()) + .map(|s| format!("Auto-selecting session \"{s}\"")) + } else { + None + }; + match auth_message_type { AuthMessageType::Secret => { // Greetd has requested input that should be hidden @@ -331,6 +340,9 @@ impl Greeter { self.updates.set_input(String::new()); self.updates .set_input_prompt(auth_message.trim_end().to_string()); + if let Some(msg) = auto_select_msg { + self.display_info(sender, &msg, "Skipped user/session selection"); + } return; } AuthMessageType::Visible => { @@ -340,6 +352,9 @@ impl Greeter { self.updates.set_input(String::new()); self.updates .set_input_prompt(auth_message.trim_end().to_string()); + if let Some(msg) = auto_select_msg { + self.display_info(sender, &msg, "Skipped user/session selection"); + } return; } AuthMessageType::Info => {