Avoid unwraps in winit fullscreen handling code (#11735)

# Objective

- Get rid of unwraps in winit fullscreen handling code, which are the
source of some crashes.
- Fix #11275

## Solution

- Replace the unwraps with warnings. Ignore the fullscreen request, do
nothing instead.
This commit is contained in:
Friz64 2024-02-10 21:17:04 +01:00 committed by GitHub
parent b6945e5332
commit d939c4402d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 198 additions and 181 deletions

View File

@ -7,7 +7,9 @@ use bevy_ecs::{
system::{NonSendMut, Query, SystemParamItem}, system::{NonSendMut, Query, SystemParamItem},
}; };
use bevy_utils::tracing::{error, info, warn}; use bevy_utils::tracing::{error, info, warn};
use bevy_window::{RawHandleWrapper, Window, WindowClosed, WindowCreated, WindowResized}; use bevy_window::{
RawHandleWrapper, Window, WindowClosed, WindowCreated, WindowMode, WindowResized,
};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use winit::{ use winit::{
@ -119,35 +121,46 @@ pub(crate) fn changed_windows(
mut window_resized: EventWriter<WindowResized>, mut window_resized: EventWriter<WindowResized>,
) { ) {
for (entity, mut window, mut cache) in &mut changed_windows { for (entity, mut window, mut cache) in &mut changed_windows {
if let Some(winit_window) = winit_windows.get_window(entity) { let Some(winit_window) = winit_windows.get_window(entity) else {
continue;
};
if window.title != cache.window.title { if window.title != cache.window.title {
winit_window.set_title(window.title.as_str()); winit_window.set_title(window.title.as_str());
} }
if window.mode != cache.window.mode { if window.mode != cache.window.mode {
let new_mode = match window.mode { let new_mode = match window.mode {
bevy_window::WindowMode::BorderlessFullscreen => { WindowMode::BorderlessFullscreen => {
Some(winit::window::Fullscreen::Borderless(None)) Some(Some(winit::window::Fullscreen::Borderless(None)))
} }
bevy_window::WindowMode::Fullscreen => { mode @ (WindowMode::Fullscreen | WindowMode::SizedFullscreen) => {
Some(winit::window::Fullscreen::Exclusive(get_best_videomode( if let Some(current_monitor) = winit_window.current_monitor() {
&winit_window.current_monitor().unwrap(), let videomode = match mode {
))) WindowMode::Fullscreen => get_best_videomode(&current_monitor),
} WindowMode::SizedFullscreen => get_fitting_videomode(
bevy_window::WindowMode::SizedFullscreen => { &current_monitor,
Some(winit::window::Fullscreen::Exclusive(get_fitting_videomode(
&winit_window.current_monitor().unwrap(),
window.width() as u32, window.width() as u32,
window.height() as u32, window.height() as u32,
))) ),
} _ => unreachable!(),
bevy_window::WindowMode::Windowed => None,
}; };
Some(Some(winit::window::Fullscreen::Exclusive(videomode)))
} else {
warn!("Could not determine current monitor, ignoring exclusive fullscreen request for window {:?}", window.title);
None
}
}
WindowMode::Windowed => Some(None),
};
if let Some(new_mode) = new_mode {
if winit_window.fullscreen() != new_mode { if winit_window.fullscreen() != new_mode {
winit_window.set_fullscreen(new_mode); winit_window.set_fullscreen(new_mode);
} }
} }
}
if window.resolution != cache.window.resolution { if window.resolution != cache.window.resolution {
let physical_size = PhysicalSize::new( let physical_size = PhysicalSize::new(
window.resolution.physical_width(), window.resolution.physical_width(),
@ -261,9 +274,7 @@ pub(crate) fn changed_windows(
// Currently unsupported changes // Currently unsupported changes
if window.transparent != cache.window.transparent { if window.transparent != cache.window.transparent {
window.transparent = cache.window.transparent; window.transparent = cache.window.transparent;
warn!( warn!("Winit does not currently support updating transparency after window creation.");
"Winit does not currently support updating transparency after window creation."
);
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@ -295,5 +306,4 @@ pub(crate) fn changed_windows(
cache.window = window.clone(); cache.window = window.clone();
} }
}
} }

View File

@ -55,18 +55,25 @@ impl WinitWindows {
WindowMode::BorderlessFullscreen => winit_window_builder.with_fullscreen(Some( WindowMode::BorderlessFullscreen => winit_window_builder.with_fullscreen(Some(
winit::window::Fullscreen::Borderless(event_loop.primary_monitor()), winit::window::Fullscreen::Borderless(event_loop.primary_monitor()),
)), )),
WindowMode::Fullscreen => { mode @ (WindowMode::Fullscreen | WindowMode::SizedFullscreen) => {
winit_window_builder.with_fullscreen(Some(winit::window::Fullscreen::Exclusive( if let Some(primary_monitor) = event_loop.primary_monitor() {
get_best_videomode(&event_loop.primary_monitor().unwrap()), let videomode = match mode {
))) WindowMode::Fullscreen => get_best_videomode(&primary_monitor),
} WindowMode::SizedFullscreen => get_fitting_videomode(
WindowMode::SizedFullscreen => winit_window_builder.with_fullscreen(Some( &primary_monitor,
winit::window::Fullscreen::Exclusive(get_fitting_videomode(
&event_loop.primary_monitor().unwrap(),
window.width() as u32, window.width() as u32,
window.height() as u32, window.height() as u32,
)), ),
)), _ => unreachable!(),
};
winit_window_builder
.with_fullscreen(Some(winit::window::Fullscreen::Exclusive(videomode)))
} else {
warn!("Could not determine primary monitor, ignoring exclusive fullscreen request for window {:?}", window.title);
winit_window_builder
}
}
WindowMode::Windowed => { WindowMode::Windowed => {
if let Some(position) = winit_window_position( if let Some(position) = winit_window_position(
&window.position, &window.position,