基座+设计文档(三特性): meow_ui.h 字体档/状态栏收合API + launcher fonts/fullscreen解析+env注入+通知dump钩子 + meow_ui_gfx.c 收合渲染+字体档; spec-ref/SYSTEM_SETTINGS/APPS/NOTIFICATION 三特性设计落档

This commit is contained in:
MeowOS Dev committed 2026-08-30 11:28:11 +08:00
1 parent 9b8a1e5c8b
commit 0b4d1d3215
8 files changed
+297 -25

No files matched your search

+20 -3
View File
@@ -96,6 +96,7 @@
- 控件:`meow_list_source = int (*)(int idx,char *label,int len,void *ctx)`([D2] 定案)`[meow_ui.h]`
- 刷新率:`meow_ui_set_refresh_rate(60/30/15)`/`meow_ui_set_refresh_always_max(1)`/`meow_ui_effective_rate()`/`meow_ui_frames_presented()` `[meow_ui.h §7.1]`
- 状态栏:`meow_ui_set_statusbar(1/0)`/`meow_ui_statusbar_height()`(非全屏=28,全屏=0)/`meow_ui_set_fullscreen(on)`;状态栏高 **MUI_SBAR_H=28**(用户定 40→28,字号随之为 20)`[MIGRATION_AC §11.1][meow_ui.h]`
- 全屏/状态栏收合(M2.5x):launcher 启动 app/切 activity 据 `app.json fullscreen`/`route.<id>.fullscreen` 预先设 SDK 全屏(env **`MEOW_FULLSCREEN`** 注入);进入全屏 = 状态栏**向上收出屏顶、只留一条提示线**(新增 `meow_ui_statusbar_collapsed()` 语义,区分「**收合=状态栏缩为提示线**」vs「**隐藏=高度0**」),带自然过渡动画;全屏下**保留左缘返回手势 + 顶部提示线,顶部下滑仍开通知中心(顶部热区缩小)** `[源:用户 2026-08-30]`
- 日志:`MEOW_LOG_DEBUG=0/INFO/WARN/ERROR`;`meow_log(lvl,fmt,...)`/`meow_log_set_level`/`meow_log_get_level` `[meow_ui.h §9]`
- 通知:见 §4。
@@ -144,6 +145,7 @@
- **左缘返回手势**:手指从**屏幕左缘 ≤24px** 向内(右)划 **≥90px**,**抬手(release 边沿)才触发** `MEOW_SWIPE_LEFT`("左滑=返回"契约);过程以 `on_swipe_progress` 实时上报 + SDK 自动画顶部进度条 `meow_ui_swipe_hint(x)`(5px 高,top,theme accent 色);x<=0 清条。**中部左/右滑不是返回**(中部右滑→SWIPE_RIGHT,中部左滑→落 TAP)`[MEOW_APP_SDK §6][GESTURE_BACK §2.2/§3]`
- 偏差:原「左缘+向左 mdx<-90」物理不可达 → 取「左缘向内(右)划 ≥90px」,事件仍报 `MEOW_SWIPE_LEFT` `[GESTURE_BACK §3]`
- **全局状态栏**:SDK 内置,默认显示(时钟/电量/WiFi/蓝牙/音量),1s 轻刷,z 最顶;仅 APP 声明全屏/`fullscreen:1` 才隐藏;非全屏 APP 须用 `meow_ui_statusbar_height()` 做 inset `[meow_ui.h §3.1][MIGRATION_AC §3]`
- **全屏机制(M2.5x,`app.json fullscreen` 即 app 级 + `route.<id>.fullscreen` 即 activity 级)**:launcher 启动 app/切 activity 时据声明**预先设 SDK 全屏**(env `MEOW_FULLSCREEN`)。进入/退出全屏:**状态栏向上收出屏顶、只留一条提示线高度**(非全隐藏),带上收/恢复的**自然过渡动画**。**全屏下保留**:左缘返回手势 + 顶部动态伸缩提示线;顶部下滑仍可展开通知中心,但**顶部热区缩小**(不影响全屏 app)`[源:用户 2026-08-30]`(细化既有「全屏=隐藏状态栏/隐藏返回键」的表述,见 §7 A-13)
- 沉浸:`app.json immersive:1` → launcher 写 `/tmp/meowapp_state=1` → 隐藏虚拟返回键,手势归 SDK `[APPS §3.5][GESTURE_BACK §2.4]`
### 5.2 主题
@@ -152,17 +154,24 @@
- 主界面背景:深色用 background(可选色)、浅色用 surface(白) `[DEV_NOTES #13]`
- **TF 卡多字体库(M2.5x)**:
- 目录 **`<卡根>/MeowOS/fonts/<family>/`**(每套一个子目录),内含三件套:`font.png`(预渲染灰度 PNG,bit depth 4|8)+ `font.idx`(MFNI v2 索引),二者均由 `font/gen/gen_font.py` 生成;`font.json` 为元数据+完整性校验。**缺任一件 → 该套不进列表 + 日志**。
- **font.json schema(定版)**:`family`(同目录名,信息用)/`name`(下拉显示名,缺则回退目录名)/`glyph_count`(信息用)/`size_list`(信息用)/`bit_depth`(4|8,信息用)/`sha256_png`(font.png 的 sha256 低 64hex)/`sha256_idx`(font.idx 的 sha256)/`source`(可选)/`license`(可选)。校验失败**仅 WARN 不硬失败**(该套仍可选);缺 font.json 或解析不出 `name` → 跳过。
- **font.json schema(定版)**:`family`(同目录名,信息用)/`name`(下拉显示名,缺则回退目录名)/`glyph_count`(信息用)/`charset`(`common|gbk|full`,字库档位,信息用+驱动按需加载,见「字体档位/大字库」)/`size_list`(信息用)/`bit_depth`(4|8,信息用)/`sha256_png`(font.png 的 sha256 低 64hex)/`sha256_idx`(font.idx 的 sha256)/`source`(可选)/`license`(可选)。校验失败**仅 WARN 不硬失败**(该套仍可选);缺 font.json 或解析不出 `name` → 跳过。
- **加载优先级**:`font.file`(设置键,默认 `MeowOS/fonts/default/font.png`)指向的字体**存在且能 load → 用它**;否则回退卡默认 `MeowOS/fonts/default/font.png` → 固件 `/usr/share/meowos/font/font.png`。相对路径按卡根 `/usr/data/mnt/sd_0/` 解析。全失败 → 字库不可用,`ui_draw` 回退 5x7 点阵(系统不死)。
- **默认字库目录**:默认字体统一放 **`<卡根>/MeowOS/fonts/default/`**(`font.png`+`font.idx`,可选 `font.json`),不再用 `MeowAPPs/fonts/font.png`;设备旧 `MeowAPPs/fonts/` **保留**(勿删,避免破坏老约定/已有文件),仅新引用一律指向 `MeowOS/fonts/default`。
- **`font.file` 变更即 unload+reload 生效**(设置页回调);拔卡 → 回退固件内置。
- **preset 动态化**:启动/进设置页扫描一次 `MeowOS/fonts/*/`,重建「字体文件」下拉(默认字体 + ≤16 套卡内字体;上限防爆)。扫描仅此二时机,勿放热路径。
- **MeowPanel 预留**:`meow_font_import_zip()`/`meow_font_export_zip()` 为 TODO 声明(不实现),供 MeowPanel 后续接入(`.zip` 导入校验→解压到 `MeowOS/fonts/<family>/`、导出打包)。
- **多字体(M2.5x,`display.multi_font`)**:按字符类别(CJK/CJK_SYM/NUM/LATIN/LATIN_SYM/OTHER)逐字符路由,每类可各选一套字库(`font.class_*`,默认空=跟随全局 `font.file`);同 family 去重、同时装载不同字体 ≤4 套(超出 WARN「过多不同字体会增内存」并截断);开关关 = 单字体(现状)。详见 §5.7.7「多字体」。
- **字体档位 / 大字库(M2.5x)**:抽象出**字库大小档位**,让系统/应用/设置页都知道选的是多大字库 `[源:用户 2026-08-30]`。
- 档位枚举:`MEOW_FONT_TIER_COMMON`(**默认 / ≈4k** 码位)/ `MEOW_FONT_TIER_GBK`(**大 / ≈20k+**)/ `MEOW_FONT_TIER_FULL`(**全 / 可选**,码位/体积最大)。
- `font/gen/gen_font.py` 增 `--charset common|gbk|full` 按档生成 `font.png/font.idx`(现行仅 `--extra` 思路升级为**档位选择**,**本次新增**);每个 `MeowOS/fonts/<family>/font.json` 标 `charset` + `glyph_count`(覆盖声明/信息用)。
- **默认用小字库(`common`≈4k)**;仅当 app 声明需大字库(`app.json "fonts":"full"` 或档位)才为该 app 加载大字库(`gbk`≈20k+),见 §5.7.8。
- **系统设置「加载大字库」开关**(`font.load_full`,强制全系统用大字库),见 SYSTEM_SETTINGS §1;**每个字体选项标注字库大小标记**(如 `default(common≈4k)` / `gbk≈20k` / `full`),让用户知道所选字库量级。
- 判缺字:SDK `meow_font_has_glyph(cp)` 预判当前字库是否含该码位(缺字 → app 回退/提示)。
### 5.3 通知配额/转储
- **每 App 最多 4 类型;每类型活动 ≤4;媒体单例(每 App 仅 1 条,可多 App)**;系统事件抽象为 App(`app_id=system`) 走同一配额 `[NOTIFICATION_SYSTEM §7][meow_ui.h][DEV_NOTES #11]`
- 通知创建 **10s 后自动转储到 TF `MeowOS/notifications/`**(保留最新 10MB ring,不被电源事件清);正常关机先转储再清板载;无卡可运行 `[NOTIFICATION_SYSTEM §8]`
- **通知 TF 转储(定案 #6,M2.5x)**:转储格式 = **appended 日志行**(每条通知一行,CSV 风格:`id,app_id,分类,标题,时间,…`)+ **按总大小滚动截断**(保留最新 **10MB**)。**启动时清板载通知 + 清内存通知表**(开机清残留/内存表);正常关机/重启前**先转储未上卡通知**再清板载(沿用既有规则)`[源:用户 2026-08-30]`
### 5.4 配置版本单点 / 刷新率 / 息屏
- /etc/meowos_version 版本单点(见 §1.1)`[DEV_NOTES #4]`
@@ -175,7 +184,7 @@
- `<pkg>/` = 程序主体+app.json+资源;`MeowData/<pkg>/{data,cache}` = 数据;首次启动自动建 data/cache 并经 env 注入,exFAT 无软链 `[APPS 附录 §1/§2]`
- `.mpk` = tar.gz(app.json + meow 二进制 + 资源),**不含 data/cache**;导入校验 app.json/哈希→解压→数据 init→登入列表 `[APPS 附录 §3]`
- 包管理 **CLI `nyai`**(静态 MIPS,部署 `MeowOS/opt/bin/nyai`):install/remove/list/info/search/index/export/upgrade/scan;源 `MeowOS/opt/nyai/sources.list`;索引 `Packages`(Package/Version/Filename/Size/SHA256/Depends/Description)`[APPS 附录 §5]`
- 应用数上限 **8**(单屏 8 行);扫描深度 1 级;`app.json` 字段:name(仅 ASCII)/exec(静态 MIPS32r2 ELF)/version/author + **`package`(反域名权威 app_id;==目录名;缺省回退目录名)** + 扩展 `framework`/`immersive`/`icon`/`route.<id>`/`awake.<id>`(keep_awake)/`service.<svc>`/`fullscreen`(**未解析**,见矛盾 §A-12) `[APPS §2][MEOW_APP_SDK §9][FRAMEWORK_DESIGN §2][源:审计 2026-08-30]`
- 应用数上限 **8**(单屏 8 行);扫描深度 1 级;`app.json` 字段:name(仅 ASCII)/exec(静态 MIPS32r2 ELF)/version/author + **`package`(反域名权威 app_id;==目录名;缺省回退目录名)** + 扩展 `framework`/`immersive`/`icon`/`route.<id>`/`awake.<id>`(keep_awake)/`service.<svc>`/`fullscreen`(app 级;`route.<id>.fullscreen`=activity 级;**本次实现**:launcher 启动/切 activity 据声明预设 SDK 全屏,见 §5.1/§3.1/§A-12)/`fonts`(字体档位 `"full"|"gbk"|"common"`,需大字库时声明,见 §5.7.8) `[APPS §2][MEOW_APP_SDK §9][FRAMEWORK_DESIGN §2][源:审计 2026-08-30][源:用户 2026-08-30]`
### 5.6 冷启动充电屏
- 触发(**三者同时**):冷启动(`poweroff` 写 `/data/meow_cold_boot=1`;`reboot` 写 0)+ 在充电(AC online=1 或 battery status=Charging)+(开机瞬间一次性快照,判定后不回头)`[CHARGING_SCREEN §0]`
@@ -287,6 +296,12 @@
- **launcher env 注入**(launch_app,app 跟随系统字体):`MEOW_MULTI_FONT=0/1`;`MEOW_FONT_PNG/IDX`(全局,保留);6 类 `MEOW_FONT_CLS_<类>_PNG/IDX`(命中则覆盖全局;类值为空=跟随全局不注入)。SDK `meow_ui_gfx` 读 env 构建同一映射;无 env/关 → 单字体。
- **持久化**:类别字体设置在 settings.conf(板载,无卡也可存),经 `meow_settings_*` 读写,随设置页变更即重配。
- **内存**(推断解码 atlas = `plane_w×plane_h×(depth 4→0.5 / 8→1.0)` 字节;每套另加 glyph 数组 ≈ glyph_count×16B、idx 头保留约 128KB,idx 原始缓冲载毕即释)。实测仓库字库(depth 4):misans(CJK)≈2.44MiB、source_han_sans(CJK)≈2.53MiB、meslo(Latin)≈1.68MiB、google_sans(Latin)≈1.12MiB;按用户估算口径(**depth 8**):CJK ≈ 5-6MB、Latin ≈ 0.3-0.5MB(后者为窄覆盖 Latin 专库)。**典型「1CJK+1Latin」增量**:全局=CJK,另加一套 Latin → 增加 ≈0.3-1.7MB(depth 8 约 0.5MB;实测 depth4 latin 1.1-1.7MB);全局=Latin 另加一套 CJK → 增加 ≈2.4-2.5MB(depth 8 约 5-6MB)。`display.multi_font=0` 时仅全局一套,无任何额外装载。
- **5.7.8 字体档位分层 / 按需大字库(app 声明 + 系统开关)** `[源:用户 2026-08-30]`
- **口径**:默认用**小字库 `common`(≈4k 码位)**;当 app 声明需要**大字库**(如小说阅读器,`app.json` 声明 `"fonts":"full"` 或档位 `"gbk"`/`"common"`)时,才为该 app 加载**大字库 `gbk`(≈20k+)**。档位与 `gen_font.py --charset`、`font.json charset/glyph_count` 见 §5.2「字体档位/大字库」。
- **app 级 / activity 级**:app 级以 `app.json "fonts":"<tier>"` 声明;activity 级(如需)以 `route.<id>.fonts` 声明(沿用 `route.<id>` 扩展口径)。launcher 启动 app/切 activity 时据声明选加载大/小字库,并经 env 注入(`MEOW_FONT_PNG/IDX` 指向所选档位字库;新增 `MEOW_FONT_TIER` 标注档位)。
- **系统设置「加载大字库」**(`font.load_full`,默认 0):开 → **强制全系统用大字库(gbk 档)**,覆盖 app 未声明 + 覆盖默认 `font.file`;关(默认)→ 默认小字库,app 声明才大字库。
- **SDK 判缺字**:`meow_font_has_glyph(cp)` 预判当前字库是否含该码位 → app 据此决定回退/提示(避免 `common` 小字库下静默豆腐或缺字)。
- **⚠️ 与 §5.7.3 冲突**:§5.7.3 `"fonts":[<handle>…]` 为**应用自带字库句柄数组**;本小节 `"fonts":"full"` 为**字库档位字符串**。同名键两种语义,需统一解析口径(见 §7 A-14)。
---
@@ -310,5 +325,7 @@
- **A-9 SDK 通知转储**:NOTIFICATION_SYSTEM §8「创建 10s 后自动转储到 TF」;meow_ui.h 现仅「活动表+meow_log 打日志,真实投递 UI/D-Bus 为后续」。→ 10s 转储/TF 尚未实现,属"已定未做"。
- **A-10 版本来源细解**:DEV_NOTES #4「/etc/meowos_version 唯一来源;MEOWOS_VERSION 宏仅 dev 占位永不动」;APPS.md §4.6「MEOWOS_VERSION 宏=单一来源,build 时 sed 写入 etc/meowos_version」。→ 两者都强调"写入同源",但"谁是源头"措辞矛盾;实践上 build 脚本 echo 生成 /etc/meowos_version,宏作屏显 dev 占位。
- **A-11 `MeowOS/opt/` vs `MeowOpt/`**:§1.2 树中 `MeowOS/opt/{bin,nyai,sources.list},lib/,tools/`(nyai 包管 + 工具)与新增顶层 `MeowOpt/`(板载外部工具/二进制,如 mdnsd)并存,命名仅大小写之差、语义可能重叠。→ **两者是否为同一用途/是否需归并待确认**;当前按各自文档记录,勿混用。
- **A-12 `fullscreen` 字段未解析**:§5.5 与 MEOW_APP_SDK §9 将 `fullscreen` 列为 app.json 字段,但 `meow_parse_app_json()` **并未读取该键**(实现只解析 name/exec/icon/package/framework/immersive/route./awake./service.)。→ 文档与实现不一致,属"已定未做";若要用需在解析器补读并处理。
- **A-12 `fullscreen` 字段(已定 → 本次实现)**:§5.5 与 MEOW_APP_SDK §9 将 `fullscreen` 列为 app.json 字段,但 `meow_parse_app_json()` **此前并未读取该键**(实现只解析 name/exec/icon/package/framework/immersive/route./awake./service.),属"已定未做"。→ **本次实现**:launcher 启动 app/切 activity 据 `app.json fullscreen`/`route.<id>.fullscreen` 预设 SDK 全屏(env `MEOW_FULLSCREEN`),见 §5.1/§3.1。注意全屏语义由「隐藏状态栏+隐藏返回键」细化为「状态栏收合至提示线 + 保留左缘返回+顶部提示线+下滑通知中心(热区缩小)」(见 A-13)。
- **A-13 全屏语义细化(状态栏「隐藏」→「收合至提示线」)**:既有 §3.1/§5.1 描述全屏=隐藏状态栏(`meow_ui_statusbar_height()`=0、隐藏返回键=沉浸);本次定案细化为**进入/退出全屏:状态栏向上收出屏顶、只留一条提示线高度**,**全屏下保留**左缘返回手势 + 顶部动态伸缩提示线,且**顶部下滑仍可开通知中心(顶部热区缩小)**。→ 需在 SDK 端明确「收合(collapsed)」状态(新增 `meow_ui_statusbar_collapsed()` 等)与「隐藏」的差异,UI 依此绘制提示线。
- **A-14 `fonts` 键二义**:§5.7.3 `"fonts":[<handle>…]`=应用自带字库句柄数组;§5.2/§5.7.8 `"fonts":"full"|"gbk"|"common"`=字库档位字符串。→ 同名键两种语义,解析器需区分(字符串→档位 / 数组→句柄);若避免歧义可改用专键如 `"font_tier"`(**未拍板**)。
`[各源标注见上]`