?1000 Mouse Tracking
Ask the terminal to report mouse buttons and movement, and choose how the reports are encoded.
CSI ? 1000 h
- xterm
- Mouse Tracking
These modes ask the terminal to send the program a report when the mouse is used over it, instead of using the mouse itself for selecting text. They are xterm’s, in DEC’s private space. Two groups of them work together: one chooses which events are reported, the other how a report is encoded.
| Mode | Reports |
|---|---|
9 | a button press only (X10 compatibility) |
1000 | presses and releases |
1001 | presses and releases, with highlight tracking |
1002 | presses, releases, and movement while a button is down |
1003 | presses, releases, and all movement |
| Mode | Encoding |
|---|---|
| none | CSI M and three bytes: the button and the coordinates, each plus 32; coordinates beyond 223 cannot be sent |
1005 | the same, with the coordinates in UTF-8 |
1006 | SGR: CSI < b ; x ; y M for a press, m for a release, in decimal |
1015 | urxvt: CSI b ; x ; y M, in decimal |
1016 | SGR, with the coordinates in pixels rather than cells |
Mode 1007, alternate scroll, has the mouse wheel send cursor up and down keys while the alternate screen is showing and the wheel is not being reported (AlternateScroll); focus events, 1004, have their own page.
The reports go to the program, so a case cannot see them; what it can see is what DECRQM says. The cases follow xterm, which keeps one value for each group, not a flag per mode (dpmodes, really_set_mousemode):
- Setting one event mode replaces the one before it, and DECRQM reports only the latest as set. Resetting any of them turns tracking off.
- Setting one encoding replaces the one before it too, but resetting an encoding takes effect only if it is the one in use: xterm’s comment says “a reset is only effective against the matching mode”.
- Alternate scroll is off unless the
alternateScrollresource turns it on (charproc.c). - RIS turns tracking and the encoding off; DECSTR does not (
ReallyReset).
libghostty-vt tracks the events the same way, with one value, but DECRQM answers from a separate flag for each mode, so it reports a replaced mode as still set. Resetting any encoding goes back to the default encoding even if another is in use, which DECRQM does not show either: in that case it still reports the other as set. It does not know mode 1001, and it starts with alternate scroll on. The cases those touch are known differences.
Validation
MOUSE-1: Off to begin with
\e[?1000$p
\e[?1002$p
\e[?1003$p
\e[?1006$p
|____|
reply \e[?1000;2$y\e[?1002;2$y\e[?1003;2$y\e[?1006;2$y
MOUSE-2: Set and reset
\e[?1002h
\e[?1002$p
\e[?1002l
\e[?1002$p
|____|
reply \e[?1002;1$y\e[?1002;2$y
MOUSE-3: One event mode at a time
\e[?1000h
\e[?1002h # replaces 1000
\e[?1000$p
\e[?1002$p
|____|
reply \e[?1000;2$y\e[?1002;1$y
MOUSE-4: X10 replaces the others too
\e[?1003h
\e[?9h
\e[?9$p
\e[?1003$p
|____|
reply \e[?9;1$y\e[?1003;2$y
MOUSE-5: Resetting any event mode turns tracking off
\e[?1002h
\e[?1000l # not the one that was set
\e[?1002$p
|____|
reply \e[?1002;2$y
MOUSE-6: Highlight tracking
\e[?1001h
\e[?1001$p
|____|
reply \e[?1001;1$y
MOUSE-7: One encoding at a time
\e[?1006h
\e[?1015h # replaces 1006
\e[?1006$p
\e[?1015$p
|____|
reply \e[?1006;2$y\e[?1015;1$y
MOUSE-8: Resetting another encoding leaves this one
\e[?1006h
\e[?1015l
\e[?1006$p
|____|
reply \e[?1006;1$y
MOUSE-9: UTF-8 and pixel encodings
\e[?1005h
\e[?1005$p
\e[?1016h
\e[?1016$p
|____|
reply \e[?1005;1$y\e[?1016;1$y
MOUSE-10: Alternate scroll is off by default
\e[?1007$p
|____|
reply \e[?1007;2$y
MOUSE-11: DECSTR leaves tracking on
\e[?1002h
\e[?1006h
\e[!p
\e[?1002$p
\e[?1006$p
|____|
reply \e[?1002;1$y\e[?1006;1$y
MOUSE-12: RIS turns it off
\e[?1002h
\e[?1006h
\ec
\e[?1002$p
\e[?1006$p
|____|
reply \e[?1002;2$y\e[?1006;2$y