Files
MeowOS-SDK/meow_ui_theme.c
T
MeowOS 9f4143af22 启动器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 方案先行
2026-08-30 18:42:59 +08:00

207 lines
7.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* meow_ui_theme.c — 主题/配置(B1.5 / M2.46)。
*
* 内置日间/夜间两套色板;模式跟随系统设置键 display.theme_mode + display.theme
* (/usr/data/meow/settings.conf,与 launcher meow_settings 同源)。
* 判定与 launcher 的 s_ui_theme() 完全对齐(避免两套逻辑漂移):
* - display.theme_mode = manual:直读 display.theme(dark/light)决定深浅。
* - display.theme_mode = auto:按深色时段 display.theme_dark_start/end(分钟 0-1439),
* 半开区间 [start,end);start>end 跨午夜;start==end 视为未配置 → 回退 manual(display.theme)。
* 读取缺失/非法一律回退深色(与 launcher 默认一致)。
* 切换即广播 listener。AUTO 解析只在查询时按当前系统时间计算(不缓存)。
*/
#include "meow_ui.h"
#include "meow_ui_internal.h" /* meow_theme_reload() 定义(供 launcher 逼重读 settings) */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define MEOW_SETTINGS_FILE "/usr/data/meow/settings.conf"
static meow_theme g_light = {
0xE8EAF0, 0x1A1A2A, 0x2A5A8A, 0x4A4F5A, 28, 20
};
static meow_theme g_dark = {
0x141824, 0xFFFFFF, 0x4A6A9A, 0x9AA4C8, 28, 20
};
static meow_theme_mode g_mode = MEOW_THEME_DARK; /* 配置生效的判定模式(默认深色,与 launcher 默认一致) */
static meow_theme_mode g_manual = MEOW_THEME_DARK; /* display.theme 解析出的手动深浅;auto 未配置时段时回退用之 */
static int g_dark_start = 0; /* 深色时段开始(分钟 0-1439) */
static int g_dark_end = 0; /* 深色时段结束(分钟 0-1439) */
static int g_loaded = 0;
static meow_theme_listener g_listeners[8];
static int g_nlisteners = 0;
/* ---- 读 /usr/data/meow/settings.conf 的 key=value(兼容 "key = value" 带空格形式)----
* 与 launcher meow_settings_import 同款解析:按 '=' 切分,key/value 各自去首尾空白,
* 精确匹配 key(避免 display.theme 误匹配 display.theme_mode)。返回 0=命中,-1=未命中。 */
static int get_setting_str(const char *key, char *buf, int buflen)
{
FILE *f = fopen(MEOW_SETTINGS_FILE, "r");
if (!f || buflen <= 0) return -1;
char line[160];
int kl = (int)strlen(key);
int found = 0;
while (fgets(line, sizeof line, f)) {
char *eq = strchr(line, '=');
if (!eq) continue;
/* key = 行首到 '=',去尾空白 */
char *k = line;
while (*k == ' ' || *k == '\t') k++;
int n = (int)(eq - k);
while (n > 0 && (k[n-1] == ' ' || k[n-1] == '\t')) n--;
if (n != kl || strncmp(k, key, (size_t)kl) != 0) continue;
/* value = '=' 后,去首尾空白 / 行尾 CRLF */
const char *v = eq + 1;
while (*v == ' ' || *v == '\t') v++;
int m = 0;
while (*v && *v != '\n' && *v != '\r' && m < buflen - 1) buf[m++] = *v++;
while (m > 0 && (buf[m-1] == ' ' || buf[m-1] == '\t')) m--;
buf[m] = 0;
found = 1;
break;
}
fclose(f);
return found ? 0 : -1;
}
static int get_setting_int(const char *key, int *out)
{
char buf[32];
if (get_setting_str(key, buf, sizeof buf) != 0) return -1;
*out = atoi(buf);
return 0;
}
/* 解析 display.theme 的值(dark/light,非索引)→ LIGHT/DARK;未知/缺失回退 DARK(launcher 默认)。 */
static meow_theme_mode parse_manual(const char *v)
{
while (*v == ' ' || *v == '\t') v++;
if (!strncmp(v, "light", 5)) return MEOW_THEME_LIGHT;
return MEOW_THEME_DARK; /* "dark" / 未知 → 深色 */
}
static void load_settings(void)
{
char buf[64];
g_manual = MEOW_THEME_DARK;
g_mode = MEOW_THEME_DARK;
g_dark_start = 0;
g_dark_end = 0;
/* display.theme:手动深浅(auto 未配置时段时也回退这里) */
if (get_setting_str("display.theme", buf, sizeof buf) == 0)
g_manual = parse_manual(buf);
/* display.theme_mode:manual=读 display.theme;auto=时段。缺失/非法 → manual */
if (get_setting_str("display.theme_mode", buf, sizeof buf) == 0) {
if (!strcmp(buf, "auto")) g_mode = MEOW_THEME_AUTO;
else g_mode = g_manual; /* manual(含 "light"/"dark"/未知)→ 读 display.theme */
} else {
g_mode = g_manual; /* 无 theme_mode 键 → 默认 manual → display.theme */
}
get_setting_int("display.theme_dark_start", &g_dark_start);
get_setting_int("display.theme_dark_end", &g_dark_end);
}
/* 当前本地时刻的「当天第几分钟」(tm_hour*60+tm_min);供时段判定用(与 launcher s_now_min_of_day 一致)。 */
static int now_min_of_day(void)
{
time_t t = time(NULL);
struct tm tm;
localtime_r(&t, &tm);
return tm.tm_hour * 60 + tm.tm_min;
}
/* 深色时段判定(与 launcher theme_should_dark 完全一致):now_min ∈ [start,end) → 深色。
* - start==end 视为未配置,返回 -1(由调用方决定回退策略)。
* - start<end:非跨天(如 720→1080 = 12:00→18:00)。
* - start>end:跨午夜(如 1140→420 = 19:00→次日07:00)。
* - 边界:end 半开(恰好 end 分回到浅色),start 闭(恰好 start 分进入深色)。 */
static int theme_should_dark(int now_min, int start, int end)
{
if (start == end) return -1; /* 未配置 */
if (start < end)
return (now_min >= start && now_min < end) ? 1 : 0;
return (now_min >= start || now_min < end) ? 1 : 0; /* 跨午夜 */
}
static meow_theme_mode resolve_mode(meow_theme_mode m)
{
if (m != MEOW_THEME_AUTO) return m;
int d = theme_should_dark(now_min_of_day(), g_dark_start, g_dark_end);
if (d < 0) return g_manual; /* 时段未配置:回退 display.theme 手动深浅 */
return d ? MEOW_THEME_DARK : MEOW_THEME_LIGHT;
}
static void broadcast(void)
{
for (int i = 0; i < g_nlisteners; i++)
if (g_listeners[i]) g_listeners[i](g_mode);
}
const meow_theme *meow_theme_get(void)
{
if (!g_loaded) {
load_settings();
g_loaded = 1;
}
return resolve_mode(g_mode) == MEOW_THEME_DARK ? &g_dark : &g_light;
}
meow_theme_mode meow_theme_get_mode(void)
{
if (!g_loaded) { load_settings(); g_loaded = 1; }
return g_mode;
}
void meow_theme_set_mode(meow_theme_mode m)
{
if (!g_loaded) { load_settings(); g_loaded = 1; }
if (m < MEOW_THEME_LIGHT || m > MEOW_THEME_AUTO) return;
if (m == g_mode) return;
g_mode = m;
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)
{
switch (resolve_mode(m)) {
case MEOW_THEME_DARK: return g_dark;
case MEOW_THEME_LIGHT:
default: return g_light;
}
}
void meow_theme_add_listener(meow_theme_listener cb)
{
if (!cb) return;
if (g_nlisteners >= (int)(sizeof g_listeners / sizeof g_listeners[0])) return;
for (int i = 0; i < g_nlisteners; i++) if (g_listeners[i] == cb) return;
g_listeners[g_nlisteners++] = cb;
}
void meow_theme_remove_listener(meow_theme_listener cb)
{
for (int i = 0; i < g_nlisteners; i++) {
if (g_listeners[i] == cb) {
g_listeners[i] = g_listeners[g_nlisteners - 1];
g_nlisteners--;
return;
}
}
}