feat(sdk/view): 视图框架批次① — z序绘制物注册表(meow_ui_draw.c: 自动注册+auto_z(深度*步长+层内seq)+set_z(999)置顶+MEOW_Z_AUTO_MAX=127) + meow_view骨架(meow_ui_view.c/.h: 嵌套容器+六生命周期+page_push/pop/replace包装activity栈+sub_push/pop预留桩) + 收敛live_btn走invalidate + hello迁移(d_paint_region/d_redraw删除→meow_ui_invalidate, chrome set_z(999), demo文本注册CUSTOM z=128) (agent-176, 定案见SDK_VIEW_FRAMEWORK_DESIGN.md §E①)

meow_ui.a d814d0ed→7e20f10e; hello 0a1c96a5→2ce09466
宿主验证: test_p1p2p3_repro P1c/P2/P3 ALL PASS; test_meow_ui_widgets ALL PASS 无回归; mipsel -Wall -Wextra 0 warning
This commit is contained in:
MeowOS committed 2026-08-31 02:38:32 +08:00
1 parent fbc412e96a
commit 08c70aa14c
13 files changed
+872 -96

No files matched your search

+357
View File
@@ -0,0 +1,357 @@
/*
* meow_ui_draw.c — 绘制物注册表 / z 序 / 区域重画(§6.2 / SDK_Z_ORDER_DESIGN §2)。
*
* 非保留模型下,把「清底 + 按 z 重画重叠区完整 z 栈」下沉到 SDK:
* - 控件(meow_widget)创建即自动注册(create 末尾调 meow_draw_widget_register),
* meow_widget_free 自动注销;rect 实时读 w->x/y/w/h;
* - App 直绘的非控件内容显式 meow_draw_custom_register(声明 bbox + 绘制回调);
* - z 自动推导(子>父、同层注册先序);显式 set_z 粘滞、置顶。
* 显式 z 存于本注册表(按 w 反查 entry),**不改 struct meow_widget**(零 ABI 破坏)。
*/
#include "meow_ui.h"
#include "meow_ui_internal.h"
#include "meow_ui_view.h"
#include <stdlib.h>
#include <string.h>
#define MEOW_DRAW_MAX 256
#define MEOW_ITEM_VIEW 2 /* 内部 kinds(不进公共枚举):meow_view 绘制物 */
typedef struct draw_entry {
int kind; /* MEOW_ITEM_WIDGET / MEOW_ITEM_CUSTOM / MEOW_ITEM_VIEW */
meow_widget *w; /* WIDGET:绘制其 meow_widget_draw(w) */
meow_draw_fn draw_cb; /* CUSTOM:绘制回调 */
void *ctx; /* CUSTOM: 传给 draw_cb; VIEW: (meow_view*)v */
int rx, ry, rw, rh; /* CUSTOM bbox(WIDGET 读 w->x/y/w/h,VIEW 读 v->x/y/w/h) */
int z; /* 生效 z(显式=其值,否则=自动推导) */
int z_explicit; /* 1=显式(粘滞) */
int id; /* CUSTOM id(0=无效) */
int seq; /* 全局注册序(z 同值时稳定先序) */
struct meow_view *view; /* WIDGET:所属 view(z 深度源)+1 */
} draw_entry;
static draw_entry g_e[MEOW_DRAW_MAX];
static int g_n = 0;
static int g_seq = 0; /* 全局注册序(单调递增) */
static int g_next_id = 1; /* CUSTOM id 起点(0=无效) */
static uint32_t g_page_bg = 0;
static int g_page_bg_set = 0;
/* ---- 内部访问器(widget.c 提供;跨 TU 用 meow_ui_internal.h 声明)---- */
static int w_is_layout(const meow_widget *w) { return meow_widget_is_layout(w); }
/* ---- 查找 ---- */
static draw_entry *e_find_widget(const meow_widget *w)
{
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_WIDGET && g_e[i].w == w) return &g_e[i];
return NULL;
}
static draw_entry *e_find_view(const meow_view *v)
{
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_VIEW && g_e[i].ctx == (void *)v) return &g_e[i];
return NULL;
}
static draw_entry *e_find_id(int id)
{
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_CUSTOM && g_e[i].id == id) return &g_e[i];
return NULL;
}
/* ---- 深度:view 树深度 ---- */
static int view_depth(const meow_view *v)
{
int d = 0;
const meow_view *p = v ? v->parent : NULL;
while (p) {
d++;
if (d > MEOW_Z_DEPTH_MAX) break;
p = p->parent;
}
return d;
}
/* ---- 深度:widget 所属嵌套深度(view 树为主;否则 W_LAYOUT children 反推;否则 0)---- */
static int widget_nest_depth(meow_widget *w, int depth)
{
if (depth > MEOW_Z_DEPTH_MAX) return MEOW_Z_DEPTH_MAX;
draw_entry *e = e_find_widget(w);
if (e && e->view) return view_depth(e->view) + 1; /* 视图树深度源(更确定) */
/* 注册表反推:w 是否经 meow_layout_add 挂在某布局下(此时布局自身已注册为 WIDGET)。 */
for (int i = 0; i < g_n; i++) {
if (g_e[i].kind != MEOW_ITEM_WIDGET) continue;
meow_widget *lw = g_e[i].w;
if (!lw || !w_is_layout(lw)) continue;
int nc = meow_widget_nchild(lw);
for (int j = 0; j < nc; j++)
if (meow_widget_child_at(lw, j) == w)
return widget_nest_depth(lw, depth + 1) + 1; /* 子层 >= 父层+1 */
}
return 0;
}
/* 计算 auto z(显式不重算——粘滞):depth*STRIDE + 层内 seq(注册先序,折叠 MEOW_Z_PER_LEVEL_MAX)。 */
static void e_compute_auto(draw_entry *e)
{
if (e->z_explicit) return;
int depth = 0;
if (e->kind == MEOW_ITEM_WIDGET && e->w) depth = widget_nest_depth(e->w, 0);
else if (e->kind == MEOW_ITEM_VIEW && e->ctx) depth = view_depth((const meow_view *)e->ctx);
/* CUSTOM:z 恒显式(register 传入),不进 auto 分支 */
int cnt = 0;
for (int i = 0; i < g_n; i++) {
draw_entry *o = &g_e[i];
if (o == e || o->z_explicit) continue;
if (o->seq >= e->seq) continue;
if (o->z / MEOW_Z_STRIDE == depth) cnt++;
}
if (cnt > MEOW_Z_PER_LEVEL_MAX) cnt = MEOW_Z_PER_LEVEL_MAX;
e->z = depth * MEOW_Z_STRIDE + cnt;
}
/* ============================================================ */
/* 控件自动注册 / 注销(create 末尾 / meow_widget_free 调用) */
/* ============================================================ */
void meow_draw_widget_register(meow_widget *w)
{
if (!w || e_find_widget(w)) return; /* 幂等 */
if (g_n >= MEOW_DRAW_MAX) return; /* 满:静默(骨架级) */
draw_entry *e = &g_e[g_n++];
memset(e, 0, sizeof *e);
e->kind = MEOW_ITEM_WIDGET;
e->w = w;
e->seq = g_seq++;
e_compute_auto(e);
}
void meow_draw_widget_unregister(meow_widget *w)
{
if (!w) return;
int idx = -1;
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_WIDGET && g_e[i].w == w) { idx = i; break; }
if (idx < 0) return;
g_e[idx] = g_e[--g_n]; /* 交换移除(seq 保留,排序稳定) */
}
int meow_draw_widget_registered(const meow_widget *w)
{
return w ? e_find_widget(w) != NULL : 0;
}
void meow_draw_widget_set_view(meow_widget *w, struct meow_view *v)
{
draw_entry *e = e_find_widget(w);
if (!e) return;
e->view = v;
e_compute_auto(e);
}
/* ============================================================ */
/* 显式 z(widget) */
/* ============================================================ */
void meow_widget_set_z(meow_widget *w, int z)
{
if (!w || z < 0) return;
draw_entry *e = e_find_widget(w);
if (!e) return;
e->z_explicit = 1;
e->z = z;
}
int meow_widget_z(const meow_widget *w)
{
if (!w) return 0;
draw_entry *e = e_find_widget((meow_widget *)w);
if (!e) return 0;
if (e->z_explicit) return e->z;
e_compute_auto(e);
return e->z;
}
void meow_widget_clear_z(meow_widget *w)
{
if (!w) return;
draw_entry *e = e_find_widget(w);
if (!e) return;
e->z_explicit = 0;
e_compute_auto(e);
}
/* ============================================================ */
/* CUSTOM(App 直绘)注册 / 注销 / 改 z */
/* ============================================================ */
int meow_draw_custom_register(int z, int x, int y, int w, int h,
meow_draw_fn cb, void *ctx)
{
if (!cb || w <= 0 || h <= 0) return 0;
if (g_n >= MEOW_DRAW_MAX) return 0;
draw_entry *e = &g_e[g_n++];
memset(e, 0, sizeof *e);
e->kind = MEOW_ITEM_CUSTOM;
e->draw_cb = cb;
e->ctx = ctx;
e->rx = x; e->ry = y; e->rw = w; e->rh = h;
e->z = z < 0 ? 0 : z;
e->z_explicit = 1;
e->id = g_next_id++;
e->seq = g_seq++;
return e->id;
}
void meow_draw_unregister(int id)
{
if (id <= 0) return;
int idx = -1;
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_CUSTOM && g_e[i].id == id) { idx = i; break; }
if (idx < 0) return;
g_e[idx] = g_e[--g_n];
}
int meow_draw_set_z(int id, int z)
{
if (id <= 0 || z < 0) return -1;
draw_entry *e = e_find_id(id);
if (!e) return -1;
e->z = z;
e->z_explicit = 1;
return 0;
}
/* ============================================================ */
/* view 绘制物注册 / 注销 */
/* ============================================================ */
void meow_draw_view_register(struct meow_view *v)
{
if (!v || e_find_view(v)) return;
if (g_n >= MEOW_DRAW_MAX) return;
draw_entry *e = &g_e[g_n++];
memset(e, 0, sizeof *e);
e->kind = MEOW_ITEM_VIEW;
e->ctx = (void *)v;
e->seq = g_seq++;
e_compute_auto(e);
}
void meow_draw_view_unregister(struct meow_view *v)
{
if (!v) return;
int idx = -1;
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_VIEW && g_e[i].ctx == (void *)v) { idx = i; break; }
if (idx < 0) return;
g_e[idx] = g_e[--g_n];
}
int meow_draw_view_entered(const struct meow_view *v)
{
return v ? meow_view_get_state(v) & MEOW_VIEW_STATE_ENTERED : 0;
}
void meow_draw_view_set_z(struct meow_view *v, int z)
{
draw_entry *e = e_find_view(v);
if (!e) return;
if (z <= 0) {
e->z_explicit = 0;
e_compute_auto(e);
} else {
e->z_explicit = 1;
e->z = z;
}
}
/* ============================================================ */
/* page bg / 区域重画 / 整帧 */
/* ============================================================ */
void meow_ui_set_page_bg(uint32_t color) { g_page_bg = color; g_page_bg_set = 1; }
uint32_t meow_ui_page_bg(void) { return g_page_bg_set ? g_page_bg : meow_theme_get()->bg; }
static int rect_hit(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh)
{
return ax < bx + bw && ax + aw > bx && ay < by + bh && ay + ah > by;
}
static int entry_rect(draw_entry *e, int out[4])
{
if (e->kind == MEOW_ITEM_WIDGET && e->w) {
meow_widget_rect(e->w, out);
} else if (e->kind == MEOW_ITEM_VIEW && e->ctx) {
meow_view *v = (meow_view *)e->ctx;
out[0] = v->x; out[1] = v->y; out[2] = v->w; out[3] = v->h;
} else {
out[0] = e->rx; out[1] = e->ry; out[2] = e->rw; out[3] = e->rh;
}
return out[2] > 0 && out[3] > 0;
}
static void draw_one(draw_entry *e)
{
switch (e->kind) {
case MEOW_ITEM_WIDGET:
meow_widget_draw(e->w);
break;
case MEOW_ITEM_CUSTOM:
e->draw_cb(e->ctx);
break;
case MEOW_ITEM_VIEW: {
meow_view *v = (meow_view *)e->ctx;
if (v->hooks.on_draw) v->hooks.on_draw(v, meow_theme_get(), v->ctx);
break;
}
default:
break;
}
}
static void paint(int full, int x, int y, int w, int h)
{
uint32_t bg = meow_ui_page_bg();
if (full) {
meow_ui_clear(bg);
} else {
if (w <= 0 || h <= 0) return;
meow_ui_fill_rect(x, y, w, h, bg);
}
/* 刷新 auto z + 组装按 (z,seq) 升序的绘制序(owner==active 过滤 WIDGET;view 须已进入)。 */
draw_entry *order[MEOW_DRAW_MAX];
int nn = 0;
int active = meow_ui_activity_active();
for (int i = 0; i < g_n; i++) {
draw_entry *e = &g_e[i];
e_compute_auto(e);
if (e->kind == MEOW_ITEM_WIDGET && e->w && meow_widget_owner(e->w) != active) continue;
if (e->kind == MEOW_ITEM_VIEW && !meow_draw_view_entered((meow_view *)e->ctx)) continue;
order[nn++] = e;
}
/* 稳定插入排序:(z 升序,同 z 按 seq 升序=注册先序)。 */
for (int i = 1; i < nn; i++) {
draw_entry *key = order[i];
int j = i - 1;
while (j >= 0 && (order[j]->z > key->z ||
(order[j]->z == key->z && order[j]->seq > key->seq))) {
order[j + 1] = order[j];
j--;
}
order[j + 1] = key;
}
if (full) {
for (int i = 0; i < nn; i++) draw_one(order[i]);
meow_ui_flush();
} else {
int r[4];
for (int i = 0; i < nn; i++) {
if (!entry_rect(order[i], r)) continue;
if (rect_hit(r[0], r[1], r[2], r[3], x, y, w, h)) draw_one(order[i]);
}
meow_ui_flush_region(x, y, w, h);
}
}
void meow_ui_invalidate(int x, int y, int w, int h)
{
if (w <= 0 || h <= 0) return;
paint(0, x, y, w, h);
}
void meow_ui_paint_full(void)
{
paint(1, 0, 0, 0, 0);
}