From b6b31f19678147360cfe53864a7e0aea8c3059ae Mon Sep 17 00:00:00 2001 From: MeowOS Date: Mon, 31 Aug 2026 03:11:35 +0800 Subject: [PATCH] =?UTF-8?q?fix(perf+sdk/ime):=20=E2=91=A0perf=20net=5Fjson?= =?UTF-8?q?=20=E7=BC=BA=20network=20=E5=AF=B9=E8=B1=A1=E9=97=AD=E5=90=88?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7=20=E2=86=92=20=E5=85=A8=E9=87=8F=20JSON=20?= =?UTF-8?q?=E6=A0=B9=E5=AF=B9=E8=B1=A1=E4=B8=8D=E9=97=AD=E5=90=88/?= =?UTF-8?q?=E9=9D=9E=E6=B3=95=EF=BC=88MeowPanel=20/api/system=20jv=5Fparse?= =?UTF-8?q?=20=E5=A4=B1=E8=B4=A5=E6=A0=B9=E5=9B=A0=EF=BC=8C=E7=9C=9F?= =?UTF-8?q?=E6=9C=BA+python=20=E5=8F=8C=E9=87=8D=E8=AF=81=E5=AE=9E?= =?UTF-8?q?=EF=BC=89=E2=91=A1IME=20flush=20=E6=8C=82=E8=B5=B7(meow=5Fgfx?= =?UTF-8?q?=5Fflush=5Fhold):=20=E9=98=BB=E5=A1=9E=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E6=95=B4=E5=91=A8=E6=9C=9F=E5=8F=AA=E8=AE=B0=E8=84=8F=E3=80=81?= =?UTF-8?q?IME=E7=94=BB=E5=AE=8C=E4=B8=80=E6=AC=A1=E5=8E=9F=E5=AD=90?= =?UTF-8?q?=E4=B8=8A=E5=B1=8F=EF=BC=8C=E6=A0=B9=E6=B2=BB=20on=5Ftick=20?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E6=9D=A1=E4=B8=8E=E9=94=AE=E7=9B=98=E5=90=8C?= =?UTF-8?q?=E5=8C=BA=E4=B8=A4=E5=88=B7=E9=A2=91=E9=97=AA=20=E2=91=A2TextFi?= =?UTF-8?q?eld=20on=5Fchange=20=E5=8F=AA=E6=A0=87=E8=84=8F=E4=B8=8D?= =?UTF-8?q?=E9=87=8D=E7=94=BB=E2=86=92=E6=94=B9=20meow=5Fui=5Finvalidate?= =?UTF-8?q?=20=E7=9C=9F=E9=87=8D=E7=94=BB=EF=BC=8C=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E5=AE=9E=E6=97=B6=E5=9B=9E=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit meow_svc_perf fa073bf9→7ea196de; meow_ui.a d814d0ed→ece0ecdb; hello 2ce09466→f45ba051; launcher 9ca4c5e8→bd37c8b0(重链) 宿主验证: test_ime_fix/test_p1p2p3_repro/test_meow_ui_widgets 全 PASS; perf_host all 输出经 python json 校验合法 --- meow_ui_gfx.c | 10 ++++++++-- meow_ui_ime.c | 5 +++++ meow_ui_internal.h | 4 ++++ meow_ui_widget.c | 6 ++++-- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/meow_ui_gfx.c b/meow_ui_gfx.c index fdcd3fc..e2dd313 100644 --- a/meow_ui_gfx.c +++ b/meow_ui_gfx.c @@ -179,6 +179,12 @@ void meow_gfx_mark_dirty(int x, int y, int w, int h) { dirty_add(x, y, w, h); } void meow_gfx_mark_full(void) { dirty_full(); } void meow_gfx_dirty_reset(void) { dirty_reset(); } +/* flush 挂起(IME/模态阻塞循环用):挂起期间 flush/flush_region 只记脏不上屏, + * 解除后由调用方一次 flush 原子上屏——避免「App on_tick 重绘先上屏、覆盖层随后再上屏」 + * 同一区域一帧两刷的频闪。 */ +static int g_flush_hold = 0; +void meow_gfx_flush_hold(int on) { g_flush_hold = on ? 1 : 0; } + /* back_buf 每行字节数 / 位深(M2.71-bug3:模态/IME 整帧快照恢复用)。 */ int meow_ui_back_buf_pitch(void) { return g_line; } int meow_ui_back_buf_bpp(void) { return g_bpp; } @@ -918,10 +924,10 @@ static void present(void) dirty_reset(); } -void meow_ui_flush(void) { present(); } +void meow_ui_flush(void) { if (!g_flush_hold) present(); } void meow_ui_flush_region(int x, int y, int w, int h) -{ dirty_add(x, y, w, h); present(); } +{ dirty_add(x, y, w, h); if (!g_flush_hold) present(); } /* ---- 帧率调度设置接口(launcher 与 app 共用;归口 PERF_SCHEDULER 显示刷新率子域)---- */ /* 设目标档位(60/30/15):同时把当前有效档对齐到目标(与 launcher settings_load 语义一致)。 */ diff --git a/meow_ui_ime.c b/meow_ui_ime.c index ce15065..968566d 100644 --- a/meow_ui_ime.c +++ b/meow_ui_ime.c @@ -268,6 +268,10 @@ int meow_ui_text_input(meow_ime_ctx *ctx) meow_ui_text_input_async(ctx); /* 阻塞循环:直到 done;on_change 由 handle_tap 触发 */ while (meow_ime_active()) { + /* flush 挂起:整个周期内(事件处理触发的 on_change 重绘 + App on_tick 重绘) + * 只记脏不上屏;IME 画完后一次 flush 原子上屏——否则 on_tick 的 invalidate + * 会先把进度条等区域刷上屏盖住键盘,IME 随后再盖回,同区一帧两刷→频闪。 */ + meow_gfx_flush_hold(1); meow_input_ev e; while (meow_input_pop(&e)) { meow_ui_activity_ping(); /* M2.71-bug5:IME 打字交互也重置息屏计时 */ @@ -277,6 +281,7 @@ int meow_ui_text_input(meow_ime_ctx *ctx) * 顺序要求:先喂 on_tick(App 重绘进 back_buf)→ 再 meow_ime_draw(IME 面板随后盖上去), * 保证 IME 面板覆盖在最上,不被 App 的 d_paint_region 覆盖。 */ meow_ui_feed_tick(); + meow_gfx_flush_hold(0); meow_ime_draw(); meow_ui_flush(); usleep(16000); diff --git a/meow_ui_internal.h b/meow_ui_internal.h index bc3c89b..9e7fc22 100644 --- a/meow_ui_internal.h +++ b/meow_ui_internal.h @@ -98,6 +98,10 @@ void meow_gfx_blit_rgba(int x, int y, int w, int h, const uint8_t *rgba, int alp /* 标记一个区域脏(供非标准绘制使用)。 */ void meow_gfx_mark_dirty(int x, int y, int w, int h); +/* flush 挂起(IME/模态阻塞循环用):on=1 期间 meow_ui_flush/flush_region 只记脏不上屏, + * 解除后由调用方一次 flush 原子上屏,避免覆盖层与 App on_tick 重绘同帧两刷频闪。 */ +void meow_gfx_flush_hold(int on); + /* 标记整帧脏(launcher 手动脏模型桥接:自绘 raw 像素后标全屏,present 走 SDK)。 */ void meow_gfx_mark_full(void); diff --git a/meow_ui_widget.c b/meow_ui_widget.c index 0881ae8..21b428b 100644 --- a/meow_ui_widget.c +++ b/meow_ui_widget.c @@ -507,7 +507,8 @@ void meow_textfield_set_placeholder(meow_widget *w, const char *placeholder) meow_gfx_mark_dirty(w->x, w->y, w->w, w->h); } const char *meow_textfield_text(meow_widget *w) { return (w && w->type == W_TEXTFIELD && w->buf) ? w->buf : ""; } -/* 输入中实时把 IME 文本同步到字段缓冲 + 只刷字段区(字段在顶部,IME 键盘在底部覆盖层) */ +/* 输入中实时把 IME 文本同步到字段缓冲 + 重画字段区(invalidate 重画 z 栈相交绘制物; + * flush 在 IME 阻塞循环内被挂起(meow_gfx_flush_hold),随本周期末一次原子上屏) */ static void textfield_change_cb(const char *text, void *ctx) { meow_widget *w = (meow_widget *)ctx; @@ -517,7 +518,8 @@ static void textfield_change_cb(const char *text, void *ctx) w->buf[w->maxlen - 1] = 0; } w->buflen = text ? (int)strlen(text) : 0; - meow_gfx_mark_dirty(w->x, w->y, w->w, w->h); + /* 只标脏不重画的话 back_buf 仍是旧文本,flush 上去的还是旧的——必须真重画 */ + meow_ui_invalidate(w->x, w->y, w->w, w->h); } int meow_textfield_activate(meow_widget *w) {