Files
MeowOS-For-R3P2/patch_v2/meow_launcherd/test_lock_widgets.c
T
AskaEth 3d70a3dd2c feat: M6.10–M6.19 批量收编 + M6.19 推卡验收
- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘)
- OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复
- ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640
- 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫)
- 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
2026-09-03 12:16:01 +08:00

224 lines
9.5 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_lock_widgets.c — M7.1b 锁屏 UI 控件化宿主验证。
*
* 复现 lock_screen_ui.c 所建锁屏键盘控件集(12 键 meow_widget_custom + meow_widget 命中 +
* 按压态 MEOW_WS_PRESSED→primary 26% α),验证:
* P1 键盘渲染:12 键各画成 surfaceContainer 圆角钮(非背景像素);
* P2 键盘命中:meow_widget_hit 在每键中心命中;键值映射(digit/清空/退格)正确;间隙不命中;
* P3 主题四态(MD3/MIUIx × 明暗)键盘渲染非背景;
* P4 按压态:meow_widget_set_state(MEOW_WS_PRESSED) → 该键像素变化(primary 26% α 叠加);
* P5 键值 round-trip:lk_key_value_at 在键中心/间隙分别返回正确键值与 LK_DOWN_NONE。
*
* 布局几何/键序与 lock_screen_ui.c 镜像(LK_X0..LK_COLS/LK_ROWS/lk_keys),控件创建方式与
* lk_widgets_build 同(owner=哨兵 0x51,meow_widget_custom_create,render 读 meow_widget_rect 几何)。
*
* 编译(在 patch_v2/meow_launcherd 下):
* gcc -Wall -Wextra -o test_lock_widgets test_lock_widgets.c \
* ../sdk/test_host_stub.c ../sdk/meow_ui_gfx.c ../sdk/meow_ui_sys.c \
* ../sdk/meow_ui_theme.c ../sdk/meow_ui_vol.c ../sdk/meow_ui_log.c \
* ../sdk/meow_ui_widget.c ../sdk/meow_ui_input.c ../sdk/meow_ui_activity.c \
* ../sdk/meow_ui_dialog.c ../sdk/meow_ui_ime.c ../sdk/meow_ui_str.c ../sdk/meow_pinyin.c \
* ../sdk/meow_ui_draw.c ../sdk/meow_ui_view.c ../sdk/meow_ui_box.c ../sdk/meow_ui_anim.c \
* ../sdk/meow_ui_scroll.c ../sdk/meow_ui_img.c ../sdk/meow_ui_media.c \
* ../sdk/meow_notify_ipc.c ../sdk/stb_image.c -I../sdk -I. -DMEOW_UI_HOST_TEST -pthread -lm
* 运行:./test_lock_widgets
*/
#include "meow_ui.h"
#include "meow_ui_internal.h" /* meow_ui_back_buf / meow_widget_rect / meow_gfx_fill_round[_alpha] */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int g_fail = 0;
#define CHECK(cond, ...) do { \
if (cond) { printf(" PASS: " __VA_ARGS__); printf("\n"); } \
else { printf(" FAIL: " __VA_ARGS__); printf("\n"); g_fail++; } } while (0)
/* ---- 与 lock_screen_ui.c 同源几何(镜像) ---- */
#define LK_X0 32
#define LK_COLW 130
#define LK_COLG 8
#define LK_Y0 320
#define LK_ROW_H 82
#define LK_ROWG 10
#define LK_ROWS 4
#define LK_COLS 3
#define LK_ACT_CLR (-2)
#define LK_ACT_BS (-1)
#define LK_SENTINEL 0x51 /* 锁屏控件 owner 哨兵(镜像 lock_screen_ui.c) */
#define LK_DOWN_NONE (-10)
static const int lk_keys[LK_ROWS][LK_COLS] = {
{ 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { LK_ACT_CLR, 0, LK_ACT_BS },
};
#define XRES 480
#define YRES 720
static meow_widget *lk_w[LK_ROWS][LK_COLS];
static void lk_rect(int row, int col, int rc[4])
{
rc[0] = LK_X0 + col * (LK_COLW + LK_COLG);
rc[1] = LK_Y0 + row * (LK_ROW_H + LK_ROWG);
rc[2] = LK_COLW;
rc[3] = LK_ROW_H;
}
static void lk_center(int row, int col, int *cx, int *cy)
{
int rc[4]; lk_rect(row, col, rc);
*cx = rc[0] + rc[2] / 2;
*cy = rc[1] + rc[3] / 2;
}
/* ---- 键渲染(镜像 lock_screen_ui.c lk_key_render 的视觉语义)---- */
static void key_render(meow_widget *w, const meow_theme *th, void *ctx)
{
(void)ctx;
int rc[4]; meow_widget_rect(w, rc);
int rad = (th->radius > 0) ? th->radius : 10;
meow_gfx_fill_round(rc[0], rc[1], rc[2], rc[3], rad, th->surfaceContainer);
if (meow_widget_state(w) & MEOW_WS_PRESSED)
meow_gfx_fill_round_alpha(rc[0], rc[1], rc[2], rc[3], rad, th->primary, 66);
meow_ui_text_center(rc[0] + rc[2] / 2,
rc[1] + rc[3] / 2 - meow_ui_text_height(22) / 2,
"1", 22, th->onSurface);
}
static void mk_widgets(void)
{
meow_ui_activity_push(LK_SENTINEL);
for (int r = 0; r < LK_ROWS; r++)
for (int c = 0; c < LK_COLS; c++) {
int rc[4]; lk_rect(r, c, rc);
lk_w[r][c] = meow_widget_custom_create(rc[0], rc[1], rc[2], rc[3],
key_render, NULL,
(void *)(intptr_t)lk_keys[r][c]);
}
meow_ui_activity_pop();
}
/* 坐标 -> 键值(镜像 lock_screen_ui.c lk_key_value_at)。 */
static int key_value_at(int x, int y)
{
for (int r = 0; r < LK_ROWS; r++)
for (int c = 0; c < LK_COLS; c++)
if (lk_w[r][c] && meow_widget_hit(lk_w[r][c], x, y))
return lk_keys[r][c];
return LK_DOWN_NONE;
}
static void draw_all(void)
{
const meow_theme *th = meow_theme_get();
meow_ui_fill_rect(0, 0, XRES, YRES, th->surface);
for (int r = 0; r < LK_ROWS; r++)
for (int c = 0; c < LK_COLS; c++)
if (lk_w[r][c]) meow_widget_draw(lk_w[r][c]);
}
static unsigned short px565(int x, int y)
{
unsigned char *bb = meow_ui_back_buf();
int pitch = meow_ui_back_buf_pitch(), bpp = meow_ui_back_buf_bpp();
if (!bb || x < 0 || y < 0 || x >= XRES || y >= YRES) return 0;
if (bpp == 16) return *(unsigned short *)(bb + (size_t)y * pitch + (size_t)x * 2);
return (unsigned short)(*(unsigned int *)(bb + (size_t)y * pitch + (size_t)x * 4) >> 16);
}
static unsigned short bg565(uint32_t bg)
{
return (unsigned short)(((bg >> 8) & 0xF800) | ((bg >> 5) & 0x07E0) | ((bg >> 3) & 0x001F));
}
int main(void)
{
setbuf(stdout, NULL);
setenv("MEOW_UI_DUMP", "/tmp/lock_widgets.ppm", 1);
meow_ui_opts o = { XRES, YRES };
if (meow_ui_init(&o) != 0) { printf("init failed\n"); return 1; }
mk_widgets();
meow_ui_activity_push(LK_SENTINEL); /* 命中闸门打开(owner==active) */
/* ============ P1 键盘渲染(12 键各画成非背景钮) ============ */
printf("P1 keypad render (12 keys non-bg)\n");
const meow_theme *th = meow_theme_get();
draw_all();
int all_nonbg = 1;
for (int r = 0; r < LK_ROWS && all_nonbg; r++)
for (int c = 0; c < LK_COLS && all_nonbg; c++) {
int cx, cy; lk_center(r, c, &cx, &cy);
if (px565(cx, cy) == bg565(th->surface)) all_nonbg = 0;
}
CHECK(all_nonbg, "each of 12 keys draws non-surface at center");
/* ============ P2 命中(meow_widget_hit + 键值映射) ============ */
printf("P2 keypad hit via meow_widget_hit\n");
int hit_ok = 1, val_ok = 1;
for (int r = 0; r < LK_ROWS; r++)
for (int c = 0; c < LK_COLS; c++) {
int cx, cy; lk_center(r, c, &cx, &cy);
if (!meow_widget_hit(lk_w[r][c], cx, cy)) hit_ok = 0;
if (key_value_at(cx, cy) != lk_keys[r][c]) val_ok = 0;
}
CHECK(hit_ok, "meow_widget_hit hits every key center");
CHECK(val_ok, "key_value_at maps every key center to its digit/clear/backspace value");
/* 间隙(两列之间)不命中 */
int gap_x = LK_X0 + LK_COLW + LK_COLG / 2; /* 列0 与列1 之间的间隙中心 */
int gap_y = LK_Y0 + LK_ROW_H / 2;
CHECK(meow_widget_hit(lk_w[0][0], gap_x, gap_y) == 0, "gap between columns not hit");
CHECK(key_value_at(gap_x, gap_y) == LK_DOWN_NONE, "gap not mapped to any key");
/* ============ P3 主题四态(MD3/MIUIx × 明暗)键盘渲染非背景 ============ */
printf("P3 theme 4-state keypad render\n");
const int styles[2] = { MEOW_STYLE_MD3, MEOW_STYLE_MIUIX };
const int modes[2] = { MEOW_THEME_LIGHT, MEOW_THEME_DARK };
char nm[96];
for (int si = 0; si < 2; si++) {
for (int mi = 0; mi < 2; mi++) {
meow_ui_set_style(styles[si]);
meow_theme_set_mode((meow_theme_mode)modes[mi]);
th = meow_theme_get();
draw_all();
/* 用一个键区的多像素带判定非背景(文字+底) */
int rc[4]; lk_rect(1, 0, rc);
int nonbg = 0;
for (int dy = 0; dy < rc[3] && !nonbg; dy++)
for (int dx = 0; dx < rc[2] && !nonbg; dx++)
if (px565(rc[0] + dx, rc[1] + dy) != bg565(th->surface)) nonbg = 1;
snprintf(nm, sizeof nm, "style=%s mode=%s keypad renders non-surface",
styles[si] ? "MIUIx" : "MD3", modes[mi] ? "dark" : "light");
CHECK(nonbg, "%s", nm);
}
}
meow_ui_set_style(MEOW_STYLE_MD3);
meow_theme_set_mode(MEOW_THEME_DARK);
/* ============ P4 按压态(MEOW_WS_PRESSED → primary 26% α 像素变化) ============ */
printf("P4 pressed state -> primary 26%% alpha overlay\n");
th = meow_theme_get();
draw_all();
int cx, cy; lk_center(2, 1, &cx, &cy); /* 键 (2,1) = 数字 8 */
unsigned short p0 = px565(cx, cy);
meow_widget_set_state(lk_w[2][1], MEOW_WS_PRESSED, 1);
draw_all();
unsigned short p1 = px565(cx, cy);
meow_widget_set_state(lk_w[2][1], MEOW_WS_PRESSED, 0);
CHECK(p1 != p0, "pressed key center pixel changes (primary 26%% overlay)");
draw_all();
unsigned short p2 = px565(cx, cy);
CHECK(p2 == p0, "release restores original pixel");
/* ============ P5 键值 round-trip(清空/退格/间隙) ============ */
printf("P5 key-value round-trip (clear/backspace/gap)\n");
int ccx, ccy, bcx, bcy, zcx, zcy;
lk_center(3, 0, &ccx, &ccy); /* 清空 */
lk_center(3, 1, &zcx, &zcy); /* 0 */
lk_center(3, 2, &bcx, &bcy); /* 退格 */
CHECK(key_value_at(ccx, ccy) == LK_ACT_CLR, "bottom-left center == CLEAR (-2)");
CHECK(key_value_at(zcx, zcy) == 0, "bottom-mid center == 0");
CHECK(key_value_at(bcx, bcy) == LK_ACT_BS, "bottom-right center == BACKSPACE (-1)");
meow_ui_activity_pop();
meow_ui_shutdown();
printf(g_fail ? "\nRESULT: %d FAIL(S)\n" : "\nRESULT: ALL PASS\n", g_fail);
return g_fail;
}