feat: add window management (list, minimize-all, focus, maximize)
This commit is contained in:
parent
c9643c8543
commit
9f06d84f28
7 changed files with 277 additions and 1 deletions
130
crates/client/src/windows_mgmt.rs
Normal file
130
crates/client/src/windows_mgmt.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
use helios_common::protocol::WindowInfo;
|
||||
|
||||
// ── Windows implementation ──────────────────────────────────────────────────
|
||||
|
||||
#[cfg(windows)]
|
||||
mod win_impl {
|
||||
use super::*;
|
||||
use std::sync::Mutex;
|
||||
use windows::Win32::Foundation::{BOOL, HWND, LPARAM};
|
||||
use windows::Win32::UI::WindowsAndMessaging::{
|
||||
BringWindowToTop, EnumWindows, GetWindowTextW, IsWindowVisible, SetForegroundWindow,
|
||||
ShowWindow, SW_MAXIMIZE, SW_MINIMIZE, SHOW_WINDOW_CMD,
|
||||
};
|
||||
|
||||
// Collect HWNDs via EnumWindows callback
|
||||
unsafe extern "system" fn enum_callback(hwnd: HWND, lparam: LPARAM) -> BOOL {
|
||||
let list = &mut *(lparam.0 as *mut Vec<HWND>);
|
||||
list.push(hwnd);
|
||||
BOOL(1)
|
||||
}
|
||||
|
||||
fn get_all_hwnds() -> Vec<HWND> {
|
||||
let mut list: Vec<HWND> = Vec::new();
|
||||
unsafe {
|
||||
let _ = EnumWindows(
|
||||
Some(enum_callback),
|
||||
LPARAM(&mut list as *mut Vec<HWND> as isize),
|
||||
);
|
||||
}
|
||||
list
|
||||
}
|
||||
|
||||
fn hwnd_title(hwnd: HWND) -> String {
|
||||
let mut buf = [0u16; 512];
|
||||
let len = unsafe { GetWindowTextW(hwnd, &mut buf) };
|
||||
String::from_utf16_lossy(&buf[..len as usize])
|
||||
}
|
||||
|
||||
pub fn list_windows() -> Result<Vec<WindowInfo>, String> {
|
||||
let hwnds = get_all_hwnds();
|
||||
let mut windows = Vec::new();
|
||||
for hwnd in hwnds {
|
||||
let visible = unsafe { IsWindowVisible(hwnd).as_bool() };
|
||||
let title = hwnd_title(hwnd);
|
||||
if title.is_empty() {
|
||||
continue;
|
||||
}
|
||||
windows.push(WindowInfo {
|
||||
id: hwnd.0 as u64,
|
||||
title,
|
||||
visible,
|
||||
});
|
||||
}
|
||||
Ok(windows)
|
||||
}
|
||||
|
||||
pub fn minimize_all() -> Result<(), String> {
|
||||
let hwnds = get_all_hwnds();
|
||||
for hwnd in hwnds {
|
||||
let visible = unsafe { IsWindowVisible(hwnd).as_bool() };
|
||||
let title = hwnd_title(hwnd);
|
||||
if visible && !title.is_empty() {
|
||||
unsafe {
|
||||
let _ = ShowWindow(hwnd, SW_MINIMIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn focus_window(window_id: u64) -> Result<(), String> {
|
||||
let hwnd = HWND(window_id as isize);
|
||||
unsafe {
|
||||
BringWindowToTop(hwnd).map_err(|e| format!("BringWindowToTop failed: {e}"))?;
|
||||
SetForegroundWindow(hwnd);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn maximize_and_focus(window_id: u64) -> Result<(), String> {
|
||||
let hwnd = HWND(window_id as isize);
|
||||
unsafe {
|
||||
ShowWindow(hwnd, SW_MAXIMIZE);
|
||||
BringWindowToTop(hwnd).map_err(|e| format!("BringWindowToTop failed: {e}"))?;
|
||||
SetForegroundWindow(hwnd);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// ── Non-Windows stubs ───────────────────────────────────────────────────────
|
||||
|
||||
#[cfg(not(windows))]
|
||||
mod win_impl {
|
||||
use super::*;
|
||||
|
||||
pub fn list_windows() -> Result<Vec<WindowInfo>, String> {
|
||||
Err("Window management is only supported on Windows".to_string())
|
||||
}
|
||||
|
||||
pub fn minimize_all() -> Result<(), String> {
|
||||
Err("Window management is only supported on Windows".to_string())
|
||||
}
|
||||
|
||||
pub fn focus_window(_window_id: u64) -> Result<(), String> {
|
||||
Err("Window management is only supported on Windows".to_string())
|
||||
}
|
||||
|
||||
pub fn maximize_and_focus(_window_id: u64) -> Result<(), String> {
|
||||
Err("Window management is only supported on Windows".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// ── Public API ──────────────────────────────────────────────────────────────
|
||||
|
||||
pub fn list_windows() -> Result<Vec<WindowInfo>, String> {
|
||||
win_impl::list_windows()
|
||||
}
|
||||
|
||||
pub fn minimize_all() -> Result<(), String> {
|
||||
win_impl::minimize_all()
|
||||
}
|
||||
|
||||
pub fn focus_window(window_id: u64) -> Result<(), String> {
|
||||
win_impl::focus_window(window_id)
|
||||
}
|
||||
|
||||
pub fn maximize_and_focus(window_id: u64) -> Result<(), String> {
|
||||
win_impl::maximize_and_focus(window_id)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue