- 通知中心=launcher侧系统级叠加层(§6.1③ 仅内部): meow_notif_panel.h(纯逻辑) + meow_launcherd.c(内联 draw/run_notif_center + run_menu顶部热区下滑接入) + test_notif_panel.c(56单测) - 通知中心零旁路走 meow_settings_*; 通知列表读 meow_notif; 左缘返回复用 meow_edge_back; 局部脏区; 系统级控件无公共API(App无法自建悬浮层) - meow_ui.a 零改动(d249c6e6); meow_launcherd=4652901a(0warn) - FRAMEWORK_DESIGN §10 进程模型/Supervisor树(svcd服务子进程化隔离防级联崩) ; MEOW_APP_SDK §6.1 系统UI归launcher+SDK/APP进程隔离; NOTIFICATION_SYSTEM §9 归属; SYSTEM_SETTINGS/SPEC_REF/DEVELOPMENT_PLAN 补齐 - README 重写为面向第三方(进度/架构/构建/部署/SDK开发; 固件打包标注本地工具不入库, 无敏感) - 遗留: SDK(App进程)侧通知中心/activity跳转 依赖 M3 导航栈(独立里程碑); 真机待验证
117 lines
4.7 KiB
C
117 lines
4.7 KiB
C
/* meow_notif_panel.h — 通知中心面板的纯逻辑(header-only,宿主可单测)。
|
||
*
|
||
* 定位:把通知中心面板里「无副作用、可独立判定」的部分抽成 static inline,
|
||
* 供 launcher(meow_launcherd.c 内嵌面板)与宿主单测(test_notif_panel.c)共用同一份实现,
|
||
* 避免两端漂移;绘制/触摸循环等依赖 launcher static 符号的部分留在 meow_launcherd.c 内。
|
||
*
|
||
* 不依赖 launcher 头 / SDK 头,仅 <stdint.h> <string.h> <stdio.h> <time.h> —— 纯宿主可编。
|
||
*/
|
||
#ifndef MEOW_NOTIF_PANEL_H
|
||
#define MEOW_NOTIF_PANEL_H
|
||
|
||
#include <stdint.h>
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <time.h>
|
||
|
||
/* ---- 手势判定 ---- */
|
||
|
||
/* 左缘宽度:与 launcher meow_touch.h MEOW_EDGE_W(24) / SDK 全局左缘返回同口径。
|
||
* 顶部下滑打开通知中心时,左缘起点保留给「左缘返回」,不与其抢占(spec-ref §5.1)。 */
|
||
#ifndef MNP_EDGE_W
|
||
#define MNP_EDGE_W 24
|
||
#endif
|
||
|
||
/* 顶部热区下滑 → 打开通知中心(纯函数)。
|
||
* down_x/down_y=抬手原点;dx/dy=抬手位移(当前-原点,即 t_last - t_down);hotzone=顶部热区高
|
||
* (launcher=SB_BAR_H=28);thresh=下滑触发位移阈值(launcher=MENU_SWIPE_THRESH=65)。
|
||
* 返回 1=应打开。约束:起点不在左缘(down_x>=MNP_EDGE_W,左缘保留给返回)+ 起点落在顶部热区
|
||
* (down_y ∈ [0,hotzone))+ 向下主导(dy>=thresh 且 |dy|>|dx|)。调用方通常先判左缘返回
|
||
* (meow_edge_back)+ 本函数,两者互斥。 */
|
||
static inline int mnp_top_swipe_down(int down_x, int down_y, int dx, int dy,
|
||
int hotzone, int thresh)
|
||
{
|
||
if (down_x < MNP_EDGE_W) return 0; /* 左缘保留给返回手势 */
|
||
if (down_y < 0 || down_y >= hotzone) return 0;
|
||
if (dy < thresh) return 0; /* 未达下滑阈值 / 向上 */
|
||
int ax = dx < 0 ? -dx : dx;
|
||
return ax < dy; /* 向下主导(横向位移小于竖向) */
|
||
}
|
||
|
||
/* 竖向主导上滑(面板内关闭):dy<=-thresh 且 |dy|>|dx|。返回 1=应关闭。 */
|
||
static inline int mnp_vertical_up(int dx, int dy, int thresh)
|
||
{
|
||
if (dy > -thresh) return 0;
|
||
int ax = dx < 0 ? -dx : dx;
|
||
return ax < -dy;
|
||
}
|
||
|
||
/* ---- 滑条 ---- */
|
||
|
||
/* 滑条值映射:px(屏幕坐标)→ 值,clamp 到 [min,max]。sx=track 左缘、sw=track 宽。
|
||
* 与 launcher 设置页 s_slider_val_from_x 同构(此处参数化,供面板亮度/音量滑条与单测用)。 */
|
||
static inline int mnp_slider_val_from_x(int px, int sx, int sw, int min, int max)
|
||
{
|
||
int range = max - min;
|
||
int v = min + (range ? (px - sx) * range / sw : 0);
|
||
if (v < min) v = min;
|
||
if (v > max) v = max;
|
||
return v;
|
||
}
|
||
|
||
/* ---- 亮度 clamp ---- */
|
||
|
||
/* 亮度 clamp:下限 vmin(=display.brightness_min,≥1 防黑屏)、上限 100(防闪屏)。
|
||
* vmin<1 时钳到 1。与 SYSTEM_SETTINGS §1 / spec-ref A-3 一致(旧文档 25 为陈旧值)。 */
|
||
static inline int mnp_brightness_clamp(int v, int vmin)
|
||
{
|
||
if (vmin < 1) vmin = 1;
|
||
if (v < vmin) v = vmin;
|
||
if (v > 100) v = 100;
|
||
return v;
|
||
}
|
||
|
||
/* ---- 时间显示 ---- */
|
||
|
||
/* 通知时间(created_ms 墙钟 epoch ms)→ 显示串。
|
||
* <60s「刚刚」;<60min「N分钟前」;否则本地「HH:MM」。now_ms=当前墙钟 epoch ms。 */
|
||
static inline void mnp_time_ago(uint64_t created_ms, uint64_t now_ms, char *buf, int len)
|
||
{
|
||
if (!buf || len <= 0) return;
|
||
if (now_ms < created_ms) now_ms = created_ms; /* 时钟回拨防御 */
|
||
uint64_t diff = now_ms - created_ms;
|
||
if (diff < 60000u) { if (len >= 1) snprintf(buf, (size_t)len, "刚刚"); return; }
|
||
if (diff < 3600000u) {
|
||
snprintf(buf, (size_t)len, "%llu分钟前", (unsigned long long)(diff / 60000u));
|
||
return;
|
||
}
|
||
time_t t = (time_t)(created_ms / 1000u);
|
||
struct tm tm;
|
||
if (localtime_r(&t, &tm))
|
||
snprintf(buf, (size_t)len, "%02d:%02d", tm.tm_hour, tm.tm_min);
|
||
else if (len >= 1) snprintf(buf, (size_t)len, "--:--");
|
||
}
|
||
|
||
/* ---- 列表命中 ---- */
|
||
|
||
/* 通知列表行命中:y 为绝对纵坐标;list_top/list_bot 为列表区上下缘;row_h 为行高。
|
||
* 返回行号(0 起);越界返回 -1。 */
|
||
static inline int mnp_row_at(int y, int list_top, int list_bot, int row_h)
|
||
{
|
||
if (y < list_top || y >= list_bot) return -1;
|
||
int r = (y - list_top) / row_h;
|
||
return r;
|
||
}
|
||
|
||
/* 列表滚动 clainmp:把 scroll 钳到 [0, total-view]。content 高度=total(总行数*row_h)。 */
|
||
static inline int mnp_scroll_clamp(int scroll, int total, int view)
|
||
{
|
||
if (total <= view) return 0;
|
||
int mx = total - view;
|
||
if (scroll < 0) scroll = 0;
|
||
if (scroll > mx) scroll = mx;
|
||
return scroll;
|
||
}
|
||
|
||
#endif /* MEOW_NOTIF_PANEL_H */
|