module Tput::Mouse

Overview

Normalized mouse handling.

Defines the terminal-agnostic Mouse::Event produced when parsing xterm-style mouse reporting sequences (see Tput::Input#listen). Meant as the common currency for any mouse source: applications layered on top of Tput (e.g. Crysterm) convert other sources (e.g. the Linux console gpm daemon) into this same struct.

On-the-wire encodings understood (see Tput::Input):

Defined in:

tput/mouse.cr

Class Method Summary

Class Method Detail

def self.decode_button(cb : Int32, released : Bool = false) : Tuple(Action, Button, Bool, Bool, Bool) #

Decodes the common xterm "Cb" button byte (shared by the X10 and SGR encodings) into {action, button, shift, meta, ctrl}.

Bit layout of cb:

  • bits 0-1 : button (0 = left, 1 = middle, 2 = right, 3 = none/release)
  • bit 2 : shift
  • bit 3 : meta (alt)
  • bit 4 : control
  • bit 5 : motion (a drag/move report rather than a click)
  • bit 6 : wheel (then bit 0 selects up=0 / down=1)
  • bit 7 : extra button (8-11, e.g. back/forward) — reported as Unknown

released is supplied by the caller when the encoding itself signals a release independently of the button bits (SGR's trailing m); for X10 a release is encoded as button bits == 3.


[View source]
def self.encode(io : IO, encoding : Encoding, action : Action, button : Button, x1 : Int32, y1 : Int32, *, shift : Bool = false, meta : Bool = false, ctrl : Bool = false) : Nil #

Writes the xterm mouse report for one normalized event into io, in encoding. x1/y1 are 1-based on-the-wire coordinates (callers holding 0-based cells pass x + 1/y + 1). Raw bytes are written for the legacy encoding: packed values may exceed 0x7F, which a UTF-8 String round-trip would corrupt — so give this a binary-safe io (e.g. IO::Memory) and forward its bytes.


[View source]
def self.parse_dec(cb : Int32, cx : Int32, cy : Int32, cp : Int32) : Event #

Parses a DEC-locator event report (\e[ Pe ; Pb ; Pr ; Pc [; Pp] & w). The caller maps the wire fields to these arguments: cb = Pe locator event code, cx = Pc column, cy = Pr row, cp = Pp page (1 when the terminal omits it, as xterm does). The button-state mask Pb is not currently surfaced.

Each button has a press/release pair of codes (even = press, odd = release): 2/3 = left, 4/5 = middle, 6/7 = right.


[View source]
def self.parse_sgr(cb : Int32, cx : Int32, cy : Int32, final : Char) : Event #

Parses an SGR (1006) encoded event. cb, cx, cy are the decimal parameters from \e[< Cb ; Cx ; Cy, and final is the terminating byte ('M' press/motion, 'm' release).


[View source]
def self.parse_sgr_pixels(cb : Int32, cx : Int32, cy : Int32, final : Char, cell_w : Int32, cell_h : Int32) : Event #

Parses an SGR-Pixels (DEC private mode 1016) encoded event. The wire format is identical to SGR (1006) — \e[< Cb ; Cx ; Cy M|m — but cx/cy are pixel coordinates, not cells. cell_w/cell_h are the terminal's cell size in pixels (from Tput#mouse_cell_pixels); they derive the cell coordinates carried on x/y while the raw 0-based pixels are kept on px/py. A non-positive cell size (unknown, e.g. under a multiplexer) degrades gracefully: the pixel value is used directly as the cell value rather than dividing by zero.


[View source]
def self.parse_urxvt(cb : Int32, cx : Int32, cy : Int32) : Event #

Parses a URxvt (mode 1015) encoded event. cb, cx, cy are the decimal parameters from \e[ Cb ; Cx ; Cy M. Like X10, cb carries the +32 bias and there is no explicit release distinction; unlike X10 the coordinates are decimal and unbounded.


[View source]
def self.parse_vt300(cb : Int32, cx : Int32, cy : Int32) : Event #

Parses a vt300 event report (\e[ 24 Cb ~ [ Cx , Cy ] \r). cb selects the button (1 = left, 2 = middle, 5 = right); the report is always a press.


[View source]
def self.parse_x10(cb : Int32, cx : Int32, cy : Int32) : Event #

Parses an X10 / "normal" encoded event. cb, cx, cy are the three raw bytes following \e[M, each still carrying the +32 bias.

Corrects the buggy-VTE coordinate overflow: VTE can only send unsigned chars, so a coordinate whose +32-biased byte exceeds 255 wraps modulo 256, landing below the normal 0x20 floor. A raw byte under 0x20 is unwrapped by adding a full 256 cycle to recover the original biased byte. (Adding 0xff, as before, lands one short and decodes every wrapped coordinate one cell too low.)


[View source]
def self.report_cb(action : Action, button : Button, sgr : Bool, *, shift : Bool = false, meta : Bool = false, ctrl : Bool = false) : Int32 #

Reconstructs the xterm "Cb" button byte for a report. In SGR the button is preserved on release (the trailing m signals the release); the legacy encodings use the generic "button 3" release code.


[View source]