game: start on updated WindowOptions component and window_sync_system

This commit is contained in:
SeanOMik 2024-09-21 14:09:24 -04:00
parent 782d64f6cf
commit 393b4206d3
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
1 changed files with 330 additions and 358 deletions

View File

@ -1,10 +1,10 @@
use std::sync::Arc; use std::sync::Arc;
use glam::{IVec2, Vec2}; use glam::{IVec2, Vec2};
use lyra_ecs::{query::{Entities, ResMut, TickOf}, Component, World}; use lyra_ecs::{query::{filter::Changed, Entities, ResMut, TickOf}, Component, World};
use tracing::{error, warn}; use tracing::{error, warn};
use winit::{ use winit::{
dpi::{LogicalPosition, LogicalSize, PhysicalPosition}, error::ExternalError, monitor::VideoModeHandle, window::{Fullscreen, Window} dpi::{LogicalPosition, LogicalSize, PhysicalPosition}, error::ExternalError, monitor::VideoModeHandle, window::{CustomCursor, Fullscreen, Window, WindowAttributes}
}; };
pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel}; pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel};
@ -19,7 +19,7 @@ pub struct Area {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum Size { pub enum Size {
Physical { x: i32, y: i32 }, Physical { x: u32, y: u32 },
Logical { x: f64, y: f64 }, Logical { x: f64, y: f64 },
} }
@ -38,9 +38,18 @@ impl Into<winit::dpi::Size> for Size {
} }
} }
impl From<winit::dpi::Size> for Size {
fn from(value: winit::dpi::Size) -> Self {
match value {
winit::dpi::Size::Physical(physical_position) => Self::new_physical(physical_position.width, physical_position.height),
winit::dpi::Size::Logical(logical_position) => Self::new_logical(logical_position.width, logical_position.height),
}
}
}
impl Size { impl Size {
pub fn new_physical(x: i32, y: i32) -> Self { pub fn new_physical(x: u32, y: u32) -> Self {
Self::Physical { x, y } Self::Physical { x, y }
} }
@ -70,6 +79,15 @@ impl Into<winit::dpi::Position> for Position {
} }
} }
impl From<winit::dpi::Position> for Position {
fn from(value: winit::dpi::Position) -> Self {
match value {
winit::dpi::Position::Physical(physical_position) => Self::new_physical(physical_position.x, physical_position.y),
winit::dpi::Position::Logical(logical_position) => Self::new_logical(logical_position.x, logical_position.y),
}
}
}
impl Position { impl Position {
pub fn new_physical(x: i32, y: i32) -> Self { pub fn new_physical(x: i32, y: i32) -> Self {
Self::Physical { x, y } Self::Physical { x, y }
@ -84,331 +102,344 @@ impl Position {
#[derive(Clone, Component)] #[derive(Clone, Component)]
pub struct PrimaryWindow; pub struct PrimaryWindow;
#[derive(Clone)]
pub enum CursorAppearance {
Icon(CursorIcon),
Custom(CustomCursor)
}
#[derive(Clone)]
pub struct Cursor {
/// Modifies the cursor icon of the window.
///
/// Platform-specific
/// * **iOS / Android / Orbital:** Unsupported.
/// * **Web:** Custom cursors have to be loaded and decoded first, until then the previous cursor is shown.
appearance: CursorAppearance,
/// Gets/sets the window's cursor grab mode
///
/// # Tip:
/// First try confining the cursor, and if it fails, try locking it instead.
grab: CursorGrabMode,
/// Gets/sets whether the window catches cursor events.
///
/// If `false`, events are passed through the window such that any other window behind it
/// receives them. By default hittest is enabled.
///
/// Platform-specific
/// * **iOS / Android / Web / Orbital:** Unsupported.
hittest: bool,
/// Gets/sets the cursor's visibility
///
/// Platform-specific
/// * **Windows / X11 / Wayland:** The cursor is only hidden within the confines of the window.
/// * **macOS:** The cursor is hidden as long as the window has input focus, even if the
/// cursor is outside of the window.
/// * **iOS / Android:** Unsupported.
visible: bool,
//cursor_position: Option<PhysicalPosition<i32>>,
}
/// Options that the window will be created with. /// Options that the window will be created with.
#[derive(Clone, Component)] #[derive(Clone, Component)]
pub struct WindowOptions { pub struct WindowOptions {
/// Prevents the window contents from being captured by other apps. /// The enabled window buttons.
/// ///
/// Platform-specific: /// Platform-specific
/// * macOS: if false, NSWindowSharingNone is used but doesnt completely prevent all apps /// * **Wayland / X11 / Orbital:** Not implemented. Always set to [`WindowButtons::all`].
/// from reading the window content, for instance, QuickTime. /// * **Web / iOS / Android:** Unsupported. Always set to [`WindowButtons::all`].
/// * iOS / Android / x11 / Wayland / Web / Orbital: Unsupported. enabled_buttons: WindowButtons,
pub content_protected: bool,
/// Gets or sets if the window is in focus.
///
/// Platform-specific
/// * **iOS / Android / Wayland / Orbital:** Unsupported.
focused: bool,
/// Set grabbing mode on the cursor preventing it from leaving the window. /// Gets or sets the fullscreen setting.
pub cursor_grab: CursorGrabMode, ///
/// If this is `None`, the window is windowed.
///
/// Platform-specific
/// * **iOS:** Can only be called on the main thread.
/// * **Android / Orbital:** Will always return None.
/// * **Wayland:** Can return Borderless(None) when there are no monitors.
/// * **Web:** Can only return None or Borderless(None).
fullscreen: Option<Fullscreen>,
/// Modifies whether the window catches cursor events. /// Gets/sets the position of the top-left hand corner of the windows client area relative to
/// the top-left hand corner of the desktop.
///
/// Note that the top-left hand corner of the desktop is not necessarily the same
/// as the screen. If the user uses a desktop with multiple monitors, the top-left
/// hand corner of the desktop is the top-left hand corner of the monitor at the
/// top-left of the desktop.
///
/// If this is none, the position will be chosen by the windowing manager at creation, then set
/// when the window is created.
///
/// Platform-specific
/// * **iOS:** Value is the top left coordinates of the windows safe area in the screen
/// space coordinate system.
/// * **Web:** Value is the top-left coordinates relative to the viewport. Note: this will be
/// the same value as [`WindowOptions::outer_position`].
/// * **Android / Wayland:** Unsupported.
inner_position: Option<Position>,
/// If true, the window will catch the cursor events. If false, events are passed through /// Gets/sets the size of the view in the window.
/// the window such that any otherwindow behind it receives them. By default hittest is enabled. ///
/// /// The size does not include the window title bars and borders.
/// Platform-specific: ///
/// * iOS / Android / Web / X11 / Orbital: Unsupported. /// Platform-specific
pub cursor_hittest: bool, /// * **Web:** The size of the canvas element. Doesnt account for CSS `transform`.
size: Option<Size>,
/// Modifies the cursor icon of the window. /// Gets/sets if the window has decorations.
/// ///
/// Platform-specific: /// Platform-specific
/// * iOS / Android / Orbital: Unsupported. /// * **iOS / Android / Web:** Always set to `true`.
/// * Web: Custom cursors have to be loaded and decoded first, until then the previous decorated: bool,
/// cursor is shown.
pub cursor: winit::window::Cursor,
/// The cursors visibility. /// Gets/sets the window's current maximized state
/// If false, this will hide the cursor. If true, this will show the cursor. ///
/// /// Platform-specific
/// Platform-specific: /// * **iOS / Android / Web:** Unsupported.
/// * Windows: The cursor is only hidden within the confines of the window. maximized: bool,
/// * X11: The cursor is only hidden within the confines of the window.
/// * Wayland: The cursor is only hidden within the confines of the window.
/// * macOS: The cursor is hidden as long as the window has input focus, even if
/// the cursor is outside of the window.
/// * iOS / Android / Orbital: Unsupported.
pub cursor_visible: bool,
/// The windows current visibility state. /// Gets/sets the window's current minimized state.
///
/// Is `None` if the minimized state could not be determined.
///
/// Platform-specific
/// * **Wayland:** always `None`, un-minimize is unsupported.
/// * **iOS / Android / Web / Orbital:** Unsupported.
minimized: Option<bool>,
/// Gets/sets the window's current resizable state
///
/// If this is false, the window can still be resized by changing [`WindowOptions::size`].
///
/// Platform-specific
/// Setting this only has an affect on desktop platforms.
///
/// * **X11:** Due to a bug in XFCE, setting this has no effect..
/// * **iOS / Android / Web:** Unsupported.
resizable: bool,
/// Gets/sets the window's current visibility state.
///
/// `None` means it couldn't be determined.
/// ///
/// Platform-specific /// Platform-specific
/// * **X11:** Not implemented. /// * **X11:** Not implemented.
/// * **Wayland / iOS / Android / Web:** Unsupported. /// * **Wayland / Android / Web:** Unsupported.
pub visible: bool, /// * **iOS:** Setting is not implemented, getting is unsupported.
visible: Option<bool>,
/// The window's transparency state. /// Gets/sets the position of the top-left hand corner of the window relative to
/// the top-left hand corner of the desktop.
///
/// Note that the top-left hand corner of the desktop is not necessarily the same
/// as the screen. If the user uses a desktop with multiple monitors, the top-left
/// hand corner of the desktop is the top-left hand corner of the monitor at the
/// top-left of the desktop.
///
/// If this is none, the position will be chosen by the windowing manager at creation, then set
/// when the window is created.
///
/// Platform-specific
/// * **iOS:** Value is the top left coordinates of the windows safe area in the screen
/// space coordinate system.
/// * **Web:** Value is the top-left coordinates relative to the viewport.
/// * **Android / Wayland:** Unsupported.
outer_position: Option<Position>,
/// Gets/sets the window resize increments.
///
/// This is a niche constraint hint usually employed by terminal emulators and other apps
/// that need “blocky” resizes.
///
/// Platform-specific
/// * **macOS:** Increments are converted to logical size and then macOS rounds them to whole numbers.
/// * **Wayland:** Not implemented, always `None`.
/// * **iOS / Android / Web / Orbital:** Unsupported.
resize_increments: Option<Size>,
/// Gets/sets the scale factor.
///
/// The scale factor is the ratio of physical pixels to logical pixels.
/// See [winit docs](https://docs.rs/winit/latest/winit/window/struct.Window.html#method.scale_factor)
/// for more information.
scale_factor: f64,
/// Gets/sets the window's blur state.
///
/// Platform-specific
/// * **Android / iOS / X11 / Web / Windows:** Unsupported.
/// * **Wayland:** Only works with org_kde_kwin_blur_manager protocol.
blur: bool,
/// Prevents the window contents from being captured by other apps.
///
/// Platform-specific
/// * **macOS:** if false, [`NSWindowSharingNone`](https://developer.apple.com/documentation/appkit/nswindowsharingtype/nswindowsharingnone)
/// is used but doesnt completely prevent all apps from reading the window content,
/// for instance, QuickTime.
/// * **iOS / Android / x11 / Wayland / Web / Orbital:** Unsupported.
content_protected: bool,
cursor: Cursor,
/// Sets whether the window should get IME events
///
/// When IME is allowed, the window will receive [`Ime`](winit::event::WindowEvent::Ime)
/// events, and during the preedit phase the window will NOT get KeyboardInput events.
/// The window should allow IME while it is expecting text input.
///
/// When IME is not allowed, the window wont receive [`Ime`](winit::event::WindowEvent::Ime)
/// events, and will receive [`KeyboardInput`](winit::event::WindowEvent::KeyboardInput) events
/// for every keypress instead. Not allowing IME is useful for games for example.
/// IME is not allowed by default.
///
/// Platform-specific
/// * **macOS:** IME must be enabled to receive text-input where dead-key sequences are combined.
/// * **iOS / Android / Web / Orbital:** Unsupported.
/// * **X11:** Enabling IME will disable dead keys reporting during compose.
ime_allowed: bool,
/// Sets area of IME candidate box in window client area coordinates relative to the top left.
///
/// Platform-specific
/// * **X11:** - area is not supported, only position.
/// * **iOS / Android / Web / Orbital:** Unsupported.
ime_cursor_area: Option<Area>,
/// Gets/sets the minimum size of the window.
///
/// Platform-specific
/// * **iOS / Android / Orbital:** Unsupported.
min_size: Option<Size>,
/// Gets/sets the maximum size of the window.
///
/// Platform-specific
/// * **iOS / Android / Orbital:** Unsupported.
max_size: Option<Size>,
/// Gets/sets the current window theme.
///
/// Specify `None` to reset the theme to the system default. May also be `None` on unsupported
/// platforms.
///
/// Platform-specific
/// * **Wayland:** Sets the theme for the client side decorations. Using `None` will use dbus
/// to get the system preference.
/// * **X11:** Sets `_GTK_THEME_VARIANT` hint to `dark` or `light` and if `None` is used,
/// it will default to [`Theme::Dark`](winit::window::Theme::Dark).
/// * **iOS / Android / Web / Orbital:** Unsupported.
theme: Option<Theme>,
/// Gets/sets the title of the window.
///
/// Platform-specific
/// * **iOS / Android:** Unsupported.
/// * **X11 / Wayland / Web:** Cannot get, will always be an empty string.
title: String,
/// Gets/sets the window's transparency state.
/// ///
/// This is just a hint that may not change anything about the window transparency, however /// This is just a hint that may not change anything about the window transparency, however
/// doing a mismatch between the content of your window and this hint may result in visual /// doing a mismatch between the content of your window and this hint may result in visual
/// artifacts. /// artifacts.
/// ///
/// The default value follows the [`winit::window::WindowAttributes::with_transparent`].
///
/// Platform-specific /// Platform-specific
/// * **macOS:** This will reset the windows background color. /// * **macOS:** This will reset the windows background color.
/// * **Web / iOS / Android:** Unsupported. /// * **Web / iOS / Android:** Unsupported.
/// * **X11:** Can only be set while building the window, with /// * **X11:** Can only be set while building the window.
/// [`winit::window::WindowAttributes::with_transparent`]. transparent: bool,
pub transparent: bool,
/// The current blur state of the window /// Sets the window's icon.
/// ///
/// If `true`, this will make the transparent window background blurry. /// On Windows and X11, this is typically the small icon in the top-left corner of
/// the titlebar.
/// ///
/// Platform-specific /// Platform-specific
/// * **Android / iOS / X11 / Web / Windows:** Unsupported. /// * **iOS / Android / Web / Wayland / macOS / Orbital:** Unsupported.
/// * **Wayland:** Only works with org_kde_kwin_blur_manager protocol. /// * **Windows:** Sets `ICON_SMALL`. The base size for a window icon is 16x16, but its
pub blur: bool, /// recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
/// * **X11:** Has no universal guidelines for icon sizes, so youre at the whims of
/// Turn window decorations on or off. /// the WM. That said, its usually in the same ballpark as on Windows.
/// Enable/disable window decorations provided by the server or Winit. By default this is enabled. window_icon: Option<Icon>,
///
/// Platform-specific
/// * iOS / Android / Web: No effect.
pub decorations: bool,
/// Sets the enabled window buttons.
///
/// Platform-specific:
/// * Wayland / X11 / Orbital: Not implemented.
/// * Web / iOS / Android: Unsupported.
pub enabled_buttons: WindowButtons,
/// The fullscreen settings for the monitor.
///
/// Set to `None` for windowed.
pub fullscreen: Option<Fullscreen>,
/// Sets whether the window should get IME events.
///
/// If its allowed, the window will receive Ime events instead of KeyboardInput events.
/// This should only be allowed if the window is expecting text input.
///
/// Platform-specific:
/// * iOS / Android / Web / Orbital: Unsupported.
pub ime_allowed: bool,
/// Set the IME cursor editing area, where the `position` is the top left corner of that
/// area and `size` is the size of this area starting from the position. An example of such
/// area could be a input field in the UI or line in the editor.
///
/// The windowing system could place a candidate box close to that area, but try to not
/// obscure the specified area, so the user input to it stays visible.
///
/// The candidate box is the window / popup / overlay that allows you to select the desired
/// characters. The look of this box may differ between input devices, even on the same
/// platform.
///
/// (Apples official term is “candidate window”, see their chinese and japanese guides).
///
/// Platform-specific
/// * **X11:** - area is not supported, only position.
/// * **iOS / Android / Web / Orbital:** Unsupported.
pub ime_cursor_area: Area,
/// Modifies the inner size of the window.
///
/// Platform-specific:
/// * iOS / Android: Unsupported.
/// * Web: Sets the size of the canvas element.
pub inner_size: Size,
/// Sets a maximum dimension size for the window.
///
/// Platform-specific:
/// * iOS / Android / Web / Orbital: Unsupported.
pub max_inner_size: Option<Size>,
/// Sets a minimum dimension size for the window.
///
/// Platform-specific:
/// * iOS / Android / Web / Orbital: Unsupported.
pub min_inner_size: Option<Size>,
/// The top-left hand corner of the window relative to the top-left hand corner of the desktop.
///
/// Note that the top-left hand corner of the desktop is not necessarily the same as the
/// screen. If the user uses a desktop with multiple monitors, the top-left hand corner of
/// the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
///
/// Platform-specific
/// * **iOS:** Can only be called on the main thread. Returns the top left coordinates of
/// the window in the screen space coordinate system.
/// * **Web:** Returns the top-left coordinates relative to the viewport.
/// * **Android / Wayland:** Always returns NotSupportedError.
pub outer_position: Option<Position>,
/// Returns the position of the top-left hand corner of the windows client area relative to
/// the top-left hand corner of the desktop.
///
/// The same conditions that apply to `WindowOptions::outer_position` apply to this.
///
/// Platform-specific
/// * **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
/// windows safe area in the screen space coordinate system.
/// * **Web:** Returns the top-left coordinates relative to the viewport.
/// * **Android / Wayland:** Always returns NotSupportedError.
pub inner_position: Option<Position>,
/// Sets the window to maximized or back.
///
/// Platform-specific:
/// * iOS / Android / Web / Orbital: Unsupported.
pub maximized: bool,
/// Sets the window to minimized or back.
///
/// Platform-specific:
/// * iOS / Android / Web / Orbital: Unsupported.
pub minimized: bool,
/// Modifies the position of the window.
///
/// Platform-specific:
/// * Web: Sets the top-left coordinates relative to the viewport.
/// * Android / Wayland: Unsupported.
//pub outer_position: Vec2,
/// Sets whether the window is resizable or not.
///
/// Platform-specific:
/// * X11: Due to a bug in XFCE, this has no effect on Xfwm.
/// * iOS / Android / Web: Unsupported.
pub resizeable: bool,
/// Sets window resize increments.
/// This is a niche constraint hint usually employed by terminal emulators and other apps that need “blocky” resizes.
///
/// Platform-specific:
/// * Wayland / Windows: Not implemented.
/// * iOS / Android / Web / Orbital: Unsupported.
pub resize_increments: Option<Size>,
/// Sets the current window theme. Use None to fallback to system default.
///
/// Platform-specific:
/// * macOS: This is an app-wide setting.
/// * x11: If None is used, it will default to Theme::Dark.
/// * iOS / Android / Web / x11 / Orbital: Unsupported.
pub theme: Option<Theme>,
/// Modifies the title of the window.
///
/// Platform-specific:
/// * iOS / Android: Unsupported.
pub title: String,
/// Sets the window icon.
/// On Windows and X11, this is typically the small icon in the top-left corner of the titlebar.
///
/// Platform-specific
/// * iOS / Android / Web / Wayland / macOS / Orbital: Unsupported.
/// * Windows: Sets ICON_SMALL. The base size for a window icon is 16x16, but its recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
/// * X11: Has no universal guidelines for icon sizes, so youre at the whims of the WM. That said, its usually in the same ballpark as on Windows.
pub icon: Option<Icon>,
/// Change the window level. /// Change the window level.
///
/// This is just a hint to the OS, and the system could ignore it. /// This is just a hint to the OS, and the system could ignore it.
pub level: WindowLevel, ///
/// See [`WindowLevel`] for details.
window_level: WindowLevel,
/// Get/set the window's focused state. /// Show [window menu](https://en.wikipedia.org/wiki/Common_menus_in_Microsoft_Windows#System_menu)
pub focused: bool, /// at a specified position.
///
/// This is the context menu that is normally shown when interacting with the title bar. This is useful when implementing custom decorations.
/// Platform-specific
/// * **Android / iOS / macOS / Orbital / Wayland / Web / X11:** Unsupported.
show_window_menu: Option<Position>,
}
/// Get whether or not the cursor is inside the window. impl From<winit::window::WindowAttributes> for WindowOptions {
pub cursor_inside_window: bool, fn from(value: winit::window::WindowAttributes) -> Self {
Self {
enabled_buttons: value.enabled_buttons,
focused: false,
fullscreen: value.fullscreen,
inner_position: None,
size: value.inner_size.map(|s| s.into()),
decorated: value.decorations,
maximized: value.maximized,
minimized: None,
resizable: value.resizable,
visible: Some(value.visible),
outer_position: value.position.map(|p| p.into()),
resize_increments: value.resize_increments.map(|r| r.into()),
scale_factor: 1.0,
blur: value.blur,
content_protected: value.content_protected,
cursor: Cursor {
appearance: match value.cursor {
winit::window::Cursor::Icon(icon) => CursorAppearance::Icon(icon),
winit::window::Cursor::Custom(custom) => CursorAppearance::Custom(custom),
},
grab: CursorGrabMode::None,
hittest: true,
visible: true,
},
ime_allowed: false,
ime_cursor_area: None,
min_size: value.min_inner_size.map(|m| m.into()),
max_size: value.max_inner_size.map(|m| m.into()),
theme: value.preferred_theme,
title: value.title,
transparent: value.transparent,
window_icon: value.window_icon,
window_level: value.window_level,
show_window_menu: None,
}
}
} }
impl Default for WindowOptions { impl Default for WindowOptions {
fn default() -> Self { fn default() -> Self {
Self { Self::from(Window::default_attributes())
content_protected: false,
cursor_grab: CursorGrabMode::None,
cursor_hittest: true,
cursor: Default::default(),
cursor_visible: true,
decorations: true,
enabled_buttons: WindowButtons::all(),
fullscreen: None,
ime_allowed: false,
ime_cursor_area: Area::default(),
inner_size: Size::new_physical(800, 600),
max_inner_size: None,
min_inner_size: None,
maximized: false,
minimized: false,
//outer_position: Default::default(),
resizeable: false,
resize_increments: None,
theme: None,
title: "Lyra Engine Game".to_string(),
icon: None,
level: WindowLevel::Normal,
focused: false,
cursor_inside_window: false,
blur: false,
inner_position: None,
outer_position: None,
transparent: false,
visible: true,
}
} }
} }
impl WindowOptions { #[derive(Clone, Component)]
pub(crate) fn as_winit_attributes(&self) -> winit::window::WindowAttributes { struct LastWindow {
let mut att = Window::default_attributes(); last: WindowOptions,
att.inner_size = Some(self.inner_size.into());
if let Some(min_inner_size) = self.min_inner_size {
att.min_inner_size = Some(min_inner_size.into());
}
if let Some(max_inner_size) = self.max_inner_size {
att.max_inner_size = Some(max_inner_size.into());
}
if let Some(position) = self.outer_position.clone()
.or(self.inner_position.clone())
{
att.position = Some(position.into());
}
att.resizable = self.resizeable;
att.enabled_buttons = self.enabled_buttons.clone();
att.title = self.title.clone();
att.maximized = self.maximized;
att.visible = self.visible;
att.transparent = self.transparent;
att.blur = self.blur;
att.decorations = self.decorations;
//att.window_icon = self.icon.clone
todo!()
/* winit::window::WindowAttributes {
inner_size: Some(self.inner_size.into()),
min_inner_size: self.min_inner_size.map(|v| v.into()),
max_inner_size: self.max_inner_size.map(|v| v.into()),
position: self.outer_position.clone().or(self.inner_position.clone()).map(|v| v.into()), // TODO: sync in system
resizable: self.resizeable,
enabled_buttons: self.enabled_buttons.clone(),
title: self.title.clone(),
maximized: self.maximized,
visible: self.visible, // TODO: sync in system
transparent: self.transparent, // TODO: sync in system
blur: self.blur, // TODO: sync in system
decorations: self.decorations,
window_icon: self.icon.clone(),
preferred_theme: self.theme,
resize_increments: self.resize_increments.map(|v| v.into()),
content_protected: self.content_protected,
window_level: self.level,
active: false, // TODO
cursor: self.cursor.clone(),
fullscreen: self.fullscreen.clone(),
parent_window: todo!(),
platform_specific: todo!(),
} */
}
} }
#[derive(Default)] #[derive(Default)]
@ -445,7 +476,7 @@ fn vec2_to_logical_size_op(size: Option<Vec2>) -> Option<LogicalSize<f32>> {
/// Set the cursor grab of a window depending on the platform. /// Set the cursor grab of a window depending on the platform.
/// This will also modify the parameter `grab` to ensure it matches what the platform can support /// This will also modify the parameter `grab` to ensure it matches what the platform can support
fn set_cursor_grab(window: &Window, grab: &mut CursorGrabMode) -> anyhow::Result<()> { /* fn set_cursor_grab(window: &Window, grab: &mut CursorGrabMode) -> anyhow::Result<()> {
if *grab != CursorGrabMode::None { if *grab != CursorGrabMode::None {
if cfg!(unix) { if cfg!(unix) {
*grab = CursorGrabMode::Confined; *grab = CursorGrabMode::Confined;
@ -483,76 +514,17 @@ fn center_mouse(window: &Window, options: &WindowOptions) {
}; };
window.set_cursor_position(middle).unwrap(); window.set_cursor_position(middle).unwrap();
} }
} } */
fn window_updater_system(world: &mut World) -> anyhow::Result<()> { /// A system that syncs Winit Windows with [`WindowOptions`] components.
/* if let (Some(window), Some(opts)) = ( pub fn window_sync_system(world: &mut World) -> anyhow::Result<()> {
world.try_get_resource::<Arc<Window>>(), for (entity, mut opts, mut last_window, windows) in world.filtered_view_iter::<(Entities, &mut WindowOptions, &mut LastWindow, ResMut<WinitWindows>), Changed<WindowOptions>>() {
world.try_get_resource::<Ct<WindowOptions>>(),
) { */
let tick = world.tick();
for (entity, mut opts, window_tick, windows) in world.view_iter::<(Entities, &mut WindowOptions, TickOf<WindowOptions>, ResMut<WinitWindows>)>() {
let window = windows.get_entity_window(entity) let window = windows.get_entity_window(entity)
.expect("entity's window is missing"); .expect("entity's window is missing");
if window_tick == tick {
if opts.focused {
window.focus_window();
}
window.set_content_protected(opts.content_protected);
set_cursor_grab(&window, &mut opts.cursor_grab)?;
match window.set_cursor_hittest(opts.cursor_hittest) {
Ok(()) => {}
Err(ExternalError::NotSupported(_)) => { /* ignore */ }
Err(e) => {
error!("OS error when setting cursor hittest: {:?}", e);
}
}
window.set_cursor(opts.cursor.clone()); // TODO: Handle unsupported platforms
window.set_cursor_visible(opts.cursor_visible); // TODO: Handle unsupported platforms
window.set_decorations(opts.decorations); // TODO: Handle unsupported platforms
window.set_enabled_buttons(opts.enabled_buttons); // TODO: Handle unsupported platforms
window.set_fullscreen(opts.fullscreen.clone());
window.set_ime_allowed(opts.ime_allowed);
window.set_ime_cursor_area(opts.ime_cursor_area.position, opts.ime_cursor_area.size);
window.request_inner_size(opts.inner_size);
if opts.max_inner_size.is_some() {
window.set_max_inner_size(opts.max_inner_size);
}
if opts.min_inner_size.is_some() {
window.set_min_inner_size(opts.min_inner_size);
}
window.set_maximized(opts.maximized);
window.set_minimized(opts.minimized);
window.set_resizable(opts.resizeable);
window.set_resize_increments(opts.resize_increments);
window.set_theme(opts.theme);
window.set_title(&opts.title);
window.set_window_icon(opts.icon.clone());
window.set_window_level(opts.level);
center_mouse(&window, &opts);
} else {
if let Some(event_queue) = world.try_get_resource_mut::<EventQueue>() {
if let Some(events) = event_queue.read_events::<InputEvent>() {
for ev in events {
match ev {
InputEvent::CursorEntered { .. } => {
opts.cursor_inside_window = true;
}
InputEvent::CursorLeft { .. } => {
opts.cursor_inside_window = false;
}
_ => {}
}
}
}
}
// update the stored state of the window to match the actual window todo!()
opts.focused = window.has_focus();
center_mouse(&window, &opts);
}
} }
Ok(()) Ok(())
@ -563,6 +535,6 @@ impl Plugin for WindowPlugin {
let window_options = WindowOptions::default(); let window_options = WindowOptions::default();
app.world.add_resource(Ct::new(window_options)); app.world.add_resource(Ct::new(window_options));
app.with_system("window_updater", window_updater_system, &[]); app.with_system("window_sync", window_sync_system, &[]);
} }
} }