I am rendering a log feed for a p2p rendezvous server. When the box first renders, everything is correct, but the second render (log added) causes it to break. I’ve attached an image of what that looks like. It works fine if I call terminal.clear() before drawing, but that causes alot of flickering.
It looks like the Session start messages are writing to the stdout (or stderr possibly), and are conflicting with the state that Ratatui keeps in the two buffers. See Rendering under the hood | Ratatui for more info on how this works. Ratatui only writes the diff between the buffer states, not the full screen.
The Clear widget is only for helping make that transition from two known states. Its one job is to write empty spaces to areas of the buffer that might have previously been written with non-empty cells. This is needed as most widgets only modify the specific ares that they need to rather than blanking out the entire area.
But those rendering actions are only against the buffers, Ratatui’s understanding of what the terminal should hold after each frame. If you modify the actual terminal contents from some other part of your applicaiton, then Ratatui doesn’t know that it needs to redraw that area.
I suspect additionally that the Session start messages are also coming from another thread which happens to run at the same time as the render calls that Ratatui makes when it calls Terminal::flush() from draw().
We don’t have a good way (yet) to force Ratatui to treat the screen as having junk information that always needs to be rewritten. The right way of fixing this problem is to remove that “Session Start” output from being written.
A bit of a hacky workaround to force Ratatui to always render the full buffer if you need it (there may be other ways, but I think this one will work) is to write a junk character to every cell of the buffer using Terminal::get_buffer_mut(), then flip the two buffers with Terminal::swap(). This makes the next time that you draw diff against the junk character (choose one that will never be in your app UI) and always come up different, which will cause every screen cell to be written. This is much slower than the diff approach, but it avoids the screen flicker of doing a full clear screen. You should in general not notice writing the same character over an existing character.
Aside: one thing you should do generally is run your app in release mode to avoid the above mentioned rendering slowness - there’s a massive difference in terminal rendering speed between debug and release mode.