- 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 推卡自刷验收全绿
401 lines
19 KiB
C
401 lines
19 KiB
C
/* test_settings_widgets.c — M7.2 设置页主列表迁 SDK 控件(宿主验证)。
|
||
*
|
||
* 复现 settings_page.c M7.2 SDK 路径所建控件集(meow_listview 虚拟化 vsource + section 段头 +
|
||
* set_item_draw 自绘 + 行内真 meow_switch + 拖拽同布局 meow_slider),验证:
|
||
* P1 listview 虚拟化渲染:section 段头 + 开关/枚举/滑条/幂等行非背景像素;
|
||
* P2 meow_listview 命中:行号(含滚动换算 + 段头行 enabled=1 可命中);
|
||
* P3 开关写回:行 tap → meow_settings_set_switch(key,!on) → settings.conf 键正确(读改写单键);
|
||
* P4 滑条写回:track 映射 x→值 → meow_settings_set_int(key,v)(含息屏时间档位索引→秒)→ 键正确;
|
||
* P5 枚举写回:enum 选项 → meow_settings_set_enum(key,idx) → settings.conf 键值正确。
|
||
* 写回全部走 meow_settings_set_*(单键读改写,勿整文件覆盖——音量存盘教训)+ meow_settings_save。
|
||
*
|
||
* 几何/控件创建与 settings_page.c「M7.2 SDK 路径」镜像(owner=哨兵 0x53,listview 用 set_vsource
|
||
* + set_item_draw + set_item_h 68)。SMENU 行表取代表性子集(键/类型/min/max 与真表一致)。
|
||
*
|
||
* 编译(在 patch_v2/meow_launcherd 下):
|
||
* gcc -Wall -Wextra -o test_settings_widgets test_settings_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 \
|
||
* -DMEOW_SETTINGS_FILE='"/tmp/meow_set_test/settings.conf"' -pthread -lm
|
||
* 运行:./test_settings_widgets
|
||
*/
|
||
#include "meow_ui.h"
|
||
#include "meow_ui_internal.h" /* meow_ui_back_buf / meow_gfx_mark_dirty / meow_input_touch_set */
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <sys/stat.h>
|
||
#include <sys/types.h>
|
||
|
||
/* 覆盖存储路径到临时目录(需父目录存在;test 内初始化时 mkdir)。
|
||
* 注意:须在 include "meow_settings.c" 前定义(SDK meow_ui_sys/theme 自带默认,勿用 -D 以免重定义)。 */
|
||
#define MEOW_SETTINGS_FILE "/tmp/meow_set_test/settings.conf"
|
||
#include "meow_settings.c"
|
||
|
||
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)
|
||
|
||
/* ---- 与 settings_page.c / meow_launcher_internal.h 同源几何(镜像) ---- */
|
||
#define XRES 480
|
||
#define YRES 720
|
||
#define SET_CARD_X 8
|
||
#define SET_CARD_W (XRES - 16)
|
||
#define SET_CONTENT_W (SET_CARD_W - 24)
|
||
#define S_SLIDER_X (SET_CARD_X + 16) /* 24 */
|
||
#define S_SLIDER_W SET_CONTENT_W /* 440 */
|
||
#define SET_LIST_Y 100
|
||
#define SET_FOOT_H 40
|
||
#define SET_ITEM_H 68
|
||
#define SET_SLIDER_YOFF 32
|
||
#define SET_TRACK_CY 52
|
||
#define SET_SENTINEL 0x53
|
||
#define LV_H (YRES - SET_LIST_Y - SET_FOOT_H) /* 580 */
|
||
|
||
/* 息屏时间档位(镜像 settings_page.c s_time_tiers) */
|
||
static const int s_time_tiers[] = { 0, 5, 10, 15, 20, 30, 45, 60, 90, 120, 180, 300, 600, 900, 1800, 3600, 7200 };
|
||
#define S_TIME_TIERS_N ((int)(sizeof s_time_tiers / sizeof s_time_tiers[0]))
|
||
|
||
/* ---- srow_t 行表镜像(键/类型/min/max 与 settings_page.c SMENU 代表行一致) ---- */
|
||
typedef enum { SC_HEADER, SC_SWITCH, SC_SLIDER, SC_ENUM, SC_PRESET, SC_INFO, SC_LIST } sctrl_t;
|
||
typedef struct { const char *label; const char *key; sctrl_t ctrl;
|
||
int min, max, step; } srow_t;
|
||
static const srow_t ROWS[] = {
|
||
{ "显示", NULL, SC_HEADER, 0, 0, 0 },
|
||
{ "亮度", "display.brightness", SC_SLIDER, 1, 100, 1 },
|
||
{ "最高刷新率", "display.refresh_always_max", SC_SWITCH, 0, 0, 0 },
|
||
{ "息屏模式", "display.screen_off_mode", SC_ENUM, 0, 0, 0 },
|
||
{ "息屏时间", "display.screen_off_timeout", SC_SLIDER, 0, S_TIME_TIERS_N - 1, 1 },
|
||
{ "UI风格", "ui.style", SC_ENUM, 0, 0, 0 },
|
||
{ "滑动方向", "input.swipe_invert", SC_SWITCH, 0, 0, 0 },
|
||
{ "网络", NULL, SC_HEADER, 0, 0, 0 },
|
||
{ "WiFi", NULL, SC_LIST, 0, 0, 0 },
|
||
};
|
||
#define NROWS ((int)(sizeof ROWS / sizeof ROWS[0]))
|
||
|
||
static meow_widget *lv = NULL;
|
||
|
||
/* ---- 值格式化/映射(镜像 settings_page.c s_fmt_value/s_time_tier_idx/s_time_tier_val) ---- */
|
||
static int s_time_tier_idx(int sec)
|
||
{
|
||
if (sec <= s_time_tiers[0]) return 0;
|
||
for (int i = 1; i < S_TIME_TIERS_N; i++) {
|
||
if (sec == s_time_tiers[i]) return i;
|
||
if (sec < s_time_tiers[i]) {
|
||
int lo = s_time_tiers[i-1], hi = s_time_tiers[i];
|
||
return (sec - lo < hi - sec) ? i - 1 : i;
|
||
}
|
||
}
|
||
return S_TIME_TIERS_N - 1;
|
||
}
|
||
static int s_time_tier_val(int idx)
|
||
{
|
||
if (idx < 0) idx = 0;
|
||
if (idx >= S_TIME_TIERS_N) idx = S_TIME_TIERS_N - 1;
|
||
return s_time_tiers[idx];
|
||
}
|
||
static void s_fmt_time(int sec, char *buf, int len)
|
||
{
|
||
if (sec <= 0) { snprintf(buf, len, "常亮"); return; }
|
||
if (sec < 60) { snprintf(buf, len, "%d 秒", sec); return; }
|
||
if (sec < 3600) { snprintf(buf, len, "%d 分", sec / 60); return; }
|
||
snprintf(buf, len, "%d 时", sec / 3600);
|
||
}
|
||
static void s_fmt_value(const srow_t *r, char *buf, int len)
|
||
{
|
||
int v = 0;
|
||
if (meow_settings_get_int(r->key, &v) != 0) { snprintf(buf, len, "-"); return; }
|
||
if (!strcmp(r->key, "display.screen_off_timeout")) { s_fmt_time(v, buf, len); return; }
|
||
snprintf(buf, len, "%d", v);
|
||
}
|
||
static void s_display_value(const srow_t *r, char *buf, int len)
|
||
{
|
||
int idx = 0; meow_settings_get_enum(r->key, &idx);
|
||
if (meow_settings_enum_label(r->key, idx, buf, len) != 0) snprintf(buf, len, "-");
|
||
}
|
||
static int s_slider_val_from_x(const srow_t *r, int px)
|
||
{
|
||
int range = r->max - r->min;
|
||
int v = r->min + (range ? (px - S_SLIDER_X) * range / S_SLIDER_W : 0);
|
||
if (v < r->min) v = r->min;
|
||
if (v > r->max) v = r->max;
|
||
return v;
|
||
}
|
||
/* 滑条落值(含息屏时间 挡位→秒 换算;镜像 s_slider_set_from_track) */
|
||
static void s_slider_set(const srow_t *r, int sl_v, int save)
|
||
{
|
||
(void)save;
|
||
if (!strcmp(r->key, "display.screen_off_timeout")) sl_v = s_time_tier_val(sl_v);
|
||
meow_settings_set_int(r->key, sl_v);
|
||
}
|
||
/* 开关 tap:读改写单键(镜像 run_settings_page SC_SWITCH 分支) */
|
||
static void s_switch_toggle(const srow_t *r)
|
||
{
|
||
int on = 0; meow_settings_get_switch(r->key, &on);
|
||
meow_settings_set_switch(r->key, !on);
|
||
}
|
||
|
||
/* ---- listview 虚拟化数据源(镜像 settings_page.c set_lv_bind) ---- */
|
||
static int lv_count(void *ctx) { (void)ctx; return NROWS; }
|
||
static void lv_bind(int idx, meow_lv_item *out, void *ctx)
|
||
{
|
||
(void)ctx;
|
||
memset(out, 0, sizeof *out);
|
||
out->icon_kind = MEOW_LIST_ICON_NONE;
|
||
out->enabled = 1;
|
||
if (idx < 0 || idx >= NROWS) { out->title = ""; return; }
|
||
const srow_t *r = &ROWS[idx];
|
||
out->title = r->label ? r->label : "";
|
||
out->section = (r->ctrl == SC_HEADER) ? 1 : 0;
|
||
if (r->ctrl == SC_SWITCH) {
|
||
int on = 0; meow_settings_get_switch(r->key, &on);
|
||
out->right = MEOW_LIST_RIGHT_SWITCH; out->on = on;
|
||
}
|
||
}
|
||
|
||
/* 行内开关池(镜像 settings_page.c g_set_sw pool) */
|
||
#define SET_SWITCH_POOL 12
|
||
static meow_widget *g_set_sw[SET_SWITCH_POOL];
|
||
static int g_set_sw_n = 0, g_set_sw_use = 0;
|
||
static meow_widget *set_sw_take(void)
|
||
{
|
||
if (g_set_sw_use < g_set_sw_n) return g_set_sw[g_set_sw_use++];
|
||
if (g_set_sw_n >= SET_SWITCH_POOL) return NULL;
|
||
meow_widget *w = meow_switch_create(0, 0, 0);
|
||
if (w) { g_set_sw[g_set_sw_n++] = w; return g_set_sw[g_set_sw_use++]; }
|
||
return NULL;
|
||
}
|
||
|
||
/* ---- 整行自绘(镜像 settings_page.c set_lv_draw) ---- */
|
||
static void lv_draw(int idx, int x, int y, int w, int h, int state, void *ctx)
|
||
{
|
||
(void)ctx; (void)h;
|
||
const meow_theme *mt = meow_theme_get();
|
||
if (idx < 0) return;
|
||
const srow_t *r = &ROWS[idx];
|
||
int sel = (state & MEOW_LISTVIEW_ST_SELECTED);
|
||
int press = (state & MEOW_LISTVIEW_ST_PRESSED);
|
||
int thh = meow_ui_text_height(mt->font_body);
|
||
uint32_t textcol = sel ? mt->onPrimaryContainer : mt->onSurface;
|
||
uint32_t subcol = sel ? mt->onPrimaryContainer : mt->onSurfaceVariant;
|
||
|
||
if (r->ctrl == SC_HEADER) {
|
||
meow_ui_fill_rect(x, y, w, SET_ITEM_H, mt->surfaceContainerHigh);
|
||
int ty = y + (SET_ITEM_H - thh) / 2;
|
||
if (ty >= 0) meow_ui_text(x + 16, ty, r->label, mt->font_body, mt->primary);
|
||
meow_ui_fill_rect(x, y + SET_ITEM_H - 1, w, 1, mt->outlineVariant);
|
||
return;
|
||
}
|
||
if (sel) meow_ui_fill_rect(x, y, w, SET_ITEM_H, mt->primaryContainer);
|
||
else if (press) meow_ui_fill_rect_alpha(x, y, w, SET_ITEM_H, mt->primary, 26);
|
||
int ly = y + (SET_ITEM_H - thh) / 2;
|
||
switch (r->ctrl) {
|
||
case SC_SWITCH: {
|
||
meow_ui_text(x + 16, ly, r->label, mt->font_body, textcol);
|
||
meow_widget *sw = set_sw_take();
|
||
if (sw) {
|
||
int on = 0; meow_settings_get_switch(r->key, &on);
|
||
meow_widget_set_rect(sw, x + w - 16 - 56, y + (SET_ITEM_H - 32) / 2, 56, 32);
|
||
meow_switch_set(sw, on);
|
||
meow_widget_draw(sw);
|
||
}
|
||
break;
|
||
}
|
||
case SC_SLIDER: {
|
||
/* 宿主测试不引入 launcher s_draw_slider/s_ui_theme:只验证行文字渲染 + 命中,track 视觉由
|
||
* 真机 s_draw_slider 呈现(settings_page.c set_lv_draw 已复用)。 */
|
||
meow_ui_text(x + 16, ly, r->label, mt->font_body, textcol);
|
||
char vb[32]; s_fmt_value(r, vb, sizeof vb);
|
||
meow_ui_text(x + w - 16 - meow_ui_text_width(vb, mt->font_body), ly, vb, mt->font_body, subcol);
|
||
break;
|
||
}
|
||
case SC_LIST: {
|
||
meow_ui_text(x + 16, ly, r->label, mt->font_body, textcol);
|
||
meow_ui_text(x + w - 16 - meow_ui_text_width("已连接", mt->font_body), ly, "已连接", mt->font_body, subcol);
|
||
break;
|
||
}
|
||
default: { /* SC_ENUM / SC_PRESET */
|
||
meow_ui_text(x + 16, ly, r->label, mt->font_body, textcol);
|
||
char vb[40]; s_display_value(r, vb, sizeof vb);
|
||
int vx = x + w - 16 - meow_ui_text_width(vb, mt->font_body);
|
||
meow_ui_text(vx, ly, vb, mt->font_body, subcol);
|
||
break;
|
||
}
|
||
}
|
||
meow_ui_fill_rect(x, y + SET_ITEM_H - 1, w, 1, mt->outlineVariant);
|
||
if (state & MEOW_LISTVIEW_ST_DISABLED) meow_ui_fill_rect_alpha(x, y, w, SET_ITEM_H, mt->onSurface, 90);
|
||
}
|
||
|
||
static void mk_widgets(void)
|
||
{
|
||
meow_ui_activity_push(SET_SENTINEL);
|
||
lv = meow_listview_create(0, SET_LIST_Y, XRES, LV_H, 0, NULL, NULL, MEOW_LIST_SEL_SINGLE);
|
||
meow_listview_set_vsource(lv, lv_count, lv_bind, NULL);
|
||
meow_listview_set_item_draw(lv, lv_draw, NULL);
|
||
meow_listview_set_item_h(lv, SET_ITEM_H);
|
||
meow_ui_activity_pop();
|
||
}
|
||
|
||
static void draw_all(void)
|
||
{
|
||
const meow_theme *th = meow_theme_get();
|
||
meow_ui_fill_rect(0, 0, XRES, YRES, th->surface);
|
||
meow_ui_fill_rect(0, SET_LIST_Y, XRES, LV_H, th->surfaceVariant);
|
||
if (lv) { g_set_sw_use = 0; meow_widget_draw(lv); }
|
||
}
|
||
|
||
/* ---- 像素探测 ---- */
|
||
static void rd_px(int x, int y, unsigned short *p)
|
||
{
|
||
unsigned char *bb = meow_ui_back_buf();
|
||
int line = meow_ui_back_buf_pitch(), bpp = meow_ui_back_buf_bpp();
|
||
if (!bb || x < 0 || y < 0) { *p = 0; return; }
|
||
if (bpp == 16) *p = *(unsigned short *)(bb + (size_t)y * line + (size_t)x * 2);
|
||
else *p = (unsigned short)(*(unsigned int *)(bb + (size_t)y * line + (size_t)x * 4) >> 16);
|
||
}
|
||
static unsigned short px565(int x, int y) { unsigned short p; rd_px(x, y, &p); return p; }
|
||
static int region_nonbg(int x, int y, int w, int h, uint32_t bg)
|
||
{
|
||
unsigned short bg565 = ((bg >> 8) & 0xF800) | ((bg >> 5) & 0x07E0) | ((bg >> 3) & 0x001F);
|
||
int cnt = 0;
|
||
for (int dy = 0; dy < h; dy++)
|
||
for (int dx = 0; dx < w; dx++)
|
||
if (px565(x + dx, y + dy) != bg565) cnt++;
|
||
return cnt;
|
||
}
|
||
|
||
/* ---- meow_settings 写回验证辅助:清盘后 save,再 grep conf(格式 `key = value`,去空格比较) ---- */
|
||
static int conf_has(const char *key, const char *val)
|
||
{
|
||
char line[256], expect[256];
|
||
FILE *f = fopen(MEOW_SETTINGS_FILE, "r");
|
||
if (!f) return 0;
|
||
snprintf(expect, sizeof expect, "%s=%s", key, val);
|
||
int found = 0;
|
||
while (fgets(line, sizeof line, f)) {
|
||
char stripped[256]; int k = 0;
|
||
for (int i = 0; line[i] && k < 255; i++)
|
||
if (line[i] != ' ' && line[i] != '\n' && line[i] != '\r') stripped[k++] = line[i];
|
||
stripped[k] = 0;
|
||
if (!strcmp(stripped, expect)) { found = 1; break; }
|
||
}
|
||
fclose(f);
|
||
return found;
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
setbuf(stdout, NULL);
|
||
mkdir("/tmp/meow_set_test", 0777);
|
||
setenv("MEOW_UI_DUMP", "/tmp/settings.ppm", 1);
|
||
if (meow_settings_init() != 0) printf("settings init (defaults; file may be absent)\n");
|
||
meow_ui_opts o = { XRES, YRES };
|
||
if (meow_ui_init(&o) != 0) { printf("init failed\n"); return 1; }
|
||
mk_widgets();
|
||
|
||
/* ============ P1 listview 虚拟化渲染(section 段头 + 各型行非背景) ============ */
|
||
printf("P1 listview virtualized render (settings rows)\n");
|
||
meow_ui_activity_push(SET_SENTINEL);
|
||
const meow_theme *th = meow_theme_get();
|
||
draw_all();
|
||
/* 段头行整体填 surfaceContainerHigh(覆盖列表底 surfaceVariant)→ 对列表底背景即非背景;
|
||
* 注意宿主无 mfont 时 CJK 标题回退点阵不显形,故以「段头底 vs 列表底」判渲染而非文字像素。 */
|
||
int hdrcnt = region_nonbg(2, SET_LIST_Y + 4, XRES - 4, SET_ITEM_H - 8, th->surfaceVariant);
|
||
int rowcnt = region_nonbg(2, SET_LIST_Y + SET_ITEM_H + 4, XRES - 4, SET_ITEM_H - 8, th->surfaceVariant);
|
||
CHECK(hdrcnt > 0, "section header band renders (hdr=%d)", hdrcnt);
|
||
CHECK(rowcnt > 40, "row band renders (title/value/switch) cnt=%d", rowcnt);
|
||
/* P1b:开关行(ROWS[2]=最高刷新率 right switch)中心右缘区非背景 */
|
||
{
|
||
int swy = SET_LIST_Y + 2 * SET_ITEM_H + SET_ITEM_H / 2;
|
||
int swc = region_nonbg(XRES - 16 - 56, swy - 4, 56, 8, th->surfaceVariant);
|
||
CHECK(swc > 0, "switch row right tail (meow_switch) renders swc=%d", swc);
|
||
}
|
||
|
||
/* ============ P2 meow_listview 命中(行号 + 段头可命中) ============ */
|
||
printf("P2 meow_listview hit\n");
|
||
CHECK(meow_listview_hit(lv, 10, SET_LIST_Y + 0 * SET_ITEM_H + SET_ITEM_H / 2) == 0,
|
||
"row0 (header 显示) hit idx0 (enabled=1)");
|
||
CHECK(meow_listview_hit(lv, 10, SET_LIST_Y + 1 * SET_ITEM_H + SET_ITEM_H / 2) == 1,
|
||
"row1 (亮度 slider) hit idx1");
|
||
CHECK(meow_listview_hit(lv, 10, SET_LIST_Y + 3 * SET_ITEM_H + SET_ITEM_H / 2) == 3,
|
||
"row3 (息屏模式 enum) hit idx3");
|
||
CHECK(meow_listview_hit(lv, 10, SET_LIST_Y + 8 * SET_ITEM_H + SET_ITEM_H / 2) == 8,
|
||
"row8 (WiFi list) hit idx8");
|
||
CHECK(meow_listview_hit(lv, 10, SET_LIST_Y - 2) == -1, "above list -> -1");
|
||
/* 滚动后命中(listview set_scroll 换算):scroll=20(<9*68-视口=32)时点 row1 中心 → idx1 */
|
||
meow_listview_set_scroll(lv, 20);
|
||
CHECK(meow_listview_hit(lv, 10, SET_LIST_Y + SET_ITEM_H + SET_ITEM_H / 2) == 1,
|
||
"scrolled +20px: row1 center hits idx1");
|
||
CHECK(meow_listview_max_scroll(lv) > 0, "max_scroll > 0 (list taller than viewport) got %d",
|
||
meow_listview_max_scroll(lv));
|
||
meow_listview_set_scroll(lv, 0);
|
||
|
||
/* ============ P3 开关写回(读改写单键 → settings.conf) ============ */
|
||
printf("P3 switch write-back to settings.conf\n");
|
||
meow_settings_set_switch("input.swipe_invert", 0); /* reset */
|
||
meow_settings_save();
|
||
int before_on = 0; meow_settings_get_switch("input.swipe_invert", &before_on);
|
||
{
|
||
/* 模拟 tap ROWS[6]=滑动方向 */
|
||
const srow_t *r = &ROWS[6];
|
||
s_switch_toggle(r);
|
||
meow_settings_save();
|
||
}
|
||
int after_on = 0; meow_settings_get_switch("input.swipe_invert", &after_on);
|
||
CHECK(before_on == 0 && after_on == 1,
|
||
"input.swipe_invert toggled 0->1 (read-modify-write single key)");
|
||
CHECK(conf_has("input.swipe_invert", "1"), "settings.conf has input.swipe_invert=1");
|
||
CHECK(!conf_has("display.refresh_always_max", "1"), "untouched sibling key unchanged in conf");
|
||
|
||
/* ============ P4 滑条写回(x→值 → settings.conf;含息屏时间 挡位→秒) ============ */
|
||
printf("P4 slider write-back to settings.conf\n");
|
||
meow_settings_set_int("display.brightness", 50); meow_settings_save();
|
||
{
|
||
const srow_t *r = &ROWS[1]; /* 亮度 1..100 */
|
||
int v = s_slider_val_from_x(r, S_SLIDER_X + S_SLIDER_W / 2); /* 中点 ≈ 50 */
|
||
s_slider_set(r, v, 1);
|
||
meow_settings_save();
|
||
int got = 0; meow_settings_get_int("display.brightness", &got);
|
||
CHECK(got == v, "display.brightness set via track -> %d (expect %d)", got, v);
|
||
char kv[64]; snprintf(kv, sizeof kv, "%d", v);
|
||
CHECK(conf_has("display.brightness", kv), "settings.conf has display.brightness=%d", v);
|
||
}
|
||
{ /* 息屏时间:秒→挡位索引(显示用)与 挡位索引→秒(落盘用)双向映射 */
|
||
const srow_t *r = &ROWS[4]; /* 0..S_TIME_TIERS_N-1 */
|
||
int idx = 5; /* 第 5 挡 = 30 秒 */
|
||
int sec = s_time_tier_val(idx);
|
||
CHECK(s_time_tier_idx(30) == idx, "screen_off_timeout sec 30 -> tier idx %d", idx);
|
||
s_slider_set(r, idx, 1);
|
||
meow_settings_save();
|
||
int got = 0; meow_settings_get_int("display.screen_off_timeout", &got);
|
||
CHECK(sec == 30 && got == 30, "screen_off_timeout tier idx5 -> 30s (got %d)", got);
|
||
CHECK(conf_has("display.screen_off_timeout", "30"), "settings.conf has display.screen_off_timeout=30");
|
||
}
|
||
|
||
/* ============ P5 枚举写回(enum 选项 → settings.conf 键值正确) ============ */
|
||
printf("P5 enum write-back to settings.conf\n");
|
||
{
|
||
const char *names[8]; int kn = 0;
|
||
meow_settings_enum_names("display.screen_off_mode", names, &kn);
|
||
CHECK(kn > 0, "display.screen_off_mode enum names count=%d", kn);
|
||
int pick = 1; /* "black"(黑屏) */
|
||
meow_settings_set_enum("display.screen_off_mode", pick);
|
||
meow_settings_save();
|
||
int got = 0; meow_settings_get_enum("display.screen_off_mode", &got);
|
||
CHECK(got == pick, "display.screen_off_mode enum -> %d (expect %d)", got, pick);
|
||
CHECK(conf_has("display.screen_off_mode", "black"), "settings.conf has display.screen_off_mode=black");
|
||
}
|
||
|
||
meow_ui_activity_pop();
|
||
meow_ui_shutdown();
|
||
printf(g_fail ? "\nRESULT: %d FAIL(S)\n" : "\nRESULT: ALL PASS\n", g_fail);
|
||
return g_fail;
|
||
}
|