1use std::sync::Arc;
2
3use astrelis_core::geometry::{LogicalSize, PhysicalSize, ScaleFactor};
4pub use winit::dpi::PhysicalSize as WinitPhysicalSize;
5pub use winit::window::Fullscreen;
6pub use winit::window::Window as WinitWindow;
7use winit::{error::OsError, event_loop::ActiveEventLoop};
8
9pub struct WindowDescriptor {
10 pub title: String,
11 pub resizeable: bool,
12 pub size: Option<winit::dpi::PhysicalSize<f32>>,
13 pub visible: bool,
14 pub fullscreen: Option<Fullscreen>,
15}
16
17impl Default for WindowDescriptor {
18 fn default() -> Self {
19 Self {
20 title: "Astrelis Window".to_string(),
21 resizeable: true,
22 size: None,
23 visible: true,
24 fullscreen: None,
25 }
26 }
27}
28
29pub struct Window {
30 pub window: Arc<winit::window::Window>,
31}
32
33impl Window {
34 pub fn id(&self) -> winit::window::WindowId {
35 self.window.id()
36 }
37
38 pub fn logical_size(&self) -> LogicalSize<u32> {
40 let physical_size = self.window.inner_size();
41 let scale_factor = self.window.scale_factor();
42 LogicalSize::new(
43 (physical_size.width as f64 / scale_factor) as u32,
44 (physical_size.height as f64 / scale_factor) as u32,
45 )
46 }
47
48 pub fn physical_size(&self) -> PhysicalSize<u32> {
50 self.window.inner_size().into()
51 }
52
53 pub fn scale_factor(&self) -> ScaleFactor {
55 ScaleFactor(self.window.scale_factor())
56 }
57
58 pub fn scale_factor_f64(&self) -> f64 {
60 self.window.scale_factor()
61 }
62
63 pub fn platform_dpi() -> f64 {
64 #[cfg(target_os = "macos")]
65 return 2.0;
66 #[cfg(not(target_os = "macos"))]
67 return 1.0;
68 }
69
70 pub(crate) fn new(
71 event_loop: &ActiveEventLoop,
72 descriptor: WindowDescriptor,
73 ) -> Result<Self, OsError> {
74 let mut attributes = WinitWindow::default_attributes()
75 .with_title(descriptor.title)
76 .with_resizable(descriptor.resizeable)
77 .with_visible(descriptor.visible)
78 .with_fullscreen(descriptor.fullscreen);
79
80 if let Some(size) = descriptor.size {
81 attributes = attributes.with_inner_size(size);
82 }
83
84 let window = Arc::new(event_loop.create_window(attributes)?);
85
86 Ok(Window { window })
87 }
88}
89
90pub trait WindowBackend {
91 type FrameContext;
92 type Error;
93
94 fn try_begin_drawing(&mut self) -> Result<Self::FrameContext, Self::Error>;
100
101 fn begin_drawing(&mut self) -> Self::FrameContext
106 where
107 Self::Error: std::fmt::Debug,
108 {
109 self.try_begin_drawing()
110 .expect("Failed to begin drawing - consider using try_begin_drawing() for graceful error handling")
111 }
112}
113
114pub trait WindowExt {
115 fn request_redraw(&self);
120}
121
122impl WindowExt for Window {
123 fn request_redraw(&self) {
124 self.window.request_redraw();
125 }
126}