Repository navigation
fix(native): accept UTF-8 mouse rows above U+FFFF - #42
Merged
Merged
Conversation
Ghostty computes the row code point in u32, so rows 65503 and 65534 are valid 4-byte UTF-8. The binding still rejects them, so this fails. Signed-off-by: Thomas Kosiewski <tk@coder.com> --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `medium`_ Change-Id: I8829cfec1c0e4c9792417c3219434367703453f1
Ghostty's row is u32, so cell.y + 33 cannot wrap. Only a surrogate reaches utf8Encode's catch unreachable, so keep that rule alone for both axes and drop the false 16-bit claim from the docs. Signed-off-by: Thomas Kosiewski <tk@coder.com> --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `medium`_ Change-Id: Ib9c1ea32b54dd1646a37fc2fbf01f99a052c8bcb
Member
Author
|
Verdict: PASS Parent: bf41459. I ran every scenario on Node v26.12.1 against the ReleaseSafe libghostty-vt prefix (Ghostty 48ccec1), each batch in a child process. A signal or exit 134 counted as FAIL.
Generated with |
Merged
ThomasK33
added a commit
that referenced
this pull request
Oct 30, 2026
encodeMouse first ships in this release, so #41 and #42 did not fix a released bug. Their behavior now reads as part of the new API. _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_ Change-Id: Ic6de3b1b21ac87d8274619c74fd8121ef0e333e0 Signed-off-by: Thomas Kosiewski <tk@coder.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
This is one of four small fixes left over from the mouse-encoding PR (#12).
With UTF-8 mouse mode (1005) set,
encodeMousethrowsRangeErrorfor rows 65503 to 65534. Ghostty encodes those rows as valid 4-byte UTF-8. The binding rejected them because a comment claimed Ghostty adds 33 to the row in u16 arithmetic. That is false.point.Coordinate.yisu32(src/terminal/point.zig:89), andsrc/input/mouse_encode.zig:142computescell.y + 33in u32 before the u21 cast. The row cannot wrap. Only a UTF-16 surrogate reachesutf8Encode'scatch unreachable.What changed
native/terminal.cc:ValidateUtf8MouseCoordinateloses itsis_rowparameter and thecodepoint > 65535rule. The surrogate rule still applies to both axes. The comment now states the real constraint.test/mouse-safety.test.ts: the[0, 65503]RangeError case is now a positive check. Rows 65503 and 65534 must encode asESC [ M,0x20,0x21, then U+10000 (F0 90 80 80) and U+1001F (F0 90 80 9F). The expected bytes come from the protocol: x=0 is column 1 (code point 33), y=65503 is row 65504 (code point 65536). Every surrogate case stays.README.mdandnative/README.md: the 16-bit row claim is gone. The surrogate statements stay.Scope
Only the UTF-8 row rule. The other three #12 follow-ups are separate PRs.
Blast Radius
Callers that use mode 1005 on a grid taller than 65502 rows now get bytes instead of a
RangeErrorfor the last 32 rows. Surrogate cells still throw on both axes. Other mouse formats are unaffected.Verification
All runs used Node v26.12.1.
Failing at the test commit (724f98b), ReleaseSafe addon,
npx vitest run test/mouse-safety.test.ts:Passing at the fix commit (b5712d7):
Repro script on the ReleaseSafe addon, before the fix:
After the fix:
Gates, each exit 0:
npm ci && LIBGHOSTTY_VT_PREFIX=<ReleaseFast> npm run build:native && npm run build && npm run verify: 67 tests passed.-fsanitize=undefined,float-cast-overflow -fno-sanitize-recover=all,dist/deleted) thennpm test && npm run smoke: 67 tests passed, smoke passed..agents/skills/verify-native-lifecycle/run.sh:OK: every result matches EXPECT.Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:medium