Files
MeowOS-SDK/sdk/test_notif_gesture.c
T
AskaEth 27a3750e36 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。
2026-11-06 21:31:54 +08:00

122 lines
6.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* test_notif_gesture.c — M2.87 宿主验证「顶部下滑 → 通知中心」手势优先分类(meow_ui_input.c):
* 复现并断言修复:起点在顶部热区 + 有真实向下位移(mdy>0 且 ady≥SWIPE_THRESH)的下滑,必须
* 分类为 MEOW_EV_NOTIF_PULL(系统保留手势,路由 meow_ui_sys_notif_pull → MSG_NOTIF_OPEN),
* 即便该手势同时落在左缘且向右位移 ≥ ady(旧代码被水平分量抢判为 MEOW_SWIPE_LEFT → 漏给
* App on_swipe → 根页退出)。纯水平右滑/起点不在热区的下滑不误判。
*
* 用例(经 meow_input_touch_set/move/release 驱动真实 touch_release + 队列,pop 断言):
* T1 顶部+左缘+向下右侧滑 (10,5)->(110,75):adx=100≥ady=70, 热区内, ady≥65 → NOTIF_PULL(旧代码→LEFT)
* T2 顶部+左缘 竖直下滑 (240,5)->(240,120):ady=115, 热区内 → NOTIF_PULL
* T3 顶部+左缘 下移<65 (10,5)->(100,40):ady=35<65 → 非 NOTIF_PULL → LEFT(水平占优)
* T4 顶部+左缘 纯水平右滑 (5,5)->(110,5):ady=0<65 → 非 NOTIF_PULL → LEFT
* T5 中部(非热区)下滑 (240,100)->(240,220):ady=120 但原点 y=100≥热区 → SWIPE DOWN(内容滚动)
* T6 左缘中部 右滑返回 (5,300)->(110,300):非热区, 水平占优 → SWIPE LEFT(返回)
* T7 顶部中央 下滑后回弹 (240,5)->(240,-... 不适用;改用 (240,5)->(240,90) 大 ady) → NOTIF_PULL
*
* 编译(宿主 gcc,链真实 gfx/sys/theme/vol/log/widget/input/ime/media/notify_ipc + 打桩 font/global):
* gcc -Wall -Wextra -o test_notif_gesture test_notif_gesture.c test_host_stub.c \
* meow_ui_gfx.c meow_ui_time.c meow_ui_sys.c meow_ui_theme.c meow_ui_vol.c meow_ui_log.c \
* meow_ui_widget.c meow_ui_input.c meow_ui_ime.c meow_ui_str.c meow_ui_activity.c meow_ui_media.c \
* meow_pinyin.c meow_ui_draw.c meow_ui_view.c meow_ui_box.c meow_ui_anim.c meow_notify_ipc.c meow_ui_nav.c \
* -I. -Iinclude -DMEOW_UI_HOST_TEST -pthread -lm
* 运行:./test_notif_gesture
*/
#include "meow_ui.h"
#include "meow_ui_internal.h"
#include "meow_ui_sys.h"
#include <stdio.h>
#include <assert.h>
#include <signal.h>
/* MEOW_EV_NOTIF_PULL 是 meow_ui_input.c 内部常量(未入公共头),宿主测试按同值声明。 */
#ifndef MEOW_EV_NOTIF_PULL
#define MEOW_EV_NOTIF_PULL 5
#endif
/* 与 meow_ui_input.c 同阈值(防漂移:直接引用会打破封装,这里显式对齐注释值)。 */
#define SWIPE_THRESH 65
#define EDGE_W 24
#define HOTZONE 28 /* meow_ui_statusbar_hotzone():非全屏=状态栏高 MUI_SBAR_H */
static int g_fail = 0;
/* 驱动一次手势并返回队列中首个(应唯一)语义事件类型;无事件返回 -1。
* 顺序:drain → touch_set(按下) → touch_move(终点) → touch_release(抬手) → pop。 */
static int gesture_ev(int x0, int y0, int x1, int y1, int *a, int *b)
{
meow_input_drain();
meow_input_touch_set(1, x0, y0, 0); /* 按下锁定原点 (x0,y0) */
meow_input_touch_move(x1, y1); /* 移动到终点 */
meow_input_touch_release(); /* 抬手:touch_release 做手势分类 */
meow_input_touch_set(0, 0, 0, 0); /* 复位触摸状态机 */
meow_input_ev e;
if (!meow_input_pop(&e)) { *a = *b = -1; return -1; }
*a = e.a; *b = e.b;
return e.type;
}
static void expect(const char *name, int got, int want, int a, int b)
{
if (got == want) {
printf("PASS %s: type=%d (a=%d b=%d)\n", name, got, a, b);
} else {
printf("FAIL %s: got type=%d want=%d (a=%d b=%d)\n", name, got, want, a, b);
g_fail = 1;
}
}
int main(void)
{
meow_ui_opts o = { 480, 720 };
assert(meow_ui_init(&o) == 0);
/* 默认非全屏 / 状态栏激活 → 热区 28 */
assert(meow_ui_statusbar_hotzone() == HOTZONE);
int a = 0, b = 0, t = 0;
/* T1 顶部+左缘 向下右侧滑:旧代码 → SWIPE_LEFT;修复后 → NOTIF_PULL(顶部优先)。
* adx=100 ≥ ady=70,且 t_dx=10<EDGE_W、右移≥65——正是真机「状态栏下拉被当左缘返回」场景。 */
t = gesture_ev(10, 5, 110, 75, &a, &b);
expect("T1 top-left down-right -> NOTIF_PULL", t, MEOW_EV_NOTIF_PULL, a, b);
assert(a == 5); /* e.a = 按下原点 Y(热区判定复核用) */
/* T2 顶部中央 竖直下滑(纯纵向):NOTIF_PULL */
t = gesture_ev(240, 5, 240, 120, &a, &b);
expect("T2 top-center vertical down -> NOTIF_PULL", t, MEOW_EV_NOTIF_PULL, a, b);
/* T3 顶部+左缘 下移 <SWIPE_THRESH(40px):非真实下拉 → 仍走水平占优 → LEFT(不误判 DOWN) */
t = gesture_ev(10, 5, 100, 40, &a, &b);
expect("T3 top-left small-down -> LEFT", t, MEOW_EV_SWIPE, a, b);
assert(a == MEOW_SWIPE_LEFT);
/* T4 顶部+左缘 纯水平右滑:ady=0 → 非下拉 → LEFT */
t = gesture_ev(5, 5, 110, 5, &a, &b);
expect("T4 top-left pure right -> LEFT", t, MEOW_EV_SWIPE, a, b);
assert(a == MEOW_SWIPE_LEFT);
/* T5 中部(原点 y=100 ≥ 热区 28)大下滑:非 NOTIF_PULL → SWIPE DOWN(内容滚动不误判) */
t = gesture_ev(240, 100, 240, 220, &a, &b);
expect("T5 mid down (origin below hotzone) -> SWIPE DOWN", t, MEOW_EV_SWIPE, a, b);
assert(a == MEOW_SWIPE_DOWN);
/* T6 左缘中部 右滑返回(非热区):SWIPE LEFT */
t = gesture_ev(5, 300, 110, 300, &a, &b);
expect("T6 left-edge mid right -> SWIPE LEFT", t, MEOW_EV_SWIPE, a, b);
assert(a == MEOW_SWIPE_LEFT);
/* T7 顶部中央 大幅竖直下滑:NOTIF_PULL */
t = gesture_ev(240, 5, 240, 90, &a, &b);
expect("T7 top-center vertical down (large) -> NOTIF_PULL", t, MEOW_EV_NOTIF_PULL, a, b);
/* T8 SIGUSR1 护栏:meow_ui_init 已装无害处理器。raise(SIGUSR1)(等价 watchdog/测试路径
* 泄漏进来)——若无护栏,默认动作会终止本进程(return 走不到下一行);护栏记日志+忽略 → 存活。 */
raise(SIGUSR1);
printf("PASS T8 sigusr1-guard: survived raise(SIGUSR1)\n");
meow_ui_shutdown();
if (g_fail) { printf("RESULT: FAIL\n"); return 1; }
printf("RESULT: ALL PASS\n");
return 0;
}