Change the requested cursor grab depending on platform support, fix setting window size

This commit is contained in:
SeanOMik 2023-09-19 00:16:01 -04:00
parent fef032351e
commit db84f03b57
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
1 changed files with 43 additions and 41 deletions

View File

@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use glam::Vec2; use glam::{Vec2, IVec2};
use tracing::{warn, error}; use tracing::{warn, error, debug};
use winit::{window::{Window, Fullscreen}, dpi::{LogicalPosition, LogicalSize}, error::ExternalError}; use winit::{window::{Window, Fullscreen}, dpi::{LogicalPosition, LogicalSize}, error::ExternalError};
pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel}; pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel};
@ -99,19 +99,19 @@ pub struct WindowOptions {
/// Platform-specific: /// Platform-specific:
/// * iOS / Android: Unsupported. /// * iOS / Android: Unsupported.
/// * Web: Sets the size of the canvas element. /// * Web: Sets the size of the canvas element.
pub inner_size: Vec2, pub inner_size: IVec2,
/// Sets a maximum dimension size for the window. /// Sets a maximum dimension size for the window.
/// ///
/// Platform-specific: /// Platform-specific:
/// * iOS / Android / Web / Orbital: Unsupported. /// * iOS / Android / Web / Orbital: Unsupported.
pub max_inner_size: Option<Vec2>, pub max_inner_size: Option<IVec2>,
/// Sets a minimum dimension size for the window. /// Sets a minimum dimension size for the window.
/// ///
/// Platform-specific: /// Platform-specific:
/// * iOS / Android / Web / Orbital: Unsupported. /// * iOS / Android / Web / Orbital: Unsupported.
pub min_inner_size: Option<Vec2>, pub min_inner_size: Option<IVec2>,
/// Sets the window to maximized or back. /// Sets the window to maximized or back.
/// ///
@ -188,7 +188,7 @@ impl Default for WindowOptions {
mode: WindowMode::Windowed, mode: WindowMode::Windowed,
ime_allowed: false, ime_allowed: false,
ime_position: Default::default(), ime_position: Default::default(),
inner_size: Default::default(), inner_size: glam::i32::IVec2::new(800, 600),
max_inner_size: None, max_inner_size: None,
min_inner_size: None, min_inner_size: None,
maximized: false, maximized: false,
@ -209,20 +209,48 @@ pub struct WindowPlugin {
create_options: WindowOptions, create_options: WindowOptions,
} }
/// Convert an Vec2 to a LogicalPosition<f32>
fn vec2_to_logical_pos(pos: Vec2) -> LogicalPosition<f32> { fn vec2_to_logical_pos(pos: Vec2) -> LogicalPosition<f32> {
LogicalPosition { x: pos.x, y: pos.y } LogicalPosition { x: pos.x, y: pos.y }
} }
fn vec2_to_logical_size(size: Vec2) -> LogicalSize<f32> { /// Convert an IVec2 to a LogicalSize<i32>
fn ivec2_to_logical_size(size: IVec2) -> LogicalSize<i32> {
LogicalSize { width: size.x, height: size.y } LogicalSize { width: size.x, height: size.y }
} }
fn vec2_to_logical_pos_op(pos: Option<Vec2>) -> Option<LogicalPosition<f32>> { /// Convert an Option<IVec2> to an Option<LogicalSize<i32>>
pos.map(|pos| vec2_to_logical_pos(pos)) fn ivec2_to_logical_size_op(size: Option<IVec2>) -> Option<LogicalSize<i32>> {
size.map(|size| ivec2_to_logical_size(size))
} }
/// Convert an Option<Vec2> to an Option<LogicalSize<f32>>
fn vec2_to_logical_size_op(size: Option<Vec2>) -> Option<LogicalSize<f32>> { fn vec2_to_logical_size_op(size: Option<Vec2>) -> Option<LogicalSize<f32>> {
size.map(|size| vec2_to_logical_size(size)) size.map(|size| LogicalSize { width: size.x, height: size.y } )
}
/// 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
fn set_cursor_grab(window: &Window, grab: &mut CursorGrabMode) -> anyhow::Result<()> {
if *grab != CursorGrabMode::None {
if cfg!(unix) {
*grab = CursorGrabMode::Confined;
// TODO: Find a way to see if winit is using x11 or wayland. wayland supports Locked
} else if cfg!(wasm) {
*grab = CursorGrabMode::Locked;
} else if cfg!(windows) {
*grab = CursorGrabMode::Confined; // NOTE: May support Locked later
} else if cfg!(target_os = "macos") {
*grab = CursorGrabMode::Locked; // NOTE: May support Confined later
} else if cfg!(any(target_os = "android", target_os = "ios", target_os = "orbital")) {
warn!("CursorGrabMode is not supported on Android, IOS, or Oribital, skipping");
return Ok(())
}
}
window.set_cursor_grab(*grab)?;
Ok(())
} }
fn window_updater_system(world: &mut edict::World) -> anyhow::Result<()> { fn window_updater_system(world: &mut edict::World) -> anyhow::Result<()> {
@ -230,36 +258,10 @@ fn window_updater_system(world: &mut edict::World) -> anyhow::Result<()> {
// if the options changed, update the window // if the options changed, update the window
if opts.changed() { if opts.changed() {
window.set_content_protected(opts.content_protected); window.set_content_protected(opts.content_protected);
match opts.cursor_grab { set_cursor_grab(&window, &mut opts.cursor_grab)?;
CursorGrabMode::Confined => {
match window.set_cursor_grab(opts.cursor_grab)
.or_else(|_e| window.set_cursor_grab(CursorGrabMode::Locked)) {
Ok(()) => {},
Err(ExternalError::NotSupported(_)) => {
warn!("Setting CursorGrab is not supported on this platform");
},
Err(e) => {
error!("OS error when setting CursorGrab: {:?}", e);
}
}
},
_ => {
match window.set_cursor_grab(opts.cursor_grab) {
Ok(()) => {},
Err(ExternalError::NotSupported(_)) => {
warn!("Setting CursorGrab is not supported on this platform");
},
Err(e) => {
error!("OS error when setting CursorGrab: {:?}", e);
}
}
}
}
match window.set_cursor_hittest(opts.cursor_hittest) { match window.set_cursor_hittest(opts.cursor_hittest) {
Ok(()) => {}, Ok(()) => {},
Err(ExternalError::NotSupported(_)) => { Err(ExternalError::NotSupported(_)) => { /* ignore */ },
warn!("Setting cursor hittest is not supported on this platform");
},
Err(e) => { Err(e) => {
error!("OS error when setting cursor hittest: {:?}", e); error!("OS error when setting cursor hittest: {:?}", e);
} }
@ -284,12 +286,12 @@ fn window_updater_system(world: &mut edict::World) -> anyhow::Result<()> {
window.set_ime_allowed(opts.ime_allowed); window.set_ime_allowed(opts.ime_allowed);
window.set_ime_position(vec2_to_logical_pos(opts.ime_position)); window.set_ime_position(vec2_to_logical_pos(opts.ime_position));
//window.set_inner_size(vec2_to_logical_size(opts.inner_size)); // TODO window.set_inner_size(ivec2_to_logical_size(opts.inner_size));
if opts.max_inner_size.is_some() { if opts.max_inner_size.is_some() {
window.set_max_inner_size(vec2_to_logical_size_op(opts.max_inner_size)); window.set_max_inner_size(ivec2_to_logical_size_op(opts.max_inner_size));
} }
if opts.min_inner_size.is_some() { if opts.min_inner_size.is_some() {
window.set_min_inner_size(vec2_to_logical_size_op(opts.min_inner_size)); window.set_min_inner_size(ivec2_to_logical_size_op(opts.min_inner_size));
} }
//window.set_maximized(opts.maximized); // TODO //window.set_maximized(opts.maximized); // TODO
//window.set_minimized(opts.minimized); // TODO //window.set_minimized(opts.minimized); // TODO