kitty
kitty copied to clipboard
[WIP] Implement smooth and precise scrolling
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.
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.
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.
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.
Use a uniform to pass values from C to the shader. See glUniform
Your tip was very helpful. My first prototype is sort of working, here is a short video: https://youtu.be/6n31SO1HJAI.
@maximbaz
if you ever get to implementing improvements for scrolling, be sure to ping me for testing
Doing it now 😁🎉
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.
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.
@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...
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 😢
@kovidgoyal what do prepare_to_render_os_window()
and render_os_window()
do?
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
Where is screen_resize()
from kitty/screen.c
called? If I search for it, that's the only occurrence in the entire source tree.
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!
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.
On Thu, Apr 09, 2020 at 03:41:14AM -0700, Luflosi wrote:
Where is
screen_resize()
fromkitty/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
Pity that this features seems to have been abandoned. It would be really nice for Vim.
@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 Yeah, probably not
@serhez there is vim-smoothie that adds smooth scrolling to navigation via ctrl-f and ctrl-d
@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.
@Luflosi Is this 100% abbandoned? it would be one of the biggest features for quality of life, especially with trackpads
@jclsn Per your comment: https://github.com/neovim/neovim/issues/27583
@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!