#3555·neovide

macOS/Metal: 按住键时,按键自动重复的速率会间歇性地减半 - 当事件线程在`nextDrawable()`中忙碌时,OS 会合并重复操作

作者: vsndrg创建于 2026年8月24日更新于 2026年8月24日
标签bug

描述错误

在正常模式下按住 h/j/k/l 时,Cursor 移动间歇性地减慢到配置的按键重复速率的一半。在 Neovim 中观察到的按键间隔从正常的 16.7 毫秒跳到干净的 33.4 毫秒 - 每秒钟的自动重复都缺失了。该模式可以在按住期间切换:单个按键按住的一部分以全速运行,其余部分以半速运行。帧速率不受影响(分析器显示在事件期间稳定的 120 FPS);渲染保持平滑,只有输入被降级。我将此问题追踪到交付层,在输入管线的四个点上进行了测量(详细信息如下):WindowServer 生成并按时提供每次重复,但到达 NSApplication.sendEvent: 的事件已经被精简了。损失发生在系统侧,并且与应用程序主线程事件分发延迟精确相关:当延迟保持在大约一个显示帧(120 Hz 下为 8.3 毫秒)以下时,所有重复都到达;一旦超过该阈值,macOS 会默默地合并每秒钟的待处理自动重复(重复不会排队给慢速消费者 - 很可能是防止冻结应用程序在恢复时喷出缓冲字符的相同保护;我没有找到有关此行为的公开文档)。

使用 Metal 渲染器时,延迟是结构性的:VSync::MacosMetal() 不提供主动调节(wait_for_vsync() 是空操作,uses_winit_throttling() 为 false),因此唯一阻止渲染的事情是阻塞的 nextDrawable() 调用 - 在 winit 事件线程上执行。渲染和该调用保持主线程在每个 8.3 毫秒的帧中忙碌约 6-10 毫秒,因此分派延迟正好处于操作系统阈值上并缓慢地通过它进行相位偏移(键盘重复时钟和显示时钟是独立的),这就是为什么在按住期间重复减半时来来去去不可预测的原因。这可能是 #1336 的根本原因。

内容来源: neovide/neovide