Skip to main content

ursus_core/app/
window_config.rs

1use winit::dpi::LogicalSize;
2use winit::window::{Fullscreen, Icon, WindowAttributes};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum WindowMode {
6    Windowed,
7    BorderlessFullscreen,
8    ExclusiveFullscreen,
9}
10
11#[derive(Debug, Clone)]
12pub struct WindowConfig {
13    pub title: String,
14    pub width: u32,
15    pub height: u32,
16    pub resizable: bool,
17    pub mode: WindowMode,
18    pub visible_on_start: bool,
19    pub icon_rgba: Option<(Vec<u8>, u32, u32)>, // (pixels RGBA8, width, height)
20}
21
22impl Default for WindowConfig {
23    fn default() -> Self {
24        Self {
25            title: "ursus-core".to_string(),
26            width: 1280,
27            height: 720,
28            resizable: true,
29            mode: WindowMode::Windowed,
30            visible_on_start: true,
31            icon_rgba: None,
32        }
33    }
34}
35
36impl WindowConfig {
37    pub fn new() -> Self {
38        Self::default()
39    }
40
41    pub fn with_title(mut self, title: impl Into<String>) -> Self {
42        self.title = title.into();
43        self
44    }
45
46    pub fn with_size(mut self, width: u32, height: u32) -> Self {
47        self.width = width;
48        self.height = height;
49        self
50    }
51
52    pub fn with_resizable(mut self, resizable: bool) -> Self {
53        self.resizable = resizable;
54        self
55    }
56
57    pub fn with_mode(mut self, mode: WindowMode) -> Self {
58        self.mode = mode;
59        self
60    }
61
62    pub fn with_visible_on_start(mut self, visible: bool) -> Self {
63        self.visible_on_start = visible;
64        self
65    }
66
67    pub fn with_icon(mut self, pixels: Vec<u8>, width: u32, height: u32) -> Self {
68        self.icon_rgba = Some((pixels, width, height));
69        self
70    }
71
72    pub(crate) fn to_winit_attributes(&self) -> WindowAttributes {
73        let mut attrs = WindowAttributes::default()
74            .with_title(&self.title)
75            .with_inner_size(LogicalSize::new(self.width, self.height))
76            .with_resizable(self.resizable)
77            .with_visible(false);
78
79        if let Some(icon) = self.build_icon() {
80            attrs = attrs.with_window_icon(Some(icon));
81        }
82
83        if matches!(self.mode, WindowMode::BorderlessFullscreen) {
84            attrs = attrs.with_fullscreen(Some(Fullscreen::Borderless(None)));
85        }
86
87        attrs
88    }
89
90    fn build_icon(&self) -> Option<Icon> {
91        let (pixels, w, h) = self.icon_rgba.as_ref()?;
92        Icon::from_rgba(pixels.clone(), *w, *h).ok()
93    }
94}