Terminal: Bug: resizing doesn't work properly in Windows Terminal

Created on 23 Jun 2019  路  16Comments  路  Source: microsoft/terminal

Environment

Windows build number: [Version 10.0.18362.175]
Windows Terminal version (0.2.1715.0):

Steps to reproduce

open any terminal (PowerShell/cmd/wsl). type any command (e.g. dir, ver, uname) and enter. resize the app window to the minimum and gradually enlarge the window.

Expected behavior

information should stay the same. shouldn't break and should render all the characters like below

powershell0
wsl0
cmd0

Actual behavior


breaks apart and doesn't render properly

powershell1
wsl1
cmd1

Area-Output Issue-Bug Needs-Tag-Fix Priority-1 Product-Conpty Resolution-Fix-Committed v1-Scrubbed

Most helpful comment

If I set "historySize" : 90000, resizing will be broken vs "historySize" : 9000, it will work fine. Version: 0.5.2762.0

All 16 comments

Kinda like #1433 but this time, its with all command lines.

Here is a screen movie to illustrate the described problems above (note how the scrollbar modifies):
2019-06-24_14-16-55

Auxiliary observations:

  • VtPipeTerm.exe misbehaves as well when resizing either of the background host window, or the front window.
  • OpenConsole.exe does not have this problem, but acts very slowly when trying to resize the window (why?)

OpenConsole in debug or in release?

If vtpipeterm is hitting it too, that's definitely a conpty issue.

(I should have added that I was testing with master a5f31f77 .

OpenConsole in debug or in release?

OK the slowness was just in debug mode; I recompiled and re-tested in release mode and it's back to the usual speed ("fast").

If vtpipeterm is hitting it too, that's definitely a conpty issue.

For this my interpretation of what's going on may be erroneous because I'm also looking at the background host window, while the front window only allows resizing but not scrolling. See the animation below.
2019-06-24_19-36-51

I think I found one resize bug. A ConPTY sends two WINDOW_BUFFER_SIZE_EVENT messages when the window is restored from maximize, but the first one has the wrong size (not sure of the internals of this, but it appears in conhost/tmux/pwsh, alacritty/pwsh, and Windows Terminal).

Run this program as conevents -es in conhost and a different terminal to see the difference; maximize and restore the window. For example, restoring the WinTerm window reports 119 x 46 in the WINDOW_BUFFER_SIZE_EVENT message, but GetConsoleScreenBufferInfo returns the correct value 119 x 32.

I'm moving the conpty maximize thing to its own separate issue, #1765.

This is definitely a conpty bug, but I'm not really sure the right way to fix it. If I had to guess, when we repaint the buffer due to a resize, we're painting more or less lines than the terminal expects, which is causing the old viewport contents to slide into the scrollback.

This is pretty bad and I really want to find some time to fix it.

My best bet to fix or at least simplify this is to not emit new resized buffer from conhost, but instead run the resize on terminall's buffer too. This way both buffers should be the same and additionally terminal will have access to context of the resize, which would e.g. enable us to track selection transform (#1368), and maybe to fix the bugs above too.

It should be at least as (in)efficient as it is now (especially over network), because despite doubled work, conhost wouldn't need to transfer the buffer back to terminal, which seems comparatively costly.

It could eventually be futher optimizied so thet when user drags window the resize runs only on terminal's buffer and is reported to conhost only when the user releases LMB (but this would reqiure to freeze sth like the conhost does when scrolling?).

And since you want to support existing 3-party terminals - they handle resize themselfs. So while the present solution should work, it will be unusual to them and may cause some troubles such as we have now (even if we resolve them on terminal side).

And finally, in passthrough mode terminal would have to resize the buffer itself.

Currently, the terminal _does_ also resize it's buffer at the same time as when it requests a resize with the conpty. We're using an older resize algorithim right now in the Terminal, that only does a "traditional resize". The terminal doesn't try to reflow text in its buffer at all (like conhost does). The result of this is that when there's text outside the viewport in the terminal, the rows of text are going to get clipped to the width of the terminal. If you resize down to 5 chars wide, _every_ row is going to only have 5 chars in it.

Right now, when the console (conpty) resizes, it might reflow text, to try and maintain line wrapping. If conpty didn't re-emit the state of its buffer after the resize, then a terminal that didn't support resize with reflow would be in a torn state with the pseudoconsole.

What we _should_ be doing is reusing conhost's ResizeWithReflow in the terminal. It's a method that's a little tightly tied to conhost itself currently, which is why we haven't had a chance to pull it out quite yet.

Now, there might actually be a better way to handle resizes that aren't so chatty. There's probably a class of resize operations that don't need to force a repaint. We might even want to experiment with having conpty disable resize with reflow entirely, though that might be a strictly worse experience (as text that's cut off from the conpty will be lost forever, and when it's repainted, the terminal will lose it too).

Part of the oddity of all this is due to the fact that conpty has to maintain its own buffer state - passthrough mode might not have so much difficulty with this scenario.

We could almost certainly have a mode for the terminal where it doesn't resize until the drag handle is released. That deserves its own issue (#2140)

Couldn't we just ResizeWithOverflow on both conhost and terminal, without any rendering and repainting in the process (VT, not graphical rendering ofc)? If the input (buffer) is the same and we run the same operation, then output should also be the same.

Part of the problem is that we don't _know_ the terminal connected to conpty is the Windows Terminal. If it was something like xterm, and conpty reflowed its buffer, but xterm didn't, then the terminal and the conpty buffers will be in a torn state.

But is it appropriate for a terminal not to resize it's buffer, and even more, resize it the same way we do? I don't suppose there is a global standard for this, but I don't see any other way this could be done.

If I set "historySize" : 90000, resizing will be broken vs "historySize" : 9000, it will work fine. Version: 0.5.2762.0

If I set "historySize" : 90000, resizing will be broken vs "historySize" : 9000, it will work fine. Version: 0.5.2762.0

OMG, it really works! version: 0.5.2681.0

Another repro from another thread:

Steps to reproduce

  1. SSH to a linux. I tired centos7.
  2. Maximize the windows terminal window.
  3. Enter a command which print something to the terminal. for example "ls".
  4. Restore down the window.
  5. keep pressing enter to create new lines.

Expected behavior

Nothing happens.

Actual behavior

Previous message is shown again.

bugreportjpg

If I set "historySize" : 90000, resizing will be broken vs "historySize" : 9000, it will work fine. Version: 0.5.2762.0

It seems that the historySize limit seems 32K - possible_screen_rows. So if your terminal can have 120 lines at most, historySize should be 32648 or less. So practically, the value around 32600 can be good enough; 9999 is too small for me anyway.

@jjoos thanks, it works, the max num seems 32 723,
"historySize": 32723,

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mdtauk picture mdtauk  路  3Comments

ghvanderweg picture ghvanderweg  路  3Comments

dev-logan picture dev-logan  路  3Comments

alabuzhev picture alabuzhev  路  3Comments

miniksa picture miniksa  路  3Comments