From a738771c937921ba0b5b7a0266b1155fb5faca36 Mon Sep 17 00:00:00 2001 From: Wouter Standaert Date: Thu, 13 Aug 2020 10:47:40 +0200 Subject: [PATCH] Add resizable and windowmode options to window creation --- crates/bevy_window/src/window.rs | 20 ++++++ crates/bevy_winit/src/winit_windows.rs | 85 +++++++++++++++++++++++--- examples/window/multiple_windows.rs | 1 + examples/window/window_settings.rs | 4 ++ 4 files changed, 101 insertions(+), 9 deletions(-) diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index bffb0121fc..c15e6d7b5c 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -34,6 +34,20 @@ pub struct Window { pub height: u32, pub title: String, pub vsync: bool, + pub resizable: bool, + pub mode: WindowMode, +} + +/// Defines the way a window is displayed +/// The use_size option that is used in the Fullscreen variant +/// defines whether a videomode is chosen that best fits the width and height +/// in the Window structure, or if these are ignored. +/// E.g. when use_size is set to false the best video mode possible is chosen. +#[derive(Debug, Clone, Copy)] +pub enum WindowMode { + Windowed, + BorderlessFullscreen, + Fullscreen { use_size: bool }, } impl Window { @@ -44,6 +58,8 @@ impl Window { width: window_descriptor.width, title: window_descriptor.title.clone(), vsync: window_descriptor.vsync, + resizable: window_descriptor.resizable, + mode: window_descriptor.mode, } } } @@ -54,6 +70,8 @@ pub struct WindowDescriptor { pub height: u32, pub title: String, pub vsync: bool, + pub resizable: bool, + pub mode: WindowMode, } impl Default for WindowDescriptor { @@ -63,6 +81,8 @@ impl Default for WindowDescriptor { width: 1280, height: 720, vsync: true, + resizable: true, + mode: WindowMode::Windowed, } } } diff --git a/crates/bevy_winit/src/winit_windows.rs b/crates/bevy_winit/src/winit_windows.rs index ac23c50281..ee0df6f48d 100644 --- a/crates/bevy_winit/src/winit_windows.rs +++ b/crates/bevy_winit/src/winit_windows.rs @@ -1,4 +1,4 @@ -use bevy_window::{Window, WindowId}; +use bevy_window::{Window, WindowId, WindowMode}; use std::collections::HashMap; #[derive(Default)] @@ -17,18 +17,39 @@ impl WinitWindows { #[cfg(target_os = "windows")] let winit_window_builder = { use winit::platform::windows::WindowBuilderExtWindows; - winit::window::WindowBuilder::new() - .with_drag_and_drop(false) + winit::window::WindowBuilder::new().with_drag_and_drop(false) }; #[cfg(not(target_os = "windows"))] - let winit_window_builder = winit::window::WindowBuilder::new(); + let mut winit_window_builder = winit::window::WindowBuilder::new(); - let winit_window = winit_window_builder - .with_title(&window.title) - .with_inner_size(winit::dpi::PhysicalSize::new(window.width, window.height)) - .build(&event_loop) - .unwrap(); + winit_window_builder = winit_window_builder.with_title(&window.title); + + let winit_window = match window.mode { + WindowMode::BorderlessFullscreen => { + let winit_window = winit_window_builder.build(&event_loop).unwrap(); + winit_window.set_fullscreen(Some(winit::window::Fullscreen::Borderless( + winit_window.current_monitor(), + ))); + winit_window + } + WindowMode::Fullscreen { use_size } => { + let winit_window = winit_window_builder.build(&event_loop).unwrap(); + + winit_window.set_fullscreen(Some(winit::window::Fullscreen::Exclusive( + match use_size { + true => get_fitting_videomode(&winit_window.current_monitor(), &window), + false => get_best_videomode(&winit_window.current_monitor()), + }, + ))); + winit_window + } + _ => winit_window_builder + .with_inner_size(winit::dpi::PhysicalSize::new(window.width, window.height)) + .with_resizable(window.resizable) + .build(&event_loop) + .unwrap(), + }; self.window_id_to_winit.insert(window.id, winit_window.id()); self.winit_to_window_id.insert(winit_window.id(), window.id); @@ -46,3 +67,49 @@ impl WinitWindows { self.winit_to_window_id.get(&id).cloned() } } +fn get_fitting_videomode( + monitor: &winit::monitor::MonitorHandle, + window: &Window, +) -> winit::monitor::VideoMode { + let mut modes = monitor.video_modes().collect::>(); + + fn abs_diff(a: u32, b: u32) -> u32 { + if a > b { + return a - b; + } + b - a + } + + modes.sort_by(|a, b| { + use std::cmp::Ordering::*; + match abs_diff(a.size().width, window.width).cmp(&abs_diff(b.size().width, window.width)) { + Equal => { + match abs_diff(a.size().height, window.height) + .cmp(&abs_diff(b.size().height, window.height)) + { + Equal => b.refresh_rate().cmp(&a.refresh_rate()), + default => default, + } + } + default => default, + } + }); + + modes.first().unwrap().clone() +} + +fn get_best_videomode(monitor: &winit::monitor::MonitorHandle) -> winit::monitor::VideoMode { + let mut modes = monitor.video_modes().collect::>(); + modes.sort_by(|a, b| { + use std::cmp::Ordering::*; + match b.size().width.cmp(&a.size().width) { + Equal => match b.size().height.cmp(&a.size().height) { + Equal => b.refresh_rate().cmp(&a.refresh_rate()), + default => default, + }, + default => default, + } + }); + + modes.first().unwrap().clone() +} diff --git a/examples/window/multiple_windows.rs b/examples/window/multiple_windows.rs index 3f8c83bca5..aa3622a5d1 100644 --- a/examples/window/multiple_windows.rs +++ b/examples/window/multiple_windows.rs @@ -39,6 +39,7 @@ fn setup( height: 600, vsync: false, title: "second window".to_string(), + ..Default::default() }, }); diff --git a/examples/window/window_settings.rs b/examples/window/window_settings.rs index 81d48b7dfe..81c6a1c662 100644 --- a/examples/window/window_settings.rs +++ b/examples/window/window_settings.rs @@ -1,4 +1,5 @@ use bevy::prelude::*; +use bevy_window::WindowMode; /// This example illustrates how to customize the default window settings fn main() { @@ -8,6 +9,9 @@ fn main() { width: 300, height: 300, vsync: true, + resizable: false, + mode: WindowMode::Fullscreen { use_size: false }, + ..Default::default() }) .add_default_plugins() .run();