veridian_kernel/graphics/
compositor.rs1#![allow(dead_code)] use alloc::vec::Vec;
10
11use spin::RwLock;
12
13use super::Rect;
14use crate::{error::KernelError, sync::once_lock::GlobalState};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct WindowId(pub u32);
19
20#[derive(Debug, Clone)]
22pub struct Window {
23 pub id: WindowId,
24 pub rect: Rect,
25 pub title: &'static str,
26 pub visible: bool,
27 pub focused: bool,
28 pub surface_id: u32,
30}
31
32impl Window {
33 pub fn new(id: WindowId, rect: Rect, title: &'static str) -> Self {
34 Self {
35 id,
36 rect,
37 title,
38 visible: true,
39 focused: false,
40 surface_id: 0,
41 }
42 }
43}
44
45pub struct Compositor {
47 windows: Vec<Window>,
48 next_id: u32,
49 focused_window: Option<WindowId>,
50 bg_color: u32,
52}
53
54impl Compositor {
55 pub const fn new() -> Self {
56 Self {
57 windows: Vec::new(),
58 next_id: 1,
59 focused_window: None,
60 bg_color: 0xFF2D_3436,
61 }
62 }
63}
64
65impl Default for Compositor {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl Compositor {
72 pub fn create_window(&mut self, rect: Rect, title: &'static str) -> WindowId {
74 let id = WindowId(self.next_id);
75 self.next_id += 1;
76
77 let window = Window::new(id, rect, title);
78 self.windows.push(window);
79
80 if self.focused_window.is_none() {
81 self.focused_window = Some(id);
82 }
83
84 id
85 }
86
87 pub fn destroy_window(&mut self, id: WindowId) {
89 self.windows.retain(|w| w.id != id);
90 if self.focused_window == Some(id) {
91 self.focused_window = self.windows.first().map(|w| w.id);
92 }
93 }
94
95 pub fn get_window(&self, id: WindowId) -> Option<&Window> {
97 self.windows.iter().find(|w| w.id == id)
98 }
99
100 pub fn focus_window(&mut self, id: WindowId) {
102 for window in &mut self.windows {
103 window.focused = window.id == id;
104 }
105 self.focused_window = Some(id);
106 }
107
108 pub fn focused_window(&self) -> Option<WindowId> {
110 self.focused_window
111 }
112
113 pub fn window_count(&self) -> usize {
115 self.windows.len()
116 }
117
118 pub fn render(&mut self) {
123 for _window in &self.windows {
126 }
128 }
129}
130
131static COMPOSITOR: GlobalState<RwLock<Compositor>> = GlobalState::new();
132
133pub fn with_compositor<R, F: FnOnce(&mut Compositor) -> R>(f: F) -> Option<R> {
135 COMPOSITOR.with(|comp| {
136 let mut compositor = comp.write();
137 f(&mut compositor)
138 })
139}
140
141pub fn init() -> Result<(), KernelError> {
143 println!("[COMP] Initializing compositor...");
144
145 if COMPOSITOR.init(RwLock::new(Compositor::new())).is_err() {
147 println!("[COMP] Compositor already initialized, skipping...");
149 return Ok(());
150 }
151
152 with_compositor(|comp| {
154 comp.create_window(
155 Rect {
156 x: 100,
157 y: 100,
158 width: 640,
159 height: 480,
160 },
161 "VeridianOS",
162 )
163 });
164
165 println!("[COMP] Compositor initialized");
166 Ok(())
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_compositor_create_window() {
175 let mut comp = Compositor::new();
176 let id = comp.create_window(
177 Rect {
178 x: 0,
179 y: 0,
180 width: 100,
181 height: 100,
182 },
183 "Test",
184 );
185 assert!(comp.get_window(id).is_some());
186 }
187
188 #[test]
189 fn test_compositor_destroy_window() {
190 let mut comp = Compositor::new();
191 let id = comp.create_window(
192 Rect {
193 x: 0,
194 y: 0,
195 width: 100,
196 height: 100,
197 },
198 "Test",
199 );
200 comp.destroy_window(id);
201 assert!(comp.get_window(id).is_none());
202 }
203}