密码框打开方案菜单导致键盘隐藏的修复
反馈与日志
用户通过宏的「应用操作 → 切换 Rime 方案」打开菜单时,菜单短暂显示,键盘随后消失再弹出。 来源是用户提供的 io.github.sandyyur.rime.direct-2026-10-20T11_06_48Z.txt;下面仅记录排错所需的生命周期时间线。
| 轮次 | 菜单窗口加入 | 输入界面结束 | 键盘再次显示 |
|---|---|---|---|
| 1 | 19:06:19.909 | 19:06:20.264 | 19:06:21.778 |
| 2 | 19:06:28.811 | 19:06:29.166 | 19:06:30.706 |
| 3 | 19:06:38.305 | 19:06:38.655 | 19:06:39.591 |
三轮中菜单都先收到窗口焦点,加入后约 350–355 ms 进入 onFinishInputView。 同一进程 PID 9914 持续存在,日志没有 FATAL EXCEPTION 或原生崩溃堆栈。 前两轮明确记录了临时 inputType=0,随后恢复到 inputType=225(TEXT | WEB_PASSWORD); Rime 重新绑定约 481/504/514 ms,放大了窗口隐藏带来的延迟。 这些现象支持菜单抢占宿主窗口焦点后,网页密码编辑器结束并重新建立输入连接的判断。 日志中的厂商 Receiver not registered 出现在窗口销毁期间,不能据此认定它是应用崩溃原因。
修改
宏动作和语言键长按共用 FcitxInputMethodService.showDialog。 原来的附着窗口使用 FLAG_ALT_FOCUSABLE_IM,仍可获取窗口焦点。 现在选择菜单保持非焦点窗口:
- 先通过
Dialog.create()完成内容初始化,再清除FLAG_ALT_FOCUSABLE_IM、设置FLAG_NOT_FOCUSABLE,菜单仍接受触摸。 - 不同时设置两个标记,避免菜单被放到输入法后面。
- 返回键和方向键由输入服务转交菜单分发,保持菜单取消和导航行为。
- 保留点选、遮罩和触摸外部关闭;键盘已隐藏时不再显示异步返回的菜单。
- 关闭旧菜单的异步回调只清理旧实例,避免把刚打开的新菜单引用清空。
该窗口入口也用于输入法选择菜单,因此两种选择菜单共享此焦点策略。 Android 的 AlertController 在创建没有文本编辑器的菜单内容时会自动加入 ALT_FOCUSABLE_IM; 必须在内容创建后设置最终标记,显示后的实际窗口属性也纳入设备断言。 本次没有修改 Rime 原生调用、方案数据、用户词库、密码直出或禁止学习设置。
回归验证
DirectRimeFrontendTest.schemaMenuKeepsPasswordEditorFocused 使用完整输入法界面,覆盖:
- 普通文本、普通密码、网页密码标记(225)与数字密码四类编辑框。
- 通过宏实际使用的
executeButtonAction("rime_schema_menu")入口打开菜单。 - 菜单显示后等待超过日志中的触发时间,确认宿主窗口没有失焦,键盘保持可见,输入代次与已有文本不变。
- 实际注入触摸选择另一方案,确认切换成功并关闭菜单。
- 返回键关闭菜单后继续输入,确认文字仍进入原编辑框。
- 普通文本框额外检查触摸菜单外部可关闭菜单,且不隐藏键盘。
首轮设备 CI 39436090809 在外部点击用例失败:测试把两个窗口各自的根坐标直接比较,点击点不保证在菜单外。 该用例已统一使用屏幕坐标,并选择工具栏空白区;这次修正只涉及测试坐标,不更改输入法窗口策略。
第二轮 39437662001 中,密码菜单用例通过全部四类输入框,随后 API 回放用例继承了密码能力标记而超时。 测试准备现在为新的普通文本模拟会话显式设置默认能力,隔离不同用例;产品的密码保护逻辑保持不变。
自动化宿主是 Android EditText,包含与日志一致的网页密码输入标记;它验证共同的窗口焦点机制, 不等同于在用户的 Oplus/Edge 设备上执行回归。该机型还需安装修复版确认。 本地编译、单测及最终设备 CI 的结果和对应签名包以 PR #4 的本轮验证记录为准。