Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable using the alt buffer in the Terminal #12561

Merged
merged 20 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
83466a4
I think this is the conhost half of the changes
zadjii-msft Feb 23, 2022
e94e08c
This quite nearly implements everything for the Terminal half
zadjii-msft Feb 23, 2022
dd702c7
Most of the remaining todos, comments
zadjii-msft Feb 23, 2022
1209fa4
one last comment
zadjii-msft Feb 23, 2022
bf24cdd
more comments are always good
zadjii-msft Feb 23, 2022
dff1b94
spel
zadjii-msft Feb 24, 2022
60d2c2e
fix tests
zadjii-msft Feb 24, 2022
54dc304
Stashing this for now. I think this does the save/restore cursor stuf…
zadjii-msft Feb 28, 2022
57094b7
start writing tests
zadjii-msft Mar 8, 2022
69d0973
make this test way more elaborate
zadjii-msft Mar 8, 2022
0a1ed70
I thought this was a test for https://github.com/microsoft/terminal/p…
zadjii-msft Mar 8, 2022
9453aa5
More test cleanup. Make sure viewport doesnt move
zadjii-msft Mar 8, 2022
e658431
Merge remote-tracking branch 'origin/main' into dev/migrie/b/alt-buff…
zadjii-msft Mar 8, 2022
0cfb463
Merge remote-tracking branch 'origin/main' into dev/migrie/b/alt-buff…
zadjii-msft Mar 16, 2022
bf3d79e
fine that's not a word
zadjii-msft Mar 16, 2022
7237fce
thats not a word either
zadjii-msft Mar 17, 2022
65b4571
notes from j4james
zadjii-msft Mar 17, 2022
7c3e808
Merge remote-tracking branch 'origin/main' into dev/migrie/b/alt-buff…
zadjii-msft Apr 1, 2022
002fbbc
Merge remote-tracking branch 'origin/main' into dev/migrie/b/alt-buff…
zadjii-msft Apr 12, 2022
f209d98
fix the urls in the alt buffer
zadjii-msft Apr 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/buffer/out/textBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ bool TextBuffer::IncrementCircularBuffer(const bool inVtMode)
{
// FirstRow is at any given point in time the array index in the circular buffer that corresponds
// to the logical position 0 in the window (cursor coordinates and all other coordinates).
_renderTarget.TriggerCircling();
_renderTarget.TriggerFlush(true);

// Prune hyperlinks to delete obsolete references
_PruneHyperlinks();
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 @@ -67,6 +67,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
157 changes: 112 additions & 45 deletions src/cascadia/TerminalCore/Terminal.cpp

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,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,7 +321,8 @@ class Microsoft::Terminal::Core::Terminal final :

// TODO: These members are not shared by an alt-buffer. They should be
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
// 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;

Expand Down Expand Up @@ -373,6 +376,9 @@ class Microsoft::Terminal::Core::Terminal final :

void _NotifyTerminalCursorPositionChanged() noexcept;

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

#pragma region TextSelection
// These methods are defined in TerminalSelection.cpp
std::vector<SMALL_RECT> _GetSelectionRects() const noexcept;
Expand Down
207 changes: 154 additions & 53 deletions src/cascadia/TerminalCore/TerminalApi.cpp

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,9 @@ bool TerminalDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param,
case DispatchTypes::ModeParams::W32IM_Win32InputMode:
success = EnableWin32InputMode(enable);
break;
case DispatchTypes::ModeParams::ASB_AlternateScreenBuffer:
success = enable ? UseAlternateScreenBuffer() : UseMainScreenBuffer();
break;
default:
// If no functions to call, overall dispatch was a failure.
success = false;
Expand Down Expand Up @@ -722,3 +725,35 @@ bool TerminalDispatch::HardReset()

return true;
}

// - ASBSET - Creates and swaps to the alternate screen buffer. In virtual terminals, there exists both a "main"
// screen buffer and an alternate. ASBSET creates a new alternate, and switches to it. If there is an already
// existing alternate, it is discarded.
// Arguments:
// - None
// Return Value:
// - True.
bool TerminalDispatch::UseAlternateScreenBuffer()
{
// TODO GH#3849: When de-duplicating this, the AdaptDispatch version of this calls:
// CursorSaveState();
_terminalApi.UseAlternateScreenBuffer();
_usingAltBuffer = true;
return true;
}

