Wayland layer-shell overlay using tiny-skia for rendering a glowing rounded rectangle ring. Includes PID-based lock file toggle via SIGUSR1, keyboard capture (Escape to exit), and pointer tracking for cursor avoidance. Configurable ring geometry and glow parameters.
75 lines
1.9 KiB
Rust
75 lines
1.9 KiB
Rust
mod lock;
|
|
mod render;
|
|
mod wayland;
|
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
use anyhow::{Context, Result};
|
|
use tiny_skia::Pixmap;
|
|
|
|
use lock::ToggleResult;
|
|
use wayland::{OverlayEvent, WaylandBackend};
|
|
|
|
const DISPLAY_DURATION: Duration = Duration::from_secs(5);
|
|
|
|
fn main() -> Result<()> {
|
|
match lock::try_toggle()? {
|
|
ToggleResult::SignaledExisting => return Ok(()),
|
|
ToggleResult::RunNew => {}
|
|
}
|
|
|
|
let _lock = lock::create_lock()?;
|
|
|
|
let mut wl = WaylandBackend::new()?;
|
|
let (w, h) = wl.screen_size();
|
|
let mut pixmap = Pixmap::new(w, h).context("create pixmap")?;
|
|
let mut argb_buf = vec![0u8; (w as usize) * (h as usize) * 4];
|
|
|
|
let mut cursor_x = w as f64 / 2.0;
|
|
let mut cursor_y = h as f64 / 2.0;
|
|
|
|
draw(&mut wl, &mut pixmap, &mut argb_buf, cursor_x, cursor_y)?;
|
|
|
|
let start = Instant::now();
|
|
|
|
loop {
|
|
let elapsed = start.elapsed();
|
|
if elapsed >= DISPLAY_DURATION || lock::should_exit() {
|
|
break;
|
|
}
|
|
let remaining = DISPLAY_DURATION - elapsed;
|
|
let event = match wl.next_event(remaining)? {
|
|
Some(ev) => ev,
|
|
None => continue, // poll timeout — loop back to check elapsed time
|
|
};
|
|
match event {
|
|
OverlayEvent::Close => break,
|
|
OverlayEvent::CursorMoved(x, y) => {
|
|
cursor_x = x;
|
|
cursor_y = y;
|
|
draw(&mut wl, &mut pixmap, &mut argb_buf, cursor_x, cursor_y)?;
|
|
}
|
|
OverlayEvent::Configure(new_w, new_h) => {
|
|
if new_w != w || new_h != h {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn draw(
|
|
wl: &mut WaylandBackend,
|
|
pixmap: &mut Pixmap,
|
|
argb_buf: &mut [u8],
|
|
cursor_x: f64,
|
|
cursor_y: f64,
|
|
) -> Result<()> {
|
|
render::render_ring_light(pixmap, cursor_x, cursor_y);
|
|
render::pixmap_to_argb8888(pixmap, argb_buf);
|
|
let (w, h) = wl.screen_size();
|
|
wl.present(argb_buf, w, h)
|
|
}
|