Merge branch 'imbris/current-monitor-fix' into 'master'

Eliminate panics when .current_monitor() returns None

Closes #1199 and #811

See merge request veloren/veloren!2463
This commit is contained in:
Marcel 2021-06-16 07:34:52 +00:00
commit 0729e487c0
2 changed files with 50 additions and 28 deletions

View File

@ -164,9 +164,8 @@ impl<'a> Widget for Video<'a> {
.window .window
.window() .window()
.current_monitor() .current_monitor()
.unwrap() .map(|monitor| monitor.video_modes().collect())
.video_modes() .unwrap_or_default();
.collect();
State { State {
ids: Ids::new(id_gen), ids: Ids::new(id_gen),

View File

@ -1130,7 +1130,10 @@ impl Window {
pub fn is_fullscreen(&self) -> bool { self.fullscreen.enabled } pub fn is_fullscreen(&self) -> bool { self.fullscreen.enabled }
pub fn select_video_mode_rec( /// Select a video mode that fits the specified requirements
/// Returns None if a matching video mode doesn't exist or if
/// the current monitor can't be retrieved
fn select_video_mode_rec(
&self, &self,
resolution: [u16; 2], resolution: [u16; 2],
bit_depth: Option<u16>, bit_depth: Option<u16>,
@ -1142,15 +1145,16 @@ impl Window {
// if a previous iteration of this method filtered the available video modes for // if a previous iteration of this method filtered the available video modes for
// the correct resolution already, load that value, otherwise filter it // the correct resolution already, load that value, otherwise filter it
// in this iteration // in this iteration
let correct_res = correct_res.unwrap_or_else(|| { let correct_res = match correct_res {
self.window Some(correct_res) => correct_res,
.current_monitor() None => self
.unwrap() .window
.current_monitor()?
.video_modes() .video_modes()
.filter(|mode| mode.size().width == resolution[0] as u32) .filter(|mode| mode.size().width == resolution[0] as u32)
.filter(|mode| mode.size().height == resolution[1] as u32) .filter(|mode| mode.size().height == resolution[1] as u32)
.collect() .collect(),
}); };
match bit_depth { match bit_depth {
// A bit depth is given // A bit depth is given
@ -1270,12 +1274,12 @@ impl Window {
} }
} }
pub fn select_video_mode( fn select_video_mode(
&self, &self,
resolution: [u16; 2], resolution: [u16; 2],
bit_depth: Option<u16>, bit_depth: Option<u16>,
refresh_rate: Option<u16>, refresh_rate: Option<u16>,
) -> VideoMode { ) -> Option<VideoMode> {
// (resolution, bit depth, refresh rate) represents a video mode // (resolution, bit depth, refresh rate) represents a video mode
// spec: as specified // spec: as specified
// max: maximum value available // max: maximum value available
@ -1285,24 +1289,34 @@ impl Window {
// (spec, spec, max), (spec, max, spec) // (spec, spec, max), (spec, max, spec)
// (spec, max, max) // (spec, max, max)
// (max, max, max) // (max, max, max)
self.select_video_mode_rec(resolution, bit_depth, refresh_rate, None, None, None) match self.select_video_mode_rec(resolution, bit_depth, refresh_rate, None, None, None) {
// if there is no video mode with the specified resolution, fall back to the video mode with max resolution, bit depth and refresh rate Some(mode) => Some(mode),
.unwrap_or_else(|| { // if there is no video mode with the specified resolution,
// fall back to the video mode with max resolution, bit depth and refresh rate
None => {
warn!( warn!(
"Resolution specified in settings is incompatible with the monitor. Choosing \ "Resolution specified in settings is incompatible with the monitor. Choosing \
highest resolution possible instead." highest resolution possible instead."
); );
if let Some(monitor) = self.window.current_monitor() {
let mode = monitor
.video_modes()
// Prefer bit depth over refresh rate
.sorted_by_key(|mode| mode.refresh_rate())
.sorted_by_key(|mode| mode.bit_depth())
.max_by_key(|mode| mode.size().width);
self if mode.is_none() {
.window warn!("Failed to select video mode, no video modes available!!")
.current_monitor().unwrap() }
.video_modes()
// Prefer bit depth over refresh rate mode
.sorted_by_key(|mode| mode.refresh_rate()) } else {
.sorted_by_key(|mode| mode.bit_depth()) warn!("Failed to select video mode, can't get the current monitor!");
.max_by_key(|mode| mode.size().width) None
.expect("No video modes available!!") }
}) },
}
} }
pub fn set_fullscreen_mode(&mut self, fullscreen: FullScreenSettings) { pub fn set_fullscreen_mode(&mut self, fullscreen: FullScreenSettings) {
@ -1310,14 +1324,23 @@ impl Window {
self.fullscreen = fullscreen; self.fullscreen = fullscreen;
window.set_fullscreen(fullscreen.enabled.then(|| match fullscreen.mode { window.set_fullscreen(fullscreen.enabled.then(|| match fullscreen.mode {
FullscreenMode::Exclusive => { FullscreenMode::Exclusive => {
winit::window::Fullscreen::Exclusive(self.select_video_mode( if let Some(video_mode) = self.select_video_mode(
fullscreen.resolution, fullscreen.resolution,
fullscreen.bit_depth, fullscreen.bit_depth,
fullscreen.refresh_rate, fullscreen.refresh_rate,
)) ) {
winit::window::Fullscreen::Exclusive(video_mode)
} else {
warn!(
"Failed to select a video mode for exclusive fullscreen. Falling back to \
borderless fullscreen."
);
winit::window::Fullscreen::Borderless(None)
}
}, },
FullscreenMode::Borderless => { FullscreenMode::Borderless => {
winit::window::Fullscreen::Borderless(window.current_monitor()) // None here will fullscreen on the current monitor
winit::window::Fullscreen::Borderless(None)
}, },
})); }));
} }