Add exclusive fullscreen

This commit is contained in:
reo 2025-12-15 22:16:41 +03:00
parent 2a255affe4
commit b50a60755a
3 changed files with 69 additions and 2 deletions

View file

@ -58,6 +58,7 @@ impl System for DisplaySettings {
for mode in [ for mode in [
WindowMode::Windowed, WindowMode::Windowed,
WindowMode::BorderlessFullscreen, WindowMode::BorderlessFullscreen,
WindowMode::ExclusiveFullscreen,
] { ] {
ui.selectable_value( ui.selectable_value(
&mut state.selected_fullscreen_mode, &mut state.selected_fullscreen_mode,
@ -88,5 +89,6 @@ fn window_mode_label(mode: WindowMode) -> &'static str {
match mode { match mode {
WindowMode::Windowed => "Windowed", WindowMode::Windowed => "Windowed",
WindowMode::BorderlessFullscreen => "Borderless Fullscreen", WindowMode::BorderlessFullscreen => "Borderless Fullscreen",
WindowMode::ExclusiveFullscreen => "Exclusive Fullscreen",
} }
} }

View file

@ -8,5 +8,5 @@ winit = "0.30.12"
raidillon_core = { path = "../core" } raidillon_core = { path = "../core" }
raidillon_assets = { path = "../asset" } raidillon_assets = { path = "../asset" }
glam = "0.30.5" glam = "0.30.5"
serde = "1.0.228" serde = { version = "1.0.228", features = ["derive"] }
toml = "0.9.8" toml = "0.9.8"

View file

@ -1,4 +1,4 @@
use winit::dpi::LogicalSize; use winit::monitor::{MonitorHandle, VideoModeHandle};
use winit::window::{Fullscreen, Window}; use winit::window::{Fullscreen, Window};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::error::Error; use std::error::Error;
@ -19,6 +19,7 @@ pub fn default_config_path() -> PathBuf {
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum WindowMode { pub enum WindowMode {
BorderlessFullscreen, BorderlessFullscreen,
ExclusiveFullscreen,
#[default] #[default]
Windowed, Windowed,
} }
@ -93,9 +94,73 @@ impl DisplaySettings {
let monitor = window.current_monitor().or_else(|| window.primary_monitor()); let monitor = window.current_monitor().or_else(|| window.primary_monitor());
window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); window.set_fullscreen(Some(Fullscreen::Borderless(monitor)));
} }
WindowMode::ExclusiveFullscreen => {
let monitor = window.current_monitor().or_else(|| window.primary_monitor());
match monitor {
Some(monitor) => {
if let Some(video_mode) = pick_best_video_mode(&monitor) {
window.set_fullscreen(Some(Fullscreen::Exclusive(video_mode)));
} else {
// fallback to borderless
window.set_fullscreen(Some(Fullscreen::Borderless(Some(monitor))));
}
}
None => {
// no monitor info, fallback to windowed
window.set_fullscreen(None);
}
}
}
WindowMode::Windowed => { WindowMode::Windowed => {
window.set_fullscreen(None); window.set_fullscreen(None);
}, },
} }
} }
} }
fn pick_best_video_mode(monitor: &MonitorHandle) -> Option<VideoModeHandle> {
let target_size = monitor.size();
let mut best_native: Option<VideoModeHandle> = None;
let mut best_any: Option<VideoModeHandle> = None;
for mode in monitor.video_modes() {
if mode.size() == target_size {
let replace = match best_native.as_ref() {
None => true,
Some(best) => {
(mode.refresh_rate_millihertz(), mode.bit_depth())
> (best.refresh_rate_millihertz(), best.bit_depth())
}
};
if replace {
best_native = Some(mode.clone());
}
}
let replace = match best_any.as_ref() {
None => true,
Some(best) => is_better_video_mode(&mode, best),
};
if replace {
best_any = Some(mode);
}
}
best_native.or(best_any)
}
fn is_better_video_mode(a: &VideoModeHandle, b: &VideoModeHandle) -> bool {
let a_size = a.size();
let b_size = b.size();
let a_area = u64::from(a_size.width) * u64::from(a_size.height);
let b_area = u64::from(b_size.width) * u64::from(b_size.height);
match a_area.cmp(&b_area) {
std::cmp::Ordering::Greater => true,
std::cmp::Ordering::Less => false,
std::cmp::Ordering::Equal => {
(a.refresh_rate_millihertz(), a.bit_depth()) > (b.refresh_rate_millihertz(), b.bit_depth())
}
}
}