On Windows, avoid panic in video_modes()

This commit is contained in:
Fredrik Fornwall 2023-12-06 17:47:33 +01:00 committed by GitHub
parent 73718c9f2f
commit b863283c38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -230,37 +230,45 @@ impl MonitorHandle {
// EnumDisplaySettingsExW can return duplicate values (or some of the // EnumDisplaySettingsExW can return duplicate values (or some of the
// fields are probably changing, but we aren't looking at those fields // fields are probably changing, but we aren't looking at those fields
// anyway), so we're using a BTreeSet deduplicate // anyway), so we're using a BTreeSet deduplicate
let mut modes = BTreeSet::new(); let mut modes = BTreeSet::<RootVideoMode>::new();
let mut i = 0; let mod_map = |mode: RootVideoMode| mode.video_mode;
loop { let monitor_info = match get_monitor_info(self.0) {
unsafe { Ok(monitor_info) => monitor_info,
let monitor_info = get_monitor_info(self.0).unwrap(); Err(error) => {
let device_name = monitor_info.szDevice.as_ptr(); log::warn!("Error from get_monitor_info: {error}");
let mut mode: DEVMODEW = mem::zeroed(); return modes.into_iter().map(mod_map);
mode.dmSize = mem::size_of_val(&mode) as u16;
if EnumDisplaySettingsExW(device_name, i, &mut mode, 0) == false.into() {
break;
}
i += 1;
const REQUIRED_FIELDS: u32 =
DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
assert!(has_flag(mode.dmFields, REQUIRED_FIELDS));
// Use Ord impl of RootVideoMode
modes.insert(RootVideoMode {
video_mode: VideoMode {
size: (mode.dmPelsWidth, mode.dmPelsHeight),
bit_depth: mode.dmBitsPerPel as u16,
refresh_rate_millihertz: mode.dmDisplayFrequency * 1000,
monitor: self.clone(),
native_video_mode: Box::new(mode),
},
});
} }
};
let device_name = monitor_info.szDevice.as_ptr();
let mut i = 0;
loop {
let mut mode: DEVMODEW = unsafe { mem::zeroed() };
mode.dmSize = mem::size_of_val(&mode) as u16;
if unsafe { EnumDisplaySettingsExW(device_name, i, &mut mode, 0) } == false.into() {
break;
}
const REQUIRED_FIELDS: u32 =
DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
assert!(has_flag(mode.dmFields, REQUIRED_FIELDS));
// Use Ord impl of RootVideoMode
modes.insert(RootVideoMode {
video_mode: VideoMode {
size: (mode.dmPelsWidth, mode.dmPelsHeight),
bit_depth: mode.dmBitsPerPel as u16,
refresh_rate_millihertz: mode.dmDisplayFrequency * 1000,
monitor: self.clone(),
native_video_mode: Box::new(mode),
},
});
i += 1;
} }
modes.into_iter().map(|mode| mode.video_mode) modes.into_iter().map(mod_map)
} }
} }