- 在hdc/input.py中实现多行文本支持,使用HarmonyOS keyEvent 2054处理换行 - 移除type_text函数的x/y坐标参数,简化接口 - 将多行文本处理逻辑从handler.py移至hdc/input.py,统一处理 - 优化parse_action函数,支持Type动作的text参数提取 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
150 lines
4.8 KiB
Python
150 lines
4.8 KiB
Python
"""Input utilities for HarmonyOS device text input."""
|
|
|
|
import base64
|
|
import subprocess
|
|
from typing import Optional
|
|
|
|
from phone_agent.hdc.connection import _run_hdc_command
|
|
|
|
|
|
def type_text(text: str, device_id: str | None = None) -> None:
|
|
"""
|
|
Type text into the currently focused input field.
|
|
|
|
Args:
|
|
text: The text to type. Supports multi-line text with newline characters.
|
|
device_id: Optional HDC device ID for multi-device setups.
|
|
|
|
Note:
|
|
HarmonyOS uses: hdc shell uitest uiInput text "文本内容"
|
|
This command works without coordinates when input field is focused.
|
|
For multi-line text, the function splits by newlines and sends ENTER keyEvents.
|
|
ENTER key code in HarmonyOS: 2054
|
|
Recommendation: Click on the input field first to focus it, then use this function.
|
|
"""
|
|
hdc_prefix = _get_hdc_prefix(device_id)
|
|
|
|
# Handle multi-line text by splitting on newlines
|
|
if '\n' in text:
|
|
lines = text.split('\n')
|
|
for i, line in enumerate(lines):
|
|
if line: # Only process non-empty lines
|
|
# Escape special characters for shell
|
|
escaped_line = line.replace('"', '\\"').replace("$", "\\$")
|
|
|
|
_run_hdc_command(
|
|
hdc_prefix + ["shell", "uitest", "uiInput", "text", escaped_line],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
# Send ENTER key event after each line except the last one
|
|
if i < len(lines) - 1:
|
|
try:
|
|
_run_hdc_command(
|
|
hdc_prefix + ["shell", "uitest", "uiInput", "keyEvent", "2054"],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
except Exception as e:
|
|
print(f"[HDC] ENTER keyEvent failed: {e}")
|
|
else:
|
|
# Single line text - original logic
|
|
# Escape special characters for shell (keep quotes for proper text handling)
|
|
# The text will be wrapped in quotes in the command
|
|
escaped_text = text.replace('"', '\\"').replace("$", "\\$")
|
|
|
|
# HarmonyOS uitest uiInput text command
|
|
# Format: hdc shell uitest uiInput text "文本内容"
|
|
_run_hdc_command(
|
|
hdc_prefix + ["shell", "uitest", "uiInput", "text", escaped_text],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
|
|
def clear_text(device_id: str | None = None) -> None:
|
|
"""
|
|
Clear text in the currently focused input field.
|
|
|
|
Args:
|
|
device_id: Optional HDC device ID for multi-device setups.
|
|
|
|
Note:
|
|
This method uses repeated delete key events to clear text.
|
|
For HarmonyOS, you might also use select all + delete for better efficiency.
|
|
"""
|
|
hdc_prefix = _get_hdc_prefix(device_id)
|
|
# Ctrl+A to select all (key code 2072 for Ctrl, 2017 for A)
|
|
# Then delete
|
|
_run_hdc_command(
|
|
hdc_prefix + ["shell", "uitest", "uiInput", "keyEvent", "2072", "2017"],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
_run_hdc_command(
|
|
hdc_prefix + ["shell", "uitest", "uiInput", "keyEvent", "2055"], # Delete key
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
|
|
def detect_and_set_adb_keyboard(device_id: str | None = None) -> str:
|
|
"""
|
|
Detect current keyboard and switch to ADB Keyboard if available.
|
|
|
|
Args:
|
|
device_id: Optional HDC device ID for multi-device setups.
|
|
|
|
Returns:
|
|
The original keyboard IME identifier for later restoration.
|
|
|
|
Note:
|
|
This is a placeholder. HarmonyOS may not support ADB Keyboard.
|
|
If there's a similar tool for HarmonyOS, integrate it here.
|
|
"""
|
|
hdc_prefix = _get_hdc_prefix(device_id)
|
|
|
|
# Get current IME (if HarmonyOS supports this)
|
|
try:
|
|
result = _run_hdc_command(
|
|
hdc_prefix + ["shell", "settings", "get", "secure", "default_input_method"],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
current_ime = (result.stdout + result.stderr).strip()
|
|
|
|
# If ADB Keyboard equivalent exists for HarmonyOS, switch to it
|
|
# For now, we'll just return the current IME
|
|
return current_ime
|
|
except Exception:
|
|
return ""
|
|
|
|
|
|
def restore_keyboard(ime: str, device_id: str | None = None) -> None:
|
|
"""
|
|
Restore the original keyboard IME.
|
|
|
|
Args:
|
|
ime: The IME identifier to restore.
|
|
device_id: Optional HDC device ID for multi-device setups.
|
|
"""
|
|
if not ime:
|
|
return
|
|
|
|
hdc_prefix = _get_hdc_prefix(device_id)
|
|
|
|
try:
|
|
_run_hdc_command(
|
|
hdc_prefix + ["shell", "ime", "set", ime], capture_output=True, text=True
|
|
)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def _get_hdc_prefix(device_id: str | None) -> list:
|
|
"""Get HDC command prefix with optional device specifier."""
|
|
if device_id:
|
|
return ["hdc", "-t", device_id]
|
|
return ["hdc"]
|