滚动协议

在 0.50.0 版本加入.

鼠标协议将滚动报告为虚拟滚轮按钮的按压,每行一次;程序看到的触控板像不连贯的滚轮,也不知道手势何时开始、结束或进入惯性滚动。滚动协议是开放终端扩展,按系统提供的方式报告滚动:以像素为单位的距离、产生事件的设备和手势阶段。封装与 数位板指针协议 相同,目标也一致:小巧、低干扰、易于实现,不改变 TTY 的本质。

消息封装

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

<OSC> 777 ; scroll ; v=1 : op=query : id=7 <ST>

帧遵循 OSC 777 扩展封装 规定的 OSC 777 共用规则:字段语法、拒绝哪些帧、单位和时钟。协议版本 v 为 1,op 为 query、cap、mode 或 event。

能力探测

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

<OSC> 777 ; scroll ; v=1 : op=query : id=7 <ST>

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

<OSC> 777 ; scroll ; v=1 : op=cap : id=7 : caps=1 : mode=0 <ST>

caps 为位集合,目前只定义 1,表示终端报告像素距离。mode 为下述模式的当前状态。不支持本协议的终端会忽略查询,因此程序必须设置超时,并回退到鼠标报告。查询不改变模式。

模式

报告默认关闭,按终端窗口开启::

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

用 mode=0 关闭。开启时,窗口中的滚动由本协议报告,不再作为滚轮按钮按压;点击和移动仍使用程序请求的鼠标报告方式。终端也不滚动自己的回滚缓冲区,滚动由程序控制。模式仅作用于当前窗口,并由 RIS 重置。程序必须在退出、挂起或失败时关闭,恢复时重新开启。多路复用器与其他终端状态一起保存它。终端可允许用户针对全部或部分程序拒绝该模式;被拒绝时读回为关闭,不报告滚动,因此程序应读回状态,不要假定已获准。

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

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

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

报告

每个滚动事件一帧::

<OSC> 777 ; scroll ; v=1 : op=event : t=408211 : tu=73 : dx=0 : dy=250 : x=8448 : y=3072 : mods=1 : src=1 : phase=2 <ST>

除 tu 外,所有字段均为必需:

t

系统认定滚动发生的时刻,以终端全部扩展共用时钟的毫秒表示,见 OSC 777 扩展封装。终端自行生成的报告(例如自身惯性滚动)使用生成报告的时刻

tu

t 之后的微秒数,范围 0 至 999;仅在系统时间戳精度高于毫秒时出现

dx, dy

视图应移动的距离,以物理像素的百分之一为单位,有符号,向右和向下为正。触控板使用系统测得的距离;有刻度的滚轮将滚动行数按终端字符单元尺寸和滚动倍率转换,因此程序对两者使用相同单位

x, y

指针位置,以物理像素的 1/256 为单位,有符号、从零开始,相对于字符单元区域的左上角

mods

Shift 1,Alt 2,Control 4,Super 8

src

0 表示有刻度滚轮,1 表示触控板等精密设备

phase

0 无阶段,1 手指手势开始,2 手势继续,3 手势结束,4 手指抬起后惯性滚动开始,5 惯性滚动继续,6 惯性滚动结束,7 手势或惯性滚动被取消

报告中的距离可以为零,尤其是阶段 1、3、4 和 6。自行实现惯性动画的程序应在阶段 4 停止自身动画,因为终端已经开始报告系统的惯性滚动。滚轮仅报告阶段 0。

无法跟上程序处理速度的终端或中继,只能将同一设备、同一阶段的连续报告合并:距离求和,其他字段使用最后一条报告的值,包括 t 和 tu。阶段变化绝不合并或丢弃,见 OSC 777 扩展封装。

多路复用器按窗格原点(含边框)转换 x,y,其余字段原样转发,并将报告交给指针下方的窗格。

silkie 实现说明

silkie 报告窗口系统提供的信息:

  • macOS:使用 AppKit 触控板事件的像素距离和上述全部阶段。距离与 x,y 一样以物理像素表示,因此 Retina 显示器上为系统自身单位值的两倍。AppKit 事件带微秒时间戳,因此仅 macOS 发送 tu;Wayland 和 X11 的时间戳为整毫秒。

  • Wayland:从 wl_pointer 轴事件取得像素距离。版本 5 及以上的 seat 通过轴来源和手指抬起时合成器发送的轴停止事件,提供手指阶段 1 至 3。惯性阶段 4 至 6 来自终端自己的惯性滚动器,因此阶段 4 紧跟阶段 3。惯性滚动被打断(例如手指重新落下),或手指仍在滚动时指针离开窗口,会发送阶段 7。

  • X11:可用时从 XInput 2 平滑滚动取得像素距离;否则将行数转换为像素,并设置 src=0。惯性阶段 4 至 7 由终端自身的惯性滚动器提供。X 服务器不报告手指何时抬起,滚动器只能根据停顿推测,因此不报告手指阶段 1 至 3。