Files
kindle-calendar/dash/docs/pagepress-theme-menu-plan.zh.md
2026-03-17 10:37:27 +08:00

9.4 KiB
Raw Blame History

Kindle Dashboard 双翻页键主题菜单方案

0. 当前状态

本文是评审方案,不是实机结论。

当前 Kindle 已掉出 Wi-FiSSH 中断,因此这份文档的目标是:

  • 先把“左右同时按下翻页键,呼出主题选择页面”的方案固定下来
  • 明确交互、进程模型、文件落点和风险
  • 等 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

而不能解释为:

  • 两个键共享同一个内核时间戳

推荐窗口:

  • 300ms350ms

1.3 真正系统挂起时,用户态监听器不会继续工作

当前 dashboard 会在休眠路径里进入:

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
  • 中部竖向列表
  • 当前选中项前用 > 标识
  • 底部两行提示文案

示意:

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 <theme-id> [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. 推荐配置

建议新增这些环境变量:

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 不稳定阶段先落地评审的方案。