libobs_window_helper/util/
validators.rs1use std::os::raw::c_void;
2use windows::Win32::UI::WindowsAndMessaging::{
3 GetClientRect, GetWindowLongPtrW, IsIconic, IsWindowVisible, GWL_EXSTYLE, GWL_STYLE, WS_CHILD,
4 WS_EX_TOOLWINDOW,
5};
6use windows::{
7 core::Result,
8 Win32::{
9 Foundation::{HWND, RECT},
10 Graphics::Dwm::{DwmGetWindowAttribute, DWMWA_CLOAKED},
11 },
12};
13
14const INTERNAL_MICROSOFT_EXES_EXACT: &[&str] = &[
15 "startmenuexperiencehost.exe",
16 "applicationframehost.exe",
17 "peopleexperiencehost.exe",
18 "shellexperiencehost.exe",
19 "microsoft.notes.exe",
20 "systemsettings.exe",
21 "textinputhost.exe",
22 "searchapp.exe",
23 "video.ui.exe",
24 "searchui.exe",
25 "lockapp.exe",
26 "cortana.exe",
27 "gamebar.exe",
28 "tabtip.exe",
29 "time.exe",
30];
31
32const INTERNAL_MICROSOFT_EXES_PARTIAL: &[&str] = &["windowsinternal"];
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum WindowSearchMode {
36 ExcludeMinimized,
37 IncludeMinimized,
38}
39
40#[allow(clippy::upper_case_acronyms)]
41type DWORD = u32;
42
43pub(crate) fn is_window_cloaked(handle: HWND) -> bool {
44 let cloaked: DWORD = 0;
45 let res = unsafe {
46 DwmGetWindowAttribute(
47 handle,
48 DWMWA_CLOAKED,
49 cloaked as *mut c_void,
50 size_of::<DWORD>() as u32,
51 )
52 };
53
54 res.is_ok() && cloaked != 0
55}
56
57pub fn is_window_valid(handle: HWND, mode: WindowSearchMode) -> Result<bool> {
58 let is_visible = unsafe { IsWindowVisible(handle) };
59 if !is_visible.as_bool() {
60 return Ok(false);
61 }
62
63 if mode == WindowSearchMode::ExcludeMinimized {
64 let is_minimized = unsafe { IsIconic(handle).as_bool() } || is_window_cloaked(handle);
65 if is_minimized {
66 return Ok(false);
67 }
68 }
69
70 let mut rect = RECT::default();
71 let styles;
72 let ex_styles;
73
74 unsafe {
75 GetClientRect(handle, &mut rect)?;
76
77 styles = GetWindowLongPtrW(handle, GWL_STYLE) as DWORD;
79 ex_styles = GetWindowLongPtrW(handle, GWL_EXSTYLE) as DWORD;
80 }
81
82 if ex_styles & WS_EX_TOOLWINDOW.0 > 0 {
83 return Ok(false);
84 }
85 if styles & WS_CHILD.0 > 0 {
86 return Ok(false);
87 }
88
89 if mode == WindowSearchMode::ExcludeMinimized && (rect.bottom == 0 || rect.right == 0) {
90 return Ok(false);
91 }
92
93 Ok(true)
94}
95
96pub fn is_microsoft_internal_exe(exe: &str) -> bool {
97 let exact = INTERNAL_MICROSOFT_EXES_EXACT.contains(&exe);
98 let partial = INTERNAL_MICROSOFT_EXES_PARTIAL
99 .iter()
100 .any(|e| exe.contains(e));
101
102 exact || partial
103}