Files
MeowOS-For-R3P2/patch_v2/sdk/meow_ui_theme.c
T
MeowOS Dev 245bee2946 MeowOS for HiBy R3 Pro II — 公共发布版本(历史已重置)
• 全新单提交:清除含敏感信息的旧历史(sudo 口令、内网 IP、SSH 密钥路径、热点 SSID、设备 MAC)
• 本地开发文档/测试记录/构建脚本全部移入 gitignored 的 devdocs/ 与 scripts/build/(不入库)
• 保留:MeowOS 源码(launcher/watchdog/bootmenu/meow_svcd/SDK)、项目规范文档、mips-repo
增补组件:SDK 统一日志+通知 API、meow_svcd 服务管理器、mips-repo 软件仓库
2026-08-30 01:12:34 +08:00

198 lines
7.1 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 <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 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;
}
}
}