winvd/
desktop.rs

1use crate::interfaces::ComIn;
2
3use super::comobjects::*;
4use super::{interfaces::IVirtualDesktop, *};
5use std::{convert::TryFrom, fmt::Debug};
6use windows::{core::GUID, Win32::Foundation::HWND};
7
8/// You can construct Desktop instance with `get_desktop(5)` by index or GUID.
9#[derive(Copy, Clone, Debug)]
10pub struct Desktop(DesktopInternal);
11
12impl Eq for Desktop {}
13
14impl PartialEq for Desktop {
15    fn eq(&self, other: &Self) -> bool {
16        let a = self.0;
17        let b = other.0;
18        match (&a, &b) {
19            (DesktopInternal::Index(a), DesktopInternal::Index(b)) => a == b,
20            (DesktopInternal::Guid(a), DesktopInternal::Guid(b)) => a == b,
21            (DesktopInternal::IndexGuid(a, b), DesktopInternal::IndexGuid(c, d)) => {
22                a == c && b == d
23            }
24            (DesktopInternal::Index(a), DesktopInternal::IndexGuid(b, _)) => a == b,
25            (DesktopInternal::IndexGuid(a, _), DesktopInternal::Index(b)) => a == b,
26            (DesktopInternal::Guid(a), DesktopInternal::IndexGuid(_, b)) => a == b,
27            (DesktopInternal::IndexGuid(_, a), DesktopInternal::Guid(b)) => a == b,
28            _ => with_com_objects(move |f| Ok(f.get_desktop_id(&a)? == f.get_desktop_id(&b)?))
29                .unwrap_or(false),
30        }
31    }
32}
33
34// Impl from u32 to DesktopTest
35impl From<u32> for Desktop {
36    fn from(index: u32) -> Self {
37        Desktop(DesktopInternal::Index(index))
38    }
39}
40
41// Impl from i32 to DesktopTest
42impl From<i32> for Desktop {
43    fn from(index: i32) -> Self {
44        Desktop(DesktopInternal::Index(index as u32))
45    }
46}
47
48// Impl from GUID to DesktopTest
49impl From<GUID> for Desktop {
50    fn from(guid: GUID) -> Self {
51        Desktop(DesktopInternal::Guid(guid))
52    }
53}
54
55// Impl from &GUID to DesktopTest
56impl From<&GUID> for Desktop {
57    fn from(guid: &GUID) -> Self {
58        Desktop(DesktopInternal::Guid(*guid))
59    }
60}
61
62impl From<DesktopInternal> for Desktop {
63    fn from(desktop: DesktopInternal) -> Self {
64        Desktop(desktop)
65    }
66}
67
68impl From<Desktop> for DesktopInternal {
69    fn from(desktop: Desktop) -> Self {
70        desktop.0
71    }
72}
73
74impl TryFrom<IVirtualDesktop> for Desktop {
75    type Error = Error;
76
77    fn try_from(desktop: IVirtualDesktop) -> Result<Self> {
78        Ok(Desktop(DesktopInternal::try_from(&desktop)?))
79    }
80}
81impl<'a> TryFrom<&'a ComIn<'a, IVirtualDesktop>> for Desktop {
82    type Error = Error;
83
84    fn try_from(desktop: &'a ComIn<'a, IVirtualDesktop>) -> Result<Self> {
85        Ok(Desktop(DesktopInternal::try_from(desktop)?))
86    }
87}
88impl<'a> TryFrom<ComIn<'a, IVirtualDesktop>> for Desktop {
89    type Error = Error;
90
91    fn try_from(desktop: ComIn<'a, IVirtualDesktop>) -> Result<Self> {
92        Ok(Desktop(DesktopInternal::try_from(&desktop)?))
93    }
94}
95impl Desktop {
96    /// Get the GUID of the desktop
97    pub fn get_id(&self) -> Result<GUID> {
98        let internal = self.0.clone();
99        with_com_objects(move |o| o.get_desktop_id(&internal))
100    }
101
102    pub fn get_index(&self) -> Result<u32> {
103        let internal = self.0.clone();
104        with_com_objects(move |o| o.get_desktop_index(&internal))
105    }
106
107    /// Get desktop name
108    pub fn get_name(&self) -> Result<String> {
109        let internal = self.0.clone();
110        with_com_objects(move |o| o.get_desktop_name(&internal))
111    }
112
113    /// Set desktop name
114    pub fn set_name(&self, name: &str) -> Result<()> {
115        let internal = self.0.clone();
116        let name_ = name.to_owned();
117        with_com_objects(move |o| o.set_desktop_name(&internal, &name_))
118    }
119
120    /// Get desktop wallpaper path
121    pub fn get_wallpaper(&self) -> Result<String> {
122        let internal = self.0.clone();
123        with_com_objects(move |o| o.get_desktop_wallpaper(&internal))
124    }
125
126    /// Set desktop wallpaper path
127    pub fn set_wallpaper(&self, path: &str) -> Result<()> {
128        let internal = self.0.clone();
129        let path_ = path.to_owned();
130        with_com_objects(move |o| o.set_desktop_wallpaper(&internal, &path_))
131    }
132}
133
134/// Get desktop by index or GUID
135///
136/// # Examples
137/// * Get first desktop by index `get_desktop(0)`
138/// * Get second desktop by index `get_desktop(1)`
139/// * Get desktop by GUID `get_desktop(GUID(0, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0]))`
140///
141/// Note: This function does not check if the desktop exists.
142pub fn get_desktop<T>(desktop: T) -> Desktop
143where
144    T: Into<Desktop>,
145{
146    desktop.into()
147}
148
149/// Switch desktop by index or GUID
150pub fn switch_desktop<T>(desktop: T) -> Result<()>
151where
152    T: Into<Desktop>,
153    T: Send + 'static + Copy,
154{
155    with_com_objects(move |o| o.switch_desktop(&desktop.into().into()))
156}
157
158/// Remove desktop by index or GUID
159pub fn remove_desktop<T>(desktop: T, fallback_desktop: T) -> Result<()>
160where
161    T: Into<Desktop>,
162    T: Send + 'static + Copy,
163{
164    with_com_objects(move |o| {
165        o.remove_desktop(&desktop.into().into(), &fallback_desktop.into().into())
166    })
167}
168
169/// Is window on desktop by index or GUID
170pub fn is_window_on_desktop<T>(desktop: T, hwnd: HWND) -> Result<bool>
171where
172    T: Into<Desktop>,
173    T: Send + 'static + Copy,
174{
175    with_com_objects(move |o| o.is_window_on_desktop(&hwnd, &desktop.into().into()))
176}
177
178/// Move window to desktop by index or GUID
179pub fn move_window_to_desktop<T>(desktop: T, hwnd: &HWND) -> Result<()>
180where
181    T: Into<Desktop>,
182    T: Send + 'static + Copy,
183{
184    let hwnd = hwnd.clone();
185    with_com_objects(move |o| o.move_window_to_desktop(&hwnd, &desktop.into().into()))
186}
187
188/// Create desktop
189pub fn create_desktop() -> Result<Desktop> {
190    with_com_objects(|o| o.create_desktop().map(Desktop))
191}
192
193/// Get current desktop
194pub fn get_current_desktop() -> Result<Desktop> {
195    with_com_objects(|o| o.get_current_desktop().map(Desktop))
196}
197
198/// Get all desktops
199pub fn get_desktops() -> Result<Vec<Desktop>> {
200    with_com_objects(|o| Ok(o.get_desktops()?.into_iter().map(Desktop).collect()))
201}
202
203/// Get desktop by window
204pub fn get_desktop_by_window(hwnd: HWND) -> Result<Desktop> {
205    with_com_objects(move |o| o.get_desktop_by_window(&hwnd).map(Desktop))
206}
207
208/// Get desktop count
209pub fn get_desktop_count() -> Result<u32> {
210    with_com_objects(|o| o.get_desktop_count())
211}
212
213pub fn is_window_on_current_desktop(hwnd: HWND) -> Result<bool> {
214    with_com_objects(move |o| o.is_window_on_current_desktop(&hwnd))
215}
216
217/// Is window pinned?
218pub fn is_pinned_window(hwnd: HWND) -> Result<bool> {
219    with_com_objects(move |o| o.is_pinned_window(&hwnd))
220}
221
222/// Pin window
223pub fn pin_window(hwnd: HWND) -> Result<()> {
224    with_com_objects(move |o| o.pin_window(&hwnd))
225}
226
227/// Unpin window
228pub fn unpin_window(hwnd: HWND) -> Result<()> {
229    with_com_objects(move |o| o.unpin_window(&hwnd))
230}
231
232/// Is pinned app
233pub fn is_pinned_app(hwnd: HWND) -> Result<bool> {
234    with_com_objects(move |o| o.is_pinned_app(&hwnd))
235}
236
237/// Pin app
238pub fn pin_app(hwnd: HWND) -> Result<()> {
239    with_com_objects(move |o| o.pin_app(&hwnd))
240}
241
242/// Unpin app
243pub fn unpin_app(hwnd: HWND) -> Result<()> {
244    with_com_objects(move |o| o.unpin_app(&hwnd))
245}