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

+33 -23
View File
@@ -68,6 +68,8 @@
/* §6.4 事件分发形式化:手势捕获终点前向声明(meow_input_drain 之前定义后置,见下方实现)。 */
void meow_ui_gesture_end(void);
/* 触摸状态机复位(定义在触摸状态机变量之后,meow_input_drain 内调用)。 */
void meow_input_touch_reset(void);
/* ── 内部事件:系统级「下拉展开通知中心」(M2.5x 接线)──
* 触摸状态机在抬手判定处识别「SWIPE_DOWN 起始于顶部热区」后压入;事件循环按系统手势处理
@@ -120,13 +122,6 @@ static uint64_t last_tick_ms = 0;
static uint64_t startup_cooldown_until = 0;
#define STARTUP_COOLDOWN_MS 500
static uint64_t now_ms(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)ts.tv_sec * 1000u + (uint64_t)ts.tv_nsec / 1000000u;
}
/* settings.conf 路径(可被 env MEOW_SETTINGS_FILE 覆盖,宿主测试用;设备默认同 meow_ui_sys.c)。 */
static const char *meow_settings_path(void)
{
@@ -212,6 +207,10 @@ void meow_input_drain(void)
g_qh = 0; g_qt = 0;
pthread_mutex_unlock(&g_qm);
meow_ui_gesture_end(); /* §6.4:清空队列=丢弃未完成手势(如开 IME/模态前),释放捕获防悬垂 */
/* WiFi 设置页 bug3(2026-09-15):drain 同时复位触摸状态机——语义自洽:drain=丢弃在途
* 手势。否则 drain 前已开始、drain 后才被输入线程读出的「抬起」仍会按残留原点产生
* 一个迟到 TAP 入队(IME 打开瞬间被当「点背景=取消」或幻影按键,键盘开即关)。 */
meow_input_touch_reset();
}
static void push_ev(int type, int a, int b)
@@ -260,6 +259,19 @@ static int t_mv_x = -1, t_mv_y = -1;
/* §6.3 通用长按:本次按压是否已触发过长按(触发后抬手不再产生 TAP/SWIPE)。 */
static int t_long_fired = 0;
/* 触摸状态机整体复位:丢弃在途手势(down/原点/坐标/长按触发标记全部归零)。
* 调用点:① meow_input_drain(drain=丢弃在途手势,IME/模态打开前);② §10.5 叠加抑制
* 进入沿(防抑制期丢失抬手致 t_down 卡死)。效果:复位前已开始、复位后才抬起的按压
* 不再产生 TAP/SWIPE(WiFi 设置页 bug3:IME 打开 drain 之后才入队的迟到「抬起 TAP」
* 曾把键盘当「点背景=取消」瞬间关闭)。 */
void meow_input_touch_reset(void)
{
t_down = 0; t_press_valid = 0; t_origin_valid = 0;
t_cx = -1; t_cy = -1; t_dx = 0; t_dy = 0; t_down_ms = 0;
t_mv_x = -1; t_mv_y = -1;
t_long_fired = 0;
}
/* §6.3 通用长按:阈值(默认 MEOW_LONG_PRESS_MS;App 可经 meow_ui_set_long_press_ms 配)。 */
static int g_long_press_ms = MEOW_LONG_PRESS_MS;
/* §6.3 注册的长按回调(NULL=未注册;触发时以 (x,y) 调用,坐标=触发时刻按下点)。 */
@@ -275,7 +287,7 @@ static void touch_press(int x, int y)
t_origin_valid = 0;
t_cx = -1; t_cy = -1;
t_dx = 0; t_dy = 0;
t_down_ms = now_ms(); /* 记按下时刻:供实时按住时长/按住视觉 */
t_down_ms = meow_ui_time_ms(); /* 记按下时刻:供实时按住时长/按住视觉 */
t_mv_x = -1; t_mv_y = -1; /* M2.71:拖动过程起点未定 */
t_long_fired = 0; /* §6.3:每次新按压复位长按触发标记 */
}
@@ -373,7 +385,7 @@ int meow_input_touch_y(void) { return t_cy; }
unsigned int meow_input_touch_hold_ms(void)
{
if (!t_down) return 0;
uint64_t e = now_ms() - t_down_ms;
uint64_t e = meow_ui_time_ms() - t_down_ms;
if (e > 0xFFFFFFFFu) e = 0xFFFFFFFFu;
return (unsigned int)e;
}
@@ -384,7 +396,7 @@ void meow_input_touch_set(int down, int x, int y, unsigned hold_ms)
if (down) {
t_down = 1; t_press_valid = 1; t_origin_valid = 1; t_long_fired = 0;
t_cx = x; t_cy = y; t_dx = x; t_dy = y;
uint64_t now = now_ms();
uint64_t now = meow_ui_time_ms();
t_down_ms = (now > (uint64_t)hold_ms) ? (now - (uint64_t)hold_ms) : 0;
} else {
t_down = 0; t_press_valid = 0; t_origin_valid = 0; t_long_fired = 0;
@@ -525,7 +537,7 @@ static uint64_t g_sys_press_ms = 0;
static void sys_key_press(int code)
{
uint64_t now = now_ms();
uint64_t now = meow_ui_time_ms();
if (code == g_sys_press_code && now - g_sys_press_ms < SYS_KEY_DEDUP_MS)
return; /* 事件流 + EVIOCGKEY 双源去重:同码窗口内只消化一次 */
g_sys_press_code = code;
@@ -592,9 +604,7 @@ static void *input_thread(void *arg)
if (overlay_input_suppressed()) {
if (!overlay_was) { /* 进入沿:复位触摸状态机,防抑制期丢失抬手致 t_down 卡死 */
overlay_was = 1;
t_down = 0; t_press_valid = 0; t_origin_valid = 0;
t_cx = t_cy = -1; t_dx = t_dy = 0; t_down_ms = 0; t_mv_x = t_mv_y = -1;
t_long_fired = 0;
meow_input_touch_reset();
}
if (r > 0)
for (int i = 0; i < nfd; i++) {
@@ -685,7 +695,7 @@ void meow_ui_request_exit(void) { g_exit = 1; }
static uint64_t g_activity_last_ms = 0;
void meow_ui_activity_ping(void)
{
uint64_t now = now_ms();
uint64_t now = meow_ui_time_ms();
if (now - g_activity_last_ms < 500) return; /* 节流:任意交互连续触摸也只 ~2 次/s */
g_activity_last_ms = now;
if (!meow_gfx_is_device()) return; /* 离屏/宿主:无 launcher 消费 */
@@ -698,8 +708,8 @@ void meow_ui_run(const meow_ui_events *ev)
if (ev) { g_events = *ev; g_events_set = 1; }
g_exit = 0;
meow_input_start();
last_tick_ms = now_ms();
startup_cooldown_until = now_ms() + STARTUP_COOLDOWN_MS; /* M2.22(C):启动窗口丢弃 SWIPE */
last_tick_ms = meow_ui_time_ms();
startup_cooldown_until = meow_ui_time_ms() + STARTUP_COOLDOWN_MS; /* M2.22(C):启动窗口丢弃 SWIPE */
while (!g_exit) {
/* agent-119:实时触摸按压/按住/释放 → 即时重绘命中按钮区(不等 app 重绘)。
@@ -707,10 +717,10 @@ void meow_ui_run(const meow_ui_events *ev)
* §6.3 通用长按:每帧检测「按下 ≥ 阈值且位移 ≤ 容忍」跨越(IME 打开不驱动;启动窗口不触发)。 */
if (!meow_ime_active()) {
meow_widget_touch_refresh();
if (now_ms() >= startup_cooldown_until) meow_input_long_press_poll();
if (meow_ui_time_ms() >= startup_cooldown_until) meow_input_long_press_poll();
} else if (meow_ime_mode_pinyin()) {
/* 拼音 IME 打开:喂长按轮询(长按退格清空字段)。英文模式不喂(保持既有行为)。 */
if (now_ms() >= startup_cooldown_until) meow_input_long_press_poll();
if (meow_ui_time_ms() >= startup_cooldown_until) meow_input_long_press_poll();
}
meow_input_ev e;
@@ -719,7 +729,7 @@ void meow_ui_run(const meow_ui_events *ev)
if (g_exit) break; /* 已请求退出:不再分发剩余事件,杜绝「退出后又触发」的偶发再进/退 */
got = 1;
meow_ui_activity_ping(); /* M2.71-bug5:任意交互事件都喂 launcher 重置息屏计时(节流) */
int in_startup = (now_ms() < startup_cooldown_until); /* M2.22(C) */
int in_startup = (meow_ui_time_ms() < startup_cooldown_until); /* M2.22(C) */
if (e.type == MEOW_EV_TAP) {
if (in_startup) continue; /* 启动窗口也吞 TAP:旧手势残留点按(如上一次左滑抬起)
* 在进入瞬间命中 UI 按钮(如全屏按钮)会误触发——丢弃。 */
@@ -834,7 +844,7 @@ void meow_ui_run(const meow_ui_events *ev)
}
}
uint64_t now = now_ms();
uint64_t now = meow_ui_time_ms();
if (g_events_set && g_events.on_tick) {
if (now - last_tick_ms >= 16) {
last_tick_ms = now;
@@ -860,7 +870,7 @@ void meow_ui_run(const meow_ui_events *ev)
if (meow_ime_active()) { /* 软键盘覆盖层随帧绘制(30fps 节流,省 CPU) */
static uint64_t last_ime_ms = 0;
uint64_t n = now_ms();
uint64_t n = meow_ui_time_ms();
if (n - last_ime_ms >= 33) {
last_ime_ms = n;
meow_ime_draw();
@@ -880,7 +890,7 @@ void meow_ui_run(const meow_ui_events *ev)
void meow_ui_feed_tick(void)
{
if (!(g_events_set && g_events.on_tick)) return;
uint64_t now = now_ms();
uint64_t now = meow_ui_time_ms();
if (now - last_tick_ms < 16) return;
last_tick_ms = now;
g_events.on_tick();