Files
MeowOS-SDK/sdk/test_meow_ui_scroll.c
T
AskaEth 432875d4e6 sdk: 宿主测试头注释按实测修订 + select T1 探针修正
- test_meow_ui_select: T1 选中高亮探针移到容器卡内(x=12),
  适配 M6.37 起的 listview 默认容器模式;6/6 PASS
- 各 test_*.c 头注释补 -Iinclude、meow_ui_nav.c 及精简源列表最小补集
  (theme/widgets/notif_gesture/overlay/suppress/sdk_fixes/pinyin/ime_fix)
- test_sb_statusbar 头注释给出可链接命令(--allow-multiple-definition)
- notify_post/ui_audio_host/p1p2p3 标注需主仓组件,公开仓跳过
- docs/APP_DEV_GUIDE.md: 去掉叠字与过强表述,改为 34/38 实测口径
2026-11-04 20:26:35 +08:00

185 lines
6.6 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_meow_ui_scroll.c — §12.3 meow_scroll 滚动物理宿主验证:
* 跟手拖动(track 跟随与 clamp)、速度跟踪→松手 fling(位移序列/停止位置/单调/不越界)、
* 边界过冲 clamp + 简单回弹、snap。时间推进用真实 usleep(meow_anim_tick 驱动 fling)。
*
* 编译(宿主 gcc,链真实 gfx/sys/theme/vol/log/widget/draw/activity/ime + 打桩 font/global):
* gcc -o test_meow_ui_scroll test_meow_ui_scroll.c test_host_stub.c \
* meow_ui_gfx.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_activity.c meow_ui_dialog.c meow_ui_ime.c meow_ui_str.c \
* meow_pinyin.c meow_ui_draw.c meow_ui_view.c meow_ui_box.c meow_ui_anim.c meow_ui_scroll.c \
* meow_ui_img.c meow_ui_media.c meow_notify_ipc.c stb_image.c meow_ui_nav.c \
* -I. -Iinclude -DMEOW_UI_HOST_TEST -pthread -lm
* 运行:./test_meow_ui_scroll
*/
#include "meow_ui.h"
#include "meow_ui_internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int g_pass = 0, g_fail = 0;
#define CHECK(cond, ...) do { \
if (cond) { g_pass++; } \
else { g_fail++; printf("FAIL %s:%d ", __FILE__, __LINE__); printf(__VA_ARGS__); printf("\n"); } \
} while (0)
#define LIST_H 400
#define ITEM_H 44
#define COUNT 50
/* max_scroll = COUNT*ITEM_H - LIST_H = 2200 - 400 = 1800 */
#define MAXS (COUNT * ITEM_H - LIST_H)
static int src(int idx, char *label, int len, void *ctx)
{
(void)ctx;
if (idx < 0 || idx >= COUNT) return 0;
snprintf(label, (size_t)len, "row %d", idx);
return 1;
}
static meow_widget *make_list(void)
{
meow_widget *lv = meow_list_create(0, 0, 480, LIST_H, COUNT, src, NULL);
meow_list_set_item_h(lv, ITEM_H);
return lv;
}
/* 喂一串向下(正)速度采样,模拟快速下划 */
static void feed_drag(meow_scroll *s, int step, int n)
{
uint64_t now = meow_ui_time_ms();
for (int i = 0; i < n; i++) {
meow_scroll_track(s, step, now + (uint64_t)i * 16);
}
/* 最后用一个真实稍晚时刻的 track 让采样时间戳真实(保持一致钟) */
meow_scroll_track(s, 0, meow_ui_time_ms());
}
static void pump_until_idle(meow_scroll *s, int *max_off, int *mono_ok)
{
int prev = meow_scroll_offset(s);
int guard = 0;
while (meow_scroll_active(s) && guard++ < 300) {
meow_anim_tick();
int cur = meow_scroll_offset(s);
if (*max_off < cur) *max_off = cur;
if (cur < prev) *mono_ok = 0; /* 下划 fling 应单调不减(回弹段除外:此处只测无回弹) */
prev = cur;
usleep(10000);
}
meow_anim_tick();
}
static void test_track_follow(void)
{
meow_widget *lv = make_list();
meow_scroll *s = meow_scroll_wrap(lv, 0);
CHECK(s != NULL, "wrap");
CHECK(meow_scroll_offset(s) == 0, "init offset 0");
meow_scroll_track(s, 10, meow_ui_time_ms());
CHECK(meow_scroll_offset(s) == 10, "follow +10 got %d", meow_scroll_offset(s));
/* 超量拖到底:clamp 到 max */
meow_scroll_track(s, 100000, meow_ui_time_ms());
CHECK(meow_scroll_offset(s) == MAXS, "clamp to max got %d", meow_scroll_offset(s));
meow_scroll_free(s);
meow_widget_free(lv);
}
static void test_fling_no_boundary(void)
{
meow_widget *lv = make_list();
meow_scroll *s = meow_scroll_wrap(lv, 0);
/* 从 0 起拖 ~300px,建正初速 */
uint64_t t = meow_ui_time_ms();
for (int i = 0; i < 12; i++) meow_scroll_track(s, 25, t + (uint64_t)i * 16);
int start = meow_scroll_offset(s);
CHECK(start > 0, "dragged start>0 got %d", start);
meow_scroll_fling(s);
CHECK(meow_scroll_active(s) == 1, "fling active");
int max_off = start, mono = 1, prev = start;
int guard = 0;
while (meow_scroll_active(s) && guard++ < 300) {
meow_anim_tick();
int cur = meow_scroll_offset(s);
if (max_off < cur) max_off = cur;
if (cur < prev) mono = 0;
prev = cur;
usleep(10000);
}
meow_anim_tick();
int end = meow_scroll_offset(s);
CHECK(mono == 1, "monotonic non-decreasing during fling");
CHECK(end >= start, "fling advances end=%d start=%d", end, start);
CHECK(end <= MAXS, "no overflow end=%d max=%d", end, MAXS);
CHECK(meow_scroll_active(s) == 0, "settles idle");
meow_scroll_free(s);
meow_widget_free(lv);
}
static void test_fling_boundary_bounce(void)
{
meow_widget *lv = make_list();
meow_scroll *s = meow_scroll_wrap(lv, 0);
/* 先拖到近底(~1700) */
meow_list_set_scroll(lv, 1700);
/* 快速下划,冲过底界 */
uint64_t t = meow_ui_time_ms();
for (int i = 0; i < 8; i++) meow_scroll_track(s, 40, t + (uint64_t)i * 16);
meow_scroll_fling(s);
int max_off = 0, mono = 1;
pump_until_idle(s, &max_off, &mono);
int end = meow_scroll_offset(s);
CHECK(max_off <= MAXS, "never exceed max, max_off=%d max=%d", max_off, MAXS);
CHECK(end == MAXS, "bounce settles at bottom end=%d", end); /* 回弹后回到底 */
CHECK(meow_scroll_active(s) == 0, "idle after bounce");
meow_scroll_free(s);
meow_widget_free(lv);
}
static void test_snap(void)
{
meow_widget *lv = make_list();
meow_scroll *s = meow_scroll_wrap(lv, 0);
meow_scroll_set_snap(s, ITEM_H); /* 吸附到行边界 */
/* 慢拖到某非边界位置并给 small velocity → fling 结束 snap 到行倍数 */
uint64_t t = meow_ui_time_ms();
for (int i = 0; i < 6; i++) meow_scroll_track(s, 20, t + (uint64_t)i * 16);
meow_scroll_fling(s);
int max_off = 0, mono = 1;
pump_until_idle(s, &max_off, &mono);
int end = meow_scroll_offset(s);
CHECK((end % ITEM_H) == 0, "snap to item multiple got %d", end);
CHECK(end <= MAXS, "snap in range %d", end);
meow_scroll_free(s);
meow_widget_free(lv);
}
static void test_stop(void)
{
meow_widget *lv = make_list();
meow_scroll *s = meow_scroll_wrap(lv, 0);
uint64_t t = meow_ui_time_ms();
for (int i = 0; i < 6; i++) meow_scroll_track(s, 20, t + (uint64_t)i * 16);
meow_scroll_fling(s);
CHECK(meow_scroll_active(s) == 1, "fling active (stop test)");
meow_scroll_stop(s);
CHECK(meow_scroll_active(s) == 0, "stopped immediately");
meow_scroll_free(s);
meow_widget_free(lv);
}
int main(void)
{
meow_ui_opts o = { 480, 720 };
if (meow_ui_init(&o) != 0) { printf("init failed\n"); return 1; }
test_track_follow();
test_fling_no_boundary();
test_fling_boundary_bounce();
test_snap();
test_stop();
meow_ui_shutdown();
printf("scroll: %d pass / %d fail\n", g_pass, g_fail);
return g_fail ? 1 : 0;
}