DEC locator suite — DECELR / DECEFR / DECSLE / DECRQLP (mouse / locator events)
The original DEC pointing-device protocol (predates xterm SGR mouse modes by a decade). Four sequences enable, filter, select, and query locator events; modern interactive UIs use SGR mouse modes (`?1000` + `?1006`) instead.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\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 / 7cDescription
The DEC locator protocol predates the xterm extended mouse modes by a decade and is how VT300+ hardware terminals (and software emulators when bumped to a high DECSCL conformance — see `decscl-compat-level`) report pointing-device events. Four sequences make up the family — all share the single-quote (`0x27`) intermediate byte: - **DECELR** — *Enable Locator Reports* — `\x1b[<Pn>;<Pu>'z` - `Pn`: `0` = disable locator reports, `1` = enable, `2` = enable for one report only (then auto-disable). - `Pu`: `0` or `2` = report coordinates in character cells, `1` = report in device units (pixels). - Once enabled, the terminal sends a DECLRP report on every button transition that passes the DECSLE filter, plus one when an outside-the-rectangle move happens (if DECEFR has set a rectangle). - **DECSLE** — *Select Locator Events* — `\x1b[<Pm>'{` - `Pm`: `0` = only explicit DECRQLP requests trigger a report; `1` = button-down events trigger reports; `2` = disable button-down reporting; `3` = button-up events trigger reports; `4` = disable button-up reporting. - May be repeated with different `Pm` values to enable button-down AND button-up: `\x1b[1'{\x1b[3'{`. - **DECEFR** — *Enable Filter Rectangle* — `\x1b[<Pt>;<Pl>;<Pb>;<Pr>'w` - Defines an inclusive rectangle: top row, left col, bottom row, right col. Locator movement *outside* the rectangle triggers one DECLRP report, then the filter is auto-disabled. - Used for cursor-tracking apps that only care about 'mouse exited my widget' transitions. - **DECRQLP** — *Request Locator Position* — `\x1b[<Ps>'|` - `Ps`: number of transactions (currently always `1`). - Forces an immediate DECLRP report regardless of filter / event settings. **DECLRP — the reply** — `\x1b[<Pe>;<Pb>;<Pr>;<Pc>;<Pp>&w` (note the `&` intermediate, distinct from request finals): - `Pe` = event type: `0` = locator unavailable (no pointer), `1` = response to DECRQLP, `2` = left button down, `3` = left button up, `4` = middle down, `5` = middle up, `6` = right down, `7` = right up, `8` = M4 (button 4) down, `9` = M4 up, `10` = locator outside filter rectangle. - `Pb` = button-state bitmask: `1` = left, `2` = middle, `4` = right, `8` = button 4. OR them together. - `Pr`, `Pc` = row, column (1-indexed) in whatever units DECELR's `Pu` selected. - `Pp` = page number (always `1` on modern emulators — multi-page is a hardware-terminal concept). **Why you almost certainly don't need this**: certain legacy CAD, terminal-based GIS, and radar / SCADA apps written in the 1980s expect this protocol. Some xterm extensions (the `xterm*set-locator-events` X resource) still enable it. Modern interactive UIs — tmux, htop, mc, lazygit, fzf, neovim's `:terminal` — all use SGR mouse modes (`?1000` enable + `?1006` SGR encoding; see `dec-mouse-tracking` and `sgr-mouse-encoding`) because they're easier to parse, support multi-byte coordinates trivially, and have near-universal cross-emulator coverage. **Coverage matrix**: **xterm** = full implementation (only widely-deployed emulator that does). **gnome-terminal** / **konsole** = partial (DECRQLP returns a synthetic 'no pointer' DECLRP). **iTerm2** / **kitty** / **wezterm** / **alacritty** / **ghostty** / **Windows Terminal** / **cmd** / **Linux console** / **macOS Terminal** = none — the sequences are silently consumed and produce no reply. **When you might still reach for it**: targeting xterm specifically on a legacy XFCE / CDE system; porting old SCADA terminal apps; testing terminfo entries for `locator_*` capabilities. Otherwise use SGR mouse modes.
Spec citation: DEC VT510 RM (DECELR / DECEFR / DECSLE / DECRQLP / DECLRP) / xterm-ctlseqs
Examples
# 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) */Terminal support
- xterm
- yes
- Linux console (fbcon)
- no
- macOS Terminal.app
- no
- iTerm2
- no
- Windows Terminal
- no
- cmd.exe / ConPTY
- no
- kitty
- no
- alacritty
- no
- WezTerm
- no
- Ghostty
- no
- GNOME Terminal
- partial
- Konsole
- partial
- tmux
- no
- GNU screen
- no
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | no | no | no | no | no | no | no | no | no | partial | partial | no | no |