display_profile_lib/
lib.rs1#![cfg_attr(all(doc, not(doctest)), feature(doc_cfg))]
2#![expect(clippy::missing_errors_doc)]
3#![doc = include_str!("../README.md")]
4
5pub use error::Error;
6pub use get_profile::get_profile;
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9pub use set_profile::{SetProfileAction, set_profile};
10use windows_ccd::windows::DISPLAYCONFIG_2DREGION;
11
12mod error;
13mod get_profile;
14mod set_profile;
15mod util;
16
17const VIRTUAL_MODE_AWARE: bool = true;
18
19pub type Result<T, E = Error> = std::result::Result<T, E>;
20
21macro_rules! define_windows_mapped_struct {
22 (
23 $name:ident => $win_name:ident in $($win_path:ident)::+ {
24 $(
25 $field:ident => $win_field:ident : $field_type:ty ,
26 )*
27 }
28 ) => {
29 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
30 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31 pub struct $name {
32 $(
33 pub $field: $field_type,
34 )*
35 }
36
37 impl From<$($win_path::)+ $win_name> for $name {
38 fn from(value: $($win_path::)+ $win_name) -> Self {
39 $name {
40 $(
41 $field: value.$win_field,
42 )*
43 }
44 }
45 }
46
47 impl From<$name> for $($win_path::)+ $win_name {
48 fn from(value: $name) -> Self {
49 $($win_path::)+ $win_name {
50 $(
51 $win_field: value.$field,
52 )*
53 }
54 }
55 }
56 };
57}
58
59macro_rules! define_windows_mapped_enum {
60 (
61 $name:ident => $win_type:ident in $($win_path:ident)::+ {
62 $(
63 $( #[ $attribute:meta ] )?
64 $variant:ident => $win_val:ident ,
65 )*
66 }
67 ) => {
68 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
69 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
70 pub enum $name {
71 $(
72 $( #[ $attribute ] )?
73 $variant,
74 )*
75 }
76
77 impl From<$($win_path::)+ $win_type> for $name {
78 fn from(value: $($win_path::)+ $win_type) -> Self {
79 use $($win_path)::+ as WinPath;
80 match value {
81 $( WinPath::$win_val => $name::$variant, )*
82 _ => unreachable!(),
83 }
84 }
85 }
86
87 impl From<$name> for $($win_path::)+ $win_type {
88 fn from(value: $name) -> Self {
89 use $($win_path)::+ as WinPath;
90 match value {
91 $( $name::$variant => WinPath::$win_val, )*
92 }
93 }
94 }
95 };
96}
97
98pub type Profile = Vec<Monitor>;
99
100#[derive(Debug, Clone, PartialEq, Eq)]
101#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
102pub struct Monitor {
103 pub friendly_device_name: String,
104 pub source_device_name: String,
105 pub device_path: String,
106 pub dimensions: Dimensions,
107 pub pixel_format: PixelFormat,
108 pub position: Position,
109 pub rotation: Rotation,
110 pub scaling: Scaling,
111 pub refresh_rate: Rational,
112 pub path_source_size: Position,
113 pub desktop_image_region: Rect,
114 pub desktop_image_clip: Rect,
115}
116
117#[derive(Debug, Clone, PartialEq, Eq)]
118#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
119pub struct Dimensions {
120 pub width: u32,
121 pub height: u32,
122}
123impl From<Dimensions> for DISPLAYCONFIG_2DREGION {
124 fn from(value: Dimensions) -> Self {
125 DISPLAYCONFIG_2DREGION {
126 cx: value.width,
127 cy: value.height,
128 }
129 }
130}
131
132define_windows_mapped_enum!(
133 PixelFormat => DISPLAYCONFIG_PIXELFORMAT in windows_ccd::windows {
134 #[cfg_attr(feature = "serde", serde(rename = "8BPP"))]
135 BitsPerPixel8 => DISPLAYCONFIG_PIXELFORMAT_8BPP,
136 #[cfg_attr(feature = "serde", serde(rename = "16BPP"))]
137 BitsPerPixel16 => DISPLAYCONFIG_PIXELFORMAT_16BPP,
138 #[cfg_attr(feature = "serde", serde(rename = "24BPP"))]
139 BitsPerPixel24 => DISPLAYCONFIG_PIXELFORMAT_24BPP,
140 #[cfg_attr(feature = "serde", serde(rename = "32BPP"))]
141 BitsPerPixel32 => DISPLAYCONFIG_PIXELFORMAT_32BPP,
142 NONGDI => DISPLAYCONFIG_PIXELFORMAT_NONGDI,
143 }
144);
145
146define_windows_mapped_struct!(
147 Position => POINTL in windows_ccd::windows {
148 x => x: i32,
149 y => y: i32,
150 }
151);
152
153define_windows_mapped_enum!(
154 Rotation => DISPLAYCONFIG_ROTATION in windows_ccd::windows {
155 IDENTITY => DISPLAYCONFIG_ROTATION_IDENTITY,
156 ROTATE90 => DISPLAYCONFIG_ROTATION_ROTATE90,
157 ROTATE180 => DISPLAYCONFIG_ROTATION_ROTATE180,
158 ROTATE270 => DISPLAYCONFIG_ROTATION_ROTATE270,
159 }
160);
161
162define_windows_mapped_enum!(
163 Scaling => DISPLAYCONFIG_SCALING in windows_ccd::windows {
164 IDENTITY => DISPLAYCONFIG_SCALING_IDENTITY,
165 CENTERED => DISPLAYCONFIG_SCALING_CENTERED,
166 STRETCHED => DISPLAYCONFIG_SCALING_STRETCHED,
167 ASPECTRATIOCENTEREDMAX => DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX,
168 CUSTOM => DISPLAYCONFIG_SCALING_CUSTOM,
169 PREFERRED => DISPLAYCONFIG_SCALING_PREFERRED,
170 }
171);
172
173define_windows_mapped_struct!(
174 Rational => DISPLAYCONFIG_RATIONAL in windows_ccd::windows {
175 numerator => Numerator: u32,
176 denominator => Denominator: u32,
177 }
178);
179
180define_windows_mapped_struct!(
181 Rect => RECTL in windows_ccd::windows {
182 left => left: i32,
183 top => top: i32,
184 right => right: i32,
185 bottom => bottom: i32,
186 }
187);