Skip to content
This repository was archived by the owner on Aug 12, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ getopts = "0.2.24"
greetd_ipc = { version = "0.10.3", features = [ "tokio-codec" ] }
i18n-embed = { version = "0.16.0", features = [ "desktop-requester", "fluent-system" ] }
i18n-embed-fl = "0.10.0"
nix = { version = "0.31.3", features = [ "feature" ] }
nix = { version = "0.31.3", features = [ "feature", "ioctl" ] }
notify = { version = "8.2.0", features = [ "macos_fsevent" ] }
rand = "0.10.2"
rust-embed = "8.12.0"
Expand Down
3 changes: 3 additions & 0 deletions contrib/example.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ debug = false
# Log file path
log_file = "/tmp/tuigreet.log"

# Enable numlock on startup
numlock = false

[session]
# Override session with a specific command
# command = "sway"
Expand Down
11 changes: 11 additions & 0 deletions crates/tuigreet-config/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ pub fn load_env_variables() -> Config {
config.general.log_file = value;
}

if let Ok(value) = env::var("TUIGREET_NUMLOCK") {
if let Ok(numlock) = parse_bool(&value) {
config.general.numlock = numlock;
} else {
tracing::warn!(
"Invalid TUIGREET_NUMLOCK value: '{}', expected true/false",
value
);
}
}

// Session config
if let Ok(value) = env::var("TUIGREET_SESSION_COMMAND") {
config.session.command = Some(value);
Expand Down
6 changes: 6 additions & 0 deletions crates/tuigreet-config/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ fn apply_config_layer(dest: &mut Config, src: Config) {
if src.general.log_file != defaults.general.log_file {
dest.general.log_file = src.general.log_file;
}
if src.general.numlock != defaults.general.numlock {
dest.general.numlock = src.general.numlock;
}

// Session
if src.session.command != defaults.session.command {
Expand Down Expand Up @@ -519,6 +522,9 @@ pub fn extract_cli_config(matches: &getopts::Matches) -> Config {
if matches.opt_present("debug") {
config.general.debug = true;
}
if matches.opt_present("numlock") {
config.general.numlock = true;
}
// Display config
if matches.opt_present("time") {
config.display.show_time = true;
Expand Down
5 changes: 5 additions & 0 deletions crates/tuigreet-config/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,18 @@ pub struct GeneralConfig {
/// Log file path
#[serde(default = "default_log_file")]
pub log_file: String,

/// Enable numlock on startup
#[serde(default)]
pub numlock: bool,
}

impl Default for GeneralConfig {
fn default() -> Self {
Self {
debug: false,
log_file: default_log_file(),
numlock: false,
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/tuigreet/src/greeter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub struct Greeter {
pub logfile: String,
pub logger: Option<WorkerGuard>,

pub numlock: bool,
pub locale: Locale,
pub config: Option<Matches>,
pub loaded_config: Option<tuigreet_config::Config>, /* store loaded TOML
Expand Down Expand Up @@ -181,6 +182,7 @@ impl Default for Greeter {
debug: false,
logfile: DEFAULT_LOG_FILE.to_string(),
logger: None,
numlock: false,
locale: DEFAULT_LOCALE,
config: None,
loaded_config: None,
Expand Down Expand Up @@ -818,6 +820,7 @@ impl Greeter {
opts.optopt("", "config", "path to configuration file", "PATH");
opts.optflag("", "no-config", "disable loading configuration files");
opts.optflag("", "dump-config", "print effective configuration and exit");
opts.optflag("", "numlock", "enable numlock on startup");
opts.optflag("", "list-outputs", "list available DRM outputs and exit");

opts.optopt(
Expand Down Expand Up @@ -1316,6 +1319,7 @@ impl Greeter {
// General
self.debug = config.general.debug;
self.logfile.clone_from(&config.general.log_file);
self.numlock = config.general.numlock;
// Session
self.session_source = config.session.command.as_ref().map_or_else(
SessionSource::default,
Expand Down
17 changes: 17 additions & 0 deletions crates/tuigreet/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ where

register_panic_handler();

if greeter.numlock {
enable_numlock();
}

#[cfg(not(test))]
{
enable_raw_mode()?;
Expand Down Expand Up @@ -226,6 +230,19 @@ async fn exit(greeter: &mut Greeter, status: AuthStatus) {
greeter.exit = Some(status);
}

use nix::{ioctl_read_bad, ioctl_write_int_bad};
ioctl_read_bad!(get_keyboard_flags, 0x4B64, u8);
ioctl_write_int_bad!(set_keyboard_flags, 0x4B65);
fn enable_numlock() {
unsafe {
let mut flags: u8 = 0;
if get_keyboard_flags(0, &mut flags).is_ok() {
flags |= 0x22;
let _ = set_keyboard_flags(0, flags as i32);
}
}
}

fn register_panic_handler() {
let hook = std::panic::take_hook();

Expand Down
Loading