状态栏正确闭环(agent-142): 系统进程统一渲染+App不画+覆盖叠加+数据唯一+MD3图标式+主题换图标

- meow_ui_sys_set_system_mode: launcher置1才渲染, App默认0→不画状态栏; app_overlay_statusbar在launch_app循环~1s叠加28px顶条(不SIGSTOP App)
- 数据源唯一(launcher g_sys→meow_ui_sys_feed; wifi_level/batt/vol/bri/clock), 根治"launcher有亮度App没有"
- 右侧=MD3图标+变量值(statusbar_right_str文本退役→图标簇, 复用sb_icons.h/MEOW_SB_ICON_*/meow_gfx_blit_icon); 颜色随meow_theme
- ui.style换图标集(meow_ui_style/set_style读ui.style md3/miuix, MIUIx暂MD3占位)
- hello最小改动(redraw非全屏只清inset=28之下, 不冲系统顶条); 开放点: App不SIGSTOP/inset28/MIUIx占位/set_statusbar系统模式门
- meow_ui.a=3da5af7b launcher=a2b1c096 hello=67075741 0warning; 宿主test_sb_statusbar ALL PASS + render PPM目检(左时钟右亮度/WiFi/蓝牙/音量/电量)
- 遗留: 真机验证(无双画/数据一致/顶条叠加/inset/ui.style); 运行时fullscreen沉浸叠画待M3; MIUIx图标占位
This commit is contained in:
MeowOS committed 2026-08-30 19:32:40 +08:00
1 parent 2a6c4e97c5
commit 7300fc0a13
14 files changed
+731 -44

No files matched your search

