启动器SDK改造 阶段一: 状态栏收敛单一SDK全局(agent-136)

- launcher meow_ui_set_statusbar(1) 启用SDK全局状态栏; 旧自绘(draw_statusbar/sb_redraw等)#if0退役(保留回退)
- 新增 SDK meow_ui_sys_feed(): launcher 喂 batt/charging/wifi/bt/vol/brightness 进SDK快照+置force+标脏顶条(0,0,xres,28)→present只重画顶条
- meow_ui_theme_reload(): SDK状态栏跟手launcher换肤; meow_sys_state 增 brightness
- 主界面/设置页/电源菜单/通知中心 顶部28px 由SDK全局状态栏统一绘制; 与App同实现/同主题/同日·夜
- ⚠️ 状态栏由MD3图标式→SDK文本式(HH:MM:SS …81% WIFI 蓝牙 VOL 亮度) — 用户拍板"用SDK的"既定结果; 图标MD3化属后续
- meow_ui.a=110c820a(仅新增符号,向后兼容) launcher=d4f108dd hello=12f48840(重编确认App不破坏); 0warning
- devdocs/plan/LAUNCHER_SDK_REWRITE.md 方案先行
This commit is contained in:
MeowOS committed 2026-08-30 18:42:59 +08:00
1 parent 815cc8cd19
commit a31a004afe
7 files changed
+151 -24

No files matched your search

