SDK: 同步主仓 M15/M16/bug3/MD3 修复 — 时钟 ABI 补全/IME 冷却窗/列表行高派生/形状 token/翻页键

公开 SDK 落后主仓的一批 bugfix(主仓是固件构建源,这些修复已在设备上跑过)。
本次只做「主仓 → 公开仓」单向同步,图像栈方向由主仓侧另一单处理。

时钟 ABI(M16 第二弹,原文件自认「残余未修」):
- meow_ui_time.c 147→345 行:futex 相对超时接管(__timedwait/_cp)、
  timerfd_create/settime/gettime 的 itimerspec 64↔32 双向转换、
  __clock_settime64 越界返 ENOTSUP,另有 4 个纯换算函数
- meow_ui_internal.h:struct meow_time32 / meow_itimerspec32 契约移入内部头
- CLOCK_ABI.md:补接管机制、验证配方与 objdump 证据
- 新增 test_meow_time64.c

IME bug3(成对才有意义):
- meow_ui_ime.c:IME_TAP_COOLDOWN_MS 200 冷却窗 + 打开时二次 drain
- meow_ui_input.c:meow_input_touch_reset() 并在 drain 内调用(复位触摸状态机)
- test_ime_fix.c:新增用例④ stray-tap

列表行高(M15,修用户可见 bug):
- meow_ui_widget.c:listv_item_h() 由主题字体行高派生,不再写死 56
  (两行列表 62 > 56 会让首行标题被裁剪守卫整条跳过)
- include/meow_ui_widgets.h:新增 meow_listview_item_h()
- 新增 test_meow_ui_listview_rowh.c

其余:meow_select.c / meow_ui_dialog.c 统一 MD3 形状 token;
include/meow_ipc.h 补 MSG_KEY_PAGEUP/PAGEDOWN 枚举;
meow_ui_sys.c / meow_cachegov.c 取时统一走 meow_ui_time_ms()。

测试辅助函数标定:tuku/test/test_settings_lock_host.c 的注入前等待 150ms→350ms。
该等待按修复前 IME 标定,新冷却窗下首键 dt_open≈114ms 会被当迟到抬起吞掉,
只录到 "68" 两位。仅改等待时长,断言原样保留。

验证:tuku 四套脚本全绿(run_tests 644 PASS / zip 106 / cbz 296 / webtoon PASS);
12 个源文件与主仓逐字节一致;sdk/build_sdk.sh 34 成员;
tuku/build_tuku.sh 产出静态 MIPS32r2 ELF。
This commit is contained in:
AskaEth committed 2026-11-06 21:31:54 +08:00
1 parent 38cc9d4acb
commit 27a3750e36
37 files changed
+1026 -111

No files matched your search

