Skip to content

Picker popup flickers on Vim 9.2 due to popup redraw regression #89

@loyalpartner

Description

@loyalpartner

问题

Picker 弹窗在 Vim 9.2 上输入时整个弹窗会闪烁,但在 Vim 9.1 上完全正常。

环境

  • Vim 9.2 — 闪烁
  • Vim 9.1 — 正常
  • 两台机器使用相同终端模拟器,lazyredraw 均为 0

复现

  1. 使用 Vim 9.2
  2. 打开 Picker(<C-p> 或对应映射)
  3. 输入任意字符

整个弹窗(input + results)在每次按键时可见闪烁。

最小复现(无需 yac.vim)

let g:tp = popup_create(repeat(['test'], 10), #{
  \ line: 5, col: 5,
  \ minwidth: 40, maxwidth: 40,
  \ minheight: 10, maxheight: 10,
  \ border: [1,1,1,1],
  \ filter: {id, key -> key == "\<Esc>"
  \   ? [popup_close(id), 1][1]
  \   : [popup_settext(id, repeat([key .. ' pressed'], 10)), 1][1]},
  \ })

在 Vim 9.2 上按键时 popup 闪烁,9.1 上不闪。

分析

问题出在 Vim 9.2 的 popup 渲染管线变更。9.2 新增了 popup opacity 支持(patch 9.2.0017),可能改变了 popup 的重绘路径,导致每次 popup_settext() / popup_setoptions() 调用时 popup 区域会被先清除再重绘,产生可见的闪烁。

已尝试的 workaround(均无效)

  1. set lazyredraw 包裹批量更新 — 无效
  2. 合并 win_execute() 调用 — 将 5-10 次 win_execute() 合并为 1 次 — 无效
  3. 使用 text properties — 将高亮嵌入 popup_settext() 调用实现原子更新,消除 clearmatches() + matchaddpos() 的中间无高亮状态 — 无效

以上所有优化均无法解决闪烁,说明问题在 Vim 9.2 内部的 popup 重绘机制,而非调用次数或调用方式。

相关 Vim issues

  • vim/vim#4458 — Flicker in popup window(maintainer 确认 "when there is a popup all text is redrawn every time")
  • vim/vim#11718 — Implement flicker free redraw and scroll(BSU/ESU synchronized updates)
  • patch 9.1.1621 — 修复 cmdline popup menu 闪烁,通过推迟 screen update

当前状态

等待 Vim 上游修复。如果后续找到有效的 workaround 会更新此 issue。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions