est_render/
window.rs

1use winit::{event, event_loop::EventLoopProxy};
2
3#[cfg(feature = "software")]
4use crate::software::PixelBufferInner;
5
6use crate::{
7    gpu::GPUInner, math::Point2, runner::{CursorIcon, Handle, Runner, RunnerError, WindowEvent}, utils::{ArcMut, ArcRef}
8};
9
10#[derive(Clone, Debug)]
11pub struct Window {
12    pub(crate) inner: ArcRef<WindowInner>,
13}
14
15impl Window {
16    pub(crate) fn new(
17        runner: &mut Runner,
18        parent: Option<&Window>,
19        title: String,
20        size: Point2,
21        pos: Option<Point2>,
22    ) -> Result<Self, WindowError> {
23        let parent_id = if let Some(parent) = parent {
24            Some(parent.inner.wait_borrow().window_id)
25        } else {
26            None
27        };
28
29        let result = runner.internal_new_window(parent_id, title, size, pos);
30        if result.is_err() {
31            return Err(WindowError::RunnerError(result.unwrap_err()));
32        }
33
34        let (window_id, proxy) = result.unwrap();
35        let window_events = runner.get_events_pointer(window_id);
36        let window_pointer = runner.get_window_pointer(window_id);
37
38        if window_events.is_none() || window_pointer.is_none() {
39            return Err(WindowError::WindowNotFound);
40        }
41
42        let window_events = window_events.unwrap();
43        let window_pointer = window_pointer.unwrap();
44
45        let inner = ArcRef::new(WindowInner {
46            window_id,
47            window_events,
48            window_pointer: Some(window_pointer),
49            proxy,
50            graphics: None,
51            size: size.into(),
52
53            #[cfg(feature = "software")]
54            pixelbuffer: None,
55        });
56
57        runner.window_events_attributes.push(inner.clone());
58
59        Ok(Self { inner })
60    }
61
62    /// Get the window ID of this window.
63    ///
64    /// This is a unique identifier for the window, useful
65    /// for identifying the window in event handling and other operations.
66    pub fn id(&self) -> usize {
67        self.inner.wait_borrow().window_id
68    }
69
70    /// Get the size of the window.
71    ///
72    /// This useful for determining the dimensions of the window, such
73    /// as when rendering content or handling layout.
74    pub fn size(&self) -> Point2 {
75        self.inner.wait_borrow().size
76    }
77
78    /// Send quit event to the runner to close the window.
79    pub fn quit(&self) {
80        let inner = self.inner.wait_borrow();
81
82        _ = inner.proxy.send_event(WindowEvent::Close {
83            ref_id: inner.window_id,
84        });
85    }
86
87    /// Set the title of the window.
88    pub fn set_title(&mut self, title: &str) {
89        let inner = self.inner.wait_borrow();
90
91        _ = inner.proxy.send_event(WindowEvent::Title {
92            ref_id: inner.window_id,
93            title: title.to_string(),
94        });
95    }
96
97    /// Set the cursor icon for the window.
98    pub fn set_cursor(&mut self, cursor: Option<CursorIcon>) {
99        let inner = self.inner.wait_borrow();
100
101        _ = inner.proxy.send_event(WindowEvent::Cursor {
102            ref_id: inner.window_id,
103            cursor,
104        });
105    }
106
107    /// Set the window size.
108    pub fn set_size(&mut self, size: Point2) {
109        let inner = self.inner.wait_borrow();
110
111        _ = inner.proxy.send_event(WindowEvent::Size {
112            ref_id: inner.window_id,
113            size: size.into(),
114        });
115    }
116
117    /// Set the widnow position.
118    pub fn set_position(&mut self, pos: Point2) {
119        let inner = self.inner.wait_borrow();
120
121        _ = inner.proxy.send_event(WindowEvent::Position {
122            ref_id: inner.window_id,
123            pos: pos.into(),
124        });
125    }
126
127    /// Request a redraw of the window.
128    pub fn request_redraw(&mut self) {
129        let inner = self.inner.wait_borrow();
130
131        _ = inner.proxy.send_event(WindowEvent::Redraw {
132            ref_id: inner.window_id,
133        });
134    }
135}
136
137pub struct WindowBuilder<'a> {
138    runner: &'a mut Runner,
139    parent_window: Option<&'a Window>,
140    title: String,
141    size: Point2,
142    pos: Option<Point2>,
143}
144
145impl<'a> WindowBuilder<'a> {
146    pub(crate) fn new(runner: &'a mut Runner, title: &str, size: Point2) -> Self {
147        WindowBuilder {
148            runner,
149            parent_window: None,
150            title: title.to_string(),
151            size,
152            pos: None,
153        }
154    }
155
156    /// Sets the title of the window.
157    pub fn title(mut self, title: String) -> Self {
158        self.title = title;
159        self
160    }
161
162    /// Sets the size of the window.
163    pub fn size(mut self, size: Point2) -> Self {
164        self.size = size;
165        self
166    }
167
168    /// Sets the position of the window.
169    pub fn pos(mut self, pos: Option<Point2>) -> Self {
170        self.pos = pos;
171        self
172    }
173
174    /// Sets the parent window for this window. \
175    /// This is useful for creating child windows or popups.
176    /// The parent window must be created before this window.
177    pub fn with_parent_window(mut self, parent: &'a Window) -> Self {
178        self.parent_window = Some(parent);
179        self
180    }
181
182    pub fn build(self) -> Result<Window, WindowError> {
183        Window::new(
184            self.runner,
185            self.parent_window,
186            self.title,
187            self.size,
188            self.pos,
189        )
190    }
191}
192
193pub(crate) struct WindowInner {
194    pub window_id: usize,
195    pub window_events: ArcRef<Vec<event::WindowEvent>>,
196    pub window_pointer: Option<ArcMut<Handle>>,
197    pub proxy: EventLoopProxy<WindowEvent>,
198    pub size: Point2,
199
200    pub(crate) graphics: Option<ArcRef<GPUInner>>,
201
202    #[cfg(feature = "software")]
203    pub(crate) pixelbuffer: Option<ArcRef<PixelBufferInner>>,
204}
205
206impl WindowInner {
207    pub fn process_event(&mut self) {
208        for event in self.window_events.wait_borrow_mut().iter() {
209            match event {
210                event::WindowEvent::CloseRequested => {
211                    self.graphics = None;
212                    self.window_pointer = None;
213                }
214                event::WindowEvent::Resized(size) => {
215                    if let Some(gpu) = &self.graphics {
216                        gpu.wait_borrow_mut().resize(*size);
217                    }
218
219                    #[cfg(feature = "software")]
220                    if let Some(softbuffer) = &self.pixelbuffer {
221                        _ = softbuffer.wait_borrow_mut().resize(*size);
222                    }
223
224                    self.size = Point2::from(*size);
225                }
226                _ => {}
227            }
228        }
229    }
230
231    pub fn cycle(&mut self) {
232        if let Some(gpu) = &self.graphics {
233            gpu.wait_borrow_mut().cycle();
234        }
235    }
236}
237
238
239#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
240pub enum RunMode {
241    Poll,
242    ReDraw,
243}
244
245#[derive(Clone, Debug, Eq, Hash, PartialEq)]
246pub enum WindowError {
247    RunnerError(RunnerError),
248    WindowNotFound,
249}