全屏滑条统一路径+对比色(112/115) + 字体索引+查列表+丢失降级(113) + 文档刷新(114) + svcd CLI文档+mips-repo拆bins/mpk(116)
This commit is contained in:
1 parent
b75ecce5de
commit
19a001f007
22 files changed
+666
-129
No files matched your search
Binary file not shown.
@@ -117,6 +117,54 @@ int meow_font_config_multifont(int on,
|
||||
int meow_font_import_zip(const char *zip_path); /* TODO:MeowPanel */
|
||||
int meow_font_export_zip(const char *family, const char *out_zip); /* TODO:MeowPanel */
|
||||
|
||||
/* ================================================================== */
|
||||
/* M2.58 字体索引 + 应用字库查询(规格 §5.7:索引文件 / 查列表 / 丢失降级默认) */
|
||||
/* ================================================================== */
|
||||
/* 系统字体列表的持久化快照 = TF 卡 <card_root>/MeowOS/config/fonts/index(CSV,每套一条:
|
||||
* "family","weight","path","label","tier",glyph_count
|
||||
* path = 卡根相对 font.png(如 MeowOS/fonts/misans/regular/font.png)
|
||||
* label = 显示名(含字重 + 尺寸标记,如 `MiSans Regular(common≈4k)`)
|
||||
* tier = common|gbk|full(档位,信息用 + 驱动按需加载)
|
||||
* launcher 扫描 MeowOS/fonts/<family>/<weight>/ 后写该文件(覆盖,含默认行 index0);
|
||||
* SDK 侧 meow_font_get_available_count()/enumerate() 只从这个文件读,不依赖 launcher 内存数组;
|
||||
* 无卡/无 index → 仅 1 项板载默认(family=default)。 */
|
||||
#define MEOW_FONT_INDEX_REL "MeowOS/config/fonts/index"
|
||||
|
||||
/* 权威列表数据模型(SDK 侧快照,枚举时填充;规格 §5.7.1)。 */
|
||||
#ifndef MEOW_FONT_INFO_DEFINED
|
||||
#define MEOW_FONT_INFO_DEFINED
|
||||
typedef struct meow_font_info {
|
||||
char family[64]; /* family slug = MeowOS/fonts/<family>/ 一级目录名 */
|
||||
char name[64]; /* 显示名(index 无单列 → 回退 family) */
|
||||
char weight[32]; /* weight slug(regular|bold|…,缺省 regular) */
|
||||
char tier[8]; /* 档位 common|gbk|full(info 用) */
|
||||
int glyph_count; /* font.json glyph_count(info 用) */
|
||||
char label[128]; /* index 显示名(含字重 + 尺寸标记) */
|
||||
int size_list[16]; /* 原生字号表(index 无 → 空) */
|
||||
int size_count; /* 有效字号数 */
|
||||
int bit_depth; /* 4|8(index 无 → 0) */
|
||||
char path_png[320]; /* 卡根相对 MeowOS/fonts/<family>/<weight>/font.png */
|
||||
} meow_font_info;
|
||||
#endif
|
||||
|
||||
/* 卡根:env MEOW_CARD_ROOT 优先,否则默认 /usr/data/mnt/sd_0。 */
|
||||
const char *meow_font_card_root(void);
|
||||
/* <card_root>/MeowOS/config/fonts/index 绝对路径写入 out;0=成功。 */
|
||||
int meow_font_index_path(char *out, int olen);
|
||||
/* 读 index → 填充 out 数组(最多 max 条),返回「总条数」(无 index/不可读/空 → 1=合成默认行)。
|
||||
* 注意 out[i].path_png 为「卡根相对」路径,需经卡根解析为绝对路径再使用。 */
|
||||
int meow_font_index_load(meow_font_info *out, int max);
|
||||
|
||||
/* 应用可读 TF 卡字体列表(规格 §5.7.2):
|
||||
* - get_available_count():可用字库数(含默认;无卡 → 1)。
|
||||
* - enumerate(idx, out):按序号取,越界返回 0;idx=0=默认行(family=default)。
|
||||
* - select_by_id(id):id=0 跟随系统默认(font.file,经 env MEOW_FONT_PNG/IDX);
|
||||
* id>0 会话内固定用该套;该套字库缺失 → 降级默认(不丢请求)+ WARN 日志
|
||||
* (meow_log→app 日志)。成功 0,越界负值。 */
|
||||
int meow_font_get_available_count(void);
|
||||
int meow_font_enumerate(int idx, meow_font_info *out);
|
||||
int meow_font_select_by_id(int id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Binary file not shown.
@@ -897,7 +897,7 @@ static int meow_font_ensure(void)
|
||||
return 1;
|
||||
}
|
||||
if (have_sel)
|
||||
logmsg("meow_font: %s load failed, fallback", fpng);
|
||||
logmsg("meow_font: selected font %s missing, fallback default", fpng); /* 系统日志 */
|
||||
/* 卡默认 → 固件。 */
|
||||
if (meow_font_load(UI_FONT_PNG_CARD, UI_FONT_IDX_CARD) == 0 ||
|
||||
meow_font_load(UI_FONT_PNG_SYS, UI_FONT_IDX_SYS) == 0) {
|
||||
@@ -906,6 +906,7 @@ static int meow_font_ensure(void)
|
||||
meow_font_has_size(28), meow_font_has_size(20));
|
||||
return 1;
|
||||
}
|
||||
logmsg("meow_font: all font sources missing, using 5x7 bitmap"); /* WARN:字库不可用 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1082,6 +1083,9 @@ static void meow_font_reload_multifont(void)
|
||||
cidx[c][n-4]='.'; cidx[c][n-3]='i'; cidx[c][n-2]='d'; cidx[c][n-1]='x'; cidx[c][n]=0;
|
||||
}
|
||||
cfg[c].png = cpng[c]; cfg[c].idx = cidx[c];
|
||||
} else {
|
||||
/* M2.58:类别字体配置了但缺失 → 该类别回退全局,并记系统 WARN。 */
|
||||
logmsg("multi_font: class %s font %s missing, fallback global", cls_keys[c], ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1900,10 +1904,84 @@ static int meow_font_probe_weight(const char *dirpath, const char *family, const
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* M2.58 字体索引:CSV 字段写入(始终双引号包裹,内嵌双引号加倍)。返回写入长度。 */
|
||||
static int font_index_csvq(char *dst, int olen, const char *s)
|
||||
{
|
||||
int o = 0;
|
||||
if (olen <= 0) return 0;
|
||||
if (o < olen) dst[o++] = '"';
|
||||
for (; *s && o < olen - 3; s++) {
|
||||
if (*s == '"') dst[o++] = '"';
|
||||
if (o < olen - 2) dst[o++] = *s;
|
||||
}
|
||||
if (o < olen) dst[o++] = '"';
|
||||
dst[o] = 0;
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 把当前 font_presets* 扫描结果落盘为 <card_root>/MeowOS/config/fonts/index(覆盖)。
|
||||
* 每套一条 `"family","weight","path","label","tier",glyph_count`;path=卡根相对 font.png。
|
||||
* 目录不存在则 mkdir -p;无卡(mkdir/fopen 失败)→ 静默放弃(仅内存默认项)。
|
||||
* 该文件是 SDK meow_font_get_available_count()/enumerate() 的持久数据源(规格 §5.7)。 */
|
||||
static void meow_font_write_index(const char *card_root)
|
||||
{
|
||||
if (!card_root || !card_root[0]) return;
|
||||
char t1[360], t2[380], base[400], path[420];
|
||||
snprintf(t1, sizeof t1, "%s/MeowOS", card_root);
|
||||
snprintf(t2, sizeof t2, "%s/MeowOS/config", card_root);
|
||||
snprintf(base, sizeof base, "%s/MeowOS/config/fonts", card_root);
|
||||
/* 无卡(card_root 父目录不存在 → ENOENT)→ 静默放弃:仅内存默认项,不刷系统日志。 */
|
||||
if (mkdir(t1, 0755) != 0 && errno != EEXIST) {
|
||||
if (errno != ENOENT) logmsg("fonts: index mkdir fail %s", t1);
|
||||
return;
|
||||
}
|
||||
if (mkdir(t2, 0755) != 0 && errno != EEXIST) { logmsg("fonts: index mkdir fail %s", t2); return; }
|
||||
if (mkdir(base, 0755) != 0 && errno != EEXIST) { logmsg("fonts: index mkdir fail %s", base); return; }
|
||||
snprintf(path, sizeof path, "%s/index", base);
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) { logmsg("fonts: index fopen fail %s", path); return; }
|
||||
char line[1024];
|
||||
for (int i = 0; i < font_presets_n; i++) {
|
||||
const char *fam = font_preset_fams[i] ? font_preset_fams[i] : "default";
|
||||
const char *wt = font_preset_wts[i] ? font_preset_wts[i] : "regular";
|
||||
const char *val = font_presets[i] ? font_presets[i] : "MeowOS/fonts/default/regular/font.png";
|
||||
const char *lbl = font_preset_labels[i] ? font_preset_labels[i] : fam;
|
||||
const char *tier = font_preset_tiers[i] ? font_preset_tiers[i] : "common";
|
||||
int o = 0;
|
||||
o = font_index_csvq(line, sizeof line, fam);
|
||||
line[o++] = ','; line[o] = 0;
|
||||
o += font_index_csvq(line + o, sizeof line - (size_t)o, wt);
|
||||
line[o++] = ','; line[o] = 0;
|
||||
o += font_index_csvq(line + o, sizeof line - (size_t)o, val);
|
||||
line[o++] = ','; line[o] = 0;
|
||||
o += font_index_csvq(line + o, sizeof line - (size_t)o, lbl);
|
||||
line[o++] = ','; line[o] = 0;
|
||||
o += font_index_csvq(line + o, sizeof line - (size_t)o, tier);
|
||||
line[o++] = ','; line[o] = 0;
|
||||
snprintf(line + o, sizeof line - (size_t)o, "%d\n", font_preset_glyphs[i]);
|
||||
fputs(line, f);
|
||||
}
|
||||
fclose(f);
|
||||
logmsg("fonts: index written (%d entries) -> %s", font_presets_n, path);
|
||||
}
|
||||
|
||||
/* 扫描 <card_root>/MeowOS/fonts/ 下两级 <family>/<weight>/,重建字体 preset 列表。
|
||||
* 每个 (family,weight) 组合一套(如 misans/regular、misans/bold);family 级 'default' 由
|
||||
* 索引 0(默认字体)单独处理,不进循环,避免重复。上限 FONT_PRESETS_MAX
|
||||
* (1 默认 + ≤16 用户字体)。无卡/无目录时仅默认。 */
|
||||
* (1 默认 + ≤16 用户字体)。无卡/无目录时仅默认。
|
||||
*
|
||||
* M2.58 释放语义(规格 §5.7 需求 4「扫→写 index→释放(或按需读 index)」结论):
|
||||
* - 持久来源 = <card_root>/MeowOS/config/fonts/index(扫描后由 meow_font_write_index 落盘)。
|
||||
* SDK 只读该文件,从不依赖本内存数组。
|
||||
* - font_presets* / *_buf 均为「静态、有界(FONT_PRESETS_MAX=17)、非堆」数组:无内存泄漏,
|
||||
* 故无运行期 free;「释放」含义 = 两个扫描点(启动 / 进设置页)重建 + 每套固定上限防膨胀。
|
||||
* - 设置字体列表(font.file / font.class_* 下拉、family→字重子菜单)在本视图内显示时用
|
||||
* 该数组;离开字体列表视图(run_settings_page 退出)无需显式 free(静态数组),下次
|
||||
* 进设置/重扫自动重建。
|
||||
* - ⚠️ 未做「启动后即清空数组」:meow_font_effective_paths_tiered(launch_app 大字库档位
|
||||
* 选库)与 meow_font_reload_multifont 在运行期持续读 font_presets_n,清空会造成大字库
|
||||
* 档位退化(red line「保持档位/多字体行为」)。如需「零驻留」,须把这几个核心路径改为
|
||||
* 直接读 index(较大重构,超出本批边界,留待后续)。 */
|
||||
static void meow_font_scan_presets_root(const char *card_root)
|
||||
{
|
||||
font_presets_n = 0;
|
||||
@@ -1933,43 +2011,48 @@ static void meow_font_scan_presets_root(const char *card_root)
|
||||
char root[340];
|
||||
snprintf(root, sizeof root, "%s/%s", card_root, MEOW_FONTS_CFG);
|
||||
DIR *d = opendir(root);
|
||||
if (!d) return; /* 无卡/无字库目录:仅默认 */
|
||||
struct dirent *de;
|
||||
while ((de = readdir(d)) && font_presets_n < FONT_PRESETS_MAX) {
|
||||
if (de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "default")) continue; /* 默认字体由索引 0 单独处理 */
|
||||
char fampath[400];
|
||||
snprintf(fampath, sizeof fampath, "%s/%s", root, de->d_name);
|
||||
DIR *w = opendir(fampath); /* 一级:<family>/ */
|
||||
if (!w) continue;
|
||||
struct dirent *we;
|
||||
while ((we = readdir(w)) && font_presets_n < FONT_PRESETS_MAX) {
|
||||
if (we->d_name[0] == '.') continue;
|
||||
char dirpath[400], label[96], cs[8] = ""; int gc = 0; char wt[32] = "", nm[64] = "";
|
||||
snprintf(dirpath, sizeof dirpath, "%s/%s", fampath, we->d_name);
|
||||
if (meow_font_probe_weight(dirpath, de->d_name, we->d_name, label, sizeof label,
|
||||
cs, sizeof cs, &gc, wt, sizeof wt, nm, sizeof nm) == 0)
|
||||
continue; /* 缺组件/损坏 → 跳过该套 */
|
||||
int i = font_presets_n;
|
||||
snprintf(font_preset_val_buf[i], sizeof font_preset_val_buf[i],
|
||||
"%s/%s/%s/font.png", MEOW_FONTS_CFG, de->d_name, we->d_name);
|
||||
snprintf(font_preset_label_buf[i], sizeof font_preset_label_buf[i], "%s", label);
|
||||
snprintf(font_preset_tier_buf[i], sizeof font_preset_tier_buf[i], "%s", cs[0]?cs:"common");
|
||||
snprintf(font_preset_fam_buf[i], sizeof font_preset_fam_buf[i], "%s", de->d_name);
|
||||
snprintf(font_preset_wt_buf[i], sizeof font_preset_wt_buf[i], "%s", wt);
|
||||
snprintf(font_preset_name_buf[i], sizeof font_preset_name_buf[i], "%s", nm);
|
||||
font_presets[i] = font_preset_val_buf[i];
|
||||
font_preset_labels[i] = font_preset_label_buf[i];
|
||||
font_preset_tiers[i] = font_preset_tier_buf[i];
|
||||
font_preset_fams[i] = font_preset_fam_buf[i];
|
||||
font_preset_wts[i] = font_preset_wt_buf[i];
|
||||
font_preset_names[i] = font_preset_name_buf[i];
|
||||
font_preset_glyphs[i] = gc;
|
||||
font_presets_n++;
|
||||
if (d) { /* 无卡/无字库目录 → 跳过扫描,仅默认 */
|
||||
struct dirent *de;
|
||||
while ((de = readdir(d)) && font_presets_n < FONT_PRESETS_MAX) {
|
||||
if (de->d_name[0] == '.') continue;
|
||||
if (!strcmp(de->d_name, "default")) continue; /* 默认字体由索引 0 单独处理 */
|
||||
char fampath[400];
|
||||
snprintf(fampath, sizeof fampath, "%s/%s", root, de->d_name);
|
||||
DIR *w = opendir(fampath); /* 一级:<family>/ */
|
||||
if (!w) continue;
|
||||
struct dirent *we;
|
||||
while ((we = readdir(w)) && font_presets_n < FONT_PRESETS_MAX) {
|
||||
if (we->d_name[0] == '.') continue;
|
||||
char dirpath[400], label[96], cs[8] = ""; int gc = 0; char wt[32] = "", nm[64] = "";
|
||||
snprintf(dirpath, sizeof dirpath, "%s/%s", fampath, we->d_name);
|
||||
if (meow_font_probe_weight(dirpath, de->d_name, we->d_name, label, sizeof label,
|
||||
cs, sizeof cs, &gc, wt, sizeof wt, nm, sizeof nm) == 0)
|
||||
continue; /* 缺组件/损坏 → 跳过该套 */
|
||||
int i = font_presets_n;
|
||||
snprintf(font_preset_val_buf[i], sizeof font_preset_val_buf[i],
|
||||
"%s/%s/%s/font.png", MEOW_FONTS_CFG, de->d_name, we->d_name);
|
||||
snprintf(font_preset_label_buf[i], sizeof font_preset_label_buf[i], "%s", label);
|
||||
snprintf(font_preset_tier_buf[i], sizeof font_preset_tier_buf[i], "%s", cs[0]?cs:"common");
|
||||
snprintf(font_preset_fam_buf[i], sizeof font_preset_fam_buf[i], "%s", de->d_name);
|
||||
snprintf(font_preset_wt_buf[i], sizeof font_preset_wt_buf[i], "%s", wt);
|
||||
snprintf(font_preset_name_buf[i], sizeof font_preset_name_buf[i], "%s", nm);
|
||||
font_presets[i] = font_preset_val_buf[i];
|
||||
font_preset_labels[i] = font_preset_label_buf[i];
|
||||
font_preset_tiers[i] = font_preset_tier_buf[i];
|
||||
font_preset_fams[i] = font_preset_fam_buf[i];
|
||||
font_preset_wts[i] = font_preset_wt_buf[i];
|
||||
font_preset_names[i] = font_preset_name_buf[i];
|
||||
font_preset_glyphs[i] = gc;
|
||||
font_presets_n++;
|
||||
}
|
||||
closedir(w);
|
||||
}
|
||||
closedir(w);
|
||||
closedir(d);
|
||||
}
|
||||
closedir(d);
|
||||
/* M2.58:扫描结果落盘为 <card_root>/MeowOS/config/fonts/index(含默认行 index0),
|
||||
* 作为 SDK meow_font_get_available_count()/enumerate() 的持久数据源;无卡时仅默认 1 行,
|
||||
* 由 meow_font_write_index 内部 mkdir-fail 静默放弃(此路径不刷屏)。 */
|
||||
meow_font_write_index(card_root);
|
||||
}
|
||||
|
||||
/* 设备默认卡根扫描(等价现状:无卡时 opendir 失败 → 仅默认字体)。 */
|
||||
|
||||
@@ -158,6 +158,32 @@ meow_svcd pid
|
||||
|
||||
应答:`OK` / `ERR no-such-service` / 多行 `svc=... state=... pid=... restart=... exit=...`。
|
||||
|
||||
### 6.1 `systemctl` 式 CLI 用法(SSH 终端示例)
|
||||
|
||||
守护已由固件 `etc/init.d/S89meow_svcd` 开机自启,SSH 登录设备后**直接敲**命令即可,无需先知道 socket:
|
||||
|
||||
```bash
|
||||
meow_svcd status # 列出所有服务 + 全局状态
|
||||
# # meow_svcd status
|
||||
# card_present=1 wifi_up=0 services=3
|
||||
# svc=mdnsd state=running pid=1234 restart=0 exit=0 trigger=boot
|
||||
# svc=meow_netd state=stopped pid=0 restart=0 exit=0 trigger=card-mount
|
||||
# svc=ntpc state=stopped pid=0 restart=0 exit=0 trigger=card-mount
|
||||
|
||||
meow_svcd restart mdnsd # 重启单个服务(如板载 mDNS 应答器)
|
||||
meow_svcd start meow_netd # 启动单个服务
|
||||
meow_svcd stop all # 停止全部服务
|
||||
meow_svcd reload # 重读板载 + TF 双源 services.d 配置
|
||||
meow_svcd pid # 打印守护进程 pid
|
||||
```
|
||||
|
||||
- **socket**:控制走 AF_UNIX 单行文本,默认 `/tmp/meow_svcd.sock`(`--sock`/`MEOW_SVCD_SOCK` 可改)。
|
||||
守护**未运行**时命令回退打印状态文件 `/tmp/meow_svcd.status`(或 `card_present=0 services=0`)并以退出码 1 返回。
|
||||
- **守护前台**:`-f`/`--foreground` —— 守护自身跑前台,供 supervisor `fork/exec`+`waitpid` 托管;
|
||||
默认(无子命令)则为后台常驻。
|
||||
- 应答:成功 `OK`(`pid`→pid 数字);服务不存在 `ERR no-such-service`;`svc=... state=...` 行
|
||||
含 `pid/restart(重启计数)/exit(上次退出码)/trigger`。
|
||||
|
||||
## 7. 编译
|
||||
|
||||
```bash
|
||||
|
||||
@@ -333,6 +333,41 @@ 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);
|
||||
|
||||
/* ============================================================ */
|
||||
/* §5.7 应用可读 TF 卡字体列表(M2.58:字体索引 / 查列表 / 丢失降级默认) */
|
||||
/* ============================================================ */
|
||||
/* 系统字体管理器的面向应用接口(规格 §5.7.1/§5.7.2):
|
||||
* - 权威列表 = launcher 扫描 MeowOS/fonts/<family>/<weight>/ 后落盘的持久文件
|
||||
* MeowOS/config/fonts/index(CSV:family,weight,path,label,tier,glyph_count)。
|
||||
* app 只经本接口读该列表(不直接拼路径、不依赖 launcher 内存数组)。
|
||||
* - 渲染仍走 env MEOW_FONT_PNG/MEOW_FONT_IDX(launcher 注入的「当前生效字体」,
|
||||
* 选中字体那一套);本节的 get_available_count/enumerate 只负责「列有哪些库」,
|
||||
* select_by_id 负责「app 会话内固定用哪套」。两路明确。
|
||||
* - 无卡 / 无 index → 仅 1 项板载默认(family=default)。 */
|
||||
#ifndef MEOW_FONT_INFO_DEFINED
|
||||
#define MEOW_FONT_INFO_DEFINED
|
||||
typedef struct meow_font_info {
|
||||
char family[64]; /* family slug = MeowOS/fonts/<family>/ 一级目录名 */
|
||||
char name[64]; /* 显示名(index 无单列 → 回退 family) */
|
||||
char weight[32]; /* weight slug(regular|bold|…,缺省 regular) */
|
||||
char tier[8]; /* 档位 common|gbk|full(info 用) */
|
||||
int glyph_count; /* font.json glyph_count(info 用) */
|
||||
char label[128]; /* index 显示名(含字重 + 尺寸标记) */
|
||||
int size_list[16]; /* 原生字号表(index 无 → 空) */
|
||||
int size_count; /* 有效字号数 */
|
||||
int bit_depth; /* 4|8(index 无 → 0) */
|
||||
char path_png[320]; /* 卡根相对 MeowOS/fonts/<family>/<weight>/font.png */
|
||||
} meow_font_info;
|
||||
#endif
|
||||
|
||||
/* 可用字库数(含默认;无卡 → 1)。 */
|
||||
int meow_font_get_available_count(void);
|
||||
/* 按序号取:idx=0=默认行(family=default);越界返回 0。 */
|
||||
int meow_font_enumerate(int idx, meow_font_info *out);
|
||||
/* 选该套为 app 会话默认字体:id=0 跟随系统默认(font.file,经 env);id>0 固定用该套。
|
||||
* 该套字库缺失 → 降级默认(不丢请求)+ WARN(meow_log→app 日志)。成功 0,越界负值。 */
|
||||
int meow_font_select_by_id(int id);
|
||||
|
||||
/* ============================================================ */
|
||||
/* §10 字体分层 / 大字库(M2.5x:基座声明 + font 域已实现按档装载) */
|
||||
/* ============================================================ */
|
||||
|
||||
+15
-12
@@ -361,19 +361,22 @@ void meow_ui_swipe_hint(int x)
|
||||
* 有状态栏(非全屏)→ y = 状态栏高度;收合(collapsed)→ y=提示线下缘
|
||||
* (MUI_SBAR_COLLAPSE_H,与提示线不重叠);无状态栏(全屏/隐藏)→ y=0。 */
|
||||
int hy = meow_ui_statusbar_height();
|
||||
/* x<0 视为清空(条长 0);条长上限=屏宽。 */
|
||||
if (x < 0) x = 0;
|
||||
if (x > g_xres) x = g_xres;
|
||||
/* 只按「新旧长度的差」增量绘制,避免整段重涂背景色:
|
||||
* - 伸长:仅补画新增段(旧段已是 accent,不再用 bg 重涂——否则 app 底色≠theme bg
|
||||
* 时会在旧段留下 bg 色块,就是残留残条);
|
||||
* - 回缩/清空:仅把「超出新长度」的尾部填回背景色(实时回缩)。 */
|
||||
if (x > g_hint_last) {
|
||||
meow_ui_fill_rect(g_hint_last, hy, x - g_hint_last, MUI_HINT_H, th->accent);
|
||||
} else if (x < g_hint_last) {
|
||||
meow_ui_fill_rect(x, hy, g_hint_last - x, MUI_HINT_H, th->bg);
|
||||
/* 单一实现(与非全屏 Hello 完全一致,全屏仅 hy 不同):grow 画 0..x、shrunk 先清旧长
|
||||
* 再画 0..x、x<=0 清空。x<0 视为清空;条长上限=屏宽。 */
|
||||
if (x > 0) {
|
||||
if (x > g_xres) x = g_xres;
|
||||
/* 往回滑(新长度 < 上次)时,先清掉「上次画到旧长度、但本次超出的部分」,
|
||||
* 否则条只增不减(右滑变长、左滑回缩实时可见)。 */
|
||||
if (g_hint_last > x) meow_ui_fill_rect(0, hy, g_hint_last, MUI_HINT_H, th->bg);
|
||||
/* 条色取主题前景(fg):fg 定义为与背景对比,能同时覆盖「非全屏(底=主题bg)」与
|
||||
* 「全屏 Hello 类(底=主题accent)」两种情况——accent 在 Hello 全屏 accent 底上同色不可见。 */
|
||||
meow_ui_fill_rect(0, hy, x, MUI_HINT_H, th->fg);
|
||||
g_hint_last = x;
|
||||
} else if (g_hint_last > 0) {
|
||||
/* 手指回原点/抬手未达标/抬手达标:清掉此前画的条(填回背景色) */
|
||||
meow_ui_fill_rect(0, hy, g_hint_last, MUI_HINT_H, th->bg);
|
||||
g_hint_last = 0;
|
||||
}
|
||||
g_hint_last = x;
|
||||
/* 不发 flush:由调用方 meow_ui_flush_region(0,0,宽,6) 只刷顶部条 */
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,6 @@ static int t_press_valid = 0; /* BTN_TOUCH=1 已见(本次按下的 gate
|
||||
static int t_dx = 0, t_dy = 0; /* 按下原点(BTN_TOUCH 后首个有效 ABS 锁定) */
|
||||
static int t_cx = 0, t_cy = 0; /* 当前坐标(-1=本次尚未见到有效坐标) */
|
||||
static int t_origin_valid = 0; /* 原点是否已锁定 */
|
||||
static int t_gmax_dx = 0; /* 本手势「最大右移位移」(t_cx-t_dx 的最大值,条长上限) */
|
||||
|
||||
/* 按下边沿:只标记按下,绝不用传入坐标立即锁原点(避免用上一手势残留坐标当原点)。
|
||||
* t_cx/t_cy 归 -1 —— 本次手势以「无坐标」起步,只接受随后到来的有效 ABS。 */
|
||||
@@ -137,7 +136,6 @@ static void touch_press(int x, int y)
|
||||
t_origin_valid = 0;
|
||||
t_cx = -1; t_cy = -1;
|
||||
t_dx = 0; t_dy = 0;
|
||||
t_gmax_dx = 0; /* 新手势:最大右移位移清零(条长从 0 计) */
|
||||
}
|
||||
/* 由 ABS_X/ABS_Y 驱动:若本次按下且原点未锁且坐标有效 → 锁原点;再更新当前坐标。 */
|
||||
static void touch_update(int x, int y)
|
||||
@@ -147,17 +145,13 @@ static void touch_update(int x, int y)
|
||||
}
|
||||
if (x >= 0) t_cx = x;
|
||||
if (y >= 0) t_cy = y;
|
||||
if (t_down && t_origin_valid) {
|
||||
int dx = t_cx - t_dx;
|
||||
if (dx > t_gmax_dx) t_gmax_dx = dx; /* 记录本手势已达的最大右移位移(条长上限) */
|
||||
}
|
||||
}
|
||||
static void touch_release(void)
|
||||
{
|
||||
if (!t_down) return;
|
||||
t_down = 0; t_press_valid = 0;
|
||||
/* 本次按下从未锁到有效坐标(幽灵触摸/坐标未就绪):丢弃,且清空全部轨迹。 */
|
||||
if (!t_origin_valid) { t_cx = t_cy = -1; t_dx = t_dy = 0; t_gmax_dx = 0; return; }
|
||||
if (!t_origin_valid) { t_cx = t_cy = -1; t_dx = t_dy = 0; return; }
|
||||
t_origin_valid = 0;
|
||||
int mdx = t_cx - t_dx, mdy = t_cy - t_dy;
|
||||
int adx = mdx < 0 ? -mdx : mdx, ady = mdy < 0 ? -mdy : mdy;
|
||||
@@ -169,8 +163,7 @@ static void touch_release(void)
|
||||
* 被手势级清空,绝不继承上一手势坐标,确保:
|
||||
* ① 中部右滑不会误判成左缘返回(t_dx>=EDGE_W);
|
||||
* ② 先点中部再侧滑不返回(原点锁定在中部,>=EDGE_W),符合「必须从左缘起划」;
|
||||
* ③ 返回判定要求右移严格正向(t_cx-t_dx>=0 且 ≥SWIPE_THRESH),杜绝「向左划也误返回」;
|
||||
* 左划过程仅让进度条实时回缩,不额外生长(过程见上方 MEOW_EV_SWIPE_PROGRESS)。
|
||||
* ③ 右移严格正向(t_cx-t_dx>=0),杜绝「向左划也出条/误返回」。
|
||||
* SDK 统一上报为 MEOW_SWIPE_LEFT(设计"左滑=返回"契约,hello 用 on_swipe(LEFT) 退出)。
|
||||
*
|
||||
* 屏幕中部滑动不是返回手势:中部右滑→RIGHT(内容导航),中部左滑→非返回(落 TAP,
|
||||
@@ -199,7 +192,7 @@ static void touch_release(void)
|
||||
push_ev(MEOW_EV_TAP, t_cx, t_cy);
|
||||
}
|
||||
/* 手势级干净起点:清空全部轨迹,下一手势从零开始,杜绝污染无自愈。 */
|
||||
t_cx = t_cy = -1; t_dx = t_dy = 0; t_gmax_dx = 0;
|
||||
t_cx = t_cy = -1; t_dx = t_dy = 0;
|
||||
}
|
||||
|
||||
/* ---- 输入线程:poll 所有 event 设备 + 解析 ---- */
|
||||
@@ -231,22 +224,14 @@ static void *input_thread(void *arg)
|
||||
if (code == ABS_X || code == ABS_MT_POSITION_X) {
|
||||
if (t_down) touch_update(val, t_cy); /* 锁原点+更新当前(t_down 时才驱动) */
|
||||
else t_cx = val;
|
||||
/* 左滑进度实时上报(视觉条)。抬手触发仍由 touch_release 判定;这里只报过程。
|
||||
* 修复要点(左缘返回滑条 bug):
|
||||
* ① 双向上报(不再要求 t_cx>t_dx):向右→条伸长、向左→条实时回缩,
|
||||
* 摒弃「只在返回瞬间闪末帧 / 反向才出条」;
|
||||
* ② 仅左缘起手(t_dx<EDGE_W)才上报并被绘制——屏幕中部起手绝不触发条/返回;
|
||||
* ③ 条长 = 本手势右移位移 clamped 到「本次手势最大右移位移」(t_gmax_dx),
|
||||
* 条的最大 x 恒等于本次手势达过的最大右移距离,反复反向滑不会放大它。
|
||||
* 负数(左滑越过原点)→ 条长 0(清空)。
|
||||
* 事件载荷:a=按下X(t_dx),b=条长 len(clamp 后,≥0)。 */
|
||||
if (t_down && t_origin_valid && t_dx >= 0 && t_dx < EDGE_W) {
|
||||
int dx = t_cx - t_dx;
|
||||
if (dx > t_gmax_dx) t_gmax_dx = dx;
|
||||
int len = dx < 0 ? 0 : dx;
|
||||
if (len > t_gmax_dx) len = t_gmax_dx;
|
||||
push_ev(MEOW_EV_SWIPE_PROGRESS, t_dx, len);
|
||||
}
|
||||
/* 左滑进度实时上报(视觉条):原点确实在左缘(t_dx<EDGE_W) 且 向右移动
|
||||
* (t_cx>t_dx)——grow/回缩全程由「非全屏已验证的同一条路径」驱动,全屏仅
|
||||
* 垂直位置 hy 不同(hy=meow_ui_statusbar_height()),别无全屏特判。
|
||||
* 抬手触发仍由 touch_release 判定;这里只报过程(事件载荷 b=当前X)。
|
||||
* t_dx 是本次按下后首个有效 ABS 锁定的真实按下点(非残留),且每次抬手已
|
||||
* 清空,杜绝「中部点一下出条 / 向左划也出条」。 */
|
||||
if (t_down && t_origin_valid && t_dx >= 0 && t_dx < EDGE_W && t_cx > t_dx)
|
||||
push_ev(MEOW_EV_SWIPE_PROGRESS, t_dx, t_cx);
|
||||
}
|
||||
else if (code == ABS_Y || code == ABS_MT_POSITION_Y) {
|
||||
if (t_down) touch_update(t_cx, val); else t_cy = val;
|
||||
@@ -335,17 +320,17 @@ void meow_ui_run(const meow_ui_events *ev)
|
||||
meow_ui_sys_notif_pull();
|
||||
} else if (e.type == MEOW_EV_SWIPE_PROGRESS) {
|
||||
if (in_startup) continue; /* 启动窗口进度条静音 */
|
||||
/* e.a=按下X(t_dx),e.b=条长 len(输入层已 clamp 到「本手势最大右移位移」且≥0)。
|
||||
* SDK 自动画顶部条:从 x=0 画到 len(右移位移),向右伸长、向左实时回缩。
|
||||
* M2.5x/A-13:全屏/收合下「左缘返回手势保留」,顶部动态提示条仍需绘制——不再以
|
||||
* meow_ui_sys_statusbar_active()(全屏/隐藏=0)开关,否则全屏时滑条完全不显示。
|
||||
* 条位 y=meow_ui_statusbar_height():非全屏=状态栏下沿、全屏=0、收合=提示线下缘
|
||||
* (MUI_SBAR_COLLAPSE_H),与提示线不重叠加。APP 若注册 on_swipe_progress 仍可自绘
|
||||
* (系统条照常画);递交给 app 的是 (len-x_start) 使 x_start+dx==len,与系统条同长。 */
|
||||
int len = e.b;
|
||||
meow_ui_swipe_hint(len);
|
||||
int x0 = e.a, xc = e.b, dx = xc - x0; /* dx=当前X-按下X */
|
||||
/* SDK 自动画顶部条:长度=手指当前 X(=距左缘距离,向内划长度随位移增长)。
|
||||
* 全屏/收合下「左缘返回手势保留」,顶部动态提示条(meow_ui_swipe_hint)照常绘制
|
||||
* (与 agent-108:不再以 meow_ui_sys_statusbar_active()(全屏/隐藏=0)开关,否则
|
||||
* 全屏时滑条完全不显示)。条位 y=meow_ui_statusbar_height():非全屏=状态栏下沿
|
||||
* (28)、全屏=顶部、收合=提示线下缘(MUI_SBAR_COLLAPSE_H),与提示线不重叠加——
|
||||
* 全屏与非全屏共用同一条绘制/进度路径,只 hy 不同,无全屏特有的坐标/方向/最大值逻辑。
|
||||
* APP 若注册 on_swipe_progress 仍可自绘(系统条照常画;x_start+dx==当前X,幂等)。 */
|
||||
meow_ui_swipe_hint(xc);
|
||||
if (g_events_set && g_events.on_swipe_progress)
|
||||
g_events.on_swipe_progress(e.a, len - e.a);
|
||||
g_events.on_swipe_progress(x0, dx);
|
||||
meow_ui_flush_region(0, meow_ui_statusbar_height(), meow_ui_width(), 6);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user