From 9e26c020e4fb10ce6c5cea0f2cf753d1819719ac Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Thu, 9 Jul 2020 04:24:20 -0700 Subject: [PATCH] Implement preventing auto-scroll on new output (#6062) ## Summary of the Pull Request Updates the Terminal's scroll response to new output. The Terminal will not automatically scroll if... - a selection is active, or - the viewport is at the bottom of the scroll history ## References #2529 - Spec #3863 - Implementation ## PR Checklist * [X] Closes #980 * [X] Closes #3863 * [ ] Tests added/passed * [ ] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Updates the `_scrollOffset` value properly in TerminalCore when the cursor moves. We calculate a new `_scrollOffset` based on if we are circling the buffer and how far below the mutable bottom is. We specifically check for if a selection is active and if the viewport is at the bottom, then use that as a condition for deciding if we should update `_scrollOffset` to the new calculated value or 0 (the bottom of the scroll history). ## Validation Steps Performed Manual testing. Though I should add automated tests. - [X] new output - [X] new output when circling - [X] new output when circling and viewport is at the top --- src/cascadia/TerminalCore/Terminal.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index f620d82779b..4bf52299801 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -788,9 +788,9 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition) // If we're about to scroll past the bottom of the buffer, instead cycle the // buffer. SHORT rowsPushedOffTopOfBuffer = 0; + const auto newRows = std::max(0, proposedCursorPosition.Y - bufferSize.Height() + 1); if (proposedCursorPosition.Y >= bufferSize.Height()) { - const auto newRows = proposedCursorPosition.Y - bufferSize.Height() + 1; for (auto dy = 0; dy < newRows; dy++) { _buffer->IncrementCircularBuffer(); @@ -804,7 +804,8 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition) // Move the viewport down if the cursor moved below the viewport. bool updatedViewport = false; - if (proposedCursorPosition.Y > _mutableViewport.BottomInclusive()) + const auto scrollAmount = std::max(0, proposedCursorPosition.Y - _mutableViewport.BottomInclusive()); + if (scrollAmount > 0) { const auto newViewTop = std::max(0, proposedCursorPosition.Y - (_mutableViewport.Height() - 1)); if (newViewTop != _mutableViewport.Top()) @@ -817,6 +818,13 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition) if (updatedViewport) { + // scroll if... + // - no selection is active + // - viewport is already at the bottom + const bool scrollToOutput = !IsSelectionActive() && _scrollOffset == 0; + + _scrollOffset = scrollToOutput ? 0 : _scrollOffset + scrollAmount + newRows; + _NotifyScrollEvent(); }