Skip to content

Commit

Permalink
Enable using the alt buffer in the Terminal (#12561)
Browse files Browse the repository at this point in the history
This PR allows the Terminal to actually use the alt buffer
appropriately. Currently, we just render the alt buffer state into the
main buffer and that is wild. It means things like `vim` will let the
user scroll up to see the previous history (which it shouldn't).

Very first thing this PR does: updates the
`{Trigger|Invalidate}Circling` methods to instead be
`{Trigger|Invalidate}Flush(bool circling)`. We need this so that when an
app requests the alt buffer in conpty, we can immediately flush the
frame before asking the Terminal side to switch to the other buffer. The
`Circling` methods was a great place to do this, but we don't actually
want to set the circled flag in VtRenderer when that happens just for a
flush. 

The Terminal's implementation is a little different than conhost's.
Conhost's implementation grew organically, so I had it straight up
create an entire new screen buffer for the alt buffer. The Terminal
doesn't need all that! All we need to do is have a separate `TextBuffer`
for the alt buffer contents. This makes other parts easier as well - we
don't really need to do anything with the `_mutableViewport` in the alt
buffer, because it's always in the same place. So, we can just leave it
alone and when we come back to the main buffer, there it is. Helper
methods have been updated to account for this. 

* [x] Closes #381
* [x] Closes #3492
* #3686, #3082, #3321, #3493 are all good follow-ups here.
  • Loading branch information
zadjii-msft authored Apr 12, 2022
1 parent 7648411 commit 13fb1f5
Show file tree
Hide file tree
Showing 37 changed files with 915 additions and 297 deletions.
2 changes: 1 addition & 1 deletion src/buffer/out/textBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ bool TextBuffer::IncrementCircularBuffer(const bool inVtMode)
// to the logical position 0 in the window (cursor coordinates and all other coordinates).
if (_isActiveBuffer)
{
_renderer.TriggerCircling();
_renderer.TriggerFlush(true);
}

// Prune hyperlinks to delete obsolete references
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalCore/ITerminalApi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ namespace Microsoft::Terminal::Core
virtual void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) = 0;
virtual void PopGraphicsRendition() = 0;

virtual void UseAlternateScreenBuffer() = 0;
virtual void UseMainScreenBuffer() = 0;

protected:
ITerminalApi() = default;
};
Expand Down
188 changes: 131 additions & 57 deletions src/cascadia/TerminalCore/Terminal.cpp

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class Microsoft::Terminal::Core::Terminal final :
void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override;
void PopGraphicsRendition() override;

void UseAlternateScreenBuffer() override;
void UseMainScreenBuffer() override;
#pragma endregion

#pragma region ITerminalInput
Expand Down Expand Up @@ -319,11 +321,11 @@ class Microsoft::Terminal::Core::Terminal final :
SelectionExpansion _multiClickSelectionMode;
#pragma endregion

// TODO: These members are not shared by an alt-buffer. They should be
// encapsulated, such that a Terminal can have both a main and alt buffer.
std::unique_ptr<TextBuffer> _buffer;
std::unique_ptr<TextBuffer> _mainBuffer;
std::unique_ptr<TextBuffer> _altBuffer;
Microsoft::Console::Types::Viewport _mutableViewport;
SHORT _scrollbackLines;
bool _detectURLs{ false };

// _scrollOffset is the number of lines above the viewport that are currently visible
// If _scrollOffset is 0, then the visible region of the buffer is the viewport.
Expand Down Expand Up @@ -375,6 +377,10 @@ class Microsoft::Terminal::Core::Terminal final :

void _NotifyTerminalCursorPositionChanged() noexcept;

bool _inAltBuffer() const noexcept;
TextBuffer& _activeBuffer() const noexcept;
void _updateUrlDetection();

#pragma region TextSelection
// These methods are defined in TerminalSelection.cpp
std::vector<SMALL_RECT> _GetSelectionRects() const noexcept;
Expand Down
Loading

0 comments on commit 13fb1f5

Please sign in to comment.