CC: Tweaked

CC: Tweaked

42M Downloads

Multishell scrolls the window when the terminal is resized and the cursor is offscreen

LoganDark opened this issue ยท 8 comments

commented

Multishell scrolls the window when the terminal is resized and the cursor is offscreen. This breaks some more advanced drawing techniques (like only redrawing content of the screen that changed) because the screen scrolls unexpectedly.

There are two solutions while multishell has this behavior:

  • Always put the cursor at (1, 1) after a render. I do this currently. It means I can't use the cursor inside the program and I have to use some other visual indicator, such as a reverse-video block.
  • Always redraw the entire screen after a resize. Hardcoding routines for calculating how the screen changed when resized under multishell is too fragile, especially since it depends on the cursor position. Redrawing the entire screen is the only reasonable option.

The culprit is this block:

if y > windowHeight then
tProcess.window.scroll(y - windowHeight)
tProcess.window.setCursorPos(x, windowHeight)
end

This doesn't seem conducive to anything other than the shell - it's unexpected behavior for the screen contents to move when the terminal resizes. It's useful to keep the shell prompt on-screen in that case, but it's an unexpected implementation detail that can't be disabled by programs. I think the drawbacks outweigh the benefits. :/

Please consider removing it from multishell. IMHO, it would have made more sense in read, but CC already forgets offscreen contents by the time you receive a term_resize event, so it's not possible to reimplement there.


I'd like to note that I've seen the recent announcement post detailing SquidDev's departure from CC:T. That is quite unfortunate, especially on the day that I discovered this issue, and I'm not sure if it's possible to solve this if CC:T is no longer making releases.

I'm posting this bug report regardless just to have.

commented

You could draw to a buffer and then use that to help you redraw the screen when it resizes.

commented

You could draw to a buffer and then use that to help you redraw the screen when it resizes.

I already use buffers for compositing and reconciliation. (Also, "a buffer" on its own would not help here, as you usually want to fit your UI to the new size when the terminal resizes.) That's exactly the problem, since my buffer library assumes that it can finish a render update faster by only blitting portions of the screen that changed. There's no reason I can think of that this shouldn't be the case, and the fact that it isn't only under multishell is an inconsistency that I don't think should exist.

I don't need advice on workarounds, as I already know about them. A couple are already listed in the issue body, and I am capable of doing either one (currently I am moving the cursor to the top of the screen to prevent this behavior from occurring). However, I don't think workarounds like those should be necessary.

This behavior in multishell is surprising and unexpected and I think it should be removed.

commented

IMHO, it would have made more sense in read

It's relevant for pretty much all non-GUI programs, not just those using read. For anything which is printing output to the screen, in makes more sense to see the bottom than the top.

Really, it feel the right thing to do is just handle the term_resize event and do a full redraw on that.

commented

IMHO, it would have made more sense in read

It's relevant for pretty much all non-GUI programs, not just those using read. For anything which is printing output to the screen, in makes more sense to see the bottom than the top.

It does indeed.

Really, it feel the right thing to do is just handle the term_resize event and do a full redraw on that.

That is one of the workarounds to this behavior, yes. However, certain programs like edit technically only need to redraw the bottom line of the screen when the terminal is resized to be smaller - since the top-left portion (excluding of course the menu) will stay the same regardless of screen size.

It wouldn't be worth it to implement rendering like that in edit, but it's just an example.

I think behaviors like this should be up to the application. print, read, etc. should all have it since those are primitives used to build command-line applications, and developers can opt out of them, but stuff like multishell probably shouldn't, because there's no guarantee that the user will only be running command-line applications. GUI libraries suffer when they try to do clever things and get hit by stuff like this.

commented

That is one of the workarounds to this behavior, yes.

It is not a workaround. It is expected that a program that is not simple terminal printer (like gui based) that receives term_resize event is supposed to redraw all of its contents cause terminal has changed size in undefined way (example: Its on monitor and someone removed/added row of monitors on right side thereby increasing length of term object)

You can see monitor.lua program causing this exact thing i described here.
Also one should note that all CC programs that react to term_resize event do full rewrite.

commented

That is one of the workarounds to this behavior, yes.

It is not a workaround. It is expected that a program that is not simple terminal printer (like gui based) that receives term_resize event is supposed to redraw all of its contents cause terminal has changed size in undefined way (example: Its on monitor and someone removed/added row of monitors on right side herby increasing length of term object)

The specific behavior I'm referring to is the fact that multishell currently breaks the guarantee that the origin of the terminal resize is always the top-left, i.e. cells within both the old and new size remain the same. Although I am not quite sure if CC ever made such a guarantee, that has traditionally been how it works everywhere outside of multishell.

commented

It kinda sounds like functional behavior that was never promised to work out that way in any of CC literature.

commented

It kinda sounds like functional behavior that was never promised to work out that way in any of CC literature.

It's an implementation detail yes, but usually vanilla CC only has one implementation of behavior like this.

I suppose I would also consider it a resolution of this issue if it were specified in the documentation that term_resize events break all guarantees of what is on the screen and where it is located since that is in effect what is happening here. Then sure, the correct solution would simply be to invalidate the cache and redraw the entire screen.