Skip to content

release: 0.1.36 — terminal scroll & rendering overhaul, Vietnamese text fix#69

Merged
thangnm93 merged 9 commits into
masterfrom
develop
Jun 13, 2026
Merged

release: 0.1.36 — terminal scroll & rendering overhaul, Vietnamese text fix#69
thangnm93 merged 9 commits into
masterfrom
develop

Conversation

@thangnm93

Copy link
Copy Markdown
Collaborator

Summary

Releases 0.1.36: fixes mouse-wheel scrolling inside mouse-aware TUIs (claude CLI, htop, vim, tmux), decomposed (NFD) Vietnamese text rendering, and scrollback drift at the buffer cap; adds a per-line picture render cache (~7× less per-frame paint work), Shift+PageUp/PageDown scrollback paging, and a right-click Reset Terminal recovery action.

Changes

Type of change

  • release — version release to master

How was this tested?

  • cd app && flutter analyze — no new warnings
  • cd app && flutter test — 1371 tests pass (20 new: mouse-report encoding, NFC/NFD composition, scroll behavior, picture-cache pixel equivalence)
  • Manually verified on: macOS (wheel inside claude --resume, NFD filenames via ls, seq 1 500 scrollback, Shift+PageUp, Reset Terminal)

Checklist

  • PR title follows Conventional Commits
  • Code and comments are written in English
  • New/changed behavior is covered by tests
  • No secrets, credentials, or personal data in the diff

Required when targeting master (release PRs)

  • CHANGELOG.md updated — [Unreleased] moved to [0.1.36], comparison links updated (added missing 0.1.33–0.1.36 links)
  • Version bumped in app/pubspec.yaml (0.1.36+1)
  • CLAUDE.md updated (xterm fork patch notes)
  • docs/roadmap.md updated (0.1.36 shipped section)
  • Wiki release notes prepared (docs/wiki/User-Guide-Terminal.md — Scrolling section)

- CHANGELOG 0.1.35: add macOS universal build, perf/size pass, and the
  VS 2026 Windows build fix alongside the existing entries
- roadmap: bump to 0.1.35, move path jump / universal build / perf pass
  to Shipped, refresh Top 3 (K8s panel shipped in 0.1.34 — replaced by
  Docker panel completion)
- wiki: Getting Started points at the universal DMG (Apple Silicon +
  Intel); SFTP guide documents the Go-to-path breadcrumb editor
Wheel up/down were reported with button codes 68/69 (flag 64 added to the
X11 button number instead of its low two bits), which no application
recognizes — mouse-wheel scrolling was dead inside every mouse-aware TUI
(claude CLI, htop, vim mouse=a, lazygit, tmux with mouse on). Wheel
buttons are now encoded as 64-67 per the xterm spec.

Normal/UTF report mode also added an extra +1 to the row byte, placing
every mouse event one row below the pointer.

Closes #65
Buffer.writeChar wrote every codepoint into its own cell, including
zero-width combining marks — decomposed (NFD) Vietnamese text (macOS ls
filenames, output of many tools) rendered with one displaced cell per
diacritic and a wrong cursor column.

A zero-width mark is now canonically composed (NFC, via unorm_dart) with
the codepoint in the preceding cell when a precomposed form exists; every
Vietnamese letter has one, so Vietnamese NFD coverage is complete. The
base cell's style is preserved and wide-char continuation cells are
skipped. Marks with no precomposed form keep the legacy own-cell
behavior (the cell model stores a single codepoint).

Closes #67
Shift+PageUp / Shift+PageDown page through the scrollback locally
(standard terminal-emulator behavior); only in the main buffer, so
alternate-screen apps still receive the keys.

Terminal.recoverFromStuckState() is the local equivalent of reset for a
full-screen app that died uncleanly (crash, kill -9, dropped SSH
connection) and left the session trapped in the alternate screen with
mouse reporting on — wheel scrolling appeared completely dead at a
prompt. Wired to a new right-click 'Reset Terminal' menu item.
Rendering painted every visible cell as its own Paragraph every frame
(~10k drawParagraph calls for a 50x180 viewport) and re-ran keyword
regexes per frame. Visible lines are now painted via cached per-line
recorded Pictures keyed by a new monotonic BufferLine.version, so
scrolling and steady output replay O(visible lines) pictures instead:
~7x less per-frame paint work in the included benchmark, with keyword
highlights baked into the cached picture (regex runs on line change
only). The LRU cache (1024 entries) is invalidated on
textStyle/textScaler/theme/font/keyword-rule changes; pixel equivalence
with the direct path is covered by tests.

Scrollback trim compensation: once the buffer reaches maxLines, each new
line trims one from the top while the pixel offset stayed put, so the
content a scrolled-up reader was viewing streamed past uncontrollably.
The circular buffer now exposes a monotonic droppedLines counter and
RenderTerminal shifts the offset by the trimmed amount each layout
(clamped at 0; re-baselined on main/alt buffer switches).

Closes #66
…icode

fix(terminal): wheel scrolling in TUIs, NFD Vietnamese rendering, scrollback stability + render perf
- version: 0.1.35+1 -> 0.1.36+1
- CHANGELOG: [Unreleased] -> 0.1.36 (2026-06-12); add the missing
  0.1.33-0.1.36 comparison links
- roadmap: bump to 0.1.36, add the terminal scroll & rendering overhaul
  to Shipped (wheel in TUIs, NFD Vietnamese, scrollback stability,
  render cache, paging keys, Reset Terminal)
- wiki: Terminal guide gains a Scrolling section (wheel behavior in
  full-screen apps, Shift+PageUp/PageDown, Reset Terminal recovery)
wcwidth is 0 for NUL as well as combining marks, and a NUL continuation
cell is written after every wide (CJK) character — each one paid for a
string allocation plus an unorm.nfc() call on the hottest write path.
Guard the composition attempt with codePoint >= 0x0300 (canonical
combining marks all live there), so CJK streams skip it entirely.

Found by post-release code review of #68.
@thangnm93 thangnm93 merged commit 0a8cb77 into master Jun 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant