kitty icon indicating copy to clipboard operation
kitty copied to clipboard

[WIP] Implement smooth and precise scrolling

Open Luflosi opened this issue 5 years ago • 24 comments

I started to implement smooth and precise scrolling, see #1123. My plan is to render to some kind of buffer (I'm currently using a texture) and then copy the right part of that buffer to the normal framebuffer to allow pixel-precise scrolling. This is still very much a WIP, my code currently doesn't even do anything with scrolling. The code is also very hacky with some of it copied straight from learnopengl.com, that I don't even know exactly what it does. A lot of the new code for example in init_cell_program() should probably be somewhere else. I also hardcoded the size of the texture. This also literally the first time I've done anything with OpenGL, so this will be difficult for me and probably take a while to finish implementing. My current problem is getting the information that tells the shader by how much to shift the content up and down from after_render() into the shader. I'm currently just using 0.1 as a constant. I think you're doing something like that in create_cell_vao() with the A1 define but I don't know how that works. Could you help me with that please? Any other feedback is also welcome.

Luflosi avatar Mar 10 '19 18:03 Luflosi

Dont worry about the awkwardness of your OpenGL code -- OpenGL is a pain to use. I will help you clean up your code after you have something working.

As for your question: If you want to convert a pixel scroll offset into an OpenGL offset, you basically divide the pixel scroll offset by the viewport height (os_window->viewport_height). Then divide that by 2 because the opengl co-ord system goes from -1 to 1 which means the full screen has length 2.

Some general comments. This will as far as I can see render blank at the bottom line when scrolling. If that is all you want to do, you could simply offset the rendering of the main shader and then draw a blank rectangle at the bottom. No need to use framebuffers at all.

kovidgoyal avatar Mar 11 '19 03:03 kovidgoyal

I didn't ask about converting the offset from pixels to OpenGL but thank you anyways because I'll need that info later. But first I need to actually copy that offset from the C code to the shader and I don't know how to do that.

As for the blank sections, my first proof of concept will have those, yes. But it won't be the same as drawing a blank rectangle at the bottom or the top because the content will be shifted by a specific number of pixels. I also plan to render more than what is currently visible on screen and then keep what was rendered as a sort of cache. This will allow me to pre-render parts that are not yet visible. It should also save a little bit of GPU time and power because I don't have to render the whole screen on every frame. This will become more important than it currently is because kitty currently only needs to render one frame per line scrolled and the user doesn't scroll 60 lines per second (or whatever FPS their monitor has) most of the time while 60 pixels per second is going to be a lot more likely, at least with high resolution input devices.

Luflosi avatar Mar 11 '19 10:03 Luflosi

you could simply offset the rendering of the main shader and then...

Oh, I missed that. But my other reason for doing it like this, still applies.

Luflosi avatar Mar 11 '19 10:03 Luflosi

Use a uniform to pass values from C to the shader. See glUniform

kovidgoyal avatar Mar 11 '19 13:03 kovidgoyal

Your tip was very helpful. My first prototype is sort of working, here is a short video: https://youtu.be/6n31SO1HJAI.

Luflosi avatar Mar 11 '19 23:03 Luflosi

@maximbaz

if you ever get to implementing improvements for scrolling, be sure to ping me for testing

Doing it now 😁🎉

Luflosi avatar Mar 11 '19 23:03 Luflosi

Nice contribution, I've been following this PR 😝 The demo on the video is awesome!

