Files
agentic-mobile-control/driver/_w3c_actions.py
T

70 lines
2.1 KiB
Python

from __future__ import annotations
from typing import Any
POINTER_ID = "finger1"
def _pointer(*actions: dict[str, Any]) -> list[dict[str, Any]]:
return [
{
"type": "pointer",
"id": POINTER_ID,
"parameters": {"pointerType": "touch"},
"actions": list(actions),
}
]
def build_swipe_actions(
waypoints: list[tuple[float, float]], total_duration_ms: int
) -> list[dict[str, Any]]:
"""W3C actions moving through ``waypoints`` in one continuous touch."""
if len(waypoints) < 2:
raise ValueError("swipe path requires at least two waypoints")
segments = len(waypoints) - 1
per_segment = max(1, total_duration_ms // segments)
sx, sy = waypoints[0]
actions: list[dict[str, Any]] = [
{"type": "pointerMove", "duration": 0, "x": int(sx), "y": int(sy)},
{"type": "pointerDown", "button": 0},
]
for point in waypoints[1:]:
actions.append(
{
"type": "pointerMove",
"duration": per_segment,
"x": int(point[0]),
"y": int(point[1]),
}
)
ex, ey = waypoints[-1]
actions.append(
{"type": "pointerUp", "button": 0, "x": int(ex), "y": int(ey)}
)
return _pointer(*actions)
def build_double_tap_actions(
x: float, y: float, interval_ms: int
) -> list[dict[str, Any]]:
actions = [
{"type": "pointerMove", "duration": 0, "x": int(x), "y": int(y)},
{"type": "pointerDown", "button": 0},
{"type": "pointerUp", "button": 0},
{"type": "pause", "duration": max(1, interval_ms)},
{"type": "pointerDown", "button": 0},
{"type": "pointerUp", "button": 0},
]
return _pointer(*actions)
def perform_actions(client: Any, actions: list[dict[str, Any]]) -> None:
"""Send a W3C actions payload via the Appium/Selenium command seam.
Import is lazy so the pure payload builders stay importable without
selenium on the path (used by unit tests).
"""
from selenium.webdriver.remote.command import Command
client.execute(Command.W3C_ACTIONS, {"actions": actions})