SGR mouse-reporting support: the control sequences that turn reporting on and off, and a decoder for the events the terminal sends back.
Mouse reporting is opt-in. Write enable/1 to the terminal to start receiving
events and disable/0 (on teardown) to stop. While enabled, the terminal
sends each event as an SGR mouse sequence — CSI < b ; x ; y M for a
press/motion or … m for a release — which Vtex.Input surfaces as a
{:mouse, event} tuple. How much motion is reported depends on the :motion
level passed to enable/1.
Only the SGR encoding (mode 1006) is supported. It is the modern default and,
unlike the legacy X10 encoding, is unambiguous and unbounded in coordinate
range. Do not enable X10 mouse mode (CSI ? 1000 h without 1006): its
raw coordinate bytes are not representable as a control sequence and cannot be
tokenized.
enable/1 and disable/0 are the one place this otherwise input-only library
emits output, because mouse reporting cannot be received without first being
switched on. They return the bytes for you to write; the library performs no
IO of its own.
Event
A decoded event is a map:
%{
action: :press | :release | :drag | :move,
button: :left | :middle | :right
| :wheel_up | :wheel_down | :wheel_left | :wheel_right
| :none | {:button, 8..11},
x: pos_integer(), # 1-based column
y: pos_integer(), # 1-based row
mods: [:shift | :alt | :ctrl]
}
Summary
Functions
Decode an SGR mouse sequence body into an event map, or nil if malformed.
The control sequence that disables mouse reporting. Write it on teardown.
The control sequence that enables SGR mouse reporting. Write it to the terminal.
Types
@type button() ::
:left
| :middle
| :right
| :wheel_up
| :wheel_down
| :wheel_left
| :wheel_right
| :none
| {:button, 8..11}
@type event() :: %{ action: :press | :release | :drag | :move, button: button(), x: pos_integer(), y: pos_integer(), mods: [:shift | :alt | :ctrl] }
Functions
Decode an SGR mouse sequence body into an event map, or nil if malformed.
params is the CSI parameter string ("b;x;y") and final is ?M
(press/motion) or ?m (release).
Examples
iex> Vtex.Mouse.decode("0;10;5", ?M)
%{action: :press, button: :left, x: 10, y: 5, mods: []}
iex> Vtex.Mouse.decode("0;10;5", ?m)
%{action: :release, button: :left, x: 10, y: 5, mods: []}
iex> Vtex.Mouse.decode("64;3;3", ?M)
%{action: :press, button: :wheel_up, x: 3, y: 3, mods: []}
iex> Vtex.Mouse.decode("49;7;2", ?M)
%{action: :drag, button: :middle, x: 7, y: 2, mods: [:ctrl]}
@spec disable() :: binary()
The control sequence that disables mouse reporting. Write it on teardown.
Examples
iex> Vtex.Mouse.disable() =~ "1006l"
true
The control sequence that enables SGR mouse reporting. Write it to the terminal.
The :motion option chooses how much motion is reported:
:drag(default) — press, release, and motion while a button is held:all— also bare pointer motion with no button (fires on every cell the pointer crosses; a firehose, but needed for hover):none— press and release only
Examples
iex> Vtex.Mouse.enable() =~ "1002h"
true
iex> Vtex.Mouse.enable(motion: :all) =~ "1003h"
true
iex> Vtex.Mouse.enable(motion: :none) =~ "1002h"
false