rdesktop_core/
window_extras.rs1use crate::config::{WindowConfig, WindowKind};
14use tao::window::{Icon, Window};
15
16pub fn window_icon(config: &WindowConfig) -> Option<Icon> {
18 let icon = config.icon.as_ref()?;
19 match Icon::from_rgba(icon.rgba.clone(), icon.width, icon.height) {
20 Ok(icon) => Some(icon),
21 Err(error) => {
22 tracing::warn!(%error, "invalid rdesktop window icon; continuing without icon");
23 None
24 }
25 }
26}
27
28pub fn apply_window_attributes(window: &Window, config: &WindowConfig) {
30 let click_through = config.click_through || config.kind == WindowKind::Wallpaper;
31 let is_wallpaper = config.kind == WindowKind::Wallpaper;
32
33 #[cfg(target_os = "windows")]
34 windows::apply(window, click_through, is_wallpaper);
35 #[cfg(target_os = "macos")]
36 macos::apply(window, click_through, is_wallpaper);
37 #[cfg(not(any(target_os = "windows", target_os = "macos")))]
38 {
39 let _ = (window, click_through, is_wallpaper);
40 tracing::debug!("click-through / wallpaper layer not implemented on this platform");
41 }
42}
43
44#[cfg(target_os = "windows")]
45mod windows {
46 use std::ptr;
47
48 use tao::platform::windows::WindowExtWindows;
49 use tao::window::Window;
50 use windows_sys::Win32::Foundation::{BOOL, HWND, LPARAM};
51 use windows_sys::Win32::UI::WindowsAndMessaging::{
52 EnumWindows, FindWindowExW, FindWindowW, GetWindowLongPtrW, SendMessageTimeoutW, SetParent,
53 SetWindowLongPtrW, SetWindowPos, GWL_EXSTYLE, HWND_BOTTOM, SMTO_ABORTIFHUNG,
54 SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, WS_EX_LAYERED, WS_EX_TRANSPARENT,
55 };
56
57 pub(crate) fn apply(window: &Window, click_through: bool, is_wallpaper: bool) {
58 let hwnd = window.hwnd() as HWND;
59 if hwnd == 0 {
60 return;
61 }
62 unsafe {
63 if click_through {
64 let ex = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
65 let new_ex = ex | (WS_EX_LAYERED as isize) | (WS_EX_TRANSPARENT as isize);
66 SetWindowLongPtrW(hwnd, GWL_EXSTYLE, new_ex);
67 }
68 if is_wallpaper {
69 if let Some(worker) = find_desktop_workerw() {
70 SetParent(hwnd, worker);
71 }
72 SetWindowPos(
73 hwnd,
74 HWND_BOTTOM,
75 0,
76 0,
77 0,
78 0,
79 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE,
80 );
81 }
82 }
83 }
84
85 unsafe fn find_desktop_workerw() -> Option<HWND> {
89 let progman = FindWindowW(windows_sys::w!("Progman"), ptr::null::<u16>());
90 if progman == 0 {
91 return None;
92 }
93 SendMessageTimeoutW(
95 progman,
96 0x52C,
97 0,
98 0,
99 SMTO_ABORTIFHUNG,
100 1000,
101 ptr::null_mut::<usize>(),
102 );
103 let mut worker: HWND = 0;
104 EnumWindows(Some(enum_proc), &mut worker as *mut _ as LPARAM);
105 if worker == 0 {
106 None
107 } else {
108 Some(worker)
109 }
110 }
111
112 extern "system" fn enum_proc(hwnd: HWND, lparam: LPARAM) -> BOOL {
113 unsafe {
114 let defview = FindWindowExW(
115 hwnd,
116 0,
117 windows_sys::w!("SHELLDLL_DefView"),
118 ptr::null::<u16>(),
119 );
120 if defview != 0 {
121 let pworker = &mut *(lparam as *mut HWND);
122 *pworker = FindWindowExW(0, hwnd, windows_sys::w!("WorkerW"), ptr::null::<u16>());
123 }
124 windows_sys::Win32::Foundation::TRUE
125 }
126 }
127}
128
129#[cfg(target_os = "macos")]
130mod macos {
131 use core_graphics::window::{CGWindowLevelForKey, CGWindowLevelKey};
132 use objc::{msg_send, runtime::Object};
133 use tao::platform::macos::WindowExtMacOS;
134 use tao::window::Window;
135
136 pub(crate) fn apply(window: &Window, click_through: bool, is_wallpaper: bool) {
137 let ns_win = window.ns_window() as *mut Object;
138 if ns_win.is_null() {
139 return;
140 }
141 unsafe {
142 let _: () = msg_send![ns_win, setIgnoresMouseEvents: click_through || is_wallpaper];
143 if is_wallpaper {
144 let level: i64 =
145 CGWindowLevelForKey(CGWindowLevelKey::kCGDesktopWindowLevelKey) as i64;
146 let _: () = msg_send![ns_win, setLevel: level];
147 let _: () = msg_send![ns_win, orderBack: ns_win];
148 }
149 }
150 }
151}