# MeowOS 核心规范速查(MEOWOS_SPEC_REF) > 单一速查来源。常量/路径**照抄原文**;矛盾处单列「已知矛盾/待确认」。 > 各条末尾 `[源:XX.md]` 标注出处。 --- ## 1. 文件系统路径 ### 1.1 板载(NAND rootfs / /data) - 设置持久化:**板载** `/usr/data/meow/settings.conf`(UBIFS,小文件 <10KB,跨换卡保留)`[SYSTEM_SETTINGS §2][MEOWOS_API §3]` - **板载服务目录**:`/usr/data/meow/services.d/.conf`(M2.54,Data 区,恒定存在、权威优先;首启由 `S89meow_svcd` 预置 `mdnsd.conf`)。与 TF `MeowOS/services.d/` 双源,同名板载优先 + WARN;板载 `trigger=boot` 服务不依赖卡(拔卡保留)`[meow_svcd.md][meow_svcd.c]` - **主机名**:设置键 `system.hostname`(SET_STR,默认 `meowos`;RFC1035 首标签),`S89meow_svcd` 开机读 settings `sethostname`;供自研 mDNS 应答器公布 `.local` `[SYSTEM_SETTINGS §1][mips-repo/bins/meow_mdns]` - `/etc/meowos_version`:版本唯一来源(launcher 运行时 `load_meowos_version` 读;`MEOWOS_VERSION` 宏仅作 dev 占位兜底)`[DEV_NOTES #4]` - **`/data/meow_boot_default`:开机默认权威标记(O_TRUNC 单值:`0`=MeowOS / `1`=HiByOS)**。由 launcher `meow_settings_save()` 在保存 `boot.default` 时同步写;bootmenu `set_boot_default_meow()`(写 0)/ launcher `set_boot_default_hiby()`(写 1)同文件同语义;bootmenu 开机读它定默认;init 读入不触发、不反向覆盖;`meow.conf` 不再承担 boot_default `[M2.61 同步修复][README][meow_settings.c][meow_bootmenu.c]` - `/tmp`:tmpfs,开机清空;开机模式标记 `/tmp/meow_boot_mode`、电源菜单 `/tmp/meow_power_menu{,_active}`、app 沉浸 `/tmp/meowapp_state` `[BOOT_SELECTOR §1][KEY_CONTROL §9][APPS §3.5]` - 日志启动缓冲 `/tmp/meow_boot.log`(256KB 滚动,卡出现后自动迁卡)`[APPS §4.5]` - IPC socket:`/usr/data/meow_ipc.sock`(AF_UNIX SOCK_STREAM,0666,backlog 4)`[FRAMEWORK_DESIGN §1][WORK_STATE]` - seccomp/分区(勿写):mtd0=uboot mtd1=kernel mtd2=rootfs mtd3=kernel2 mtd4=rootfs2 mtd5=ota(8M 标记) mtd6=userdata `[WORK_STATE]` ### 1.2 TF 卡(挂载点 `/usr/data/mnt/sd_0`,exFAT) ``` /usr/data/mnt/sd_0/ ├── Music/ # 播放器标准索引目录 ├── MeowData//{data,cache} # 应用专属数据(exFAT 无软链,用 env 注入) ├── MeowAPPs/ # 应用(=app.json.package=目录名;app.json+二进制+资源, fonts/, backgrounds/;日志已入 MeowOS/logs[源:审计 2026-08-30]) └── MeowOS/ # MeowOS 专属(一切非必要文件;**MeowOpt 已废弃并入此处的 opt/**) ├── backups/settings/setting.bak # 设置导出默认路径 ├── services.d/ # 服务配置(meow_svcd 的 .conf;TF 源,与板载 /usr/data/meow/services.d 双源,同名板载优先)`[meow_svcd.md]` ├── fonts/// # 多字体库(每 / 一套三件套;见 §5.2) │ ├── font.png # 预渲染灰度 PNG(bit depth 4|8,gen/gen_font.py 产物) │ ├── font.idx # 索引(MFNI v2,gen/gen_font.py 产物) │ └── font.json # 元数据 + sha256 完整性校验(schema 见 §5.2;含 weight+charset+glyph_count) ├── config/fonts/index # 字体列表索引(M2.58:CSV family,weight,path,label,tier,glyph_count;见 §5.7) ├── logs/ # 系统日志 meow_.log + apps/...(见 §3 日志) ├── notifications/(转储区,保留最新 10MB,不被电源事件清;文件 = notifications.log,appended CSV 行) ├── opt/{bin,nyai,sources.list}, lib/, tools/ # 外围工具/二进制(MeowOpt 已废弃并入;mDNS 自研 meow_mdns 在固件,不入此) └── themes/charging// # 充电屏主题(theme.json manifest) ``` `[TF_CARD_LAYOUT §1][APPS 附录][NOTIFICATION_SYSTEM §5]` - 环境注入(launcher 每次启动 app 前):`MEOW_DATA_DIR`/`MEOW_CACHE_DIR`/`MEOW_LOG_DIR`/`MEOW_LOG_APP`(app_id=package)/`MEOW_LOG_LEVEL`/`MEOW_ACTIVITY`/`MEOW_CHAIN`;XDG:`XDG_DATA_HOME`/`XDG_CACHE_HOME`/`XDG_CONFIG_HOME`(=MeowData//{data,cache,config})`[APPS 附录 §2][FRAMEWORK_DESIGN 附录 D2]` - **升级/刷机契约**:升级镜像 = 卡根固定名 **`r3proii.upt`**(`build_fw_apps*.sh` 打包);升级模式=uboot 读 mtd5=`ota:kernel2` 引导 kernel2 自动刷(非传统 UI 升级按钮);failsafe(关机按住 音量加+电源)从卡根 `r3proii.upt` 升级;**`/data/recovery_all`=恢复出厂,危险勿触发**(调试/部署前必须 `rm -f /data/recovery_all`;发现即删+告警——highest-priority 红线)。刷 rootfs 分区不丢卡数据 `[WORK_STATE][APPS §1.3/§6]` ### 1.3 板载 vs TF 划分原则(拔卡降级) - 板载只放**稳定框架+KB 级设置**;日志/字库/媒体等大件一律 TF 卡 `[TF_CARD_LAYOUT §0][SYSTEM_SETTINGS §2]` - 拔卡:launcher/bootmenu/SSH 不死;应用列表"未插卡"、日志回退内存环、字体回退点阵、opt 不可用——均优雅降级 `[TF_CARD_LAYOUT §3]` - 关键配置优先板载(无卡系统能跑);转储/日志可降级 → 卡,无卡 /tmp 回退 `[DEV_NOTES #7]` - **服务配置双源(M2.54)**:板载 `/usr/data/meow/services.d/` + TF `MeowOS/services.d/`,板载优先;板载服务(`trigger=boot`)随 Data 区恒定存在,拔卡不丢(mDNS 应答器托管于此)`[meow_svcd.md]` - rootfs 体积上限:**45,088,768 B(≈45MB)**,回验 0 diff `[BOOT_SELECTOR §1][APPS §6]` --- ## 2. IPC / 接口 ### 2.1 launcher↔app env 注入 `MEOW_LOG_DIR`(卡日志目录,无卡不设)/`MEOW_LOG_APP`(app_id=app.json.package,缺省回退目录名)/`MEOW_LOG_LEVEL`(本 app 级别,系统下发)/`MEOW_ACTIVITY`/`MEOW_CHAIN`;;...; `[APPS §3.5][APP_LOG_MANAGER §3][FRAMEWORK_DESIGN §3]` ### 2.2 meow_ipc 消息协议(AF_UNIX,全小端 LE) - 帧头 16B:`magic=0x4D4F5701`('MEOW'|1)/`version=1`/`type`/`req_id`/`len`;`len` 上限 **MEOW_IPC_MAX=4096**;列表编码 `[u16 count]`+NUL 串 `[FRAMEWORK_DESIGN §1]` - 消息类型:`MSG_HELLO 0x0001↑ / ACK 0x0002↓ / ERR 0x0003↓ / REGISTER 0x0010↑ / SERVICE_OK 0x0011↓ / SERVICE_STOP 0x0012↑ / MSG_NOTIFY 0x0020↑ / NOTIFY_ACK 0x0021↓ / NOTIFY_DISMISS 0x0022↑ / NOTIFY_LIST 0x0023↓ / ACT_DECLARE 0x0030↑ / ACT_QUERY 0x0031↑ / ACT_RESULT 0x0032↓ / NAV 0x0040↑ / SHOW_ACTIVITY 0x0041↓ / SYS 0x00F0↓` `[FRAMEWORK_DESIGN §1]` - 媒体:`MSG_META`(元数据)、`MSG_PLAYCTL`(cmd 1=播放2=暂停3=上一首4=下一首5=seek)、`MSG_PROGRESS` `[附录 B]` - IPC 线程**只读帧+解析+入队**;状态变更主循环单写者(eventfd 唤醒,10ms 热键轮询非阻塞排空)`[FRAMEWORK_DESIGN §0][§6]` ### 2.3 watchdog / supervisor 信号 - 应用返回键=**SIGTERM**(1s 后 SIGKILL 兜底);**SIGUSR1 仅**=沉浸左缘滑动手势,不是返回键 `[APPS §3.5]` - 强杀兜底:应用卡死 = 音量减连按 3 次(间隔 权威签名 = `patch_v2/sdk/meow_ui.h`;MEOW_APP_SDK.md §3-§8 为设计蓝本。 ### 3.1 关键常量 - 屏幕:**480×720**,24-bit RGB(`0xRRGGBB`),内部转 RGB565;文本字号 28(标题/状态栏)/20(正文/按钮) `[MEOW_APP_SDK §2]` - keycode:POWER=116/VOLUMEDOWN=114/VOLUMEUP=115/PLAYPAUSE=164/PREVIOUS=19(注释标 KEY_PREVIOUSSONG,**有疑**)/NEXT=163 `[meow_ui.h][KEY_CONTROL 注:165 才是 prevsong]` - 事件:`on_key(code,is_down)/on_tap(x,y)/on_swipe(dir,dx,dy)/on_tick/on_swipe_progress(x_start,dx)`;`MEOW_SWIPE_LEFT=0/RIGHT=1/UP=2/DOWN=3` `[meow_ui.h]` - 主题:`MEOW_THEME_LIGHT/DARK/AUTO`;`meow_theme{bg,fg,accent,dim,font_title=28,font_body=20}` `[meow_ui.h]` - 控件:`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..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。 ### 3.2 render/控件/图片/输入/IME 签名(关键) - `meow_ui_init(const meow_ui_opts*)`(opts.width/height,0=自动读 fb)/`meow_ui_shutdown`/`meow_ui_width`(480)/`meow_ui_height`(720) - 绘制:`meow_ui_clear/put_px/fill_rect/draw_rect/draw_rect_round/fill_rect_alpha(color,alpha 0-255)/flush/flush_region` - 文本:`meow_ui_text/text_right/text_center(x,y,utf8,size,color)/text_width/text_height` - 图片:`meow_img_load_file/mem/free/w/h`/`meow_ui_img/scaled/alpha/cover`(stb_image 解 PNG/JPEG/BMP,最近邻缩放,`cover`=居中裁方) - 控件:`meow_btn_create/slider_create/switch_create/list_create(count,src,ctx)/widget_free/draw/hit`;`meow_slider_set/get`、`meow_switch_set/get`、`meow_btn_pressed` - IME:`MEOW_IME_ASCII/NUM`;`meow_ime_ctx{mode,buf[256],maxlen,on_change,ctx}`;`meow_ui_text_input`(阻塞)/`_async`/`meow_ime_active`/`meow_ime_text`(仅英文/数字 ASCII;键盘占底 ~300px) - 生命周期:`meow_ui_run(&ev)`(阻塞)/`meow_ui_request_exit()`;`meow_ui_time_ms()`(单调 ms) ### 3.3 实现定案(相对设计稿)`[MEOW_APP_SDK §12][meow_ui.h]` - [D1] `meow_ui_opts` 补 width/height;[D2] `meow_list_source` 定案签名;[D3] 内部 `meow_gfx_fill_round/blit_rgba/mark_dirty`(非公共);[D4] 新增 `meow_theme_defaults(mode)`/`meow_theme_current()`;[D5] `on_swipe_progress`+`meow_ui_swipe_hint(x)`+内部 `MEOW_EV_SWIPE_PROGRESS`/`meow_input_inject`;[D6] 状态栏高=40(后续用户定 40→28);[D7] 音量源=settings.conf `audio.volume`;[D8] 蓝牙读 `hciconfig` 30s 缓存;[D9] 状态读取器跑在 `meow_ui_run` 1s 节流(无独立线程);[D10] 全局返回默认语义="APP 未注册 on_swipe 时 SDK 默认退出;已注册交 APP" - **构建取向(已知设计,非缺陷)**:`build_sdk.sh` 用 `-I../meow_launcherd` 引 `meow_ipc.h`(`meow_notify_ipc.c` 复用共享协议头),故 SDK 编译期依赖 launcher 头、**非独立库**;**运行时无碍** —— App 只链 `meow_ui.a`(含 meow_font.o),不会链入 launcher 符号。SDK 编译依赖 launcher 头属已知设计,勿当作耦合错误。 ### 3.4 SDK 统一控件库 + 主题增强(M2.70/M2.71 落地)`[MEOW_APP_SDK §5.8/§8.1][meow_ui.h][meow_ui_widget.c]` > 定位:把 §5(最小控件集)与设计模板(§5.2-§5.7)收敛到**统一控件架构**;实现分两批(§5.8.8)。 - **第一批 = 通用基座(M2.70/0.7.65)**:`meow_widget` 基座统一标准控件/自定义画布;`meow_widget_opts`(Modifier 式 Options,`meow_widget_set_opts`/`meow_widget_opts_get`,0/-1 用默认);统一状态机 `MEOW_WS_ENABLED/SELECTED/FOCUSED/PRESSED`(`meow_widget_set_state`/`meow_widget_state`/`meow_widget_enabled`/`selected`);`meow_widget_custom_create`(自定义画布,App 给 render/hit 回调,`W_CUSTOM`);布局 `meow_row/column/box`+`meow_layout_add/arrange`+`spacer`;MD3 语义色板(§5.8.4)+ 主题接口 `meow_ui_set_style`(`MEOW_STYLE_MD3/MIUIX`)`/meow_theme_get`。 - **第二批 = Material 组件子集(M2.71/0.7.66)**:`meow_btn_create_variant`(五型)/`meow_textfield_create`(IME)/`meow_card_create`/`meow_divider_create`/`meow_badge_create`/`meow_checkbox_create`/`meow_radio_create`/`meow_progress_create`/`meow_progress_circular_create`/`meow_fab_create`/`meow_topappbar_create`/`meow_navigationbar_create`/`meow_tabbar_create`/`meow_lazycolumn_create`/`meow_lazyrow_create`/`meow_dialog_create`/`meow_sheet_create`。 - **兼容**:既有 `meow_btn/slider/switch/list_create` 签名一字不改(Options/状态机走新增挂载器);`meow_ui_theme`/`meow_widget` 结构变化 = **`meow_ui.a` ABI 变化** → 需同步重编 hello(§5.8.8)。 - **主题增强(§8.1)**:主题 = **顶级风格族 `ui.style`(md3/miuix)× 明暗 `display.theme`(dark/light)** 共同决定「整套配色+控件形态+背景底」;`display.background` 为「style×mode」派生的**可选背景底选项集**(非独立维度);状态栏图标随 `ui.style` 换集。⚠️ **`miui`/`miuix` 命名待定案(保留,勿拍板)**:`MEOW_APP_SDK §8.1` 用 `miuix`;`SYSTEM_SETTINGS §1` 注明 `meow_settings.c g_defs` 现值 `"md3,miui"`(label "Material You,MIUI"),实现时把 `g_defs` 的 `miui` 对齐为 `miuix`(**MIUIx 未实现,当前仅 md3 生效**)。 --- ## 4. SDK 之外系统组件 - **系统进程 supervisor 树(源:2026-08-30 定案;M2.71 已落地 `meow_sysui`)**:`meow_sysui`(`patch_v2/meow_sysui/meow_sysui.c`,~113KB;`etc/init.d/S70meow_sysui` 开机拉起,早于 S89)监管系统进程,**一个崩→只拉起它,绝不级联**;`meow_launcherd`=系统 UI 渲染宿主(状态栏/通知中心/电源菜单/全局手势,与 APP 进程独立);`meow_svcd`=服务管理器(服务全子进程化,svcd 自身不死);APP 进程只渲染自己内容,崩不连累系统 UI。**系统组件渲染归系统进程(launcher),APP 进程不渲染系统 UI**(SDK 系统组件 API 仅系统进程可链,App 不可自建悬浮层);通知中心 UI 渲染主体=系统进程,数据经 IPC 从通知存储读。现网(bootmenu execv launcher + S89 svcd 自启)→ 定案(sysui 统一监管)为渐进迁移,属系统基建线。**sysui 当前默认只监护 `meow_svcd`**(`/usr/data/meow/sysui.d/.conf`,目录式复用 services.d 语义;launcher 由 S90meow_bootmenu 的 execv 拥有,登记但 `enabled=0` 防双重拉起;mdns 是 svcd 服务子进程,不双重管理)。`[FRAMEWORK_DESIGN §10][MEOW_APP_SDK §6.1][NOTIFICATION_SYSTEM §9][patch_v2/meow_sysui/meow_sysui.md]` - **专项子服务(一期在跑,规划见 `devdocs/plan/SYSTEM_FRAMEWORK_SERVICES.md`)**:两个 **svcd 托管、板载 `trigger=boot`** 的专项子服务——`meow_svc_perf`(性能/系统只读聚合)、`meow_svc_power`(关机/重启/升级/回 HiBy 系统动作)。launcher 电源菜单与 MeowPanel 均改经这些服务 IPC 触发(不再直连 `sys_do_reboot`/爬 `/proc`)。**电源 CLI `meow_svc_power `**(root 免鉴权、单一命令、不覆盖系统 shutdown/reboot):`shutdown`/`reboot`(强制回 MeowOS)/`upgrade`(写 mtd5=`ota:kernel2`)/`set-default-hiby`/`reboot --hiby` + `status`/`screen`/`dac`/`battery`/`reboot-reason`/`upgrade-status`。**二期**:关键 IPC 只接受 **`os.meow.*`** 鉴权 + `.mpk` 打包签名验签(解包验签/导出保留签名)。`[SYSTEM_FRAMEWORK_SERVICES][APPS 附录 §3]` - 通知(SDK `meow_notify_*`,M2.53 最小版 `[meow_ui.h §9.1]`): - 常量:`MEOW_NOTIFY_MAX_TYPES=4`/`MEOW_NOTIFY_MAX_PER_TYPE=4`/`MEOW_NOTIFY_MAX_MEDIA=1`/`MEOW_NOTIFY_TIMEOUT_ONGOING=-1`/`MEOW_NOTIFY_TIMEOUT_NEVER=0` - 分类:`CAT_GENERAL/MESSAGE/EMAIL/EVENT/PROGRESS/MEDIA(=5)/COUNT`;紧急度 `URG_LOW/NORMAL/HIGH/CRITICAL` - `meow_notify_register_type(cat)`/`meow_notify_send(const meow_notify*)`(返回 id)/`meow_notify_cancel(id)`/`meow_notify_active_count`/`count_in_type`/`has_active`/`urgency_str`/`category_str` - **本阶段落点=SDK 内部活动表 + meow_log() 打日志**;真实投递通知中心 UI / D-Bus 是后续任务 `[meow_ui.h 注释]` - `meow_config_*`(app 配置读写,走 meow_settings 后端)——**SDK 缺失清单第 3,未定** `[WORK_STATE]` - `meow_media_*`(媒体会话)——**依赖阶段 D 落地,未定** `[WORK_STATE]` - 崩溃捕获/看门狗——**规划中未定** `[WORK_STATE SDK 缺失清单 #5]` - `meow_notify_dbus`(org.freedesktop.Notifications 桥)——**已定,待实现** `[FRAMEWORK_DESIGN 附录 C]` - **meow_svcd 服务管理器**(`patch_v2/meow_svcd/`,mipsel 静态 ~101KB 进固件,不入卡)`[meow_svcd.md]`: - 类 systemd/systemctl。**已接入系统启动链(M2.54)**:固件 `etc/init.d/S89meow_svcd` 开机自启(`-f` 前台 + 重挂循环,失败不死;置于 S84ssh 之后、S90meow_bootmenu 之前——因 S90 exec 引导选单阻塞 rcS)。由 bootmenu/launcher `fork/exec` + `waitpid` 托管仍为备选。 - **双源 services.d**(板载优先):板载 `/usr/data/meow/services.d/.conf` + TF **`MeowOS/services.d/.conf`**,两处都读;同名服务板载优先(TF 同名跳过 + WARN「 板载与 TF 都存在,采用板载」)。目录式 `key=value`,未知键忽略/前向兼容:`exec`(必填)/`args`/`env`/`enabled`(0=永不自动启动,默认0)/`restart`(`always`/`on-fail`/`never`,默认on-fail)/`backoff_ms`(默认1000)/`max_restart`(默认5)/`cap`(本阶段仅解析不实装)/`trigger`(`boot`/`card-mount`/`wifi-up`,默认card-mount)。 - **板载-trigger=boot 语义**:板载服务恒定存在,boot 触发不依赖卡(拔卡保留);TF 服务 boot 仍需卡。 - **服务目录规则**:**固件工具**→板载 `/usr/data/meow/services.d/.conf`(Data 区,拔卡保留);**TF 工具/第三方**→TF `MeowOS/services.d/.conf`(随卡存在/消失);**双源板载优先**(TF 同名被板载屏蔽 + WARN「 板载与 TF 都存在,采用板载」)。 - 崩溃隔离:服务=svcd **独立子进程**(`fork+execv`),svcd 只 `waitpid`/`SIGCHLD` 感知;服务死不影响 svcd/supervisor;重启受 `backoff_ms` 退避防热循环。 - 状态机:`DISABLED/STOPPED/RUNNING/STOPPING/FAILED`;稳定运行 30s 清零 restart_count。CLI(systemctl 式,SSH 直呼):`status/reload/start|stop|restart /pid`,示例 `meow_svcd status`/`meow_svcd restart mdnsd`/`meow_svcd stop all`/`meow_svcd reload`;控制走 AF_UNIX 单行文本 `/tmp/meow_svcd.sock`;守护默认后台,`-f/--foreground` 前台供 supervisor 托管。 - **卡上外部工具 = `MeowOS/opt/`**(`{bin,nyai,sources.list}, lib/, tools/`):MeowOS 启动时从卡加载,拔卡降级不崩。**`MeowOpt` 已废弃并入此处**;mDNS 已改为自研 `meow_mdns`(固件 `/usr/bin`),不再放卡。`[DEV_NOTES][meow_svcd.md]`。 - **mDNS 应答器 = `meow_mdns`(自研,已拍板替代完整 mdnsd)**:`mips-repo/bins/meow_mdns/`,**IPv4-only**(内核无 IPv6,完整 mDNSResponder/SAResponder 均 `socket(AF_INET6)` 失败),mipsel 静态 ~79KB(md5 b23de7ce)。**进固件 `/usr/bin/meow_mdns`**(不入卡),由 meow_svcd 托管(板载 `/usr/data/meow/services.d/mdnsd.conf`,`trigger=boot`、root 即可绑 5353/组播,`cap=` 空)。功能:join `224.0.0.251:5353`,应答 `.local` A(wlan0 IPv4)/`_ssh._tcp` PTR/SRV/TXT/`_services._dns-sd` PTR;支持 `MEOW_MDNS_HOST`/`_ADDR`/`_PORT`/`_TTL`/`_CF`/`_QD`/`_MCAST`/`_MIF`/`_DBG`。⚠️ **手机热点隔离**:设备→主机组播被热点丢弃,avahi 只收组播应答 → 该热点下 `avahi-resolve .local` 超时(网络层限制,非应答器缺陷),主机需 DNS 兜底 `[mips-repo/bins/meow_mdns/manifest.md][meow_svcd.md]`。 - `meow_settings_*`(设置后端,已定)/`meowcli`/`meow_sys_devattr`/`meow_devattr_set` `[MEOWOS_API]` - 后台权限:`MSG_HELLO/MSG_REGISTER.flags` 扩展 `MF_BACKGROUND`/`MF_PLAYBACK`;`PERF_BACKGROUND`/`PERF_AUDIO_BACKGROUND`(规划)`[FRAMEWORK_DESIGN 附录 A]` --- ## 5. 关键约定 & 约束 ### 5.1 按键/手势/状态栏/全屏 - 按键全局接管(除电源菜单),见 §2.4 `[APPS §3.4.1]` - **左缘返回手势**:手指从**屏幕左缘 ≤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.66 收敛,「同一个状态栏」正确闭环)**:状态栏是**某一个渲染主体**(系统进程 launcher)——主界面与 App 前台用**同一个**状态栏实例,**App 进程不渲染、不自绘、不叠加**(§10.2/@`FRAMEWORK_DESIGN §10.2`);App 前台时状态栏作为**系统叠加层**盖在内容之上(复用 fb 双缓冲备份/恢复/pan);**数据源唯一由 launcher 统一喂/取**(时间/电量/WiFi/音量/亮度)→ 两边必然一致(根治 M2.66「桌面有亮度、App 没有」的不一致)。右侧为 **MD3 图标 + 变量值**(随 `ui.style` 换图标集)。**全屏收合**:状态栏向上收出屏顶、只留提示线,**顶部保留热区**(仍可下滑通知中心)+ 左缘指示条(见 §3.1/A-13/§5.1)。`[FRAMEWORK_DESIGN §10.2]` - **全屏机制(M2.5x,`app.json fullscreen` 即 app 级 + `route..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]` - **横向分页设计模板(M2.5x 预留,见 `MEOW_APP_SDK.md` §5.2)**:主页/子页多页横向滑动复用的设计模板(参照 HibyOS 播放器主页横划进播放页)。与左缘返回/顶部下滑**按起始位置分流**互斥——左缘 ≤热区→**左滑返回**(§5.1);中部左/右滑→**页切换**;顶部下滑→**通知中心**。实现要点:相邻页各预渲染一张快照、切换只 blit 快照 + 跟手平移/吸附(vsync ≤60 帧、零 UI 重算)。**注**:模板 API 为「草案/待定案」,当前未实现 `[源:2026-08-30]` - **SDK 可复用设计模板清单(M2.5x 预留,见 `MEOW_APP_SDK.md` §5.3)**:把反复出现的界面结构抽象为可复用设计模板——①**分组设置表单** ②**列表+选择** ③**弹窗/对话框** ④**顶/底下拉面板**(A+B 先行,已展开 §5.4-§5.7)+ 媒体播放/沉浸/加载(C)、卡片/导航/列表项(D,随 app/MD3 细化)、拖拽排序/长按菜单/时间轴(E,后置),共 11 项;横向分页另见 §5.2。**所有模板与既有手势约定一致**:左缘返回 + 顶部滑条 + 状态栏收合 + 通知中心热区(本 §5.1/§3.1/A-13)——模板只在内部做命中分流,**不重定义全局手势**;顶部/底部面板与左缘返回/通知中心按起始位置与触达途径分流互斥(快捷设置触达途径为**待定案**)。**注**:A①②/B③④ 模板 API 均为「草案/待定案」,当前未实现 `[源:2026-08-30]` ### 5.2 主题 - **日/夜/自动**:SDK `meow_theme` 内置 `meow_theme_light/dark`;模式键 `display.theme_mode`(SYSTEM_SETTINGS 记为 `manual`/`auto`——**与 SDK 枚举 light/dark/auto 冲突**,见 §A);AUTO 判时段 `[SYSTEM_SETTINGS §1][MEOW_APP_SDK §8]` - 背景图系统:`display.bg_mode`(color/image)/`display.bg_dark_color`/`display.bg_light_color`/`display.bg_image`/`display.bg_image_dark`/`bg_image_light`/`display.bg_overlay_alpha`(0-255 默认 ~120);图片目录 **`MeowData/backgrounds/`**(480×720 约束);叠加层颜色随主题(深=黑叠/白=白叠)`[MAIN_MD3_PLAN §6][DEV_NOTES #12/#13]` - 主界面背景:深色用 background(可选色)、浅色用 surface(白) `[DEV_NOTES #13]` - **TF 卡多字体库(M2.5x)+ 字重结构(M2.6)**: - 目录 **`<卡根>/MeowOS/fonts///`**(每 `/` 一套,如 `misans/regular`),内含三件套:`font.png`(预渲染灰度 PNG,bit depth 4|8)+ `font.idx`(MFNI v2 索引),二者均由 `font/gen/gen_font.py` 生成;`font.json` 为元数据+完整性校验。**缺任一件 → 该套不进列表 + 日志**。 - **font.json schema(定版)**:`family`(同目录名,信息用)/`name`(下拉显示名,缺则回退目录名)/`weight`(`regular|bold|italic|…`,字重 slug,缺省 `regular`;对应 `//` 目录第二级)/`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/regular/font.png`)指向的字体**存在且能 load → 用它**;否则回退卡默认 `MeowOS/fonts/default/regular/font.png` → 固件 `/usr/share/meowos/font/font.png`。相对路径按卡根 `/usr/data/mnt/sd_0/` 解析。全失败 → 字库不可用,`ui_draw` 回退 5x7 点阵(系统不死)。 - **默认字库目录**:默认字体统一放 **`<卡根>/MeowOS/fonts/default/regular/`**(`font.png`+`font.idx`,可选 `font.json`),不再用 `MeowAPPs/fonts/font.png`;设备旧 `MeowAPPs/fonts/` 及旧 `MeowOS/fonts//`(无 weight 级)**保留**(勿删,避免破坏老约定/已有文件),仅新引用一律指向 `MeowOS/fonts/default/regular`。 - **`font.file` 变更即 unload+reload 生效**(设置页回调);拔卡 → 回退固件内置。 - **preset 动态化(两级扫描)**:启动/进设置页扫描一次 `MeowOS/fonts///`,重建「字体文件」下拉(默认字体 + ≤16 套卡内 /;上限防爆)。扫描仅此二时机,勿放热路径。**存量卡片迁移**:旧版扫 `MeowOS/fonts//`(图片直接在该层);迁移到 `/regular/` 后,旧 `/` 下不再有三件套 → 新扫默认按两级找,故若未重做成 `//` 则扫不到(需先用 mv 迁成 `//` 再重扫)。 - **MeowPanel 预留**:`meow_font_import_zip()`/`meow_font_export_zip()` 为 TODO 声明(不实现),供 MeowPanel 后续接入(`.zip` 导入校验→解压到 `MeowOS/fonts///`、导出打包)。 - **多字体(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 [--weight ]` 按档生成 `font.png/font.idx/font.json`(**已实现**,现行仅 `--extra` 思路升级为**档位选择**;M2.6 加 `--weight` 写 `font.json.weight`,缺省 `regular`);每个 `MeowOS/fonts///font.json` 标 `weight`+`charset` + `glyph_count`(覆盖声明/信息用,launcher/settings 据此标注与按需装载)。 - **默认用小字库(`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]` - **通知模型补全(2026-08-30 用户定案,全链路 SDK→IPC→存储→dump)**: - 字段:SDK `meow_notify` / IPC `m_notify_t` / 存储 `meow_notif_t` 全链路补 **`urgency`(0-3,缺省 NORMAL)**、**`icon`(name/path,NULL/空 → 用该 app 默认图标,launcher 按 app_id 回退 app.json 的 icon;每条可独立指定)**;`progress` 已有(0-100,-1=无)。 - 实时进度:`meow_notify_update_progress(local_id, progress)`(SDK)→ IPC `MSG_NOTIFY_PROGRESS(0x0024)` → launcher 只改**内存活跃槽**(不落盘)。 - **里程碑落盘**:TF 快照只在**创建时 + 结束(100% 或 dismiss)** 触发(沿用 `meow_notif_dump_tf`,progress 写当时值);实时进度**不每帧落盘**。 - **CSV 列**(`meow_notif_dump_tf`/`tf_line`):`timestamp,id,app_id,app_icon,category,urgency,progress,title,body,target_activity,ongoing,media,dismissed`。 - 说明:旧调用(无 urgency/progress/icon)兼容——urgency 缺省 NORMAL、progress=-1、icon=NULL→app 图标。`[源:用户 2026-08-30]` - **⑥ 通知中心快捷 chip + 勿扰面板内开关(launcher 侧,M2.64)**:快捷行 **5 chip**(WiFi/蓝牙/主题/亮度/**电源菜单**——第 5 个 chip 点击唤起既有系统电源菜单 `show_power_menu`,真弹对话框);**勿扰不做 chip**,改**面板内开关**(列表上方小 toggle),开=只显示 `urgency>=2`(HIGH/CRITICAL),键 `notify.dnd`(SYSTEM_SETTINGS §1),面板内读写 `meow_settings_*` 零旁路。`[NOTIFICATION_SYSTEM §9]` - **⑦ 单条通知左滑删除(launcher 侧,M2.64)**:通知行**从右往左横向滑动删除**,跟手;未过阈值/反向滑回 → **回弹复原(半程可回)**;松手过阈值 → `meow_notif_dismiss` + 行移除/重排。竖向=列表滚动(方向随 `input.swipe_invert`)、`meow_edge_back`(左缘)优先不变。`[NOTIFICATION_SYSTEM §9]` - **⑧ 一键清除通知(launcher 侧,M2.65)**:勿扰开关**对称处(右半段)**加「一键清除」按钮;点击先**转储留档**(走既有 dump 链 `meow_notif_dismiss → meow_notif_dump_tf`,一行 CSV 追加 `MeowOS/notifications/notifications.log` + 10MB 滚动),再**清空显示**。**红线:绝不清「活动」通知**——① ongoing 常驻、② 媒体通知(媒体会话单例)、③ 带进度条进行中(`progress>=0`)一律保留;只清「非 ongoing / 非 media / 无进行中进度(`progress<0`)」的普通通知。`[NOTIFICATION_SYSTEM §9]` - **⑨ 面板「跟手下拉、半程可回」(launcher 侧,M2.65)**:面板打开/关闭由触发式 180ms 过渡升级为**手指拖动实时跟手**——顶部热区下拉 `progress = 手指位移映射`(复用 `mnp_anim_off`,∈[0,1024],1:1 跟手);松手 `progress≥40%×1024≈410` → 时间轴补到 1024(展开);`<阈值 或 反向拖回` → 回弹到 0 收回(半程取消);关闭同理可跟手。与行左滑(⑦ 横向主导)/列表滚动(竖向溢出)/`meow_edge_back`(左缘)互斥分流。`[NOTIFICATION_SYSTEM §9]` ### 5.4 配置版本单点 / 刷新率 / 息屏 - **现行:M2.71(`/etc/meowos_version` = `0.7.66`;M2.70/0.7.65、M2.69/0.7.64、M2.68/0.7.63 …)**;版本单点 = `/etc/meowos_version`(见 §1.1,`build_fw_apps.sh -v` 写入)`[DEV_NOTES #4][fw_content.conf]` - 刷新率:`display.refresh_rate` enum 60/30/15(默认 60);`display.refresh_always_max` bool false(关=允许 60→30→15 降档)。governor:连续 12 帧超预算降一档,连续 4 批≈48 帧远低预算升一档 `[SYSTEM_SETTINGS §1][PERF_SCHEDULER][MIGRATION_AC §12.1]` - 息屏:`display.screen_off_timeout` int 秒 默认 **30**(0=常亮);`display.screen_off_mode` enum `panel`(面板下电+背光0+FBIOPBLANK)/`black`(背光0全黑+双击亮屏) `[SYSTEM_SETTINGS §1]` - 亮度 clamp:`display.brightness` 0-255 默认 101(clamp ≥ `display.brightness_min`);`display.brightness_min` 默认 **1**(M2.39 由 25 改 1)——**与旧文档 25 冲突见 §A** `[SYSTEM_SETTINGS §1]` - **主机名(M2.54)**:`system.hostname`(SET_STR 默认 `meowos`,RFC1035 首标签);`S89meow_svcd` 开机读板载 `settings.conf` 应用 `sethostname`,缺省 `meowos`/系统名;供 `meow_mdns` 公布 `.local`。settings 无该键 → 默认 `meowos`。`[SYSTEM_SETTINGS §1][mips-repo/bins/meow_mdns/manifest.md]` ### 5.5 MeowAPPs 包结构 / .mpk / 数据 - `/` = 程序主体+app.json+资源;`MeowData//{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.`/`awake.`(keep_awake)/`service.`/`fullscreen`(app 级;`route..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]` - 热启动(reboot、含充电态 reboot)一律**不进**充电屏,走引导选单 `[CHARGING_SCREEN §0]` - 主题:`theme.charging=`(默认 default);`MeowOS/themes/charging//theme.json`;加载失败回退内置纯代码默认主题 `[CHARGING_SCREEN §1/§2]` ### 5.7 字体管理 + 应用字库接口(扩展 → SDK 统一接口 / 应用自带字库 / 多句柄) > 在 §5.2「TF 卡多字体库(M2.5x)」基础上**扩展**:把 MeowOS 字体管理器定义为可用字库的**唯一权威来源**,向 SDK 提供统一查询/选用接口,并支持**应用自带字库**与**多句柄(多字体)**。 > ⚠️ **状态分级(2026-08-30)**:launcher 侧字体管理器(§5.7.1)与 **两级扫描/字重子菜单(agent-111,M2.58)**、`meow_font_has_glyph` 已实现;**列表枚举(§5.7.1/§5.7.2)** 落地(**agent-113,M2.58**):「扫描结果落盘 `MeowOS/config/fonts/index`(family/weight/path/label/tier/glyph_count),SDK `meow_font_get_available_count/enumerate` 从该文件读、不依赖 launcher 内存数组;字库丢失→降级默认+日志;render 走 env `MEOW_FONT_PNG/IDX`,list 枚举走 index——两路明确」。**应用自带字库(§5.7.3)/ 多句柄(§5.7.4)/ 凡 `_h` 接口仍为「草案/未实现」**,勿当作已落地;当前 SDK 只有单字体 `meow_font_*` 与 `meow_ui_text*`(用当前默认字体)。 > `[源:meow_font.h][源:agent-79 实现][源:meow_ui.h]` > **app 未自带字库 → 跟随系统 `font.file`(M2.x 已落地)**:launcher 每次 `launch_app` 前把「当前生效字体」注入为环境变量 `MEOW_FONT_PNG`/`MEOW_FONT_IDX`(绝对路径,可选 `MEOW_FONT_APP=`);SDK `meow_ui_gfx.c load_font()` **优先读 env**,无 env 则回退卡默认 `MeowOS/fonts/default` → 固件。§5.7.3 的 `load_handle`(app 自带字库)**未实现**,故当前 app 只能跟随系统字体;一旦实现自带字库,其加载优先级应高于 env。 - **5.7.1 字体管理器(launcher 侧)= 可用字库唯一权威来源** - 唯一维护并扫描 `MeowOS/fonts///`(+默认),产出「字体列表」(family slug / weight slug / 显示名 / glyph_count / size_list / bit_depth)。**SDK 不自行发现字库**,一律经本接口取 launcher 扫描结果。**扫描结果落盘 `MeowOS/config/fonts/index`**(family/weight/path/label/tier/glyph_count);SDK 读该文件(不依赖 launcher 内存数组)。 - **释放语义(agent-113 落地结论)**:持久来源 = index 文件;`font_presets*`/`*_buf` 为「静态、有界(`FONT_PRESETS_MAX=17`)、非堆」数组 → 无内存泄漏、无运行期 free;「释放」= 两个扫描点(启动/进设置页)重建 + 固定上限防膨胀,离开字体列表视图无需显式 free(下次进设置/重扫自动重建)。⚠️ **未做「启动后即清空数组」**:`meow_font_effective_paths_tiered`(launch_app 大字库档位选库)与 `meow_font_reload_multifont` 运行期持续读 `font_presets_n`,清空会造成大字库档位退化(red line「保持档位/多字体行为」);如需「零驻留」,须把这几个核心路径改为直接读 index(较大重构,留待后续)。 - 扫描与校验规则沿用 §5.2:三件套 `font.png/font.idx/font.json` **缺任一件 → 该套跳过 + 日志**;`font.json` 解析 `name`(缺回退目录名)/`weight`(缺省 `regular`)/`glyph_count`/`size_list`/`bit_depth`;`sha256_png/sha256_idx` 仅 **WARN** 不硬失败(该套仍可选)。 - 列表上限沿用 `FONT_PRESETS_MAX = 17`(1 默认 + ≤16 卡内套装,防爆);顺序 = 默认(0) + 扫描顺序。扫描时机不变(启动 / 进设置页),**勿放热路径** `[源:agent-79 实现]`。 - 权威列表数据模型(SDK 侧快照,枚举时填充): ```c typedef struct meow_font_info { char family[64]; /* family slug = MeowOS/fonts// 第一级目录名 */ char name[64]; /* font.json "name",缺则回退 family */ char weight[32]; /* font.json "weight"(regular|bold|italic|…),缺省 "regular" */ int glyph_count; /* font.json "glyph_count",信息用 */ int size_list[16]; /* font.json "size_list"(原生面字号,0 结束) */ int size_count; /* 有效字号数 */ int bit_depth; /* 4 | 8 */ char path_png[320]; /* 系统库:相对卡根 MeowOS/fonts///font.png */ } meow_font_info; ``` - **5.7.2 应用可读 TF 卡字体列表(统一规范接口,app 面向;已落地,M2.58)** `[源:agent-79 实现][源:agent-113 实现][源:meow_font.h]` - **读取来源 = `MeowOS/config/fonts/index`**(launcher 扫 `MeowOS/fonts///` 后落盘;CSV 每套一条 `"family","weight","path","label","tier",glyph_count`,path=卡根相对 `font.png`,label=显示名+字重+尺寸标记,tier=common|gbk|full;默认行恒为 index0)。`meow_font_get_available_count/enumerate` **只读该文件**,不再依赖 launcher 内存数组;无卡/无 index → 仅板载默认项(family=default,count=1)。index 解析在 `font/meow_font.c`(`meow_font_index_load`),SDK 经 `meow_ui.h §5.7` 暴露。 ```c int meow_font_get_available_count(void); /* 可用字库数(含默认;无卡→1) */ int meow_font_enumerate(int idx, meow_font_info *out); /* 按序号取,越界返回 0 */ typedef int (*meow_font_enum_cb)(const meow_font_info *info, void *ctx); int meow_font_enumerate_cb(meow_font_enum_cb cb, void *ctx); /* 回调式,返回套数 */ int meow_font_select_by_id(int id); /* 选该套为 app 会话默认字体 */ ``` - 语义:`id` = 列表序号(index 行号);`0` = **跟随系统默认**(用户 `font.file` 所选,经 env `MEOW_FONT_PNG/IDX`,app 会话不覆盖);`>0` = **app 会话内固定用该套**(覆盖 `font.file` 至 app 结束)。成功 0,越界返回负值。 - **字库丢失降级默认(不丢请求)+ 日志**:`select_by_id(id>0)` 加载失败(png 缺失/坏)→ **降级**到系统默认(env→卡默认→固件),并 `meow_log(MEOW_LOG_WARN, "font missing, fallback default")`(落 app 日志 = SDK meow_log);请求不丢(仍按"选过"处理)。渲染仍走 env `MEOW_FONT_PNG/IDX`(选中的那一套),**列表枚举走 index 文件**——两路明确匹配。 - **列表快照是临时的**:launcher 仅启动/进设置页重扫,期间拔卡或改卡内字库不刷新;app 应**每次会话重新枚举**、按 `family` 持久化,勿缓存数值 id。 - 覆盖范围:系统库 `MeowOS/fonts///` 与默认(含固件 `/usr/share/meowos/font` 回退)都反映在列表里;app 侧「选用已有字库」**只用本接口,不直接拼路径**。 - **launcher 侧系统设置同样降级 + 系统日志**:`font.file` 选中字体缺失 → `meow_font_ensure`/`meow_font_reload_multifont` 兜底链(font.file→卡默认→固件)回退默认,并 `logmsg("meow_font: selected font %s missing, fallback default")`(系统日志 = launcher logmsg;多字体类别缺失 → `multi_font: class %s font %s missing, fallback global`)。app 日志(SDK meow_log)与系统日志(launcher logmsg)分流明确。 - **5.7.3 应用自带字库(按 handle 加载)** `[源:meow_font.h]` - 目录:`MeowAPPs//fonts//{font.png,font.idx,font.json}`;`` = `app.json.package`(反域名 app_id,见 §5.5),`` = 应用自设名字(如 `lyrics`/`reader`)。 - `app.json` 声明(**可选**):`"fonts": ["lyrics","reader"]`。作用 = MeowPanel 打包校验 / launcher 装包校验 / SDK 提供取证;**不声明也可运行时按 handle 加载**。 - SDK 接口(草案): ```c int meow_font_load_handle(const char *pkg, const char *handle); /* 返回字体句柄(>0),失败负值;pkg=NULL=当前 app */ void meow_font_unload_handle(int h); int meow_font_handle_info(int h, meow_font_info *out); /* 查句柄对应信息 */ ``` - **应用自带字库校验更严**:三件套缺任一或 `font.json` 解析不出 → 加载**失败**(app 自声明字库,坏库应显式失败,而非静默回退点阵/默认)。 - 与系统库**并存可混用**:系统套件经 §5.7.2 `meow_font_select_by_id` 激活即成合法 handle;应用自带经 `load_handle` 取得 handle;两者在同一 handle 空间。 - **5.7.4 多句柄 / 多字体(不同控件用不同字体)** `[源:meow_font.h][源:meow_ui.h]` - 低层 `meow_font_*` 新增 `_h` 句柄版本(显式传 handle): ```c void meow_font_drawtext_h(uint16_t *fb,int x,int y,const char *utf8,uint16_t color,int size,int handle); void meow_font_drawtext_outline_h(uint16_t *fb,int x,int y,const char *utf8, uint16_t color,uint16_t outline_color,int ol,int size,int handle); int meow_font_width_text_h(const char *utf8,int size,int handle); int meow_font_line_height_h(int size,int handle); int meow_font_ascent_h(int size,int handle); int meow_font_has_size_h(int size,int handle); ``` - **兼容关键**:现有无 `_h` 的 `meow_font_*`(drawtext/width_text/line_height/...)语义变更为「作用于**当前句柄**」(默认 = 系统 `font.file` 那套);`meow_font_load(png,idx)` 仍是装载系统默认的入口;新增 `meow_font_use(handle)` 设定当前句柄。**不改任何现有签名 → 纯扩展、向后兼容。** ```c void meow_font_use(int handle); /* 设定后续无 _h meow_font_* 所用字体 */ int meow_font_get_current(void); ``` - SDK `meow_ui_*` 高层文本同理: ```c void meow_ui_use_font(int handle); /* 设定后续 meow_ui_text* 字体 */ int meow_ui_font_get_current(void); /* 取当前 meow_ui_text* 所用句柄 */ void meow_ui_text_h(int x,int y,const char *utf8,int size,uint32_t color,int handle); void meow_ui_text_right_h(int right_x,int y,const char *utf8,int size,uint32_t color,int handle); void meow_ui_text_center_h(int cx,int y,const char *utf8,int size,uint32_t color,int handle); int meow_ui_text_width_h(const char *utf8,int size,int handle); int meow_ui_text_height_h(int size,int handle); /* = meow_font_line_height_h */ ``` 现有 `meow_ui_text/text_right/text_center`(无 handle)= 用当前字体(`meow_ui_use_font` 设;默认系统默认)。**向后兼容。** 建议 app 切库前用 `meow_font_get_current()` / `meow_ui_font_get_current()` 求值保存,画完再 `meow_ui_use_font(旧)` 显式恢复,避免句柄状态泄漏影响后续绘制。 - **5.7.5 多句柄用法示例(歌词页用 A 库、正文用 B 库)** ```c /* 应用自带 lyrics(歌词页) + 系统字库(正文)混用 */ int hLyrics = meow_font_load_handle(NULL, "lyrics"); /* MeowAPPs//fonts/lyrics/ */ meow_ui_use_font(hLyrics); meow_ui_text_center(240, 300, "歌词行…", 20, 0xFFFFFF); /* 用 lyrics 库 */ int hBody = meow_font_select_by_id(2); /* 系统字库第 2 套(正文用) */ meow_ui_use_font(hBody); meow_ui_text(20, 60, "正文…", 20, 0xFFFFFF); /* 用系统库 */ /* 量宽/行高须与最终实际字形一致:用同 handle 的 _h 版 */ int w = meow_ui_text_width_h("正文…", 20, hBody); int lh = meow_ui_text_height_h(20, hBody); ``` - 说明:句柄状态为 app 进程内**全局**;同一屏需混排时,推荐每段绘制前显式 `meow_ui_use_font`,或全部走 `*_h` 显式传 handle,避免依赖上次绘制遗留的句柄状态。 - **5.7.6 MeowPanel 上传 / 导出(.zip,预留)** `[源:meow_font.h]` - 复用已声明的 `meow_font_import_zip(zip_path)` / `meow_font_export_zip(family,out_zip)`(§5.2 已列为 TODO,未实现)。 - **系统字库导入**:`.zip` 内含 `font.png+font.idx+font.json` 三件套;校验三件套就绪 + `font.json` 可解析;sha256 沿用 `font.json` 约定(建议与运行时同口径 = **WARN**,仅缺件/不可解析硬失败);`family`/`weight` 取自 `font.json.family`/`font.json.weight`(缺省 `regular`)或 zip 名;解压到 `MeowOS/fonts///`;**覆盖冲突需先确认**;导入后应触发 launcher 重扫(刷新 §5.7.1 列表)。 - **应用字库导入**:目标 `MeowAPPs//fonts//`,与 `app.json "fonts"` 声明对齐,校验同上。 - **导出**:系统库把 `MeowOS/fonts///` 三件套打包;应用库把 `MeowAPPs//fonts//` 打包。 - 约定:`.zip` 布局与校验沿用 `font.json` schema(§5.2);导入/导出后的一致性(列表刷新、应用声明同步)归 MeowPanel + launcher 协作,本小节仅列接口语义。 - **5.7.7 多字体(按字符类别逐字符路由,`display.multi_font`,M2.5x 新增)** `[源:meow_font.h][源:MEOWOS_SPEC_REF §5.2/§5.5]` - **背景**:一款字体难兼顾中文(大图集、字形全)与拉丁/数字(干净、省内存)。多字体让**不同字符类别各用一套字库**,按 codepoint 逐字符路由取字形。 - **设置键**(launcher 读,SDK 经 env 读同一映射): - `display.multi_font`(int **0/1,默认 0=单字体**):1=按字符类别逐字符路由;0=只走 `font.file`(现状,零额外内存/性能开销)。 - 6 个类别字体(SET_STR,值 = 字体 `/` 相对路径(如 `misans/bold`,M2.6);**默认空 = 跟随全局 `font.file`**):`font.class_cjk`(CJK 表意+扩展)、`font.class_cjk_sym`(全角/中文标点)、`font.class_num`(0-9)、`font.class_latin`(A-Za-z)、`font.class_latin_sym`(半角标点)、`font.class_other`(其他)。 - **字符分类器**(`meow_font_class_of(cp)`,按 codepoint):`MEOW_FCLS_CJK`/`_CJK_SYM`/`_NUM`/`_LATIN`/`_LATIN_SYM`/`_OTHER`。规则(ASCII 优先 + Unicode 区间):0x30-39→NUM、0x41-5A/61-7A→LATIN、<0x80(其余)→LATIN_SYM;0x3000-303F/0xFF00-FFEF/0x2014/0x2018-201D/0x2026/0x00B7→CJK_SYM;CJK 表意+扩展+兼容表意区(0x3400-4DBF/4E00-9FFF/20000-2FA1F…)→CJK;其余(假名/韩文/其他文字/扩展区)→OTHER。 - **逐字符路由**:`meow_font_drawtext`/`_outline`/`width_text`/`line_height`/`ascent`/`has_size` 在 multi_font 开启时**逐字符分类 → 用类别对应槽的字库取字形与度量**(宽度/行高按该字体);缺某类字体/槽未载 → **回退全局**(slot0);该字符其字体无字形 → **豆腐缺字**(可经 `meow_font_has_glyph(cp)` 预判)。开关关 → 一律 slot0,与单字体一致。 - **SDK 接口**:`meow_font_load_slot(slot,png,idx)`/`meow_font_unload_slot(slot)`/`meow_font_enable_multifont(on)`/`meow_font_set_class_slot(cls,slot)`/`meow_font_config_multifont(on,global_png,global_idx,cfg[],&distinct,&truncated)`;`MEOW_MAX_SLOTS=5`(slot0=全局 + ≤4 类别)。`meow_font_config_multifont` 统一做**同 png 去重**(含与全局相同 → follow slot0)与**≤4 套上限**(超出 → 置 `*truncated=1`,调用方 WARN「过多不同字体会增内存」,已装载者保留、新类别回退全局)。 - **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":""` 声明(launcher `meow_parse_app_json` 已解析);activity 级(如需)以 `route..fonts` 声明(沿用 `route.` 扩展口径)。launcher 启动 app 时据声明 + `font.load_full` 算**生效档**,经 env 注入(`MEOW_FONT_PNG/IDX` 指向所选档位字库绝对路径;`MEOW_FONT_TIER` 标注档位;launcher `meow_font_effective_paths_tiered` 按卡内 `font.json charset` 选库)。 - **系统设置「加载大字库」**(`font.load_full`,默认 0):开 → **强制全系统用大字库(gbk 档)**,覆盖 app 未声明 + 覆盖默认 `font.file`;关(默认)→ 默认小字库,app 声明才大字库。 - **SDK 判缺字**:`meow_font_has_glyph(cp)` 预判当前字库是否含该码位 → app 据此决定回退/提示(避免 `common` 小字库下静默豆腐或缺字)。 - **⚠️ 与 §5.7.3 冲突**:§5.7.3 `"fonts":[…]` 为**应用自带字库句柄数组**;本小节 `"fonts":"full"` 为**字库档位字符串**。同名键两种语义,需统一解析口径(见 §7 A-14)。 --- ## 6. 标志性 TODO / 未决(文档未定,勿凭猜实现) - OPEN_QUESTIONS.md 待定 ❓:#1 背景图加载时机/缓存、#2 非 480×720 图如何处(拉伸/裁剪/回退)、#3 叠加层颜色联动、#4 背景色板具体枚举、#5 浅色主题文字对比度、#7 首期是否做应用图标、#8 通知来源(**最大空白**,M2 已定为 系统+IPC+D-Bus 三路)、#9 下拉手势 vs 左滑返回区分、#10 通知存储上限/FIFO、#11 媒体活跃会话判定、#12 多 app 音频混音/焦点、#13 web 实时画面 JPEG/WS、#14 远程输入注入仲裁、#16 主页左滑=侧边栏 vs 返回 `[OPEN_QUESTIONS]` - DEVELOPMENT_PLAN:阶段 0(bootmenu 双系统)**待实现**(M0-M4);阶段 B/E/F;M2-M6 阶段 D 里程碑未做 `[DEVELOPMENT_PLAN]` - 未定/待拍板:`meow_config_*`/`meow_media_*`/崩溃捕获(见 §4);MeowOS 音频输出设置(只读还是可配);OTA 依赖 MeowPanel `[WORK_STATE][OPEN_QUESTIONS #17/#18]` - **meow_svcd 后续(M2.54 已落地大部分)**:~~接入 supervisor 启动链~~(已改 `etc/init.d/S89meow_svcd` 开机自启;bootmenu/launcher `fork+exec`+`waitpid` 仍为备选);~~写 `MeowOS/services.d/mdnsd.conf` 落地 mDNS~~(已改**板载** `/usr/data/meow/services.d/mdnsd.conf` 预置,`trigger=boot`)。剩余:`cap` setcap 真机实装(cap_net_bind_service,cap_net_raw);`wifi-up` 判定收紧。**services.d/svcd 已接入开机链(S89)**,但真机行为待验证。 `[WORK_STATE][meow_svcd.md]` --- ## 7. 已知矛盾 / 待确认(⚠️ 别凭猜) - **A-1 热键窗口下限**:APPS.md §3.1/§4.2 写「电源按下后 **300ms**~2.5s」;DEVELOPMENT_PLAN §0/阶段A 写「窗口下限 **60ms**(v6.7 修)。→ 以 **60ms** 为准,APPS.md 已过时。 - **A-2 主题模式枚举**:SYSTEM_SETTINGS §1 `display.theme_mode`=`manual`/`auto`(另设 `display.theme`=dark/light);MEOW_APP_SDK §8 / meow_ui.h `meow_theme_mode`=`LIGHT/DARK/AUTO` 且直接跟随 `display.theme_mode`。→ 两套枚举语义不一致;AUTO 时段:SYSTEM_SETTINGS 用可配 `theme_dark_start/end`(分钟),SDK §12 用固定「6:00-18:00 日间」。WORK_STATE/DEV_NOTES 明言「时段判定 launcher/SDK 两份逻辑需抽共享纯函数」。→ **DOM 键值 enum 与 SDK enum 需统一,时段判定需抽共享函数后再实现。** - **A-3 亮度下限**:`display.brightness_min` 默认 **1**(SYSTEM_SETTINGS §1,M2.39 由 25 改 1);但 MEOWOS_API §2.2「clamp ≥ brightness_min 默认 **25**」、MD3_UI_SPEC §3.2「亮度 clamp ≥25」仍写 25。→ 以 **SYSTEM_SETTINGS(1)** 为准,另两份文档陈旧。 - **A-4 左缘返回阈值**:MEOW_APP_SDK §6 / GESTURE_BACK 取「左缘 ≤24px + 向内划 **≥90px**,抬手触发」;MIGRATION_AC §7 写「左缘 24px + 右滑 **≥65px** 触发」。→ **90 vs 65 不一致**(meow_ui.h 未给阈值,GESTURE_BACK + MEOW_APP_SDK 较权威=90,但确认真机前留疑)。 - **A-5 通知 app_quota**:NOTIFICATION_SYSTEM §7/meow_ui.h = 4 类型×每类型 4=16 条/App;SYSTEM_SETTINGS §1 `notify.app_quota`=16。FRAMEWORK_DESIGN §4「配额 ≤16/应用」。→ **口径可归并(4×4=16)**,但 SYSTEM_SETTINGS 未列 4/4 细分,建议实现以 meow_ui.h 的 `MEOW_NOTIFY_MAX_TYPES/MAX_PER_TYPE` 为准。 - **A-6 KEY_PREVIOUS(code)**:KEY_CONTROL §3 明注「KEY_PREVIOUSSONG 是 **165**;19 是另一码」;meow_ui.h `#define MEOW_KEY_PREVIOUS 19 /* KEY_PREVIOUSSONG */` 注释标错。→ **19 的标签应改**(值 19 非 prevsong;165 才是),属 meow_ui.h 注释误导。 - **A-7 app 日志路径**:APP_LOG_MANAGER §4 写 `apps/.log`(单文件);meow_ui.h §9 / DEV_NOTES #9 为 **`apps/<包名>/logs/<启动时间>_.log`**(每次启动新文件)——用户已纠正,勿用单文件。→ 以 meow_ui.h/DEV_NOTES(M2.51)为准,APP_LOG_MANAGER 目录小节过时。 - **A-8 状态栏高**:MEOW_APP_SDK §3.1「slim ~20-40px」;实际定案 **40px**([D6] MIGRATION_AC §11.1),后被用户改为 **28px**(MUI_SBAR_H=28,字号 20,图标 ink 16/中线 14,见 M2.x 状态栏压缩)。→ 现取 28。 - **A-9 SDK 通知转储**:NOTIFICATION_SYSTEM §8「创建 10s 后自动转储到 TF」;meow_ui.h 现仅「活动表+meow_log 打日志,真实投递 UI/D-Bus 为后续」。→ **10s 转储/TF 已实现(M2.5x,#6)**:launcher 侧带 TTL 10s 转储钩子,dump 到 `MeowOS/notifications/notifications.log`(appended CSV + 10MB 滚动 + 开机清板载/内存表);meow_ui.h 注释「真实投递 UI/D-Bus 为后续」仍指**通知中心 UI / D-Bus 桥**未做。 - **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 占位。→ **M2.64:APPS.md §4.6 已修正为「`/etc/meowos_version` 单点、`MEOWOS_VERSION` 宏仅 dev 占位」,方使矛盾消除**。 - **A-11 `MeowOS/opt/` vs `MeowOpt/`(已归并)**:曾有顶层 `MeowOpt/`(板载外部工具/二进制,如 mdnsd)与 `MeowOS/opt/{bin,nyai,sources.list},lib/,tools/`(nyai 包管 + 工具)并存、命名仅大小写之差。→ **已归并**:`MeowOpt` 废弃并入 `MeowOS/opt/`;mDNS 由完整 mdnsd(TF MeowOS/opt/mdnsd)改为**自研 `meow_mdns`(固件 `/usr/bin`,IPv4-only)**,不再放卡。全仓库统一用 `MeowOS/opt/`。 - **A-12 `fullscreen` 字段(已定 → 已实现,M2.5x)**:§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..fullscreen` 预设 SDK 全屏(env `MEOW_FULLSCREEN`),见 §5.1/§3.1。全屏语义由「隐藏状态栏+隐藏返回键」细化为「状态栏收合至提示线 + 保留左缘返回+顶部提示线+下滑通知中心(热区缩小)」(见 A-13)。 - **A-13 全屏语义细化(状态栏「隐藏」→「收合至提示线」)**:既有 §3.1/§5.1 描述全屏=隐藏状态栏(`meow_ui_statusbar_height()`=0、隐藏返回键=沉浸);本次定案细化为**进入/退出全屏:状态栏向上收出屏顶、只留一条提示线高度**,**全屏下保留**左缘返回手势 + 顶部动态伸缩提示线,且**顶部下滑仍可开通知中心(顶部热区缩小)**。→ **已实现(M2.5x)**:SDK 端明确「收合(collapsed)=状态栏缩为提示线(4px)」vs「隐藏=高度0」;全屏下保留左缘返回+顶部伸缩滑条+顶部下滑通知中心(热区缩小)。⚠️ **全屏顶部动态伸缩滑条仍有已知问题在跟进(agent-112)**。 - **A-14 `fonts` 键二义**:§5.7.3 `"fonts":[…]`=应用自带字库句柄数组;§5.2/§5.7.8 `"fonts":"full"|"gbk"|"common"`=字库档位字符串。→ 同名键两种语义,解析器需区分(字符串→档位 / 数组→句柄);若避免歧义可改用专键如 `"font_tier"`(**未拍板**)。 `[各源标注见上]`