use std::borrow::Cow; use crate::ecs::Component; use crate::reflection::Reflection; use crate::windowing::dpi::{PhysicalSize, Position, Size}; pub mod platform; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Id { inner: winit::window::WindowId, } impl Id { pub(crate) fn from_inner(inner: winit::window::WindowId) -> Self { Self { inner } } } #[derive(Debug, Component, Clone)] #[non_exhaustive] pub struct CreationAttributes { pub title: Cow<'static, str>, pub transparent: bool, pub maximized: bool, pub fullscreen: Option, pub visible: bool, pub resizable: bool, pub position: Option, pub inner_size: Option, pub x_visual_id: Option, } macro_rules! gen_creation_attrs_with_fn { ($field: ident, $field_type: ty) => { paste::paste! { impl CreationAttributes { pub fn [](mut self, new: impl Into<$field_type>) -> Self { self.$field = new.into(); self } } } }; } gen_creation_attrs_with_fn!(title, Cow<'static, str>); gen_creation_attrs_with_fn!(transparent, bool); gen_creation_attrs_with_fn!(maximized, bool); gen_creation_attrs_with_fn!(fullscreen, Option); gen_creation_attrs_with_fn!(visible, bool); gen_creation_attrs_with_fn!(resizable, bool); gen_creation_attrs_with_fn!(position, Option); gen_creation_attrs_with_fn!(inner_size, Option); gen_creation_attrs_with_fn!(x_visual_id, Option); impl CreationAttributes { pub(crate) fn into_window_attrs(self) -> winit::window::WindowAttributes { let mut window_attrs = winit::window::WindowAttributes::default() .with_title(self.title.into_owned()) .with_transparent(self.transparent) .with_maximized(self.maximized) .with_fullscreen(match self.fullscreen { Some(Fullscreen::Borderless) => Some(winit::window::Fullscreen::Borderless(None)), None => None }) .with_visible(self.visible) .with_resizable(self.resizable); window_attrs.position = self.position.map(Into::into); window_attrs.inner_size = self.inner_size.map(Into::into); #[cfg(target_os = "linux")] if let Some(visual_id) = self.x_visual_id { return ::with_x11_visual(window_attrs, visual_id) } window_attrs } } impl Default for CreationAttributes { fn default() -> Self { Self { title: "Unnamed window".into(), transparent: false, maximized: false, fullscreen: None, visible: true, resizable: true, position: None, inner_size: None, x_visual_id: None } } } #[derive(Debug, Clone)] #[non_exhaustive] pub enum Fullscreen { Borderless, } #[derive(Debug, Component, Clone, Copy)] pub struct CreationReady; #[derive(Debug, Component, Reflection)] #[non_exhaustive] pub struct Window { pub title: String, pub cursor_visible: bool, pub cursor_grab_mode: CursorGrabMode, pub inner_size: PhysicalSize, wid: Id, scale_factor: f64, } impl Window { pub fn wid(&self) -> Id { self.wid } pub fn scale_factor(&self) -> f64 { self.scale_factor } pub(crate) fn new( winit_window: &winit::window::Window, creation_attrs: &CreationAttributes, ) -> Self { Self { title: creation_attrs.title.clone().into_owned(), cursor_visible: true, cursor_grab_mode: CursorGrabMode::None, wid: Id::from_inner(winit_window.id()), inner_size: winit_window.inner_size().into(), scale_factor: winit_window.scale_factor(), } } #[must_use] pub(crate) fn apply(&self, winit_window: &winit::window::Window) -> ApplyResults { winit_window.set_title(&self.title); winit_window.set_cursor_visible(self.cursor_visible); let curr_inner_size = winit_window.inner_size().clone().into(); let inner_size_request_result = match winit_window .request_inner_size(winit::dpi::Size::Physical(self.inner_size.clone().into())) { // The comparison of curr_inner_size is in case the user's windowing system // lies about using the requested inner size None if curr_inner_size == self.inner_size => Ok(()), None => Err(curr_inner_size), Some(inner_size) => Err(inner_size.into()), }; ApplyResults { inner_size_request: inner_size_request_result, } } pub(crate) fn set_scale_factor(&mut self, scale_factor: f64) { self.scale_factor = scale_factor; } } #[derive(Debug, Component)] pub struct Closed; #[derive( Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Reflection, )] #[repr(usize)] pub enum CursorGrabMode { #[default] None, /// The cursor is locked to a specific position in the window. Locked, } /// A unique identifier for an X11 visual. pub type XVisualID = u32; #[derive(Debug)] pub(crate) struct ApplyResults { pub inner_size_request: Result<(), PhysicalSize>, }