基座+设计文档(三特性): meow_ui.h 字体档/状态栏收合API + launcher fonts/fullscreen解析+env注入+通知dump钩子 + meow_ui_gfx.c 收合渲染+字体档; spec-ref/SYSTEM_SETTINGS/APPS/NOTIFICATION 三特性设计落档

This commit is contained in:
MeowOS Dev committed 2026-08-30 11:28:11 +08:00
1 parent 318e6ec7c1
commit 20c7c8dbbd
2 files changed
+166 -5

No files matched your search

+39
View File
@@ -175,6 +175,24 @@ void meow_ui_set_fullscreen(int on);
* 全屏/隐藏时返回 0。 */
int meow_ui_statusbar_height(void);
/* ---- 状态栏「上收出屏只留提示线」(collapsed,草案/待定案——本批仅加声明)----
* 供全屏调用:把状态栏内容上移出屏顶、只留一条「提示线」高度(可下拉还原)。
* 与 meow_ui_set_fullscreen(1) 的关系:fullscreen 隐藏整条状态栏(沉浸,inset=0);
* collapsed 仍视状态栏为「激活」,左缘返回手势(SWIPE_LEFT)与顶部伸缩提示线
* (meow_ui_swipe_hint)依旧生效,只是其内容上收、仅留提示线——用于「不完全沉浸」,
* 保留一处可下拉拉出状态栏的入口。顶部下滑热区 meow_ui_statusbar_hotzone() 在全屏时缩小。
* 实现位置:meow_ui_gfx.c(基座让 on 生效:true→只画提示线/内容上移);逐帧过渡动画
* (上收/恢复插值)为待定案,后续代理可经 meow_ui_statusbar_animate(ms) 补齐。 */
void meow_ui_statusbar_set_collapsed(int on); /* on=1 上收(内容上移出屏、只留提示线);on=0 恢复 */
int meow_ui_statusbar_collapsed(void); /* 当前是否处于「上收」目标(1=是) */
void meow_ui_statusbar_animate(int ms); /* TBD:上收/恢复过渡时长(ms);占位,后续代理实现插值 */
/* 顶部下滑热区(下拉展开状态栏/通知)高度(px)。
* 非全屏=整条状态栏可视高度;全屏时缩小到 MEOW_SBAR_HOTZONE_FS(保留一处下拉入口)。
* 返回「可用于起始下拉」的热区高度;由输入层/后续代理据此判定下拉起点。 */
int meow_ui_statusbar_hotzone(void);
#define MEOW_SBAR_HOTZONE_FS 4 /* 全屏时缩小后的顶部热区高度(px,草案值) */
/* ============================================================ */
/* §7 动画/时间(B1 最小可用) */
/* ============================================================ */
@@ -309,6 +327,27 @@ int meow_notify_has_active(void); /* 1=尚有活动通知,0=无 *
const char *meow_notify_urgency_str(meow_notify_urgency u);
const char *meow_notify_category_str(meow_notify_category cat);
/* ============================================================ */
/* §10 字体分层 / 大字库(草案/待定案 —— 本批仅加声明/枚举/宏,不实现) */
/* ============================================================ */
/* 字体「档位」概念:launcher 按 app.json 声明的字库档("fonts":<档>)向 app 注入
* MEOW_FONT_TIER=<0|1|2>;SDK(meow_ui_gfx / 后续 meow_font 大字库加载)据档选库:
* MEOW_FONT_TIER_COMMON=0 默认 4K 常用字库;
* MEOW_FONT_TIER_GBK =1 大字库 GBK;
* MEOW_FONT_TIER_FULL =2 Full(全字符集)。
* 后续 font 域代理据此在 meow_font.c / gen_font.py 实现大字库生成与按档装载。
* 既有 meow_font_* 符号(class_of/has_glyph/load_slot/config_multifont…)保留不动;
* 大字库装载以 set_tier/tier 作为入口,或由后续代理按 meow_font_config_multifont 扩展。 */
#define MEOW_FONT_TIER_COMMON 0
#define MEOW_FONT_TIER_GBK 1
#define MEOW_FONT_TIER_FULL 2
/* 设当前字体档(0/1/2,越界 clamp 到合法值),返回生效档。
* 基座在 meow_ui_gfx.c 定义(只存档 + 触发重载请求);真正按档装载大字库由后续 font 代理实现。 */
int meow_font_set_tier(int tier);
/* 当前字体档(初始 = MEOW_FONT_TIER_COMMON;meow_ui_init 时读 MEOW_FONT_TIER env 对齐)。 */
int meow_font_tier(void);
#ifdef __cplusplus
}
#endif
+127 -5
View File
@@ -63,6 +63,24 @@ static int g_dirty_full = 1;
static char *g_dump_path = NULL;
/* ---- 状态栏「上收出屏只留提示线」(collapsed,基座)----
* g_sbar_collapsed = 目标态(1=上收);g_sbar_collapse_h = 当前实际上收偏移
* (0..MUI_SBAR_H:0=完全展开,MUI_SBAR_H=内容全部上移出屏、仅留提示线)。
* 基座让 meow_ui_statusbar_set_collapsed(on) 立即生效(true→只画提示线/内容上移);
* 过渡(每帧插值)留待后续代理或经 meow_ui_statusbar_animate(ms) 启用的简易线性逼近。 */
#define MUI_SBAR_HINT_H 6 /* 上收状态下顶部提示线高(px) */
static int g_sbar_collapsed = 0; /* 目标:1=上收 */
static int g_sbar_collapse_h = 0; /* 当前上收偏移(0..MUI_SBAR_H) */
static int g_sbar_collapse_anim_ms = 0; /* 过渡时长(0=瞬切);meow_ui_statusbar_animate 设置 */
static int g_sbar_collapse_from_h = 0; /* 本次过渡起点偏移 */
static unsigned long long g_sbar_collapse_start_ms = 0; /* 本次过渡起始(monotonic ms) */
/* ---- 字体档位(MEOW_FONT_TIER,基座存档 + 公共 get/set)----
* launcher 按 app.json "fonts":<档> 注入 MEOW_FONT_TIER=<0|1|2>;SDK 读入并以
* meow_font_set_tier/tier 暴露。真正按档装载大字库(GBK/Full)由后续 font 代理在
* meow_font.c / meow_gfx_load_multifont 挂钩实现——此处仅记录档位不换库。 */
static int g_font_tier = MEOW_FONT_TIER_COMMON;
/* ---- 帧率调度(A-1/A-2:从 launcher M2.16 迁入,刷新率调度归口 SDK)----
* meow_ui_flush()/present() 的 fps 档位与自适应降档 governor。launcher 不再自带
* 一套帧率门控;launcher 与 app 统一走这里 → 全局观感/刷新率一致。
@@ -499,6 +517,71 @@ static void dump_ppm(void)
fclose(f);
}
/* ================= 状态栏「上收出屏只留提示线」(collapsed,基座) ================= */
/* 每帧推进上收/恢复:向目标偏移(collapsed→MUI_SBAR_H、否则→0)线性逼近;
* 无过渡时长(g_sbar_collapse_anim_ms<=0)= 一步到位(基座默认)。动画插值骨架在此,
* 后续代理可换缓动/每帧步进。 */
static void statusbar_collapse_step(void)
{
int tgt = g_sbar_collapsed ? MUI_SBAR_H : 0;
if (g_sbar_collapse_h == tgt) return;
if (g_sbar_collapse_anim_ms <= 0) { g_sbar_collapse_h = tgt; return; }
unsigned long long now = now_ms();
unsigned long long el = now - g_sbar_collapse_start_ms;
int span = g_sbar_collapse_anim_ms;
if ((int)el >= span) { g_sbar_collapse_h = tgt; return; }
int delta = tgt - g_sbar_collapse_from_h;
g_sbar_collapse_h = g_sbar_collapse_from_h +
(int)((long long)delta * (long long)el / (long long)span);
}
/* 上收中是否需要逐帧重画(动画未达目标位置时置位,强制每帧推进)。 */
static int statusbar_collapse_in_transition(void)
{
int tgt = g_sbar_collapsed ? MUI_SBAR_H : 0;
return g_sbar_collapse_h != tgt;
}
/* 上收状态栏:内容整体上移出屏(不画时钟/电量),仅在顶部画一条「提示线」。
* 与 meow_ui_swipe_hint(左滑返回进度条,5px,动态)不同:此线是「状态栏可下拉还原」的
* 常驻提示(主题强调色下边缘)。原状态栏整块清回主题背景,避免残影(app inset 之内)。 */
static void statusbar_collapsed_render(int h)
{
(void)h;
const meow_theme *th = meow_theme_get();
int w = meow_ui_width();
/* h 越大内容越贴顶;基座:折叠态整块清底 + 顶部提示线(提示线下缘=主题 accent) */
meow_ui_fill_rect(0, 0, w, MUI_SBAR_H, th->bg);
meow_ui_fill_rect(0, MUI_SBAR_HINT_H - 1, w, 1, th->accent);
}
/* ---- 公共 API(基座实现;动画插值骨架见 statusbar_collapse_step)---- */
void meow_ui_statusbar_set_collapsed(int on)
{
int tgt = on ? 1 : 0;
if (tgt == g_sbar_collapsed) return;
g_sbar_collapsed = tgt;
g_sbar_collapse_from_h = g_sbar_collapse_h;
g_sbar_collapse_start_ms = now_ms();
dirty_full(); /* 顶栏显隐/上收变化 → 全帧重画 */
}
int meow_ui_statusbar_collapsed(void) { return g_sbar_collapsed; }
void meow_ui_statusbar_animate(int ms)
{
g_sbar_collapse_anim_ms = (ms > 0) ? ms : 0; /* 0=瞬切(基座默认) */
}
int meow_ui_statusbar_hotzone(void)
{
/* 非全屏=整条状态栏可视;全屏时缩小到 MEOW_SBAR_HOTZONE_FS(保留一处下拉入口)。
* 上收(collapsed、非全屏)时热区=提示线下缘高度。全屏态由 meow_ui_sys 维护。 */
if (meow_ui_sys_statusbar_active())
return g_sbar_collapsed ? MUI_SBAR_HINT_H : MUI_SBAR_H;
return MEOW_SBAR_HOTZONE_FS;
}
/* 顶部状态栏条是否被本次脏区触及(含整帧):触及或数据已变(force)才需要重画顶条。 */
static int statusbar_touched(void)
{
@@ -519,13 +602,20 @@ static void present(void)
if (!g_refresh_always_max) {
if (g_last_present_ms && now - g_last_present_ms < (unsigned long long)period) return;
}
/* 全局状态栏(A-0):上屏前把状态栏画进 back_buf 顶部 MUI_SBAR_H 行(z 最顶)。
/* 全局状态栏(A-0)+ 上收(collapsed)基座:上屏前把状态栏画进 back_buf 顶部 MUI_SBAR_H 行。
* 全屏/隐藏时 active()==0 不画(沉浸),app 内容可占满整屏。触发条件:
* 数据已变(1s 轻刷/显隐切换) 或 顶条被 app 内容触及(含整帧清+绘,未 inset 时被顶条覆盖)。
* 无需每帧重画——app 局部刷新不触及顶条时,back_buf/screen 顶条保持不变,省一次 blit。 */
* 数据已变(1s 轻刷/显隐切换) / 顶条被 app 内容触及 / 上收动画未到位(逐帧推进)。
* 展开态仍走 meow_ui_sys_statusbar_render()(meow_ui_sys.c 不改,留给后续代理);
* 上收折叠态(collapse_h>=MUI_SBAR_H)由基座只画提示线(内容上移出屏)。 */
if (meow_ui_sys_statusbar_active() &&
(meow_ui_sys_statusbar_force() || statusbar_touched()))
meow_ui_sys_statusbar_render();
(meow_ui_sys_statusbar_force() || statusbar_touched() ||
statusbar_collapse_in_transition())) {
statusbar_collapse_step();
if (g_sbar_collapse_h >= MUI_SBAR_H)
statusbar_collapsed_render(g_sbar_collapse_h);
else
meow_ui_sys_statusbar_render();
}
if (g_fb_mem) {
ioctl(g_fb_fd, FBIO_WAITFORVSYNC, 0); /* 等垂直同步 */
unsigned long long tbg = now_ms();
@@ -575,6 +665,23 @@ unsigned long long meow_ui_frames_presented(void) { return g_frames_presented; }
int meow_gfx_is_device(void) { return g_fb_mem != NULL; }
int meow_gfx_mfont_ready(void) { return g_mfont_ready; }
/* ---- 字体档位(公共 API,基座定义)----
* 注意:meow_font_tier()/meow_font_set_tier() 已在 meow_ui_gfx.c 定义(符号唯一),
* 后续 font 代理勿在 meow_font.c 重复定义;可在 meow_font.c 实现「按档装载大字库」并在
* meow_font_set_tier 的钩子处唤起(见下)。 */
int meow_font_tier(void) { return g_font_tier; }
int meow_font_set_tier(int tier)
{
if (tier < MEOW_FONT_TIER_COMMON) tier = MEOW_FONT_TIER_COMMON;
if (tier > MEOW_FONT_TIER_FULL) tier = MEOW_FONT_TIER_FULL;
if (tier == g_font_tier) return g_font_tier;
g_font_tier = tier;
/* TBD(基座):真正按档装载大字库(meow_font_load_tier 或 config_multifont 扩展)由
* 后续 font 代理在 meow_font.c 实现;此处仅记录档位 + 标记重载(下一轮 load 读 tier)。 */
return g_font_tier;
}
/* ================= 初始化/销毁 ================= */
/* 字库加载优先级(M2.x):
* 1) 环境变量 MEOW_FONT_PNG/MEOW_FONT_IDX(launcher 注入的「当前生效字体」= 系统 font.file)
@@ -584,6 +691,16 @@ int meow_gfx_mfont_ready(void) { return g_mfont_ready; }
* 全失败 → g_mfont_ready=0,text_draw 回退 5x7 点阵(系统不死)。 */
static int load_font(void)
{
/* 字体档位(MEOW_FONT_TIER env,由 launcher 按 app.json "fonts" 注入):
* 0=默认4K常用 1=大字库GBK 2=Full。基座只读入存档 + 对齐公共 get/set;
* 真正按档装载大字库(GBK/Full 的字库路径/面)由后续 font 代理在 meow_font.c /
* meow_gfx_load_multifont 挂钩实现——此处仍先装载默认(tier0)字库,档位仅记录。 */
const char *etr = getenv("MEOW_FONT_TIER");
if (etr && etr[0]) {
g_font_tier = atoi(etr);
if (g_font_tier < MEOW_FONT_TIER_COMMON) g_font_tier = MEOW_FONT_TIER_COMMON;
if (g_font_tier > MEOW_FONT_TIER_FULL) g_font_tier = MEOW_FONT_TIER_FULL;
}
const char *ep = getenv("MEOW_FONT_PNG");
const char *ei = getenv("MEOW_FONT_IDX");
if (ep && ep[0] && ei && ei[0] && meow_font_load(ep, ei) == 0) return 1;
@@ -677,6 +794,11 @@ int meow_ui_init(const meow_ui_opts *opts)
g_init_ok = 1;
dirty_full();
meow_ui_sys_init(); /* A-0:系统状态读取器首刷(电量/WiFi/蓝牙/音量),状态栏就绪 */
/* 全屏预置(基座):launcher 按 app.json "fullscreen" 注入 MEOW_FULLSCREEN=1,SDK 据此
* 预先设全屏(隐藏整条状态栏/沉浸,statusbar_active()==0、statusbar_height()==0)。
* 未注入/非"1"=非全屏(默认)。放在 sys_init 后使首帧即为全屏态。 */
const char *efs = getenv("MEOW_FULLSCREEN");
if (efs && efs[0] == '1') meow_ui_set_fullscreen(1);
return 0;
}