-
Notifications
You must be signed in to change notification settings - Fork 330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make sixel output flicker free #1943
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this - I have tested this myself on wezterm
and found that the overall experience was smoother.
I should also mention that sixel support was originally implemented in #1211, and it predates the LockRegion
/TTY
support added in tcell 2.7.0, so thank you for taking the time to update the code accordingly.
I do have a few comments that I would like to see addressed before merging this, and even then I think I will leave it here for a while in case other users wish to test the changes themselves.
A prominent issue that I've encountered is how when I open up some file that spawns another window and the |
This fixes issues related to clearing the previous sixel data
New commit addresses the issue where if the new image was wider/taller then the previous image, there would be some residue from the previous image. The idea is that we look up the width and height of the upcoming sixel image data and lock only the region required to fit those dimensions. Next time the image gets cleared, we unlock that same region. The two calls, clearing and printing sixel can be done one after another given that the new one will simply overwrite the previous one. This effectively also takes care of thinking about clearing the image. |
@Kuchteq Thanks for looking into the overlapping image residue problem. I think it makes sense to restrict locking to only the size of the sixel image itself. Based on my testing, locking the entire preview window seems to prevent the residue from the previous image from being cleaned up. I have a few more comments, after that I'm mostly happy with the PR assuming there aren't any other bugs. |
corruption.mp4I'm unfortunately facing an issue where the preview gets corrupted if files are flipped too often. I'm not sure why this happens exactly but it probably has to do something with the caches as adding exit 1 to the end of my preview script dismisses the issue. |
I haven't been able to reproduce that issue of the preview becoming corrupt so far, it might be because the terminal is receives the sixel data interleaved with something else. But I'm not sure what it has to do with the sixel data being cached, unless that itself is corrupt. Have you tried testing on other terminals? So far I have only really used Another thing is that I tested the behavior of
Also just note that there were some recent changes committed to the master branch to fix various other issues. There are a few merge conflicts which you'll have to resolve. BTW I ended up writing my own branch for this - it's based on your work but closer to how I would implement it, and I wanted to resolve the merge conflicts on my end so I could test on top of all the recent changes. Feel free to take anything from there if it's helpful. |
Thank you for the work you put in and checking out the various options, I haven't really done so myself as I was trying to make sense of the corruption issue. I checked out your branch and it unfortunately faces the same issue, both in foot as well as wezterm (I attach a screen recording) but in wezterm the corruption looks a bit different. wezterm-corruption.mp4What I do notice is that its occurance is much rarer when the terminal spans the entire width of the screen (or is just big). Btw I might not have mentioned it but I test it by first going to a marked directory and then alternating between the jump list (I guess, default mapped to double apostrophes, mine's at ). |
I haven't been able to trigger this corruption issue at all. So you don't have anything in your config file that could trigger it? You probably are doing this already, but for testing it's easier to just have a minimal config file (just need to set |
Though so obvious, I've been oblivious to it. Minimal config works flawlessly, the reason it failed on mine is because of the on-cd command:
Which just sets the title name of the terminal for title bar purposes and that must corrupt the output because of an escape there. Perhaps a lock could help resolving that or making sure that on-cd runs before preview as this seems to be the source of the issue? This complicates things so maybe there's some way to solve it on the configuration side, though I doubt it. Furthermore, this is part of lf docs so this configuration might be commonplace. --- Edit
|
Yes, writing to
All of these happen in the event loop of the main thread so there is no problem. For the purpose of implementing features like changing the window title, rather than adding a flag option to control whether case "tty-write":
if len(e.args) != 1 {
app.ui.echoerr("tty-write: requires an argument")
return
}
tty, ok := app.ui.screen.Tty()
if !ok {
log.Printf("tty-write: failed to get tty")
return
}
tty.Write([]byte(e.args[0]))
cmd on-cd &{{
lf -remote "send $id tty-write \"\033]0;$PWD\007\""
}}
cmd on-init :{{
on-cd
}} |
Great idea, this way adds flexibility! Would we implement it as a separate merge request? |
I've already submitted it as a separate PR: #1961 Can you please test it to see if it fixes the issue for you? If so then I will merge it. |
Yup, this works, no corruption occurs from now on, I've left one comment there regarding documentation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this stage I'm mostly happy with the changes - I did find one issue however during testing though. Fixed, see #1943 (comment)
Also I was originally thinking about leaving this PR open for at least a month to get feedback, however I think there generally isn't enough interest from users that they will bother testing PR branches. So the only way to get proper feedback is to actually merge it, but then there is a chance I will have to revert it if it causes too many issues. What is your opinion on this?
Another issue to solve is when a user updates the currently previewed image to something else it currently doesn't update in the preview, somewhere there needs to be a call to forcefully update the preview with the new contents. I couldn't have figured out what's the best place to put it. Maybe somewhere in some update channel code? |
@@ -50,6 +50,10 @@ func (sxs *sixelScreen) printSixel(win *win, screen tcell.Screen, reg *reg) { | |||
return | |||
} | |||
cw, ch := ws.CellDimensions() | |||
if cw < 0 || ch < 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you meant to write:
if cw <= 0 || ch <= 0
Or this should work too:
if !(cw > 0 && ch > 0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't have a fallback plan for this condition, just be aware that this means images will no longer work on Windows, or remote connections over telnet. And there might still be some Linux terminals that will be affected as well.
@Kuchteq I think in this case it's fine to just set the diff --git a/app.go b/app.go
index e03c07e..3ca7611 100644
--- a/app.go
+++ b/app.go
@@ -431,14 +431,17 @@ func (app *app) loop() {
case r := <-app.nav.regChan:
app.nav.regCache[r.path] = r
curr, err := app.nav.currFile()
if err == nil {
if r.path == curr.path {
app.ui.regPrev = r
+ if gOpts.sixel {
+ app.ui.sxScreen.forceClear = true
+ }
}
}
app.ui.draw(app.nav)
case f := <-app.nav.fileChan:
for _, dir := range app.nav.dirCache {
if dir.path != filepath.Dir(f.path) {
|
Majorly overhaul sixel preview. Basically fixes #1738
Largely inspired by how it is done in tcell's sixel demo
I upload the comparison between current master, this pr and the last known version when there was no flicker. Terminal emulator: foot.
flicker-small.mp4
It might miss some edge cases, so please suggest any changes.