Skip to content
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

React to terminal size changes on JVM #152

Closed
mikehearn opened this issue Jan 19, 2024 · 10 comments · Fixed by #151
Closed

React to terminal size changes on JVM #152

mikehearn opened this issue Jan 19, 2024 · 10 comments · Fixed by #151

Comments

@mikehearn
Copy link
Contributor

Currently, changing the size of the terminal window whilst a progress tracker runs will cause corrupt display, as the new size isn't taken into account. There's a sun.misc.Signal API I think, that would allow for reacting to the SIGWINCH on UNIX. On Windows it's harder, I don't think the JVM exposes anything for that, not even in private APIs. Perhaps jline has some code for it.

@ajalt
Copy link
Owner

ajalt commented Jan 19, 2024

I think this would require some JNA code.

In the meantime, you could potentially poll terminal.info.updateTerminalSize(). The reason I don't do that automatically is because, due to the JNA bug mentioned in #86, we still have to shell out to stty on macs, which is potentially slow. If that ever gets resolved, we could check for a new size before each frame.

@mrbubble
Copy link

updateTerminalSize correctly detects the size change, but doesn't address the garbling of the output when the screen shrinks.
What seems to happen when using full width progress bars is that any reduction in the screen width causes the progress bar lines to wrap, so when the next animation frame comes the number of lines to clear is incorrect, and some of the lines become permanent above the animation.

@ajalt
Copy link
Owner

ajalt commented Jan 20, 2024

Oh, good point. That's a tougher problem. It seems like the solution would be to keep track of the terminal size between frames and calculate where we think the cursor is after wrapping so that we can move back to the original position.

@mrbubble
Copy link

Should be something like previousHeight * ceil(previousWitdh/newWidth), for the case where the animation width covers the entire terminal width, and the newWidth is smaller than the previous.

@mikehearn
Copy link
Contributor Author

Would printing the right number of backspace characters be an alternate way to clear the animation?

@ajalt
Copy link
Owner

ajalt commented Jan 21, 2024

Backspace is a good idea, but unfortunately terminals handle it very differently. Some will ignore it entirely, some will only delete back to the start of the line etc.

@ajalt
Copy link
Owner

ajalt commented Jan 27, 2024

Ok, so I implemented this in #151.

  • The Terminal will now check for size updates before it draws each frame, so you don't need to poll yourself, and we don't need SIGWINCH (so we can support Windows). Unfortunately, due the the JNI bug I mentioned, we don't do this on JVM macOS, since it's potentially a little too slow.
  • I try to calculate the hard wrap and compensate for it, but it's inconsistent across terminals. Even whether or not the cursor is visible seems to affect the results. So it may leave part of a frame on screen after the resize, but it will at least work on future frames.

If you're able to try out that branch and let me know what you think, I'd be appreciate it.

@mikehearn
Copy link
Contributor Author

Thanks! I'll try and make time for it in the next few weeks.

We have our own multi-task progress bar implementation that uses Mordants rendering alongside its own, but it uses the animation APIs so it should work. Do you have any pictures of what the new multi-task tracker looks like? Perhaps we can migrate, although I do like our current look.

The JNA bug could be worked around by using Panama on modern JVMs. JNA isn't necessary anymore on those versions.

@ajalt
Copy link
Owner

ajalt commented Jan 27, 2024

The multi bar looks pretty much the same, but

  • Animations are synchronized to the same framerate and start time, so you get less flickering with fewer redraws
  • Columns are (optionally) aligned

image

Panama looks promising, but it's still in preview, so it will be quite a while before we can drop JNA.

@JakeWharton
Copy link
Contributor

It's stable in JDK 22 releasing in two months. A multi-release jar would allow its use only when running on 22+.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants