2026-07-16 01:19:47 +08:00
|
|
|
|
"""L1 Backend 抽象层基类:定义 BackendProtocol 与 WindowGeometry。
|
|
|
|
|
|
|
|
|
|
|
|
所有具体后端(xdotool / OpenCV / CDP)均实现 BackendProtocol,
|
|
|
|
|
|
上层 Actions / Flow 通过 Protocol 解耦具体实现,便于切换或回滚。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
|
class WindowGeometry:
|
|
|
|
|
|
"""窗口几何信息(绝对坐标 + 宽高)。
|
|
|
|
|
|
|
|
|
|
|
|
所有字段默认值 0,避免构造时必填字段顺序问题。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
x: int = 0
|
|
|
|
|
|
y: int = 0
|
|
|
|
|
|
width: int = 0
|
|
|
|
|
|
height: int = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BackendProtocol(ABC):
|
|
|
|
|
|
"""UI 自动化后端协议(L1 抽象)。
|
|
|
|
|
|
|
|
|
|
|
|
子类必须实现所有 abstract 方法;capabilities 属性提供该后端
|
|
|
|
|
|
支持的能力集合(如 click / type / key / screenshot / window)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
|
async def click(self, x: int, y: int) -> None:
|
|
|
|
|
|
"""在绝对坐标 (x, y) 处左键单击。"""
|
|
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
|
async def type_text(self, text: str) -> None:
|
|
|
|
|
|
"""输入文本(不解析修饰键组合,原样输入)。"""
|
|
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
|
async def key_press(self, key: str, repeat: int = 1) -> None:
|
|
|
|
|
|
"""按键,支持 repeat 重复。"""
|
|
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
|
async def screenshot(self) -> bytes:
|
|
|
|
|
|
"""截图并返回 PNG 字节流(不落盘)。"""
|
|
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
|
async def get_window_geometry(self, window_title: str) -> WindowGeometry:
|
|
|
|
|
|
"""按窗口标题查找窗口并返回几何信息。"""
|
|
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
|
async def activate_window(self, window_title: str) -> None:
|
|
|
|
|
|
"""激活指定窗口(使其获得焦点)。"""
|
|
|
|
|
|
|
2026-07-18 04:51:54 +08:00
|
|
|
|
async def is_window_active(self, window_title: str) -> bool:
|
|
|
|
|
|
"""校验指定标题的窗口是否是当前活动窗口(拥有焦点)。
|
|
|
|
|
|
|
|
|
|
|
|
默认实现返回 True(信任 activate_window 的结果)。
|
|
|
|
|
|
XdotoolBackend 覆盖为真正调用 getactivewindow 对比。
|
|
|
|
|
|
用于纯坐标模式下 _verify_session_still_open 校验窗口焦点,
|
|
|
|
|
|
避免 cache_hit 分支命中已失焦的会话。
|
|
|
|
|
|
"""
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
2026-07-16 01:19:47 +08:00
|
|
|
|
@property
|
|
|
|
|
|
def capabilities(self) -> set[str]:
|
|
|
|
|
|
"""返回后端支持的能力集合。子类可覆盖。"""
|
|
|
|
|
|
return {"click", "type", "key", "screenshot", "window"}
|