zellij-org / zellij

A terminal workspace with batteries included
https://zellij.dev
MIT License
20.81k stars 638 forks source link

Cursor flickers even when no repainting is needed #1903

Open xJonathanLEI opened 1 year ago

xJonathanLEI commented 1 year ago

Basic information

zellij --version: zellij 0.33.0 stty size: 34 97 uname -av or ver(Windows): Linux dev 5.4.0-131-generic #147-Ubuntu SMP Fri Oct 14 17:07:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Further information

This has actually been reported in the Discord channel, and I understand that it's not immediately actionable due to some technical debt to be resolved, but I'm still creating the issue here for better tracking.

The flickering is mostly only noticible when using Zellij over SSH. It's quite distracting when editing text with Vim as the cursor disappears briefly with every keystroke. Somehow Helix doesn't suffer from this in normal mode, but in insert mode it still flickers.

To reproduce it, simply open Zellij in an SSH section, then hold down the backspace key.

Expected result: nothing should happen as no repainting is needed.

Actual result: the cursor blinks.

Trying the same thing in tmux 3.3a gives no flickering.

According to @imsnif, this is because the plugins do not use an output buffer (like the virtual DOM in React), and are always repainted. Thus fixing this would require changes on the plugin system.

utkarshgupta137 commented 1 year ago

Any updates on this? I'm noticing this issue with macOS + Alacritty + Zellij + NeoVim + LazyVim (all latest). The cursor flickers if any part of the screen updates. It is especially noticeable if you have animated notifications or animated indent lines enabled. Or when doing cargo build where the last line updates a lot. Outside Zellij, there is no flickering. With Zellij it flickers a lot.

According to @imsnif, this is because the plugins do not use an output buffer (like the virtual DOM in React), and are always repainted. Thus fixing this would require changes on the plugin system.

I'm using compact-bar only. Since most of the plugins right now (as listed in the docs) are fairly static, would it not make sense to only update them once every few seconds or with any Zellij specific keystroke? At least as a temporary workaround?

imsnif commented 1 year ago

The plugins should no longer be an issue (the explanation in this issue is out of date). If this still happens in the latest release (0.36.0 at the time of this writing) I'd be happy to take another look at it and find out what's wrong.

I do need some help though. Could you help me out with a minimal reproduction? Something that does not involve so many moving parts? Because even if I install neovim and all of these plugins, it's very likely that I will not be able to reproduce this issue exactly. If you're unable to reproduce it with eg. just a certain vanilla piece of software without plugins, then I'll ask that you try to reproduce this issue with the --debug flag as described in our ISSUE_TEMPLATE. That way I can reproduce it 100% and find the cause.

utkarshgupta137 commented 1 year ago

Basic information

alacritty --version: 0.12 wezterm --version: wezterm 20230501-084619-d0e9a034 zellij --version: 0.36 stty size: 63 238 uname -av or ver(Windows): Darwin utkarsh-mbp 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar 6 20:59:28 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6000 arm64

Further information

Start Alacritty or WezTerm nightly (which is supposed to have the faster WebGPU). git clone git@github.com:zellij-org/zellij.git rm -rf $TMPDIR/zellij-* zellij --debug setup --clean cargo build

Without Zellij: https://user-images.githubusercontent.com/5155100/236430177-c180d8fc-18db-4d0b-8c46-c96881b4696c.mov With Zellij: https://user-images.githubusercontent.com/5155100/236430246-118fa881-db94-4dbf-a6d3-984c03129b17.mov

To be fair, even without Zellij, there is a little flickering in Alacritty, but with Zellij, the flickering is too much & too distracting.

Logs

I've done 2 invocations:

zellij.log zellij-11.log

imsnif commented 1 year ago

Hey @xJonathanLEI - I issued a fix for this issue in the PR linked above.

@utkarshgupta137 - the issue you mention is different and a bit more involved to fix. In short, it happens because we read the terminal output from the pty in an async loop. Due to the nature of said loop, we sometime get partial output that is fixed in the next render when we get more output. Buffering it is a bit tricky because it's hard to identify when the output actually is partial.

I plan on looking into that issue a bit more in the future, as its fix might require a bit of an architecture change.

xJonathanLEI commented 1 year ago

@imsnif Great! Happy to test it out!

utkarshgupta137 commented 1 year ago

Hey @xJonathanLEI - I issued a fix for this issue in the PR linked above.

