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