libobs_window_helper/
lib.rs

1//! # OBS Window Helper
2//! This crate provides necessary information about windows that could be used
3//! so they can be captured with the `window_capture` or `game_capture` source in OBS.
4//! <br> The function you probably want to use is `get_all_windows` which returns a list of `WindowInfo` structs.
5
6#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
7
8#[cfg(not(target_pointer_width = "64"))]
9compile_error!("compilation is only allowed for 64-bit targets");
10
11mod error;
12pub use error::WindowHelperError;
13
14#[cfg_attr(coverage_nightly, coverage(off))]
15#[cfg(windows)]
16mod game;
17#[cfg_attr(coverage_nightly, coverage(off))]
18#[cfg(windows)]
19mod monitor;
20#[cfg(windows)]
21mod util;
22#[cfg_attr(coverage_nightly, coverage(off))]
23#[cfg(windows)]
24mod window;
25
26#[cfg(windows)]
27pub use util::*;
28#[cfg(test)]
29#[cfg(windows)]
30mod test;
31
32#[cfg(windows)]
33pub use game::*;
34#[cfg(windows)]
35pub use helper::*;
36#[cfg(windows)]
37use win_iterator::{first_window, next_window};
38#[cfg(windows)]
39use windows::Win32::{Foundation::HWND, System::Console::GetConsoleWindow};
40
41/// Retrieves information about all windows based on the specified search mode and game check flag.
42///
43/// # Arguments
44///
45/// * `mode` - The search mode to use for window enumeration.
46/// * `check_game` - A flag indicating wether a `game_capture` or a `window_capture` is used
47///
48/// # Returns
49///
50/// A `Result` containing a vector of `WindowInfo` structs representing the retrieved window information, or a `WindowHelperError` if an error occurs.
51#[cfg(windows)]
52pub fn get_all_windows(mode: WindowSearchMode) -> Result<Vec<WindowInfo>, WindowHelperError> {
53    let mut use_find_window_ex = false;
54
55    let mut parent = None as Option<HWND>;
56    let window = unsafe { first_window(mode, &mut parent, &mut use_find_window_ex)? };
57    let mut window = Some(window);
58
59    let curr = unsafe { GetConsoleWindow() };
60
61    let mut out = Vec::new();
62    while window.is_some_and(|e| !e.is_invalid()) {
63        let w = window.unwrap();
64        if curr != w {
65            let res = get_window_info(w);
66            if let Ok(info) = res {
67                out.push(info);
68            } else {
69                //eprintln!("Error: {:?}", res.err().unwrap());
70            }
71        }
72
73        unsafe {
74            window = next_window(window, mode, &mut parent, use_find_window_ex)?;
75        }
76    }
77
78    Ok(out)
79}
80
81#[cfg(windows)]
82const OBS_PIPE_NAME: &str = "CaptureHook_Pipe";
83
84#[cfg(windows)]
85pub fn is_window_in_use_by_other_instance(window_pid: u32) -> std::io::Result<bool> {
86    #[cfg(not(windows))]
87    return false;
88
89    let pipe_name = format!("{}{}", OBS_PIPE_NAME, window_pid);
90    let paths = std::fs::read_dir(r"\\.\pipe\")?;
91
92    for path in paths {
93        let path = path?;
94        let name = path.file_name();
95        let name = name.to_string_lossy();
96
97        if name == pipe_name {
98            return Ok(true);
99        }
100    }
101
102    Ok(false)
103}