GNOME Bugzilla – Bug 744774
Jerky scrolling
Last modified: 2018-10-06 21:58:10 UTC
Make the window larger than the default 80x24. Open a text editor/viewer (e.g. vim, mcview, less...) with a larger file, and press and hold the Up or Down arrow. Or, produce some output to the scrollback buffer and scroll by holding Ctrl+Shift+Up/Down. I often have a feeling that scrolling is uneven: after about every 5-10 lines of scrolling it suddenly jumps by 2 lines, skipping a position. I guess it boils down to an interference between the keyboard repeat rate (xset q: 33/sec, i.e. 30.3 ms for me) and the display update rate (VTE_UPDATE_REPEAT_TIMEOUT: 30 ms, deliberately increased by the time it takes to update the screen as per bug 730732, so probably in the ballpark of 35-40 ms). Display cycles should probably -within reasonable limits- dynamically adapt to keypresses as well as the app's output stream's characteristics, e.g. if data is received in batches at 33 FPS and it can keep up this refresh rate then it should do so. If it sees data arriving continuously then it can relax with updates (this could speed up catting giant files), but if the data stream stalls it could be much more eager to initiate a repaint, e.g. after 2ms of being idle, unless the refresh rate would become way too frequent.
Here someone seems to complain about this same issue: http://askubuntu.com/questions/34827/why-is-linewise-scrolling-in-vim-in-gnome-terminal-jerky
Bug 754971 requires pretty much the same refactoring.
A while ago I was thinking a bit how I'd do it. I think we should have 2 g_timeout objects: a short (~2ms perhaps) and a long (~30ms) one. When incoming data is processed, the long one would be created if it doesn't exist, but left intact if it's already there. The short one would always be cancelled and reinstalled. Then whichever of the two kicks in updates the screen and cancels both timeouts, so everything starts over.
Spent a few hours on this. - I still don't understand at all the process_timeout/update_timeout business and how/why processing the incoming data is handled in these methods. Basically I don't see the architecture, let alone the design decisions behind. - I couldn't come up with a proof of concept without totally breaking things and having no clue why. - All this updating/processing stuff is global (one single instance responsible for all the vte widgets). In order to fix the current bug, at least the displaying part would need to be per-terminal, meaning that a huge refactoring is inevitable (or accept that the bugfix is only for the case when no other terminal is active, otherwise scrolling might remain jerky). - It's probably not a bug that can be fixed without understanding the entire picture.
Thinking about it a bit more... I don't think there's anything we could do here. This behavior is not caused by an interference between the keyboard repeat rate and some internal VTE concept. This is caused by an interference between the keyboard repeat rate and the monitor refresh rate, both of which are out of our control. My monitor refreshes at 60.02 Hz, and my keyboard repeat rate is 33 Hz. Hence while scrolling, most of the states are present for 2 display frames, but some are only for 1. I recorded the VTE window with kazam at 60 FPS and replayed in mplayer frame by frame (the "." key) to confirm this. There weren't any half updated frames or any such ugliness potentially done by VTE. As expected, most of the frames are duplicated, but roughly every 7th or so (varying) are not. The issue is also present in any other terminal emulator. Probably 80x24 is too small for the eye to track the motion of a given line to notice these jumps, hence the need for a taller window. What a user can do is pick a keyboard repeat rate that plays nicely with the monitor refresh rate, e.g. "xset r rate 500 30" for 30 Hz, although I'm not sure it's tracked that precisely. These jumps could only be eliminated by X.Org or Wayland, by picking default keyboard rates according to the monitor. There'd be probably more downsides to this behavior than upsides.
Not sure if "notabug", "notgnome" or "invalid", picking randomly :)