基座+设计文档(三特性): meow_ui.h 字体档/状态栏收合API + launcher fonts/fullscreen解析+env注入+通知dump钩子 + meow_ui_gfx.c 收合渲染+字体档; spec-ref/SYSTEM_SETTINGS/APPS/NOTIFICATION 三特性设计落档
This commit is contained in:
1 parent
9b8a1e5c8b
commit
0b4d1d3215
8 files changed
+297
-25
No files matched your search
Binary file not shown.
@@ -915,6 +915,20 @@ static int meow_font_effective_paths(char *out_png, int plen, char *out_idx, int
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 【tier 选择入口,font 域占位】按字体档位取「当前生效字体」png/idx,供 launch_app 注入
|
||||
* MEOW_FONT_PNG/IDX/APP(配合 MEOW_FONT_TIER)。基座只实现 tier=COMMON(=meow_font_effective_paths);
|
||||
* tier>0 的大字库(GBK/Full)绝对路径由后续 font 代理据此演进填充(约定 MeowOS/fonts/<family>/
|
||||
* <tier>/…,或 settings 键 font.tier_gbk / font.tier_full —— 见 MEOW_APP_SDK.md 字体分层)。
|
||||
* 未实现前暂回退全局字体。返回 0 成功,-1 无可用。 */
|
||||
static int meow_font_effective_paths_tiered(int tier, char *out_png, int plen,
|
||||
char *out_idx, int ilen, char *out_family, int flen)
|
||||
{
|
||||
if (tier == MEOW_FONT_TIER_COMMON || tier < MEOW_FONT_TIER_COMMON)
|
||||
return meow_font_effective_paths(out_png, plen, out_idx, ilen, out_family, flen);
|
||||
/* TODO(font 代理):按 tier 解析大字库绝对路径(GBK/Full);暂回退全局(tier0)。 */
|
||||
return meow_font_effective_paths(out_png, plen, out_idx, ilen, out_family, flen);
|
||||
}
|
||||
|
||||
/* M2.5x 多字体:从 settings 读 display.multi_font + 6 类 font.class_*,把各自相对路径按卡根
|
||||
* 解析为绝对路径,去重装载到 meow_font 槽位(同 family 去重 & ≤4 套上限由
|
||||
* meow_font_config_multifont 统一处理)。仅当全局字库已装载(mfont_ready / slot0)时生效;
|
||||
@@ -1308,6 +1322,7 @@ struct meow_route {
|
||||
char act[16]; /* route 键后缀,如 "nowplaying" */
|
||||
char chain[MEOW_CHAIN_MAX]; /* 如 "home;search;nowplaying" */
|
||||
int keep_awake; /* M2.17:该 activity 常亮(app.json awake.<id>=1 / route.<id>.keep_awake=1) */
|
||||
int fullscreen; /* 活动级全屏声名(app.json route.<id>.fullscreen=1;M3 活动切换时消费) */
|
||||
};
|
||||
|
||||
/* 服务行:service.<svc>=mode:restart:max:window_ms(M1 仅解析存储,M4 保活) */
|
||||
@@ -1328,6 +1343,8 @@ struct app {
|
||||
/* ---- 阶段 D · M1:app.json 路由/框架/服务/图标(scan_apps 解析)---- */
|
||||
char framework; /* '1'=framework=true(看门狗返回发 SIGUSR1) */
|
||||
char immersive; /* '1'=immersive=true(隐藏虚拟返回键,返回手势归 SDK) */
|
||||
char fullscreen; /* '1'=app.json fullscreen=true(注入 MEOW_FULLSCREEN=1,SDK 预先设全屏) */
|
||||
char fonts; /* 字库档:0=默认4K常用 1=大字库GBK 2=Full(app.json "fonts";注入 MEOW_FONT_TIER) */
|
||||
char icon[129]; /* icon= 路径 */
|
||||
int nroute; /* route.<id> 行数 */
|
||||
struct meow_route routes[MEOW_MAX_ROUTES];
|
||||
@@ -1805,6 +1822,8 @@ static void meow_parse_app_json(FILE *f, struct app *a)
|
||||
char name[17] = "", exec[129] = "", icon[129] = "";
|
||||
char package[MEOW_APP_ID_MAX] = "";
|
||||
int fram = 0, immersive = 0;
|
||||
int fullscreen = 0; /* app.json fullscreen=<true|1>(注入 MEOW_FULLSCREEN env,SDK 预先设全屏) */
|
||||
int fonts = 0, fonts_set = 0; /* app.json "fonts":<档>(0=默认4K常用 1=大字库GBK 2=Full;缺省 0) */
|
||||
struct app tmp;
|
||||
memset(&tmp, 0, sizeof tmp);
|
||||
while (fgets(buf, sizeof buf, f)) {
|
||||
@@ -1816,8 +1835,8 @@ static void meow_parse_app_json(FILE *f, struct app *a)
|
||||
char *rp = strstr(buf, "route.");
|
||||
if (rp && tmp.nroute < MEOW_MAX_ROUTES) {
|
||||
rp += 6; /* 跳过 "route." */
|
||||
int idl = 0; char id[16] = "";
|
||||
while (*rp && *rp != '"' && *rp != ':' && *rp != '=' && idl < 15)
|
||||
int idl = 0; char id[32] = ""; /* 读满整键(识别 ".fullscreen" 后缀,cap 31) */
|
||||
while (*rp && *rp != '"' && *rp != ':' && *rp != '=' && idl < 31)
|
||||
id[idl++] = *rp++;
|
||||
id[idl] = 0;
|
||||
if (idl > 0) {
|
||||
@@ -1826,16 +1845,30 @@ static void meow_parse_app_json(FILE *f, struct app *a)
|
||||
if (*vp == ':' || *vp == '=') vp++;
|
||||
while (*vp == ' ' || *vp == '\t') vp++;
|
||||
if (*vp == '"') vp++;
|
||||
int vl = 0; char chain[MEOW_CHAIN_MAX] = "";
|
||||
while (*vp && *vp != '"' && *vp != ',' && *vp != '\n' &&
|
||||
*vp != '\r' && vl < MEOW_CHAIN_MAX - 1)
|
||||
chain[vl++] = *vp++;
|
||||
chain[vl] = 0;
|
||||
while (vl > 0 && (chain[vl - 1] == ' ' || chain[vl - 1] == '\t'))
|
||||
chain[--vl] = 0;
|
||||
strncpy(tmp.routes[tmp.nroute].act, id, 15);
|
||||
strncpy(tmp.routes[tmp.nroute].chain, chain, MEOW_CHAIN_MAX - 1);
|
||||
tmp.nroute++;
|
||||
/* route.<id>.fullscreen=<on>:活动级全屏声明(M1 顺带;M3 活动切换时消费)。
|
||||
* 命中既有 route.<id> 置 fullscreen;不新建 route(避免 id 被截断误建 "…fulls")。 */
|
||||
if (idl >= 11 && !strcmp(id + idl - 11, ".fullscreen")) {
|
||||
id[idl - 11] = 0; /* 去掉 ".fullscreen" 还原 act */
|
||||
char v[8] = ""; int k = 0;
|
||||
while (*vp && *vp != '"' && *vp != ',' && *vp != '\n' &&
|
||||
*vp != '\r' && k < 7) v[k++] = *vp++;
|
||||
v[k] = 0;
|
||||
int on = (!strcmp(v, "1") || !strcmp(v, "true") || !strcmp(v, "yes"));
|
||||
for (int i = 0; i < tmp.nroute; i++)
|
||||
if (!strcmp(tmp.routes[i].act, id)) { tmp.routes[i].fullscreen = on; break; }
|
||||
} else {
|
||||
int vl = 0; char chain[MEOW_CHAIN_MAX] = "";
|
||||
while (*vp && *vp != '"' && *vp != ',' && *vp != '\n' &&
|
||||
*vp != '\r' && vl < MEOW_CHAIN_MAX - 1)
|
||||
chain[vl++] = *vp++;
|
||||
chain[vl] = 0;
|
||||
while (vl > 0 && (chain[vl - 1] == ' ' || chain[vl - 1] == '\t'))
|
||||
chain[--vl] = 0;
|
||||
strncpy(tmp.routes[tmp.nroute].act, id, 15);
|
||||
tmp.routes[tmp.nroute].act[15] = 0; /* 显式收尾(原依赖 id 读长 ≤15) */
|
||||
strncpy(tmp.routes[tmp.nroute].chain, chain, MEOW_CHAIN_MAX - 1);
|
||||
tmp.nroute++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* awake.<id>=1(M2.17 keep_awake:该 activity 常亮,超时不自动息屏)。
|
||||
@@ -1881,6 +1914,29 @@ static void meow_parse_app_json(FILE *f, struct app *a)
|
||||
immersive = 1;
|
||||
}
|
||||
}
|
||||
/* fullscreen=true(app 级:注入 MEOW_FULLSCREEN=1,SDK 端 meow_ui_init 预先设全屏)。
|
||||
* 与 immersive 是两回事:fullscreen 隐藏状态栏/沉浸,immersive 关虚拟返回键。 */
|
||||
if (!fullscreen && strstr(buf, "fullscreen")) {
|
||||
char v[8] = "";
|
||||
if (json_str(buf, "fullscreen", v, sizeof v) > 0) {
|
||||
if (!strcmp(v, "true") || !strcmp(v, "1") || !strcmp(v, "yes"))
|
||||
fullscreen = 1;
|
||||
}
|
||||
}
|
||||
/* "fonts":<档>(字库档:0=默认4K常用 1=大字库GBK 2=Full;可选,缺省 0)。
|
||||
* launcher 注入 MEOW_FONT_TIER;大字库装载由后续 font 代理实现。 */
|
||||
if (!fonts_set && strstr(buf, "fonts")) {
|
||||
char v[8] = "";
|
||||
if (json_str(buf, "fonts", v, sizeof v) > 0) {
|
||||
if (!strcmp(v, "common") || !strcmp(v, "0")) fonts = 0;
|
||||
else if (!strcmp(v, "gbk") || !strcmp(v, "1")) fonts = 1;
|
||||
else if (!strcmp(v, "full") || !strcmp(v, "2")) fonts = 2;
|
||||
else fonts = atoi(v); /* 数字兜底(越界收敛到 [0,2]) */
|
||||
if (fonts < 0) fonts = 0;
|
||||
if (fonts > 2) fonts = 2;
|
||||
fonts_set = 1;
|
||||
}
|
||||
}
|
||||
/* service.<svc>=mode:restart:max:window_ms(M1 解析存储,保活 M4) */
|
||||
char *sp = strstr(buf, "service.");
|
||||
if (sp && tmp.nsvc < MEOW_MAX_SVCS) {
|
||||
@@ -1911,6 +1967,8 @@ static void meow_parse_app_json(FILE *f, struct app *a)
|
||||
strncpy(a->package, package, sizeof a->package - 1);
|
||||
a->framework = fram ? '1' : 0;
|
||||
a->immersive = immersive ? '1' : 0;
|
||||
a->fullscreen = fullscreen ? '1' : 0; /* 注入 MEOW_FULLSCREEN env */
|
||||
a->fonts = (char)(fonts < 0 ? 0 : (fonts > 2 ? 2 : fonts)); /* 注入 MEOW_FONT_TIER env */
|
||||
strncpy(a->icon, icon, 128);
|
||||
a->nroute = tmp.nroute;
|
||||
if (tmp.nroute) memcpy(a->routes, tmp.routes, sizeof(a->routes[0]) * (size_t)tmp.nroute);
|
||||
@@ -2263,6 +2321,19 @@ static void settings_sync_cache_listener(const char *key)
|
||||
else if (!strcmp(key, "power.forceoff_ms")) { int v; if (meow_settings_get_int("power.forceoff_ms", &v) == 0) power_forceoff_ms = v; }
|
||||
}
|
||||
|
||||
/* ---- 通知 dump 回调占位(通知#6 转储 TF 卡;接线/占位,不做 TF 写)----
|
||||
* meow_notif 在 TTL 到点(meow_notif_tick,§8 10s)调用此回调归档一条通知,随后释放槽。
|
||||
* 基座只把回调挂上来(见 settings_load 的 meow_notif_set_dump_cb);真实 TF 落盘
|
||||
* (按 NOTIFICATION_SYSTEM.md §8 / TF_CARD_LAYOUT.md 写 <卡>/MeowOS/notify/...)由后续
|
||||
* 通知代理在回调体内实现。注意 meow_notif.c 的 archive_one 自身已 log 一行 "dump: ...",
|
||||
* 故本回调保持轻量(避免重复刷屏),落盘逻辑填在下方 TODO 处。 */
|
||||
static void notif_dump_tf_placeholder(const meow_notif_t *n)
|
||||
{
|
||||
(void)n;
|
||||
/* TODO(通知代理, M2c):在此写 TF 卡 <MeowOS>/notify/<date>/<id>.json 等;
|
||||
* 基座不实现,仅保留挂接点(触发时机=meow_notif_tick 内 10s 到点/止机转储)。 */
|
||||
}
|
||||
|
||||
/* 启动加载(M2.11/M2.24):统一由 meow_settings 后端读 settings.conf;
|
||||
* 此处仅注册监听(一次性)+ 把 backend 当前值同步到缓存全局。重载(应用期
|
||||
* watchdog 可能改音量)等价于 meow_settings_init() + 手动同步。 */
|
||||
@@ -2271,6 +2342,7 @@ static void settings_load(void)
|
||||
{
|
||||
meow_settings_init(); /* 幂等:注册默认 + 读 settings.conf */
|
||||
meow_notif_init(); /* M2a:通知存储初始化(幂等,读 notify.* 配额) */
|
||||
meow_notif_set_dump_cb(notif_dump_tf_placeholder); /* 基座(通知#6):挂 dump 回调(TF 转储占位,M2c 落盘由后续代理实现) */
|
||||
if (!settings_cache_registered) {
|
||||
meow_settings_add_listener(settings_sync_cache_listener);
|
||||
settings_cache_registered = 1;
|
||||
@@ -6732,8 +6804,10 @@ static int launch_app(struct app *a)
|
||||
char env_app[MEOW_APP_ID_MAX + 16], env_lvl[48];
|
||||
char env_fpng[400], env_fidx[400], env_fapp[96];
|
||||
char env_mf[24];
|
||||
char env_tier[24];
|
||||
char env_fs[20];
|
||||
char env_cls[MEOW_FCLS_COUNT][2][400];
|
||||
char *envp[32]; /* PATH,HOME,log_dir,log_app,log_lvl,font 全局(3),多字体(1),class(≤12),data,cache */
|
||||
char *envp[40]; /* PATH,HOME,log_dir,log_app,log_lvl,font 全局(3),多字体(1),tier(1),class(≤12),fullscreen(1),data,cache */
|
||||
int ne = 0;
|
||||
const char *cp = getenv("PATH");
|
||||
snprintf(env_path, sizeof env_path, "PATH=%s", cp ? cp : "/usr/bin:/bin");
|
||||
@@ -6772,8 +6846,13 @@ static int launch_app(struct app *a)
|
||||
meow_settings_get_bool("display.multi_font", &mf_on);
|
||||
snprintf(env_mf, sizeof env_mf, "MEOW_MULTI_FONT=%d", mf_on ? 1 : 0);
|
||||
envp[ne++] = env_mf;
|
||||
have_global = (meow_font_effective_paths(fpng, sizeof fpng, fidx, sizeof fidx,
|
||||
fam, sizeof fam) == 0);
|
||||
/* M2.x(基座):字库档 MEOW_FONT_TIER=<0|1|2> —— 按 app.json "fonts" 声明注入;
|
||||
* 0=默认4K常用(未声明/缺省),1=大字库GBK,2=Full。SDK meow_ui_gfx 读入存档,
|
||||
* 真正按档装载大字库由后续 font 代理实现(见 meow_font_effective_paths_tiered)。 */
|
||||
snprintf(env_tier, sizeof env_tier, "MEOW_FONT_TIER=%d", a->fonts);
|
||||
envp[ne++] = env_tier;
|
||||
have_global = (meow_font_effective_paths_tiered(a->fonts, fpng, sizeof fpng,
|
||||
fidx, sizeof fidx, fam, sizeof fam) == 0);
|
||||
if (have_global) {
|
||||
snprintf(env_fpng, sizeof env_fpng, "MEOW_FONT_PNG=%s", fpng);
|
||||
snprintf(env_fidx, sizeof env_fidx, "MEOW_FONT_IDX=%s", fidx);
|
||||
@@ -6801,6 +6880,14 @@ static int launch_app(struct app *a)
|
||||
envp[ne++] = env_cls[c][1];
|
||||
}
|
||||
}
|
||||
/* 全屏声明:app.json "fullscreen"(app 级)→ 注入 MEOW_FULLSCREEN=1,SDK 端
|
||||
* meow_ui_init 据此预先设全屏。基座只接 app 级;活动级 route.<id>.fullscreen
|
||||
* (meow_route.fullscreen)在 M3 活动切换时由后续代理消费(此处暂不下发)。
|
||||
* 未声明则不注入(SDK 默认非全屏)。 */
|
||||
if (a->fullscreen) {
|
||||
snprintf(env_fs, sizeof env_fs, "MEOW_FULLSCREEN=1");
|
||||
envp[ne++] = env_fs;
|
||||
}
|
||||
char pkg[64];
|
||||
if (meow_pkg_name(a->exec, pkg, sizeof pkg) == 0) {
|
||||
snprintf(env_data, sizeof env_data, "MEOW_DATA_DIR=/usr/data/mnt/sd_0/MeowData/%s/data", pkg);
|
||||
|
||||
Reference in new issue
Block a user