[PR #4354] [CLOSED] When the Terminal is resized, don't remove lines from scrollback #25713

Open
opened 2026-01-31 09:11:18 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/4354
Author: @zadjii-msft
Created: 1/24/2020
Status: Closed

Base: masterHead: dev/migrie/b/3490-resizing-but-no-invalidateall-ing


📝 Commits (10+)

  • b5c8c85 let's first move reflowing to the text buffer
  • 9aec694 add a doc comment because I'm not a barbarian
  • 1a2654d Try to wrap the line properly with conpty
  • aae6ce6 This works, fixing the ECH at end of wrapped line bug
  • 416be46 This is some cleanup, almost ready for PR but I need to write tests which are blocked on #4213
  • 4319589 start by authoring a simple test class
  • 399b002 This seems to fix it?
  • 38ebbb6 This is good, but when we resize down quickly, sometimes a line gets duplicated.
  • c8c794f Horrifyingly try to not increment the buffer in the middle of multiple resize operations.
  • ee08a5b Revert "Horrifyingly try to not increment the buffer in the middle of multiple resize operations."

📊 Changes

19 files changed (+556 additions, -72 deletions)

View changed files

📝 src/cascadia/TerminalCore/Terminal.cpp (+30 -3)
📝 src/cascadia/TerminalCore/Terminal.hpp (+7 -2)
📝 src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp (+264 -13)
src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp (+108 -0)
📝 src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj (+1 -0)
📝 src/host/ConsoleArguments.cpp (+14 -0)
📝 src/host/ConsoleArguments.hpp (+4 -0)
📝 src/host/VtIo.cpp (+15 -0)
📝 src/host/VtIo.hpp (+4 -0)
📝 src/host/getset.cpp (+9 -1)
📝 src/host/globals.cpp (+16 -0)
📝 src/host/globals.h (+4 -0)
📝 src/host/screenInfo.cpp (+39 -5)
📝 src/host/screenInfo.hpp (+9 -1)
📝 src/host/ut_host/ConptyOutputTests.cpp (+5 -0)
📝 src/host/ut_host/VtRendererTests.cpp (+3 -3)
📝 src/inc/test/CommonState.hpp (+13 -8)
📝 src/renderer/vt/state.cpp (+6 -33)
📝 src/renderer/vt/vtrenderer.hpp (+5 -3)

📄 Description

Summary of the Pull Request

This PR fixes a bug in the Windows Terminal, where decreasing the height of the window would cause some lines from the scrollback to be lost. While a seemingly trivial bug, this actually involved some elaborate manipulation of how conpty decides to render a resize operation.

References

PR Checklist

Detailed Description of the Pull Request / Additional comments

Conpty was not emitting the correct thing when you'd decrease the height of the viewport. When you increase the height of the window, we'd both invalidate the entire buffer, and insert new lines to the bottom of the buffer. What this meant is that on every height-only resize, we'd re-emit the entire viewport.

  • If you resized down twice (From R to R-1 to R-2), once during the frame being emitted by conpty, the Terminal would try to process the R-1 lines emitted by conpty when there are only R-2 available rows in the terminal buffer. This would lead to duplicated lines.

This involved a bunch of changes throughout the codebase to make sure we weren't just calling TriggerRedraw on the entire viewport when we resize the buffer. Magically, conpty was pretty good about knowing what actually changed, though that did need some updating as well (in VtEngine::UpdateViewport).

  • Importantly, there's a minor change to ScreenInfo to cause it to only invalidate wrapped lines during a ResizeWithReflow. Previously, we'd be invalidating the entire viewport, but that caused issues terminal-side. It's better to only tell the terminal what actually changed during the reflow.

With those changes, the Terminal was changed to more intelligently stick to the right location in the buffer. When increasing the height of conpty, new lines always get inserted at the bottom of the viewport, so the terminal needs to stick to roughly the old top's position to re-create this stateWhen resizing down, empty lines are clipped from the conpty if there are any, then lines from the top are removed.

This is obviously all very complicated, so I've added some tests to validate all this. ConptyRoundtripTests::TestResizeHeight is elaborate and it does the right thing here, validating the contents of both conpty and the Terminal after emitting various numbers of lines into the buffer and doing arbitrary resizes.

As with any conpty change, I'm horrified that this will break in new and more horrifying ways. I'm hoping that a long bake time will help us identify bugs in this changelist (if there are any).

Validation Steps Performed

In VtPipeTerm and Windows Terminal:

  1. wsl seq 100
  2. resize down - scroll to make sure buffer has the right contents
  3. resize up - scroll to make sure buffer has the right contents
  4. resize down quickly - scroll to make sure buffer has the right contents
  5. resize up quickly - scroll to make sure buffer has the right contents

Additionally, resize quickly from the corner, and ensure ll the lines are right.

Aditionally, perform all the above with less than a full viewport of output.

Aditidionally, after the above tests, perform a sleep 2 ; printf "\e[6n" and quickly hit esc to query the cursors position in conpty, and make sure it lines up with the Terminal's.

Also play with resizing and PSReadline, and all the lovely things PSR does to the cursor.

This was the original PR body I had for this change. It's included here for future code archeologists. It's not really accurate, but it might guide people with the text that's in #3490 to help recreaate how I got here.

This PR encompasses a pair of fixes that are needed simultaneously to make the Windows Terminal work correctly.

  • Conpty was not emitting the correct thing when you'd decrease the height of the viewport. When you increase the height of the window, we'd both invalidate the entire buffer, and insert new lines to the bottom of the buffer. What this meant is that on every height-only resize, we'd re-emit the entire viewport.
    • If you resized down twice (From R to R-1 to R-2), once during the frame being emitted by conpty, the Terminal would try to process the R-1 lines emitted by conpty when there are only R-2 available rows in the terminal buffer. This would tlead to duplicated lines.
  • This buggy conpty behavior was causing us to correctly believe that the terminal viewport should remain "stuck" to the top position. That was what was causing us to apparently erase lines from the scrollback as we'd resize down. So this also changes the terminal to stick to the bottom when the viewport height changes.

This involved a bunch of changes throughout the codebase to make sure we weren't just calling TriggerRedraw on the entire viewport when we resize the buffer. Magically, conpty was pretty good about knowing what actually changed, though that did need some updating as well (in VtEngine::UpdateViewport).

As with any conpty change, I'm horrified that this will break in new and more horrifying ways. I'm hoping that a long bake time will help us identify bugs in this changelist (if there are any).

Validation Steps Performed

In VtPipeTerm and Windows Terminal:

  1. wsl seq 100
  2. resize down - scroll to make sure buffer has the right contents
  3. resize up - scroll to make sure buffer has the right contents
  4. resize down quickly - scroll to make sure buffer has the right contents
  5. resize up quickly - scroll to make sure buffer has the right contents

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/4354 **Author:** [@zadjii-msft](https://github.com/zadjii-msft) **Created:** 1/24/2020 **Status:** ❌ Closed **Base:** `master` ← **Head:** `dev/migrie/b/3490-resizing-but-no-invalidateall-ing` --- ### 📝 Commits (10+) - [`b5c8c85`](https://github.com/microsoft/terminal/commit/b5c8c854cc2d0000a09672112dc20e6a98639713) let's first move reflowing to the text buffer - [`9aec694`](https://github.com/microsoft/terminal/commit/9aec69467cf72c536fca001abc4e82222012307e) add a doc comment because I'm not a barbarian - [`1a2654d`](https://github.com/microsoft/terminal/commit/1a2654d291e530a189c376702d6f47ecc05c84bc) Try to wrap the line properly with conpty - [`aae6ce6`](https://github.com/microsoft/terminal/commit/aae6ce60a491036f5917042efe6a85fee76ea67a) This works, fixing the ECH at end of wrapped line bug - [`416be46`](https://github.com/microsoft/terminal/commit/416be4656febb708193ed7ecc36914c6e98c1333) This is some cleanup, almost ready for PR but I need to write tests which are blocked on #4213 - [`4319589`](https://github.com/microsoft/terminal/commit/431958951045cb6a1cff8b8a68adaa061e986f36) start by authoring a simple test class - [`399b002`](https://github.com/microsoft/terminal/commit/399b002af5e14a050de3bdb4391b1f03b5ca22ae) This seems to fix it? - [`38ebbb6`](https://github.com/microsoft/terminal/commit/38ebbb6f11664a6b01628e842567de5e1d11624c) This is good, but when we resize down quickly, sometimes a line gets duplicated. - [`c8c794f`](https://github.com/microsoft/terminal/commit/c8c794f0d2f925f6ff34aff0134da59ce4c5ce3c) Horrifyingly try to not increment the buffer in the middle of multiple resize operations. - [`ee08a5b`](https://github.com/microsoft/terminal/commit/ee08a5b86605dbc84dc47394dcf7774d65d6cd67) Revert "Horrifyingly try to not increment the buffer in the middle of multiple resize operations." ### 📊 Changes **19 files changed** (+556 additions, -72 deletions) <details> <summary>View changed files</summary> 📝 `src/cascadia/TerminalCore/Terminal.cpp` (+30 -3) 📝 `src/cascadia/TerminalCore/Terminal.hpp` (+7 -2) 📝 `src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp` (+264 -13) ➕ `src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp` (+108 -0) 📝 `src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj` (+1 -0) 📝 `src/host/ConsoleArguments.cpp` (+14 -0) 📝 `src/host/ConsoleArguments.hpp` (+4 -0) 📝 `src/host/VtIo.cpp` (+15 -0) 📝 `src/host/VtIo.hpp` (+4 -0) 📝 `src/host/getset.cpp` (+9 -1) 📝 `src/host/globals.cpp` (+16 -0) 📝 `src/host/globals.h` (+4 -0) 📝 `src/host/screenInfo.cpp` (+39 -5) 📝 `src/host/screenInfo.hpp` (+9 -1) 📝 `src/host/ut_host/ConptyOutputTests.cpp` (+5 -0) 📝 `src/host/ut_host/VtRendererTests.cpp` (+3 -3) 📝 `src/inc/test/CommonState.hpp` (+13 -8) 📝 `src/renderer/vt/state.cpp` (+6 -33) 📝 `src/renderer/vt/vtrenderer.hpp` (+5 -3) </details> ### 📄 Description ## Summary of the Pull Request This PR fixes a bug in the Windows Terminal, where decreasing the height of the window would cause some lines from the scrollback to be lost. While a seemingly trivial bug, this actually involved some elaborate manipulation of how conpty decides to render a resize operation. ## References ## PR Checklist * [x] Closes #3490 * [x] I work here * [x] Tests added/passed - you don't even know * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Conpty was not emitting the correct thing when you'd decrease the height of the viewport. When you increase the height of the window, we'd both invalidate the entire buffer, and insert new lines to the bottom of the buffer. What this meant is that on every height-only resize, we'd re-emit the entire viewport. - If you resized down twice (From `R` to `R-1` to `R-2`), once _during the frame being emitted by conpty_, the Terminal would try to process the `R-1` lines emitted by conpty when there are only `R-2` available rows in the terminal buffer. This would lead to duplicated lines. This involved a bunch of changes throughout the codebase to make sure we weren't just calling `TriggerRedraw` on the entire viewport when we resize the buffer. Magically, conpty was pretty good about knowing what actually changed, though that did need some updating as well (in `VtEngine::UpdateViewport`). - Importantly, there's a minor change to `ScreenInfo` to cause it to only invalidate wrapped lines during a ResizeWithReflow. Previously, we'd be invalidating the entire viewport, but that caused issues terminal-side. It's better to only tell the terminal what actually changed during the reflow. With those changes, the Terminal was changed to more intelligently stick to the right location in the buffer. When increasing the height of conpty, new lines always get inserted at the bottom of the viewport, so the terminal needs to stick to _roughly_ the old top's position to re-create this stateWhen resizing down, _empty_ lines are clipped from the conpty if there are any, then lines from the top are removed. This is obviously all very complicated, so I've added some tests to validate all this. `ConptyRoundtripTests::TestResizeHeight` is _elaborate_ and it does the right thing here, validating the contents of both conpty and the Terminal after emitting various numbers of lines into the buffer and doing arbitrary resizes. As with any conpty change, I'm horrified that this will break in new and more horrifying ways. I'm hoping that a long bake time will help us identify bugs in this changelist (if there are any). ## Validation Steps Performed In VtPipeTerm and Windows Terminal: 1. `wsl seq 100` 2. resize down - scroll to make sure buffer has the right contents 3. resize up - scroll to make sure buffer has the right contents 4. resize down _quickly_ - scroll to make sure buffer has the right contents 5. resize up _quickly_ - scroll to make sure buffer has the right contents Additionally, resize quickly from the corner, and ensure ll the lines are right. Aditionally, perform all the above with less than a full viewport of output. Aditidionally, after the above tests, perform a `sleep 2 ; printf "\e[6n"` and quickly hit <kbd>esc</kbd> to query the cursors position in conpty, and make sure it lines up with the Terminal's. Also play with resizing and PSReadline, and all the lovely things PSR does to the cursor. <details> <summary> This was the original PR body I had for this change. It's included here for future code archeologists. It's not really accurate, but it might guide people with the text that's in #3490 to help recreaate how I got here.</summary> This PR encompasses a pair of fixes that are needed simultaneously to make the Windows Terminal work correctly. * Conpty was not emitting the correct thing when you'd decrease the height of the viewport. When you increase the height of the window, we'd both invalidate the entire buffer, and insert new lines to the bottom of the buffer. What this meant is that on every height-only resize, we'd re-emit the entire viewport. - If you resized down twice (From `R` to `R-1` to `R-2`), once _during the frame being emitted by conpty_, the Terminal would try to process the `R-1` lines emitted by conpty when there are only `R-2` available rows in the terminal buffer. This would tlead to duplicated lines. * This buggy conpty behavior was causing us to correctly believe that the terminal viewport should remain "stuck" to the top position. That was what was causing us to apparently erase lines from the scrollback as we'd resize down. So this also changes the terminal to stick to the bottom when the viewport height changes. This involved a bunch of changes throughout the codebase to make sure we weren't just calling `TriggerRedraw` on the entire viewport when we resize the buffer. Magically, conpty was pretty good about knowing what actually changed, though that did need some updating as well (in `VtEngine::UpdateViewport`). As with any conpty change, I'm horrified that this will break in new and more horrifying ways. I'm hoping that a long bake time will help us identify bugs in this changelist (if there are any). ## Validation Steps Performed In VtPipeTerm and Windows Terminal: 1. `wsl seq 100` 2. resize down - scroll to make sure buffer has the right contents 3. resize up - scroll to make sure buffer has the right contents 4. resize down _quickly_ - scroll to make sure buffer has the right contents 5. resize up _quickly_ - scroll to make sure buffer has the right contents </details> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:11:18 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#25713