Binary file not shown.
+91 -7
View File
@@ -2817,6 +2817,7 @@ typedef struct meow_sys_state {
int batt_mv; /* 电压 mV */
int wifi_on; /* M2.48:1 网卡 up(射频开)0 down(关则不显示图标) */
int wifi_connected;/* M2.48:1 已关联 AP(operstate up)0 未连(区分「网卡up未连」→WIFI_NO) */
int wifi_level; /* M2.66+:信号 dBm(-1000=未知);状态栏 WiFi 分档(强/中/弱),喂给 SDK */
char wifi_ssid[33];
char wifi_ip[16];
int bt_on; /* 1 蓝牙上电 0 关 */
@@ -2899,6 +2900,43 @@ static int hci_powered(void)
return up;
}
#define WIFI_LVL_UNKNOWN (-1000) /* wifi_signal_level 读取失败哨兵(低于任何真实 dBm) */
/* 读 /proc/net/wireless 的 wlan0 level(dBm,如 -46);失败(文件不存在/无 wlan0 行/解析失败)返回
* WIFI_LVL_UNKNOWN。行格式(Linux wext)形如 " wlan0: 0000 64. -46. -256 0 ...";
* 接口名后第 3 个空白分隔数值 = level(注意末尾带 '.',需剥离)。状态栏 WiFi 信号分档喂给 SDK。 */
static int wifi_signal_level(void)
{
FILE *f = fopen("/proc/net/wireless", "r");
if (!f) return WIFI_LVL_UNKNOWN;
char line[256];
int lvl = WIFI_LVL_UNKNOWN;
while (fgets(line, sizeof line, f)) {
char *p = strstr(line, "wlan0:");
if (!p) continue;
p += 6; /* 跳过 "wlan0:" */
int tok = 0;
while (*p) {
while (*p == ' ' || *p == '\t') p++;
if (!*p) break;
char *t = p;
while (*p && *p != ' ' && *p != '\t' && *p != '\n') p++;
char save = *p; *p = 0; /* 临时截断 token */
if (tok == 2) { /* 第 3 个数值(0 起) = level */
size_t n = strlen(t);
if (n && t[n - 1] == '.') t[n - 1] = 0; /* 去尾部 '.'(-46. → -46) */
lvl = atoi(t);
*p = save;
break;
}
*p = save;
tok++;
}
break; /* 只需 wlan0 行 */
}
fclose(f);
return lvl;
}
/* 全量重抓(进 MeowOS 时调用一次;阻塞可接受)。绝不放进 10ms 主循环。 */
static void meow_sys_refresh(void)
{
@@ -2916,6 +2954,7 @@ static void meow_sys_refresh(void)
read_sys_str("/sys/class/net/wlan0/operstate", op, sizeof op);
g_sys.wifi_connected = !strcmp(op, "up") ? 1 : 0;
g_sys.wifi_on = wlan_radio_up();
g_sys.wifi_level = g_sys.wifi_connected ? wifi_signal_level() : WIFI_LVL_UNKNOWN;
g_sys.wifi_ip[0] = 0; g_sys.wifi_ssid[0] = 0;
if (g_sys.wifi_connected) {
/* 行形如 "2: wlan0 inet <device_ip>/24 brd ...",取 inet 后第一个斜杠前的 token。
@@ -2974,6 +3013,7 @@ static void meow_sys_light(void)
read_sys_str("/sys/class/net/wlan0/operstate", op, sizeof op);
g_sys.wifi_connected = !strcmp(op, "up") ? 1 : 0;
g_sys.wifi_on = wlan_radio_up();
g_sys.wifi_level = g_sys.wifi_connected ? wifi_signal_level() : WIFI_LVL_UNKNOWN;
g_sys.vol = settings_volume_get(); /* 每进 MeowOS 重抓;此处同步内存值 */
bt_role_refresh(0); /* M2.48:节流探测蓝牙角色(约 5s 一次,不阻塞主循环) */
}
@@ -3293,13 +3333,15 @@ static void sb_sdk_refresh(void)
{
meow_theme_reload(); /* SDK 状态栏主题随 launcher 换肤(重读 settings) */
meow_ui_feed f;
f.batt = g_sys.batt;
f.charging = g_sys.charging;
f.wifi_on = g_sys.wifi_on;
f.bt_seen = g_sys.bt_seen;
f.bt_on = g_sys.bt_on;
f.vol = g_sys.vol;
f.brightness = g_sys.brightness;
f.batt = g_sys.batt;
f.charging = g_sys.charging;
f.wifi_on = g_sys.wifi_on;
f.wifi_connected = g_sys.wifi_connected;
f.wifi_level = g_sys.wifi_level;
f.bt_seen = g_sys.bt_seen;
f.bt_on = g_sys.bt_on;
f.vol = g_sys.vol;
f.brightness = g_sys.brightness;
meow_ui_sys_feed(&f); /* 权威快照喂入 + 置 force(顶条必重画) */
meow_dirty_add(0, SB_BAR_Y, fb_xres, SB_BAR_H); /* 标脏顶条 → present() 时 SDK 重画 */
}
@@ -4077,6 +4119,10 @@ static void run_menu(struct app apps[MAX_APPS], int napps, int state,
* 与 App 同一实现/同一主题/同日/夜。详见 devdocs/plan/LAUNCHER_SDK_REWRITE.md。 */
meow_ui_init(NULL);
meow_ui_set_statusbar(1);
/* 「同一个状态栏」闭环(FRAMEWORK_DESIGN §10.2 / MEOW_APP_SDK §3.1):SDK 全局状态栏
* 仅系统进程(launcher)渲染。launcher 是系统 UI 渲染宿主 → 置 system_mode=1 让 SDK 渲染顶条
* /提示线;App 进程默认 0(不渲染、只 inset,由 launcher 叠加)。详见 devdocs/plan/LAUNCHER_SDK_REWRITE.md。 */
meow_ui_sys_set_system_mode(1);
meow_ui_set_refresh_rate(refresh_rate_cfg);
meow_ui_set_refresh_always_max(refresh_always_max);
@@ -8835,6 +8881,34 @@ static void meow_write_app_state(int immersive)
close(fd);
}
/* ---- App 前台状态栏叠加(「同一个状态栏」闭环,FRAMEWORK_DESIGN §10.2 / MEOW_APP_SDK §3.1)----
* App 前台时状态栏由 launcher(系统进程)作为**常驻**系统叠加层绘制顶条 28px(App 进程不渲染、
* 只 inset,§6.1 ③)。本函数由 launch_app 的 waitpid 循环定时调用:
* 1) 刷新权威数据 meow_sys_light()(电池/WiFi/音量/蓝牙)+ 喂 SDK → 唯一数据源(主界面与 App 一致);
* 2) 标脏顶条 + meow_ui_flush() → SDK present() 在上屏前把全局状态栏画进 back_buf 顶部 MUI_SBAR_H
* 行并原子 blit 到 buffer0(仅顶条);
* 3) 只 blit 顶条(不碰 y>=28 的 App 内容)→ 不覆盖 App、不 SIGSTOP App(App 继续播/响应)。
* 与通知中心/电源菜单(SIGSTOP + 全屏叠画)的差异:状态栏常驻、非模态、只碰顶条。 */
static void app_overlay_statusbar(void)
{
if (!back_buf_ok || !fb) return; /* 无 SDK back_buf(直写模式):无法叠加,跳过 */
meow_sys_light(); /* 刷新 g_sys(电池/WiFi/音量/蓝牙;唯一权威源) */
meow_theme_reload(); /* SDK 状态栏主题随 launcher 换肤(重读 settings) */
meow_ui_feed f;
f.batt = g_sys.batt;
f.charging = g_sys.charging;
f.wifi_on = g_sys.wifi_on;
f.wifi_connected = g_sys.wifi_connected;
f.wifi_level = g_sys.wifi_level;
f.bt_seen = g_sys.bt_seen;
f.bt_on = g_sys.bt_on;
f.vol = g_sys.vol;
f.brightness = g_sys.brightness;
meow_ui_sys_feed(&f); /* 喂权威快照 + 置 force(顶条必重画) */
meow_dirty_add(0, 0, fb_xres, SB_BAR_H); /* 标脏顶条 → present() 时 SDK 重画状态栏(仅顶条) */
meow_ui_flush(); /* SDK present:vsync + 原子 blit 脏区(仅顶条) */
}
static int launch_app(struct app *a);
/* (definition follows) */
@@ -9051,6 +9125,11 @@ static int launch_app(struct app *a)
unsigned long save_pow[KEYBUF_WORDS], save_keys[KEYBUF_WORDS];
memcpy(save_pow, kp_power.cur, sizeof save_pow);
memcpy(save_keys, kp_keys.cur, sizeof save_keys);
/* 「同一个状态栏」闭环:App 前台状态栏由 launcher 常驻叠加(顶条 28px、非模态、不 SIGSTOP App)。
* 立即叠一次(App 首帧前顶条就有),其后每 ~1s 重画(时钟每秒变 + 数据新鲜)。app 级
* fullscreen 声明(沉浸,整条隐藏)时不叠。 */
unsigned long long last_sb_overlay_ms = 0;
if (!a->fullscreen) app_overlay_statusbar();
/* M2.24:清上一次会话可能残留的电源菜单标记,只认本次新 watchdog 生成的请求。 */
unlink(POWMENU_MARKER);
unlink(POWMENU_ACTIVE);
@@ -9147,6 +9226,11 @@ static int launch_app(struct app *a)
app_last_input = now_ms(); /* M2.17:菜单交互即输入,重置应用会话自动息屏计时 */
if (pm_ret != 0) break; /* 关机/重启/回HibyOS:系统通常已 reboot,防御性退出 */
}
/* 「同一个状态栏」闭环:常驻顶条每 ~1s 重画(时钟/数据新鲜;仅标脏顶条上屏,不碰 App 内容)。 */
if (!a->fullscreen && now_ms() - last_sb_overlay_ms >= 1000) {
last_sb_overlay_ms = now_ms();
app_overlay_statusbar();
}
usleep(100000);
}
if (wpid > 0) {