1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//! "Hide from screen capture".
//!
//! The menu is drawn into the game's own back buffer, so to a recorder its
//! pixels *are* the game's pixels — there is no way to exclude just the menu
//! from a capture of that window. What Windows does offer is
//! `SetWindowDisplayAffinity`, which takes the whole window out of capture:
//! recorders, screen shares and PrintScreen get black where it used to be.
//!
//! So this is honest about what it is: an all-or-nothing switch on the game
//! window, not a way to record clean footage with the menu open. On Linux there
//! is no equivalent at all, and it says so rather than pretending.
#[cfg(windows)]
mod imp {
use std::sync::atomic::{AtomicIsize, Ordering};
use windows_sys::Win32::Foundation::HWND;
use windows_sys::Win32::UI::WindowsAndMessaging::{
SetWindowDisplayAffinity, WDA_EXCLUDEFROMCAPTURE, WDA_NONE,
};
static HWND_CELL: AtomicIsize = AtomicIsize::new(0);
pub fn set_window(handle: isize) {
HWND_CELL.store(handle, Ordering::SeqCst);
}
/// Returns false when Windows refused — the API needs Windows 10 2004 or newer.
pub fn apply(hide: bool) -> bool {
let hwnd = HWND_CELL.load(Ordering::SeqCst);
if hwnd == 0 {
return false;
}
let affinity = if hide { WDA_EXCLUDEFROMCAPTURE } else { WDA_NONE };
// SAFETY: hwnd is the game's window, stored once at startup.
unsafe { SetWindowDisplayAffinity(hwnd as HWND, affinity) != 0 }
}
}
#[cfg(unix)]
mod imp {
//! Neither X11 nor Wayland has a per-window "exclude from capture" flag: a
//! compositor or screen recorder captures whatever it can composite, and
//! nothing a client asks for changes that. The switch is therefore a no-op
//! that reports failure, so the UI can show it did nothing.
pub fn set_window(_handle: isize) {}
pub fn apply(_hide: bool) -> bool {
false
}
}
pub use imp::{apply, set_window};