windows-troll 0.1.0

Modular Windows prank library
//! Shared helpers for working with the Windows desktop.
//!
//! Window enumeration is used by several troll modules (e.g. `window_hider`,
//! `window_wobbler`), so it lives here instead of being duplicated in each
//! module.

use windows::core::BOOL;
use windows::Win32::Foundation::{HWND, LPARAM};
use windows::Win32::UI::WindowsAndMessaging::{
    EnumWindows, GetWindowTextW, IsIconic, IsWindowVisible,
};

/// Information about a single top-level window on the desktop.
#[derive(Debug, Clone)]
pub struct WindowInfo {
    handle: HWND,
    title: String,
}

impl WindowInfo {
    /// The native window handle.
    pub fn handle(&self) -> HWND {
        self.handle
    }

    /// The window's title text.
    pub fn title(&self) -> &str {
        &self.title
    }
}

struct EnumContext {
    windows: Vec<WindowInfo>,
}

extern "system" fn enum_windows_proc(window: HWND, param: LPARAM) -> BOOL {
    unsafe {
        if IsWindowVisible(window).as_bool() && !IsIconic(window).as_bool() {
            let mut text = [0u16; 512];
            let len = GetWindowTextW(window, &mut text);
            if len > 0 {
                let context = &mut *(param.0 as *mut EnumContext);
                context.windows.push(WindowInfo {
                    handle: window,
                    title: String::from_utf16_lossy(&text[..len as usize]),
                });
            }
        }
    }
    BOOL(1)
}

/// Returns all visible, non-minimized top-level windows that have a title.
pub fn list_windows() -> Vec<WindowInfo> {
    let mut context = EnumContext {
        windows: Vec::new(),
    };
    unsafe {
        let param = LPARAM(&mut context as *mut _ as isize);
        let _ = EnumWindows(Some(enum_windows_proc), param);
    }
    context.windows
}