WIP checkpoint (M2.53→M2.54 工作区): 字体归MeowOS/fonts+SDK跟随+多字体(进行中)+boot板载+状态栏28+亮度/音量修复+文档刷新

This commit is contained in:
MeowOS Dev committed 2026-08-30 03:27:24 +08:00
1 parent 245bee2946
commit 064635b3c4
44 files changed
+2834 -308

No files matched your search

+62 -16
View File
@@ -12,15 +12,20 @@
* (替换);媒体类型单例(每 app 仅保留最近 1 条,重发替换——可多媒体 App)。
* - 超时语义 [实现定案]:timeout_ms > 0 为该毫秒数后过期;0 = 不自动过期(直到
* meow_notify_cancel);-1 = 常驻(ONGOING),同样不自动过期。
* - 落点:本阶段内部维护活动通知表 + 用既有 meow_log() 打日志作为落点;真实投递到
* 通知中心 UI / D-Bus 是后续任务——meow_notify 结构已对齐 freedesktop 字段
* (summary/body/…)为此预留,但不写死后端。
* - 落点(任务 #5 SDK↔IPC 桥):本表登记后,经 IPC 把 MSG_NOTIFY(0x0020) 送到
* launcher 中央存储(meow_notif.c 的 meow_notif_post),回读 MSG_NOTIFY_ACK(0x0021)
* 取 launcher 分配的通知 id(nid,存进 slot->ipc_id,供后续 replaces_id/dismiss 用)。
* 通知中心 UI / D-Bus / TF 转储由 launcher 侧处理;SDK 本地活动表保留(app 进程内
* 即时查询/配额自检)。无 socket/写失败/超时 → 优雅降级(保留本地 id 兜底,不崩)。
* meow_notify 结构已对齐 freedesktop 字段(summary/body/…)为此预留。
*
* 线程安全:pthread_mutex(同 meow_ui_log.c,launcher 前后台进程都会在已链 -lpthread
* 的应用里调用)。不依赖 /dev/fb0、不依赖板子,可宿主编译。内部只复用
* meow_ui_time_ms()(单调毫秒)与 meow_log()(统一日志)两个既有 SDK 能力。
* 的应用里调用),且 IPC 发送/读 ACK 在持锁之外进行(避免 socket I/O 阻塞其它查询)。
* 不依赖 /dev/fb0、不依赖板子,可宿主编译。内部只复用 meow_ui_time_ms()(单调毫秒)、
* meow_log()(统一日志)与 meow_notify_ipc_*(IPC 桥,纯传输层)三个既有/新增 SDK 能力。
*/
#include "meow_ui.h"
#include "meow_notify_ipc.h" /* 任务 #5:通知 → launcher 中央存储的 IPC 桥(映射+传输) */
#include <stdio.h>
#include <string.h>
@@ -32,7 +37,8 @@
/* 活动通知槽(内部;标题/正文等复制副本,不持 app 外部指针,避免栈字符串悬垂) */
typedef struct {
uint32_t id; /* 唯一 id;0=空闲槽 */
uint32_t id; /* 本地唯一 id(app 侧句柄);0=空闲槽 */
uint32_t ipc_id; /* launcher 中央存储分配的通知 id(nid);0=未同步/降级 */
int active; /* 1=活动(未取消未过期),0=空闲 */
meow_notify_category cat;
meow_notify_urgency urg;
@@ -85,6 +91,7 @@ static void notify_purge_expired(void)
if (s->timeout_ms > 0 && (now - s->created_ms) >= (uint64_t)s->timeout_ms) {
s->active = 0;
s->id = 0;
s->ipc_id = 0;
}
}
}
@@ -93,6 +100,7 @@ static void notify_purge_expired(void)
static void notify_fill(notify_slot_t *s, const meow_notify *n, uint32_t id, uint64_t now)
{
s->id = id;
s->ipc_id = 0; /* 初值=未同步;发送后由 notify_deliver 回填 launcher 分配的 nid */
s->active = 1;
s->cat = n->cat;
s->urg = ((int)n->urgency >= 0 && (int)n->urgency < (int)MEOW_NOTIFY_URG_COUNT)
@@ -106,12 +114,23 @@ static void notify_fill(notify_slot_t *s, const meow_notify *n, uint32_t id, uin
s->progress = (n->progress < -1) ? -1 : (n->progress > 100 ? 100 : n->progress);
}
/* 落点:本阶段用统一日志标出一条投递;真实后端(通知中心 UI / D-Bus)后续替换此处。 */
static void notify_deliver(const notify_slot_t *s, const char *ev)
/* 落点(任务 #5):把通知经 IPC MSG_NOTIFY(0x0020) 送到 launcher 中央存储
* (meow_notif.c 的 meow_notif_post),回读 MSG_NOTIFY_ACK(0x0021) 取 launcher 分配的
* 通知 id(nid)。返回 nid(>0=成功);无 socket/写失败/超时 → 返回 0(调用方保留本地 id
* 兜底,不崩)。调用方须在持锁外调用(socket I/O 不占 g_mu,避免阻塞其它查询)。
* replaces_id:0=新建;>0=更新 launcher 侧已存在通知(freedesktop 语义)。 */
static uint32_t notify_deliver(const meow_notify *n, uint32_t replaces_id)
{
meow_log(MEOW_LOG_INFO, "[notify] %s id=%u type=%s urgency=%s title=%s",
ev, (unsigned)s->id, meow_notify_category_str(s->cat),
meow_notify_urgency_str(s->urg), s->title);
uint32_t nid = meow_notify_ipc_send(n, replaces_id);
if (nid) {
meow_log(MEOW_LOG_INFO, "[notify] delivered nid=%u replaces=%u cat=%s title=%s",
(unsigned)nid, (unsigned)replaces_id, meow_notify_category_str(n->cat),
n->title ? n->title : "");
} else {
meow_log(MEOW_LOG_INFO, "[notify] degraded (no launcher) cat=%s title=%s",
meow_notify_category_str(n->cat), n->title ? n->title : "");
}
return nid;
}
/* ============================================================ */
@@ -132,7 +151,7 @@ int meow_notify_register_type(meow_notify_category cat)
uint32_t meow_notify_send(const meow_notify *n)
{
uint32_t id;
uint32_t id, nid, replaces_id = 0;
uint64_t now, oldest;
int i, slot_idx, count, oldest_idx;
@@ -155,11 +174,16 @@ uint32_t meow_notify_send(const meow_notify *n)
if (n->cat == MEOW_NOTIFY_CAT_MEDIA) {
/* 媒体单例:复用已存在的媒体槽(重发替换同 app 上一条媒体通知) */
for (i = 0; i < MEOW_NOTIFY_MAX_ACTIVE; i++)
if (g_slots[i].active && g_slots[i].cat == MEOW_NOTIFY_CAT_MEDIA) { slot_idx = i; break; }
if (g_slots[i].active && g_slots[i].cat == MEOW_NOTIFY_CAT_MEDIA) {
slot_idx = i;
replaces_id = g_slots[i].ipc_id; /* 更新该媒体通知(0=降级/未同步) */
break;
}
} else {
count = notify_count_cat(n->cat);
if (count >= MEOW_NOTIFY_MAX_PER_TYPE) {
/* 满则丢该类型最旧一条(替换) */
/* 满则丢该类型最旧一条(更新):先取被丢最旧的 launcher nid 作 replaces_id,
* 再释放槽(顺序不可反,否则 ipc_id 已被清 0)。 */
oldest_idx = -1;
oldest = UINT64_MAX;
for (i = 0; i < MEOW_NOTIFY_MAX_ACTIVE; i++)
@@ -167,7 +191,13 @@ uint32_t meow_notify_send(const meow_notify *n)
oldest = g_slots[i].created_ms;
oldest_idx = i;
}
if (oldest_idx >= 0) { g_slots[oldest_idx].active = 0; g_slots[oldest_idx].id = 0; }
if (oldest_idx >= 0) {
replaces_id = g_slots[oldest_idx].ipc_id; /* 复用被丢最旧的 launcher nid */
if (replaces_id == 0) replaces_id = 0; /* 未同步时按新建处理 */
g_slots[oldest_idx].active = 0;
g_slots[oldest_idx].id = 0;
g_slots[oldest_idx].ipc_id = 0;
}
}
}
if (slot_idx < 0) {
@@ -184,26 +214,42 @@ uint32_t meow_notify_send(const meow_notify *n)
id = g_next_id++;
if (g_next_id == 0) g_next_id = 1; /* 防回绕 */
notify_fill(&g_slots[slot_idx], n, id, now);
notify_deliver(&g_slots[slot_idx], "send");
pthread_mutex_unlock(&g_mu);
/* 落点(持锁外):IPC 送 launcher 中央存储,回读 nid;无 launcher 则降级(nid=0)。 */
nid = notify_deliver(n, replaces_id);
/* 回填 launcher 分配的 nid(槽可能已被并发 cancel/过期清掉——仅在时回填)。 */
if (nid) {
pthread_mutex_lock(&g_mu);
for (i = 0; i < MEOW_NOTIFY_MAX_ACTIVE; i++)
if (g_slots[i].active && g_slots[i].id == id) { g_slots[i].ipc_id = nid; break; }
pthread_mutex_unlock(&g_mu);
}
return id;
}
int meow_notify_cancel(uint32_t id)
{
int i, rc = 0;
uint32_t ipc_id = 0;
if (id == 0) return 0;
pthread_mutex_lock(&g_mu);
notify_purge_expired();
for (i = 0; i < MEOW_NOTIFY_MAX_ACTIVE; i++) {
if (g_slots[i].active && g_slots[i].id == id) {
ipc_id = g_slots[i].ipc_id; /* launcher 侧 nid;0=未同步/降级 */
g_slots[i].active = 0;
g_slots[i].id = 0;
g_slots[i].ipc_id = 0;
rc = 1;
break;
}
}
pthread_mutex_unlock(&g_mu);
/* 落点:经 IPC MSG_NOTIFY_DISMISS(0x0022) 撤下 launcher 中央存储对应通知
* (best-effort;无 launcher/未同步则静默降级)。 */
if (rc && ipc_id) meow_notify_ipc_dismiss(ipc_id);
return rc;
}