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 |