1 | use sctk::reexports::client::protocol::wl_output::WlOutput; |
2 | use sctk::reexports::client::Proxy; |
3 | |
4 | use sctk::output::OutputData; |
5 | |
6 | use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; |
7 | use crate::platform_impl::platform::VideoModeHandle as PlatformVideoModeHandle; |
8 | |
9 | use super::event_loop::ActiveEventLoop; |
10 | |
11 | impl ActiveEventLoop { |
12 | #[inline ] |
13 | pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> { |
14 | self.state.borrow().output_state.outputs().map(MonitorHandle::new) |
15 | } |
16 | |
17 | #[inline ] |
18 | pub fn primary_monitor(&self) -> Option<MonitorHandle> { |
19 | // There's no primary monitor on Wayland. |
20 | None |
21 | } |
22 | } |
23 | |
24 | #[derive (Clone, Debug)] |
25 | pub struct MonitorHandle { |
26 | pub(crate) proxy: WlOutput, |
27 | } |
28 | |
29 | impl MonitorHandle { |
30 | #[inline ] |
31 | pub(crate) fn new(proxy: WlOutput) -> Self { |
32 | Self { proxy } |
33 | } |
34 | |
35 | #[inline ] |
36 | pub fn name(&self) -> Option<String> { |
37 | let output_data = self.proxy.data::<OutputData>().unwrap(); |
38 | output_data.with_output_info(|info| info.name.clone()) |
39 | } |
40 | |
41 | #[inline ] |
42 | pub fn native_identifier(&self) -> u32 { |
43 | let output_data = self.proxy.data::<OutputData>().unwrap(); |
44 | output_data.with_output_info(|info| info.id) |
45 | } |
46 | |
47 | #[inline ] |
48 | pub fn size(&self) -> PhysicalSize<u32> { |
49 | let output_data = self.proxy.data::<OutputData>().unwrap(); |
50 | let dimensions = output_data.with_output_info(|info| { |
51 | info.modes.iter().find_map(|mode| mode.current.then_some(mode.dimensions)) |
52 | }); |
53 | |
54 | match dimensions { |
55 | Some((width, height)) => (width as u32, height as u32), |
56 | _ => (0, 0), |
57 | } |
58 | .into() |
59 | } |
60 | |
61 | #[inline ] |
62 | pub fn position(&self) -> PhysicalPosition<i32> { |
63 | let output_data = self.proxy.data::<OutputData>().unwrap(); |
64 | output_data.with_output_info(|info| { |
65 | info.logical_position.map_or_else( |
66 | || { |
67 | LogicalPosition::<i32>::from(info.location) |
68 | .to_physical(info.scale_factor as f64) |
69 | }, |
70 | |logical_position| { |
71 | LogicalPosition::<i32>::from(logical_position) |
72 | .to_physical(info.scale_factor as f64) |
73 | }, |
74 | ) |
75 | }) |
76 | } |
77 | |
78 | #[inline ] |
79 | pub fn refresh_rate_millihertz(&self) -> Option<u32> { |
80 | let output_data = self.proxy.data::<OutputData>().unwrap(); |
81 | output_data.with_output_info(|info| { |
82 | info.modes.iter().find_map(|mode| mode.current.then_some(mode.refresh_rate as u32)) |
83 | }) |
84 | } |
85 | |
86 | #[inline ] |
87 | pub fn scale_factor(&self) -> i32 { |
88 | let output_data = self.proxy.data::<OutputData>().unwrap(); |
89 | output_data.scale_factor() |
90 | } |
91 | |
92 | #[inline ] |
93 | pub fn video_modes(&self) -> impl Iterator<Item = PlatformVideoModeHandle> { |
94 | let output_data = self.proxy.data::<OutputData>().unwrap(); |
95 | let modes = output_data.with_output_info(|info| info.modes.clone()); |
96 | |
97 | let monitor = self.clone(); |
98 | |
99 | modes.into_iter().map(move |mode| { |
100 | PlatformVideoModeHandle::Wayland(VideoModeHandle { |
101 | size: (mode.dimensions.0 as u32, mode.dimensions.1 as u32).into(), |
102 | refresh_rate_millihertz: mode.refresh_rate as u32, |
103 | bit_depth: 32, |
104 | monitor: monitor.clone(), |
105 | }) |
106 | }) |
107 | } |
108 | } |
109 | |
110 | impl PartialEq for MonitorHandle { |
111 | fn eq(&self, other: &Self) -> bool { |
112 | self.native_identifier() == other.native_identifier() |
113 | } |
114 | } |
115 | |
116 | impl Eq for MonitorHandle {} |
117 | |
118 | impl PartialOrd for MonitorHandle { |
119 | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
120 | Some(self.cmp(other)) |
121 | } |
122 | } |
123 | |
124 | impl Ord for MonitorHandle { |
125 | fn cmp(&self, other: &Self) -> std::cmp::Ordering { |
126 | self.native_identifier().cmp(&other.native_identifier()) |
127 | } |
128 | } |
129 | |
130 | impl std::hash::Hash for MonitorHandle { |
131 | fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
132 | self.native_identifier().hash(state); |
133 | } |
134 | } |
135 | |
136 | #[derive (Debug, Clone, PartialEq, Eq, Hash)] |
137 | pub struct VideoModeHandle { |
138 | pub(crate) size: PhysicalSize<u32>, |
139 | pub(crate) bit_depth: u16, |
140 | pub(crate) refresh_rate_millihertz: u32, |
141 | pub(crate) monitor: MonitorHandle, |
142 | } |
143 | |
144 | impl VideoModeHandle { |
145 | #[inline ] |
146 | pub fn size(&self) -> PhysicalSize<u32> { |
147 | self.size |
148 | } |
149 | |
150 | #[inline ] |
151 | pub fn bit_depth(&self) -> u16 { |
152 | self.bit_depth |
153 | } |
154 | |
155 | #[inline ] |
156 | pub fn refresh_rate_millihertz(&self) -> u32 { |
157 | self.refresh_rate_millihertz |
158 | } |
159 | |
160 | pub fn monitor(&self) -> MonitorHandle { |
161 | self.monitor.clone() |
162 | } |
163 | } |
164 | |