# Kindle Dashboard 双翻页键主题菜单方案 ## 0. 当前状态 本文是评审方案,不是实机结论。 当前 Kindle 已掉出 Wi-Fi,SSH 中断,因此这份文档的目标是: - 先把“左右同时按下翻页键,呼出主题选择页面”的方案固定下来 - 明确交互、进程模型、文件落点和风险 - 等 SSH 恢复后,再按这份方案做实机联调和裁剪 本文默认设备为: - Kindle Voyage - 固件 5.13.6 - dashboard 运行时会停掉 framework / webreader ## 1. 已确认事实 ### 1.1 左右翻页键在内核里是两个独立键 实机上已经确认: - 输入设备名为 `fsr_keypad` - 设备节点为 `/dev/input/event2` - `evtest /dev/input/event2` 可识别: - `Event code 104 (PageUp)` - `Event code 109 (PageDown)` 这意味着: - 左右翻页键不是一个“翻页动作” - 而是两个可以分别监听的 `EV_KEY` - 软件层可以把它们组合成一个“组合键” ### 1.2 组合键不可能在同一时刻上报 Linux 输入事件一定是串行上报的。 所以“左右同时按下”在实现上必须解释为: - 两个键在一个很短的时间窗口内先后进入 pressed 而不能解释为: - 两个键共享同一个内核时间戳 推荐窗口: - `300ms` 到 `350ms` ### 1.3 真正系统挂起时,用户态监听器不会继续工作 当前 dashboard 会在休眠路径里进入: ```sh echo "mem" >/sys/power/state ``` 一旦进入这个状态: - 用户态 shell / Lua / evtest 监听器都会停掉 - 无法继续等待双键输入 因此本方案的有效范围是: - dashboard 正在运行 - Kindle 尚未进入真正的 `mem` 挂起 这也是为什么本方案先聚焦: - 运行态主题菜单 而不把目标直接扩展为: - 真休眠态唤醒菜单 ## 2. 目标 目标能力如下: 1. 用户在 dashboard 运行态下,同时按下左右翻页键 2. 屏幕弹出一个 KUAL 风格的主题选择页面 3. 用户通过翻页键在主题列表中移动选中项 4. 用户再次同时按下左右翻页键,确认并切换主题 5. 切换完成后,立即刷新背景和时钟 本阶段非目标: - 不做真正休眠态下的按键唤醒菜单 - 不在 Kindle 上实现复杂触摸手势 - 不做缩略图式主题画廊 - 不做 theme + orientation 同时编辑的完整设置页 ## 3. 推荐交互 ### 3.1 触发方式 触发手势: - 左右翻页键在 `350ms` 内同时按下 解释规则: - 先按左,再按右,且间隔不超过 `350ms`,视为组合键 - 先按右,再按左,且间隔不超过 `350ms`,也视为组合键 - 单独按左或单独按右,不触发菜单 ### 3.2 菜单打开后的操作 推荐第一版交互保持纯物理键可用: - `PageUp`:向上移动 - `PageDown`:向下移动 - 再次双键同时按下:确认当前主题 这样做的原因: - 不依赖 framework - 不依赖系统触摸 UI - 行为闭环简单,便于在无 SSH 时本机恢复 ### 3.3 方向处理 推荐第一版只切换 `theme id`,保持当前方向不变。 例如: - 当前是 `simple / landscape` - 菜单里选中 `paper` - 最终切到 `paper / landscape` 如果目标主题不支持当前方向,再回退到: - 该主题可用的默认方向 这样能避免菜单第一版就把交互复杂度拉高到二维。 ## 4. 菜单布局 ### 4.1 布局风格 菜单布局可以模拟 KUAL,但不追求逐像素复刻。 推荐视觉结构: - 全屏白底 - 顶部两行标题 - `Kindle Dashboard` - `Theme Menu` - 中部竖向列表 - 当前选中项前用 `>` 标识 - 底部两行提示文案 示意: ```text Kindle Dashboard Theme Menu Orientation: landscape Selected: Simple -------------------------------- > Default (default) Paper (paper) Classic (classic) Simple (simple) PageUp/PageDown: move Press both keys: apply ``` ### 4.2 为什么不做缩略图页 在当前阶段,不建议直接做缩略图式主题预览页。 原因: - 需要更多图形绘制和排版能力 - 需要解决选中态、滚动和点击区域映射 - 在 SSH 不稳定时,调试成本显著上升 所以推荐第一版先做: - 纯文本 KUAL 风格列表 确认流程稳定后,再考虑升级到: - 缩略图 + 文本说明 ## 5. 进程模型 ### 5.1 推荐采用独立监听服务 推荐新增一个独立后台服务,例如: - `dash/src/local/theme-menu-service.sh` 职责: - 独立监听 `/dev/input/event2` - 识别组合键 - 维护菜单状态 - 在确认后调用现有主题切换链路 不建议把这套逻辑直接塞进 `dash.sh` 主循环。 原因: - 主循环核心职责已经是拉图、刷屏、休眠 - 组合键菜单属于输入状态机 - 两者耦合后,调试和排错都会变差 ### 5.2 与现有链路的关系 推荐关系如下: 1. `dash.sh` 启动时拉起 `theme-menu-service.sh` 2. `theme-menu-service.sh` 常驻监听 `event2` 3. 识别到组合键后,本机绘制菜单 4. 用户确认后,调用现有: - `/mnt/us/dashboard/switch-theme.sh [orientation]` 5. `switch-theme.sh` 继续负责: - 同步主题配置 - 拉最新背景 - 刷新屏幕 - 重绘时钟 也就是说,菜单服务只负责: - 触发 - 选择 - 调用已有切换入口 而不是重新实现一套主题切换。 ## 6. 事件状态机 ### 6.1 空闲态 空闲态只关注组合键触发。 状态变量: - `pending_key` - `pending_time` - `combo_window_seconds` 逻辑: 1. 收到 `PageUp down` - 记录 `pending_key=up` 2. 收到 `PageDown down` - 如果此前 `pending_key=up` 且时间差小于窗口,判定为组合键 3. 反向顺序同理 4. 组合键成立后,打开菜单 ### 6.2 菜单态 菜单态下,状态机切成另一套规则: - `PageUp` release:选中项上移 - `PageDown` release:选中项下移 - 组合键:确认当前项 推荐选中项循环: - 第一项再上移 -> 跳到最后一项 - 最后一项再下移 -> 跳到第一项 这样可以减少边界判断和失败反馈。 ## 7. 文件落点 推荐新增或修改这些文件。 ### 7.1 新增 - `dash/src/local/theme-menu-service.sh` - 常驻监听器和菜单状态机 ### 7.2 修改 - `dash/src/local/theme-json.lua` - 新增 `list` 子命令 - 输出主题列表给菜单服务消费 - `dash/src/local/env.sh` - 新增菜单相关开关,例如: - `THEME_MENU_ENABLED` - `THEME_MENU_EVENT_DEVICE` - `THEME_MENU_COMBO_WINDOW_SECONDS` - `dash/src/dash.sh` - 在初始化阶段拉起菜单监听服务 - `dash/src/stop.sh` - 停止 dashboard 时顺手停止菜单服务 - `scripts/sync-layered-clock-to-kindle.sh` - 把新增服务脚本同步到设备 ## 8. 推荐配置 建议新增这些环境变量: ```sh export THEME_MENU_ENABLED=true export THEME_MENU_EVENT_DEVICE="/dev/input/event2" export THEME_MENU_COMBO_WINDOW_SECONDS=0.35 ``` 说明: - `THEME_MENU_ENABLED` - 总开关 - `THEME_MENU_EVENT_DEVICE` - Voyage 上通常是 `event2` - 后续换机型时可以只改这个 - `THEME_MENU_COMBO_WINDOW_SECONDS` - 组合键判定窗口 ## 9. 风险与限制 ### 9.1 真休眠态不可用 这是本方案最重要的限制。 只要系统真的进入: - `echo "mem" >/sys/power/state` 那么: - 监听器就不会继续运行 - 双键菜单也不会再响应 因此第一版推荐配套策略是: - 调试阶段 `DISABLE_SYSTEM_SUSPEND=true` - 菜单只保证运行态可用 后续如果要支持“近似待机但仍可双键唤出菜单”,再单独设计: - sleeping 页面但不进真 suspend ### 9.2 菜单样式是 KUAL 风格,不是 KUAL 组件 本方案里的“KUAL 风格”是指: - 白底 - 列表 - 简洁标题 - 文本选中态 并不是: - 真的把 KUAL 的 Java/UI 组件拉起来 原因是当前 dashboard 已经停掉 framework,直接复用 KUAL UI 的成本会更高。 ### 9.3 第一版不依赖触摸 从评审角度看,第一版最好不要把选择动作建立在触摸上。 原因: - 触摸设备事件会更复杂 - 点选区域映射也更容易出错 - 无 SSH 时问题更难恢复 所以第一版推荐: - 只用翻页键完成整个菜单闭环 ## 10. 后续验证路径 等 SSH 恢复后,建议按这个顺序验证: 1. 确认 `evtest /dev/input/event2` 仍能看到: - `PageUp` - `PageDown` 2. 先同步本地最新 dashboard 代码到 Kindle - 本轮已在本地加入一个“短按 `power` 提前唤醒后,额外保持 60 秒”的改动 - 相关配置在 `dash/src/local/env.sh`: - `MANUAL_WAKE_KEEP_AWAKE_SECONDS=60` - `MANUAL_WAKE_EARLY_TOLERANCE_SECONDS=5` - 相关运行逻辑在 `dash/src/dash.sh` 3. 重启 dashboard,先单独验证短按 `power`: - 从休眠态短按 `power` - 预期不再只亮约 3 秒 - 预期应保持约 60 秒再回到下一轮休眠 4. 让 dashboard 保持运行态,不进真 suspend 5. 手动启动菜单服务 6. 验证: - 双键能否稳定打开菜单 - 单键移动是否会误触组合键 - 再次双键能否稳定确认 7. 验证主题切换后: - 背景立即更新 - 时钟位置和方向保持正确 ## 11. 结论 在当前仓库和 Kindle Voyage 的约束下,推荐采用下面这条路线: - 监听 `/dev/input/event2` - 用短时间窗口识别 `PageUp + PageDown` 组合键 - 在运行态下绘制一个 KUAL 风格的文本主题菜单 - 用 `PageUp / PageDown` 导航 - 再次双键确认 - 最终复用现有 `switch-theme.sh` 完成主题切换 这是当前成本最低、最容易恢复、也最适合在 SSH 不稳定阶段先落地评审的方案。