@utkarshgupta137 - the issue you mention is different and a bit more involved to fix. In short, it happens because we read the terminal output from the pty in an async loop. Due to the nature of said loop, we sometime get partial output that is fixed in the next render when we get more output. Buffering it is a bit tricky because it's hard to identify when the output actually is partial.

I plan on looking into that issue a bit more in the future, as its fix might require a bit of an architecture change.

Let me know if I can help in any way. This is the only complaint I have about Zellij which is otherwise perfect.

imsnif commented 1 year ago

Let me know if I can help in any way. This is the only complaint I have about Zellij which is otherwise perfect.

I'm happy to hear that! I apologize ahead of time that it might take me a while to get to it. The way I see things, since Zellij is still pre 1.0, these sorts of issues* are to be expected and so they usually get a lower priority. I try to fix them as they come, but if the fix is involved as this one is it sometimes gets postponed to a much later stabilization run.

*to be clear: "these sorts of issues" are visual glitches that don't crash the app and can be classified as "minor annoyance"

xJonathanLEI commented 1 year ago

It's weird. I just tested again (have not been daily driving with Zellij for a while due to the lack of session switching), and it turns out the issue was actually already gone with 0.34.0 (yes I did re-test 0.33.0 and the issue is still there), the very release after this issue itself was submitted.

That means this issue itself has been fixed since last December, and whatever that got fixed last week is not directly related to this.

Maybe we can close this then?

imsnif commented 1 year ago

That's great to hear, @xJonathanLEI (also, native session switching is coming soon, but if you'd like for now there are a bunch of community alternatives. Thanks for checking!

I still want to get to the bottom of what @utkarshgupta137 was talking about. So, with the latest version I tried this with/without Zellij and I'm at a point where I'm not sure there's a difference. On the ANSI/VT level this happens because cargo sends us a clear-line before it renders the Building... line. I'm pretty sure this happens everywhere and that we don't chunk stuff wrong as I thought before.

So @utkarshgupta137 - could you try with the latest version and see if there's still a noticeable difference? If so we're going to have to try and find a way to measure it, because I can't tell at this point.

utkarshgupta137 commented 1 year ago

I'm on v0.37.0. I'm not sure, but I feel it might be slightly better. I would say there is still a noticeable difference. Did you notice a difference in the videos I had previously shared?

imsnif commented 1 year ago

I did, but I do not with the recent version. I'm pretty bad at noticing these things though. If you think this is still around in the latest version, I'll try to play with this some more when I have the time. In any case, I think after the various fixes this issue has been significantly reduced, for all those scrolling down to the last comment to see what's up :)

imsnif commented 1 year ago

Actually, @utkarshgupta137 - would you be willing to run a version with a diff and seeing if you notice a difference? I have this theory I'm playing around with that this has to do with output processing when reading from the socket.

It would basically involve adding these lines:

    let mut orig_termios = orig_termios.clone();
    orig_termios.output_flags.remove(OutputFlags::OPOST);
    orig_termios.output_flags.remove(OutputFlags::ONLCR);

Here: https://github.com/zellij-org/zellij/blob/main/zellij-server/src/os_input_output.rs#L227

Then running: cargo x install /tmp/test-zellij-version, running /tmp/test-zellij-version, and seeing if you notice a difference.

What say you?

utkarshgupta137 commented 1 year ago

Actually, @utkarshgupta137 - would you be willing to run a version with a diff and seeing if you notice a difference? I have this theory I'm playing around with that this has to do with output processing when reading from the socket.

It would basically involve adding these lines:

    let mut orig_termios = orig_termios.clone();
    orig_termios.output_flags.remove(OutputFlags::OPOST);
    orig_termios.output_flags.remove(OutputFlags::ONLCR);

Here: https://github.com/zellij-org/zellij/blob/main/zellij-server/src/os_input_output.rs#L227

Then running: cargo x install /tmp/test-zellij-version, running /tmp/test-zellij-version, and seeing if you notice a difference.

What say you?

Well it breaks the output from the terminal. The cursor doesn't move to the start of the new line before printing it, resulting in output like so:

image

Same result even if only one of the flags is removed.

dinhlongviolin1 commented 4 weeks ago

Not sure if anyone still have this. I am using macOS + Wezterm + Zellij + NeoVim + LazyVim and also experience the same issue with cursor flashing and flickering when moving between lines.