fix: detect and enable logind functionality at runtime

Downstream distributions have optional logind, but the logind feature
must be defined at compile time. If cosmic-greeter is compiled with
logind support it fails to run on a host that's not running logind.

Detect whether logind is present at runtime, enabling the use of the
same binaries regardless of whether logind is installed or not.
This commit is contained in:
Hugo 2026-07-29 17:51:37 +02:00 • committed by GitHub
parent d39915ae23
commit f64e2d8fab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 71 additions and 40 deletions

View file

@ -280,6 +280,8 @@ pub fn main() -> Result<(), Box<dyn Error>> {
sessions
};
let logind_available = cfg!(feature = "logind") && crate::logind::is_available();
let flags = Flags {
user_icons: user_datas
.iter_mut()
@ -289,6 +291,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
sessions,
greeter_config,
greeter_config_handler,
logind_available,
};
let settings = Settings::default().no_main_window(true);
@ -305,6 +308,7 @@ pub struct Flags {
sessions: HashMap<String, (Vec<String>, Vec<String>)>,
greeter_config: CosmicGreeterConfig,
greeter_config_handler: Option<cosmic_config::Config>,
logind_available: bool,
}
#[derive(Clone, Debug)]
@ -688,7 +692,7 @@ impl App {
let accessibility_button = accessibility_dropdown;
let button_row = iced::widget::row![
let mut button_row = iced::widget::row![
widget::tooltip(
accessibility_button,
text(fl!("accessibility")),
@ -709,30 +713,32 @@ impl App {
text(fl!("session")),
widget::tooltip::Position::Top
),
widget::tooltip(
widget::button::custom(widget::icon::from_name("system-suspend-symbolic"))
.padding(12.0)
.on_press(Message::Suspend),
text(fl!("suspend")),
widget::tooltip::Position::Top
),
widget::tooltip(
widget::button::custom(widget::icon::from_name("system-reboot-symbolic"))
.padding(12.0)
.on_press(Message::Restart),
text(fl!("restart")),
widget::tooltip::Position::Top
),
widget::tooltip(
widget::button::custom(widget::icon::from_name("system-shutdown-symbolic"))
.padding(12.0)
.on_press(Message::Shutdown),
text(fl!("shutdown")),
widget::tooltip::Position::Top
)
]
.padding([16.0, 0.0, 0.0, 0.0])
.spacing(8.0);
];
if self.flags.logind_available {
button_row = button_row
.push(widget::tooltip(
widget::button::custom(widget::icon::from_name("system-suspend-symbolic"))
.padding(12.0)
.on_press(Message::Suspend),
text(fl!("suspend")),
widget::tooltip::Position::Top,
))
.push(widget::tooltip(
widget::button::custom(widget::icon::from_name("system-reboot-symbolic"))
.padding(12.0)
.on_press(Message::Restart),
text(fl!("restart")),
widget::tooltip::Position::Top,
))
.push(widget::tooltip(
widget::button::custom(widget::icon::from_name("system-shutdown-symbolic"))
.padding(12.0)
.on_press(Message::Shutdown),
text(fl!("shutdown")),
widget::tooltip::Position::Top,
));
}
let button_row = button_row.padding([16.0, 0.0, 0.0, 0.0]).spacing(8.0);
widget::container(iced::widget::column![
date_time_column,

View file

@ -79,6 +79,8 @@ pub fn main(user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>> {
// We are already the user at this point
user_data.load_config_as_user();
let logind_available = cfg!(feature = "logind") && crate::logind::is_available();
let flags = Flags {
user_icon: user_data
.icon_opt
@ -86,6 +88,7 @@ pub fn main(user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>> {
.map(widget::image::Handle::from_bytes),
user_data,
lockfile_opt: lockfile_opt(),
logind_available,
};
let settings = Settings::default().no_main_window(true);
@ -247,6 +250,7 @@ pub struct Flags {
user_data: UserData,
user_icon: Option<widget::image::Handle>,
lockfile_opt: Option<PathBuf>,
logind_available: bool,
}
///TODO: this is custom code that should be better handled by libcosmic
@ -429,7 +433,7 @@ impl App {
}
//TODO: implement these buttons
let button_row = iced::widget::row![
let mut button_row = iced::widget::row![
/*TODO: greeter accessibility options
widget::button::custom(widget::icon::from_name(
"applications-accessibility-symbolic"
@ -442,16 +446,17 @@ impl App {
widget::text(fl!("keyboard-layout")),
widget::tooltip::Position::Top
),
widget::tooltip(
];
if cfg!(feature = "logind") && self.flags.logind_available {
button_row = button_row.push(widget::tooltip(
widget::button::custom(widget::icon::from_name("system-suspend-symbolic"))
.padding(12.0)
.on_press(Message::Suspend),
widget::text(fl!("suspend")),
widget::tooltip::Position::Top
),
]
.padding([16.0, 0.0, 0.0, 0.0])
.spacing(8.0);
widget::tooltip::Position::Top,
));
}
let button_row = button_row.padding([16.0, 0.0, 0.0, 0.0]).spacing(8.0);
widget::container(iced::widget::column![
date_time_column,
@ -679,18 +684,18 @@ impl cosmic::Application for App {
authenticating: false,
};
let task = if cfg!(feature = "logind") {
let task = if cfg!(feature = "logind") && app.flags.logind_available {
if already_locked {
// Recover previously locked state
tracing::info!("recovering previous locked state");
app.state = State::Locking;
lock()
} else {
// When logind feature is used, wait for lock signal
// When logind is available, wait for lock signal
Task::none()
}
} else {
// When logind feature not used, lock immediately
// When logind is not available, lock immediately
tracing::info!("locking immediately");
app.state = State::Locking;
lock()
@ -1005,11 +1010,11 @@ impl cosmic::Application for App {
self.common.window_size.remove(surface_id);
commands.push(destroy_lock_surface(*surface_id));
}
if cfg!(feature = "logind") {
if cfg!(feature = "logind") && self.flags.logind_available {
return Task::batch(commands);
// When using logind feature, stick around for more lock signals
// When logind is available, stick around for more lock signals
} else {
// When not using logind feature, exit immediately after unlocking
// When logind is not available, exit immediately after unlocking
//TODO: cleaner method to exit?
process::exit(0);
}
@ -1212,8 +1217,7 @@ impl cosmic::Application for App {
}),
);
#[cfg(feature = "logind")]
{
if cfg!(feature = "logind") && self.flags.logind_available {
subscriptions.push(crate::logind::subscription());
}

View file

@ -13,6 +13,27 @@ use zbus::Connection;
use crate::common;
use crate::locker::Message;
/// Checks whether logind (either elogind or systemd-logind) is reachable on the system bus.
pub fn is_available() -> bool {
fn ping() -> zbus::Result<()> {
let connection = zbus::blocking::Connection::system()?;
connection.call_method(
Some("org.freedesktop.login1"),
"/org/freedesktop/login1",
Some("org.freedesktop.DBus.Peer"),
"Ping",
&(),
)?;
Ok(())
}
if let Err(err) = ping() {
tracing::info!("logind not available: {}", err);
false
} else {
true
}
}
pub async fn power_off() -> zbus::Result<()> {
let connection = Connection::system().await?;
let manager = ManagerProxy::new(&connection).await?;