# noVNC 客户端键盘使用指南

本指南详细介绍了如何使用 noVNC 客户端的键盘输入功能，包括支持的按键类型、使用示例和最佳实践。

## 目录

1. [基本概念](#基本概念)
2. [支持的按键类型](#支持的按键类型)
3. [基本键盘操作](#基本键盘操作)
4. [特殊按键](#特殊按键)
5. [组合键](#组合键)
6. [文本输入](#文本输入)
7. [常见用例](#常见用例)
8. [最佳实践](#最佳实践)
9. [故障排除](#故障排除)

## 基本概念

noVNC 客户端提供了完整的键盘输入功能，支持：

- **普通字符**：字母、数字、标点符号
- **特殊按键**：功能键、导航键、修饰键
- **组合键**：Ctrl+C、Alt+Tab 等
- **文本输入**：多字符文本的批量输入

所有的键盘操作都通过 `NoVNCClient` 类的方法来实现，支持异步操作。

## 支持的按键类型

### 1. 普通字符

支持所有 ASCII 可打印字符（32-126）：

```python
# 字母
await client.key_tap('a')
await client.key_tap('A')

# 数字
await client.key_tap('1')
await client.key_tap('0')

# 标点符号
await client.key_tap('!')
await client.key_tap('@')
await client.key_tap(' ')  # 空格
```

### 2. 特殊按键

#### 编辑键
- `backspace` - 退格键
- `tab` - 制表符键
- `return` / `enter` - 回车键
- `escape` - ESC 键
- `delete` - 删除键
- `insert` - 插入键

#### 导航键
- `home` - Home 键
- `end` - End 键
- `left` - 左箭头键
- `up` - 上箭头键
- `right` - 右箭头键
- `down` - 下箭头键
- `page_up` - Page Up 键
- `page_down` - Page Down 键

#### 功能键
- `f1` ~ `f12` - 功能键 F1 到 F12

#### 修饰键
- `shift` / `shift_l` - 左 Shift 键
- `shift_r` - 右 Shift 键
- `ctrl` / `ctrl_l` - 左 Ctrl 键
- `ctrl_r` - 右 Ctrl 键
- `alt` / `alt_l` - 左 Alt 键
- `alt_r` - 右 Alt 键

#### 系统键
- `win` / `win_l` / `windows` / `super` - 左 Windows 键
- `win_r` - 右 Windows 键

### 3. 类型安全的按键枚举

从 `types.py` 导入 `SpecialKey` 枚举以获得类型安全：

```python
from novnc_client.types import SpecialKey

# 使用枚举值
await client.key_tap(SpecialKey.ENTER)
await client.key_tap(SpecialKey.F1)
await client.key_tap(SpecialKey.CTRL)
```

## 基本键盘操作

### 1. 按键点击 (key_tap)

最常用的方法，按下然后释放按键：

```python
async with NoVNCClient('localhost', 6080) as client:
    # 点击单个字符
    await client.key_tap('a')

    # 点击特殊按键
    await client.key_tap('enter')
    await client.key_tap('tab')
    await client.key_tap('f1')

    # 自定义按住时间
    await client.key_tap('space', duration=0.1)
```

### 2. 按键按下和释放 (key_down/key_up)

用于精确控制按键状态：

```python
async with NoVNCClient('localhost', 6080) as client:
    # 按下按键
    await client.key_down('ctrl')
    await client.key_down('c')

    # 等待一段时间
    await asyncio.sleep(0.1)

    # 释放按键（注意顺序）
    await client.key_up('c')
    await client.key_up('ctrl')
```

### 3. 按键事件 (key_press)

底层方法，可以指定按下或释放：

```python
async with NoVNCClient('localhost', 6080) as client:
    # 按下
    await client.key_press('shift', down=True)
    await client.key_press('a', down=True)

    # 释放
    await client.key_press('a', down=False)
    await client.key_press('shift', down=False)
```

## 特殊按键

### 导航键使用示例

```python
async with NoVNCClient('localhost', 6080) as client:
    # 移动光标
    await client.key_tap('home')      # 移动到行首
    await client.key_tap('end')       # 移动到行尾
    await client.key_tap('left')      # 左移一个字符
    await client.key_tap('right')     # 右移一个字符
    await client.key_tap('up')        # 上移一行
    await client.key_tap('down')      # 下移一行

    # 翻页
    await client.key_tap('page_up')   # 上翻页
    await client.key_tap('page_down') # 下翻页
```

### 功能键使用示例

```python
async with NoVNCClient('localhost', 6080) as client:
    # 常见功能键
    await client.key_tap('f1')     # 帮助
    await client.key_tap('f2')     # 重命名
    await client.key_tap('f5')     # 刷新
    await client.key_tap('f11')    # 全屏
    await client.key_tap('f12')    # 开发者工具
```

## 组合键

### 使用 key_combination 方法

```python
async with NoVNCClient('localhost', 6080) as client:
    # 文本编辑
    await client.key_combination('ctrl', 'c')      # 复制
    await client.key_combination('ctrl', 'v')      # 粘贴
    await client.key_combination('ctrl', 'x')      # 剪切
    await client.key_combination('ctrl', 'a')      # 全选
    await client.key_combination('ctrl', 'z')      # 撤销
    await client.key_combination('ctrl', 'y')      # 重做

    # 文件操作
    await client.key_combination('ctrl', 'n')      # 新建
    await client.key_combination('ctrl', 'o')      # 打开
    await client.key_combination('ctrl', 's')      # 保存
    await client.key_combination('ctrl', 'shift', 's')  # 另存为

    # 窗口管理
    await client.key_combination('alt', 'tab')     # 切换窗口
    await client.key_combination('alt', 'f4')      # 关闭窗口
    await client.key_combination('win', 'r')       # 运行对话框
    await client.key_combination('win', 'l')       # 锁定屏幕

    # 系统快捷键
    await client.key_combination('ctrl', 'alt', 'delete')  # 任务管理器
    await client.key_combination('ctrl', 'shift', 'escape')  # 任务管理器
```

### 便捷快捷键方法

```python
async with NoVNCClient('localhost', 6080) as client:
    # 预定义的常用快捷键
    await client.send_ctrl_c()      # Ctrl+C
    await client.send_ctrl_v()      # Ctrl+V
    await client.send_ctrl_a()      # Ctrl+A
    await client.send_alt_tab()     # Alt+Tab
```

## 文本输入

### 使用 type_text 方法

```python
async with NoVNCClient('localhost', 6080) as client:
    # 输入普通文本
    await client.type_text("Hello, World!")

    # 输入包含特殊字符的文本
    await client.type_text("用户名: admin\n密码: 123456\n")

    # 自定义输入速度
    await client.type_text("慢速输入", delay=0.1)
    await client.type_text("快速输入", delay=0)

    # 输入制表符分隔的数据
    await client.type_text("姓名\t年龄\t职业\n")
    await client.type_text("张三\t25\t工程师\n")
```

### 处理特殊字符

```python
async with NoVNCClient('localhost', 6080) as client:
    # 换行符会被转换为回车键
    await client.type_text("第一行\n第二行\n")

    # 制表符会被转换为 Tab 键
    await client.type_text("列1\t列2\t列3\n")

    # 不支持的字符会被跳过
    await client.type_text("支持的字符 \x00 不支持的字符")
```

## 常见用例

### 1. 文本编辑器操作

```python
async with NoVNCClient('localhost', 6080) as client:
    # 打开文本编辑器
    await client.key_combination('win', 'r')
    await asyncio.sleep(0.5)
    await client.type_text('notepad')
    await client.key_tap('enter')
    await asyncio.sleep(2)

    # 输入文本
    await client.type_text("这是一个测试文档\n")
    await client.type_text("包含多行内容\n")

    # 全选并复制
    await client.send_ctrl_a()
    await client.send_ctrl_c()

    # 移动到末尾并粘贴
    await client.key_tap('end')
    await client.key_tap('enter')
    await client.send_ctrl_v()
```

### 2. 终端命令执行

```python
async with NoVNCClient('localhost', 6080) as client:
    # 打开终端
    await client.key_combination('ctrl', 'alt', 't')
    await asyncio.sleep(1)

    # 执行命令
    await client.type_text('ls -la')
    await client.key_tap('enter')
    await asyncio.sleep(1)

    # 清屏
    await client.type_text('clear')
    await client.key_tap('enter')

    # 使用管道
    await client.type_text('ps aux | grep python')
    await client.key_tap('enter')
```

### 3. 网页表单填写

```python
async with NoVNCClient('localhost', 6080) as client:
    # 填写表单字段
    await client.type_text('username@example.com')
    await client.key_tap('tab')  # 移动到下一个字段
    await client.type_text('password123')
    await client.key_tap('tab')

    # 提交表单
    await client.key_tap('enter')
    # 或者
    await client.key_tap('space')  # 如果是按钮
```

### 4. 代码编辑

```python
async with NoVNCClient('localhost', 6080) as client:
    # 输入代码
    await client.type_text('def hello_world():')
    await client.key_tap('enter')
    await client.type_text('    print("Hello, World!")')
    await client.key_tap('enter')
    await client.key_tap('enter')

    # 运行代码 (Python)
    await client.key_tap('f5')
    # 或者
    await client.key_combination('ctrl', 'f5')
```

## 最佳实践

### 1. 添加适当的延迟

```python
async with NoVNCClient('localhost', 6080) as client:
    # 在操作之间添加延迟，确保应用程序能够响应
    await client.key_tap('enter')
    await asyncio.sleep(0.5)  # 等待应用程序处理

    await client.type_text('下一个操作')
```

### 2. 使用类型安全的枚举

```python
from novnc_client.types import SpecialKey

async with NoVNCClient('localhost', 6080) as client:
    # 推荐：使用枚举值
    await client.key_tap(SpecialKey.ENTER)
    await client.key_tap(SpecialKey.F1)

    # 而不是字符串
    await client.key_tap('enter')  # 也可以，但缺少类型检查
```

### 3. 错误处理

```python
async with NoVNCClient('localhost', 6080) as client:
    try:
        await client.key_tap('invalid_key')
    except ValueError as e:
        print(f"不支持的按键: {e}")

    # 对于不确定的字符，使用 type_text 更安全
    await client.type_text("可能包含不支持字符的文本")
```

### 4. 组合键的正确顺序

```python
async with NoVNCClient('localhost', 6080) as client:
    # 正确：修饰键在前
    await client.key_combination('ctrl', 'shift', 'n')

    # 错误：修饰键在后
    # await client.key_combination('n', 'ctrl', 'shift')
```

## 故障排除

### 1. 按键不起作用

**可能原因：**
- 按键名称拼写错误
- 目标应用程序没有焦点
- 连接问题

**解决方法：**
```python
# 检查按键名称
try:
    await client.key_tap('enter')
except ValueError as e:
    print(f"按键错误: {e}")

# 确保应用程序有焦点
await client.mouse_click(100, 100)  # 先点击应用程序
await asyncio.sleep(0.5)
await client.key_tap('enter')
```

### 2. 组合键不工作

**可能原因：**
- 按键顺序错误
- 按键释放顺序错误
- 延迟时间不足

**解决方法：**
```python
# 使用更长的延迟
await client.key_combination('ctrl', 'c', duration=0.2)

# 或者手动控制
await client.key_down('ctrl')
await asyncio.sleep(0.1)
await client.key_down('c')
await asyncio.sleep(0.1)
await client.key_up('c')
await client.key_up('ctrl')
```

### 3. 文本输入问题

**可能原因：**
- 包含不支持的字符
- 输入速度过快
- 目标应用程序输入法冲突

**解决方法：**
```python
# 使用更慢的输入速度
await client.type_text("文本内容", delay=0.05)

# 检查日志中的警告信息
import logging
logging.basicConfig(level=logging.DEBUG)
```

### 4. 特殊字符处理

**问题：**某些特殊字符无法正确输入

**解决方法：**
```python
# 对于特殊字符，使用按键名称
await client.key_tap('tab')      # 而不是 '\t'
await client.key_tap('enter')    # 而不是 '\n'
await client.key_tap('space')    # 而不是 ' '（某些情况下）
```

## 总结

noVNC 客户端提供了完整的键盘输入功能，支持：

- ✅ 所有 ASCII 字符
- ✅ 完整的特殊按键支持
- ✅ 复杂的组合键操作
- ✅ 高效的文本输入
- ✅ 类型安全的 API
- ✅ 详细的错误处理

通过合理使用这些功能，您可以实现几乎所有的键盘操作需求。记住在操作之间添加适当的延迟，使用类型安全的枚举，并进行适当的错误处理。
