fix(launcher): §310 追加两修——未冻结App锁屏输入穿透(独占触控) + 主界面应用名截断

真机 M6.3 反馈(bcef8e0 三连修复未好全,追加两问题):

P1 锁屏 PIN 输入穿透仍在(媒体保活 App 实时读 evdev)
  根因:媒体保活 App(播放中)从不 SIGSTOP(保 PCM),SDK 输入线程实时读 evdev,不走缓冲。
  bcef8e0 的「SIGCONT 排空」只作用于冻结 App;对未冻结 App,隔离全靠 /tmp/meow_notif_active
  让 SDK 排空——若 App 的 meow_ui.a 缺该排空(或节流窗内漏网),锁屏期触摸依旧抵达 App。
  修法:run_lock_screen() 与 lck_input_pin_modal() 打开 DEV_TOUCH 后 EVIOCGRAB 独占触控设备
  (真机 goodix 实测 EVIOCGRAB 返回 0)——抓取期事件只投递抓取者、不为其它 fd 缓冲/回放,
  故**任何**前台进程(冻结或未冻结)锁屏期都收不到触摸(真全模态)。失败时记日志降级
  (仍靠标记+SIGSTOP 隔离)。overlay_gate.h 增 overlay_keepalive_needs_grab 判据。

P2 主界面应用名只显示 5 字(「流媒体客户」式,半字残形)
  根因:app_launcher.c `strncpy(a->name, name, 16)` 仍把显示名硬截 16 字节——M6.3 只扩了
  name[49]+json_str 整序列,漏改此二处。UTF-8 下 16B = 5 汉字 + 「端」首字节 + 无 NUL,
  显示成「流媒体客户」+ 残形;main_menu.c menu_name_fit 按字节回退又停在半截字符、加 "..." 溢出。
  修法:新增 meow_utf8.h(meow_utf8_char_len / meow_utf8_copy_bounded,纯决策可单测)——
  app_launcher.c 两处 strncpy(16) 改 app_name_copy(=copy_bounded, 拷满 sizeof name=49);
  menu_name_fit 改整字符前进 + 预留省略号宽度(mfont 用「…」/点阵用 "..."),总宽 ≤ maxw,
  绝不劈开多字节字符。

新增 test_utf8_name.c(14 断言:整字符长/整序列有界拷贝,含 cap=16/17/12 边界不劈字)+
  test_overlay_gate.c 扩展(S1b 未冻结 App 靠 EVIOCGRAB 隔离 4 断言)。launcher 全量宿主回归
  + SDK 叠加/状态栏/输入回归全 PASS;mipsel 交叉 -Wall -Wextra 0 warning。
md5 56dac860841c3884b4322707246e22af(/usr/bin 只读,待固件打包 M6.4;fw_content.conf 未动)。
This commit is contained in:
AskaEth committed 2026-09-02 08:13:55 +08:00
1 parent 67aa5fc7a8
commit c730333776
8 files changed
+224 -14

No files matched your search

+31 -9
View File
@@ -2,6 +2,7 @@
/* 本文件由拆分工具从 meow_launcherd.c 按职责搬移;逻辑与原文 0-diff(仅 static 可见性按跨模块需求调整)。*/
#include "meow_launcher_internal.h"
#include "meow_ams_start.h" /* MSG_AMS_START 拉起决策(meow_ams_start.c):run_menu 消费用 */
#include "meow_utf8.h" /* UTF-8 整序列字符步进(menu_name_fit 截断不劈多字节字符,问题2) */
/* set by run_menu: the player's panel was blanked (screen timeout) when the
@@ -393,20 +394,41 @@ static void menu_first_glyph(const char *nm, char out[4])
}
}
/* 名称截断(按可用像素宽;超出加 '…')。 */
/* 名称截断(按可用像素宽):UTF-8 整序列 + 「…」收尾,总宽 ≤ maxw。
* 旧实现:①按字节回退、边界判定错(do..while 读的是刚清零的字节,恒停在一个续字节上)→ 停在
* 半截多字节字符,显示成半字/方框;②先截满再加 "..." 未为省略号留宽 → 追加后溢出 maxw 被裁切。
* 修法:按字符起始字节前进,绝不劈开多字节字符;预留省略号宽度(mfont_ready 用「…」/回退点阵用
* "..."),截断后总宽 ≤ maxw。 */
static void menu_name_fit(const char *name, int maxw, int size, char *out, int olen)
{
char buf[64];
snprintf(buf, sizeof buf, "%s", name);
if (ui_width(buf, size) <= maxw) { snprintf(out, olen, "%s", buf); return; }
int n = (int)strlen(buf);
while (n > 0 && ui_width(buf, size) > maxw) {
/* 回退一个 UTF-8 字符边界 */
do { buf[--n] = 0; } while (n > 0 && ((unsigned char)buf[n] & 0xC0) == 0x80);
if (!name) name = "";
if (maxw < 0) maxw = 0;
const char *ell = mfont_ready ? "…" : "...";
int ell_w = ui_width(ell, size);
int budget = maxw - ell_w;
if (budget < 0) budget = 0;
if (ui_width(name, size) <= budget) { snprintf(out, olen, "%s", name); return; }
/* 整字符前进(meow_utf8_char_len 定步长):cut 恒停在一个完整字符之后,绝不劈开多字节字符;
* 连同下一整字符会超预算即停。 */
size_t stop = strlen(name);
if (stop > (size_t)olen - 1) stop = (size_t)olen - 1;
size_t cut = 0;
while (cut < stop && name[cut]) {
int step = meow_utf8_char_len((unsigned char)name[cut]);
size_t clen = (cut + (size_t)step <= stop) ? (size_t)step : (stop - cut);
if (clen == 0) break;
char tmp[64];
if (clen >= sizeof tmp) clen = sizeof tmp - 1;
memcpy(tmp, name + cut, clen);
tmp[clen] = 0;
if (ui_width(tmp, size) > budget) break;
cut += clen;
}
snprintf(out, olen, "%s...", buf);
if (cut == 0) { snprintf(out, olen, "%s", ell); return; }
snprintf(out, olen, "%.*s%s", (int)cut, name, ell);
}
/* 图标绘制:primary 圆角垫块始终垫底(MD3 图标 tile),首字母叠加其上,最后有图叠加
* meow_ui_img_cover(居中裁方)。
* 修复:原实现 `if (icon) { meow_ui_img_cover; return; }` 在图标为透明背景 logo(不透明像素