- 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 推卡自刷验收全绿
224 lines
9.5 KiB
C
224 lines
9.5 KiB
C
/* 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;
|
||
}
|