use std::{ collections::{BinaryHeap, VecDeque}, sync::Arc, time::Instant, }; use glam::Vec2; use idmap::IdMap; use crate::{ overlays::{ keyboard::create_keyboard, screen::{get_screens_wayland, get_screens_x11}, watch::create_watch, }, state::AppState, }; use super::overlay::{OverlayData, OverlayState}; pub enum BackendError { NotSupported, Shutdown, Restart, Fatal, } pub struct OverlayContainer where T: Default, { overlays: IdMap>, pub extent: Vec2, } impl OverlayContainer where T: Default, { pub fn new(app: &mut AppState) -> Self { let mut overlays = IdMap::new(); let (screens, extent) = if std::env::var("WAYLAND_DISPLAY").is_ok() { get_screens_wayland(&app.session) } else { get_screens_x11() }; let mut watch = create_watch::(&app, &screens); watch.state.want_visible = false; overlays.insert(watch.state.id, watch); let mut keyboard = create_keyboard(&app); keyboard.state.want_visible = true; overlays.insert(keyboard.state.id, keyboard); let mut first = true; for mut screen in screens { if first { screen.state.want_visible = true; first = false; } overlays.insert(screen.state.id, screen); } Self { overlays, extent } } pub fn mut_by_selector(&mut self, selector: &OverlaySelector) -> Option<&mut OverlayData> { match selector { OverlaySelector::Id(id) => self.mut_by_id(*id), OverlaySelector::Name(name) => self.mut_by_name(name), } } pub fn get_by_id<'a>(&'a mut self, id: usize) -> Option<&'a OverlayData> { self.overlays.get(&id) } pub fn mut_by_id<'a>(&'a mut self, id: usize) -> Option<&'a mut OverlayData> { self.overlays.get_mut(&id) } pub fn get_by_name<'a>(&'a mut self, name: &str) -> Option<&'a OverlayData> { self.overlays.values().find(|o| *o.state.name == *name) } pub fn mut_by_name<'a>(&'a mut self, name: &str) -> Option<&'a mut OverlayData> { self.overlays.values_mut().find(|o| *o.state.name == *name) } pub fn iter<'a>(&'a self) -> impl Iterator> { self.overlays.values() } pub fn iter_mut<'a>(&'a mut self) -> impl Iterator> { self.overlays.values_mut() } } pub enum OverlaySelector { Id(usize), Name(Arc), } struct AppTask { pub not_before: Instant, pub task: TaskType, } impl PartialEq for AppTask { fn eq(&self, other: &Self) -> bool { self.not_before == other.not_before } } impl PartialOrd for AppTask { fn partial_cmp(&self, other: &Self) -> Option { Some(self.not_before.cmp(&other.not_before).reverse()) } } impl Eq for AppTask {} impl Ord for AppTask { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.not_before.cmp(&other.not_before).reverse() } } pub enum TaskType { Global(Box), Overlay( OverlaySelector, Box, ), } pub struct TaskContainer { tasks: BinaryHeap, } impl TaskContainer { pub fn new() -> Self { Self { tasks: BinaryHeap::new(), } } pub fn enqueue(&mut self, task: TaskType) { self.tasks.push(AppTask { not_before: Instant::now(), task, }); } pub fn enqueue_at(&mut self, task: TaskType, not_before: Instant) { self.tasks.push(AppTask { not_before, task }); } pub fn retrieve_due(&mut self, dest_buf: &mut VecDeque) { let now = Instant::now(); while let Some(task) = self.tasks.peek() { if task.not_before > now { break; } dest_buf.push_back(self.tasks.pop().unwrap().task); } } }