I don't have high hopes as I assume it won't work on X (since it doesn't even have precise scrolling), but I just tried anyway — when kitty opens from your branch, all I see is black screen.

I'm launching via $ PATH= /usr/bin/python . /usr/bin/bash, to avoid #1406 and to make sure my zsh config is not causing any trouble, and here's what I see in the console:

❯ PATH= /usr/bin/python . /usr/bin/bash
[071 00:59:12.726902] Failed to run kitty for update check, with error: [Errno 13] Permission denied: 'kitty'
1899 2044
0.000000
0.000000
0.000000
0.000000
0.000000

Does it give you any clue?

In the meantime, I'll quickly install sway and try it out there 😉

UPDATE: having the same behavior on sway, and this command opens kitty fine on master branch.

maximbaz avatar Mar 12 '19 00:03 maximbaz

Yeah, it won't work on X but no idea why there is a black screen. But I'd consider this code pre-alpha and to be honest I'm almost surprised it worked for me 😅. #1406 should be fixed by #1408.

Luflosi avatar Mar 12 '19 00:03 Luflosi

@maximbaz the black background was probably caused by the hardcoded size. It's still not very good, resizing the window or opening a tab so that the tab bar is shown doesn't adjust the size of the texture but that will have to wait a bit...

Luflosi avatar Mar 12 '19 17:03 Luflosi

At least the black background issue is fixed now, kitty launches fine on X11 😉 👍

I also wanted to try on sway, but for unknown to me reasons kitty doesn't work there, even on master branch, kitty's window opens but remains empty. If I provide KITTY_DISABLE_WAYLAND=1, then it launches fine (and is blurry, indication of it being running via XWayland). Might be something wrong with sway on my side, I don't usually use it.

Anyway, good job once again, I'll go back now to crying about the absence of smooth scrolling for X11 in glfw 😢

maximbaz avatar Mar 12 '19 18:03 maximbaz

@kovidgoyal what do prepare_to_render_os_window() and render_os_window() do?

Luflosi avatar Mar 13 '19 17:03 Luflosi

prepare_to_render() updates all the window global state and checks if the window needs to be rendered (i.e. if anything has changed since the last time it was rendered). render_os_window() actually renders the window by calling various functions from shaders.c

kovidgoyal avatar Mar 14 '19 01:03 kovidgoyal

Where is screen_resize() from kitty/screen.c called? If I search for it, that's the only occurrence in the entire source tree.

Luflosi avatar Apr 09 '20 10:04 Luflosi

Just to give you some input, this is really nice work @Luflosi! I'm testing on sway, and although there are some grey artifacts, in general the code works, and smooth scrolling is very pleasant! 🙂

Do let me know when you want a more thorough testing / feedback!

record_1586431224

maximbaz avatar Apr 09 '20 11:04 maximbaz

Thanks for the nice words @maximbaz. The grey artefacts are there because I didn't manage to make the rendered region bigger than the window yet. It needs to be at least one line taller to fill the grey regions. Basically everything else is still broken, like resizing, OS windows, tabs, kitty windows, background images, selections, ... This will need a lot more work and while I haven't done much for the past year, I now want to work on it again.

Luflosi avatar Apr 09 '20 11:04 Luflosi

On Thu, Apr 09, 2020 at 03:41:14AM -0700, Luflosi wrote:

Where is screen_resize() from kitty/screen.c called? If I search for it, that's the only occurrence in the entire source tree.

It becomes the resize() methos of the screen object

kovidgoyal avatar Apr 09 '20 13:04 kovidgoyal

Pity that this features seems to have been abandoned. It would be really nice for Vim.

jclsn avatar May 02 '22 10:05 jclsn

@jclsn I think this wouldn't work for vim as it takes over the terminal and performs its own scrolling simulation AFAIK, but I'm not 100% sure.

serhez avatar Aug 12 '22 22:08 serhez

@serhez Yeah, probably not

jclsn avatar Aug 13 '22 06:08 jclsn

@serhez there is vim-smoothie that adds smooth scrolling to navigation via ctrl-f and ctrl-d

Akari202 avatar Aug 13 '22 15:08 Akari202

@serhez there is vim-smoothie that adds smooth scrolling to navigation via ctrl-f and ctrl-d

There are many such plugins but they do not implement pixel-wise scrolling, the do smooth scrolling in the sense that they use a non-constant (mostly non-linear too) function to calculate the delay between each line being scrolled, I think. But it's still line-wise scrolling.

serhez avatar Aug 13 '22 15:08 serhez

@Luflosi Is this 100% abbandoned? it would be one of the biggest features for quality of life, especially with trackpads

alba4k avatar Sep 22 '22 15:09 alba4k

@jclsn Per your comment: https://github.com/neovim/neovim/issues/27583

NeilGirdhar avatar Feb 22 '24 23:02 NeilGirdhar

@NeilGirdhar I am one of these guys who refuses to use Neovim 😉

It's also been five years. I reckon @Luflosi has two kids and other priorities by now!

jclsn avatar Feb 23 '24 07:02 jclsn