-
Notifications
You must be signed in to change notification settings - Fork 90
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
MultiProgressBar now buffers the output text to a single write #1825
Conversation
This is to avoid multiple small writes to the terminal, which can cause flickering.
I was just looking at the same problem and want to suggest also simplifying the command sequences (around line 102). Currently it repeats the cursor-up-one, clear-line control sequences for as many lines as need to be cleared. But the control sequences can tell the terminal how much to move/clear in a single command. No loop required; just fill in n:
|
@psimonyi thanks for your feedback! I've implemented your suggestions. In fact, I was able to remove the clear line tty commands altogether! I figured that it was enough to move the cursor up, and simply let the next progress update write over the previous terminal contents. I've tested this with multiple terminals while resizing them during download and it all works beautifully 😄 |
for (std::size_t i = 1; i < mbar.num_of_lines_to_clear; i++) { | ||
text_buffer << tty::cursor_up << tty::clear_line; | ||
if (mbar.num_of_lines_to_clear > 1) { | ||
text_buffer << tty::cursor_up_multiple_lines(mbar.num_of_lines_to_clear - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the approach, but please don't do it like this via a new public class.
Perhaps just inline it with a comment what the sequences mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Let me know if you are happy with how it looks now :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is much better and simpler, thank you.
Instead of sending multiple cursor_up and clear_line sequences, send a single command to move the cursor up multiple lines. This makes the tty::clear_line redundant, because the next update will overwrite the previous lines anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the contribution!
8fbbeb2
Let me link to the discussion at https://gitlab.gnome.org/GNOME/vte/-/issues/2837 with lots of details about how terminal emulators (and many other related components of the ecosystem) work under the hood when it comes to processing their input and updating their screen. Summary: Contrary to the claim of the opening report here, buffering the output cannot fully reliably eliminate flickers. It might make them magnitudes more unlikely to happen, but can never entirely stop them from happening. The only really 100% robust solution is never to erase the character cells that you soon afterwards re-populate with the desired new text. Just print the new text over the old one, replacing it, with no clearing in between. Use earsing escape sequences only if you actually wish to erase some previously present content and wish to now have blank there. I'm happy to see that things went in this direction here, I just wanted to leave an explicit note stating that this is the only truly right approach. |
Thanks for your comment @egmontkob. The vte discussion was a very interesting read. If you look at the final solution that was accepted, It contains no "clear line" commands. We now move the cursor up, and allow the following writes to write over the old text. |
Since PR rpm-software-management#1825 we are overwriting old output instead of specifically clearing it. This causes problems when messages are removed from progressbars like it happens when scriptlets finish successfully without any logs. Closes: rpm-software-management#1899 Also adds couple describing comments.
This is to avoid multiple small writes to the terminal, which can cause flickering.
On my machine (Fedora 41 GNOME) I can see that the new concurrent download status bar flickers quite a bit. I've tested this on gnome-terminal/xfce4-terminal/uterm and kitty. Only Kitty does not flicker. The flickering happens regardless if Wayland/X11 is used.
The old behaviour would issue multiple clear_line writes, followed by multiple writes to "draw" the new status bars.
The new behaviour buffers all of the screen updates for a single "frame" and then writes all of that out with a single syscall.
I've tested the code changes using gnome-terminal/xfce4-terminal/uterm and kitty. Wayland and X11 sessions. It works flawlessly for me now.
I've also tested resizing the terminal window during download, and that works as before (w/o flickering now)
I believe this also fixes #1263