# MeowOS 应用开发框架 SDK(meow_ui)设计 > 状态:设计稿(2026-08-29)。路线 B:**框架承载**——MeowAPPs 不再裸 `mmap("/dev/fb0")` 自绘、自读输入,而是链接统一静态库 `meow_ui.a`,用 API 开发业务;渲染/控件/图片/输入/导航由框架收口。 > 目标:应用只写业务,不重复造轮子;观感、交互、生命周期统一;避免每个应用踩一遍 fb 双缓冲 / ioctl 号 / 返回键 / 息屏交互这些坑。 --- ## 1. 问题与定案 **现状(APPS.md §3.3)**:应用必须"独占屏幕自绘"——自行 `open("/dev/fb0")`+`mmap` 绘制;自行 `open("/dev/input/event*")` 读输入;自行管返回。全部 480×720、RGB565、双缓冲 yoffset、ioctl 号 0x4600/0x4602,每个应用都要重写一遍,观感必然乱。 **定案:路线 B(框架承载)**。理由: - 现状只有 1 个示范应用能凑合;要开放多应用/第三方,裸自绘 = 爆炸。 - 渲染基建已就绪(`back_buf` + `meow_present` 无闪烁、`meow_font` 字库、`blend565` 混叠、脏区追踪),把它开放成 app 可链接的 API,是低成本高收益。 **分层决策**(分两步落地,不一次做完): - **B1 渲染/控件/图片 SDK**(本文档主体,优先):应用链接 `meow_ui.a`。依赖现成 `meow_font.a` + 内建 `stb_image`(单头文件、静态编入、解 PNG/JPEG/BMP)。**不依赖阶段 D,可独立先行。** - **B2 输入/生命周期/导航**(衔接阶段 D):把应用从"自读 event / 自管返回"解放,走 IPC + M3 导航栈。本文档 §5 给衔接设计,B2 实现归阶段 D。 --- ## 2. 架构分层 ``` ┌─────────────────────────────────────────────┐ │ MeowAPP(业务逻辑,只调 meow_ui API) │ ├─────────────────────────────────────────────┤ │ meow_ui 静态库(meow_ui.a) │ │ ├─ 绘制层 meow_draw_* │ │ ├─ 控件层 meow_widget_*(按钮/列表/滑条…)│ │ ├─ 图片层 meow_img_*(stb_image 解码) │ │ ├─ 输入层 meow_input_*(语义事件) │ ← B1:只收事件;B2:接 M3 导航 │ └─ 主题/配置 meow_theme_*(颜色/间距/字体) │ ├─────────────────────────────────────────────┤ │ 渲染后端 meow_ui_gfx(复用 launcher 机制) │ │ back_buf(RGB565) + meow_present(dirty) │ │ + meow_font(位图字库) + blend565 │ └─────────────────────────────────────────────┘ ``` **关键约定**: - 应用**只调 API**,绝不 `open fb`、`mmap`、`ioctl`、`open event`。屏幕/输入由 meow_ui 在应用 `meow_app_start()` 时建立、退出时释放。 - 渲染统一走 `back_buf` + `meow_present`:应用画到离屏,只在 `meow_ui_flush()` 时单次原子 blit 到 fb0(无撕裂无频闪,复用 M2.16 地基)。 - 颜色统一 24-bit RGB(`0xRRGGBB`),meow_ui 内部做 `rgb565()` 转换;字体绘制用 `meow_font`,字号约定 28(标题/状态栏)/20(正文/按钮)。 --- ## 3. 绘制层 API(B1) 所有绘制先画进离屏 back_buf;调用 `meow_ui_flush()` 才上屏。坐标 0,0 = 左上。 ```c /* 初始化/销毁(应用 main 里 meow_app_start 的懒加载) */ int meow_ui_init(const meow_ui_opts *opts); /* 开 fb、读几何、载字库、建 back_buf */ void meow_ui_shutdown(void); /* 帧缓冲几何(应用需自适应时读取) */ int meow_ui_width(void); /* 480 */ int meow_ui_height(void); /* 720 */ /* 基本绘制(全部画进 back_buf) */ 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); /* 圆角框 */ /* 文本 */ void meow_ui_text(int x, int y, const char *utf8, int size, uint32_t color); /* size=20/28 */ 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 */ ``` > 说明:`meow_ui_text_*` 底层即 `meow_font_drawtext` + `meow_font_width_text`;`meow_ui_fill_rect_alpha` 复用 `blend565`。**模糊/毛玻璃不在 B1 承诺**(硬件无 GPU、CPU 软渲;仅在静态小区域可考虑,见 §7)。 ### 3.1 全局状态栏(系统级组件,A+C 方案并入) **定位**:状态栏是**系统级全局组件**,由 SDK 统一绘制——所有界面(launcher 菜单 + MeowAPP 画面)默认都显示,**仅当 APP 声明全屏(fullscreen)才隐藏**。数据由 SDK 内置状态读取器抓系统快照(与 launcher 同源单点一致),非各画各的。 ```c /* 状态栏显隐(默认显示;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) */ int meow_ui_statusbar_height(void); ``` **绘制规则**: - `meow_ui_flush()` 上屏前,SDK 自动在顶部画状态栏(slim ~20-40px),内容:时钟 / 电量 / WiFi / 蓝牙 / 音量(与 launcher 一致)。 - 状态栏数据由 SDK 内置读取器周期刷新(~1s 轻刷,读 `/sys/class/power_supply/*`、WiFi 状态、时钟、音量寄存器——与 launcher 同一批 source)。 - **z 顺序**:状态栏是最顶层。APP 内容需 `meow_ui_statusbar_height()` 下移(inset),否则被状态栏盖住(有状态栏 OS 的通用做法)。 - **全屏(fullscreen)**:`meow_ui_set_fullscreen(1)` 或 app.json `fullscreen:1` → 隐藏状态栏 + 隐藏返回键(沉浸);退出全屏恢复。 **与 launcher 统一(A+C)**:launcher 迁移到 SDK 后,其状态栏(现私有 `draw_statusbar()`)改走 SDK 这一套,全局统一、单点一致。 **注意(诚实)**:这是 SDK 的较大增强——需引入系统状态读取器 + 顶部留白(inset)协调 + 与 APP 内容 z 顺序。非全屏 APP 必须给顶部 inset,否则内容被盖。API 名实现时以 `meow_ui.h` 为准。 --- ## 4. 图片层 API(B1) 内建 `stb_image`(单头文件,静态编入 `meow_ui.a`),解 PNG/JPEG/BMP,统一转 RGBA。**这是对"图片渲染"的直接答案**(背景/封面/图标)。 ```c /* 加载图片(从 RAM 缓冲或 TF 卡文件)。返回句柄,失败 NULL。 * mem: 应用可先读文件到 RAM 再喂给解码器;meow_ui 不解读自身以外的 IO。 */ 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); /* 绘制:整图 / 缩放 / 带 alpha */ 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 */ ``` > **裁剪/缩放**:软渲用最近邻(快),不做高质量插值(省 CPU)。封面用 `meow_ui_img_cover` 居中裁方 + 缩放到目标尺寸即可。 --- ## 5. 控件层 API(B1) 内置常用控件,观感统一(MD3 优先 / MIUIx 备选,见 §6 主题)。控件状态由 meow_ui 维护,绘制走 back_buf。 ```c typedef struct meow_widget meow_widget; /* 创建/销毁;控件 layout 由应用每次 flush 前调用 meow_widget_draw 绘制 */ 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); meow_widget *meow_list_create(/* 数据源回调 */); void meow_widget_free(meow_widget *w); /* 绘制 */ void meow_widget_draw(meow_widget *w); /* 状态/取值 */ void meow_slider_set(meow_widget *s, int val); int meow_slider_get(meow_widget *s); void meow_switch_set(meow_widget *s, int on); ``` > 控件命中(触摸点是否落在控件内)由输入层语义事件驱动,应用在 `meow_ui_on_tap(x,y)` 回调里做分发——见下节。 > **B1 先做最小控件集**(按钮/滑条/开关/列表四件套),其余(下拉、进度圈、通知卡片)随阶段 B 通知中心 / 网易云需要用再加。 ### 5.1 输入法(IME)—— 内置触屏软键盘 **背景**:R3 Pro II 无独立键盘设备(仅触摸 goodix-ts + 物理按键 md-gpio-keys / jz adc keyboard),无 USB/蓝牙 HID 键盘栈。**任何需要文本输入的应用(输入框/搜索/设置项)都依赖 IME,且必须由 SDK 内置**——应用绝不能自己实现键盘,否则观感/行为不一、重复造轮子。 **形态**:系统级单例软键盘,作为控件层的一个特例(`meow_ime`),应用调 `meow_ui_text_input()` 弹出,键盘覆盖在应用之上,由 SDK 绘制与分发(复用 `back_buf` + `meow_present` 无闪烁地基,不干扰业务渲染)。 **B1 范围**:**英文 QWERTY 键盘**(数字+字母+符号),覆盖字符输入、退格 Backspace、空格、回车/完成。 **不在 B1**:中文拼音/词库选字——复杂度高、依赖词库,留到后期独立 IME(网易云/中文搜索需要时再上)。B1 的 IME 只保证"能输入 ASCII 文本"。 ```c /* 弹出软键盘,输入到应用提供的缓冲。返回 1=确认(fn=enter),0=取消(fn=esc/背景点)。 * 回调驱动:输入变化由 SDK 内部循环处理,应用只需在 done 时读 out。 */ typedef enum { MEOW_IME_ASCII, MEOW_IME_NUM } meow_ime_mode; /* 全键盘/数字键盘 */ typedef struct { meow_ime_mode mode; char buf[256]; /* 应用提供的输入缓冲(初始值可预填,如 Wi-Fi 密码) */ int maxlen; /* 回调:每次字符变化回调一次(用于实时预览/校验) */ void (*on_change)(const char *text, void *ctx); void *ctx; } meow_ime_ctx; /* 阻塞:弹出键盘直到确认/取消。返回 1=确认(buf 已回填),0=取消。 */ int meow_ui_text_input(meow_ime_ctx *ctx); /* 非阻塞变体:返回后应用在 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); ``` **布局(480×720 竖屏)**:键盘占底部约 40% 高(~290px),上方为输入预览行 + 候选区。键位 40×40(够 touch target),触屏点按输入。 **物理键辅助**(兼容未来硬件键/可访问性):方向键移动光标、播放/确认键=选择、音量=翻页。B1 以触摸为主,物理键作为可选加分项(SDK 内实现)。 **[B1 后续 / 不阻塞]**:中文拼音 IME、词库、候选词联想、剪贴板、长按重复——作为独立里程碑,等首个中文输入场景(网易云搜索)出现再做。 --- ## 6. 输入层 / 生命周期(B1 部分 + B2 衔接) **B1(本阶段)**:应用不再自读 `/dev/input/event*`,meow_ui 建立输入线程,把按键/触摸翻译成语义事件回调: ```c /* 应用注册事件回调(meow_app_start 时传入) */ typedef struct { void (*on_key)(int keycode, int is_down); /* KEY_VOLUP/VOLDOWN/PLAYPAUSE/POWER…(SDK 已消化系统语义) */ void (*on_tap)(int x, int y); /* 触摸抬起落点 */ void (*on_swipe)(int dir, int dx, int dy); /* 左缘返回手势=LEFT;中部滑动=RIGHT/UP/DOWN */ void (*on_tick)(void); /* 空闲周期回调(动画/时钟用,见 §7) */ void (*on_swipe_progress)(int x_start, int dx);/* 左缘返回手势过程实时回调;x_start=按下X, dx=当前X-按下X */ } meow_ui_events; void meow_ui_run(const meow_ui_events *ev); /* 阻塞:事件循环,直到 meow_app 请求退出 */ void meow_ui_request_exit(void); /* 应用调它请求退出(相当于触返回/按退出键) */ /* 左缘返回手势的顶部视觉条(SDK 已自动绘制,应用一般无需自画)。 * 画屏幕顶部 5px、从 x=0 到 x 的横条(主题 accent 色);x<=0 清条。应用可在 * on_swipe_progress 里用它自画(长度=当前 X=x_start+dx),或留空全靠 SDK。 */ void meow_ui_swipe_hint(int x); ``` - **返回语义**:B1 下按"返回"(左缘返回手势/虚拟返回键)→ 由应用决定:`on_swipe(LEFT)` 是返回手势,应用自行 `meow_ui_request_exit()` 回应用列表;若想在页内返回,可在 `on_swipe(LEFT)` 里处理并 `return` 不退出。 - **左缘返回手势(抬手触发)**:手指从**屏幕左缘(≤24px)向内划 ≥90px**,**抬手(release 边沿)后才触发** `on_swipe(LEFT)`;过程以 `on_swipe_progress` 实时上报并自动画顶部进度条(`meow_ui_swipe_hint`,长度=当前 X)。中部左/右滑不触发返回(中部右滑→`on_swipe(RIGHT)` 内容导航;中部左滑→落 TAP)。**与设计稿 §2.2 的偏差**:§2.2 写「左縁 + 向左 mdx<-90」物理不可达(左縁起点再向左最多走 ~24px),故取「左縁向内(右)划 ≥90px」实现,事件仍报 `MEOW_SWIPE_LEFT`(保持「左滑=返回」契约),方向与 watchdog immersive 兜底一致。 - **沉浸模式**:应用声明(app.json `immersive=1`)→ launcher 写 `/tmp/meowapp_state=1` → watchdog 隐藏虚拟返回键,返回手势归 SDK。这是 B1 可做、B2 转正的一部分。 **B2(衔接阶段 D)**:把 `on_key`/`on_swipe` 换成走 IPC 的语义导航(`MSG_NAV` 上报 + 启动链路),应用不再自己决定"返回回哪层",而是上报当前 Activity,由框架导航栈统一回退。届时: - `meow_ui_run` 改为从 IPC 收启动链路(`MEOW_CHAIN`/`MEOW_ACTIVITY` 环境变量)初始化导航栈; - 返回 = 栈回退,到根才 `meow_ui_request_exit()`。**本文档 §5 的控件与 §3/§4 绘制在 B2 不变**,只换输入/导航后端。 --- ## 7. 动画/时间(B1 最小可用) 当前无动画框架。B1 提供**帧驱动回调 + 内置时间**,应用据此做低成本的帧序列/淡入淡出: ```c /* on_tick(ev) 里用 meow_ui_time_ms() 做时间轴动画 */ uint64_t meow_ui_time_ms(void); /* 单调毫秒时间戳 */ /* 动画 = 应用在 on_tick 里根据时间更新状态 → 调绘制 → meow_ui_flush_region 只刷变化区 */ ``` **约束**: - 只做**状态时间轴动画**(如滑条拖动回馈、列表项滑动、淡入淡出用 `fill_rect_alpha` 叠加),**不做实时 tween 每帧重算几何**(CPU 软渲扛不住)。 - 动图/视频:**B1 不提供**(无解码器/无 GPU)。若确需"动画封面",用**预渲染位图帧序列**(应用持有若干帧,`on_tick` 按时间切帧 + `flush_region`),这是唯一低成本的动图方案。 - 毛玻璃/模糊背景:**支持廉价版**(HibyOS 同款降采样模糊,见 §11)——用 `meow_ui_img_scaled` 缩 1/8 铺底 + `fill_rect_alpha` 遮罩;**仅在切歌/换封面时算一次,非每帧**。真高斯卷积/全屏动态模糊不做。 --- ## 8. 主题/配置(B1) 观感统一的核心,也是回应"控件样式效果"。**内置日间 / 夜间两套主题,跟随 MeowOS 系统设置的主题模式自动切换。** ```c typedef enum { MEOW_THEME_LIGHT, MEOW_THEME_DARK, MEOW_THEME_AUTO } meow_theme_mode; typedef struct { uint32_t bg; /* 背景色 */ uint32_t fg; /* 前景/正文 */ uint32_t accent; /* 强调色(按钮/选中) */ uint32_t dim; /* 次要文字 */ int font_title; /* 28 */ int font_body; /* 20 */ /* MD3 优先 / MIUIx 备选 */ } meow_theme; /* 当前生效主题(应用只读)。AUTO 时按系统主题设置(display.theme_mode)解析, * 日间取 light 表、夜间取 dark 表;由框架在主题模式变化时刷新。 */ const meow_theme *meow_theme_get(void); /* 设置主题模式(AUTO 时联动系统设置键 display.theme_mode)。 */ void meow_theme_set_mode(meow_theme_mode m); meow_theme_mode meow_theme_get_mode(void); /* 主题变化通知:应用注册后,AUTO 切换日/夜时收到回调(据此重绘)。 */ 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); ``` **双主题 + 跟随系统设置**: - **日间/夜间**:SDK 内置两套标准色板(`meow_theme_light` / `meow_theme_dark`),日间高亮(浅底深字)、夜间低亮度(深底浅字,护眼省电)。框架所有控件/绘制默认读当前生效主题,应用 `meow_theme_get()` 只读、不自配色。 - **跟随系统设置**:主题模式 `display.theme_mode`(`light`/`dark`/`auto`)是 `meow_settings` 的一个设置键。`auto` 时按系统时间(如 6:00-18:00 日间,其余夜间)或系统亮度/环境判定切换(B1 先用固定时段,后续可接入环境光,见遗留)。框架监听该键,变时对注册的 listener 广播,实体 UI / Web / 应用统一重绘。 - **主题切换即时生效**:`meow_theme_set_mode` 非"只改设置",会立即广播 listener 并让当前绘制的控件用新主题重绘(应用在 `on_tick` 里据 listener 触发 `meow_ui_flush_region`)。 > 主题随 `meow_settings` 的 `display.theme_mode` 键分发;框架统一,应用不必自配色——这正是"实体 UI / Web 面板 / 应用全程一致观感"的保证。 --- ## 9. 目录/构建约定 ``` patch_v2/apps_assets/apps//app.json # 应用描述(新增 SDK/immersive 字段,见下) patch_v2/hello_app/hello.c # 应用源码(改造为调 meow_ui 的示例) patch_v2/sdk/ # SDK 源码 ├── meow_ui.h # 对外 API(本文档 §3-§8) ├── meow_ui_gfx.c # 渲染后端(back_buf+present+font) ├── meow_ui_widget.c # 控件 ├── meow_ui_img.c # stb_image 解码 ├── meow_ui_input.c # 输入线程+语义事件 ├── meow_ui_theme.c ├── stb_image.h / stb_image.c # 单头文件(vendor) patch_v2/meow_launcherd/meow_font.a # 复用(静态链接) ``` 构建出 `patch_v2/sdk/meow_ui.a`;应用编译链(zig-mipsel-cc)额外链 `meow_ui.a meow_font.a libz.a -lpthread`。 **app.json 扩展字段**(向后兼容,缺省即旧行为): ```json { "name": "Hello App", "exec": "...", "version": "0.1", "framework": 1, // 1=走 meow_ui(框架承载);缺省/0=裸自绘(旧) "immersive": 0, // 1=沉浸模式(隐藏虚拟返回键,左缘滑动返回) "icon": "apps/hello/icon.png" // 可选:列表图标(供图片层) } ``` --- ## 10. 与阶段关系 / 落地顺序 - **B1(本文档,先行)**:`meow_ui.h` + gfx/widget/img/input/theme 最小实现 + `meow_ui.a`;**改造 hello.c 为 SDK 版**作为示例;出包 `r3proii_m2_20.upt` 或独立应用包验证。**不依赖阶段 D。** - **B2(衔接阶段 D)**:输入/导航后端换成 IPC + M3 导航栈,应用框架字段 `framework=1` 的应用自动升级为"导航栈承载",裸应用保持兼容。 - **依赖**:`meow_present/back_buf/dirty`(M2.16 地基,✅)、`meow_font`(✅)、`blend565`(✅)——B1 全部基于现有能力,**无需新的硬件依赖**;仅新增 stb_image(单头文件)与输入线程。 --- ## 11. 硬件约束(务必让应用作者知道) | 能力 | 可行性 | 说明 | |---|---|---| | 图片(PNG/JPEG/BMP 静态图) | ✅ 支持 | stb_image 解码 + 最近邻缩放;封面居中裁方 | | 半透明叠加 | ✅ 支持 | `fill_rect_alpha`(blend565),面板/遮罩可用 | | 圆角/描边 | ✅ 支持 | 圆角框 + 字体描边 | | 毛玻璃/模糊背景 | ✅ 支持(廉价版) | **HibyOS 同款「降采样模糊」**:封面缩到 1/8 再放大铺底(天然低通滤波抹掉高频),叠一层 `fill_rect_alpha` 半透明遮罩,清晰小封面叠其上。**背景只在切歌/换封面时算一次,非每帧**;不是真高斯卷积、不需 GPU。用 `meow_ui_img_blur_bg()` 生成背景 cache。**已实测依据**:设备 `playing_plane/` 无模糊背景图 + 无 GPU/无 SIMD/14MB 内存 → 运行时模糊只能走降采样近似,成本微秒级 | | 控件动画(时间轴/帧序列) | ⚠️ 有限 | 只做状态式动画;实时 tween 不做;动图=预渲染帧序列 | | 动图(GIF/WebP 动画) | ⚠️ 弱支持 | 用预渲染位图帧序列模拟;不承诺实时 GIF 解码 | | 视频 | ❌ 不做 | 无解码器/无 GPU/内存 14MB 会 OOM;如需"视频"用预渲染帧序列 | | 刷新率 | 上限 60(默认)/30/15 | 应用动画别贪高帧率,软渲耗 CPU | --- ## 12. 遗留 / 待实现 1. `meow_ui` 渲染后端需从 launcher 里**抽公共绘制实现**(`back_buf`/`meow_dirty_*`/`meow_present`/`meow_font_bind` 目前是 launcher 静态函数——需提取为可链接的 `meow_ui_gfx` 或改为共享 obj,注意 launcher 与 app 是**不同进程**,不能共享同一 back_buf;`meow_ui.a` 是**独立库**,内部自建 fb 上下文,不复用 launcher 的全局 `g_dirty`)。 2. 输入线程优先级:vs 主循环 10ms 热键轮询的竞态,需在 B1 实现时定义清楚(应用进程内独立事件循环,不与 launcher 抢)。 3. 网易云跑通后迭代控件集(播放页/列表/歌词),非一次性补齐。 4. **`meow_ui_img_blur_bg`(降采样模糊背景,HibyOS 同款)API 待加**:已在 §11 确认可行性(缩 1/8 放大铺底 + α 遮罩,切歌算一次);函数签名与实现留到 B1 之后(或并入网易云播放页时)。当前 SDK B1 的图片层先用 `meow_ui_img_scaled` + `fill_rect_alpha` 手动组合即可达到同等观感。 5. 视频**已定不做**:无解码器/无 GPU/内存 14MB 会 OOM;"视频"一律用预渲染帧序列模拟。若确需播放具体小视频,宿主机离线转帧序列 PNG → 打包到 TF 卡 → SDK 按帧播放(规避设备一切解码负担)。 ### B1 落地状态(2026-08-29) - **B1.0 渲染后端** ✅ `meow_ui_gfx.c`:自建 fb 上下文(自 mmap `/dev/fb0`、自建 `back_buf`、独立脏区集 + vsync+原子 blit);无 fb 时(宿主/qemu)离屏 480×720,`MEOW_UI_DUMP=` 可把 back_buf 导出 PPM 截图。 - **B1.1 绘制层** ✅ §3 全量:`meow_ui_clear/put_px/fill_rect/draw_rect/draw_rect_round/fill_rect_alpha/blend565` + `text/text_right/text_center/text_width/text_height`。字库(真机)优先,回退内建 5×7 点阵。 - **B1.2 图片层** ✅ `meow_ui_img.c` + 内建 `stb_image`(PNG/JPEG/BMP→RGBA):`meow_img_load_file/mem/free/w/h`、`meow_ui_img/scaled/alpha/cover`(最近邻 + 居中裁方)。宿主已用 test.png 验证预览/裁剪/缩放。 - **B1.3 控件层** ✅ `meow_ui_widget.c`:`meow_btn/slider/switch/list` 最小集(绘制 + 命中 + 取值)。 - **B1.4 输入层** ✅ `meow_ui_input.c`:输入线程读 `event*`(触摸 goodix-ts / md-gpio-keys / ADC 键),翻译成 `on_key/on_tap/on_swipe/on_tick` 语义事件;`meow_ui_run/request_exit`。手势专项(GESTURE_BACK):左缘返回手势=抬手触发 + `MEOW_EV_SWIPE_PROGRESS` 进度上报 + `on_swipe_progress` 回调;SDK 自动画顶部进度条 `meow_ui_swipe_hint`。 - **配套:Launcher 统一触摸接口 `meow_touch`**(M2.25,launcher 内部,应用不依赖)✅ `patch_v2/meow_launcherd/meow_touch.{h,c}`:Launcher 自身 UI(应用列表 / 电源菜单 / 确认框)的低性能触摸解析收敛为一份,goodix 时序免疫(`BTN_TOUCH=1` 不锁原点,等按下后首个有效 `ABS` 才锁;抬手位移 ≥65px 判滑动不命中)。应用侧**不**用它——应用触摸由本 SDK 输入层(`meow_ui_input.c`)翻译成 `on_tap/on_swipe` 回调,两者互不干扰;与 SDK 触摸保持一致的 goodix 时序免疫语义(详见 `meow_touch.h` 注释)。 - **B1.5 主题** ✅ `meow_ui_theme.c`:日间/夜间两套色板 + `get/set_mode/get_mode/add/remove_listener`;跟随 `display.theme_mode`(`/usr/data/meow/settings.conf`)。AUTO 按本地 6:00-18:00 日间。 - **B1.6 IME** ✅ `meow_ui_ime.c`:英文 QWERTY / 数字软键盘(ASCII),`meow_ui_text_input`(阻塞)+ `meow_ui_text_input_async/meow_ime_active/meow_ime_text`;覆盖底部约 300px,背景点=取消、OK=确认。 - **构建** ✅ `patch_v2/sdk/meow_ui.a`(含 meow_font.o 内联,应用只需链 `meow_ui.a libz.a -lpthread`);`build_sdk.sh` 一键重编。宿主 + `qemu-mipsel` 均跑通;示例 `hello` 改造为 SDK 版(见 §9 目录与 `patch_v2/hello_app/build_hello.sh`)。 - **验证**:`meow_ui.a` mipsel 静态编译链接 ✅(宿主 demo + qemu 均导出可见画面到 `device_test/`);真机 /dev/fb0 几何与输入触屏**未实测**(设备本次不可达,逻辑参照 launcher 既有实现)。 **实现期 API 微调(相对本文档)**: - [D1] `meow_ui_opts` 补充 `width/height`(0=自动读 fb;离屏缺省 480×720)。 - [D2] `meow_list_create` 数据源回调定案为 `int (*)(int idx, char *label, int len, void *ctx)`。 - [D3] 新增内部 `meow_gfx_fill_round/blit_rgba/mark_dirty`(控件/图片用,非公共 API)。 - [D4] 新增 `meow_theme_defaults(mode)`(脱机取内置色板)。 - [D5] 新增 `on_swipe_progress` 回调 + `meow_ui_swipe_hint(x)`(左缘返回手势视觉条)+ 内部 `MEOW_EV_SWIPE_PROGRESS` / `meow_input_inject`(宿主验证用)。 - `meow_ui.h` 为对外权威签名;本文件 §3-§8 作为设计蓝本。 --- *文档基于 2026-08-29 现有渲染基建(M2.16 无闪烁地基 + meow_font + blend565)编写;API 名会随 B1 实现微调,实现时以 `meow_ui.h` 为准。*