[ MIRROR ] Customisable, minimalist screen locker for Wayland git.ngill.net/nlock.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145// SPDX-License-Identifier: GPL-3.0-or-later// Copyright (C) 2026, Nathan Gill
pub mod args;pub mod auth;pub mod auth_sys;pub mod buffer;pub mod cairo_ext;pub mod comm;pub mod config;pub mod event;pub mod event_loop;pub mod font;pub mod render;pub mod seat;pub mod shm;pub mod signal;pub mod state;pub mod surface;pub mod util;
use std::sync::{Arc, atomic::Ordering};
use anyhow::{Result, bail};
#[cfg_attr(debug_assertions, allow(unused_imports))]#[cfg(target_os = "linux")]use nix::sys::prctl;
use tracing::{debug, error, info, warn};use wayland_client::Connection;
use crate::{ args::run_cli, auth::{AuthChannel, AuthConfig, setup_auth}, config::NLockConfig, state::{NLockState, NLockStateArgs}, util::LogLevel,};
fn start(config: NLockConfig, debug: bool) -> Result<()> { // Prevent ptrace from attaching to nlock // Only do this in release config #[cfg(not(debug_assertions))] #[cfg(target_os = "linux")] prctl::set_dumpable(false)?;
if debug { info!("Running in DEBUG mode"); }
let conn = Connection::connect_to_env()?; let display = conn.display();
let auth_comm = Arc::new(AuthChannel::new()?); let auth_config: AuthConfig = (&config).into();
let state_args = NLockStateArgs { config, display, auth_comm: auth_comm.clone(), debug, }; let mut state = NLockState::new(state_args)?;
let mut event_queue = conn.new_event_queue(); let qh = event_queue.handle();
state.get_registry(&qh); event_queue.roundtrip(&mut state)?;
if state.compositor.is_none() { bail!("Missing WlCompositor"); }
if state.subcompositor.is_none() { bail!("Missing WlSubcompositor"); }
if state.shm.is_none() { bail!("Missing WlShm"); }
if state.r_seat.is_none() { bail!("Missing WlSeat"); }
if state.session_lock_manager.is_none() { bail!("Missing ExtSessionLockManagerV1"); }
// spawn the auth thread let handle = setup_auth(auth_config, auth_comm.clone())?;
state.lock(&qh);
while state.running.load(Ordering::Relaxed) { if let Err(e) = state.event_loop_cycle(&mut event_queue) { warn!("Error while running event loop: {e}"); } }
state.unlock(); event_queue.roundtrip(&mut state)?;
if let Err(e) = auth_comm.stop.write(true) { warn!("Failed to stop auth loop: {e}"); } else { let _ = handle.join(); }
Ok(())}
fn main() { let args = run_cli();
tracing_subscriber::fmt() .with_timer(tracing_subscriber::fmt::time::uptime()) .with_max_level(args.log_level.unwrap_or(if args.debug { LogLevel::Debug } else { LogLevel::Info })) .init();
let now = chrono::Local::now(); debug!("nlock started at {}", now.to_rfc3339());
match NLockConfig::load(&args) { Ok(cfg) => { if let Err(e) = start(cfg, args.debug) { error!("{:?}", e); } } Err(e) => { error!("Error loading configuration: {:?}", e); return; } }
let now = chrono::Local::now(); debug!("nlock exited at {}", now.to_rfc3339());}