megalock 0.1.0

X11 xlock replacement
pub mod connection;
pub mod consts;
pub mod statics;

use crate::{
    clear_password,
    wm::{statics::PASSWORD, Broker, Call},
};
use anyhow::Result;
use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};

lazy_static::lazy_static! {
    static ref CLIENT: Arc<Mutex<HashMap<i32, Arc<Mutex<Client>>>>> = Arc::new(Mutex::new(HashMap::default()));
}

pub struct Client {
    screen_number: i32,
    sender: Arc<Mutex<Option<std::sync::mpsc::Sender<Call>>>>,
    pam: Arc<Mutex<std::sync::mpsc::Receiver<()>>>,
    pam_return: Arc<Mutex<std::sync::mpsc::Sender<()>>>,
}

impl Client {
    fn new(screen_number: i32) -> Result<Arc<Mutex<Self>>> {
        let (sender, receiver) = std::sync::mpsc::channel();
        let (pam_s, pam_r) = std::sync::mpsc::channel();
        let (pam_return_s, pam_return_r) = std::sync::mpsc::channel();
        let mut s = Self {
            screen_number,
            sender: Arc::new(Mutex::new(Some(sender))),
            pam: Arc::new(Mutex::new(pam_r)),
            pam_return: Arc::new(Mutex::new(pam_return_s)),
        };
        s.spawn(receiver, pam_s, pam_return_r);
        Ok(Arc::new(Mutex::new(s)))
    }

    pub fn get_client(screen_number: i32) -> Result<Arc<Mutex<Self>>> {
        let mut lock = CLIENT.lock().unwrap();

        if let Some(obj) = lock.get(&screen_number) {
            Ok(obj.clone())
        } else {
            let obj = Self::new(screen_number)?;
            lock.insert(screen_number, obj.clone());
            Ok(obj)
        }
    }

    fn spawn(
        &mut self,
        receiver: std::sync::mpsc::Receiver<Call>,
        pam: std::sync::mpsc::Sender<()>,
        pam_return: std::sync::mpsc::Receiver<()>,
    ) {
        let screen_number = self.screen_number;
        std::thread::spawn(move || {
            let mut connection =
                connection::Connection::init(screen_number).expect("Could not init X11");
            connection.set_receiver(Arc::new(Mutex::new(Some(receiver))));
            connection.set_pam(pam);
            connection.set_pam_return(Arc::new(Mutex::new(Some(pam_return))));
            connection.listen().expect("Could not listen to events");
        });
    }
}

impl crate::wm::Client for Client {
    fn pam_return(&self) -> Arc<Mutex<std::sync::mpsc::Sender<()>>> {
        self.pam_return.clone()
    }

    fn pam(&self) -> Arc<Mutex<std::sync::mpsc::Receiver<()>>> {
        self.pam.clone()
    }

    fn clear_password(&mut self) {
        clear_password!()
    }

    fn password(&self) -> String {
        PASSWORD.lock().unwrap().to_string()
    }

    fn call(&self) -> Option<std::sync::mpsc::Sender<Call>> {
        if let Some(sender) = self.sender.lock().unwrap().clone() {
            Some(sender)
        } else {
            None
        }
    }
}