Files
AskaEth 54857bc0fd sdk(ui): 字符串资源外置(i18n 雏形 §13)—— meow_str_* + 内嵌双语表 + TF 覆盖表 + 控件接入
公开 SDK 前把 SDK/App 硬编码文案外置:新增 meow_str/meow_strf/meow_str_set_locale/
meow_str_locale,按当前 locale 取串(永不 NULL),第三方开发者可做多语言。

- 新增 include/meow_ui_str.h + meow_ui_str.c:取串优先级 = TF 覆盖表 > 内嵌当前语言
  (en_us→en 其余→zh) > 内嵌内置默认(zh_cn) > 原样返回 id。内嵌双语表(common.* 21 条 +
  ime.* 9 条);热路径零 malloc(编译期静态表 + ≤256 静态覆盖数组);纯 libc 宿主可单测。
- locale 存系统设置 settings.conf 的 ui.locale(默认 zh_cn,首次调用惰性读取);
  meow_str_set_locale 即时切换 + 重载覆盖表 + best-effort 持久化(流式改写保留其它行)。
- TF 覆盖表 MeowData/<pkg>/strings/<locale>.txt(id=text 行,UTF-8,'=' 两侧去空白);
  无卡/无文件/无该 id → 回落内嵌。meow_strf 用调用方缓冲(snprintf 语义,重入安全)。
- SDK 控件接入:dialog 默认按钮 OK/CANCEL + INPUT 占位、IME 键面/徽标(空格/确定/拼英/
  ?123/清/拼音/(无候选)/中)改走 meow_str;空态/加载态给 App 提供 common.no_data/loading。
- 测试:新增 test_meow_ui_str.c(内嵌回退/TF 覆盖优先级/未知 id 回退/切 locale 即时生效/
  查找正确性/meow_strf,tmp+env 两模式);全量宿主回归(widgets/dispatch/box/anim/scroll/
  listvirt/theme/ime_fix/pinyin/overlay/notif/sdk_input_keys/p1p2p3/config/vol/sb_collapse/
  notify_*) 0 回归;交叉 zig-mipsel -Wall -Wextra 0 warning。
- 文档:MEOW_APP_SDK.md 新增 §13(字符串资源/i18n,遗留顺延为 §14);docs/APP_DEV_GUIDE.md
  新增 §7.11。各宿主 test_*.c 头注释补 meow_ui_str.c 编译依赖。

边界(§13.7):仅 zh_cn/en_us 整串取用;不做复数规则 / BiDi / RTL / 动态字体回退(雏形)。
2026-09-02 02:37:38 +08:00

121 lines
6.0 KiB
C
Raw Permalink 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_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_media.c meow_notify_ipc.c \
* -I. -I../meow_launcherd -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;
}