- Updated dependencies in cargo.toml - Added wayland-sessions and xsessions support - Added better error handling for image and config loading - Added some example configs - Add FSL-1.1-MIT License Note: All unlicensed commits prior to this commit on 17.06.2026 are considered All Rights Reserved.
161 lines
5.5 KiB
Rust
161 lines
5.5 KiB
Rust
mod callbacks;
|
|
mod config;
|
|
mod input;
|
|
mod timers;
|
|
|
|
use crate::callbacks::register_callbacks;
|
|
use crate::config::Config;
|
|
use crate::timers::register_timers;
|
|
|
|
use anyhow::Context;
|
|
use i_slint_core::model::VecModel;
|
|
use magick_rust::magick_wand_genesis;
|
|
use slint::ModelRc;
|
|
use std::rc::Rc;
|
|
use std::sync::Once;
|
|
|
|
slint::include_modules!();
|
|
|
|
static START: Once = Once::new();
|
|
|
|
use log::{debug, error, info};
|
|
use pretty_env_logger::env_logger::Target;
|
|
|
|
#[cfg(debug_assertions)]
|
|
fn start_debug_greetd_stub() {
|
|
use libgreetd_stub::SessionOptions;
|
|
|
|
let opts = SessionOptions {
|
|
username: {
|
|
std::env::var("CKGREETER_STUB_USER")
|
|
.unwrap_or_else(|_| "debug-user".to_string())
|
|
},
|
|
password: std::env::var("CKGREETER_STUB_PASSWORD")
|
|
.unwrap_or_else(|_| "debug-password".to_string()),
|
|
mfa: false,
|
|
};
|
|
|
|
debug!(target: "ckgreeter::init_greetd_stub", "Using username: {}", opts.username);
|
|
debug!(target: "ckgreeter::init_greetd_stub", "Using password: {}", opts.password);
|
|
debug!(target: "ckgreeter::init_greetd_stub", "Using MFA: {}", opts.mfa);
|
|
|
|
let socket_path = std::env::var("CKGREETER_STUB_SOCKET")
|
|
.unwrap_or_else(|_| "/tmp/greetd-stub.sock".to_string());
|
|
|
|
debug!(target: "ckgreeter::init_greetd_stub", "Using socket path: {}", socket_path);
|
|
|
|
let stub_socket_path = socket_path.clone();
|
|
let _stub_task = tokio::task::spawn(async move {
|
|
libgreetd_stub::start(&stub_socket_path, &opts).await
|
|
});
|
|
debug!(target: "ckgreeter::init_greetd_stub", "Stub started");
|
|
|
|
debug!(target: "ckgreeter::init_greetd_stub", "GREETD_SOCK set to {}", socket_path);
|
|
unsafe {std::env::set_var("GREETD_SOCK", socket_path)};
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
#[cfg(debug_assertions)]
|
|
pretty_env_logger::formatted_timed_builder()
|
|
.target(Target::Stdout)
|
|
.parse_filters("ckgreeter=debug")
|
|
.parse_filters(std::env::var("RUST_LOG").unwrap_or_else(|_| "".to_string()).as_str())
|
|
.init();
|
|
#[cfg(not(debug_assertions))]
|
|
pretty_env_logger::formatted_timed_builder()
|
|
.target(Target::Stdout)
|
|
.parse_filters("ckgreeter=info")
|
|
.init();
|
|
|
|
info!(target: "ckgreeter::init", "Initializing...");
|
|
START.call_once(|| {
|
|
magick_wand_genesis();
|
|
});
|
|
info!(target: "ckgreeter::init", "ImageMagick initialized");
|
|
|
|
#[cfg(debug_assertions)]
|
|
{
|
|
start_debug_greetd_stub();
|
|
info!(target: "ckgreeter::init", "Debug greetd stub started");
|
|
}
|
|
|
|
|
|
const CONFIG_PATH: &str = "/etc/ckgreeter/config.toml";
|
|
|
|
let config_path = std::env::var("CKGREETER_CONFIG").unwrap_or_else(|_| CONFIG_PATH.to_string());
|
|
|
|
if !std::fs::exists(&config_path)? {
|
|
error!(target: "ckgreeter::init", "Config file not found at {}", config_path);
|
|
return Err(anyhow::anyhow!("Config file not found at {}", config_path));
|
|
}
|
|
|
|
info!(target: "ckgreeter::init", "Loading config from {}", config_path);
|
|
let config_data = std::fs::read(&config_path)
|
|
.with_context(|| format!("Failed to read config file at {}", config_path))?;
|
|
info!(target: "ckgreeter::init", "Config loaded");
|
|
let mut config: Config = toml::from_slice(&config_data)
|
|
.with_context(|| format!("Failed to parse config file at {}", config_path))?;
|
|
debug!(target: "ckgreeter::init", "Config parsed");
|
|
|
|
let display = GreeterDisplay::new()?;
|
|
let data = display.global::<GreeterData>();
|
|
|
|
let (tiles, default_tile) = config.get_tiles()?;
|
|
|
|
let cache_dir = &config.background_cache_directory;
|
|
info!(target: "ckgreeter::init", "Using cache directory: {}", cache_dir.display());
|
|
std::fs::create_dir_all(cache_dir)
|
|
.with_context(|| format!("Failed to create cache directory: {}", cache_dir.display()))?;
|
|
|
|
|
|
if tiles.len() == 0 {
|
|
error!(target: "ckgreeter::init", "No tiles found in config");
|
|
return Err(anyhow::anyhow!("No tiles found in config"));
|
|
}
|
|
|
|
debug!(target: "ckgreeter::init", "Got tiles from config");
|
|
|
|
if let Some(default_tile) = default_tile {
|
|
debug!(target: "ckgreeter::init", "Default tile: '{}', index: {}", tiles[default_tile].name, default_tile);
|
|
data.set_selected_index(default_tile as i32);
|
|
}
|
|
|
|
let tiles = Rc::new(VecModel::from(tiles));
|
|
|
|
info!(target: "ckgreeter::init", "Registering callbacks and timers...");
|
|
register_callbacks(&display, &data, tiles.clone(), cache_dir.into(), &config);
|
|
info!(target: "ckgreeter::init", "Callbacks registered");
|
|
let _timers = register_timers(&display, &data, &config);
|
|
info!(target: "ckgreeter::init", "Timers registered");
|
|
|
|
match config.default_username {
|
|
Some(username) => {
|
|
display.set_default_username(username.into());
|
|
data.set_has_default_username(true);
|
|
}
|
|
None => {
|
|
data.set_has_default_username(false);
|
|
}
|
|
}
|
|
|
|
info!(target: "ckgreeter::init", "Setting up display...");
|
|
|
|
display.set_tiles(ModelRc::from(tiles));
|
|
debug!(target: "ckgreeter::init", "Tiles set");
|
|
|
|
|
|
data.set_wallpaper_cooldown(config.background_delay.max(5));
|
|
debug!(target: "ckgreeter::init", "Wallpaper cooldown set");
|
|
data.invoke_get_new_wallpaper();
|
|
debug!(target: "ckgreeter::init", "Wallpaper fetch invoked");
|
|
data.invoke_check_lock_states();
|
|
debug!(target: "ckgreeter::init", "Lock state check invoked");
|
|
|
|
info!(target: "ckgreeter::init", "Display setup complete");
|
|
display.show()?;
|
|
tokio::task::block_in_place(slint::run_event_loop)?;
|
|
display.hide()?;
|
|
|
|
Ok(())
|
|
} |