use crate::services::windows::window::{Window, WindowId}; use crate::task::TaskId; use crate::windows::WindowOwner; use prometeu_hal::color::Color; use prometeu_hal::primitives::Rect; /// PROMETEU Window Manager. pub struct WindowManager { pub windows: Vec, pub focused: Option, } impl Default for WindowManager { fn default() -> Self { Self::new() } } impl WindowManager { pub fn new() -> Self { Self { windows: Vec::new(), focused: None } } pub fn add_window( &mut self, title: String, owner: WindowOwner, viewport: Rect, color: Color, ) -> WindowId { let id = WindowId(self.windows.len() as u32); let window = Window { id, owner, viewport, has_focus: false, title, color }; self.windows.push(window); id } pub fn remove_window(&mut self, id: WindowId) { self.windows.retain(|w| w.id != id); if self.focused == Some(id) { self.focused = None; } } pub fn remove_all_windows(&mut self) { self.windows.clear(); self.focused = None; } pub fn set_focus(&mut self, id: WindowId) { self.focused = Some(id); for window in &mut self.windows { window.has_focus = window.id == id; } } pub fn focused_window_belongs_to_task(&self, task_id: TaskId) -> bool { let Some(focused_id) = self.focused else { return false; }; self.windows .iter() .find(|window| window.id == focused_id) .is_some_and(|window| window.owner == WindowOwner::Task(task_id)) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_window_manager_focus() { let mut wm = WindowManager::new(); let id1 = wm.add_window( "Window 1".to_string(), WindowOwner::Hub, Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); let id2 = wm.add_window( "Window 2".to_string(), WindowOwner::Hub, Rect { x: 10, y: 10, w: 10, h: 10 }, Color::WHITE, ); assert_eq!(wm.windows.len(), 2); assert_eq!(wm.focused, None); wm.set_focus(id1); assert_eq!(wm.focused, Some(id1)); assert!(wm.windows[0].has_focus); assert!(!wm.windows[1].has_focus); wm.set_focus(id2); assert_eq!(wm.focused, Some(id2)); assert!(!wm.windows[0].has_focus); assert!(wm.windows[1].has_focus); } #[test] fn test_window_manager_remove_window() { let mut wm = WindowManager::new(); let id = wm.add_window( "Window".to_string(), WindowOwner::Hub, Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); wm.set_focus(id); assert_eq!(wm.focused, Some(id)); wm.remove_window(id); assert_eq!(wm.windows.len(), 0); assert_eq!(wm.focused, None); } #[test] fn focused_window_belongs_to_task_returns_false_without_focus() { let mut wm = WindowManager::new(); wm.add_window( "Task Window".to_string(), WindowOwner::Task(crate::task::TaskId(1)), Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1))); } #[test] fn focused_window_belongs_to_task_matches_focused_task_owner() { let mut wm = WindowManager::new(); let id = wm.add_window( "Task Window".to_string(), WindowOwner::Task(crate::task::TaskId(1)), Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); wm.set_focus(id); assert!(wm.focused_window_belongs_to_task(crate::task::TaskId(1))); } #[test] fn focused_window_belongs_to_task_rejects_other_task_owner() { let mut wm = WindowManager::new(); let id = wm.add_window( "Task Window".to_string(), WindowOwner::Task(crate::task::TaskId(2)), Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); wm.set_focus(id); assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1))); } #[test] fn focused_window_belongs_to_task_rejects_hub_owner() { let mut wm = WindowManager::new(); let id = wm.add_window( "Hub Window".to_string(), WindowOwner::Hub, Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); wm.set_focus(id); assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1))); } #[test] fn focused_window_belongs_to_task_rejects_overlay_owner() { let mut wm = WindowManager::new(); let id = wm.add_window( "Overlay Window".to_string(), WindowOwner::Overlay, Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); wm.set_focus(id); assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1))); } #[test] fn focused_window_belongs_to_task_rejects_stale_focus() { let mut wm = WindowManager::new(); wm.add_window( "Task Window".to_string(), WindowOwner::Task(crate::task::TaskId(1)), Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE, ); wm.focused = Some(WindowId(999)); assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1))); } }