Repository navigation
Support SGR-Pixels mouse reporting (DECSET 1016), bump to 2.0.4 - #161
Conversation
?1016 selects a fourth mouse encoding: SGR reports carrying 1-based pixel coordinates instead of cells, as xterm does. DECRQM now answers set/reset for 1016 instead of "not recognised". A new GenerateMouseEvent overload takes the pointer's pixel position; the cell-only overload reports the clicked cell's top-left corner from CellWidthPixels/CellHeightPixels so existing hosts keep working. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The new tests embed raw ESC control bytes that should be replaced with escaped source representations.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Adds DECSET 1016 SGR-Pixels mouse reporting and releases it as version 2.0.4.
Changes:
- Adds pixel-coordinate SGR event generation with a cell-based fallback.
- Implements mode selection, reset, and DECRQM reporting.
- Adds coverage for pixel reporting and encoding transitions.
| File | Description |
|---|---|
src/XTerm.NET/XTerm.NET.csproj |
Bumps version to 2.0.4. |
src/XTerm.NET/Terminal.cs |
Exposes the pixel-coordinate mouse overload. |
src/XTerm.NET/InputHandler.Modes.cs |
Adds 1016 query/reset handling. |
src/XTerm.NET/InputHandler.cs |
Enables SGR-Pixels mode. |
src/XTerm.NET/Input/MouseTracker.cs |
Generates pixel-coordinate reports and fallback coordinates. |
src/XTerm.NET/Input/MouseInput.cs |
Adds the SGR-Pixels encoding value. |
src/XTerm.NET.Tests/RequestModeTests.cs |
Tests 1016 mode reporting and exclusivity. |
src/XTerm.NET.Tests/MouseTrackingTests.cs |
Tests pixel reports and fallback behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| public void MouseEvent_SGRPixels_ReportsOneBasedPixelPosition() | ||
| { | ||
| var terminal = CreateTerminal(); | ||
| terminal.Write("[?1000h[?1016h"); |
Perf comparison — this change, against its base3 run(s) of each side, alternating on one machine. Allocation is a count and is gated exactly. Time is a measurement, so its gate is derived from the spread this job just observed in itself rather than fixed in advance.
Each corpus is gated at assemblies measured
Perf comparison — cumulative, everything since 2.0.33 run(s) of each side, alternating on one machine. Allocation is a count and is gated exactly. Time is a measurement, so its gate is derived from the spread this job just observed in itself rather than fixed in advance.
Each corpus is gated at assemblies measured
|
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Summary
CSI ? 1016 h/lselects/resets a newMouseEncoding.SGRPixels: SGR-format reports (CSI < b ; x ; y M/m) with 1-based pixel coordinates, matching xterm (EmitMousePositionadds 1 in both 1006 and 1016 modes). It's mutually exclusive with 1005/1006/1015.Terminal.GenerateMouseEvent(button, x, y, pixelX, pixelY, eventType, modifiers)overload for hosts that know the pointer's pixel position. Other encodings ignore the pixels and still report cells.CellWidthPixels/CellHeightPixels, so dividing by theCSI 16 tcell size lands back on that cell.Tests
Host follow-up (Avalonia.Terminal)
TerminalView.Mouse.csshould call the pixel overload. Its once-per-cell motion dedupe also needs to compare pixel positions whenMouseEncoding == SGRPixels.🤖 Generated with Claude Code