Skip to content

Query Kitty Protocol support#90

Merged
atanunq merged 12 commits into
atanunq:masterfrom
hasezoey:kittyQuerySupport
Nov 26, 2025
Merged

Query Kitty Protocol support#90
atanunq merged 12 commits into
atanunq:masterfrom
hasezoey:kittyQuerySupport

Conversation

@hasezoey
Copy link
Copy Markdown
Contributor

@hasezoey hasezoey commented Nov 12, 2025

This PR refactors the way kitty protocol support is acquired by querying the terminal for both remote & local(file) support.
This should be more robust than check environment variables.

Also implements a fix for the race-condition of viuer removing the file before the terminal can finish reading it, leading to empty viu displays (in #79 this was fixed via i= and waiting for OK, but here it is solved via DSR, #79 (comment))

Depends on #85 and #87
Re #79
fixes #70
fixes #67
fixes #71

Due to kitty terminals deleting the file after fully reading it in known temporary directories.
To prevent the race condition of file removal before the terminal has finished reading it.
(which can result in empty viu displays on kitty)
Comment thread src/printer/kitty.rs Outdated
Comment thread src/printer/kitty.rs
…pport different VT levels

For example tmux does not respond with "CSI ? 6" but "CSI ? 1"
This reverts commit 9a95d34.

re discussion about some shells like bash not newlining the next prompt.
Comment thread src/printer/kitty.rs
let term = Term::stdout();

// first check if kitty protocol base-line(inline images / remote) is available
if has_remote_support(&term, &mut stdout).is_ok() {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be fantastic if we could reliably test remote support like that but some terminals don't respond to this type of sequence and it ends up displayed before the image's blocks. That's what happens on urxvt. However, seems like most modern emulators don't do that and we might be able to get away with it. Will check a few more tomorrow

Copy link
Copy Markdown
Contributor Author

@hasezoey hasezoey Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and it ends up displayed before the image's blocks.

What exactly do you mean with this? Do you mean that the escape sequence gets echoed to the terminal's output? (FYI: i know that kitty somehow echoes back the second part of the escape sequence(^[[?62;52;c) sometimes, i do not understand why, even though it is literally recommended to be done by kitty itself)
If that is the case, then to my knowledge, that is a wrong implementation of basic escape sequence handling and we shouldnt really special case that.
In any case, this extra handling, if necessary, should be able to be put in another PR instead of blocking this one.

Kitty 0.42.2

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Precisely, before the block characters are displayed. I mentioned it here because before this PR such escape sequences were sent only if well-known env vars are present.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Precisely, before the block characters are displayed.

I still dont quite understand what you mean. Do you mean this?
showcase

(the ^[[?62;52;c before the image)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, no, but this is also not ideal. I'll send you a picture once I am back on my PC.

Copy link
Copy Markdown
Contributor Author

@hasezoey hasezoey Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think i have found the problem with the screenshot:
We write to the stdout, but dont set raw mode, so characters have a chance of being printed.
Term::read_key activates raw mode, but this happens after we already send it to stdout. It does not seem to be possible to fix this with console::Term itself, but a workaround is using crossterm::terminal::enable_raw_mode (and explicitly disable it again).
Though from what i can tell, we would need to wrap every escape code + read in that (not just for kitty)

And while we are at it, why not just completely use crossterm at that point?

I would like to do that in another PR, or should it be part of this PR?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry if this is taking too long to be merged but I'd prefer to keep master publishable. That's also why I went with this PR, instead of #87. If we start using local printing we should fix it at the same time.

This is what I see in urxvt:
Screenshot_20251126_022240

Good points about raw mode, it's probably the same reason. I spent a good amount of time trying to get it to work with raw mode, using alternate screens (viuer is used in tmux, vim plugins, etc. I'm afraid to use that buffer) or other hacks to hide the output. Unless you manage to get it to work without putting too much effort in it, we can give it a shot as-is and revisit if it becomes an issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless you manage to get it to work without putting too much effort in it, we can give it a shot as-is and revisit if it becomes an issue.

My testing patch was:

diff --git a/src/printer/kitty.rs b/src/printer/kitty.rs
index 511e475..576c797 100644
--- a/src/printer/kitty.rs
+++ b/src/printer/kitty.rs
@@ -118,6 +118,7 @@ fn wait_for_dsr(stdout: &mut impl Write, stdin: &impl ReadKey) -> ViuResult {
 
 /// Query the terminal whether it can display inline images (the kitty image protocol base-line)
 fn has_remote_support(stdin: &impl ReadKey, stdout: &mut impl Write) -> ViuResult {
+    let _ = crossterm::terminal::enable_raw_mode();
     // send the query
     write!(
         stdout,
@@ -156,6 +157,8 @@ fn has_remote_support(stdin: &impl ReadKey, stdout: &mut impl Write) -> ViuResul
         }
     }
 
+    let _ = crossterm::terminal::disable_raw_mode();
+
     // The Graphics query response
     let expected = [
         Key::UnknownEscSeq(['_'].into()),

Could you test that with urxvt on your system? (though i dont know if it would fix this issue as that is output by us, not a key input from the terminal)

If we go with that, i would like to clean it up a bit (like not changing the raw mode if it is already enabled, so that we dont accidentally disable it if it is activated outside of viuer) and make it potentially a drop-guard (ie disable raw mode on drop) and put it basically everywhere we output escape sequences and expect responses.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have now tried rxvt-unicode, and even with the patch mentioned above, this is not fixed. I dont know why this terminal does not read & discards it instead of printing it, so i dont know how this could be fixed aside from a terminal blacklist.

@atanunq atanunq marked this pull request as ready for review November 26, 2025 17:20
@atanunq
Copy link
Copy Markdown
Owner

atanunq commented Nov 26, 2025

Thank you!!

@atanunq atanunq merged commit 3051d76 into atanunq:master Nov 26, 2025
3 checks passed
@hasezoey hasezoey deleted the kittyQuerySupport branch November 26, 2025 18:07
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.

Enable Kitty image protocol for Warp Infinite loop in Kitty+ZelliJ Query Kitty image support

2 participants