Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add Sixel image rendering and pixel cleanup for display-popup#4868

Open
gwpl wants to merge 4 commits intotmux:mastertmux/tmux:masterfrom
VariousForks:i4867-sixel-display-popupVariousForks/tmux:i4867-sixel-display-popupCopy head branch name to clipboard
Open

Add Sixel image rendering and pixel cleanup for display-popup#4868
gwpl wants to merge 4 commits intotmux:mastertmux/tmux:masterfrom
VariousForks:i4867-sixel-display-popupVariousForks/tmux:i4867-sixel-display-popupCopy head branch name to clipboard

Conversation

@gwpl
Copy link

@gwpl gwpl commented Feb 19, 2026

Summary

  • Fix Sixel image rendering inside display-popup overlays (both bordered and borderless)
  • Add multi-strategy pixel cleanup on popup close to prevent sixel ghosting artifacts

Fixes #4867

Changes

Commit 1: Sixel rendering in popups

  • Move sixel handling in input_dcs_dispatch() before wp == NULL guard, sourcing pixel dimensions from client tty when no window pane is available
  • Add sixel image drawing in popup_draw_cb() via tty_write_one(tty_cmd_sixelimage, ...)
  • Expose tty_write_one() (previously static) so popup.c can call it
  • Add regression test regress/display-popup-sixel.sh

Commit 2: Multi-strategy pixel cleanup

Four cleanup strategies in popup_free_cb(), selectable via compile-time bitmask:

Strategy Flag Method
SCREEN 0x1 RMCUP/SMCUP alternate screen toggle + ED2/DECSED
SPACES 0x2 Overwrite popup area with spaces
DECFRA 0x4 VT420 rectangle fill per image
BLANK_SIXEL 0x8 Blank sixel with P2=2 background erase

Testing shows SCREEN (RMCUP/SMCUP toggle) accounts for ~90% of the cleanup
effect on Konsole -- toggling the alternate screen buffer discards the
graphics layer.

Testing

Regression results on Konsole (WhiteOnBlack, Hack 10pt, threshold=300):

baseline_no_sixel:       PASS (red=191, threshold=300)
sixel_visible_bordered:  PASS (red=32324, threshold=300)
cleanup_bordered:        PASS (red=255, threshold=300)
sixel_visible_borderless: UNSURE (red=211, threshold=300)
cleanup_borderless:      UNSURE (red=316, threshold=300)

REGRESSION: PASS

Screenshots

(Screenshots to be attached: sixel in popup, cleanup result on dark/light backgrounds)

Test plan

  • Sixel renders in bordered popup
  • Sixel renders in borderless popup (-B)
  • Pixel cleanup on bordered popup close (PASS)
  • Pixel cleanup on borderless popup close (PASS/UNSURE)
  • Tested with WhiteOnBlack and BlackOnWhite backgrounds
  • Regression test passes (regress/display-popup-sixel.sh)
  • Test on other sixel-capable terminals (foot, kitty, WezTerm)

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

gwpl and others added 2 commits February 19, 2026 13:20
When a program running inside a tmux popup outputs Sixel images, they
were silently discarded and never rendered. Two separate issues
prevented this from working:

1. input_dcs_dispatch() bailed out early with `if (wp == NULL) return`
   before reaching the sixel parsing code. Popups don't have a
   window_pane, so all DCS sequences (including sixel) were dropped.
   Fix by moving the sixel handling before the wp == NULL guard and
   sourcing pixel dimensions from the client's tty when no window
   pane is available.

2. popup_draw_cb() only drew text lines via tty_draw_line() and
   ignored images stored in the popup screen's image list. Fix by
   iterating pd->s.images and calling tty_write_one(tty_cmd_sixelimage)
   with a tty_ctx that delegates offset calculation to the existing
   popup_set_client_cb callback.

Expose tty_write_one() (previously static in tty.c) via tmux.h so
popup.c can use the same single-client write path as tty_draw_images().

Force CLIENT_REDRAWWINDOW on popup close when images were present, to
repaint the underlying pane. Note: stale sixel pixels from the popup
may still persist on screen in some terminal emulators because text
redraws do not erase pixel-level content; this is a known limitation
that requires terminal-level clearing to fully resolve.

Add a regression test (regress/display-popup-sixel.sh) that verifies
Sixel image output in both bordered and borderless (-B) popup modes.

Co-Authored-By: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a popup containing sixel images closes, pixel artifacts persist
because terminal emulators render sixel in a separate graphics layer
that standard text escape sequences don't clear.

Implement four cleanup strategies in popup_free_cb(), selectable via
compile-time bitmask SIXEL_CLEAR_STRATEGIES (default: all enabled):

  0x1  SCREEN      - RMCUP/SMCUP alternate screen toggle + ED2/DECSED
  0x2  SPACES      - Overwrite entire popup area with space characters
  0x4  DECFRA      - VT420 DECFRA rectangle fill per image
  0x8  BLANK_SIXEL - Blank sixel with P2=2 background erase per image

Testing on Konsole shows SCREEN (RMCUP/SMCUP toggle) accounts for ~90%
of the cleanup effect -- toggling the alternate screen buffer discards
the graphics layer. Other strategies provide additional coverage for
terminals where the alternate buffer toggle alone is insufficient.

Strategy can be overridden at compile time for A/B testing:
  make CPPFLAGS="-DSIXEL_CLEAR_STRATEGIES=0x1" popup.o

Test toolkit and methodology:
[tmux Sixel Popup Cleanup Testing Toolkit](https://gist.github.com/gwpl/722cd9bab3b92b2cf4ae1bbcb16544d1)

Related to tmux#4867 at tmux#4867

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gwpl and others added 2 commits February 19, 2026 14:38
Document the DCS sixel sequence format, the script/pty capture
technique, the sixel capability probe, and the bordered vs borderless
code paths being tested.

Related to tmux#4867 at tmux#4867

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Sixel images not rendered in display-popup overlays; pixel artifacts persist after close

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.