fix(adapter): use unique foreground colors for Unicode placeholders in tmux

When running multiple Yazi instances in tmux panes, all instances show
the same image preview. This happens because the Unicode placeholder
implementation uses a hardcoded foreground color RGB(0,0,1) for all
instances.

In the Kitty graphics protocol's Unicode placeholder system, the
foreground color of the placeholder characters encodes the image ID.
Since all instances used the same color, they all had the same image ID,
causing tmux to display the same image in all panes.

Changes:
- Generate a unique image ID per Yazi instance based on process PID
- Encode this ID in the RGB foreground color of Unicode placeholders
- Each instance now has a unique color/ID, preventing image overlap
- Delete only the instance's specific image by ID

This properly implements the Unicode placeholder specification where
the foreground color serves as the image identifier.

Fixes the issue where multiple Yazi instances in tmux would display
the same image.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Yuval Spiegel 2025-08-06 19:16:27 +03:00 committed by sxyazi
parent 49910fcfe7
commit 7259a116d6
No known key found for this signature in database

View file

@ -9,6 +9,18 @@ use ratatui::layout::Rect;
use crate::{CLOSE, ESCAPE, Emulator, START, adapter::Adapter, image::Image};
// Generate unique image ID per Yazi instance to prevent tmux overlap
// This ID is encoded in the foreground color of Unicode placeholders
static INSTANCE_ID: OnceLock<u32> = OnceLock::new();
fn get_image_id() -> u32 {
*INSTANCE_ID.get_or_init(|| {
// Use PID to get unique ID per instance
// Limit to 24-bit RGB color space (0xFFFFFF)
(std::process::id() % 0xFFFFFE) + 1
})
}
static DIACRITICS: [char; 297] = [
'\u{0305}',
'\u{030D}',
@ -336,7 +348,8 @@ impl Kgp {
write!(w, "{s}")?;
}
write!(w, "{START}_Gq=2,a=d,d=A{ESCAPE}\\{CLOSE}")?;
// Delete only this instance's image by ID
write!(w, "{START}_Gq=2,a=d,d=i,i={}{ESCAPE}\\{CLOSE}", get_image_id())?;
Ok(())
})
}
@ -350,7 +363,8 @@ impl Kgp {
if let Some(first) = it.next() {
write!(
buf,
"{START}_Gq=2,a=T,i=1,C=1,U=1,f={format},s={},v={},m={};{}{ESCAPE}\\{CLOSE}",
"{START}_Gq=2,a=T,i={},C=1,U=1,f={format},s={},v={},m={};{}{ESCAPE}\\{CLOSE}",
get_image_id(),
size.0,
size.1,
it.peek().is_some() as u8,
@ -379,7 +393,12 @@ impl Kgp {
fn place(area: &Rect) -> Result<Vec<u8>> {
let mut buf = Vec::with_capacity(area.width as usize * area.height as usize * 3 + 50);
write!(buf, "\x1b[38;2;0;0;1m")?;
// Encode the image ID in the foreground color (RGB values)
let id = get_image_id();
let r = (id >> 16) & 0xFF;
let g = (id >> 8) & 0xFF;
let b = id & 0xFF;
write!(buf, "\x1b[38;2;{};{};{}m", r, g, b)?;
for y in 0..area.height {
write!(buf, "\x1b[{};{}H", area.y + y + 1, area.x + 1)?;
for x in 0..area.width {