From edef2b9b302d21c3e7bc9297984b12cfc474cbc5 Mon Sep 17 00:00:00 2001 From: asogii Date: Mon, 6 Jul 2026 17:56:22 +0800 Subject: [PATCH] config: enable numlock on startup --- Cargo.toml | 2 +- contrib/example.config.toml | 3 +++ crates/tuigreet-config/src/env.rs | 11 +++++++++++ crates/tuigreet-config/src/parser.rs | 6 ++++++ crates/tuigreet-config/src/schema.rs | 5 +++++ crates/tuigreet/src/greeter.rs | 4 ++++ crates/tuigreet/src/main.rs | 17 +++++++++++++++++ 7 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 05bb75b..da10212 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/contrib/example.config.toml b/contrib/example.config.toml index c9f2304..816da4f 100644 --- a/contrib/example.config.toml +++ b/contrib/example.config.toml @@ -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" diff --git a/crates/tuigreet-config/src/env.rs b/crates/tuigreet-config/src/env.rs index a7cd4cc..71873a1 100644 --- a/crates/tuigreet-config/src/env.rs +++ b/crates/tuigreet-config/src/env.rs @@ -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); diff --git a/crates/tuigreet-config/src/parser.rs b/crates/tuigreet-config/src/parser.rs index 1a7da1b..d1fdd11 100644 --- a/crates/tuigreet-config/src/parser.rs +++ b/crates/tuigreet-config/src/parser.rs @@ -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 { @@ -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; diff --git a/crates/tuigreet-config/src/schema.rs b/crates/tuigreet-config/src/schema.rs index c0cbf90..172f158 100644 --- a/crates/tuigreet-config/src/schema.rs +++ b/crates/tuigreet-config/src/schema.rs @@ -142,6 +142,10 @@ 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 { @@ -149,6 +153,7 @@ impl Default for GeneralConfig { Self { debug: false, log_file: default_log_file(), + numlock: false, } } } diff --git a/crates/tuigreet/src/greeter.rs b/crates/tuigreet/src/greeter.rs index 3b4a43a..9f19e66 100644 --- a/crates/tuigreet/src/greeter.rs +++ b/crates/tuigreet/src/greeter.rs @@ -69,6 +69,7 @@ pub struct Greeter { pub logfile: String, pub logger: Option, + pub numlock: bool, pub locale: Locale, pub config: Option, pub loaded_config: Option, /* store loaded TOML @@ -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, @@ -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( @@ -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, diff --git a/crates/tuigreet/src/main.rs b/crates/tuigreet/src/main.rs index d1b2014..90e9ae6 100644 --- a/crates/tuigreet/src/main.rs +++ b/crates/tuigreet/src/main.rs @@ -69,6 +69,10 @@ where register_panic_handler(); + if greeter.numlock { + enable_numlock(); + } + #[cfg(not(test))] { enable_raw_mode()?; @@ -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();