# fix\(web\): erase terminal cursor fringes between blinks · PR \#11424 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/11424)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: closed

Source repository: Unavailable fork

Source branch: fix/terminal-cursor-blink-fringe

Target branch: main

Head commit: ff042498b80c3f1994c0e1598e6f92050d3f2240

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/11424)

[Commits](https://git.cafe/pingdotgg/t3code/pull/11424/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/11424/diffs?format=markdown)

## Description

---

## What changed

Snap terminal row boundaries to device pixels and use those same boundaries for the cursor, backgrounds, selection, and text clipping. Adjacent rows share an edge, so repainting the cursor row does not touch its neighbors.

The production change is confined to the shared web/desktop renderer. Blink timing, product defaults, and the terminal protocol stay unchanged. Mobile uses its separate native renderer.

## Why

At fractional display scales, repainting an antialiased row boundary blends over the cursor edge instead of fully erasing it. This leaves faint horizontal lines during the blink's off phase. Pixel-aligned boundaries fix that without repainting the entire terminal on every blink.

Closes #11402.

```mermaid
flowchart LR
    A[Cursor on] --> B[Blink off]
    B --> C[Repaint cursor row]
    C --> D[Shared pixel edges erase the cursor completely]
```

## UI changes

Before/after Chromium reproduction using the actual renderer from `b1e223e2b0` and this branch, with identical input. The PNGs are captured at 2x density; the inset enlarges the original canvas pixels 8x. These are isolated renderer captures, not full-app screenshots.

| Before | After |
| --- | --- |
| ![Cursor edges remain during blink off](https://github.com/Lucenx9/t3code/releases/download/evidence-terminal-cursor-48311fb4d5/before.png) | ![Cursor disappears completely](https://github.com/Lucenx9/t3code/releases/download/evidence-terminal-cursor-48311fb4d5/after.png) |

[Short before/after video](https://github.com/Lucenx9/t3code/releases/download/evidence-terminal-cursor-48311fb4d5/cursor-blink.mp4). [Full comparison and integrated-terminal evidence](https://github.com/Lucenx9/t3code/releases/tag/evidence-terminal-cursor-48311fb4d5).

### Verification

- 66 focused tests pass in `renderer.test.ts` and `surface.test.ts`. The new geometry tests fail at 125% and 150% on the base renderer.
- Web package typecheck and targeted lint/format checks pass.
- All 97 real-canvas comparisons pass after the fix, covering four cursor styles, light/dark themes, text, selections, adjacent rows, four display scales, and a fractional CSS origin.
- Tested the full app in Chromium with isolated state and synthetic shell output. At 125%, the live cursor leaves no residual pixels, including after scrollback appears.
- Scoped Fallow audit passes with one thread and no introduced findings. Existing findings were left untouched.

## Checklist

- [x] This PR is small and focused
- [x] I explained what changed and why
- [x] I included before/after screenshots for any UI changes
- [x] I included a video for animation/interaction changes

Model: GPT-5. Harness: OpenAI Codex.


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Bug Fixes**
  - Improved terminal rendering across different display scales by aligning row boundaries to device pixels.
  - Corrected row heights for backgrounds, selections, text, decorations, and cursor rendering to maintain consistent vertical alignment.
  - Limited cursor updates to the affected row when appropriate, improving repaint behavior.

- **Tests**
  - Added coverage for pixel alignment, contiguous row boundaries, and targeted cursor repainting across multiple display scales.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
