sdk: 事件分发形式化(§6.4)—— 统一命中/捕获/消费/层间隔离/焦点

根治「焦点/事件穿透」一类反复 bug。此前命中/捕获/消费/层间隔离各处 ad-hoc;
现上收为单一仲裁者(meow_ui_input.c),公共 API 只追加、不删改既有签名。

分发模型:
- 触摸沿 z 序自顶向下命中(meow_draw_hit_topdown,owner==active+enable 过滤);
- 命中即消费;模态层永远先审(meow_ui_modal_begin/end/active/depth);
- down 捕获(meow_ui_gesture_begin/owner/end):命中目标捕获手势直到 up,防滑出误触下层;
- 模态存在时下层完全收不到事件——hit_topdown 恒返回模态哨兵(背板消费,不透传);
- meow_ui_run 在 TOUCH_DOWN 自动 begin、TAP/SWIPE/LONG_PRESS/NOTIF_PULL 自动 end。

焦点模型:
- 唯一持有者(meow_ui_focus_acquire/release/owner/tap);
- 点非 focus 区域→释放并通知(meow_ui_focus_tap,list 焦点残留根治);
- 滚动容器(list/listview)tap_at 命中行自动 acquire,点外由 run 的 focus_tap 释放;
- lost 回调(meow_ui_focus_set_lost_cb)通知转移。

迁移(行为修复,正常交互语义不变):
- dialog/sheet → meow_ui_modal_begin/end(模态期下层收不到;叠黑由既有整帧快照+卡片仅重绘保证);
- list/listview tap → meow_ui_focus_acquire;
- 注入/叠加让位(overlay_input_suppressed)与模态层隔离互补,语义不变。

验证:新穿透矩阵 test_meow_ui_dispatch(M1 模态点下层不触发 / M2 弹层叠开两层层隔离 /
M3 捕获手势滑出不误触 / M4 list 焦点点外释放)ALL PASS;
全量回归 widgets/ime_fix/pinyin/overlay_suppress/notif_gesture/sdk_fixes/sb_collapse/
p1p2p3_repro/box/anim/scroll/sdk_input_keys 全 PASS;交叉 -Wall -Wextra 0 warning。

meow_ui.a 新 md5:a9fcfb6eeb07ddbdd48039df4f8f18ce(主会话统一重链,本仓未重链 App)
This commit is contained in:
AskaEth committed 2026-09-02 00:57:58 +08:00
1 parent c3abc3fee4
commit 54d2791f48
8 files changed
+428 -3

No files matched your search

+22
View File
@@ -266,6 +266,28 @@ void meow_draw_view_set_z(struct meow_view *v, int z)
}
}
/* ============================================================ */
/* §6.4 自上而下命中(事件分发形式化) */
/* ============================================================ */
void *meow_draw_hit_topdown(int x, int y)
{
void *best = NULL;
int bestz = -1, bestseq = -1;
for (int i = 0; i < g_n; i++) {
draw_entry *e = &g_e[i];
e_compute_auto(e);
/* 只对注册控件做顶层命中;view 是容器(其子 widget 是独立更高 z 的绘制物,各自命中),
* CUSTOM 是 App 直绘(不参与命中)。meow_widget_hit 内部含 owner==active + enable +
* 矩形/自定义命中回调。 */
if (e->kind != MEOW_ITEM_WIDGET || !e->w) continue;
if (!meow_widget_hit(e->w, x, y)) continue;
if (e->z > bestz || (e->z == bestz && e->seq > bestseq)) {
bestz = e->z; bestseq = e->seq; best = e->w;
}
}
return best;
}
/* ============================================================ */
/* page bg / 区域重画 / 整帧 */
/* ============================================================ */