Skip to content

Commit 0e5a610

Browse files
committed
docs: add mobile terminal soft key keyboard issue
1 parent 449505c commit 0e5a610

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# 移动端终端自定义虚拟按键会重新唤起系统软键盘
2+
3+
## 标题
4+
5+
`fix(web): 移动端终端自定义虚拟按键不应重新唤起系统软键盘`
6+
7+
## 问题描述
8+
9+
`coder-studio` 的移动端 terminal 场景下,用户先让终端进入可输入状态,再手动收起系统软键盘,随后点击终端底部我们自己实现的虚拟按键行,例如 `Ctrl``Shift``Esc``Tab`、方向键或 `Enter`,系统软键盘会再次被唤起。
10+
11+
这排按键的设计目标是补足移动端终端缺失的控制键,不应该在用户已经手动收起系统软键盘后,又把键盘重新拉起。
12+
13+
## 复现步骤
14+
15+
1. 在手机或平板上打开 `coder-studio` 的 terminal。
16+
2. 点击 terminal,让系统软键盘弹出。
17+
3. 手动收起系统软键盘。
18+
4. 点击 terminal 底部自定义虚拟按键行中的任意键,例如 `Ctrl``Shift``Esc` 或方向键。
19+
5. 观察系统软键盘重新弹出。
20+
21+
## 预期行为
22+
23+
- 当系统软键盘已经打开时,点击自定义虚拟按键不应强制把它收掉。
24+
- 当系统软键盘已经被用户手动收起时,点击自定义虚拟按键也不应再次把它唤起。
25+
- 自定义虚拟按键应只向终端发送控制输入,而不改变当前系统软键盘的可见状态。
26+
27+
## 实际行为
28+
29+
用户手动收起系统软键盘后,点击自定义虚拟按键仍会导致系统软键盘再次弹出。
30+
31+
## 已确认事实
32+
33+
- 该问题涉及的是 terminal 内部我们自己实现的移动端虚拟按键行,不是系统软键盘本身。
34+
- 自定义虚拟按键的数据链路是:
35+
- `MobileTerminalInputBar`
36+
- `handleSoftKeyPress`
37+
- `handleInput`
38+
- `wsClient.sendTerminalInput`
39+
- 自定义虚拟按键并不是通过 `xterm.onData(...)` 触发输入;它们不会先走 xterm 的浏览器键盘事件采集路径。
40+
- `xterm` 在浏览器里依赖隐藏的 `textarea``.xterm-helper-textarea`)承接键盘、IME 与移动端输入。
41+
- `xterm` 自身维护这个隐藏 `textarea` 的焦点状态,并通过 `focus()` / `blur()` 管理终端输入上下文。
42+
- 在移动端浏览器里,用户“收起软键盘”不一定等价于输入元素真正 `blur`;隐藏 `textarea` 可能仍保持焦点。
43+
- 当前自定义虚拟按键在 `pointerdown` 上使用了 `preventDefault()`,因此按钮本身不会接管焦点。
44+
- 当按钮不接管焦点,而 `xterm` 的隐藏 `textarea` 仍处于焦点上下文时,浏览器可能在下一次触摸交互时重新恢复系统软键盘。
45+
46+
## 当前判断
47+
48+
问题更像是:
49+
50+
- `xterm` 的隐藏 `textarea` 在用户收起软键盘后仍保持焦点或可恢复的输入上下文
51+
- 自定义虚拟按键由于 `preventDefault()` 没有改变当前焦点归属
52+
- 浏览器在后续触摸时将该焦点中的文本输入上下文重新激活,于是系统软键盘再次弹出
53+
54+
也就是说,根因不在“自定义虚拟按键错误地走进了 xterm 的 `onData`”,而在 `xterm` 隐藏输入层的焦点生命周期与移动端浏览器软键盘策略之间的耦合。
55+
56+
## 已排除方向
57+
58+
- 不是自定义虚拟按键通过 `xterm.onData(...)` 间接触发的输入问题。
59+
- 不是 PTY / WebSocket 数据发送链路导致系统软键盘弹出。
60+
- 直接对 `document.activeElement` 做全局 `blur()` 虽然能验证问题与焦点有关,但方案过粗,可能引入键盘闪烁、误伤其他输入元素等副作用,不适合作为最终修复。
61+
62+
## 后续排查方向
63+
64+
- 在真实移动端浏览器上记录以下事件时序:
65+
- 用户手动收起软键盘前后
66+
- 点击自定义虚拟按键前后
67+
- `document.activeElement`
68+
- `xterm.textarea``focus` / `blur`
69+
- `visualViewport.height` 变化
70+
- 确认“软键盘收起但 `xterm.textarea` 仍保持焦点”是否稳定可复现,以及在不同浏览器上的差异。
71+
- 评估是否需要在移动端引入更精确的终端输入状态机,例如区分:
72+
- 系统键盘打开
73+
- 系统键盘已被用户收起
74+
- 仅使用自定义虚拟按键输入
75+
- 如果需要修复,优先考虑:
76+
- 仅围绕 `xterm.textarea` 做精确的 `focus` / `blur` 管理
77+
- 避免对全局 `activeElement` 做无条件处理
78+
- 保证“键盘开着时不强制收掉,键盘关着时不重新拉起”

0 commit comments

Comments
 (0)