sdk: meow_ui.h 公共头按模块拆分(伞头聚合,API 零改动)

- meow_ui.h(922 行)改为伞头:只做 #include 聚合 + 模块索引,不定义新 API。
- 新增 patch_v2/sdk/include/ 16 个子头(types/draw/image/theme/ime/widgets/input/
  activity/zorder/statusbar/dialog/log/notify/config/font/audio),各自自洽可单独 include,
  依赖最小化(不透明句柄前向声明 + 必要模块互引)。
- 验证:meow_ui.a md5 与主树完全一致(4786158d…,头重组 .o 逐字节等价);
  SDK .c 用 mipsel -Wall -Wextra 0 warning;hello/files 全量重编链接通过
  (-Wall -Wextra 0 warning);宿主 test_p1p2p3_repro(P1c/P2/P3 ALL PASS)
  + 15 个 SDK/宿主测试 PASS;16 子头自洽编译 0 warning;伞头完整性回归
  test_umbrella.c 0 warning;ncm 5 个含 meow_ui.h TÜ mipsel 交叉编译到 .o 0 warning。
- meow_ui_internal.h 及 view/nav/media/sys/vol 子头未动;build_sdk.sh 无需改。
- MEOW_APP_SDK.md 头部新增「公共头模块索引」。分支 sdk-header-split。
This commit is contained in:
MeowOS committed 2026-09-01 20:30:16 +08:00
1 parent 78be63d5cc
commit 2e7561d74f
18 files changed
+1339 -897

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
/*
* meow_ui_activity.h — SDK 控件生命周期与归属(§6.1):Activity 栈 + 三层控件模型。
*
* 原 meow_ui.h 拆分的一部分(activity 模块)。根治「跨页面控件残留」:控件命中/绘制必须严格
* 绑定其所属页面。三层职责(App→系统):①页面控件(绑定 owner Activity);②App 跨 Activity
* 控件(SDK 托管骨架);③系统级控件(状态栏/通知中心/返回滑条/电源菜单,仅框架内部,无公共 API)。
*/
#ifndef MEOW_UI_ACTIVITY_H
#define MEOW_UI_ACTIVITY_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §6.1 控件生命周期与归属(Activity 栈 + 三层控件模型) [源:2026-08-30] */
/* ============================================================ */
/* 根治「跨页面控件残留」:控件命中/绘制必须严格绑定其所属页面,否则会出现
* "按钮已不可见但仍被触摸命中"(如全屏页触摸到主页按钮位置闪现 accent 底)。
*
* 三层职责(从 App 到系统,风险从低到高):
* ① 页面控件:归属唯一 owner Activity;命中/实时按压只在「当前 active Activity
* 的控件集」里生效。对象不销毁(同 Activity 内复用),弹栈回来自动恢复 →
* 回页面零重建。
* ② App 跨 Activity 控件(SDK 托管):钉在 App 的 Activity 栈之上、跨 Activity 常驻,
* 逻辑/渲染由 SDK 调度。本轮为「可用骨架」(见上 API 注释),待 B2 细化。
* ③ 系统级控件(状态栏/通知中心/返回滑条/电源菜单):仅框架内部,无公共 API(不开放)。
*
* 触摸命中分流顺序:③ 系统全局 → ② App 全局 → ① 当前 active Activity 页面控件;
* 某层命中即消费,否则落到下一层。 */
/* ① Activity 栈。控件创建时绑定「当前 active Activity」为 owner;弹栈回来自动恢复。
* 栈空时 active() 返回 0(根/default Activity),故未显式管理栈的 App 默认所有控件
* 归属根 Activity 0。push 新 Activity(进子页/全屏)、pop 回上级(回根)。 */
void meow_ui_activity_push(int id);
void meow_ui_activity_pop(void);
int meow_ui_activity_active(void); /* 当前 active activity id(栈空=0) */
int meow_ui_activity_depth(void); /* 当前栈深(push/pop 页数;供 M3 导航上报用) */
/* ② App 跨 Activity 控件(SDK 托管,骨架)。SDK 维护全局控件列表:
* - 渲染:每帧(有脏区需上屏时,meow_ui_gfx present())在 active activity 内容之上、
* 全局状态栏之下调用 render_cb(跨 Activity 常驻);
* - 触摸:TAP 先给 global hit_cb(返回 1=消费),否则落到 active activity 页面控件。
* 逻辑/渲染由 SDK 调度,App 只需声明。注:骨架,待 B2 细化。 */
typedef void (*meow_global_render_fn)(void *ctx); /* 每次渲染帧回调(SDK 调用) */
typedef int (*meow_global_hit_fn)(void *ctx, int x, int y); /* 命中返回1=消费 */
void meow_ui_global_add(int id, meow_global_render_fn r, meow_global_hit_fn h, void *ctx);
void meow_ui_global_remove(int id);
/* ③ 系统级控件:状态栏/通知中心/左缘返回滑条/电源菜单等全局叠加层——仅 SDK 内部接口,
* 不向用户 App 开放任何公共悬浮/叠加层 API。既有状态栏/返回滑条逻辑(§3.1)不动。 */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_ACTIVITY_H */
+66
View File
@@ -0,0 +1,66 @@
/*
* meow_ui_audio.h — SDK 独占音频客户端(§11,devdocs/plan/AUDIOD_DESIGN.md §7;meow_ui_audio.c)。
*
* 原 meow_ui.h 拆分的一部分(audio 模块)。App 只经本 API 喂 PCM 给 meow_audiod
* (独占 hw:0,0 守护,svcd 托管)。audiod 不在一律失败(open 返回 MEOW_ERR_NOENT,负值),
* 不做隐式直开回退;调试可用 env MEOW_AUDIO_DIRECT=1 走自带直接 ALSA 直开路径(非正式能力)。
*/
#ifndef MEOW_UI_AUDIO_H
#define MEOW_UI_AUDIO_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §11 独占音频客户端(devdocs/plan/AUDIOD_DESIGN.md §7;meow_ui_audio.c) */
/* ============================================================ */
/* 说明:App 只经本 API 喂 PCM 给 meow_audiod(独占 hw:0,0 守护,svcd 托管)。audiod 不在一律
* 失败(open 返回 MEOW_ERR_NOENT,负值),不做隐式直开回退;调试可用 env MEOW_AUDIO_DIRECT=1 走
* 自带直接 ALSA 直开路径(非正式能力,勿依赖)。
* 生命周期:open 取 stream_id>0 → write 喂 PCM(阻塞,socket 背压)→ pause/resume → close 释放。
* 被抢占(后开流赢):SDK 内部读线程收 MSG_AUDIO_PREEMPTED → 调 on_preempt 回调 + 标写死
* (后续 write 返回负值,App 应重新 open)。 */
/* 当前流快照(meow_audio_query 填充)。 */
typedef struct meow_audio_state {
int active; /* 1=audiod 有活跃流(不一定是本 App 的) */
char app_id[32]; /* 活跃流 app_id(无流为 "-") */
uint32_t stream_id; /* 活跃流 id */
uint32_t rate; /* 活跃流采样率 */
uint16_t ch; /* 活跃流声道数 */
uint16_t fmt; /* 活跃流格式(AUDIO_FMT_*) */
uint64_t written_frames; /* 客户端写入 ring 的帧 */
uint64_t played_frames; /* 播放线程写到设备的帧 */
uint32_t underrun; /* xrun 计数 */
int paused; /* 当前流是否暂停 */
int route_port; /* 当前路由口(-1 未知) */
int vol; /* 当前音量 0-100 */
} meow_audio_state;
/* 被抢占回调:by_app=抢占者 app_id(非空)。ctx 由 on_preempt 注册时传入。 */
typedef void (*meow_audio_preempt_fn)(const char *by_app, void *ctx);
/* 开流。rate/ch/fmt=App 声源原生参数(fmt 值见 meow_ipc.h AUDIO_FMT_*)。
* 返回 stream_id(>0);负错误码(MEOW_ERR_NOENT=audiod 不在;MEOW_ERR_INVAL=参数非法;
* MEOW_ERR_NODEV=无可用 PCM 设备;MEOW_ERR_* 常量本身即负值)。open 后客户端须按内部记录的
* grant 格式产出 PCM。 */
int meow_audio_open(int rate, int ch, int fmt);
/* 写 PCM。pcm=native fmt/ch 样本(open 传的参数),frames=帧数;内部归一成 grant 并分批发送。
* 返回写入帧数;<0=流已死(被抢占/audiod 断开),App 应重新 open。阻塞(socket 背压)。 */
int meow_audio_write(const void *pcm, int frames);
/* 暂停(1)/恢复(0)当前流。返回 0 成功;<0 失败。 */
int meow_audio_pause(int sid, int paused);
/* 关流(STOP + 释放)。返回 0;连接保留供下次 open。 */
int meow_audio_close(int sid);
/* 查询 audiod 快照(填充 out)。返回 0 成功;<0 失败。 */
int meow_audio_query(meow_audio_state *out);
/* 注册被抢占回调(可选;内部读线程分发)。重复调用幂等。 */
void meow_audio_on_preempt(meow_audio_preempt_fn cb, void *ctx);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_AUDIO_H */
+53
View File
@@ -0,0 +1,53 @@
/*
* meow_ui_config.h — SDK 应用配置读写(§9.2,meow_config_*,M2.x 最小可用版)。
*
* 原 meow_ui.h 拆分的一部分(config 模块)。App 自有配置读写:与系统设置 meow_settings_*
* (板载 settings.conf、系统级、带 schema)明确区分——这是单个 App 自己的键值偏好,
* 落 TF 数据目录,不占板载、无 schema。返回码 MEOW_CFG_* 见下。
*/
#ifndef MEOW_UI_CONFIG_H
#define MEOW_UI_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
/* meow_config_*(§9.2)专用返回码。数值与 MEOWOS_API.md §1 的同名错误码一致,
* 但用 meow_cfg 前缀——因为 MEOW_OK/MEOW_ERR_* 这个命名空间已被共享协议头
* meow_ipc.h(枚举)与 launcher meow_settings.h(宏)占用,SDK 的 meow_notify_ipc.c
* 同 TU include meow_ui.h + meow_ipc.h,若在此定义同名宏会导致「宏展开枚举标识符」冲突。 */
#define MEOW_CFG_OK 0 /* 成功 */
#define MEOW_CFG_ERR_INVAL -1 /* 参数/取值非法(空 key、NULL out、outsz<=0 等) */
#define MEOW_CFG_ERR_NOENT -2 /* 键未设/文件不存在 */
#define MEOW_CFG_ERR_IO -5 /* 读写(存储/文件)失败 */
#define MEOW_CFG_ERR_NOMEM -6 /* 路径超长 */
#define MEOW_CFG_ERR_NODEV -10 /* 无数据目录(卡不在/只读/不可建) */
/* ============================================================ */
/* §9.2 应用配置读写(meow_config_*,M2.x 最小可用版) */
/* ============================================================ */
/* App 自有配置读写:与系统设置 meow_settings_*(板载 settings.conf、系统级、带 schema)
* 明确区分——这是单个 App 自己的键值偏好,落 TF 数据目录,不占板载、无 schema。
*
* - 数据目录:优先 env MEOW_DATA_DIR(launcher 注入 /usr/data/mnt/sd_0/MeowData/<pkg>/data,
* 见 app_launcher.c launch_app);无 env(手动跑/宿主测/无卡)回退 /tmp/meowcfg_<pid>
* (非持久但仍可写)。meow_config_dir() 返回最终目录;空/不可建返回 NULL。
* - 文件布局:每键一小文件 <data>/<sanitized_key>.cfg,内容=值字符串(空串=0 字节文件)。
* key 只允许 [A-Za-z0-9._-],其余字符替换为 '_'(杜绝路径穿越);key 上限 64。
* - 轻量:每次 get 读文件(App 配置小),不做大内存缓存;pthread_once 惰性初始化目录。
* - 失败降级:无数据目录/写失败 → 返回负错误码(见上 MEOW_CFG_ERR_*),不崩不阻塞。
*
* 返回码:MEOW_CFG_OK(0) 成功;(set) 负=失败;(get) MEOW_CFG_ERR_NOENT(-2)=键未设/文件不存在;
* meow_config_int/bool 对任何非 MEOW_CFG_OK 一律返回 def。
* 错误码数值同 MEOWOS_API.md §1 / meow_settings_*(MEOW_ERR_*)一致,便于 App 习惯。 */
const char *meow_config_dir(void); /* 当前 App 数据目录(data);空/不可建 NULL */
int meow_config_set(const char *key, const char *val);/* 写 <data>/<key>.cfg;成功 MEOW_CFG_OK(0) */
int meow_config_get(const char *key, char *out, int outsz); /* 读;未设/不存在返回 MEOW_CFG_ERR_NOENT */
int meow_config_int(const char *key, int def); /* 便捷 int;未设/非法返回 def */
int meow_config_bool(const char *key, int def); /* 便捷 bool;未设/非法返回 def */
void meow_config_remove(const char *key); /* 删键(无该键/无目录则静默) */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_CONFIG_H */
+49
View File
@@ -0,0 +1,49 @@
/*
* meow_ui_dialog.h — SDK 模态(App 层,非系统叠加):Dialog / BottomSheet(§5.8.6)。
*
* 原 meow_ui.h 拆分的一部分(dialog 模块)。复用 §5.6 B③ 弹窗 / §5.7 B④ 底部面板模板
* (与 launcher s_dd_modal 同构),控件化。阻塞式(内层 meow_input_pop 轮询,与
* meow_ui_text_input 同构);打开前排空残留触摸。关闭途径:点卡片内选项=确认、点卡片外=取消、
* 左缘返回手势=取消。不压状态栏(y 钳制)。
*/
#ifndef MEOW_UI_DIALOG_H
#define MEOW_UI_DIALOG_H
#include "meow_ui_types.h"
#include "meow_ui_ime.h" /* meow_ime_ctx(Dialog INPUT 型) */
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §5.8.6 模态(App 层,非系统叠加):Dialog / BottomSheet
* 复用 §5.6 B③ 弹窗 / §5.7 B④ 底部面板模板(与 launcher s_dd_modal 同构),控件化。
* 阻塞式(内层 meow_input_pop 轮询,与 meow_ui_text_input 同构);打开前排空残留触摸。
* 关闭途径:点卡片内选项=确认、点卡片外=取消、左缘返回手势=取消。不压状态栏(y 钳制)。 */
/* ============================================================ */
/* ---- Dialog(弹窗:确认/选择/输入/信息)---- */
typedef enum { MEOW_DLG_CONFIRM, MEOW_DLG_SELECT, MEOW_DLG_INPUT, MEOW_DLG_INFO } meow_dlg_t;
typedef struct meow_dialog meow_dialog;
meow_dialog *meow_dialog_create(meow_dlg_t t, const char *title);
void meow_dialog_set_items(meow_dialog *d, const char *const *item, int n, int cur); /* SELECT 型 */
void meow_dialog_set_ime(meow_dialog *d, meow_ime_ctx *ime); /* INPUT 型 */
void meow_dialog_show(meow_dialog *d); /* 阻塞到确认/取消 */
int meow_dialog_result(meow_dialog *d); /* SELECT=选项下标;CONFIRM/INFO 确认=1、取消=0 */
void meow_dialog_close(meow_dialog *d); /* 程序化关闭(App 亦可驱动) */
void meow_dialog_free(meow_dialog *d);
/* CONFIRM 型便捷:点「确定」返回 1,取消/遮罩=0 */
int meow_dialog_confirm(meow_dialog *d);
/* ---- BottomSheet(底部面板:标题 + 选项列表;open 阻塞返回选中 idx/-1)---- */
typedef struct meow_sheet meow_sheet;
meow_sheet *meow_sheet_create(const char *title, int h);
int meow_sheet_add_item(meow_sheet *s, const char *label); /* 返回项下标 */
int meow_sheet_open(meow_sheet *s); /* 阻塞;返回选中 idx / -1=取消 */
void meow_sheet_free(meow_sheet *s);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_DIALOG_H */
+77
View File
@@ -0,0 +1,77 @@
/*
* meow_ui_draw.h — SDK 绘制层(§3)+ 动画/时间(§7)+ 显示刷新率调度(§7.1)。
*
* 原 meow_ui.h 拆分的一部分(draw/gfx 模块)。坐标 0,0 = 左上;颜色均 24-bit RGB
* (0xRRGGBB),内部转 RGB565;所有绘制先进离屏 back_buf,调用 meow_ui_flush()/
* flush_region() 才上屏。文本字号:28(标题/状态栏)、20(正文/按钮)。
*/
#ifndef MEOW_UI_DRAW_H
#define MEOW_UI_DRAW_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §3 绘制层 */
/* ============================================================ */
/* init 选项。width/height 为 0 表示自动读取 /dev/fb0 几何;
* 无 fb(宿主/qemu 离屏)时用 480×720 缺省([D1])。 */
typedef struct meow_ui_opts {
int width;
int height;
} meow_ui_opts;
int meow_ui_init(const meow_ui_opts *opts); /* 开 fb、读几何、载字库、建 back_buf;0=成功 */
void meow_ui_shutdown(void);
int meow_ui_width(void); /* 480 */
int meow_ui_height(void); /* 720 */
void meow_ui_clear(uint32_t color); /* 整屏清(填背景色) */
void meow_ui_put_px(int x, int y, uint32_t color);
void meow_ui_fill_rect(int x, int y, int w, int h, uint32_t color);
void meow_ui_draw_rect(int x, int y, int w, int h, uint32_t color); /* 空心框 */
void meow_ui_draw_rect_round(int x, int y, int w, int h, int r, uint32_t color); /* 圆角框 */
/* 文本(size=20/28) */
void meow_ui_text(int x, int y, const char *utf8, int size, uint32_t color);
void meow_ui_text_right(int right_x, int y, const char *utf8, int size, uint32_t color);
void meow_ui_text_center(int cx, int y, const char *utf8, int size, uint32_t color);
int meow_ui_text_width(const char *utf8, int size);
int meow_ui_text_height(int size); /* = meow_font_line_height */
/* 上屏:vsync + 原子 blit 脏区(内建脏区追踪) */
void meow_ui_flush(void);
void meow_ui_flush_region(int x, int y, int w, int h); /* 只刷新指定区 */
/* 半透明(blend565:前景按 alpha 与背景混叠) */
void meow_ui_fill_rect_alpha(int x, int y, int w, int h, uint32_t color, int alpha); /* 0-255 */
/* ============================================================ */
/* §7 动画/时间(B1 最小可用) */
/* ============================================================ */
uint64_t meow_ui_time_ms(void); /* 单调毫秒时间戳 */
/* ============================================================ */
/* §7.1 显示刷新率调度(A-1/A-2:从 launcher M2.16 迁入,归口 SDK,PERF_SCHEDULER 显示子域) */
/* ============================================================ */
/* 设目标档位 60/30/15(launcher 与 app 统一走 SDK 的 present 帧率门控一致)。
* 同时把当前有效档对齐到目标(与 launcher settings_load 语义一致)。 */
void meow_ui_set_refresh_rate(int r);
/* 1=恒 max 不降档(性能优先);0=允许 governor 在 [15,30,60] 自适应降/升档。 */
void meow_ui_set_refresh_always_max(int on);
/* 当前有效帧率(governor 可能已降档;诊断用)。 */
int meow_ui_effective_rate(void);
/* 已呈现帧计数(验证 present 频率用)。 */
unsigned long long meow_ui_frames_presented(void);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_DRAW_H */
+76
View File
@@ -0,0 +1,76 @@
/*
* meow_ui_font.h — SDK 字体:应用可读 TF 卡字体列表(§5.7)+ 字体分层/大字库(§10)。
*
* 原 meow_ui.h 拆分的一部分(font 模块)。字库权威列表 = launcher 扫描落盘的持久文件
* MeowOS/config/fonts/index(CSV);App 只经本接口读该列表。字体「档位」由 launcher 按
* app.json 声明的 "fonts:<档>" 注入 MEOW_FONT_TIER;SDK 据档选库(meow_font_reload_tier)。
*/
#ifndef MEOW_UI_FONT_H
#define MEOW_UI_FONT_H
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §5.7 应用可读 TF 卡字体列表(M2.58:字体索引 / 查列表 / 丢失降级默认) */
/* ============================================================ */
/* 系统字体管理器的面向应用接口(规格 §5.7.1/§5.7.2):
* - 权威列表 = launcher 扫描 MeowOS/fonts/<family>/<weight>/ 后落盘的持久文件
* MeowOS/config/fonts/index(CSV:family,weight,path,label,tier,glyph_count)。
* app 只经本接口读该列表(不直接拼路径、不依赖 launcher 内存数组)。
* - 渲染仍走 env MEOW_FONT_PNG/MEOW_FONT_IDX(launcher 注入的「当前生效字体」,
* 选中字体那一套);本节的 get_available_count/enumerate 只负责「列有哪些库」,
* select_by_id 负责「app 会话内固定用哪套」。两路明确。
* - 无卡 / 无 index → 仅 1 项板载默认(family=default)。 */
#ifndef MEOW_FONT_INFO_DEFINED
#define MEOW_FONT_INFO_DEFINED
typedef struct meow_font_info {
char family[64]; /* family slug = MeowOS/fonts/<family>/ 一级目录名 */
char name[64]; /* 显示名(index 无单列 → 回退 family) */
char weight[32]; /* weight slug(regular|bold|…,缺省 regular) */
char tier[8]; /* 档位 common|gbk|full(info 用) */
int glyph_count; /* font.json glyph_count(info 用) */
char label[128]; /* index 显示名(含字重 + 尺寸标记) */
int size_list[16]; /* 原生字号表(index 无 → 空) */
int size_count; /* 有效字号数 */
int bit_depth; /* 4|8(index 无 → 0) */
char path_png[320]; /* 卡根相对 MeowOS/fonts/<family>/<weight>/font.png */
} meow_font_info;
#endif
/* 可用字库数(含默认;无卡 → 1)。 */
int meow_font_get_available_count(void);
/* 按序号取:idx=0=默认行(family=default);越界返回 0。 */
int meow_font_enumerate(int idx, meow_font_info *out);
/* 选该套为 app 会话默认字体:id=0 跟随系统默认(font.file,经 env);id>0 固定用该套。
* 该套字库缺失 → 降级默认(不丢请求)+ WARN(meow_log→app 日志)。成功 0,越界负值。 */
int meow_font_select_by_id(int id);
/* ============================================================ */
/* §10 字体分层 / 大字库(M2.5x:基座声明 + font 域已实现按档装载) */
/* ============================================================ */
/* 字体「档位」概念:launcher 按 app.json 声明的字库档("fonts":<档>)向 app 注入
* MEOW_FONT_TIER=<0|1|2>;SDK(meow_ui_gfx / meow_font 大字库加载)据档选库:
* MEOW_FONT_TIER_COMMON=0 默认 4K 常用字库;
* MEOW_FONT_TIER_GBK =1 大字库 GBK;
* MEOW_FONT_TIER_FULL =2 Full(全字符集)。
* 大字库生成由 font/gen/gen_font.py --charset 按档产出;按档装载由 meow_font_reload_tier()
* 实现(先 unload 旧再 load 新,释放旧 atlas 防大字库双驻留)。launcher 经
* meow_font_effective_paths_tiered() 按档解析大字库绝对路径并注入 MEOW_FONT_PNG/IDX。
* 既有 meow_font_* 符号(class_of/has_glyph/load_slot/config_multifont…)保留不动。
* 判缺字:meow_font_has_glyph(cp) 预判当前字库是否含该码位。 */
#define MEOW_FONT_TIER_COMMON 0
#define MEOW_FONT_TIER_GBK 1
#define MEOW_FONT_TIER_FULL 2
/* 设当前字体档(0/1/2,越界 clamp 到合法值),返回生效档。
* meow_ui_gfx.c 定义并触发 meow_font_reload_tier() 真重载(大字库切换释放旧 atlas)。 */
int meow_font_set_tier(int tier);
/* 当前字体档(初始 = MEOW_FONT_TIER_COMMON;meow_ui_init 时读 MEOW_FONT_TIER env 对齐)。 */
int meow_font_tier(void);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_FONT_H */
+36
View File
@@ -0,0 +1,36 @@
/*
* meow_ui_image.h — SDK 图片层(§4,B1)。
*
* 原 meow_ui.h 拆分的一部分(image 模块)。内部 stb_image(单头文件,静态编入 meow_ui.a)
* 解 PNG/JPEG/BMP,统一转 RGBA。meow_img 为不透明句柄(前向声明见 meow_ui_types.h)。
*/
#ifndef MEOW_UI_IMAGE_H
#define MEOW_UI_IMAGE_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §4 图片层 */
/* ============================================================ */
typedef struct meow_img meow_img; /* 句柄,由 meow_img_* 管理,不透明 */
meow_img *meow_img_load_file(const char *path); /* 内部读文件 + stb 解码 */
meow_img *meow_img_load_mem(const void *buf, int len);
void meow_img_free(meow_img *img);
int meow_img_w(meow_img *img);
int meow_img_h(meow_img *img);
void meow_ui_img(int x, int y, meow_img *img); /* 原始尺寸 */
void meow_ui_img_scaled(int x, int y, int w, int h, meow_img *img); /* 最近邻缩放 */
void meow_ui_img_alpha(int x, int y, int w, int h, meow_img *img, int alpha);
void meow_ui_img_cover(int x, int y, int size, meow_img *img); /* 居中裁方 → size×size */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_IMAGE_H */
+46
View File
@@ -0,0 +1,46 @@
/*
* meow_ui_ime.h — SDK 输入法(§5.1,B1):内置触屏软键盘。
*
* 原 meow_ui.h 拆分的一部分(ime 模块)。仅英文 QWERTY / 数字 / 中文拼音(ASCII/NUM/PINYIN)。
* 输入事件循环/触摸命中优先级见 meow_ui_input.h 相关约定(IME 弹出时吞触摸)。
*/
#ifndef MEOW_UI_IME_H
#define MEOW_UI_IME_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §5.1 输入法(IME)—— 内置触屏软键盘(仅英文 QWERTY / 数字,ASCII) */
/* ============================================================ */
/* 输入法模式(尾部追加枚举:ASCII/NUM 值不变,零 ABI 回归)。PINYIN=中文拼音(meow_ui_ime.c)。 */
typedef enum { MEOW_IME_ASCII, MEOW_IME_NUM, MEOW_IME_PINYIN } meow_ime_mode;
typedef struct meow_ime_ctx {
meow_ime_mode mode;
char buf[256]; /* 输入缓冲(初始值可预填) */
int maxlen; /* 最大字符数(含 NUL 预算) */
void (*on_change)(const char *text, void *ctx); /* 每次字符变化回调一次 */
void *ctx;
} meow_ime_ctx;
/* 阻塞:弹出键盘直到关闭(ESC / 点背景取消);回车=只提交不关闭(内容经 on_change 实时同步)。
* 关闭路径返回 0(取消);提交内容经 on_change 回调逐键同步,不依赖返回值回填 buf。 */
int meow_ui_text_input(meow_ime_ctx *ctx);
/* 非阻塞:返回后 app 在 on_tick 里轮询 meow_ime_active()/meow_ime_text() */
void meow_ui_text_input_async(meow_ime_ctx *ctx);
int meow_ime_active(void);
const char *meow_ime_text(void);
/* 拼音模式组合态:当前拼音组合串(去声调小写,如 "nihao")供 App 渲染字段预览;
* 无组合(或非拼音模式)返回 ""。组合串是 IME 内部态,不写入字段(§4.2)。 */
const char *meow_ime_composition(void);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_IME_H */
+64
View File
@@ -0,0 +1,64 @@
/*
* meow_ui_input.h — SDK 输入层 / 生命周期(§6,B1)+ 通用长按(§6.3,2026-08-31)。
*
* 原 meow_ui.h 拆分的一部分(input 模块)。物理键为系统语义(SDK 不下发 on_key 映射为确认/exit),
* App 只响应触摸/滑动;事件循环阻塞到 meow_ui_request_exit。
*/
#ifndef MEOW_UI_INPUT_H
#define MEOW_UI_INPUT_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §6 输入层 / 生命周期(B1) */
/* ============================================================ */
typedef struct meow_ui_events {
void (*on_key)(int keycode, int is_down); /* M2.24:物理键为系统语义,SDK 不下发;回调保留(应用不映射键为确认/exit) */
void (*on_tap)(int x, int y); /* 触摸抬起落点 */
void (*on_swipe)(int dir, int dx, int dy); /* 左滑=返回(左缘起点+抬手触发) */
void (*on_tick)(void); /* 空闲周期回调(动画/时钟) */
void (*on_swipe_progress)(int x_start, int dx);/* 左缘返回手势过程实时回调;x_start=按下X, dx=当前X-按下X */
/* M2.71-bug2/6:拖动过程回调(跟手)。on_touch_down=按下后首个有效坐标(起点);
* on_touch_move=拖动中坐标变化(坐标变了才回调)。用于 slider 拖动 / 列表/页面滚动跟手。
* 均在 IME 弹出或模态阻塞时被吞(键盘/模态优先喂)。可 NULL。 */
void (*on_touch_down)(int x, int y);
void (*on_touch_move)(int x, int y);
} meow_ui_events;
void meow_ui_run(const meow_ui_events *ev); /* 阻塞:事件循环,直到 meow_ui_request_exit */
void meow_ui_request_exit(void); /* 请求退出(相当于返回/退出键) */
/* 顶部左滑进度条(视觉反馈):画一条 5px 高、从 x=0 到 x 的横条(主题 accent 色)。
* x<=0 时清掉此前画的条(填回背景色)。不发 flush,由调用方 meow_ui_flush_region 上屏。 */
void meow_ui_swipe_hint(int x);
/* ============================================================ */
/* §6.3 通用长按(2026-08-31) */
/* ============================================================ */
/* 控件按下 ≥ 阈值(默认 500ms,可配)未抬手、且按下后位移 ≤ 容忍(超移动/抬手取消)
* → 触发一次长按回调;坐标 = 触发时刻的按下点(App 据此 meow_widget_hit / meow_listview_hit
* 判定命中哪个控件/行,与 on_tap 同一套命中流程)。
*
* **opt-in**:注册回调(meow_ui_set_long_press_cb)才启用长按判定;未注册时行为与之前完全一致
* (按压不触发长按、抬手照常 TAP/SWIPE)——hello 等不使用长按的 App 零回归。
*
* 与 pressed 状态机共存:按压视觉态(MEOW_WS_PRESSED / 按住加深)不变;短按(未达阈值或
* 抬手先于阈值)仍正常触发 on_tap 点击;长按已触发后其抬手**不再产生 TAP/SWIPE**(SDK 抑制
* 点击,App 无需自行吞掉后续 tap)。
*
* 注册经独立 set 接口:**不做进 meow_ui_events**——避免给既有 App(hello/files)按位置初始化
* meow_ui_events 的写法在 -Wextra 下引入「缺省成员」告警(_missing-field-initializers),
* 保持 SDK 头向后兼容。 */
typedef void (*meow_long_press_fn)(int x, int y);
void meow_ui_set_long_press_cb(meow_long_press_fn cb); /* 注册/更换回调;NULL=取消 */
void meow_ui_set_long_press_ms(int ms); /* 长按阈值(ms);<=0 恢复默认 500 */
int meow_ui_long_press_ms(void); /* 当前阈值(默认 500) */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_INPUT_H */
+32
View File
@@ -0,0 +1,32 @@
/*
* meow_ui_log.h — SDK 应用日志(§9,统一日志 API,M2.51 最小可用版)。
*
* 原 meow_ui.h 拆分的一部分(log 模块)。app 只需一行 meow_log();SDK 管「写哪/怎么写/过滤/降级/上限」。
*/
#ifndef MEOW_UI_LOG_H
#define MEOW_UI_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §9 应用日志(统一日志 API,M2.51 最小可用版) */
/* ============================================================ */
/* app 只需一行 meow_log();SDK 管「写哪/怎么写/过滤/降级/上限」:
* - 路径:<MEOW_LOG_DIR>/<启动时间>_<pid>.log(MEOW_LOG_DIR 已含包名分层 logs/<包名>)
* (目录不存在 mkdir -p,按 app 分目录),每次启动=新文件,同一次启动内 O_APPEND 追加;
* - 级别过滤:lvl < meow_log_get_level() 丢弃;默认 MEOW_LOG_INFO;
* - 格式:<monotonic_ms> [<app_id>] <LEVEL> message\n;
* - 上限:单文件 ≥2MB 自动开新文件追加 _<n>;每 App 总量 ≥50MB 按期删最旧,防撑爆卡;
* - 无卡/写失败降级 stderr,不阻塞 app 不崩;线程安全。
* 注意:MEOW_LOG_APP 由 launcher 注入;未注入时默认 app_id="app"。 */
typedef enum { MEOW_LOG_DEBUG=0, MEOW_LOG_INFO, MEOW_LOG_WARN, MEOW_LOG_ERROR } meow_log_level;
void meow_log(meow_log_level lvl, const char *fmt, ...); /* app 一行调用,写到按 app 分离日志 */
void meow_log_set_level(meow_log_level lvl); /* 可选:app 设本 app 级别;默认 MEOW_LOG_INFO */
meow_log_level meow_log_get_level(void);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_LOG_H */
+98
View File
@@ -0,0 +1,98 @@
/*
* meow_ui_notify.h — SDK 应用通知(§9.1,meow_notify_*,M2.53 最小可用版)。
*
* 原 meow_ui.h 拆分的一部分(notify 模块)。app 只需声明类型 + meow_notify_send() 即可发通知,
* SDK 管配额/活动表/降级。本阶段 SDK 内部维护活动通知表 + 用 meow_log() 打日志作为落点;
* 真实投递到通知中心 UI / D-Bus 是后续任务(本结构已对齐 freedesktop 字段为此预留)。
*/
#ifndef MEOW_UI_NOTIFY_H
#define MEOW_UI_NOTIFY_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §9.1 应用通知(meow_notify_*,M2.53 最小可用版) */
/* ============================================================ */
/* app 只需声明类型 + meow_notify_send() 即可发通知,SDK 管配额/活动表/降级:
* - 类型注册:app 声明支持的类型(最多 MEOW_NOTIFY_MAX_TYPES 4 种);
* meow_notify_send 也会自动注册未声明类型(受同样 4 种上限约束);
* - 配额(NOTIFICATION_SYSTEM.md §7,2026-08-29 用户拍板):每 App 最多 4 种类型;
* 每类型活动(未过期)通知上限 4,满则丢最旧(替换);媒体类型单例(每 app 仅
* 保留最近 1 条,重发替换——可多媒体 App);
* - 超时语义 [实现定案,沿用 NOTIFICATION_SYSTEM.md §2]:timeout_ms>0 = 过期毫秒数;
* 0 = 不自动过期(直到 meow_notify_cancel);-1 = 常驻(ONGOING),同样不自动过期;
* - 落点:本阶段 SDK 内部维护活动通知表 + 用 meow_log() 打日志作为落点;真实投递到
* 通知中心 UI / D-Bus(org.freedesktop.Notifications)是后续任务——本结构已对齐
* freedesktop 字段(summary/body/…)为此预留,但不写死后端;
* - 线程安全;不依赖 /dev/fb0、不依赖板子,可宿主编译。 */
#define MEOW_NOTIFY_MAX_TYPES 4 /* 每 App 最多 4 种通知类型 */
#define MEOW_NOTIFY_MAX_PER_TYPE 4 /* 每类型活动(未过期)通知上限 */
#define MEOW_NOTIFY_MAX_MEDIA 1 /* 媒体通知每 App 仅 1 条(单例) */
#define MEOW_NOTIFY_TIMEOUT_ONGOING (-1) /* 常驻(ONGOING),不自动过期 */
#define MEOW_NOTIFY_TIMEOUT_NEVER 0 /* 不自动过期,直到取消 */
/* 通知分类(freedesktop.org Desktop Notifications 的 category 最小子集 [实现定案]) */
typedef enum {
MEOW_NOTIFY_CAT_GENERAL = 0, /* 通用(默认) */
MEOW_NOTIFY_CAT_MESSAGE = 1, /* 即时消息/聊天 */
MEOW_NOTIFY_CAT_EMAIL = 2, /* 邮件 */
MEOW_NOTIFY_CAT_EVENT = 3, /* 事件/日历提醒 */
MEOW_NOTIFY_CAT_PROGRESS = 4, /* 进度/下载 */
MEOW_NOTIFY_CAT_MEDIA = 5, /* 媒体播放(MPRIS;每 app 单例) */
MEOW_NOTIFY_CAT_COUNT = 6, /* 边界哨兵(非合法类型) */
} meow_notify_category;
/* 紧急度(UI 视觉分级 + 提示音/震动强弱) */
typedef enum {
MEOW_NOTIFY_URG_LOW = 0, /* 低:仅进通知中心,不打扰 */
MEOW_NOTIFY_URG_NORMAL = 1, /* 普通 */
MEOW_NOTIFY_URG_HIGH = 2, /* 高:顶部横幅 + 提示音 */
MEOW_NOTIFY_URG_CRITICAL = 3, /* 紧急:需立刻注意 */
MEOW_NOTIFY_URG_COUNT = 4, /* 边界哨兵(非合法值) */
} meow_notify_urgency;
/* 发送负载(对齐 freedesktop Notify() 字段;SDK 内部复制副本,不持 app 外部指针,
* app 只需保证 icon/title/body/target_activity 指针在调用返回前有效)。 */
typedef struct meow_notify {
meow_notify_category cat; /* 类型(未声明则按 4 种上限自动注册) */
meow_notify_urgency urgency; /* 紧急度(缺省 MEOW_NOTIFY_URG_NORMAL;越界钳位) */
const char *title; /* summary:标题,单行(必填,NULL 则发送失败) */
const char *body; /* body:正文,可多行(可 NULL) */
const char *icon; /* app_icon:图标 icon name 或 path;NULL/空 = 用该 app 默认图标(launcher 按 app_id 回退) */
int timeout_ms; /* 见上超时语义;推荐 MEOW_NOTIFY_TIMEOUT_* */
const char *target_activity; /* 通知中心点击跳转的 Activity 名(可 NULL;M3 导航预留) */
int progress; /* 进度 0-100;-1=不显示进度条(缺省 -1) */
} meow_notify;
/* 类型注册:app 声明支持的类型。0=成功;-1=已声明/已达 4 种上限/非法。 */
int meow_notify_register_type(meow_notify_category cat);
/* 发送一条通知。返回通知 id(用于 meow_notify_cancel);失败返回 0。
* 同类型满 4 条时丢弃最旧(替换);媒体类型单例(重发替换同 app 上一条媒体通知)。 */
uint32_t meow_notify_send(const meow_notify *n);
/* 取消一条通知。1=成功;0=未找到(id 无效/已过期/已取消)。 */
int meow_notify_cancel(uint32_t id);
/* 实时更新一条活动通知的进度(0-100,-1=清除进度条)。local_id=meow_notify_send 的返回值。
* 语义(用户定案):仅改 SDK 内部活动槽 + 经 IPC 通知 launcher 改**内存活跃槽**;不落盘——
* TF 快照只在「创建时 / 结束(100% 或 dismiss)」触发。返回 1=找到并更新;0=未找到/非法。 */
int meow_notify_update_progress(uint32_t local_id, int progress);
/* 查询当前活动(未过期、未取消)通知数/是否还有。 */
int meow_notify_active_count(void);
int meow_notify_count_in_type(meow_notify_category cat);
int meow_notify_has_active(void); /* 1=尚有活动通知,0=无 */
/* 紧急度/分类 → 字符串("low"/"normal"/"high"/"critical"、"general"/"message"/…)。 */
const char *meow_notify_urgency_str(meow_notify_urgency u);
const char *meow_notify_category_str(meow_notify_category cat);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_NOTIFY_H */
+67
View File
@@ -0,0 +1,67 @@
/*
* meow_ui_statusbar.h — SDK 全局状态栏 / 全屏(§3.1,A-0,系统级组件)。
*
* 原 meow_ui.h 拆分的一部分(statusbar 模块)。状态栏是 SDK 内置全局组件:默认显示(时钟/电量/
* WiFi/蓝牙/音量),数据由 SDK 内置 meow_ui_sys 读取器 1s 轻刷(与 launcher 同源单点一致)。
* z 顺序最顶:meow_ui_flush() 上屏前自动把状态栏画进 back_buf 顶部行,覆盖非全屏内容;
* 非全屏 APP 需用 meow_ui_statusbar_height() 把内容下移(inset),否则被状态栏盖住。
* 注:状态栏的**渲染**仅系统进程(launcher)执行;App 进程只按本头声明控制显隐/全屏/inset。
*/
#ifndef MEOW_UI_STATUSBAR_H
#define MEOW_UI_STATUSBAR_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §3.1 全局状态栏 / 全屏(A-0,SDK 系统级组件) */
/* ============================================================ */
/* 状态栏是 SDK 内置全局组件:所有界面默认显示(时钟/电量/WiFi/蓝牙/音量,slim ~40px),
* 数据由 SDK 内置 meow_ui_sys 读取器 1s 轻刷(与 launcher 同源单点一致)。
* z 顺序最顶:meow_ui_flush() 上屏前自动把状态栏画进 back_buf 顶部行,覆盖非全屏内容;
* 非全屏 APP 需用 meow_ui_statusbar_height() 把内容下移(inset),否则被状态栏盖住。 */
/* 状态栏显隐(默认显示;APP 声明全屏则隐藏——沉浸)。 */
void meow_ui_set_statusbar(int visible); /* 1=显示(默认) 0=隐藏(全屏) */
int meow_ui_statusbar_visible(void);
/* 全屏声明:等价 app.json fullscreen:1(外观上隐藏状态栏 + 左缘返回手势/进度条——沉浸)。 */
void meow_ui_set_fullscreen(int on);
/* 状态栏高度(px,供 APP 布局上移内容,避免被盖——status bar inset);
* 全屏/隐藏时返回 0。 */
int meow_ui_statusbar_height(void);
/* ---- 状态栏「上收出屏只留提示线」(collapsed,草案/待定案——本批仅加声明)----
* 供全屏调用:把状态栏内容上移出屏顶、只留一条「提示线」高度(可下拉还原)。
* 与 meow_ui_set_fullscreen(1) 的关系:fullscreen 隐藏整条状态栏(沉浸,inset=0);
* collapsed 仍视状态栏为「激活」,左缘返回手势(SWIPE_LEFT)与顶部伸缩提示线
* (meow_ui_swipe_hint)依旧生效,只是其内容上收、仅留提示线——用于「不完全沉浸」,
* 保留一处可下拉拉出状态栏的入口。顶部下滑热区 meow_ui_statusbar_hotzone() 在全屏时缩小。
* 实现位置:meow_ui_gfx.c(基座让 on 生效:true→只画提示线/内容上移);逐帧过渡动画
* (上收/恢复插值)为待定案,后续代理可经 meow_ui_statusbar_animate(ms) 补齐。 */
void meow_ui_statusbar_set_collapsed(int on); /* on=1 上收(内容上移出屏、只留提示线);on=0 恢复 */
int meow_ui_statusbar_collapsed(void); /* 当前是否处于「上收」目标(1=是) */
void meow_ui_statusbar_animate(int ms); /* TBD:上收/恢复过渡时长(ms);占位,后续代理实现插值 */
/* 当前上收进度(0..MUI_SBAR_H:0=完全展开,28=内容全部上移出屏、仅留提示线)。
* 供系统进程(launcher)在 App 前台叠加顶条时读取,按「当前可见条高 = 28-offset」
* 标脏/切齐,实现收合时只 blit 可见条高、其余行保留 App 内容(平滑上收、无残留)。 */
int meow_ui_statusbar_collapse_offset(void);
/* 上收/恢复过渡是否仍在进行(current offset != target,逐帧推进中)。
* 供 launcher 在过渡期高频刷新顶条(launch_app 循环据此缩短 sleep),驱动平滑动画;稳定后回 1s 慢刷。 */
int meow_ui_statusbar_animating(void);
/* 顶部下滑热区(下拉展开状态栏/通知)高度(px)。
* 状态栏「激活」(含**收合**)时恒=整条状态栏高 MUI_SBAR_H(28)——收合只上收渲染、**不禁用顶部热区**
* (渲染与热区事件分离,全屏下顶部下滑仍开通知中心);仅「全屏隐藏」(immersive inset0)时缩小到
* MEOW_SBAR_HOTZONE_FS(保留一处下拉入口)。返回「可用于起始下拉」的热区高度。 */
int meow_ui_statusbar_hotzone(void);
#define MEOW_SBAR_HOTZONE_FS 4 /* 全屏时缩小后的顶部热区高度(px,草案值) */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_STATUSBAR_H */
+79
View File
@@ -0,0 +1,79 @@
/*
* meow_ui_theme.h — SDK 主题/配置(§8):主题模型 + MD3 语义色板 + 顶级主题风格族。
*
* 原 meow_ui.h 拆分的一部分(theme 模块)。权威结构体名 = meow_theme(App 侧),
* 与 launcher 内部的 meow_ui_theme_t(font_theme.c,仅供状态栏/设置页)无关。
*/
#ifndef MEOW_UI_THEME_H
#define MEOW_UI_THEME_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §8 主题/配置 */
/* ============================================================ */
typedef enum { MEOW_THEME_LIGHT, MEOW_THEME_DARK, MEOW_THEME_AUTO } meow_theme_mode;
/* 主题(§5.8.4 + §8.1.3)。既有字段 bg/fg/accent/dim 保留(兼容映射,见下表),
* 其后追加 MD3 语义色板 + 风格参数段(扩展兼容——既有代码读旧字段不受影响)。
* 映射:bg↔surface、fg↔onSurface、accent↔primary、dim↔onSurfaceVariant。
* 「当前 style×mode」完整主题 = meow_theme_get()(MD3 默认;MIUIx 用 MD3 基础/占位)。 */
typedef struct meow_theme {
/* —— 既有字段(兼容保留;映射见上)—— */
uint32_t bg; /* 背景色 = surface */
uint32_t fg; /* 前景/正文 = onSurface */
uint32_t accent; /* 强调色(按钮/选中)= primary */
uint32_t dim; /* 次要文字 = onSurfaceVariant */
int font_title; /* 28 */
int font_body; /* 20 */
/* —— MD3 语义色板(§5.8.4;日/夜各一组,AUTO 按 meow_theme_mode 切换)—— */
uint32_t primary, onPrimary, primaryContainer, onPrimaryContainer;
uint32_t secondary, onSecondary, secondaryContainer, onSecondaryContainer;
uint32_t tertiary, onTertiary, tertiaryContainer, onTertiaryContainer;
uint32_t surface, onSurface, surfaceVariant, onSurfaceVariant;
uint32_t surfaceContainerLowest, surfaceContainerLow, surfaceContainer,
surfaceContainerHigh, surfaceContainerHighest;
uint32_t surfaceDim, surfaceBright, surfaceTint;
uint32_t outline, outlineVariant, scrim;
uint32_t error, onError, errorContainer, onErrorContainer;
uint32_t inverseSurface, inverseOnSurface, inversePrimary;
uint32_t shadow; /* 仅状态层/描边近似用;无 GPU 不做投影(§5.8.7) */
/* —— 风格参数段(§8.1.3;MD3 默认 / MIUIx 加大圆角+描边+间距)—— */
int radius; /* 控件默认圆角(按钮等,px) */
int radius_card; /* 卡片/容器默认圆角(px) */
int spacing; /* 布局/间距步进(px) */
int stroke_w; /* 默认细描边宽(0=无边框,MD3;MIUIx=1) */
} meow_theme;
const meow_theme *meow_theme_get(void);
void meow_theme_set_mode(meow_theme_mode m);
meow_theme_mode meow_theme_get_mode(void);
typedef void (*meow_theme_listener)(meow_theme_mode m);
void meow_theme_add_listener(meow_theme_listener cb);
void meow_theme_remove_listener(meow_theme_listener cb);
/* [D4] 脱机访问两套内置色板(无 settings 文件也可靠):返回当前解析生效的色板副本。 */
meow_theme meow_theme_defaults(meow_theme_mode m);
/* ---- §8.1 顶级主题风格族(minimal,2026-08-30)----
* 主题 = 顶级主题风格族(ui.style:MD3/MIUIx)× 明暗(display.theme)。本批只落「状态栏图标集
* 随 ui.style 换集」的最小闭环:meow_ui_set_style 记录 style(同值忽略)+ 触发 theme_reload/
* 广播(让状态栏/控件下一帧用新 style 重绘)。style 还决定状态栏右侧图标集(§3.1 同一个状态栏)。
* 完整 style×mode 配色/控件形态矩阵(§8.1.3)为后续里程碑。 */
#define MEOW_STYLE_MD3 0 /* Material You(默认) */
#define MEOW_STYLE_MIUIX 1 /* MIUI 风格族(基础占位) */
void meow_ui_set_style(int style); /* 设顶级主题风格族;越界 clamp 到合法值;同值忽略 */
int meow_ui_style(void); /* 当前 style(默认 MEOW_STYLE_MD3) */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_THEME_H */
+43
View File
@@ -0,0 +1,43 @@
/*
* meow_ui_types.h — SDK 公共核心类型与常量(无依赖基础层)。
*
* 原 meow_ui.h 拆分的一部分:本头只含「无模块依赖」的基础件——
* - 物理键 keycode(内核 input.h 常用值;KEEP 与 launcher/settings 一致)
* - 滑动方向(on_swipe 的 dir 参数)
* - 各模块共用的不透明句柄前向声明(meow_widget / meow_img)
* 其它所有子头/App 经 #include 本头获得这些基础件;伞头 meow_ui.h 聚合它。
*/
#ifndef MEOW_UI_TYPES_H
#define MEOW_UI_TYPES_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* 物理键 keycode(内核 input.h 常用值;KEEP 与 launcher/settings 一致) */
/* ============================================================ */
#define MEOW_KEY_POWER 116
#define MEOW_KEY_VOLUMEDOWN 114
#define MEOW_KEY_VOLUMEUP 115
#define MEOW_KEY_PLAYPAUSE 164
#define MEOW_KEY_PREVIOUS 165 /* KEY_PREVIOUSSONG=165(上一曲;19 是另一码,勿混用) */
#define MEOW_KEY_NEXT 163 /* KEY_NEXTSONG */
/* 滑动方向(on_swipe 的 dir 参数) */
#define MEOW_SWIPE_LEFT 0
#define MEOW_SWIPE_RIGHT 1
#define MEOW_SWIPE_UP 2
#define MEOW_SWIPE_DOWN 3
/* ---- 不透明句柄(各 App/子头共用;具体结构定义在对应实现 TU)---- */
typedef struct meow_widget meow_widget; /* 控件(meow_ui_widget.c) */
typedef struct meow_img meow_img; /* 图片句柄(meow_ui_img.c) */
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_TYPES_H */
+297
View File
@@ -0,0 +1,297 @@
/*
* meow_ui_widgets.h — SDK 控件层(§5 控件)+ 控件层升级(§5.8 基座)+ Material 3 组件子集(§5.8.6)
* + 结构化列表 W_LISTVIEW(§5.5)。
*
* 原 meow_ui.h 拆分的一部分(widgets 模块)。依赖 meow_ui_theme.h(meow_theme/MD3 色板/风格参数)
* 与 meow_ui_ime.h(meow_ime_mode,TextField 接 IME);meow_img 为不透明句柄(meow_ui_types.h)。
* 向后兼容:既有 create 签名一字不改,只在上面扩展(Options/状态机走新增挂载器)。
*/
#ifndef MEOW_UI_WIDGETS_H
#define MEOW_UI_WIDGETS_H
#include "meow_ui_types.h"
#include "meow_ui_theme.h"
#include "meow_ui_ime.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §5 控件层 */
/* ============================================================ */
typedef struct meow_widget meow_widget;
meow_widget *meow_btn_create(int x, int y, int w, int h, const char *label);
meow_widget *meow_slider_create(int x, int y, int w, int min, int max, int val);
meow_widget *meow_switch_create(int x, int y, int on);
/* 列表数据源回调:idx 有效时填 label 并返回 1;越界返回 0([D2] 定案签名) */
typedef int (*meow_list_source)(int idx, char *label, int len, void *ctx);
meow_widget *meow_list_create(int x, int y, int w, int h, int count,
meow_list_source src, void *ctx);
void meow_widget_free(meow_widget *w);
void meow_widget_draw(meow_widget *w); /* 每次 flush 前调用 */
int meow_widget_hit(meow_widget *w, int x, int y); /* 点是否落在控件内 */
void meow_slider_set(meow_widget *s, int val);
int meow_slider_get(meow_widget *s);
void meow_switch_set(meow_widget *w, int on);
int meow_switch_get(meow_widget *s);
int meow_btn_pressed(meow_widget *w); /* 应用在 on_tap 命中后标记按下 */
/* ============================================================ */
/* §5.8 控件层升级(第一批=通用基座):Options / 状态机 / 自定义画布 / 布局 */
/* ============================================================ */
/* ---- §5.8.2 Modifier 式通用 Options(轻量结构体,非链式 DSL)----
* 经 meow_widget_set_opts 一次性挂载,作用于任意控件(标准/自定义)。全部控件共用。
* 哨兵语义:bg/fg==0=用控件/主题默认;stroke==0=无描边;stroke_w=描边宽;
* radius==-1=控件默认(如按钮 10),>=0=指定圆角(0=直角);pad/margin=0=无;
* disabled/selected=1=置位(立即反映到状态机位)。 */
typedef struct meow_widget_opts {
uint32_t bg; /* 背景色(0=控件/主题默认) */
uint32_t fg; /* 前景/文字(0=主题 onSurface) */
uint32_t stroke; /* 描边色(0=无描边) */
int stroke_w; /* 描边宽(px) */
int radius; /* 圆角(px;-1=控件默认,如按钮 10) */
int pad_x; /* 内边距(水平,px) */
int pad_y; /* 内边距(垂直,px) */
int margin_x; /* 外边距(水平,px;布局用) */
int margin_y; /* 外边距(垂直,px;布局用) */
int disabled; /* 1=禁用(视觉变暗 + 不响应命中,见状态机 §5.8.3) */
int selected; /* 1=选中(列表高亮/勾选,见状态机 §5.8.3) */
} meow_widget_opts;
/* 挂载:作用于任意控件(标准/自定义)。w 内部浅拷这份 opts。
* 返回 0=成功;NULL/无效=负值(不销毁 w)。 */
int meow_widget_set_opts(meow_widget *w, const meow_widget_opts *opts);
/* 取回当前 opts(浅拷到 out;0=成功)。自定义画布用它读通用修饰。 */
int meow_widget_opts_get(const meow_widget *w, meow_widget_opts *out);
/* ---- §5.8.3 统一状态机(enabled / selected / focused / pressed)----
* 标准/自定义控件共用;visual 层由 SDK/App 按状态位叠。enabled=0 阻断 hit/pressed。 */
#define MEOW_WS_ENABLED (1u<<0)
#define MEOW_WS_SELECTED (1u<<1)
#define MEOW_WS_FOCUSED (1u<<2)
#define MEOW_WS_PRESSED (1u<<3)
/* 设/查状态(置位/清位,其它位不动)。on=1 置位 / 0 清位。 */
void meow_widget_set_state(meow_widget *w, unsigned bits, int on);
unsigned meow_widget_state(const meow_widget *w);
/* 便捷:禁用/启用、选中/取消(单态等效于 set_state)。 */
int meow_widget_enabled(const meow_widget *w);
void meow_widget_set_enabled(meow_widget *w, int on);
int meow_widget_selected(const meow_widget *w);
void meow_widget_set_selected(meow_widget *w, int on);
/* 一键叠状态层(自定义画布可选):把 pressed/focused/disabled/selected 的视觉层
* 叠到 w 的矩形上(半透明状态层 + 焦点描边)。标准控件由 SDK 自动叠,无需调用;
* 自定义画布在 render_cb 里画完内容后可调它(App 也可据 meow_widget_state 自行叠)。 */
void meow_widget_draw_state_layer(meow_widget *w, const meow_theme *th);
/* ---- §5.8.1 自定义画布(App 提供 render/hit 回调;同一个 meow_widget)----
* render:SDK 在 meow_widget_draw 时调用,th=当前生效主题(MD3 语义色板);
* w 的 x/y/w/h 已就位;App 用 §3/§4 绘制 API 自绘(往 back_buf 画)。
* hit :命中判定,App 自定义(如圆形/区域外镂空);返回 1=命中。 */
typedef void (*meow_widget_render_fn)(meow_widget *w, const meow_theme *th, void *ctx);
typedef int (*meow_widget_hit_fn)(meow_widget *w, int x, int y, void *ctx);
/* 创建:自定义画布(x,y,w,h = 绝对坐标,同既有控件)。
* 生命周期/Activity 归属:创建时绑定当前 active Activity(同 meow_btn_create,§6.1 ①);
* 命中走 hit_cb(先过 owner==active + enabled 双闸门)。 */
meow_widget *meow_widget_custom_create(int x, int y, int w, int h,
meow_widget_render_fn render_cb,
meow_widget_hit_fn hit_cb,
void *ctx);
/* ---- §5.8.5 可组合布局(Row / Column / Box + Spacer)----
* 布局容器 = meow_widget(W_LAYOUT);arrange 把子控件算成绝对坐标(写进各 child 的
* x/y/w/h)→ 与现有绝对定位完全兼容(draw/hit/flush_region/owner 闸门照常)。
* 本批先支持固定尺寸子项(w/h 均已知);弹性(w/h==0)为后续增强。 */
enum { MEOW_LAYOUT_ROW = 0, MEOW_LAYOUT_COLUMN = 1, MEOW_LAYOUT_BOX = 2 };
meow_widget *meow_row_create(int x, int y, int w, int h, int spacing);
meow_widget *meow_column_create(int x, int y, int w, int h, int spacing);
meow_widget *meow_box_create(int x, int y, int w, int h);
/* 添加子控件(子可为普通控件/自定义/另一布局/Spacer)。返回 0=成功;无效=负值。 */
int meow_layout_add(meow_widget *layout, meow_widget *child);
/* 计算子控件绝对坐标(写入各 child 的 x,y,w/h;嵌套布局递归);此后照常 draw/hit。 */
void meow_layout_arrange(meow_widget *layout);
/* 固定尺寸空白(也作撑余量;不可见,hit 恒 0)。 */
meow_widget *meow_layout_spacer(int w, int h);
/* ============================================================ */
/* §5.8.6 Material 3 组件子集(第二批,基于第一批基座:Options + 状态机 + MD3 色板 + 布局)
* 每个组件 = 新增 meow_widget 类型或组合既有模板的便捷函数;复用主题语义色(th->primary /
* surfaceContainer / outline / ...)+ 风格参数(radius/radius_card/spacing/stroke_w)+ 通用
* Options(meow_widget_set_opts 对它们同样生效)+ 状态机(enabled/selected/pressed/focused)。
* 向后兼容:既有 create 签名一字不改;本批只在其上扩展。 */
/* ============================================================ */
/* ---- Button 五型(meow_btn 扩展;既有 meow_btn_create = FILLED)---- */
enum {
MEOW_BTN_FILLED = 0, /* primary 底 / onPrimary 文 */
MEOW_BTN_TONAL = 1, /* secondaryContainer 底 / onSecondaryContainer 文 */
MEOW_BTN_OUTLINED = 2, /* 透明底 / primary 文 / primary 描边 */
MEOW_BTN_TEXT = 3, /* 透明底 / primary 文 / 无描边 */
MEOW_BTN_ELEVATED = 4, /* surfaceContainerLow 底 / primary 文 */
};
meow_widget *meow_btn_create_variant(int x, int y, int w, int h, const char *label, int variant);
int meow_btn_set_variant(meow_widget *w, int variant); /* 越界 clamp;0=成功 */
/* ---- TextField(单行文本输入,接 IME §5.1)---- */
/* placeholder=提示文案;buf=App 持有的文本缓冲(组件不回拷,只绘制/编辑其上);maxlen=含 NUL 预算 */
meow_widget *meow_textfield_create(int x, int y, int w, int h, const char *placeholder,
char *buf, int maxlen, meow_ime_mode mode);
void meow_textfield_set_placeholder(meow_widget *w, const char *placeholder);
/* 聚焦并打开**阻塞** IME(同 meow_ui_text_input 内层轮询);回车不关闭键盘,ESC/点背景关闭。
* 内容经 on_change 实时同步到 w->buf(返回值关闭路径为 0,提交不依赖返回值回填)。 */
int meow_textfield_activate(meow_widget *w);
const char *meow_textfield_text(meow_widget *w);
/* ---- Card(圆角容器卡片;surfaceContainerLow 底 + 可选描边/状态层)---- */
meow_widget *meow_card_create(int x, int y, int w, int h);
/* 内容子控件:绘制时递归绘到卡片内(卡片 hit 仍为矩形;子控件独立命中) */
void meow_card_set_content(meow_widget *card, meow_widget *child);
/* ---- Divider(分隔线;vertical=1 纵向)---- */
meow_widget *meow_divider_create(int x, int y, int len, int vertical);
/* ---- Badge(角标;count=0 红点 / >0 数字 / <0 隐藏;cx,cy=锚点=角标中心)---- */
meow_widget *meow_badge_create(int cx, int cy);
void meow_badge_set(meow_widget *w, int count);
/* ---- Checkbox / Radio(勾选态走 meow_widget_set_selected/meow_widget_selected)---- */
meow_widget *meow_checkbox_create(int x, int y);
meow_widget *meow_radio_create(int x, int y);
/* ---- ProgressBar(线性/圆形;value=0-100 确定性,-1=不定)---- */
meow_widget *meow_progress_create(int x, int y, int w, int h, int value); /* 线性 */
meow_widget *meow_progress_circular_create(int cx, int cy, int r, int value); /* 圆形 */
void meow_progress_set(meow_widget *w, int value); /* -1=不定 */
/* ---- FloatingActionButton(悬浮按钮;圆角胶囊,无投影仅状态层近似)---- */
meow_widget *meow_fab_create(int x, int y, int size, const char *label);
/* ---- TopAppBar(顶部标题栏:标题 + 返回 + 动作)---- */
meow_widget *meow_topappbar_create(int x, int y, int w, int h, const char *title);
void meow_topappbar_set_title(meow_widget *w, const char *title);
void meow_topappbar_set_back(meow_widget *w, int on); /* 1=显示返回箭头 */
int meow_topappbar_add_action(meow_widget *w, const char *label); /* 返回动作下标 */
#define MEOW_TOPBAR_BACK (-2)
int meow_topappbar_hit(meow_widget *w, int x, int y); /* MEOW_TOPBAR_BACK=返回 idx>=0=动作 -1=无 */
/* ---- NavigationBar(底部导航栏)---- */
meow_widget *meow_navigationbar_create(int x, int y, int w, int h);
int meow_navigationbar_add_item(meow_widget *w, const char *label);
void meow_navigationbar_set_selected(meow_widget *w, int idx);
int meow_navigationbar_selected(meow_widget *w);
int meow_navigationbar_hit(meow_widget *w, int x, int y); /* 返回项下标/-1 */
/* ---- TabBar(顶部分页页签;swipe 联动 §5.2 由 App 在 on_swipe 驱动)---- */
meow_widget *meow_tabbar_create(int x, int y, int w, int h);
int meow_tabbar_add_tab(meow_widget *w, const char *label);
void meow_tabbar_set_selected(meow_widget *w, int idx);
int meow_tabbar_hit(meow_widget *w, int x, int y); /* 返回页签下标/-1 */
/* ---- 列表容器(LazyColumn/LazyRow:数据源回调 + 可见区虚拟化;复用 meow_list_source)
* meow_lazycolumn_create=纵向(item_h=行高);meow_lazyrow_create=横向(item_w=列宽)。
* 滚动由 App 在 on_swipe 里用 meow_list_scroll_by/set_scroll 驱动。 */
meow_widget *meow_lazycolumn_create(int x, int y, int w, int h, int item_h, int count,
meow_list_source src, void *ctx);
meow_widget *meow_lazyrow_create(int x, int y, int w, int h, int item_w, int count,
meow_list_source src, void *ctx);
void meow_list_set_scroll(meow_widget *w, int offset); /* clamp 到 [0, max_scroll] */
int meow_list_scroll(meow_widget *w);
int meow_list_max_scroll(meow_widget *w); /* max(0, count*item - viewport) */
void meow_list_scroll_by(meow_widget *w, int dy); /* 相对滚动(App on_swipe 用) */
int meow_list_set_item_h(meow_widget *w, int item); /* 改行高/列宽 */
int meow_list_hit_index(meow_widget *w, int x, int y); /* 命中项下标(含滚动换算);-1=未命中项/越界 */
/* M2.71-bug8:列表行选中 + 行点击回调。选中行已有高亮(现有绘制读 w->sel)。
* meow_list_tap_at:命中一行则置选中并回调 tap_cb(若设),返回该行 idx;未命中返回 -1。 */
void meow_list_set_selected(meow_widget *w, int idx); /* 选中行(越界 clamp);标脏 */
int meow_list_selected(meow_widget *w);
typedef void (*meow_list_tap_fn)(int idx, void *ctx);
void meow_list_set_on_tap(meow_widget *w, meow_list_tap_fn cb, void *ctx); /* 命中行→回调 */
int meow_list_tap_at(meow_widget *w, int x, int y); /* 命中行:置选中+回调,返回 idx/-1 */
/* ============================================================ */
/* §5.5 设计模板 A② 结构化列表(W_LISTVIEW):行=图标+标题+副标题+右侧操作 + 选中
* ------------------------------------------------------------
* 在既有「label-only」列表(meow_list_create/lazycolumn,行为不变)之上做**结构化扩展**:
* 行数据源回调逐行给出 meow_list_item(图标 / 标题 / 副标题 / 右侧操作 / 可选中),容器负责
* 绘制/滚动/选中/命中;支持单选/多选/无选择。向后兼容:既有 meow_list_* 全部保留不动。
* 颜色全部取 meow_theme_get() 语义色(日/夜/style 自动),不硬编码。
* 命中:meow_listview_hit 返回行号(含滚动换算 + 禁用行不响应);行右 1/3 为右侧操作区
* (meow_listview_hit_op 另判)。抬手用最新坐标(goodix 免疫,参照既有 W_LIST 习惯)。 */
/* ============================================================ */
/* 选中模式:无(纯入口列表)/ 单选 / 多选。 */
typedef enum { MEOW_LIST_SEL_NONE = 0, MEOW_LIST_SEL_SINGLE, MEOW_LIST_SEL_MULTI } meow_list_sel;
/* 行图标:meow_img*(MEOW_LIST_ICON_IMG)或内置符号(FOLDER/FILE,无图 App 用)。 */
typedef enum {
MEOW_LIST_ICON_NONE = 0, /* 无图标 */
MEOW_LIST_ICON_IMG, /* 用 item->icon(meow_img*) */
MEOW_LIST_ICON_FOLDER, /* 内置目录符号(填充矩形+页签) */
MEOW_LIST_ICON_FILE, /* 内置文件符号(空心矩形+折角) */
} meow_list_icon_kind;
/* 行右侧操作类型:无 / 箭头 / 开关 / 复选 / 详情钮(⋯)。 */
typedef enum {
MEOW_LIST_RIGHT_NONE = 0, /* 无右侧操作 */
MEOW_LIST_RIGHT_ARROW, /* 箭头 › */
MEOW_LIST_RIGHT_SWITCH, /* 开关(on/off = item->on) */
MEOW_LIST_RIGHT_CHECK, /* 复选标记 */
MEOW_LIST_RIGHT_MORE, /* ⋯ 详情钮 */
} meow_list_right;
/* 单行数据(回调填充到栈上,容器不长期持有)。title 必填;subtitle 可空。 */
typedef struct meow_list_item {
const meow_img *icon; /* 可选(icon_kind==MEOW_LIST_ICON_IMG 时用) */
int icon_kind; /* MEOW_LIST_ICON_*(NONE=无图标) */
const char *title; /* 主文本(必填,NULL 视为空行) */
const char *subtitle; /* 副文本,可空 */
int right; /* MEOW_LIST_RIGHT_* 右侧操作类型 */
int on; /* right==SWITCH 时开关态(0/1) */
int enabled; /* 1=可选中/可交互;0=变淡不响应命中 */
} meow_list_item;
/* 行数据源回调:idx 有效时填充 out 并返回 1;越界返回 0。每行轻量填充(不做 IO,§5.5)。 */
typedef int (*meow_list2_source)(int idx, meow_list_item *out, void *ctx);
/* 创建:视口(x,y,w,h) + 行数 count + 行数据源 + 选中模式。行高默认 56(可用 set_item_h 改)。 */
meow_widget *meow_listview_create(int x, int y, int w, int h, int count,
meow_list2_source src, void *ctx, meow_list_sel mode);
/* 行高(固定;越界/<=0 忽略)。 */
int meow_listview_set_item_h(meow_widget *lv, int item);
/* 行数(搜索过滤/懒加载/目录切换时动态更新):截断 sel 到新范围 + clamp scroll。 */
void meow_listview_set_count(meow_widget *lv, int count);
/* 滚动:set 越界 clamp 到 [0, max_scroll];by 相对滚动(App on_swipe/touch_move 用)。 */
void meow_listview_set_scroll(meow_widget *lv, int offset);
void meow_listview_scroll_by(meow_widget *lv, int dy);
int meow_listview_scroll(meow_widget *lv);
int meow_listview_max_scroll(meow_widget *lv); /* max(0, count*item_h - viewport_h) */
/* 选中集(mode 语义):
* NONE :忽略;SINGLE:set_sel(idx) 设/清(idx<0 清除);MULTI:set_sel(idx) 翻转 idx。
* get_sel 把当前选中下标写入 out[0..max),返回写入数;sel_count 返回选中总数。 */
void meow_listview_set_sel(meow_widget *lv, int idx);
int meow_listview_get_sel(meow_widget *lv, int *out, int max);
int meow_listview_sel_count(meow_widget *lv);
/* 命中:返回行号(含滚动换算;禁用行/越界返回 -1);行右 1/3 = 右侧操作区(另判)。 */
int meow_listview_hit(meow_widget *lv, int x, int y);
int meow_listview_hit_op(meow_widget *lv, int x, int y); /* 1=点在行右 1/3 操作区 */
/* 行点击回调(idx=行号;op:0=行体,1=右侧操作区)。 */
typedef void (*meow_listview_tap_fn)(int idx, int op, void *ctx);
void meow_listview_set_on_tap(meow_widget *lv, meow_listview_tap_fn cb, void *ctx);
/* 命中行:置选中 + 回调(若设)+ 返回 idx;未命中返回 -1。 */
int meow_listview_tap_at(meow_widget *lv, int x, int y);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_WIDGETS_H */
+72
View File
@@ -0,0 +1,72 @@
/*
* meow_ui_zorder.h — SDK 绘制物注册表 / z 序 / 区域重画(§6.2,合并 SDK_Z_ORDER_DESIGN)。
*
* 原 meow_ui.h 拆分的一部分(zorder/draw 注册表)。非保留模型(§5.8.7)下,把「清底 + 按 z
* 重画重叠区完整 z 栈」下沉到 SDK,让所有 App 自动获得正确的局部重画。全部 opt-in:
* 不调用本节的既有 App(widget/activity/flush 均不动)行为完全不变。
*/
#ifndef MEOW_UI_ZORDER_H
#define MEOW_UI_ZORDER_H
#include "meow_ui_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* §6.2 绘制物注册表 / z 序 / 区域重画(合并 SDK_Z_ORDER_DESIGN,源:2026-08-31)
* ------------------------------------------------------------
* 非保留模型(§5.8.7)下,把「清底 + 按 z 重画重叠区完整 z 栈」下沉到 SDK,让所有 App
* 自动获得正确的局部重画(根治 P1:下层动态控件局部重绘会把重叠区上层 chrome 抹掉)。
* - 控件(meow_widget)创建即自动注册进绘制物注册表;rect 实时读 w->x/y/w/h;
* - App 直绘的非控件内容(meow_ui_text/fill_rect 等)须显式 meow_draw_custom_register
* 注册(声明 bbox + 绘制回调),否则区域重画会漏画(非保留模型固有代价);
* - z 自动推导(子>父、同层注册先序);显式 meow_widget_set_z(999/MEOW_Z_TOP) 置顶(粘滞)。
* 用法:meow_ui_invalidate(x,y,w,h) 局部重画(清底+按 z 升序重画所有相交绘制物+上屏),
* 不整帧;meow_ui_paint_full() 整帧按 z 序重画。默认底=meow_theme bg(set_page_bg 覆盖)。
* 兼容:新 API 全部 opt-in;不调用本节的既有 App(widget/activity/flush 均不动)行为完全不变。 */
/* ============================================================ */
/* 绘制物种类:控件(自动注册)/ App 直绘内容(显式注册)。 */
typedef enum { MEOW_ITEM_WIDGET = 0, MEOW_ITEM_CUSTOM = 1 } meow_draw_kind;
typedef void (*meow_draw_fn)(void *ctx); /* CUSTOM 绘制回调(ctx 由 App 持有) */
/* ---- 层级常量(保证"子>父" + 值域远小于置顶值)---- */
#define MEOW_Z_STRIDE 16 /* 每层容器嵌套的 z 步进(子层至少 +16) */
#define MEOW_Z_DEPTH_MAX 7 /* 自动推导最大嵌套深度(0..6,>7 折叠) */
#define MEOW_Z_PER_LEVEL_MAX 15 /* 每层最多 16 槽(seq 0..15,超出折叠按注册序) */
#define MEOW_Z_AUTO_MAX (MEOW_Z_STRIDE * MEOW_Z_DEPTH_MAX + MEOW_Z_PER_LEVEL_MAX) /* 127 */
#define MEOW_Z_TOP 1000 /* 惯例"置顶"值;≥(MEOW_Z_AUTO_MAX+1)=128 即超一切自动值 */
/* 控件显式置层:z 为任意非负整数(0..INT_MAX,无上限),越大越上;z>所有其它控件即恒在最上。
* 惯例设 999(或 MEOW_Z_TOP)即"置顶"。显式 z 存于绘制注册表(按 w 反查 entry,不改
* struct meow_widget——零 ABI 破坏)且**粘滞**:不被后续自动推导覆盖;clear_z 才回退。 */
void meow_widget_set_z(meow_widget *w, int z);
int meow_widget_z(const meow_widget *w); /* 当前生效 z(显式=其值,否则=自动推导) */
void meow_widget_clear_z(meow_widget *w); /* 清除显式 z,回退自动推导 */
/* ---- 非控件直绘内容注册为绘制物(CUSTOM)----
* App 声明 bbox + 绘制回调 + 显式 z(任意非负;999=置顶);区域重画/整帧重画会画到它。
* 返回 id(供 meow_draw_unregister / meow_draw_set_z);注册表满返回 0。
* 生命周期契约:App 持有 ctx;widget 类内容不必注册(自动);离开页面前 unregister。 */
int meow_draw_custom_register(int z, int x, int y, int w, int h,
meow_draw_fn cb, void *ctx);
void meow_draw_unregister(int id); /* 注销(id 失效,勿再用) */
int meow_draw_set_z(int id, int z); /* 改 custom 显式 z;无效 id 返回 -1 */
/* 页面背景色(区域重画/整帧清底用);默认 meow_theme bg。 */
void meow_ui_set_page_bg(uint32_t color);
uint32_t meow_ui_page_bg(void);
/* 声明某区域内容已变化 → 清底(page_bg) + 按 z 升序重画所有相交绘制物 + 上屏。
* 局部(只画相交绘制物,完整 bbox——见 SDK_Z_ORDER_DESIGN §5),不整帧、不冲状态栏。 */
void meow_ui_invalidate(int x, int y, int w, int h);
/* 整帧按 z 序重画全部(set_page_bg 清底 + 全注册表按 z 升序 + 上屏)。 */
void meow_ui_paint_full(void);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_ZORDER_H */
+42 -897
View File
@@ -14,6 +14,32 @@
* [D2] meow_list_create 的数据源回调签名由实现定案(文档留占位注释)。
* [D3] meow_img_blend 内部实现补充(见 meow_ui_internal.h),非公共 API 增量。
* [D4] 增加 meow_theme_defaults()/meow_theme_current() 便于脱机(无 settings 文件)使用。
*
* ------------------------------------------------------------------
* 公共头模块索引(按模块拆分,本头为**伞头**:只做 #include 聚合,不定义新 API):
*
* include/meow_ui_types.h 核心类型/常量(物理键 keycode、滑动方向、meow_widget/meow_img 句柄)
* include/meow_ui_draw.h 绘制层(§3)+ 时间(§7)+ 刷新率调度(§7.1)
* include/meow_ui_image.h 图片层(§4)
* include/meow_ui_theme.h 主题/配置(§8:meow_theme、MD3 色板、风格族)
* include/meow_ui_ime.h 输入法(§5.1:ASCII/NUM/PINYIN 软键盘)
* include/meow_ui_widgets.h 控件层(§5 + §5.8 基座 + §5.8.6 MD3 组件 + §5.5 W_LISTVIEW)
* include/meow_ui_input.h 输入层/生命周期(§6)+ 通用长按(§6.3)
* include/meow_ui_activity.h Activity 栈 + 三层控件模型(§6.1)
* include/meow_ui_zorder.h 绘制物注册表 / z 序 / 区域重画(§6.2)
* include/meow_ui_statusbar.h 全局状态栏 / 全屏(§3.1)
* include/meow_ui_dialog.h 模态 Dialog / BottomSheet(§5.8.6)
* include/meow_ui_log.h 应用日志(§9)
* include/meow_ui_notify.h 应用通知(§9.1)
* include/meow_ui_config.h 应用配置读写(§9.2)
* include/meow_ui_font.h 字体列表(§5.7)+ 字体分层(§10)
* include/meow_ui_audio.h 独占音频客户端(§11)
*
* 其余模块头(非伞头、App 按需显式 include,均保持不动):
* meow_ui_view.h / meow_ui_nav.h / meow_ui_media.h / meow_ui_sys.h / meow_ui_vol.h
* ------------------------------------------------------------------
*
* 拆分不改变任何 API 名称/类型/宏(-Wall -Wextra 0 warning,既有 App 零改动)。
*/
#ifndef MEOW_UI_H
#define MEOW_UI_H
@@ -21,902 +47,21 @@
#include <stdint.h>
#include <stddef.h>
/* meow_config_*(§9.2)专用返回码。数值与 MEOWOS_API.md §1 的同名错误码一致,
* 但用 meow_cfg 前缀——因为 MEOW_OK/MEOW_ERR_* 这个命名空间已被共享协议头
* meow_ipc.h(枚举)与 launcher meow_settings.h(宏)占用,SDK 的 meow_notify_ipc.c
* 同 TU include meow_ui.h + meow_ipc.h,若在此定义同名宏会导致「宏展开枚举标识符」冲突。 */
#define MEOW_CFG_OK 0 /* 成功 */
#define MEOW_CFG_ERR_INVAL -1 /* 参数/取值非法(空 key、NULL out、outsz<=0 等) */
#define MEOW_CFG_ERR_NOENT -2 /* 键未设/文件不存在 */
#define MEOW_CFG_ERR_IO -5 /* 读写(存储/文件)失败 */
#define MEOW_CFG_ERR_NOMEM -6 /* 路径超长 */
#define MEOW_CFG_ERR_NODEV -10 /* 无数据目录(卡不在/只读/不可建) */
#include "include/meow_ui_types.h"
#include "include/meow_ui_draw.h"
#include "include/meow_ui_image.h"
#include "include/meow_ui_ime.h"
#include "include/meow_ui_input.h"
#include "include/meow_ui_activity.h"
#include "include/meow_ui_zorder.h"
#include "include/meow_ui_statusbar.h"
#include "include/meow_ui_theme.h"
#include "include/meow_ui_widgets.h"
#include "include/meow_ui_dialog.h"
#include "include/meow_ui_log.h"
#include "include/meow_ui_notify.h"
#include "include/meow_ui_config.h"
#include "include/meow_ui_font.h"
#include "include/meow_ui_audio.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* 物理键 keycode(内核 input.h 常用值;KEEP 与 launcher/settings 一致) */
/* ============================================================ */
#define MEOW_KEY_POWER 116
#define MEOW_KEY_VOLUMEDOWN 114
#define MEOW_KEY_VOLUMEUP 115
#define MEOW_KEY_PLAYPAUSE 164
#define MEOW_KEY_PREVIOUS 165 /* KEY_PREVIOUSSONG=165(上一曲;19 是另一码,勿混用) */
#define MEOW_KEY_NEXT 163 /* KEY_NEXTSONG */
/* 滑动方向(on_swipe 的 dir 参数) */
#define MEOW_SWIPE_LEFT 0
#define MEOW_SWIPE_RIGHT 1
#define MEOW_SWIPE_UP 2
#define MEOW_SWIPE_DOWN 3
/* ============================================================ */
/* §3 绘制层 */
/* ============================================================ */
/* init 选项。width/height 为 0 表示自动读取 /dev/fb0 几何;
* 无 fb(宿主/qemu 离屏)时用 480×720 缺省([D1])。 */
typedef struct meow_ui_opts {
int width;
int height;
} meow_ui_opts;
int meow_ui_init(const meow_ui_opts *opts); /* 开 fb、读几何、载字库、建 back_buf;0=成功 */
void meow_ui_shutdown(void);
int meow_ui_width(void); /* 480 */
int meow_ui_height(void); /* 720 */
void meow_ui_clear(uint32_t color); /* 整屏清(填背景色) */
void meow_ui_put_px(int x, int y, uint32_t color);
void meow_ui_fill_rect(int x, int y, int w, int h, uint32_t color);
void meow_ui_draw_rect(int x, int y, int w, int h, uint32_t color); /* 空心框 */
void meow_ui_draw_rect_round(int x, int y, int w, int h, int r, uint32_t color); /* 圆角框 */
/* 文本(size=20/28) */
void meow_ui_text(int x, int y, const char *utf8, int size, uint32_t color);
void meow_ui_text_right(int right_x, int y, const char *utf8, int size, uint32_t color);
void meow_ui_text_center(int cx, int y, const char *utf8, int size, uint32_t color);
int meow_ui_text_width(const char *utf8, int size);
int meow_ui_text_height(int size); /* = meow_font_line_height */
/* 上屏:vsync + 原子 blit 脏区(内建脏区追踪) */
void meow_ui_flush(void);
void meow_ui_flush_region(int x, int y, int w, int h); /* 只刷新指定区 */
/* 半透明(blend565:前景按 alpha 与背景混叠) */
void meow_ui_fill_rect_alpha(int x, int y, int w, int h, uint32_t color, int alpha); /* 0-255 */
/* ============================================================ */
/* §4 图片层 */
/* ============================================================ */
typedef struct meow_img meow_img; /* 句柄,由 meow_img_* 管理,不透明 */
meow_img *meow_img_load_file(const char *path); /* 内部读文件 + stb 解码 */
meow_img *meow_img_load_mem(const void *buf, int len);
void meow_img_free(meow_img *img);
int meow_img_w(meow_img *img);
int meow_img_h(meow_img *img);
void meow_ui_img(int x, int y, meow_img *img); /* 原始尺寸 */
void meow_ui_img_scaled(int x, int y, int w, int h, meow_img *img); /* 最近邻缩放 */
void meow_ui_img_alpha(int x, int y, int w, int h, meow_img *img, int alpha);
void meow_ui_img_cover(int x, int y, int size, meow_img *img); /* 居中裁方 → size×size */
/* ============================================================ */
/* §5 控件层 */
/* ============================================================ */
typedef struct meow_widget meow_widget;
meow_widget *meow_btn_create(int x, int y, int w, int h, const char *label);
meow_widget *meow_slider_create(int x, int y, int w, int min, int max, int val);
meow_widget *meow_switch_create(int x, int y, int on);
/* 列表数据源回调:idx 有效时填 label 并返回 1;越界返回 0([D2] 定案签名) */
typedef int (*meow_list_source)(int idx, char *label, int len, void *ctx);
meow_widget *meow_list_create(int x, int y, int w, int h, int count,
meow_list_source src, void *ctx);
void meow_widget_free(meow_widget *w);
void meow_widget_draw(meow_widget *w); /* 每次 flush 前调用 */
int meow_widget_hit(meow_widget *w, int x, int y); /* 点是否落在控件内 */
void meow_slider_set(meow_widget *s, int val);
int meow_slider_get(meow_widget *s);
void meow_switch_set(meow_widget *w, int on);
int meow_switch_get(meow_widget *s);
int meow_btn_pressed(meow_widget *w); /* 应用在 on_tap 命中后标记按下 */
/* ============================================================ */
/* §5.1 输入法(IME)—— 内置触屏软键盘(仅英文 QWERTY / 数字,ASCII) */
/* ============================================================ */
/* 输入法模式(尾部追加枚举:ASCII/NUM 值不变,零 ABI 回归)。PINYIN=中文拼音(meow_ui_ime.c)。 */
typedef enum { MEOW_IME_ASCII, MEOW_IME_NUM, MEOW_IME_PINYIN } meow_ime_mode;
typedef struct meow_ime_ctx {
meow_ime_mode mode;
char buf[256]; /* 输入缓冲(初始值可预填) */
int maxlen; /* 最大字符数(含 NUL 预算) */
void (*on_change)(const char *text, void *ctx); /* 每次字符变化回调一次 */
void *ctx;
} meow_ime_ctx;
/* 阻塞:弹出键盘直到关闭(ESC / 点背景取消);回车=只提交不关闭(内容经 on_change 实时同步)。
* 关闭路径返回 0(取消);提交内容经 on_change 回调逐键同步,不依赖返回值回填 buf。 */
int meow_ui_text_input(meow_ime_ctx *ctx);
/* 非阻塞:返回后 app 在 on_tick 里轮询 meow_ime_active()/meow_ime_text() */
void meow_ui_text_input_async(meow_ime_ctx *ctx);
int meow_ime_active(void);
const char *meow_ime_text(void);
/* 拼音模式组合态:当前拼音组合串(去声调小写,如 "nihao")供 App 渲染字段预览;
* 无组合(或非拼音模式)返回 ""。组合串是 IME 内部态,不写入字段(§4.2)。 */
const char *meow_ime_composition(void);
/* ============================================================ */
/* §6 输入层 / 生命周期(B1) */
/* ============================================================ */
typedef struct meow_ui_events {
void (*on_key)(int keycode, int is_down); /* M2.24:物理键为系统语义,SDK 不下发;回调保留(应用不映射键为确认/exit) */
void (*on_tap)(int x, int y); /* 触摸抬起落点 */
void (*on_swipe)(int dir, int dx, int dy); /* 左滑=返回(左缘起点+抬手触发) */
void (*on_tick)(void); /* 空闲周期回调(动画/时钟) */
void (*on_swipe_progress)(int x_start, int dx);/* 左缘返回手势过程实时回调;x_start=按下X, dx=当前X-按下X */
/* M2.71-bug2/6:拖动过程回调(跟手)。on_touch_down=按下后首个有效坐标(起点);
* on_touch_move=拖动中坐标变化(坐标变了才回调)。用于 slider 拖动 / 列表/页面滚动跟手。
* 均在 IME 弹出或模态阻塞时被吞(键盘/模态优先喂)。可 NULL。 */
void (*on_touch_down)(int x, int y);
void (*on_touch_move)(int x, int y);
} meow_ui_events;
void meow_ui_run(const meow_ui_events *ev); /* 阻塞:事件循环,直到 meow_ui_request_exit */
void meow_ui_request_exit(void); /* 请求退出(相当于返回/退出键) */
/* 顶部左滑进度条(视觉反馈):画一条 5px 高、从 x=0 到 x 的横条(主题 accent 色)。
* x<=0 时清掉此前画的条(填回背景色)。不发 flush,由调用方 meow_ui_flush_region 上屏。 */
void meow_ui_swipe_hint(int x);
/* ============================================================ */
/* §6.3 通用长按(2026-08-31) */
/* ============================================================ */
/* 控件按下 ≥ 阈值(默认 500ms,可配)未抬手、且按下后位移 ≤ 容忍(超移动/抬手取消)
* → 触发一次长按回调;坐标 = 触发时刻的按下点(App 据此 meow_widget_hit / meow_listview_hit
* 判定命中哪个控件/行,与 on_tap 同一套命中流程)。
*
* **opt-in**:注册回调(meow_ui_set_long_press_cb)才启用长按判定;未注册时行为与之前完全一致
* (按压不触发长按、抬手照常 TAP/SWIPE)——hello 等不使用长按的 App 零回归。
*
* 与 pressed 状态机共存:按压视觉态(MEOW_WS_PRESSED / 按住加深)不变;短按(未达阈值或
* 抬手先于阈值)仍正常触发 on_tap 点击;长按已触发后其抬手**不再产生 TAP/SWIPE**(SDK 抑制
* 点击,App 无需自行吞掉后续 tap)。
*
* 注册经独立 set 接口:**不做进 meow_ui_events**——避免给既有 App(hello/files)按位置初始化
* meow_ui_events 的写法在 -Wextra 下引入「缺省成员」告警(_missing-field-initializers),
* 保持 SDK 头向后兼容。 */
typedef void (*meow_long_press_fn)(int x, int y);
void meow_ui_set_long_press_cb(meow_long_press_fn cb); /* 注册/更换回调;NULL=取消 */
void meow_ui_set_long_press_ms(int ms); /* 长按阈值(ms);<=0 恢复默认 500 */
int meow_ui_long_press_ms(void); /* 当前阈值(默认 500) */
/* ============================================================ */
/* §6.1 控件生命周期与归属(Activity 栈 + 三层控件模型) [源:2026-08-30] */
/* ============================================================ */
/* 根治「跨页面控件残留」:控件命中/绘制必须严格绑定其所属页面,否则会出现
* "按钮已不可见但仍被触摸命中"(如全屏页触摸到主页按钮位置闪现 accent 底)。
*
* 三层职责(从 App 到系统,风险从低到高):
* ① 页面控件:归属唯一 owner Activity;命中/实时按压只在「当前 active Activity
* 的控件集」里生效。对象不销毁(同 Activity 内复用),弹栈回来自动恢复 →
* 回页面零重建。
* ② App 跨 Activity 控件(SDK 托管):钉在 App 的 Activity 栈之上、跨 Activity 常驻,
* 逻辑/渲染由 SDK 调度。本轮为「可用骨架」(见上 API 注释),待 B2 细化。
* ③ 系统级控件(状态栏/通知中心/返回滑条/电源菜单):仅框架内部,无公共 API(不开放)。
*
* 触摸命中分流顺序:③ 系统全局 → ② App 全局 → ① 当前 active Activity 页面控件;
* 某层命中即消费,否则落到下一层。 */
/* ① Activity 栈。控件创建时绑定「当前 active Activity」为 owner;弹栈回来自动恢复。
* 栈空时 active() 返回 0(根/default Activity),故未显式管理栈的 App 默认所有控件
* 归属根 Activity 0。push 新 Activity(进子页/全屏)、pop 回上级(回根)。 */
void meow_ui_activity_push(int id);
void meow_ui_activity_pop(void);
int meow_ui_activity_active(void); /* 当前 active activity id(栈空=0) */
int meow_ui_activity_depth(void); /* 当前栈深(push/pop 页数;供 M3 导航上报用) */
/* ② App 跨 Activity 控件(SDK 托管,骨架)。SDK 维护全局控件列表:
* - 渲染:每帧(有脏区需上屏时,meow_ui_gfx present())在 active activity 内容之上、
* 全局状态栏之下调用 render_cb(跨 Activity 常驻);
* - 触摸:TAP 先给 global hit_cb(返回 1=消费),否则落到 active activity 页面控件。
* 逻辑/渲染由 SDK 调度,App 只需声明。注:骨架,待 B2 细化。 */
typedef void (*meow_global_render_fn)(void *ctx); /* 每次渲染帧回调(SDK 调用) */
typedef int (*meow_global_hit_fn)(void *ctx, int x, int y); /* 命中返回1=消费 */
void meow_ui_global_add(int id, meow_global_render_fn r, meow_global_hit_fn h, void *ctx);
void meow_ui_global_remove(int id);
/* ③ 系统级控件:状态栏/通知中心/左缘返回滑条/电源菜单等全局叠加层——仅 SDK 内部接口,
* 不向用户 App 开放任何公共悬浮/叠加层 API。既有状态栏/返回滑条逻辑(§3.1)不动。 */
/* ============================================================ */
/* §6.2 绘制物注册表 / z 序 / 区域重画(合并 SDK_Z_ORDER_DESIGN,源:2026-08-31)
* ------------------------------------------------------------
* 非保留模型(§5.8.7)下,把「清底 + 按 z 重画重叠区完整 z 栈」下沉到 SDK,让所有 App
* 自动获得正确的局部重画(根治 P1:下层动态控件局部重绘会把重叠区上层 chrome 抹掉)。
* - 控件(meow_widget)创建即自动注册进绘制物注册表;rect 实时读 w->x/y/w/h;
* - App 直绘的非控件内容(meow_ui_text/fill_rect 等)须显式 meow_draw_custom_register
* 注册(声明 bbox + 绘制回调),否则区域重画会漏画(非保留模型固有代价);
* - z 自动推导(子>父、同层注册先序);显式 meow_widget_set_z(999/MEOW_Z_TOP) 置顶(粘滞)。
* 用法:meow_ui_invalidate(x,y,w,h) 局部重画(清底+按 z 升序重画所有相交绘制物+上屏),
* 不整帧;meow_ui_paint_full() 整帧按 z 序重画。默认底=meow_theme bg(set_page_bg 覆盖)。
* 兼容:新 API 全部 opt-in;不调用本节的既有 App(widget/activity/flush 均不动)行为完全不变。 */
/* ============================================================ */
/* 绘制物种类:控件(自动注册)/ App 直绘内容(显式注册)。 */
typedef enum { MEOW_ITEM_WIDGET = 0, MEOW_ITEM_CUSTOM = 1 } meow_draw_kind;
typedef void (*meow_draw_fn)(void *ctx); /* CUSTOM 绘制回调(ctx 由 App 持有) */
/* ---- 层级常量(保证"子>父" + 值域远小于置顶值)---- */
#define MEOW_Z_STRIDE 16 /* 每层容器嵌套的 z 步进(子层至少 +16) */
#define MEOW_Z_DEPTH_MAX 7 /* 自动推导最大嵌套深度(0..6,>7 折叠) */
#define MEOW_Z_PER_LEVEL_MAX 15 /* 每层最多 16 槽(seq 0..15,超出折叠按注册序) */
#define MEOW_Z_AUTO_MAX (MEOW_Z_STRIDE * MEOW_Z_DEPTH_MAX + MEOW_Z_PER_LEVEL_MAX) /* 127 */
#define MEOW_Z_TOP 1000 /* 惯例"置顶"值;≥(MEOW_Z_AUTO_MAX+1)=128 即超一切自动值 */
/* 控件显式置层:z 为任意非负整数(0..INT_MAX,无上限),越大越上;z>所有其它控件即恒在最上。
* 惯例设 999(或 MEOW_Z_TOP)即"置顶"。显式 z 存于绘制注册表(按 w 反查 entry,不改
* struct meow_widget——零 ABI 破坏)且**粘滞**:不被后续自动推导覆盖;clear_z 才回退。 */
void meow_widget_set_z(meow_widget *w, int z);
int meow_widget_z(const meow_widget *w); /* 当前生效 z(显式=其值,否则=自动推导) */
void meow_widget_clear_z(meow_widget *w); /* 清除显式 z,回退自动推导 */
/* ---- 非控件直绘内容注册为绘制物(CUSTOM)----
* App 声明 bbox + 绘制回调 + 显式 z(任意非负;999=置顶);区域重画/整帧重画会画到它。
* 返回 id(供 meow_draw_unregister / meow_draw_set_z);注册表满返回 0。
* 生命周期契约:App 持有 ctx;widget 类内容不必注册(自动);离开页面前 unregister。 */
int meow_draw_custom_register(int z, int x, int y, int w, int h,
meow_draw_fn cb, void *ctx);
void meow_draw_unregister(int id); /* 注销(id 失效,勿再用) */
int meow_draw_set_z(int id, int z); /* 改 custom 显式 z;无效 id 返回 -1 */
/* 页面背景色(区域重画/整帧清底用);默认 meow_theme bg。 */
void meow_ui_set_page_bg(uint32_t color);
uint32_t meow_ui_page_bg(void);
/* 声明某区域内容已变化 → 清底(page_bg) + 按 z 升序重画所有相交绘制物 + 上屏。
* 局部(只画相交绘制物,完整 bbox——见 SDK_Z_ORDER_DESIGN §5),不整帧、不冲状态栏。 */
void meow_ui_invalidate(int x, int y, int w, int h);
/* 整帧按 z 序重画全部(set_page_bg 清底 + 全注册表按 z 升序 + 上屏)。 */
void meow_ui_paint_full(void);
/* ============================================================ */
/* §3.1 全局状态栏 / 全屏(A-0,SDK 系统级组件) */
/* ============================================================ */
/* 状态栏是 SDK 内置全局组件:所有界面默认显示(时钟/电量/WiFi/蓝牙/音量,slim ~40px),
* 数据由 SDK 内置 meow_ui_sys 读取器 1s 轻刷(与 launcher 同源单点一致)。
* z 顺序最顶:meow_ui_flush() 上屏前自动把状态栏画进 back_buf 顶部行,覆盖非全屏内容;
* 非全屏 APP 需用 meow_ui_statusbar_height() 把内容下移(inset),否则被状态栏盖住。 */
/* 状态栏显隐(默认显示;APP 声明全屏则隐藏——沉浸)。 */
void meow_ui_set_statusbar(int visible); /* 1=显示(默认) 0=隐藏(全屏) */
int meow_ui_statusbar_visible(void);
/* 全屏声明:等价 app.json fullscreen:1(外观上隐藏状态栏 + 左缘返回手势/进度条——沉浸)。 */
void meow_ui_set_fullscreen(int on);
/* 状态栏高度(px,供 APP 布局上移内容,避免被盖——status bar inset);
* 全屏/隐藏时返回 0。 */
int meow_ui_statusbar_height(void);
/* ---- 状态栏「上收出屏只留提示线」(collapsed,草案/待定案——本批仅加声明)----
* 供全屏调用:把状态栏内容上移出屏顶、只留一条「提示线」高度(可下拉还原)。
* 与 meow_ui_set_fullscreen(1) 的关系:fullscreen 隐藏整条状态栏(沉浸,inset=0);
* collapsed 仍视状态栏为「激活」,左缘返回手势(SWIPE_LEFT)与顶部伸缩提示线
* (meow_ui_swipe_hint)依旧生效,只是其内容上收、仅留提示线——用于「不完全沉浸」,
* 保留一处可下拉拉出状态栏的入口。顶部下滑热区 meow_ui_statusbar_hotzone() 在全屏时缩小。
* 实现位置:meow_ui_gfx.c(基座让 on 生效:true→只画提示线/内容上移);逐帧过渡动画
* (上收/恢复插值)为待定案,后续代理可经 meow_ui_statusbar_animate(ms) 补齐。 */
void meow_ui_statusbar_set_collapsed(int on); /* on=1 上收(内容上移出屏、只留提示线);on=0 恢复 */
int meow_ui_statusbar_collapsed(void); /* 当前是否处于「上收」目标(1=是) */
void meow_ui_statusbar_animate(int ms); /* TBD:上收/恢复过渡时长(ms);占位,后续代理实现插值 */
/* 当前上收进度(0..MUI_SBAR_H:0=完全展开,28=内容全部上移出屏、仅留提示线)。
* 供系统进程(launcher)在 App 前台叠加顶条时读取,按「当前可见条高 = 28-offset」
* 标脏/切齐,实现收合时只 blit 可见条高、其余行保留 App 内容(平滑上收、无残留)。 */
int meow_ui_statusbar_collapse_offset(void);
/* 上收/恢复过渡是否仍在进行(current offset != target,逐帧推进中)。
* 供 launcher 在过渡期高频刷新顶条(launch_app 循环据此缩短 sleep),驱动平滑动画;稳定后回 1s 慢刷。 */
int meow_ui_statusbar_animating(void);
/* 顶部下滑热区(下拉展开状态栏/通知)高度(px)。
* 状态栏「激活」(含**收合**)时恒=整条状态栏高 MUI_SBAR_H(28)——收合只上收渲染、**不禁用顶部热区**
* (渲染与热区事件分离,全屏下顶部下滑仍开通知中心);仅「全屏隐藏」(immersive inset0)时缩小到
* MEOW_SBAR_HOTZONE_FS(保留一处下拉入口)。返回「可用于起始下拉」的热区高度。 */
int meow_ui_statusbar_hotzone(void);
#define MEOW_SBAR_HOTZONE_FS 4 /* 全屏时缩小后的顶部热区高度(px,草案值) */
/* ============================================================ */
/* §7 动画/时间(B1 最小可用) */
/* ============================================================ */
uint64_t meow_ui_time_ms(void); /* 单调毫秒时间戳 */
/* ============================================================ */
/* §7.1 显示刷新率调度(A-1/A-2:从 launcher M2.16 迁入,归口 SDK,PERF_SCHEDULER 显示子域) */
/* ============================================================ */
/* 设目标档位 60/30/15(launcher 与 app 统一走 SDK 的 present 帧率门控一致)。
* 同时把当前有效档对齐到目标(与 launcher settings_load 语义一致)。 */
void meow_ui_set_refresh_rate(int r);
/* 1=恒 max 不降档(性能优先);0=允许 governor 在 [15,30,60] 自适应降/升档。 */
void meow_ui_set_refresh_always_max(int on);
/* 当前有效帧率(governor 可能已降档;诊断用)。 */
int meow_ui_effective_rate(void);
/* 已呈现帧计数(验证 present 频率用)。 */
unsigned long long meow_ui_frames_presented(void);
/* ============================================================ */
/* §8 主题/配置 */
/* ============================================================ */
typedef enum { MEOW_THEME_LIGHT, MEOW_THEME_DARK, MEOW_THEME_AUTO } meow_theme_mode;
/* 主题(§5.8.4 + §8.1.3)。既有字段 bg/fg/accent/dim 保留(兼容映射,见下表),
* 其后追加 MD3 语义色板 + 风格参数段(扩展兼容——既有代码读旧字段不受影响)。
* 映射:bg↔surface、fg↔onSurface、accent↔primary、dim↔onSurfaceVariant。
* 「当前 style×mode」完整主题 = meow_theme_get()(MD3 默认;MIUIx 用 MD3 基础/占位)。 */
typedef struct meow_theme {
/* —— 既有字段(兼容保留;映射见上)—— */
uint32_t bg; /* 背景色 = surface */
uint32_t fg; /* 前景/正文 = onSurface */
uint32_t accent; /* 强调色(按钮/选中)= primary */
uint32_t dim; /* 次要文字 = onSurfaceVariant */
int font_title; /* 28 */
int font_body; /* 20 */
/* —— MD3 语义色板(§5.8.4;日/夜各一组,AUTO 按 meow_theme_mode 切换)—— */
uint32_t primary, onPrimary, primaryContainer, onPrimaryContainer;
uint32_t secondary, onSecondary, secondaryContainer, onSecondaryContainer;
uint32_t tertiary, onTertiary, tertiaryContainer, onTertiaryContainer;
uint32_t surface, onSurface, surfaceVariant, onSurfaceVariant;
uint32_t surfaceContainerLowest, surfaceContainerLow, surfaceContainer,
surfaceContainerHigh, surfaceContainerHighest;
uint32_t surfaceDim, surfaceBright, surfaceTint;
uint32_t outline, outlineVariant, scrim;
uint32_t error, onError, errorContainer, onErrorContainer;
uint32_t inverseSurface, inverseOnSurface, inversePrimary;
uint32_t shadow; /* 仅状态层/描边近似用;无 GPU 不做投影(§5.8.7) */
/* —— 风格参数段(§8.1.3;MD3 默认 / MIUIx 加大圆角+描边+间距)—— */
int radius; /* 控件默认圆角(按钮等,px) */
int radius_card; /* 卡片/容器默认圆角(px) */
int spacing; /* 布局/间距步进(px) */
int stroke_w; /* 默认细描边宽(0=无边框,MD3;MIUIx=1) */
} meow_theme;
const meow_theme *meow_theme_get(void);
void meow_theme_set_mode(meow_theme_mode m);
meow_theme_mode meow_theme_get_mode(void);
typedef void (*meow_theme_listener)(meow_theme_mode m);
void meow_theme_add_listener(meow_theme_listener cb);
void meow_theme_remove_listener(meow_theme_listener cb);
/* [D4] 脱机访问两套内置色板(无 settings 文件也可靠):返回当前解析生效的色板副本。 */
meow_theme meow_theme_defaults(meow_theme_mode m);
/* ---- §8.1 顶级主题风格族(minimal,2026-08-30)----
* 主题 = 顶级主题风格族(ui.style:MD3/MIUIx)× 明暗(display.theme)。本批只落「状态栏图标集
* 随 ui.style 换集」的最小闭环:meow_ui_set_style 记录 style(同值忽略)+ 触发 theme_reload/
* 广播(让状态栏/控件下一帧用新 style 重绘)。style 还决定状态栏右侧图标集(§3.1 同一个状态栏)。
* 完整 style×mode 配色/控件形态矩阵(§8.1.3)为后续里程碑。 */
#define MEOW_STYLE_MD3 0 /* Material You(默认) */
#define MEOW_STYLE_MIUIX 1 /* MIUI 风格族(基础占位) */
void meow_ui_set_style(int style); /* 设顶级主题风格族;越界 clamp 到合法值;同值忽略 */
int meow_ui_style(void); /* 当前 style(默认 MEOW_STYLE_MD3) */
/* ============================================================ */
/* §5.8 控件层升级(第一批=通用基座):Options / 状态机 / 自定义画布 / 布局 */
/* ============================================================ */
/* ---- §5.8.2 Modifier 式通用 Options(轻量结构体,非链式 DSL)----
* 经 meow_widget_set_opts 一次性挂载,作用于任意控件(标准/自定义)。全部控件共用。
* 哨兵语义:bg/fg==0=用控件/主题默认;stroke==0=无描边;stroke_w=描边宽;
* radius==-1=控件默认(如按钮 10),>=0=指定圆角(0=直角);pad/margin=0=无;
* disabled/selected=1=置位(立即反映到状态机位)。 */
typedef struct meow_widget_opts {
uint32_t bg; /* 背景色(0=控件/主题默认) */
uint32_t fg; /* 前景/文字(0=主题 onSurface) */
uint32_t stroke; /* 描边色(0=无描边) */
int stroke_w; /* 描边宽(px) */
int radius; /* 圆角(px;-1=控件默认,如按钮 10) */
int pad_x; /* 内边距(水平,px) */
int pad_y; /* 内边距(垂直,px) */
int margin_x; /* 外边距(水平,px;布局用) */
int margin_y; /* 外边距(垂直,px;布局用) */
int disabled; /* 1=禁用(视觉变暗 + 不响应命中,见状态机 §5.8.3) */
int selected; /* 1=选中(列表高亮/勾选,见状态机 §5.8.3) */
} meow_widget_opts;
/* 挂载:作用于任意控件(标准/自定义)。w 内部浅拷这份 opts。
* 返回 0=成功;NULL/无效=负值(不销毁 w)。 */
int meow_widget_set_opts(meow_widget *w, const meow_widget_opts *opts);
/* 取回当前 opts(浅拷到 out;0=成功)。自定义画布用它读通用修饰。 */
int meow_widget_opts_get(const meow_widget *w, meow_widget_opts *out);
/* ---- §5.8.3 统一状态机(enabled / selected / focused / pressed)----
* 标准/自定义控件共用;visual 层由 SDK/App 按状态位叠。enabled=0 阻断 hit/pressed。 */
#define MEOW_WS_ENABLED (1u<<0)
#define MEOW_WS_SELECTED (1u<<1)
#define MEOW_WS_FOCUSED (1u<<2)
#define MEOW_WS_PRESSED (1u<<3)
/* 设/查状态(置位/清位,其它位不动)。on=1 置位 / 0 清位。 */
void meow_widget_set_state(meow_widget *w, unsigned bits, int on);
unsigned meow_widget_state(const meow_widget *w);
/* 便捷:禁用/启用、选中/取消(单态等效于 set_state)。 */
int meow_widget_enabled(const meow_widget *w);
void meow_widget_set_enabled(meow_widget *w, int on);
int meow_widget_selected(const meow_widget *w);
void meow_widget_set_selected(meow_widget *w, int on);
/* 一键叠状态层(自定义画布可选):把 pressed/focused/disabled/selected 的视觉层
* 叠到 w 的矩形上(半透明状态层 + 焦点描边)。标准控件由 SDK 自动叠,无需调用;
* 自定义画布在 render_cb 里画完内容后可调它(App 也可据 meow_widget_state 自行叠)。 */
void meow_widget_draw_state_layer(meow_widget *w, const meow_theme *th);
/* ---- §5.8.1 自定义画布(App 提供 render/hit 回调;同一个 meow_widget)----
* render:SDK 在 meow_widget_draw 时调用,th=当前生效主题(MD3 语义色板);
* w 的 x/y/w/h 已就位;App 用 §3/§4 绘制 API 自绘(往 back_buf 画)。
* hit :命中判定,App 自定义(如圆形/区域外镂空);返回 1=命中。 */
typedef void (*meow_widget_render_fn)(meow_widget *w, const meow_theme *th, void *ctx);
typedef int (*meow_widget_hit_fn)(meow_widget *w, int x, int y, void *ctx);
/* 创建:自定义画布(x,y,w,h = 绝对坐标,同既有控件)。
* 生命周期/Activity 归属:创建时绑定当前 active Activity(同 meow_btn_create,§6.1 ①);
* 命中走 hit_cb(先过 owner==active + enabled 双闸门)。 */
meow_widget *meow_widget_custom_create(int x, int y, int w, int h,
meow_widget_render_fn render_cb,
meow_widget_hit_fn hit_cb,
void *ctx);
/* ---- §5.8.5 可组合布局(Row / Column / Box + Spacer)----
* 布局容器 = meow_widget(W_LAYOUT);arrange 把子控件算成绝对坐标(写进各 child 的
* x/y/w/h)→ 与现有绝对定位完全兼容(draw/hit/flush_region/owner 闸门照常)。
* 本批先支持固定尺寸子项(w/h 均已知);弹性(w/h==0)为后续增强。 */
enum { MEOW_LAYOUT_ROW = 0, MEOW_LAYOUT_COLUMN = 1, MEOW_LAYOUT_BOX = 2 };
meow_widget *meow_row_create(int x, int y, int w, int h, int spacing);
meow_widget *meow_column_create(int x, int y, int w, int h, int spacing);
meow_widget *meow_box_create(int x, int y, int w, int h);
/* 添加子控件(子可为普通控件/自定义/另一布局/Spacer)。返回 0=成功;无效=负值。 */
int meow_layout_add(meow_widget *layout, meow_widget *child);
/* 计算子控件绝对坐标(写入各 child 的 x,y,w/h;嵌套布局递归);此后照常 draw/hit。 */
void meow_layout_arrange(meow_widget *layout);
/* 固定尺寸空白(也作撑余量;不可见,hit 恒 0)。 */
meow_widget *meow_layout_spacer(int w, int h);
/* ============================================================ */
/* §5.8.6 Material 3 组件子集(第二批,基于第一批基座:Options + 状态机 + MD3 色板 + 布局)
* 每个组件 = 新增 meow_widget 类型或组合既有模板的便捷函数;复用主题语义色(th->primary /
* surfaceContainer / outline / ...)+ 风格参数(radius/radius_card/spacing/stroke_w)+ 通用
* Options(meow_widget_set_opts 对它们同样生效)+ 状态机(enabled/selected/pressed/focused)。
* 向后兼容:既有 create 签名一字不改;本批只在其上扩展。 */
/* ============================================================ */
/* ---- Button 五型(meow_btn 扩展;既有 meow_btn_create = FILLED)---- */
enum {
MEOW_BTN_FILLED = 0, /* primary 底 / onPrimary 文 */
MEOW_BTN_TONAL = 1, /* secondaryContainer 底 / onSecondaryContainer 文 */
MEOW_BTN_OUTLINED = 2, /* 透明底 / primary 文 / primary 描边 */
MEOW_BTN_TEXT = 3, /* 透明底 / primary 文 / 无描边 */
MEOW_BTN_ELEVATED = 4, /* surfaceContainerLow 底 / primary 文 */
};
meow_widget *meow_btn_create_variant(int x, int y, int w, int h, const char *label, int variant);
int meow_btn_set_variant(meow_widget *w, int variant); /* 越界 clamp;0=成功 */
/* ---- TextField(单行文本输入,接 IME §5.1)---- */
/* placeholder=提示文案;buf=App 持有的文本缓冲(组件不回拷,只绘制/编辑其上);maxlen=含 NUL 预算 */
meow_widget *meow_textfield_create(int x, int y, int w, int h, const char *placeholder,
char *buf, int maxlen, meow_ime_mode mode);
void meow_textfield_set_placeholder(meow_widget *w, const char *placeholder);
/* 聚焦并打开**阻塞** IME(同 meow_ui_text_input 内层轮询);回车不关闭键盘,ESC/点背景关闭。
* 内容经 on_change 实时同步到 w->buf(返回值关闭路径为 0,提交不依赖返回值回填)。 */
int meow_textfield_activate(meow_widget *w);
const char *meow_textfield_text(meow_widget *w);
/* ---- Card(圆角容器卡片;surfaceContainerLow 底 + 可选描边/状态层)---- */
meow_widget *meow_card_create(int x, int y, int w, int h);
/* 内容子控件:绘制时递归绘到卡片内(卡片 hit 仍为矩形;子控件独立命中) */
void meow_card_set_content(meow_widget *card, meow_widget *child);
/* ---- Divider(分隔线;vertical=1 纵向)---- */
meow_widget *meow_divider_create(int x, int y, int len, int vertical);
/* ---- Badge(角标;count=0 红点 / >0 数字 / <0 隐藏;cx,cy=锚点=角标中心)---- */
meow_widget *meow_badge_create(int cx, int cy);
void meow_badge_set(meow_widget *w, int count);
/* ---- Checkbox / Radio(勾选态走 meow_widget_set_selected/meow_widget_selected)---- */
meow_widget *meow_checkbox_create(int x, int y);
meow_widget *meow_radio_create(int x, int y);
/* ---- ProgressBar(线性/圆形;value=0-100 确定性,-1=不定)---- */
meow_widget *meow_progress_create(int x, int y, int w, int h, int value); /* 线性 */
meow_widget *meow_progress_circular_create(int cx, int cy, int r, int value); /* 圆形 */
void meow_progress_set(meow_widget *w, int value); /* -1=不定 */
/* ---- FloatingActionButton(悬浮按钮;圆角胶囊,无投影仅状态层近似)---- */
meow_widget *meow_fab_create(int x, int y, int size, const char *label);
/* ---- TopAppBar(顶部标题栏:标题 + 返回 + 动作)---- */
meow_widget *meow_topappbar_create(int x, int y, int w, int h, const char *title);
void meow_topappbar_set_title(meow_widget *w, const char *title);
void meow_topappbar_set_back(meow_widget *w, int on); /* 1=显示返回箭头 */
int meow_topappbar_add_action(meow_widget *w, const char *label); /* 返回动作下标 */
#define MEOW_TOPBAR_BACK (-2)
int meow_topappbar_hit(meow_widget *w, int x, int y); /* MEOW_TOPBAR_BACK=返回 idx>=0=动作 -1=无 */
/* ---- NavigationBar(底部导航栏)---- */
meow_widget *meow_navigationbar_create(int x, int y, int w, int h);
int meow_navigationbar_add_item(meow_widget *w, const char *label);
void meow_navigationbar_set_selected(meow_widget *w, int idx);
int meow_navigationbar_selected(meow_widget *w);
int meow_navigationbar_hit(meow_widget *w, int x, int y); /* 返回项下标/-1 */
/* ---- TabBar(顶部分页页签;swipe 联动 §5.2 由 App 在 on_swipe 驱动)---- */
meow_widget *meow_tabbar_create(int x, int y, int w, int h);
int meow_tabbar_add_tab(meow_widget *w, const char *label);
void meow_tabbar_set_selected(meow_widget *w, int idx);
int meow_tabbar_hit(meow_widget *w, int x, int y); /* 返回页签下标/-1 */
/* ---- 列表容器(LazyColumn/LazyRow:数据源回调 + 可见区虚拟化;复用 meow_list_source)
* meow_lazycolumn_create=纵向(item_h=行高);meow_lazyrow_create=横向(item_w=列宽)。
* 滚动由 App 在 on_swipe 里用 meow_list_scroll_by/set_scroll 驱动。 */
meow_widget *meow_lazycolumn_create(int x, int y, int w, int h, int item_h, int count,
meow_list_source src, void *ctx);
meow_widget *meow_lazyrow_create(int x, int y, int w, int h, int item_w, int count,
meow_list_source src, void *ctx);
void meow_list_set_scroll(meow_widget *w, int offset); /* clamp 到 [0, max_scroll] */
int meow_list_scroll(meow_widget *w);
int meow_list_max_scroll(meow_widget *w); /* max(0, count*item - viewport) */
void meow_list_scroll_by(meow_widget *w, int dy); /* 相对滚动(App on_swipe 用) */
int meow_list_set_item_h(meow_widget *w, int item); /* 改行高/列宽 */
int meow_list_hit_index(meow_widget *w, int x, int y); /* 命中项下标(含滚动换算);-1=未命中项/越界 */
/* M2.71-bug8:列表行选中 + 行点击回调。选中行已有高亮(现有绘制读 w->sel)。
* meow_list_tap_at:命中一行则置选中并回调 tap_cb(若设),返回该行 idx;未命中返回 -1。 */
void meow_list_set_selected(meow_widget *w, int idx); /* 选中行(越界 clamp);标脏 */
int meow_list_selected(meow_widget *w);
typedef void (*meow_list_tap_fn)(int idx, void *ctx);
void meow_list_set_on_tap(meow_widget *w, meow_list_tap_fn cb, void *ctx); /* 命中行→回调 */
int meow_list_tap_at(meow_widget *w, int x, int y); /* 命中行:置选中+回调,返回 idx/-1 */
/* ============================================================ */
/* §5.5 设计模板 A② 结构化列表(W_LISTVIEW):行=图标+标题+副标题+右侧操作 + 选中
* ------------------------------------------------------------
* 在既有「label-only」列表(meow_list_create/lazycolumn,行为不变)之上做**结构化扩展**:
* 行数据源回调逐行给出 meow_list_item(图标 / 标题 / 副标题 / 右侧操作 / 可选中),容器负责
* 绘制/滚动/选中/命中;支持单选/多选/无选择。向后兼容:既有 meow_list_* 全部保留不动。
* 颜色全部取 meow_theme_get() 语义色(日/夜/style 自动),不硬编码。
* 命中:meow_listview_hit 返回行号(含滚动换算 + 禁用行不响应);行右 1/3 为右侧操作区
* (meow_listview_hit_op 另判)。抬手用最新坐标(goodix 免疫,参照既有 W_LIST 习惯)。 */
/* ============================================================ */
/* 选中模式:无(纯入口列表)/ 单选 / 多选。 */
typedef enum { MEOW_LIST_SEL_NONE = 0, MEOW_LIST_SEL_SINGLE, MEOW_LIST_SEL_MULTI } meow_list_sel;
/* 行图标:meow_img*(MEOW_LIST_ICON_IMG)或内置符号(FOLDER/FILE,无图 App 用)。 */
typedef enum {
MEOW_LIST_ICON_NONE = 0, /* 无图标 */
MEOW_LIST_ICON_IMG, /* 用 item->icon(meow_img*) */
MEOW_LIST_ICON_FOLDER, /* 内置目录符号(填充矩形+页签) */
MEOW_LIST_ICON_FILE, /* 内置文件符号(空心矩形+折角) */
} meow_list_icon_kind;
/* 行右侧操作类型:无 / 箭头 / 开关 / 复选 / 详情钮(⋯)。 */
typedef enum {
MEOW_LIST_RIGHT_NONE = 0, /* 无右侧操作 */
MEOW_LIST_RIGHT_ARROW, /* 箭头 › */
MEOW_LIST_RIGHT_SWITCH, /* 开关(on/off = item->on) */
MEOW_LIST_RIGHT_CHECK, /* 复选标记 */
MEOW_LIST_RIGHT_MORE, /* ⋯ 详情钮 */
} meow_list_right;
/* 单行数据(回调填充到栈上,容器不长期持有)。title 必填;subtitle 可空。 */
typedef struct meow_list_item {
const meow_img *icon; /* 可选(icon_kind==MEOW_LIST_ICON_IMG 时用) */
int icon_kind; /* MEOW_LIST_ICON_*(NONE=无图标) */
const char *title; /* 主文本(必填,NULL 视为空行) */
const char *subtitle; /* 副文本,可空 */
int right; /* MEOW_LIST_RIGHT_* 右侧操作类型 */
int on; /* right==SWITCH 时开关态(0/1) */
int enabled; /* 1=可选中/可交互;0=变淡不响应命中 */
} meow_list_item;
/* 行数据源回调:idx 有效时填充 out 并返回 1;越界返回 0。每行轻量填充(不做 IO,§5.5)。 */
typedef int (*meow_list2_source)(int idx, meow_list_item *out, void *ctx);
/* 创建:视口(x,y,w,h) + 行数 count + 行数据源 + 选中模式。行高默认 56(可用 set_item_h 改)。 */
meow_widget *meow_listview_create(int x, int y, int w, int h, int count,
meow_list2_source src, void *ctx, meow_list_sel mode);
/* 行高(固定;越界/<=0 忽略)。 */
int meow_listview_set_item_h(meow_widget *lv, int item);
/* 行数(搜索过滤/懒加载/目录切换时动态更新):截断 sel 到新范围 + clamp scroll。 */
void meow_listview_set_count(meow_widget *lv, int count);
/* 滚动:set 越界 clamp 到 [0, max_scroll];by 相对滚动(App on_swipe/touch_move 用)。 */
void meow_listview_set_scroll(meow_widget *lv, int offset);
void meow_listview_scroll_by(meow_widget *lv, int dy);
int meow_listview_scroll(meow_widget *lv);
int meow_listview_max_scroll(meow_widget *lv); /* max(0, count*item_h - viewport_h) */
/* 选中集(mode 语义):
* NONE :忽略;SINGLE:set_sel(idx) 设/清(idx<0 清除);MULTI:set_sel(idx) 翻转 idx。
* get_sel 把当前选中下标写入 out[0..max),返回写入数;sel_count 返回选中总数。 */
void meow_listview_set_sel(meow_widget *lv, int idx);
int meow_listview_get_sel(meow_widget *lv, int *out, int max);
int meow_listview_sel_count(meow_widget *lv);
/* 命中:返回行号(含滚动换算;禁用行/越界返回 -1);行右 1/3 = 右侧操作区(另判)。 */
int meow_listview_hit(meow_widget *lv, int x, int y);
int meow_listview_hit_op(meow_widget *lv, int x, int y); /* 1=点在行右 1/3 操作区 */
/* 行点击回调(idx=行号;op:0=行体,1=右侧操作区)。 */
typedef void (*meow_listview_tap_fn)(int idx, int op, void *ctx);
void meow_listview_set_on_tap(meow_widget *lv, meow_listview_tap_fn cb, void *ctx);
/* 命中行:置选中 + 回调(若设)+ 返回 idx;未命中返回 -1。 */
int meow_listview_tap_at(meow_widget *lv, int x, int y);
/* ============================================================ */
/* §5.8.6 模态(App 层,非系统叠加):Dialog / BottomSheet
* 复用 §5.6 B③ 弹窗 / §5.7 B④ 底部面板模板(与 launcher s_dd_modal 同构),控件化。
* 阻塞式(内层 meow_input_pop 轮询,与 meow_ui_text_input 同构);打开前排空残留触摸。
* 关闭途径:点卡片内选项=确认、点卡片外=取消、左缘返回手势=取消。不压状态栏(y 钳制)。 */
/* ============================================================ */
/* ---- Dialog(弹窗:确认/选择/输入/信息)---- */
typedef enum { MEOW_DLG_CONFIRM, MEOW_DLG_SELECT, MEOW_DLG_INPUT, MEOW_DLG_INFO } meow_dlg_t;
typedef struct meow_dialog meow_dialog;
meow_dialog *meow_dialog_create(meow_dlg_t t, const char *title);
void meow_dialog_set_items(meow_dialog *d, const char *const *item, int n, int cur); /* SELECT 型 */
void meow_dialog_set_ime(meow_dialog *d, meow_ime_ctx *ime); /* INPUT 型 */
void meow_dialog_show(meow_dialog *d); /* 阻塞到确认/取消 */
int meow_dialog_result(meow_dialog *d); /* SELECT=选项下标;CONFIRM/INFO 确认=1、取消=0 */
void meow_dialog_close(meow_dialog *d); /* 程序化关闭(App 亦可驱动) */
void meow_dialog_free(meow_dialog *d);
/* CONFIRM 型便捷:点「确定」返回 1,取消/遮罩=0 */
int meow_dialog_confirm(meow_dialog *d);
/* ---- BottomSheet(底部面板:标题 + 选项列表;open 阻塞返回选中 idx/-1)---- */
typedef struct meow_sheet meow_sheet;
meow_sheet *meow_sheet_create(const char *title, int h);
int meow_sheet_add_item(meow_sheet *s, const char *label); /* 返回项下标 */
int meow_sheet_open(meow_sheet *s); /* 阻塞;返回选中 idx / -1=取消 */
void meow_sheet_free(meow_sheet *s);
/* ============================================================ */
/* §9 应用日志(统一日志 API,M2.51 最小可用版) */
/* ============================================================ */
/* app 只需一行 meow_log();SDK 管「写哪/怎么写/过滤/降级/上限」:
* - 路径:<MEOW_LOG_DIR>/<启动时间>_<pid>.log(MEOW_LOG_DIR 已含包名分层 logs/<包名>)
* (目录不存在 mkdir -p,按 app 分目录),每次启动=新文件,同一次启动内 O_APPEND 追加;
* - 级别过滤:lvl < meow_log_get_level() 丢弃;默认 MEOW_LOG_INFO;
* - 格式:<monotonic_ms> [<app_id>] <LEVEL> message\n;
* - 上限:单文件 ≥2MB 自动开新文件追加 _<n>;每 App 总量 ≥50MB 按期删最旧,防撑爆卡;
* - 无卡/写失败降级 stderr,不阻塞 app 不崩;线程安全。
* 注意:MEOW_LOG_APP 由 launcher 注入;未注入时默认 app_id="app"。 */
typedef enum { MEOW_LOG_DEBUG=0, MEOW_LOG_INFO, MEOW_LOG_WARN, MEOW_LOG_ERROR } meow_log_level;
void meow_log(meow_log_level lvl, const char *fmt, ...); /* app 一行调用,写到按 app 分离日志 */
void meow_log_set_level(meow_log_level lvl); /* 可选:app 设本 app 级别;默认 MEOW_LOG_INFO */
meow_log_level meow_log_get_level(void);
/* ============================================================ */
/* §9.1 应用通知(meow_notify_*,M2.53 最小可用版) */
/* ============================================================ */
/* app 只需声明类型 + meow_notify_send() 即可发通知,SDK 管配额/活动表/降级:
* - 类型注册:app 声明支持的类型(最多 MEOW_NOTIFY_MAX_TYPES 4 种);
* meow_notify_send 也会自动注册未声明类型(受同样 4 种上限约束);
* - 配额(NOTIFICATION_SYSTEM.md §7,2026-08-29 用户拍板):每 App 最多 4 种类型;
* 每类型活动(未过期)通知上限 4,满则丢最旧(替换);媒体类型单例(每 app 仅
* 保留最近 1 条,重发替换——可多媒体 App);
* - 超时语义 [实现定案,沿用 NOTIFICATION_SYSTEM.md §2]:timeout_ms>0 = 过期毫秒数;
* 0 = 不自动过期(直到 meow_notify_cancel);-1 = 常驻(ONGOING),同样不自动过期;
* - 落点:本阶段 SDK 内部维护活动通知表 + 用 meow_log() 打日志作为落点;真实投递到
* 通知中心 UI / D-Bus(org.freedesktop.Notifications)是后续任务——本结构已对齐
* freedesktop 字段(summary/body/…)为此预留,但不写死后端;
* - 线程安全;不依赖 /dev/fb0、不依赖板子,可宿主编译。 */
#define MEOW_NOTIFY_MAX_TYPES 4 /* 每 App 最多 4 种通知类型 */
#define MEOW_NOTIFY_MAX_PER_TYPE 4 /* 每类型活动(未过期)通知上限 */
#define MEOW_NOTIFY_MAX_MEDIA 1 /* 媒体通知每 App 仅 1 条(单例) */
#define MEOW_NOTIFY_TIMEOUT_ONGOING (-1) /* 常驻(ONGOING),不自动过期 */
#define MEOW_NOTIFY_TIMEOUT_NEVER 0 /* 不自动过期,直到取消 */
/* 通知分类(freedesktop.org Desktop Notifications 的 category 最小子集 [实现定案]) */
typedef enum {
MEOW_NOTIFY_CAT_GENERAL = 0, /* 通用(默认) */
MEOW_NOTIFY_CAT_MESSAGE = 1, /* 即时消息/聊天 */
MEOW_NOTIFY_CAT_EMAIL = 2, /* 邮件 */
MEOW_NOTIFY_CAT_EVENT = 3, /* 事件/日历提醒 */
MEOW_NOTIFY_CAT_PROGRESS = 4, /* 进度/下载 */
MEOW_NOTIFY_CAT_MEDIA = 5, /* 媒体播放(MPRIS;每 app 单例) */
MEOW_NOTIFY_CAT_COUNT = 6, /* 边界哨兵(非合法类型) */
} meow_notify_category;
/* 紧急度(UI 视觉分级 + 提示音/震动强弱) */
typedef enum {
MEOW_NOTIFY_URG_LOW = 0, /* 低:仅进通知中心,不打扰 */
MEOW_NOTIFY_URG_NORMAL = 1, /* 普通 */
MEOW_NOTIFY_URG_HIGH = 2, /* 高:顶部横幅 + 提示音 */
MEOW_NOTIFY_URG_CRITICAL = 3, /* 紧急:需立刻注意 */
MEOW_NOTIFY_URG_COUNT = 4, /* 边界哨兵(非合法值) */
} meow_notify_urgency;
/* 发送负载(对齐 freedesktop Notify() 字段;SDK 内部复制副本,不持 app 外部指针,
* app 只需保证 icon/title/body/target_activity 指针在调用返回前有效)。 */
typedef struct meow_notify {
meow_notify_category cat; /* 类型(未声明则按 4 种上限自动注册) */
meow_notify_urgency urgency; /* 紧急度(缺省 MEOW_NOTIFY_URG_NORMAL;越界钳位) */
const char *title; /* summary:标题,单行(必填,NULL 则发送失败) */
const char *body; /* body:正文,可多行(可 NULL) */
const char *icon; /* app_icon:图标 icon name 或 path;NULL/空 = 用该 app 默认图标(launcher 按 app_id 回退) */
int timeout_ms; /* 见上超时语义;推荐 MEOW_NOTIFY_TIMEOUT_* */
const char *target_activity; /* 通知中心点击跳转的 Activity 名(可 NULL;M3 导航预留) */
int progress; /* 进度 0-100;-1=不显示进度条(缺省 -1) */
} meow_notify;
/* 类型注册:app 声明支持的类型。0=成功;-1=已声明/已达 4 种上限/非法。 */
int meow_notify_register_type(meow_notify_category cat);
/* 发送一条通知。返回通知 id(用于 meow_notify_cancel);失败返回 0。
* 同类型满 4 条时丢弃最旧(替换);媒体类型单例(重发替换同 app 上一条媒体通知)。 */
uint32_t meow_notify_send(const meow_notify *n);
/* 取消一条通知。1=成功;0=未找到(id 无效/已过期/已取消)。 */
int meow_notify_cancel(uint32_t id);
/* 实时更新一条活动通知的进度(0-100,-1=清除进度条)。local_id=meow_notify_send 的返回值。
* 语义(用户定案):仅改 SDK 内部活动槽 + 经 IPC 通知 launcher 改**内存活跃槽**;不落盘——
* TF 快照只在「创建时 / 结束(100% 或 dismiss)」触发。返回 1=找到并更新;0=未找到/非法。 */
int meow_notify_update_progress(uint32_t local_id, int progress);
/* 查询当前活动(未过期、未取消)通知数/是否还有。 */
int meow_notify_active_count(void);
int meow_notify_count_in_type(meow_notify_category cat);
int meow_notify_has_active(void); /* 1=尚有活动通知,0=无 */
/* 紧急度/分类 → 字符串("low"/"normal"/"high"/"critical"、"general"/"message"/…)。 */
const char *meow_notify_urgency_str(meow_notify_urgency u);
const char *meow_notify_category_str(meow_notify_category cat);
/* ============================================================ */
/* §9.2 应用配置读写(meow_config_*,M2.x 最小可用版) */
/* ============================================================ */
/* App 自有配置读写:与系统设置 meow_settings_*(板载 settings.conf、系统级、带 schema)
* 明确区分——这是单个 App 自己的键值偏好,落 TF 数据目录,不占板载、无 schema。
*
* - 数据目录:优先 env MEOW_DATA_DIR(launcher 注入 /usr/data/mnt/sd_0/MeowData/<pkg>/data,
* 见 app_launcher.c launch_app);无 env(手动跑/宿主测/无卡)回退 /tmp/meowcfg_<pid>
* (非持久但仍可写)。meow_config_dir() 返回最终目录;空/不可建返回 NULL。
* - 文件布局:每键一小文件 <data>/<sanitized_key>.cfg,内容=值字符串(空串=0 字节文件)。
* key 只允许 [A-Za-z0-9._-],其余字符替换为 '_'(杜绝路径穿越);key 上限 64。
* - 轻量:每次 get 读文件(App 配置小),不做大内存缓存;pthread_once 惰性初始化目录。
* - 失败降级:无数据目录/写失败 → 返回负错误码(见上 MEOW_CFG_ERR_*),不崩不阻塞。
*
* 返回码:MEOW_CFG_OK(0) 成功;(set) 负=失败;(get) MEOW_CFG_ERR_NOENT(-2)=键未设/文件不存在;
* meow_config_int/bool 对任何非 MEOW_CFG_OK 一律返回 def。
* 错误码数值同 MEOWOS_API.md §1 / meow_settings_*(MEOW_ERR_*)一致,便于 App 习惯。 */
const char *meow_config_dir(void); /* 当前 App 数据目录(data);空/不可建 NULL */
int meow_config_set(const char *key, const char *val);/* 写 <data>/<key>.cfg;成功 MEOW_CFG_OK(0) */
int meow_config_get(const char *key, char *out, int outsz); /* 读;未设/不存在返回 MEOW_CFG_ERR_NOENT */
int meow_config_int(const char *key, int def); /* 便捷 int;未设/非法返回 def */
int meow_config_bool(const char *key, int def); /* 便捷 bool;未设/非法返回 def */
void meow_config_remove(const char *key); /* 删键(无该键/无目录则静默) */
/* ============================================================ */
/* §5.7 应用可读 TF 卡字体列表(M2.58:字体索引 / 查列表 / 丢失降级默认) */
/* ============================================================ */
/* 系统字体管理器的面向应用接口(规格 §5.7.1/§5.7.2):
* - 权威列表 = launcher 扫描 MeowOS/fonts/<family>/<weight>/ 后落盘的持久文件
* MeowOS/config/fonts/index(CSV:family,weight,path,label,tier,glyph_count)。
* app 只经本接口读该列表(不直接拼路径、不依赖 launcher 内存数组)。
* - 渲染仍走 env MEOW_FONT_PNG/MEOW_FONT_IDX(launcher 注入的「当前生效字体」,
* 选中字体那一套);本节的 get_available_count/enumerate 只负责「列有哪些库」,
* select_by_id 负责「app 会话内固定用哪套」。两路明确。
* - 无卡 / 无 index → 仅 1 项板载默认(family=default)。 */
#ifndef MEOW_FONT_INFO_DEFINED
#define MEOW_FONT_INFO_DEFINED
typedef struct meow_font_info {
char family[64]; /* family slug = MeowOS/fonts/<family>/ 一级目录名 */
char name[64]; /* 显示名(index 无单列 → 回退 family) */
char weight[32]; /* weight slug(regular|bold|…,缺省 regular) */
char tier[8]; /* 档位 common|gbk|full(info 用) */
int glyph_count; /* font.json glyph_count(info 用) */
char label[128]; /* index 显示名(含字重 + 尺寸标记) */
int size_list[16]; /* 原生字号表(index 无 → 空) */
int size_count; /* 有效字号数 */
int bit_depth; /* 4|8(index 无 → 0) */
char path_png[320]; /* 卡根相对 MeowOS/fonts/<family>/<weight>/font.png */
} meow_font_info;
#endif
/* 可用字库数(含默认;无卡 → 1)。 */
int meow_font_get_available_count(void);
/* 按序号取:idx=0=默认行(family=default);越界返回 0。 */
int meow_font_enumerate(int idx, meow_font_info *out);
/* 选该套为 app 会话默认字体:id=0 跟随系统默认(font.file,经 env);id>0 固定用该套。
* 该套字库缺失 → 降级默认(不丢请求)+ WARN(meow_log→app 日志)。成功 0,越界负值。 */
int meow_font_select_by_id(int id);
/* ============================================================ */
/* §10 字体分层 / 大字库(M2.5x:基座声明 + font 域已实现按档装载) */
/* ============================================================ */
/* 字体「档位」概念:launcher 按 app.json 声明的字库档("fonts":<档>)向 app 注入
* MEOW_FONT_TIER=<0|1|2>;SDK(meow_ui_gfx / meow_font 大字库加载)据档选库:
* MEOW_FONT_TIER_COMMON=0 默认 4K 常用字库;
* MEOW_FONT_TIER_GBK =1 大字库 GBK;
* MEOW_FONT_TIER_FULL =2 Full(全字符集)。
* 大字库生成由 font/gen/gen_font.py --charset 按档产出;按档装载由 meow_font_reload_tier()
* 实现(先 unload 旧再 load 新,释放旧 atlas 防大字库双驻留)。launcher 经
* meow_font_effective_paths_tiered() 按档解析大字库绝对路径并注入 MEOW_FONT_PNG/IDX。
* 既有 meow_font_* 符号(class_of/has_glyph/load_slot/config_multifont…)保留不动。
* 判缺字:meow_font_has_glyph(cp) 预判当前字库是否含该码位。 */
#define MEOW_FONT_TIER_COMMON 0
#define MEOW_FONT_TIER_GBK 1
#define MEOW_FONT_TIER_FULL 2
/* 设当前字体档(0/1/2,越界 clamp 到合法值),返回生效档。
* meow_ui_gfx.c 定义并触发 meow_font_reload_tier() 真重载(大字库切换释放旧 atlas)。 */
int meow_font_set_tier(int tier);
/* 当前字体档(初始 = MEOW_FONT_TIER_COMMON;meow_ui_init 时读 MEOW_FONT_TIER env 对齐)。 */
int meow_font_tier(void);
/* ============================================================ */
/* §11 独占音频客户端(devdocs/plan/AUDIOD_DESIGN.md §7;meow_ui_audio.c) */
/* ============================================================ */
/* 说明:App 只经本 API 喂 PCM 给 meow_audiod(独占 hw:0,0 守护,svcd 托管)。audiod 不在一律
* 失败(open 返回 MEOW_ERR_NOENT,负值),不做隐式直开回退;调试可用 env MEOW_AUDIO_DIRECT=1 走
* 自带直接 ALSA 直开路径(非正式能力,勿依赖)。
* 生命周期:open 取 stream_id>0 → write 喂 PCM(阻塞,socket 背压)→ pause/resume → close 释放。
* 被抢占(后开流赢):SDK 内部读线程收 MSG_AUDIO_PREEMPTED → 调 on_preempt 回调 + 标写死
* (后续 write 返回负值,App 应重新 open)。 */
/* 当前流快照(meow_audio_query 填充)。 */
typedef struct meow_audio_state {
int active; /* 1=audiod 有活跃流(不一定是本 App 的) */
char app_id[32]; /* 活跃流 app_id(无流为 "-") */
uint32_t stream_id; /* 活跃流 id */
uint32_t rate; /* 活跃流采样率 */
uint16_t ch; /* 活跃流声道数 */
uint16_t fmt; /* 活跃流格式(AUDIO_FMT_*) */
uint64_t written_frames; /* 客户端写入 ring 的帧 */
uint64_t played_frames; /* 播放线程写到设备的帧 */
uint32_t underrun; /* xrun 计数 */
int paused; /* 当前流是否暂停 */
int route_port; /* 当前路由口(-1 未知) */
int vol; /* 当前音量 0-100 */
} meow_audio_state;
/* 被抢占回调:by_app=抢占者 app_id(非空)。ctx 由 on_preempt 注册时传入。 */
typedef void (*meow_audio_preempt_fn)(const char *by_app, void *ctx);
/* 开流。rate/ch/fmt=App 声源原生参数(fmt 值见 meow_ipc.h AUDIO_FMT_*)。
* 返回 stream_id(>0);负错误码(MEOW_ERR_NOENT=audiod 不在;MEOW_ERR_INVAL=参数非法;
* MEOW_ERR_NODEV=无可用 PCM 设备;MEOW_ERR_* 常量本身即负值)。open 后客户端须按内部记录的
* grant 格式产出 PCM。 */
int meow_audio_open(int rate, int ch, int fmt);
/* 写 PCM。pcm=native fmt/ch 样本(open 传的参数),frames=帧数;内部归一成 grant 并分批发送。
* 返回写入帧数;<0=流已死(被抢占/audiod 断开),App 应重新 open。阻塞(socket 背压)。 */
int meow_audio_write(const void *pcm, int frames);
/* 暂停(1)/恢复(0)当前流。返回 0 成功;<0 失败。 */
int meow_audio_pause(int sid, int paused);
/* 关流(STOP + 释放)。返回 0;连接保留供下次 open。 */
int meow_audio_close(int sid);
/* 查询 audiod 快照(填充 out)。返回 0 成功;<0 失败。 */
int meow_audio_query(meow_audio_state *out);
/* 注册被抢占回调(可选;内部读线程分发)。重复调用幂等。 */
void meow_audio_on_preempt(meow_audio_preempt_fn cb, void *ctx);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_UI_H */
+84
View File
@@ -0,0 +1,84 @@
/*
* test_umbrella.c — 伞头完整性回归:只 #include "meow_ui.h",抽查各模块代表性声明
* (类型 / 函数 / 宏)都存在。头拆分后用来证明伞头聚合无遗漏、签名未变。
* 用法:gcc -std=c11 -Wall -Wextra -I<sdk> -c test_umbrella.c -o test_umbrella.o
* (纯声明级检查,不链接、不调用;产生可执行代码仍 0 warning)。
*/
#include "meow_ui.h"
#include <stddef.h>
/* ---- 类型形状 _Static_assert(编译期)---- */
_Static_assert(sizeof(meow_ui_opts) == 2 * sizeof(int), "meow_ui_opts shape");
_Static_assert(sizeof(meow_theme) > sizeof(uint32_t), "meow_theme shape");
_Static_assert(offsetof(meow_theme, bg) == 0, "meow_theme.bg at 0");
_Static_assert(offsetof(meow_ime_ctx, buf) == sizeof(meow_ime_mode), "meow_ime_ctx.buf offset");
_Static_assert(offsetof(meow_list_item, title) > 0, "meow_list_item layout");
_Static_assert(sizeof(meow_notify) > sizeof(void *), "meow_notify shape");
_Static_assert(sizeof(meow_audio_state) > 0, "meow_audio_state shape");
_Static_assert(sizeof(meow_widget_opts) > 0, "meow_widget_opts shape");
/* ---- 枚举/宏值 _Static_assert(编译期;值定格即防漂移)---- */
_Static_assert(MEOW_KEY_POWER == 116, "key power");
_Static_assert(MEOW_KEY_PREVIOUS == 165, "key previous");
_Static_assert(MEOW_SWIPE_DOWN == 3, "swipe down");
_Static_assert(MEOW_IME_PINYIN == 2, "ime pinyin");
_Static_assert(MEOW_THEME_DARK == 1, "theme dark");
_Static_assert(MEOW_STYLE_MIUIX == 1, "style miuix");
_Static_assert(MEOW_Z_TOP == 1000, "z top");
_Static_assert(MEOW_TOPBAR_BACK == (-2), "topbar back");
_Static_assert(MEOW_SBAR_HOTZONE_FS == 4, "sbar hotzone fs");
_Static_assert(MEOW_WS_PRESSED == (1u << 3), "ws pressed");
_Static_assert(MEOW_BTN_ELEVATED == 4, "btn elevated");
_Static_assert(MEOW_LAYOUT_BOX == 2, "layout box");
_Static_assert(MEOW_LIST_SEL_MULTI == 2, "list sel multi");
_Static_assert(MEOW_NOTIFY_CAT_MEDIA == 5, "notify cat media");
_Static_assert(MEOW_NOTIFY_URG_CRITICAL == 3, "notify urg critical");
_Static_assert(MEOW_NOTIFY_TIMEOUT_ONGOING == (-1), "notify ongoing");
_Static_assert(MEOW_LOG_ERROR == 3, "log error");
_Static_assert(MEOW_DLG_INPUT == 2, "dlg input");
_Static_assert(MEOW_FONT_TIER_FULL == 2, "font tier full");
_Static_assert(MEOW_CFG_ERR_NOENT == (-2), "cfg noent");
/* ---- 函数存在性检查(取址即要求已声明;未声明 → 编译错误)---- */
static void umbrella_smoke(void)
{
/* 绘制层(§3)+ 时间/刷新率(§7/§7.1) */
(void)&meow_ui_init; (void)&meow_ui_flush; (void)&meow_ui_fill_rect_alpha;
(void)&meow_ui_text_center; (void)&meow_ui_time_ms; (void)&meow_ui_effective_rate;
/* 图片层(§4) */
(void)&meow_img_load_file; (void)&meow_ui_img_cover; (void)&meow_img_w;
/* 主题(§8) */
(void)&meow_theme_get; (void)&meow_theme_defaults; (void)&meow_ui_set_style;
/* 输入法(§5.1) */
(void)&meow_ui_text_input; (void)&meow_ime_text; (void)&meow_ime_composition;
/* 控件层(§5/§5.8/§5.8.6/§5.5) */
(void)&meow_btn_create; (void)&meow_widget_custom_create; (void)&meow_row_create;
(void)&meow_topappbar_hit; (void)&meow_listview_create; (void)&meow_list_tap_at;
(void)&meow_widget_set_opts; (void)&meow_widget_state; (void)&meow_progress_set;
/* 输入层/生命周期(§6)+ 长按(§6.3) */
(void)&meow_ui_run; (void)&meow_ui_swipe_hint; (void)&meow_ui_set_long_press_cb;
/* Activity 栈(§6.1) */
(void)&meow_ui_activity_push; (void)&meow_ui_global_add; (void)&meow_ui_activity_depth;
/* 绘制物注册表 / z 序(§6.2) */
(void)&meow_widget_set_z; (void)&meow_draw_custom_register; (void)&meow_ui_invalidate;
(void)&meow_ui_paint_full; (void)&meow_ui_set_page_bg;
/* 状态栏 / 全屏(§3.1) */
(void)&meow_ui_set_statusbar; (void)&meow_ui_statusbar_height; (void)&meow_ui_statusbar_hotzone;
(void)&meow_ui_statusbar_set_collapsed;
/* 模态(§5.8.6 弹窗/面板) */
(void)&meow_dialog_create; (void)&meow_dialog_show; (void)&meow_sheet_open;
/* 日志(§9) */
(void)&meow_log; (void)&meow_log_get_level;
/* 通知(§9.1) */
(void)&meow_notify_send; (void)&meow_notify_category_str; (void)&meow_notify_update_progress;
/* 配置(§9.2) */
(void)&meow_config_dir; (void)&meow_config_int; (void)&meow_config_remove;
/* 字体(§5.7/§10) */
(void)&meow_font_enumerate; (void)&meow_font_tier; (void)&meow_font_select_by_id;
/* 音频(§11) */
(void)&meow_audio_open; (void)&meow_audio_query; (void)&meow_audio_on_preempt;
}
/* 供宿主回归驱动直接调用;不链接本库也没关系(纯地址丢弃)。 */
void test_umbrella_run(void) { umbrella_smoke(); }