wutengine/windowing/
display.rs1use core::cmp::Ordering;
4use std::sync::OnceLock;
5
6use itertools::Itertools;
7use winit::event_loop::ActiveEventLoop;
8use winit::monitor::{MonitorHandle, VideoModeHandle};
9
10static DISPLAYS: OnceLock<AvailableDisplays> = OnceLock::new();
11
12#[derive(Debug, Clone)]
14pub struct AvailableDisplays {
15 displays: Vec<Display>,
16 primary: Option<usize>,
17}
18
19impl AvailableDisplays {
20 pub fn primary(&self) -> &Display {
23 self.primary
24 .map(|idx| &self.displays[idx])
25 .unwrap_or(&self.displays[0])
26 }
27
28 pub fn all(&self) -> &[Display] {
30 &self.displays
31 }
32}
33
34#[derive(Debug, Clone)]
36pub struct Display {
37 pub(super) handle: MonitorHandle,
38 pub(super) modes: Vec<VideoModeHandle>,
39 pub(super) largest_mode: VideoModeHandle,
40}
41
42impl Display {
43 pub fn name(&self) -> String {
45 self.handle.name().unwrap()
46 }
47
48 pub fn modes(&self) -> &[VideoModeHandle] {
50 &self.modes
51 }
52
53 pub fn largest_mode(&self) -> VideoModeHandle {
56 self.largest_mode.clone()
57 }
58}
59
60pub(crate) fn configure(event_loop: &ActiveEventLoop) {
64 log::trace!("Identifying monitors");
65
66 let available = event_loop.available_monitors().collect_vec();
67 let primary = event_loop.primary_monitor();
68
69 let mut displays = AvailableDisplays {
70 displays: available.into_iter().map(map_display).collect(),
71 primary: None,
72 };
73
74 if let Some(primary) = primary {
75 for (i, display) in displays.displays.iter().enumerate() {
76 if display.handle == primary {
77 displays.primary = Some(i);
78 break;
79 }
80 }
81 }
82
83 DISPLAYS
84 .set(displays)
85 .expect("Displays already configured!");
86}
87
88fn map_display(handle: MonitorHandle) -> Display {
89 let modes = handle.video_modes().collect_vec();
90
91 let mut largest_mode: Option<&VideoModeHandle> = None;
92
93 for mode in &modes {
94 if let Some(cur_largest) = largest_mode {
95 if better_mode(mode, cur_largest) {
96 largest_mode = Some(mode);
97 }
98 } else {
99 largest_mode = Some(mode);
100 }
101 }
102
103 Display {
104 handle,
105 largest_mode: largest_mode
106 .expect("Could not determine best video mode!")
107 .clone(),
108 modes,
109 }
110}
111
112fn better_mode(mode: &VideoModeHandle, compared_to: &VideoModeHandle) -> bool {
115 let resolution_cmp = mode.size().cmp(&compared_to.size());
116 let refresh_cmp = mode
117 .refresh_rate_millihertz()
118 .cmp(&compared_to.refresh_rate_millihertz());
119
120 match resolution_cmp {
121 Ordering::Less => false,
122 Ordering::Equal => match refresh_cmp {
123 Ordering::Less => false,
124 Ordering::Equal => false,
125 Ordering::Greater => true,
126 },
127 Ordering::Greater => true,
128 }
129}
130
131pub fn available_displays() -> AvailableDisplays {
133 DISPLAYS
134 .get()
135 .expect("Displays not yet initialized!")
136 .clone()
137}