/* meow_ui_repaint.h — 解锁后「强制 App 整帧重画」请求文件(M40 F5/P5-P6)。 * * 背景:锁屏/电源菜单是整帧不透明覆盖。关闭后 launcher 会恢复它快照的底层帧,但 App * 进程只按自己的脏矩形 present;锁屏期间它可能被 SIGSTOP 冻结,从未观测到 * /tmp/meow_notif_active 的抑制态,因此 SDK 的「抑制→恢复」整帧重画边沿不会触发 —— * PIN 帧/菜单帧会残留在屏幕上,直到用户点到某个控件产生新脏区才刷新(真机 P6)。 * * 机制:launcher 在 SIGCONT 前写 /tmp/meow_app_repaint;App 的 SDK present 看到文件就 * dirty_full() 一次并删除(消费一次即失效)。请求在 present 最前面检查,**抑制期也消费** * (先置 dirty_full,等标记翻回前台后的下一帧整屏上屏),避免排空窗口把请求吃掉后不生效。 * * 实现放在头文件里(static inline):present 层(meow_ui_gfx.c)直接调用;宿主单测只 * include 本头即可验证写/读/删语义,不必链接整个渲染栈。路径可用 MEOW_APP_REPAINT_FILE * 覆盖(宿主单测隔离;真机无 env 走默认)。 */ #ifndef MEOW_UI_REPAINT_H #define MEOW_UI_REPAINT_H #include #include #define MEOW_APP_REPAINT_DEFAULT "/tmp/meow_app_repaint" static inline const char *meow_ui_repaint_path(void) { /* 每帧 getenv 很便宜(/tmp 是 tmpfs,只有一次 access);保持无状态便于宿主单测在运行中 * 改路径。若后续实测有开销,可照 meow_ui_overlay_suppressed_active 的路径缓存改造。 */ const char *e = getenv("MEOW_APP_REPAINT_FILE"); return (e && e[0]) ? e : MEOW_APP_REPAINT_DEFAULT; } /* 返回 1=消费了一次重画请求(调用方应 dirty_full);0=无请求。 */ static inline int meow_ui_repaint_requested(void) { const char *p = meow_ui_repaint_path(); if (access(p, F_OK) != 0) return 0; unlink(p); /* 一次性请求:读到即消费,防每帧整帧重画 */ return 1; } #endif /* MEOW_UI_REPAINT_H */