refactor: enforce device labels, unify screenshot, remove deprecated commands, session-id-less design
- Device labels: lowercase, no whitespace, only a-z 0-9 - _ (enforced at config time) - Session IDs removed: device label is the sole identifier - Routes changed: /sessions/:id → /devices/:label - Removed commands: click, type, find-window, wait-for-window, label, old version, server-version - Renamed: status → version (compares relay/remote.py/client commits) - Unified screenshot: takes 'screen' or a window label as argument - Windows listed with human-readable labels (same format as device labels) - Single instance enforcement via PID lock file - Removed input.rs (click/type functionality) - All docs and code in English - Protocol: Hello.label is now required (String, not Option<String>) - Client auto-migrates invalid labels on startup
This commit is contained in:
parent
5fd01a423d
commit
0b4a6de8ae
14 changed files with 736 additions and 1180 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use helios_common::protocol::WindowInfo;
|
||||
use helios_common::protocol::{sanitize_label, WindowInfo};
|
||||
|
||||
// ── Windows implementation ──────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -14,7 +14,6 @@ mod win_impl {
|
|||
keybd_event, KEYEVENTF_KEYUP, VK_MENU,
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
|
@ -38,19 +37,29 @@ mod win_impl {
|
|||
String::from_utf16_lossy(&buf[..len as usize])
|
||||
}
|
||||
|
||||
/// Generate a human-readable label from a window title.
|
||||
/// E.g. "Google Chrome" -> "google_chrome", "Discord" -> "discord"
|
||||
fn window_label(title: &str) -> String {
|
||||
sanitize_label(title)
|
||||
}
|
||||
|
||||
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);
|
||||
// Only return visible windows with a non-empty title
|
||||
if !visible || title.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let label = window_label(&title);
|
||||
if label.is_empty() {
|
||||
continue;
|
||||
}
|
||||
windows.push(WindowInfo {
|
||||
id: hwnd.0 as u64,
|
||||
title,
|
||||
label,
|
||||
visible: true,
|
||||
});
|
||||
}
|
||||
|
|
@ -71,9 +80,6 @@ mod win_impl {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Bypass Windows Focus Stealing Prevention by sending a fake Alt keypress
|
||||
/// before calling SetForegroundWindow. Without this, SetForegroundWindow
|
||||
/// silently fails when the calling thread is not in the foreground.
|
||||
unsafe fn force_foreground(hwnd: HWND) {
|
||||
keybd_event(VK_MENU.0 as u8, 0, Default::default(), 0);
|
||||
keybd_event(VK_MENU.0 as u8, 0, KEYEVENTF_KEYUP, 0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue