DEC 定位器套件 —— DECELR / DECEFR / DECSLE / DECRQLP(鼠标 / 定位器事件)
DEC 原版指点设备协议(比 xterm SGR 鼠标模式早十年)。四个序列分别 启用 / 过滤 / 选择 / 查询定位器事件;现代交互式 UI 改用 SGR 鼠标模式(?1000 + ?1006)。
字节形式
涵盖所有常见的字符串字面量写法,方便正反查找。
\x1b[<Pn>;<Pu>'z \x1b[<Pm>'{ \x1b[<Pt>;<Pl>;<Pb>;<Pr>'w \x1b[<Ps>'|\033[1;2'z\e[1;2'zESC [ ... ' z / ' { / ' w / ' |1b 5b ... 27 7a / 7b / 77 / 7c说明
DEC 定位器协议比 xterm 扩展鼠标模式早十年,是 VT300+ 硬件终端(以及软件模拟器在调到高 DECSCL 一致性级别 —— 见 decscl-compat-level —— 时)上报指点设备事件的方式。四个序列共同构成该族 —— 均以单引号(0x27)为中间字节:
- DECELR —— *启用定位器报告* —— \x1b[<Pn>;<Pu>'z
- Pn:0 = 关闭定位器报告;1 = 启用;2 = 启用一次报告后自动关闭。
- Pu:0 或 2 = 坐标按字符单元;1 = 坐标按设备单位(像素)。
- 启用后,每次按键过 DECSLE 过滤都会发 DECLRP 报告;若 DECEFR 设了矩形,离开矩形时也发一份。
- DECSLE —— *选择定位器事件* —— \x1b[<Pm>'{
- Pm:0 = 仅显式 DECRQLP 才回;1 = 按下事件回;2 = 关闭按下事件回;3 = 抬起事件回;4 = 关闭抬起事件回。
- 可多次发不同 Pm 同时开按下 + 抬起:\x1b[1'{\x1b[3'{。
- DECEFR —— *启用过滤矩形* —— \x1b[<Pt>;<Pl>;<Pb>;<Pr>'w
- 定义闭矩形:上行、左列、下行、右列。指点*离开*该矩形时触发一次 DECLRP,过滤器随即自动关闭。
- 用于只关心「鼠标离开我的控件」转换的光标追踪程序。
- DECRQLP —— *请求定位器位置* —— \x1b[<Ps>'|
- Ps:事务数(目前总为 1)。
- 强制立刻发 DECLRP,与过滤 / 事件设置无关。
DECLRP —— 回复 —— \x1b[<Pe>;<Pb>;<Pr>;<Pc>;<Pp>&w(注意中间字节 &,与请求的 final 不同):
- Pe = 事件类型:0 = 定位器不可用、1 = DECRQLP 的回复、2 = 左键按下、3 = 左键抬起、4 = 中键按下、5 = 中键抬起、6 = 右键按下、7 = 右键抬起、8 = M4(第 4 键)按下、9 = M4 抬起、10 = 离开过滤矩形。
- Pb = 按键状态位掩码:1 = 左、2 = 中、4 = 右、8 = 第 4 键。可 OR。
- Pr、Pc = 行、列(1 起算),单位取自 DECELR 的 Pu。
- Pp = 页号(现代模拟器恒为 1 —— 多页是硬件终端概念)。
为何你几乎用不到:1980 年代写的若干 CAD、终端 GIS、radar / SCADA 程序仰赖此协议。某些 xterm 扩展(xterm*set-locator-events X 资源)仍允许启用。现代交互式 UI —— tmux、htop、mc、lazygit、fzf、neovim 的 :terminal —— 全部改用 SGR 鼠标模式(?1000 启用 + ?1006 SGR 编码;见 dec-mouse-tracking 与 sgr-mouse-encoding):解析更简单、多字节坐标天然支持、跨模拟器覆盖近乎完美。
覆盖度:xterm = 完整实现(唯一广泛部署的);gnome-terminal / konsole = 部分(DECRQLP 回合成的「无指点」DECLRP);iTerm2 / kitty / wezterm / alacritty / ghostty / Windows Terminal / cmd / Linux console / macOS Terminal = 无 —— 序列被静默吞掉,不回。
仍可能用到的场景:专门面向旧 XFCE / CDE 上的 xterm;移植旧 SCADA 终端程序;测 terminfo 的 locator_* capabilities。否则直接用 SGR 鼠标模式。
规范出处: DEC VT510 RM (DECELR / DECEFR / DECSLE / DECRQLP / DECLRP) / xterm-ctlseqs
示例
# Enable locator reports (cell coords, one-shot), then query position.\nprintf \"\\033[2;0'z\" # DECELR Pn=2 one-shot, Pu=0 cells\nprintf \"\\033[1'|\" # DECRQLP — force immediate DECLRP reply\n# read reply matching: \\x1b[1;Pb;Pr;Pc;1&wimport sys\n# Set filter rectangle around rows 5-20, cols 10-60 then enable button-down events.\nsys.stdout.write(\"\\x1b[1;0'z\") # DECELR enable, cells\nsys.stdout.write(\"\\x1b[5;10;20;60'w\") # DECEFR filter rect\nsys.stdout.write(\"\\x1b[1'{\") # DECSLE enable button-down reports\nsys.stdout.flush()// Disable locator reports (clean exit).\nfmt.Print(\"\\x1b[0;0'z\")// Parse a DECLRP reply: \\x1b[Pe;Pb;Pr;Pc;Pp&w\nfunction parseDECLRP(buf) {\n const m = /\\x1b\\[(\\d+);(\\d+);(\\d+);(\\d+);(\\d+)&w/.exec(buf);\n if (!m) return null;\n return { event: +m[1], buttons: +m[2], row: +m[3], col: +m[4], page: +m[5] };\n}/* Force a single locator-position report (synchronous-ish probe). */\nprintf(\"\\x1b[1;0'z\"); /* DECELR enable, cells */\nprintf(\"\\x1b[1'|\"); /* DECRQLP */\nfflush(stdout);\n/* read reply: matches sscanf(\"\\x1b[%d;%d;%d;%d;%d&w\", &pe,&pb,&pr,&pc,&pp) */终端支持
- xterm
- 支持
- Linux console (fbcon)
- 不支持
- macOS Terminal.app
- 不支持
- iTerm2
- 不支持
- Windows Terminal
- 不支持
- cmd.exe / ConPTY
- 不支持
- kitty
- 不支持
- alacritty
- 不支持
- WezTerm
- 不支持
- Ghostty
- 不支持
- GNOME Terminal
- 部分
- Konsole
- 部分
- tmux
- 不支持
- GNU screen
- 不支持
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 不支持 | 部分 | 部分 | 不支持 | 不支持 |