Sign in Sign up
kretrod/lodestone Public
Branches
master
54 lines (45 loc) · 1.9 KB Raw
//! "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};