Binary file not shown.
Binary file not shown.
+71 -22
View File
@@ -2995,8 +2995,10 @@ static void meow_sys_light(void)
#define SB_BAR_Y 0 #define SB_BAR_Y 0
#define SB_BAR_H 28 /* rows 0..27;分隔线在 y=28 不在此(40→28,用户定) */ #define SB_BAR_H 28 /* rows 0..27;分隔线在 y=28 不在此(40→28,用户定) */
#define SB_FONT 20 /* 状态栏字体 28→20(28px 栏放不下 28 号;垂直居中锚点见 sb_text_y) */ #define SB_FONT 20 /* 状态栏字体 28→20(28px 栏放不下 28 号;垂直居中锚点见 sb_text_y) */
#if 0 /* [RETIRED Stage-One] 旧自绘状态栏的时钟/右侧包围盒变量,仅供 sb_redraw 用,现已退役 */
static int g_sb_clock_x, g_sb_clock_y, g_sb_clock_w, g_sb_clock_h; static int g_sb_clock_x, g_sb_clock_y, g_sb_clock_w, g_sb_clock_h;
static int g_sb_right_x, g_sb_right_y, g_sb_right_w, g_sb_right_h; static int g_sb_right_x, g_sb_right_y, g_sb_right_w, g_sb_right_h;
#endif
/* ---- 主题(MD3 color roles,dark/light 两套)---- /* ---- 主题(MD3 color roles,dark/light 两套)----
* M2.44:上移到本处(状态栏绘制之前),使状态栏/设置页共用同一套主题色板。 */ * M2.44:上移到本处(状态栏绘制之前),使状态栏/设置页共用同一套主题色板。 */
@@ -3086,11 +3088,13 @@ static int g_sb_icon_cy = SB_ICON_CY;
/* 状态栏文字垂直锚 y(行首升线顶):(栏高-行高)/2 把文字垂直居中于 28px 栏; /* 状态栏文字垂直锚 y(行首升线顶):(栏高-行高)/2 把文字垂直居中于 28px 栏;
* 下限 1 防极端行高(>栏高)时算出负 y 溢出顶端(不越界优先)。 */ * 下限 1 防极端行高(>栏高)时算出负 y 溢出顶端(不越界优先)。 */
#if 0 /* [RETIRED Stage-One] 旧自绘状态栏专用,现由 SDK 全局状态栏绘制,退役(保留回退) */
static int sb_text_y(void) static int sb_text_y(void)
{ {
int y = (SB_BAR_H - ui_text_height(SB_FONT)) / 2; int y = (SB_BAR_H - ui_text_height(SB_FONT)) / 2;
return (y < 1) ? 1 : y; return (y < 1) ? 1 : y;
} }
#endif
/* 状态栏 MD3 图标 blit:把 sb_icons.h 的 32x32 单通道 alpha 位图画进状态栏(fb = SDK back_buf)。 /* 状态栏 MD3 图标 blit:把 sb_icons.h 的 32x32 单通道 alpha 位图画进状态栏(fb = SDK back_buf)。
* x = 图标槽左缘(槽宽 SB_ICON_SIZE);fg = 24-bit RGB 前景色(主题 on_surface / on_surface_variant)。 * x = 图标槽左缘(槽宽 SB_ICON_SIZE);fg = 24-bit RGB 前景色(主题 on_surface / on_surface_variant)。
@@ -3147,6 +3151,7 @@ static void sb_blit_icon(int icon_idx, int x, uint32_t fg, int ink_h)
} }
} }
#if 0 /* [RETIRED Stage-One] 以下为旧「自绘状态栏」的右簇布局/信号分档,仅 sb_redraw 用,现已退役 */
/* 画一个右对齐状态栏项:右边界 = *xr,画完向左推进 *xr(含 SB_XGAP 项间隙)。 /* 画一个右对齐状态栏项:右边界 = *xr,画完向左推进 *xr(含 SB_XGAP 项间隙)。
* icon>=0 画图标(可配右侧文字 txt;txt==NULL 则仅图标)。文字/图标同用主题色 col。 * icon>=0 画图标(可配右侧文字 txt;txt==NULL 则仅图标)。文字/图标同用主题色 col。
* ink_h 传给 sb_blit_icon(主图标用 SB_ICON_INK 等大;WiFi 强弱档传 0 保持自然 ink)。 * ink_h 传给 sb_blit_icon(主图标用 SB_ICON_INK 等大;WiFi 强弱档传 0 保持自然 ink)。
@@ -3199,7 +3204,10 @@ static int wifi_signal_level(void)
fclose(f); fclose(f);
return lvl; return lvl;
} }
#endif
#if 0 /* [RETIRED Stage-One] 旧「自绘状态栏」整条重绘。现由 SDK 全局状态栏(唯一绘制者)取代,
* 经 sb_sdk_refresh() 喂权威状态 + 标脏顶条驱动。保留以便回退,勿删逻辑。 */
/* 整条状态栏:清底→重绘时钟+右侧信息→整条标脏。调用点:时钟每秒 / 电量·WiFi·音量事件。 */ /* 整条状态栏:清底→重绘时钟+右侧信息→整条标脏。调用点:时钟每秒 / 电量·WiFi·音量事件。 */
static void sb_redraw(void) static void sb_redraw(void)
{ {
@@ -3267,18 +3275,57 @@ static void sb_redraw(void)
g_sb_right_h = SB_BAR_H; g_sb_right_h = SB_BAR_H;
meow_dirty_add(0, SB_BAR_Y, fb_xres, SB_BAR_H); /* 整条标脏 */ meow_dirty_add(0, SB_BAR_Y, fb_xres, SB_BAR_H); /* 整条标脏 */
} }
#endif
/* 只重画状态栏整条到 SDK back_buf 并标整条脏 —— 每秒(时钟)/ 事件(电量/WiFi/音量)触发,绝不动列表。 /* ---- Stage-One 状态栏收敛:launcher 不再自绘状态栏,统一由 SDK 全局状态栏绘制 ----
* launcher 系统界面(主界面/设置页/电源菜单/通知中心)顶部 28px 状态栏改由 SDK 的
* meow_ui_sys_statusbar_render()(present() 时合成,z 最顶)绘制。launcher 侧只保留三个
* 入口(paint_sb_clock/paint_sb_right/draw_statusbar,调用点遍布主界面/设置页/通知中心/
* 音量/亮度/主题变更/1s 时钟),其职责从「自绘」改为「把权威状态喂进 SDK + 标脏顶条」。
* 依据(devdocs/plan/LAUNCHER_SDK_REWRITE.md):
* - launcher 不跑 SDK 事件循环 → SDK 的 meow_ui_sys_refresh() 不在 launcher 触发,数据
* 必须由 launcher 喂。g_sys(meow_sys_refresh/light + 事件路径维护)是权威源,尤其
* 亮度/音量(写入方=launcher)。
* - SDK 主题是缓存的 → 喂前 meow_theme_reload() 逼重读 settings,状态栏跟手 launcher 换肤。
* - 标脏顶条 (0,0,xres,28) → present() 时 SDK 重画顶条;SDK 只在「数据变(force)/顶条被触及/
* 收合过渡」才重画,天然满足「状态栏只在变化时重绘」。 */
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;
meow_ui_sys_feed(&f); /* 权威快照喂入 + 置 force(顶条必重画) */
meow_dirty_add(0, SB_BAR_Y, fb_xres, SB_BAR_H); /* 标脏顶条 → present() 时 SDK 重画 */
}
/* 三个入口(调用点不动):现在驱动 SDK 全局状态栏(唯一绘制者),不再自绘。 */
static void paint_sb_clock(void) { sb_sdk_refresh(); }
static void paint_sb_right(void) { sb_sdk_refresh(); }
static void draw_statusbar(void) { sb_sdk_refresh(); } /* 对齐原语义:整条状态栏 → SDK 绘制 */
/* ===== [RETIRED Stage-One] 以下为 launcher 旧「自绘状态栏」实现,已退役(不再被调用)。
* 保留以供回退,勿删逻辑(见注释)。移用者:仅注释存档;sb_blit_icon/g_sb_icon_cy/SB_ICON_CY
* 仍被通知中心 chip(ncp_sb_icon)复用,故其定义保留在使用处。 ===== */
#if 0
/* 只重画状态栏整条到 SDK back_buf 并标整条脏 ---- 每秒(时钟)/ 事件(电量/WiFi/音量)触发,绝不动列表。
* (取代 M2.16 的「只标当前内容包围盒」路径——它造成残留。) */ * (取代 M2.16 的「只标当前内容包围盒」路径——它造成残留。) */
static void paint_sb_clock(void) { sb_redraw(); } static void paint_sb_clock_retired(void) { sb_redraw(); }
static void paint_sb_right(void) { sb_redraw(); } static void paint_sb_right_retired(void) { sb_redraw(); }
static void draw_statusbar(void) static void draw_statusbar_retired(void)
{ {
sb_redraw(); sb_redraw();
const meow_ui_theme_t *th = s_ui_theme(); /* M2.44 分隔线随主题 outline */ const meow_ui_theme_t *th = s_ui_theme(); /* M2.44 分隔线随主题 outline */
fill_rect(0, SB_BAR_H, fb_xres, 1, th->outline); /* separator(整条之外,单独绘制;栏底=28) */ fill_rect(0, SB_BAR_H, fb_xres, 1, th->outline); /* separator(整条之外,单独绘制;栏底=28) */
} }
#endif
/* returns 0 on success (app ran and exited), -1 on launch failure */ /* returns 0 on success (app ran and exited), -1 on launch failure */
static int launch_app(struct app *a); static int launch_app(struct app *a);
@@ -3374,16 +3421,13 @@ static void draw_header_content(void)
} }
} }
/* Refresh ONLY the clock digits (top-left, HH:MM:SS) once per second — the one /* 每秒一次刷新状态栏时钟(顶部 HH:MM:SS,唯一每秒都变的值)。Stage-One 状态栏收敛后,
* status-bar value that changes every second. This is what makes the "clock * launcher 不再自绘状态栏——draw_clock 只经 paint_sb_clock() → sb_sdk_refresh() 把权威
* updates every second" work WITHOUT redrawing (or tearing) the app list, and * 状态喂进 SDK 全局状态栏 + 标脏顶条,由 SDK present() 顶条重绘(时钟/电量/音量等一并刷新)。
* WITHOUT the slow amixer popen that a full draw_statusbar() would incur on * 绝不动应用列表(仅顶条 28px 脏),故列表不重绘/不撕裂;无 amixer/sysfs 每帧开销。 */
* each tick. Everything else (battery/wifi/bluetooth/volume) changes only on
* user input, which triggers a full draw_menu via the dirty flag. Clears a
* small box then redraws the time, so old digits do not ghost. */
static void draw_clock(void) static void draw_clock(void)
{ {
paint_sb_clock(); /* M2.16:本地重画时钟格(每秒),只动这个矩形 */ paint_sb_clock(); /* → sb_sdk_refresh():喂 SDK + 标脏顶条,present() 时 SDK 重绘状态栏 */
} }
/* M2.36 右向小箭头(进入/下拉提示)。点阵后备字库(5x7)缺 '>' 字形(glyph_index 落到空 /* M2.36 右向小箭头(进入/下拉提示)。点阵后备字库(5x7)缺 '>' 字形(glyph_index 落到空
@@ -4027,10 +4071,12 @@ static void run_menu(struct app apps[MAX_APPS], int napps, int state,
/* A-1/A-2:launcher 用 SDK 渲染栈 —— 初始化 SDK(自建 back_buf/读几何/载字库), /* A-1/A-2:launcher 用 SDK 渲染栈 —— 初始化 SDK(自建 back_buf/读几何/载字库),
* 并把刷新率档位/恒满速开关交给 SDK present 帧率门控(去中心化:launcher 不再自带一套)。 * 并把刷新率档位/恒满速开关交给 SDK present 帧率门控(去中心化:launcher 不再自带一套)。
* set_statusbar(0):launcher 用自己的状态栏(draw_statusbar),关闭 SDK 全局状态栏避免 * set_statusbar(1)(Stage-One 状态栏收敛):launcher 系统界面(主界面/设置页/电源菜单/
* 同区双画(SDK 全局状态栏/左缘返回对 APP 生效;launcher 系统界面暂保留自有状态栏)。 */ * 通知中心)顶部状态栏统一由 SDK 全局状态栏绘制(MUI_SBAR_H=28),launcher 不再自绘
* (draw_statusbar/sb_redraw 退役,改由 sb_sdk_refresh() 喂权威状态 + 标脏顶条驱动)。
* 与 App 同一实现/同一主题/同日/夜。详见 devdocs/plan/LAUNCHER_SDK_REWRITE.md。 */
meow_ui_init(NULL); meow_ui_init(NULL);
meow_ui_set_statusbar(0); meow_ui_set_statusbar(1);
meow_ui_set_refresh_rate(refresh_rate_cfg); meow_ui_set_refresh_rate(refresh_rate_cfg);
meow_ui_set_refresh_always_max(refresh_always_max); meow_ui_set_refresh_always_max(refresh_always_max);
@@ -4662,7 +4708,8 @@ static void run_menu(struct app apps[MAX_APPS], int napps, int state,
* steady-state list must not be touched. */ * steady-state list must not be touched. */
/* M2.16:只在真变化时标脏(精确到格子),绝无"动一下就全屏重绘"。 /* M2.16:只在真变化时标脏(精确到格子),绝无"动一下就全屏重绘"。
* 光标移动 → 旧/新两行;toast 起止 → toast 区;其余结构变化 → dirty=1(全帧)。 * 光标移动 → 旧/新两行;toast 起止 → toast 区;其余结构变化 → dirty=1(全帧)。
* 音量渐变/时钟只经 paint_sb_right/draw_clock 标右侧格/时钟格。 */ * Stage-One 状态栏收敛:音量渐变/时钟只经 paint_sb_right/draw_clock → sb_sdk_refresh()
* 把权威状态喂进 SDK 全局状态栏 + 标脏顶条(0,0,xres,28),由 SDK present() 顶条重绘。 */
if (cursor != last_cursor) { if (cursor != last_cursor) {
/* M2.36 B2b:光标可能在应用行(0..napps-1)或「系统设置」行(napps,位于 Exit 行上方)。 /* M2.36 B2b:光标可能在应用行(0..napps-1)或「系统设置」行(napps,位于 Exit 行上方)。
* 分别标脏对应行 rect(设置行固定 y=EXIT_ROW-ROW_H,与 napps 无关)。 */ * 分别标脏对应行 rect(设置行固定 y=EXIT_ROW-ROW_H,与 napps 无关)。 */
@@ -4705,7 +4752,7 @@ static void run_menu(struct app apps[MAX_APPS], int napps, int state,
if (el - last_status_tick >= 1000) { if (el - last_status_tick >= 1000) {
last_status_tick = el; last_status_tick = el;
meow_sys_light(); /* 同步电量/WiFi/音量进 g_sys */ meow_sys_light(); /* 同步电量/WiFi/音量进 g_sys */
draw_clock(); /* M2.17:sb_redraw() 重画整条(时钟+电量/WiFi/音量)并标整条脏 */ draw_clock(); /* Stage-One:喂 SDK 全局状态栏 + 标脏顶条;SDK present() 重绘 */
fb_norm_buf0(); fb_norm_buf0();
meow_ui_flush(); /* blit 状态栏整条,不动列表 */ meow_ui_flush(); /* blit 状态栏整条,不动列表 */
} }
@@ -6029,7 +6076,7 @@ static void draw_settings_page(int sel, int scroll_off)
const meow_ui_theme_t *th = s_ui_theme(); const meow_ui_theme_t *th = s_ui_theme();
int W = fb_xres, H = fb_yres; int W = fb_xres, H = fb_yres;
fill_rect(0, 0, W, H, th->surface); fill_rect(0, 0, W, H, th->surface);
draw_statusbar(); /* 复用状态栏骨架 */ draw_statusbar(); /* Stage-One:驱动 SDK 全局状态栏(喂数据+标脏顶条) */
if (mfont_ready) ui_draw(24, 50, "系统设置", th->on_surface, 28); if (mfont_ready) ui_draw(24, 50, "系统设置", th->on_surface, 28);
else draw_text(24, 30, "SETTINGS", 3, th->on_surface); else draw_text(24, 30, "SETTINGS", 3, th->on_surface);
fill_rect(0, 50 + (mfont_ready ? meow_font_line_height(28) : 24) + 2, W, 2, th->outline); fill_rect(0, 50 + (mfont_ready ? meow_font_line_height(28) : 24) + 2, W, 2, th->outline);
@@ -7429,8 +7476,9 @@ static void draw_notif_center(int scroll, int redraw_sb)
const meow_ui_theme_t *th = s_ui_theme(); const meow_ui_theme_t *th = s_ui_theme();
int W = fb_xres, H = fb_yres; int W = fb_xres, H = fb_yres;
/* 状态栏带 [0,NCP_TOP) 仅当 redraw_sb=1(打开/主题变化)时清底,随后由下方 draw_statusbar() /* 状态栏带 [0,NCP_TOP) 仅当 redraw_sb=1(打开/主题变化)时清底,随后由下方 draw_statusbar()
* 覆盖重绘;redraw_sb=0(交互重绘,如拖滑条)时**绝不触碰**——保留 back_buf 中 paint_sb_right() * 覆盖重绘(Stage-One:draw_statusbar 只喂 SDK + 标脏顶条,实际由 SDK present() 重绘);
* 已绘好的状态栏,避免被清成 surface 底仍被 blit → 状态栏数值闪烁/消失(真机①修复)。 * redraw_sb=0(交互重绘,如拖滑条)时**绝不触碰**——保留 back_buf 中 SDK 状态栏/上次 top 脏,
* 避免被清成 surface 底仍被 blit → 状态栏数值闪烁/消失(真机①修复)。
* 面板体(状态栏之下 surface_variant)态恒整片铺。 */ * 面板体(状态栏之下 surface_variant)态恒整片铺。 */
if (redraw_sb) fill_rect(0, 0, W, NCP_TOP, th->surface); if (redraw_sb) fill_rect(0, 0, W, NCP_TOP, th->surface);
fill_rect(0, NCP_TOP, W, H - NCP_TOP, th->surface_variant); fill_rect(0, NCP_TOP, W, H - NCP_TOP, th->surface_variant);
@@ -7510,8 +7558,9 @@ static void draw_notif_center(int scroll, int redraw_sb)
ui_draw((W - ui_width("上滑或点空白关闭", 16)) / 2, NCP_FOOT_Y, "上滑或点空白关闭", ui_draw((W - ui_width("上滑或点空白关闭", 16)) / 2, NCP_FOOT_Y, "上滑或点空白关闭",
th->on_surface_variant, 16); th->on_surface_variant, 16);
/* 状态栏画在面板体之上(0-27 单独由 draw_statusbar 维护/标脏,不落面板体脏区)。 /* 状态栏画在面板体之上(0-27 由 SDK 全局状态栏维护,经 draw_statusbar→sb_sdk_refresh
* 仅 redraw_sb=1(打开/主题变化)才重绘,交互时跳过以保持脏区只限面板体。 */ * 喂数据+标脏顶条;不落面板体脏区)。仅 redraw_sb=1(打开/主题变化)才喂/标脏,交互时跳过
* 以保持脏区只限面板体(顶条像素留在 back_buf,由 SDK 已合成的状态栏保持)。 */
if (redraw_sb) draw_statusbar(); if (redraw_sb) draw_statusbar();
} }
+27
View File
@@ -8,6 +8,33 @@
#include <stdint.h> #include <stdint.h>
#include "meow_ui.h" #include "meow_ui.h"
/* ---- 系统状态喂入(Stage-One 状态栏收敛;meow_ui_sys.c 提供)----
* launcher(系统进程)不跑 SDK 事件循环(无 meow_ui_run),SDK 的 meow_ui_sys_refresh()
* 不会在 launcher 里自动触发;且电量/音量/亮度等权威值本就在 launcher 的 g_sys 快照里
* (launcher 是背光/音量写入方)。故此 API 让 launcher 把权威快照喂进 SDK 的系统状态,
* 喂入即置状态栏 force,下一次 present() 重画顶条。SDK 自身 meow_ui_sys_refresh() 仍按
* 同源兜底(供 App 流程 meow_ui_run 使用)。只填 SDK 快照所需最小字段,与 launcher 的
* meow_sys_state(meow_launcherd.c)字段名交叉映射,二者是不同 TU 的异名类型,故用此
* 专用喂入结构,避免 launcher 引入 meow_ui_sys.h 造成 typedef 重定义。 */
typedef struct meow_ui_feed {
int batt; /* 电量 %,-1 未知 */
int charging; /* 1 充电/满 0 放电 */
int wifi_on; /* 1 网卡 up(operstate==up) */
int bt_seen; /* hci0 节点存在 */
int bt_on; /* 实际上电 */
int vol; /* 音量 0-100 */
int brightness; /* 背光 1-100;<=0 视为未知/屏关不入顶条 */
} meow_ui_feed;
void meow_ui_sys_feed(const meow_ui_feed *f); /* 喂权威快照 + 置 force 重绘顶条 */
/* ---- 主题(meow_ui_theme.c 提供)----
* 重置主题缓存,使下一次 meow_theme_get() 重读 settings.conf(display.theme /
* display.theme_mode / display.theme_dark_start|end)。launcher 在 statusbar 刷新前调用,
* 让 SDK 状态栏(其主题是缓存的)跟手 launcher 侧主题变更,避免「launcher 界面已换肤、
* 状态栏滞留旧主题」。App 无需调用(主题变更本就由 Settings 改 settings.conf,下一个
* set_mode/get 自然读到——缓存仅挡「同会话内 settings 被外部改写」的即时反映)。 */
void meow_theme_reload(void);
/* ---- 渲染后端(meow_ui_gfx.c)提供 ---- */ /* ---- 渲染后端(meow_ui_gfx.c)提供 ---- */
/* 把 RGBA 像素(stb_image 输出,4 通道 straight alpha)blit 进 back_buf; /* 把 RGBA 像素(stb_image 输出,4 通道 straight alpha)blit 进 back_buf;
* alpha 为全局不透明度 0-255(255 时仍用像素自身 alpha 做逐像素混合)。 */ * alpha 为全局不透明度 0-255(255 时仍用像素自身 alpha 做逐像素混合)。 */
+42 -2
View File
@@ -91,11 +91,26 @@ static int settings_vol(void)
return meow_ui_vol_clamp(vol, vol_max); return meow_ui_vol_clamp(vol, vol_max);
} }
/* 亮度:读 settings.conf 的 display.brightness(launcher 同源),并 clamp 到
* [display.brightness_min, 100](与 launcher clamp_brightness 同口径,下限默认 1=极暗非全黑)。
* Stage-One 状态栏收敛(launcher 退役自绘状态栏)后,launcher 侧用 meow_ui_sys_feed() 喂
* 即时值(写入方=launcher);此处兜底让 App(meow_ui_run 的 1s 轻刷)也读到并显示亮度,
* 保证「launcher / App 同一实现、同日/夜」。 */
static int settings_bright(void)
{
int v = meow_ui_vol_read(MEOW_SETTINGS_FILE, "display.brightness", 101);
int mn = meow_ui_vol_read(MEOW_SETTINGS_FILE, "display.brightness_min", 1);
if (v < mn) v = mn;
if (v > 100) v = 100;
return v;
}
int meow_ui_sys_init(void) int meow_ui_sys_init(void)
{ {
memset(&g_sys, 0, sizeof g_sys); memset(&g_sys, 0, sizeof g_sys);
g_sys.batt = -1; g_sys.batt = -1;
g_sys.vol = settings_vol(); g_sys.vol = settings_vol();
g_sys.brightness = settings_bright();
g_statusbar_on = 1; g_statusbar_on = 1;
g_fullscreen = 0; g_fullscreen = 0;
g_statusbar_force = 1; g_statusbar_force = 1;
@@ -117,6 +132,7 @@ void meow_ui_sys_refresh(void)
g_sys.wifi_on = !strcmp(op, "up") ? 1 : 0; g_sys.wifi_on = !strcmp(op, "up") ? 1 : 0;
g_sys.vol = settings_vol(); g_sys.vol = settings_vol();
g_sys.brightness = settings_bright(); /* 兜底读 settings;launcher 喂入会覆盖(更即时) */
/* 蓝牙:hci0 存在性检查便宜;上电状态贵(hciconfig spawn),30s 缓存。 */ /* 蓝牙:hci0 存在性检查便宜;上电状态贵(hciconfig spawn),30s 缓存。 */
static uint64_t last_bt_ms = 0; static uint64_t last_bt_ms = 0;
@@ -136,6 +152,25 @@ void meow_ui_sys_refresh(void)
const meow_sys_state *meow_ui_sys_get(void) { return &g_sys; } const meow_sys_state *meow_ui_sys_get(void) { return &g_sys; }
/* ---- 系统进程(launcher)喂入权威快照(Stage-One 状态栏收敛)----
* launcher 不跑 SDK 事件循环,其 g_sys(meow_sys_refresh/light + 事件路径维护)是权威数据源
* (尤其亮度/音量,写入方=launcher)。此处把它覆盖进 SDK 快照并置 force,驱动下一次
* present() 重画顶条。不喂的字段保持 SDK 现有值(由 meow_ui_sys_refresh 同源兜底)。 */
void meow_ui_sys_feed(const meow_ui_feed *f)
{
if (!f) return;
g_sys.batt = f->batt;
g_sys.charging = f->charging;
g_sys.wifi_on = f->wifi_on;
g_sys.bt_seen = f->bt_seen;
g_sys.bt_on = f->bt_on;
g_sys.vol = f->vol;
if (f->brightness <= 0) g_sys.brightness = 0; /* 未知/屏关:不入顶条(>0 才显示) */
else if (f->brightness > 100) g_sys.brightness = 100;
else g_sys.brightness = f->brightness;
g_statusbar_force = 1; /* 数据已变 → 顶条必重画 */
}
/* ---- 公共 API ---- */ /* ---- 公共 API ---- */
void meow_ui_set_statusbar(int visible) void meow_ui_set_statusbar(int visible)
{ {
@@ -190,20 +225,25 @@ int meow_ui_sys_statusbar_force(void)
return f; return f;
} }
/* 状态栏右侧信息串:batt% WIFI 蓝牙/蓝牙 VOL nn%(同 launcher statusbar_right_str) */ /* 状态栏右侧信息串:batt% WIFI 蓝牙 VOL nn% 亮度nn%(同 launcher 状态栏右侧语义,文本式)。
* mfont 就绪用 CJK「蓝牙/亮度」,否则回退 ASCII "BT/BRI"(28px 栏紧凑,避免超宽叠到时钟)。
* 顺序与 launcher 右侧簇一致:电量 → WiFi → 蓝牙 → 音量 → 亮度。*/
static void statusbar_right_str(char *out, size_t n) static void statusbar_right_str(char *out, size_t n)
{ {
char batt[16] = "", wifi[16] = "", vol[20] = "", bt[16] = ""; char batt[16] = "", wifi[16] = "", vol[20] = "", bt[16] = "", bri[20] = "";
if (g_sys.batt >= 0) snprintf(batt, sizeof batt, "%d%%", g_sys.batt); if (g_sys.batt >= 0) snprintf(batt, sizeof batt, "%d%%", g_sys.batt);
if (g_sys.wifi_on) snprintf(wifi, sizeof wifi, "WIFI"); if (g_sys.wifi_on) snprintf(wifi, sizeof wifi, "WIFI");
snprintf(vol, sizeof vol, "VOL %d%%", g_sys.vol); snprintf(vol, sizeof vol, "VOL %d%%", g_sys.vol);
if (g_sys.bt_seen && g_sys.bt_on) if (g_sys.bt_seen && g_sys.bt_on)
snprintf(bt, sizeof bt, meow_gfx_mfont_ready() ? "蓝牙" : "BT"); snprintf(bt, sizeof bt, meow_gfx_mfont_ready() ? "蓝牙" : "BT");
if (g_sys.brightness > 0) /* >0 才显示(屏常亮态);0=屏关/未知不入 */
snprintf(bri, sizeof bri, meow_gfx_mfont_ready() ? "亮度%d%%" : "BRI %d%%", g_sys.brightness);
out[0] = 0; out[0] = 0;
if (batt[0]) strcat(out, batt); if (batt[0]) strcat(out, batt);
if (wifi[0]) { if (out[0]) strcat(out, " "); strcat(out, wifi); } if (wifi[0]) { if (out[0]) strcat(out, " "); strcat(out, wifi); }
if (bt[0]) { if (out[0]) strcat(out, " "); strcat(out, bt); } if (bt[0]) { if (out[0]) strcat(out, " "); strcat(out, bt); }
if (vol[0]) { if (out[0]) strcat(out, " "); strcat(out, vol); } if (vol[0]) { if (out[0]) strcat(out, " "); strcat(out, vol); }
if (bri[0]) { if (out[0]) strcat(out, " "); strcat(out, bri); }
} }
void meow_ui_sys_statusbar_render(void) void meow_ui_sys_statusbar_render(void)
+2
View File
@@ -27,6 +27,8 @@ typedef struct meow_sys_state {
int bt_seen; /* hci0 节点存在 */ int bt_seen; /* hci0 节点存在 */
int bt_on; /* 实际上电(hciconfig UP) */ int bt_on; /* 实际上电(hciconfig UP) */
int vol; /* 音量 0-100 */ int vol; /* 音量 0-100 */
int brightness; /* 背光/亮度 1-100;只有 >0 才显示(屏常亮态)。由 launcher 喂入
* (launcher 是背光写入/clamp 方),SDK 自己亦用 settings 兜底读。 */
} meow_sys_state; } meow_sys_state;
/* 顶部状态栏几何(与 launcher SB_BAR_H=28 / SB_FONT=20 对齐,视觉统一)。 /* 顶部状态栏几何(与 launcher SB_BAR_H=28 / SB_FONT=20 对齐,视觉统一)。
+9
View File
@@ -11,6 +11,7 @@
* 切换即广播 listener。AUTO 解析只在查询时按当前系统时间计算(不缓存)。 * 切换即广播 listener。AUTO 解析只在查询时按当前系统时间计算(不缓存)。
*/ */
#include "meow_ui.h" #include "meow_ui.h"
#include "meow_ui_internal.h" /* meow_theme_reload() 定义(供 launcher 逼重读 settings) */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -168,6 +169,14 @@ void meow_theme_set_mode(meow_theme_mode m)
broadcast(); broadcast();
} }
/* 重置缓存:下一次 meow_theme_get()/get_mode()/defaults() 重读 settings.conf。
* launcher 在 statusbar 刷新前调用,让 SDK 全局状态栏(其主题缓存于 g_loaded)跟手
* launcher 侧主题变更(settings.conf 被改后立即反映),避免「界面已换肤、状态栏滞留旧主题」。 */
void meow_theme_reload(void)
{
g_loaded = 0;
}
meow_theme meow_theme_defaults(meow_theme_mode m) meow_theme meow_theme_defaults(meow_theme_mode m)
{ {
switch (resolve_mode(m)) { switch (resolve_mode(m)) {