+35 -10
View File
@@ -79,7 +79,7 @@ struct meow_widget {
int maxlen; /* W_TEXTFIELD 上限(含 NUL) */
meow_ime_mode ime_mode; /* W_TEXTFIELD IME 模式 */
int value; /* W_PROGRESS:0-100 / -1=不定; W_BADGE:计数 */
int item_h; /* W_LIST:行高/列宽(lazy),默认 44 */
int item_h; /* W_LIST:行高/列宽(lazy),默认 44;W_LISTVIEW:显式行高,0=按字体行高派生 */
int scroll; /* W_LIST:滚动偏移(lazy) */
int horizontal; /* W_LIST:1=横向(LazyRow) */
int back_on; /* W_TOPAPPBAR:显示返回箭头 */
@@ -1051,7 +1051,24 @@ int meow_list_set_container(meow_widget *w, int on)
* 宿主/设备需图片图标的 App 经 meow_ui_img_load_* 强引用 meow_ui_img.o → 此处自动解析。 */
extern void meow_ui_img_scaled(int x, int y, int w, int h, meow_img *img) __attribute__((weak));
static int listv_item_h(const meow_widget *w) { return (w->item_h > 0) ? w->item_h : 56; }
/* 行高:显式 meow_listview_set_item_h 优先(App 自管行几何时按自己算出的值传,如 ncm 70);
* 未显式(item_h<=0)→ 按当前主题正文字体行高派生,保证「文本块 ≤ 行高」:
* lines=2:max(56, 2*line_h + MEOW_LISTV_SUB_GAP) (20px 字库行高 30 → 62)
* lines=1:max(48, line_h)
* 旧默认固定 56 在真机 source_han_serif 20px(ascent 24 + descent 6 = 30)下小于双行
* 文本块 62 → 居中后 ty = 行顶 - 3,首行(行顶==视口顶)标题被 `ty >= vy0` 裁剪守卫整条
* 跳过,只剩副标题(M12 finding / M15 本源修复)。派生值由主题字库实时算出,draw/hit/
* max_scroll 三路共用同一函数 → 行几何恒一致;改字库档位/主题后自动跟随。 */
static int listv_item_h(const meow_widget *w)
{
if (w->item_h > 0) return w->item_h;
const meow_theme *th = meow_theme_get();
int line_h = th ? meow_ui_text_height(th->font_body) : 0;
if (w->lines == 1)
return (line_h > 48) ? line_h : 48;
int h = 2 * line_h + MEOW_LISTV_SUB_GAP;
return (h > 56) ? h : 56;
}
/* §5.5 虚拟化辅助:当前行数(pool 模式实时查 count_fn;src2 模式用缓存的 w->count)。 */
static int listv_count(const meow_widget *w)
@@ -1203,7 +1220,7 @@ meow_widget *meow_listview_create(int x, int y, int w, int h, int count,
t->owner = meow_ui_activity_active();
t->state = MEOW_WS_ENABLED;
t->count = count > 0 ? count : 0; t->src2 = src; t->ctx = ctx;
t->sel = -1; t->item_h = 56; t->scroll = 0; t->swipe_idx = -1;
t->sel = -1; t->item_h = 0; t->scroll = 0; t->swipe_idx = -1; /* item_h=0 → 按字体行高派生(见 listv_item_h) */
t->sel_mode = (mode >= MEOW_LIST_SEL_NONE && mode <= MEOW_LIST_SEL_MULTI) ? mode : MEOW_LIST_SEL_NONE;
t->lines = 2; t->show_icon = 1; t->show_right = 1; /* 默认双行富 item + 图标 + 右尾件(src2 布局不变) */
t->container = 1; /* M6.37 P1:SDK 默认列表走 MD3 容器模式——行=surfaceContainer 圆角卡 + 空隙 + 去分隔线 + 卡内 tonal 选中,
@@ -1225,7 +1242,12 @@ int meow_listview_set_item_h(meow_widget *w, int item)
listv_ensure_pool(w); /* 行高变小 → 可见行增多 → 池容量随之调整 */
meow_gfx_mark_dirty(w->x, w->y, w->w, w->h);
}
return w->item_h;
return listv_item_h(w); /* 返回当前生效行高(显式值或字体派生值) */
}
int meow_listview_item_h(meow_widget *w)
{
if (!w || w->type != W_LISTVIEW) return 0;
return listv_item_h(w);
}
void meow_listview_set_count(meow_widget *w, int count)
{
@@ -1398,7 +1420,7 @@ int meow_listview_set_item_renderer(meow_widget *w, int lines, int show_icon,
if (lines < 1) lines = 1;
if (lines > 2) lines = 2;
w->lines = lines; w->show_icon = show_icon ? 1 : 0; w->show_right = show_right ? 1 : 0;
if (w->item_h <= 0) w->item_h = (lines == 1) ? 48 : 56; /* 未显式定行高 → 档位默认 */
/* 未显式定行高(item_h<=0)→ 保持派生模式(按 lines 档位从字体行高算),不写死像素 */
listv_ensure_pool(w); /* 行档位可能变化 → 确保池容量 */
meow_gfx_mark_dirty(w->x, w->y, w->w, w->h);
return 0;
@@ -1410,7 +1432,7 @@ int meow_listview_set_item_tier(meow_widget *w, int lines)
if (lines < 1) lines = 1;
if (lines > 2) lines = 2;
w->lines = lines;
w->item_h = (lines == 1) ? 48 : 56; /* 档位默认高(可随后 set_item_h 覆盖) */
w->item_h = 0; /* 档位=字体派生默认(单行 max(48,行高) / 双行 max(56,2*行高+2));set_item_h 可覆盖 */
listv_ensure_pool(w);
meow_gfx_mark_dirty(w->x, w->y, w->w, w->h);
return 0;
@@ -2007,8 +2029,9 @@ void meow_widget_draw(meow_widget *w)
}
}
} else {
/* ① src2 模式(既有):每帧按需取行(meow_list2_source),行为不变。
* 行 = 图标(左) + 标题 + 副标题(次要色) + 右侧操作区;选中行 = primaryContainer。 */
/* ① src2 模式(既有):每帧按需取行(meow_list2_source),虚拟化行为不变。
* 行 = 图标(左) + 标题 + 副标题(次要色) + 右侧操作区;选中行 = primaryContainer。
* lines=1(set_item_renderer/tier 单行档位)时不画副标题,与 pool 分支同口径。 */
for (int i = first; i < last; i++) {
meow_list_item it;
memset(&it, 0, sizeof it);
@@ -2055,9 +2078,11 @@ void meow_widget_draw(meow_widget *w)
if (icy + isz >= vy0 && icy < vy1) /* 图标不越视口边界才画(防泄漏) */
listv_draw_icon(th, rlx + pad, icy, it.icon_kind, it.icon, iccol);
/* 标题 + 副标题(两行居中;无副标题=单行居中;越界不画防泄漏) */
/* 标题 + 副标题(lines=2 有副标题→两行居中;lines=1 或无副标题→单行居中;越界不画防泄漏)。
* lines 档位与 pool 分支同口径:tier/renderer 设单行时明确不画副标题,
* 否则 48px 单行档位里塞 62px 文本块 → 首行标题被裁剪守卫跳过。 */
int ty;
if (it.subtitle && it.subtitle[0]) {
if (w->lines == 2 && it.subtitle && it.subtitle[0]) {
ty = ry + (item - (2 * thh + MEOW_LISTV_SUB_GAP)) / 2;
if (it.title && ty >= vy0 && ty + thh <= vy1)
listv_text_trunc(rtx, ty, it.title, text_maxw, th->font_body, textcol);