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