Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
main.rs 2.16 KiB
use std::env::home_dir;
use std::fs::{create_dir, OpenOptions};
use std::io::ErrorKind;
use calloop::signals::Signal::{SIGINT, SIGQUIT, SIGTERM};
use calloop::signals::Signals;
use clap::{Args, Parser};
use state::State;
use tracing::level_filters::LevelFilter;

use crate::backends::{UdevBackend, X11Backend};

mod handlers;

mod backends;
mod dbus;
mod focus;
mod input;
mod render;
mod session;
mod shell;
mod state;
mod utils;

#[derive(Args, Debug, Copy, Clone)]
#[group(required = false, multiple = false)]
struct Verbosity {
    /// Enables debug logging
    #[arg(long)]
    debug: bool,
    /// Enables trace logging
    #[arg(long)]
    trace: bool,
}

impl From<Verbosity> for LevelFilter {
    fn from(value: Verbosity) -> LevelFilter {
        if value.debug {
            LevelFilter::DEBUG
        } else if value.trace {
            LevelFilter::TRACE
        } else {
            LevelFilter::INFO
        }
    }
}

/// A kiosk compositor
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Cli {
    /// Starts the compositor as nested X11 window
    #[arg(long)]
    nested: bool,
    #[command(flatten)]
    verbosity: Verbosity,
}

fn main() {
    let home_dir_path = home_dir().expect("Home directory unknown"); 
    if let Err(error) = create_dir(&home_dir_path) {
        if error.kind() != ErrorKind::AlreadyExists {
            Err::<(),_>(error).expect("Could not create home directory");
        }
    }
    let home_dir = OpenOptions::new()
        .read(true)
        .open(home_dir_path)
        .expect("Home directory not found");
    home_dir.lock().expect("Failed to lock home directory");
    // Initialize the signals at the very beginning so that every thread will inherit the same
    // signal mask.
    let signal_source = Signals::new(&[SIGINT, SIGTERM, SIGQUIT]).expect("Failed to create signal source.");

    let args = Cli::parse();

    tracing_subscriber::fmt()
        .compact()
        .with_max_level(LevelFilter::from(args.verbosity))
        .init();

    if args.nested {
        State::<X11Backend>::new().run_render_loop(signal_source);
    } else {
        State::<UdevBackend>::new().run_render_loop(signal_source);
    }
}