239 lines
5.4 KiB
Markdown
239 lines
5.4 KiB
Markdown
# 终端交互事件捕获功能
|
||
|
||
## 概述
|
||
|
||
现在socket通信系统已支持捕获和传输所有终端交互事件,包括:
|
||
- 键盘输入
|
||
- 鼠标点击、移动、滚轮
|
||
- 终端窗口大小变化
|
||
|
||
## 新增消息类型
|
||
|
||
```c
|
||
typedef enum {
|
||
MSG_TYPE_INIT = 1, // 初始化连接
|
||
MSG_TYPE_WINDOW_SIZE_UPDATE = 2, // 窗口大小更新
|
||
MSG_TYPE_SERVER_RESPONSE = 3, // 服务器响应
|
||
MSG_TYPE_CLOSE = 4, // 关闭连接
|
||
MSG_TYPE_TERMINAL_INPUT = 5, // 终端输入(原始数据)
|
||
MSG_TYPE_TERMINAL_OUTPUT = 6, // 终端输出
|
||
MSG_TYPE_MOUSE_EVENT = 7, // 鼠标事件(结构化)
|
||
MSG_TYPE_KEY_EVENT = 8 // 键盘事件(结构化)
|
||
} MessageType;
|
||
```
|
||
|
||
## 鼠标事件结构
|
||
|
||
```c
|
||
typedef struct {
|
||
uint32_t event_type; // 1=按下, 2=释放, 3=移动, 4=滚轮上, 5=滚轮下
|
||
uint32_t button; // 鼠标按钮(1=左键,2=中键,3=右键)
|
||
uint32_t x; // X坐标(列)
|
||
uint32_t y; // Y坐标(行)
|
||
uint32_t modifiers; // 修饰键(Shift, Ctrl, Alt等)
|
||
} MouseEvent;
|
||
```
|
||
|
||
## 工作原理
|
||
|
||
### 1. 鼠标跟踪启用
|
||
|
||
客户端通过ANSI转义序列启用终端的鼠标跟踪:
|
||
|
||
```c
|
||
// 启用X11鼠标报告 + SGR扩展模式
|
||
const char* enable_seq = "\033[?1000h\033[?1002h\033[?1006h";
|
||
write(STDOUT_FILENO, enable_seq, strlen(enable_seq));
|
||
```
|
||
|
||
### 2. 事件解析
|
||
|
||
客户端监听标准输入的ANSI转义序列:
|
||
|
||
```
|
||
鼠标事件格式:\033[<b;x;yM 或 \033[<b;x;ym
|
||
- b: 按钮编码 + 修饰键
|
||
- x: 列坐标
|
||
- y: 行坐标
|
||
- M: 按下
|
||
- m: 释放
|
||
```
|
||
|
||
### 3. 独立输入线程
|
||
|
||
专门的线程持续监听stdin:
|
||
|
||
```c
|
||
static void* terminal_input_thread(void* arg) {
|
||
while (!g_should_exit) {
|
||
// 使用poll等待输入
|
||
poll(&pfd, 1, 100);
|
||
|
||
// 读取数据
|
||
read(STDIN_FILENO, buf, sizeof(buf));
|
||
|
||
// 解析鼠标事件或发送原始输入
|
||
if (is_mouse_event(buf)) {
|
||
parse_and_send_mouse_event();
|
||
} else {
|
||
send_terminal_input();
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. Go服务端处理
|
||
|
||
服务端接收并记录所有交互事件:
|
||
|
||
```go
|
||
switch msgType {
|
||
case MsgTypeTerminalInput:
|
||
logging.Debug("收到终端输入: %d bytes", len(payload))
|
||
|
||
case MsgTypeMouseEvent:
|
||
event := parseMouseEvent(payload)
|
||
logging.Info("鼠标事件 - 类型:%d, 按钮:%d, 位置:(%d,%d)",
|
||
event.EventType, event.Button, event.X, event.Y)
|
||
}
|
||
```
|
||
|
||
## 线程架构
|
||
|
||
客户端现在运行4个线程:
|
||
|
||
1. **主线程**:发送初始化消息,等待其他线程
|
||
2. **响应监听线程**:接收服务器响应
|
||
3. **窗口监控线程**:监听 SIGWINCH 信号(使用**条件变量驱动**,零 CPU 占用等待)
|
||
4. **输入监听线程**:监听stdin,捕获键盘和鼠标
|
||
|
||
## 使用示例
|
||
|
||
### 编译
|
||
|
||
```bash
|
||
cd execve_hook
|
||
make clean
|
||
make
|
||
```
|
||
|
||
### 测试
|
||
|
||
1. 启动服务端:
|
||
```bash
|
||
cd go_service
|
||
sudo ./build/bash_go_service-amd64 daemon
|
||
```
|
||
|
||
2. 运行测试程序:
|
||
```bash
|
||
cd execve_hook
|
||
./build/test_window_resize
|
||
```
|
||
|
||
3. 在程序运行时:
|
||
- 调整终端窗口大小
|
||
- 点击鼠标
|
||
- 输入键盘字符
|
||
|
||
4. 观察服务端日志输出所有事件
|
||
|
||
## 支持的鼠标模式
|
||
|
||
### X11鼠标报告模式 (\033[?1000h)
|
||
- 捕获鼠标按键按下/释放
|
||
- 基本的鼠标位置报告
|
||
|
||
### 单元格运动跟踪 (\033[?1002h)
|
||
- 捕获鼠标移动(按下按钮时)
|
||
- 拖拽操作支持
|
||
|
||
### SGR扩展模式 (\033[?1006h)
|
||
- 更好的大坐标支持(超过223列/行)
|
||
- 更清晰的按下/释放区分
|
||
|
||
## 应用场景
|
||
|
||
### 1. 用户行为分析
|
||
记录用户在终端中的所有操作,用于:
|
||
- 问题诊断
|
||
- 使用习惯分析
|
||
- 操作回放
|
||
|
||
### 2. 交互式帮助
|
||
根据用户的鼠标位置提供上下文帮助
|
||
|
||
### 3. 终端UI增强
|
||
捕获鼠标点击实现:
|
||
- 可点击的链接
|
||
- 交互式菜单
|
||
- 拖放操作
|
||
|
||
### 4. 会话记录
|
||
完整记录终端会话,包括:
|
||
- 所有输入输出
|
||
- 鼠标操作
|
||
- 窗口调整
|
||
|
||
## 性能考虑
|
||
|
||
- **窗口监听**:使用条件变量事件驱动,零 CPU 占用,即时响应
|
||
- **输入延迟**: < 10ms(poll超时100ms)
|
||
- **CPU使用**: 每个线程休眠或等待条件变量,不占用CPU
|
||
- **内存**: 每个连接 < 100KB
|
||
- **带宽**: 鼠标事件20字节,键盘事件按实际输入
|
||
|
||
## 兼容性
|
||
|
||
### 终端支持
|
||
支持以下现代终端:
|
||
- ✓ xterm
|
||
- ✓ gnome-terminal
|
||
- ✓ konsole
|
||
- ✓ iTerm2
|
||
- ✓ Windows Terminal
|
||
- ✓ alacritty
|
||
- ✓ kitty
|
||
- ⚠ screen(部分支持)
|
||
- ⚠ tmux(需要配置)
|
||
|
||
### 禁用鼠标跟踪
|
||
|
||
如果不需要鼠标功能,可以注释掉:
|
||
|
||
```c
|
||
// enable_mouse_tracking(STDOUT_FILENO);
|
||
```
|
||
|
||
## 调试
|
||
|
||
开启DEBUG模式查看所有事件:
|
||
|
||
```bash
|
||
make DEBUG=1
|
||
./build/test_window_resize
|
||
```
|
||
|
||
输出示例:
|
||
```
|
||
Mouse event: type=1, button=1, pos=(25,10)
|
||
Mouse event: type=2, button=1, pos=(25,10)
|
||
Terminal input: 5 bytes
|
||
Window size update sent to server
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **非TTY环境**:如果stdin不是TTY,鼠标跟踪会自动禁用
|
||
2. **信号处理**:正确处理SIGINT/SIGTERM以清理终端状态
|
||
3. **原始模式**:如需完全控制,可启用raw模式
|
||
4. **终端恢复**:程序退出时应恢复终端原始设置
|
||
|
||
## 扩展建议
|
||
|
||
1. **触摸事件**:支持触摸屏输入
|
||
2. **手势识别**:识别常见鼠标手势
|
||
3. **快捷键绑定**:自定义快捷键处理
|
||
4. **剪贴板集成**:捕获复制粘贴操作
|
||
5. **焦点事件**:终端获得/失去焦点通知
|