低延迟协议

在 0.50.0 版本加入.

终端不会在输出到达时立即显示,而是等待几毫秒收集更多内容,将突发输出一次解析和绘制,保持稳定绘制频率,而非每次写入后都重绘。对于 shell 或编辑器,这种延迟难以察觉,却可节省大量 CPU。对于随笔移动绘制笔迹、或随手指拖动视图的程序,每一毫秒都能被感知。低延迟协议允许此类程序请求终端在交互期间放弃批处理。它与 数位板指针协议 一样,是小巧、低干扰、易于实现的开放终端扩展,不改变 TTY 的本质。

消息封装

帧使用带有 latency 选择器的 OSC 777::

<OSC> 777 ; latency ; v=1 : op=query : id=42 <ST>

帧遵循 OSC 777 扩展封装 规定的 OSC 777 共用规则:字段语法、拒绝哪些帧,以及单位。协议版本 v 为 1,op 为 query、cap 或 mode。终端仅发送回复,回复绝不合并或丢弃。

能力探测

程序询问终端是否支持本协议::

<OSC> 777 ; latency ; v=1 : op=query : id=42 <ST>

id 是程序自行选择的非负 31 位整数,回复原样返回,以便匹配查询。支持协议的终端回答::

<OSC> 777 ; latency ; v=1 : op=cap : id=42 : caps=1 : mode=0 : input=3000 : repaint=10000 <ST>

caps 是终端能力的位集合,当前始终为 1,表示支持下述模式;mode 为该模式的当前状态。input 表示终端通常在解析已有输出前等待更多内容的时间,repaint 表示通常两帧绘制之间的等待时间,单位均为微秒;如果完全不以这种方式批处理,相应值为 0。程序可比较这些时间与可用时间预算,判断启用模式是否值得增加 CPU 开销。不支持协议的终端会忽略查询,因此程序必须设置超时,并在缺少支持时继续运行。

模式

模式默认关闭,按终端窗口开启::

<OSC> 777 ; latency ; v=1 : op=mode : mode=1 <ST>

用 mode=0 关闭。模式开启时,终端在程序输出到达后立即解析并绘制,不再等待更多内容;收到用户输入也立即交给程序。该模式不会改变等待显示器刷新的时间:原本与显示器刷新同步的终端仍会同步,一帧也不可能早于下一次刷新到达屏幕。画面呈现协议 可告诉程序提交时刻。

模式仅作用于当前窗口,RIS 会重置。原本可合并的小型写入会各自解析和绘制,因而增加 CPU 开销,所以只适用于笔划、拖动等交互期间,不应持续整个程序生命周期。程序必须在退出、挂起或失败时关闭模式,恢复时重新开启。多路复用器和中继与其他终端状态一起保存该模式,并在脱离连接时关闭;无法实现该模式的中继可仅保存状态并转发查询。终端可允许用户针对全部或部分程序拒绝此模式;被拒绝时读回为关闭,不产生任何变化,因此程序应读回状态,不要假定已获准。

不带 mode 字段的 mode 请求读取状态而不修改,回复为::

<OSC> 777 ; latency ; v=1 : op=mode : mode=1 <ST>

程序重连后恢复时,应读回模式,确认是否仍然有效,而非假定状态保留。

Silkie 中的实现

报告的两项时间分别来自 input_delay 和 repaint_delay。窗口开启此模式时,其程序输出会立即唤醒终端,无须等待输入延迟即开始解析,并在同一轮事件处理中绘制。Silkie 本来就不对输出应用重绘延迟,因此此模式只改变输入侧的等待。无论是否启用模式,交给程序的输入都会在产生后立即写入。