// Routine Description:
// - ASBRST - From the alternate buffer, returns to the main screen buffer.
// From the main screen buffer, does nothing. The alternate is discarded.
// Arguments:
// - None
// Return Value:
// - True.
bool TerminalDispatch::UseMainScreenBuffer()
{
_terminalApi.UseMainScreenBuffer();
_usingAltBuffer = false;
// TODO GH#3849: When de-duplicating this, the AdaptDispatch version of this calls:
// CursorRestoreState();
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
return true;
}
4 changes: 4 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc
bool CarriageReturn() override;
bool SetWindowTitle(std::wstring_view title) override;

bool UseAlternateScreenBuffer() override; // ASBSET
bool UseMainScreenBuffer() override; // ASBRST

bool HorizontalTabSet() override; // HTS
bool ForwardTab(const size_t numTabs) override; // CHT, HT
bool BackwardsTab(const size_t numTabs) override; // CBT
Expand Down Expand Up @@ -85,6 +88,7 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc

std::vector<bool> _tabStopColumns;
bool _initDefaultTabStops = true;
bool _usingAltBuffer = false;

size_t _SetRgbColorsHelper(const ::Microsoft::Console::VirtualTerminal::VTParameters options,
TextAttribute& attr,
Expand Down
58 changes: 29 additions & 29 deletions src/cascadia/TerminalCore/TerminalSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ std::vector<SMALL_RECT> Terminal::_GetSelectionRects() const noexcept

try
{
return _buffer->GetTextRects(_selection->start, _selection->end, _blockSelection, false);
return _activeBuffer().GetTextRects(_selection->start, _selection->end, _blockSelection, false);
}
CATCH_LOG();
return result;
Expand Down Expand Up @@ -182,7 +182,7 @@ void Terminal::SetSelectionEnd(const COORD viewportPos, std::optional<SelectionE
// - the new start/end for a selection
std::pair<COORD, COORD> Terminal::_PivotSelection(const COORD targetPos, bool& targetStart) const
{
if (targetStart = _buffer->GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0)
if (targetStart = _activeBuffer().GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0)
{
// target is before pivot
// treat target as start
Expand All @@ -207,16 +207,16 @@ std::pair<COORD, COORD> Terminal::_ExpandSelectionAnchors(std::pair<COORD, COORD
COORD start = anchors.first;
COORD end = anchors.second;

const auto bufferSize = _buffer->GetSize();
const auto bufferSize = _activeBuffer().GetSize();
switch (_multiClickSelectionMode)
{
case SelectionExpansion::Line:
start = { bufferSize.Left(), start.Y };
end = { bufferSize.RightInclusive(), end.Y };
break;
case SelectionExpansion::Word:
start = _buffer->GetWordStart(start, _wordDelimiters);
end = _buffer->GetWordEnd(end, _wordDelimiters);
start = _activeBuffer().GetWordStart(start, _wordDelimiters);
end = _activeBuffer().GetWordEnd(end, _wordDelimiters);
break;
case SelectionExpansion::Char:
default:
Expand Down Expand Up @@ -325,7 +325,7 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion
_scrollOffset -= amtBelowView;
}
_NotifyScrollEvent();
_buffer->GetRenderTarget().TriggerScroll();
_activeBuffer().GetRenderTarget().TriggerScroll();
}
}

Expand All @@ -334,22 +334,22 @@ void Terminal::_MoveByChar(SelectionDirection direction, COORD& pos)
switch (direction)
{
case SelectionDirection::Left:
_buffer->GetSize().DecrementInBounds(pos);
pos = _buffer->GetGlyphStart(til::point{ pos }).to_win32_coord();
_activeBuffer().GetSize().DecrementInBounds(pos);
pos = _activeBuffer().GetGlyphStart(til::point{ pos }).to_win32_coord();
break;
case SelectionDirection::Right:
_buffer->GetSize().IncrementInBounds(pos);
pos = _buffer->GetGlyphEnd(til::point{ pos }).to_win32_coord();
_activeBuffer().GetSize().IncrementInBounds(pos);
pos = _activeBuffer().GetGlyphEnd(til::point{ pos }).to_win32_coord();
break;
case SelectionDirection::Up:
{
const auto bufferSize{ _buffer->GetSize() };
const auto bufferSize{ _activeBuffer().GetSize() };
pos = { pos.X, std::clamp(base::ClampSub<short, short>(pos.Y, 1).RawValue(), bufferSize.Top(), bufferSize.BottomInclusive()) };
break;
}
case SelectionDirection::Down:
{
const auto bufferSize{ _buffer->GetSize() };
const auto bufferSize{ _activeBuffer().GetSize() };
pos = { pos.X, std::clamp(base::ClampAdd<short, short>(pos.Y, 1).RawValue(), bufferSize.Top(), bufferSize.BottomInclusive()) };
break;
}
Expand All @@ -361,19 +361,19 @@ void Terminal::_MoveByWord(SelectionDirection direction, COORD& pos)
switch (direction)
{
case SelectionDirection::Left:
const auto wordStartPos{ _buffer->GetWordStart(pos, _wordDelimiters) };
if (_buffer->GetSize().CompareInBounds(_selection->pivot, pos) < 0)
const auto wordStartPos{ _activeBuffer().GetWordStart(pos, _wordDelimiters) };
if (_activeBuffer().GetSize().CompareInBounds(_selection->pivot, pos) < 0)
{
// If we're moving towards the pivot, move one more cell
pos = wordStartPos;
_buffer->GetSize().DecrementInBounds(pos);
_activeBuffer().GetSize().DecrementInBounds(pos);
}
else if (wordStartPos == pos)
{
// already at the beginning of the current word,
// move to the beginning of the previous word
_buffer->GetSize().DecrementInBounds(pos);
pos = _buffer->GetWordStart(pos, _wordDelimiters);
_activeBuffer().GetSize().DecrementInBounds(pos);
pos = _activeBuffer().GetWordStart(pos, _wordDelimiters);
}
else
{
Expand All @@ -382,19 +382,19 @@ void Terminal::_MoveByWord(SelectionDirection direction, COORD& pos)
}
break;
case SelectionDirection::Right:
const auto wordEndPos{ _buffer->GetWordEnd(pos, _wordDelimiters) };
if (_buffer->GetSize().CompareInBounds(pos, _selection->pivot) < 0)
const auto wordEndPos{ _activeBuffer().GetWordEnd(pos, _wordDelimiters) };
if (_activeBuffer().GetSize().CompareInBounds(pos, _selection->pivot) < 0)
{
// If we're moving towards the pivot, move one more cell
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
_buffer->GetSize().IncrementInBounds(pos);
pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters);
_activeBuffer().GetSize().IncrementInBounds(pos);
}
else if (wordEndPos == pos)
{
// already at the end of the current word,
// move to the end of the next word
_buffer->GetSize().IncrementInBounds(pos);
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
_activeBuffer().GetSize().IncrementInBounds(pos);
pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters);
}
else
{
Expand All @@ -404,18 +404,18 @@ void Terminal::_MoveByWord(SelectionDirection direction, COORD& pos)
break;
case SelectionDirection::Up:
_MoveByChar(direction, pos);
pos = _buffer->GetWordStart(pos, _wordDelimiters);
pos = _activeBuffer().GetWordStart(pos, _wordDelimiters);
break;
case SelectionDirection::Down:
_MoveByChar(direction, pos);
pos = _buffer->GetWordEnd(pos, _wordDelimiters);
pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters);
break;
}
}

void Terminal::_MoveByViewport(SelectionDirection direction, COORD& pos)
{
const auto bufferSize{ _buffer->GetSize() };
const auto bufferSize{ _activeBuffer().GetSize() };
switch (direction)
{
case SelectionDirection::Left:
Expand Down Expand Up @@ -444,7 +444,7 @@ void Terminal::_MoveByViewport(SelectionDirection direction, COORD& pos)

void Terminal::_MoveByBuffer(SelectionDirection direction, COORD& pos)
{
const auto bufferSize{ _buffer->GetSize() };
const auto bufferSize{ _activeBuffer().GetSize() };
switch (direction)
{
case SelectionDirection::Left:
Expand Down Expand Up @@ -489,7 +489,7 @@ const TextBuffer::TextAndColor Terminal::RetrieveSelectedTextFromBuffer(bool sin
const auto includeCRLF = !singleLine || _blockSelection;
const auto trimTrailingWhitespace = !singleLine && (!_blockSelection || _trimBlockSelection);
const auto formatWrappedRows = _blockSelection;
return _buffer->GetText(includeCRLF, trimTrailingWhitespace, selectionRects, GetAttributeColors, formatWrappedRows);
return _activeBuffer().GetText(includeCRLF, trimTrailingWhitespace, selectionRects, GetAttributeColors, formatWrappedRows);
}

// Method Description:
Expand All @@ -502,7 +502,7 @@ COORD Terminal::_ConvertToBufferCell(const COORD viewportPos) const
{
const auto yPos = base::ClampedNumeric<short>(_VisibleStartIndex()) + viewportPos.Y;
COORD bufferPos = { viewportPos.X, yPos };
_buffer->GetSize().Clamp(bufferPos);
_activeBuffer().GetSize().Clamp(bufferPos);
return bufferPos;
}

Expand Down
24 changes: 12 additions & 12 deletions src/cascadia/TerminalCore/terminalrenderdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ COORD Terminal::GetTextBufferEndPosition() const noexcept

const TextBuffer& Terminal::GetTextBuffer() noexcept
{
return *_buffer;
return _activeBuffer();
}

const FontInfo& Terminal::GetFontInfo() noexcept
Expand All @@ -40,19 +40,19 @@ void Terminal::SetFontInfo(const FontInfo& fontInfo)

COORD Terminal::GetCursorPosition() const noexcept
{
const auto& cursor = _buffer->GetCursor();
const auto& cursor = _activeBuffer().GetCursor();
return cursor.GetPosition();
}

bool Terminal::IsCursorVisible() const noexcept
{
const auto& cursor = _buffer->GetCursor();
const auto& cursor = _activeBuffer().GetCursor();
return cursor.IsVisible() && !cursor.IsPopupShown();
}

bool Terminal::IsCursorOn() const noexcept
{
const auto& cursor = _buffer->GetCursor();
const auto& cursor = _activeBuffer().GetCursor();
return cursor.IsOn();
}

Expand All @@ -63,18 +63,18 @@ ULONG Terminal::GetCursorPixelWidth() const noexcept

ULONG Terminal::GetCursorHeight() const noexcept
{
return _buffer->GetCursor().GetSize();
return _activeBuffer().GetCursor().GetSize();
}

CursorType Terminal::GetCursorStyle() const noexcept
{
return _buffer->GetCursor().GetType();
return _activeBuffer().GetCursor().GetType();
}

bool Terminal::IsCursorDoubleWidth() const
{
const auto position = _buffer->GetCursor().GetPosition();
TextBufferTextIterator it(TextBufferCellIterator(*_buffer, position));
const auto position = _activeBuffer().GetCursor().GetPosition();
TextBufferTextIterator it(TextBufferCellIterator(_activeBuffer(), position));
return IsGlyphFullWidth(*it);
}

Expand All @@ -90,12 +90,12 @@ const bool Terminal::IsGridLineDrawingAllowed() noexcept

const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkUri(uint16_t id) const noexcept
{
return _buffer->GetHyperlinkUriFromId(id);
return _activeBuffer().GetHyperlinkUriFromId(id);
}

const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkCustomId(uint16_t id) const noexcept
{
return _buffer->GetCustomIdFromId(id);
return _activeBuffer().GetCustomIdFromId(id);
}

// Method Description:
Expand Down Expand Up @@ -174,7 +174,7 @@ void Terminal::SelectNewRegion(const COORD coordStart, const COORD coordEnd)

if (notifyScrollChange)
{
_buffer->GetRenderTarget().TriggerScroll();
_activeBuffer().GetRenderTarget().TriggerScroll();
_NotifyScrollEvent();
}

Expand Down Expand Up @@ -227,5 +227,5 @@ const bool Terminal::IsUiaDataInitialized() const noexcept
// when a screen reader requests it. However, the terminal might not be fully
// initialized yet. So we use this to check if any crucial components of
// UiaData are not yet initialized.
return !!_buffer;
return !!_mainBuffer;
}
Loading