scrim 0.1.0

Wayland full-screen color overlay with file interface.
mod app;
mod watcher;

use std::sync::mpsc;
use std::thread;
use std::time::Duration;

use wayland_client::globals::registry_queue_init;
use wayland_client::Connection;

fn main() {
    let ctrl = "/tmp/scrim";
    std::fs::create_dir_all(ctrl).expect("无法创建 /tmp/scrim");

    for (name, default) in [("alpha", "0"), ("r", "0"), ("g", "0"), ("b", "0")] {
        let path = format!("{}/{}", ctrl, name);
        if !std::path::Path::new(&path).exists() {
            std::fs::write(&path, default).ok();
        }
    }

    ctrlc::set_handler(|| {
        std::fs::remove_dir_all("/tmp/scrim").ok();
        std::process::exit(0);
    }).expect("ctrlc");

    let (tx, rx) = mpsc::channel();
    let dir = ctrl.to_string();
    thread::spawn(move || watcher::run(&dir, tx));

    let conn = Connection::connect_to_env().expect("无法连接 Wayland");
    let (globals, mut eq) =
        registry_queue_init::<app::Scrim>(&conn).expect("无法初始化 registry");
    let qh = eq.handle();

    let mut scrim = app::Scrim::new(&conn, &globals, &qh, rx);
    eq.roundtrip(&mut scrim).unwrap();

    loop {
        // 排空所有待处理事件(frame callback 等)
        while eq.dispatch_pending(&mut scrim).unwrap() > 0 {}

        scrim.poll_messages();
        scrim.tick();

        if scrim.dirty && !scrim.waiting_frame() {
            scrim.draw(&qh);
            scrim.dirty = false;
        }

        eq.flush().unwrap();

        if scrim.waiting_frame() {
            // 等 frame callback,阻塞在 wayland 事件队列
            eq.blocking_dispatch(&mut scrim).unwrap();
        } else if scrim.animating() {
            // 动画中,短暂 sleep
            thread::sleep(Duration::from_millis(8));
        } else {
            // 空闲,等 watcher 消息
            match scrim.wait_message(Duration::from_secs(1)) {
                Some(msg) => scrim.handle_msg(msg),
                None => {}
            }
        }
    }
}