Skip to content
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

fix cursor trail not displaying in certain cases #8092

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

coffe789
Copy link

@coffe789 coffe789 commented Nov 30, 2024

The issue

The cursor trail will occasionally either not display when the cursor jumps, or more commonly it will initially not display, and then appear shortly after to create a glitchy-looking effect.

I found this is reproducible in vim/neovim depending on how you hold down the keys. If you do not immediately release a keypress, eg you hold '$' to go to the end of a line the trail will not appear. If you hold the key for a short while and then release, the animation will start when you release (although you are only catching the end of the animation). Under the right conditions, this can also be replicated by running a script that simply prints control codes to move the cursor (I can give more details if needed).

This may be difficult to reproduce yourself, because it is dependent on the system clock. It's reproducibility seems to be dependent on which file is open. Personally I could reproduce it 100% with a fresh vim config in kitty/cursor_trail.c.

My diagnosis

The line I have changed previously compared the cursor_trail config option to the time since the cursor was changed. To me this seems unintentional, as cursor_trail is supposed to be treated like a boolean from my understanding. As a consequence if you set cursor_trail in your config to a large value (eg 100000000) the trail will stop working altogether.

Anyway, it seems it is possible for now - WD.screen->cursor->position_changed_by_client_at to return a negative value which will cause this condition to fail. I assume the reasoning for this is that now is not actually the current time, it was measured far up the stack, and it is possible for more measurements to occur before the next now is measured. If I print the value while using vim, I can see when I press a key a negative value is printed, and when I release the key a positive value is printed (hence why the animation only starts when you release).

I think what the author intended here was to stop checking for updates after the cursor trail animation is finished, so in pseudocode:
OPT(cursor_trail) && sec_to_nanosec(OPT(cursor_trail_decay_slow)) < monotonic() - WD.screen->cursor->position_changed_by_client_at

As it stands though my solution should be just as performant as the master branch, as the condition was essentially never false. If we are interested in adding some performance checks as described above I will consider it. Although going up the stack to ensure the now variable is used correctly will likely be too difficult given my knowledge of the codebase.

@kovidgoyal
Copy link
Owner

@jinhwanlazy please review

@jinhwanlazy
Copy link
Contributor

jinhwanlazy commented Dec 6, 2024

Sorry for the late response.

I was able to reproduce the bug and can confirm that the issue is fixed by your PR. However, I'm against this change.
The check now - WD.screen->cursor->position_changed_by_client_at is there to prevent another issue where the trail animation jumps between different positions. Please see the videos below - With and without your commit, I'm scrolling the cursor down in a tmux session over SSH, and the server is under heavy load:

simplescreenrecorder-2024-12-06_19.54.58.mp4
simplescreenrecorder-2024-12-06_19.52.53.mp4

The delay time set by cursor_trail effectively reduces the trail following temporary cursor positions. By changing the value of cursor_trail, I can adjust the trade-off between reducing these glitches and the trail's responsiveness . Here it is set to 5.

While I didn't expect the condition value happen to be negative, it doesn't seem to be the root cause of the problem. From my observation, it looks like the rendering is being delayed by long key presses, even though the trail is properly triggered under the hood.

Please give me some time to figure out what's happening.

@coffe789
Copy link
Author

coffe789 commented Dec 8, 2024

I see, it may be worth documenting that this is a feature in the default config file?

I was fairly convinced by my testing that the negative value was the root cause. Since the condition fails, the ct->edge members are not updated with the new position until the cursor trail is updated again.

As soon as update function is called again we go back to normal, regardless of whether the key is held down again (but the release key event will always trigger it). The update function seems to be called a handful of times when neovim is initializing all its plugins - so I have to wait a few seconds before I can reproduce the issue.

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.

3 participants