diff --git a/src/buffer/out/search.cpp b/src/buffer/out/search.cpp index bb75fc4432f..a5b2b4d9e84 100644 --- a/src/buffer/out/search.cpp +++ b/src/buffer/out/search.cpp @@ -140,7 +140,7 @@ std::pair Search::GetFoundLocation() const noexcept // - direction - The intended direction of the search // Return Value: // - Coordinate to start the search from. -COORD Search::s_GetInitialAnchor(IUiaData& uiaData, const Direction direction) +COORD Search::s_GetInitialAnchor(const IUiaData& uiaData, const Direction direction) { const auto& textBuffer = uiaData.GetTextBuffer(); const auto textBufferEndPosition = uiaData.GetTextBufferEndPosition(); diff --git a/src/buffer/out/search.h b/src/buffer/out/search.h index 39efc139f40..38e5bb7885c 100644 --- a/src/buffer/out/search.h +++ b/src/buffer/out/search.h @@ -66,7 +66,7 @@ class Search final void _IncrementCoord(COORD& coord) const noexcept; void _DecrementCoord(COORD& coord) const noexcept; - static COORD s_GetInitialAnchor(Microsoft::Console::Types::IUiaData& uiaData, const Direction dir); + static COORD s_GetInitialAnchor(const Microsoft::Console::Types::IUiaData& uiaData, const Direction dir); static std::vector> s_CreateNeedleFromString(const std::wstring& wstr); diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp index 3dd7bfc0563..f25fd86aecc 100644 --- a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp +++ b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp @@ -214,7 +214,9 @@ HRESULT HwndTerminal::Initialize() _terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>(); auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>(); auto* const localPointerToThread = renderThread.get(); - const auto& renderSettings = _terminal->GetRenderSettings(); + auto& renderSettings = _terminal->GetRenderSettings(); + renderSettings.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12)); + renderSettings.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204)); _renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(renderSettings, _terminal.get(), nullptr, 0, std::move(renderThread)); RETURN_HR_IF_NULL(E_POINTER, localPointerToThread); RETURN_IF_FAILED(localPointerToThread->Initialize(_renderer.get())); @@ -237,11 +239,7 @@ HRESULT HwndTerminal::Initialize() _renderEngine = std::move(dxEngine); - _terminal->SetBackgroundCallback([](auto) {}); - _terminal->Create(COORD{ 80, 25 }, 1000, *_renderer); - _terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12)); - _terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204)); _terminal->SetWriteInputCallback([=](std::wstring_view input) noexcept { _WriteTextToConnection(input); }); localPointerToThread->EnablePainting(); @@ -788,15 +786,17 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font { auto lock = publicTerminal->_terminal->LockForWriting(); - publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground); - publicTerminal->_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground); + auto& renderSettings = publicTerminal->_terminal->GetRenderSettings(); + renderSettings.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground); + renderSettings.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground); + publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground, theme.SelectionBackgroundAlpha); // Set the font colors for (size_t tableIndex = 0; tableIndex < 16; tableIndex++) { // It's using gsl::at to check the index is in bounds, but the analyzer still calls this array-to-pointer-decay - [[gsl::suppress(bounds .3)]] publicTerminal->_terminal->SetColorTableEntry(tableIndex, gsl::at(theme.ColorTable, tableIndex)); + [[gsl::suppress(bounds .3)]] renderSettings.SetColorTableEntry(tableIndex, gsl::at(theme.ColorTable, tableIndex)); } } diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 616914bc462..cc14f228770 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -96,9 +96,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto pfnTabColorChanged = std::bind(&ControlCore::_terminalTabColorChanged, this, std::placeholders::_1); _terminal->SetTabColorChangedCallback(pfnTabColorChanged); - auto pfnBackgroundColorChanged = std::bind(&ControlCore::_terminalBackgroundColorChanged, this, std::placeholders::_1); - _terminal->SetBackgroundCallback(pfnBackgroundColorChanged); - auto pfnScrollPositionChanged = std::bind(&ControlCore::_terminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); _terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged); @@ -128,6 +125,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto& renderSettings = _terminal->GetRenderSettings(); _renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(renderSettings, _terminal.get(), nullptr, 0, std::move(renderThread)); + _renderer->SetBackgroundColorChangedCallback([this]() { _rendererBackgroundColorChanged(); }); + _renderer->SetRendererEnteredErrorStateCallback([weakThis = get_weak()]() { if (auto strongThis{ weakThis.get() }) { @@ -1153,21 +1152,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _TabColorChangedHandlers(*this, nullptr); } - // Method Description: - // - Called for the Terminal's BackgroundColorChanged callback. This will - // re-raise a new winrt TypedEvent that can be listened to. - // - The listeners to this event will re-query the control for the current - // value of BackgroundColor(). - // Arguments: - // - - // Return Value: - // - - void ControlCore::_terminalBackgroundColorChanged(const COLORREF /*color*/) - { - // Raise a BackgroundColorChanged event - _BackgroundColorChangedHandlers(*this, nullptr); - } - // Method Description: // - Update the position and size of the scrollbar to match the given // viewport top, viewport height, and buffer size. @@ -1360,6 +1344,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation _SwapChainChangedHandlers(*this, nullptr); } + void ControlCore::_rendererBackgroundColorChanged() + { + _BackgroundColorChangedHandlers(*this, nullptr); + } + void ControlCore::BlinkAttributeTick() { auto lock = _terminal->LockForWriting(); @@ -1525,7 +1514,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation { if (clearType == Control::ClearBufferType::Scrollback || clearType == Control::ClearBufferType::All) { - _terminal->EraseInDisplay(::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType::Scrollback); + _terminal->EraseScrollback(); } if (clearType == Control::ClearBufferType::Screen || clearType == Control::ClearBufferType::All) @@ -1684,8 +1673,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderEngine->SetSelectionBackground(til::color{ _settings->SelectionBackground() }); - _renderer->TriggerRedrawAll(); - _BackgroundColorChangedHandlers(*this, nullptr); + _renderer->TriggerRedrawAll(true); } bool ControlCore::HasUnfocusedAppearance() const diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 36ce7fd1575..dfb40441130 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -265,7 +265,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _terminalWarningBell(); void _terminalTitleChanged(std::wstring_view wstr); void _terminalTabColorChanged(const std::optional color); - void _terminalBackgroundColorChanged(const COLORREF color); void _terminalScrollPositionChanged(const int viewTop, const int viewHeight, const int bufferSize); @@ -277,6 +276,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation #pragma region RendererCallbacks void _rendererWarning(const HRESULT hr); void _renderEngineSwapChainChanged(); + void _rendererBackgroundColorChanged(); #pragma endregion void _raiseReadOnlyWarning(); diff --git a/src/cascadia/TerminalCore/ITerminalApi.hpp b/src/cascadia/TerminalCore/ITerminalApi.hpp deleted file mode 100644 index 810e00dfab8..00000000000 --- a/src/cascadia/TerminalCore/ITerminalApi.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#pragma once - -#include "../../terminal/adapter/DispatchTypes.hpp" -#include "../../terminal/input/terminalInput.hpp" -#include "../../buffer/out/TextAttribute.hpp" -#include "../../renderer/inc/RenderSettings.hpp" -#include "../../types/inc/Viewport.hpp" - -namespace Microsoft::Terminal::Core -{ - class ITerminalApi - { - public: - virtual ~ITerminalApi() {} - ITerminalApi(const ITerminalApi&) = default; - ITerminalApi(ITerminalApi&&) = default; - ITerminalApi& operator=(const ITerminalApi&) = default; - ITerminalApi& operator=(ITerminalApi&&) = default; - - virtual void PrintString(std::wstring_view string) = 0; - - virtual bool ReturnResponse(std::wstring_view responseString) = 0; - - virtual TextAttribute GetTextAttributes() const = 0; - virtual void SetTextAttributes(const TextAttribute& attrs) = 0; - - virtual Microsoft::Console::Types::Viewport GetBufferSize() = 0; - virtual void SetCursorPosition(til::point pos) = 0; - virtual til::point GetCursorPosition() = 0; - virtual void SetCursorVisibility(const bool visible) = 0; - virtual void CursorLineFeed(const bool withReturn) = 0; - virtual void EnableCursorBlinking(const bool enable) = 0; - - virtual void DeleteCharacter(const til::CoordType count) = 0; - virtual void InsertCharacter(const til::CoordType count) = 0; - virtual void EraseCharacters(const til::CoordType numChars) = 0; - virtual bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) = 0; - virtual bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) = 0; - - virtual void WarningBell() = 0; - virtual void SetWindowTitle(std::wstring_view title) = 0; - - virtual COLORREF GetColorTableEntry(const size_t tableIndex) const = 0; - virtual void SetColorTableEntry(const size_t tableIndex, const COLORREF color) = 0; - virtual void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) = 0; - - virtual void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) = 0; - - virtual void SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) = 0; - virtual void SetRenderMode(const ::Microsoft::Console::Render::RenderSettings::Mode mode, const bool enabled) = 0; - - virtual void EnableXtermBracketedPasteMode(const bool enabled) = 0; - virtual bool IsXtermBracketedPasteModeEnabled() const = 0; - - virtual bool IsVtInputEnabled() const = 0; - - virtual void CopyToClipboard(std::wstring_view content) = 0; - - virtual void AddHyperlink(std::wstring_view uri, std::wstring_view params) = 0; - virtual void EndHyperlink() = 0; - - virtual void SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) = 0; - - virtual void SetWorkingDirectory(std::wstring_view uri) = 0; - virtual std::wstring_view GetWorkingDirectory() = 0; - - virtual void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) = 0; - virtual void PopGraphicsRendition() = 0; - - virtual void ShowWindow(bool showOrHide) = 0; - - virtual void UseAlternateScreenBuffer() = 0; - virtual void UseMainScreenBuffer() = 0; - - protected: - ITerminalApi() = default; - }; -} diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 5c6a5f61f0c..648d7fff902 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -3,8 +3,8 @@ #include "pch.h" #include "Terminal.hpp" +#include "../../terminal/adapter/adaptDispatch.hpp" #include "../../terminal/parser/OutputStateMachineEngine.hpp" -#include "TerminalDispatch.hpp" #include "../../inc/unicode.hpp" #include "../../types/inc/utils.hpp" #include "../../types/inc/colorTable.hpp" @@ -50,19 +50,6 @@ Terminal::Terminal() : _taskbarProgress{ 0 }, _trimBlockSelection{ false } { - auto dispatch = std::make_unique(*this); - auto engine = std::make_unique(std::move(dispatch)); - - _stateMachine = std::make_unique(std::move(engine)); - - // Until we have a true pass-through mode (GH#1173), the decision as to - // whether C1 controls are interpreted or not is made at the conhost level. - // If they are being filtered out, then we will simply never receive them. - // But if they are being accepted by conhost, there's a chance they may get - // passed through in some situations, so it's important that our state - // machine is always prepared to accept them. - _stateMachine->SetParserMode(StateMachine::Mode::AcceptC1, true); - auto passAlongInput = [&](std::deque>& inEventsToWrite) { if (!_pfnWriteInput) { @@ -87,6 +74,18 @@ void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, Renderer& rende const TextAttribute attr{}; const UINT cursorSize = 12; _mainBuffer = std::make_unique(bufferSize, attr, cursorSize, true, renderer); + + auto dispatch = std::make_unique(*this, renderer, _renderSettings, *_terminalInput); + auto engine = std::make_unique(std::move(dispatch)); + _stateMachine = std::make_unique(std::move(engine)); + + // Until we have a true pass-through mode (GH#1173), the decision as to + // whether C1 controls are interpreted or not is made at the conhost level. + // If they are being filtered out, then we will simply never receive them. + // But if they are being accepted by conhost, there's a chance they may get + // passed through in some situations, so it's important that our state + // machine is always prepared to accept them. + _stateMachine->SetParserMode(StateMachine::Mode::AcceptC1, true); } // Method Description: @@ -218,6 +217,28 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance) _defaultCursorShape = cursorShape; } +void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) +{ + auto& engine = reinterpret_cast(_stateMachine->Engine()); + engine.Dispatch().SetCursorStyle(cursorStyle); +} + +void Terminal::EraseScrollback() +{ + auto& engine = reinterpret_cast(_stateMachine->Engine()); + engine.Dispatch().EraseInDisplay(DispatchTypes::EraseType::Scrollback); +} + +bool Terminal::IsXtermBracketedPasteModeEnabled() const +{ + return _bracketedPasteMode; +} + +std::wstring_view Terminal::GetWorkingDirectory() +{ + return _workingDirectory; +} + // Method Description: // - Resize the terminal as the result of some user interaction. // Arguments: @@ -1271,15 +1292,6 @@ void Terminal::SetCursorPositionChangedCallback(std::function pfn) noexc _pfnCursorPositionChanged.swap(pfn); } -// Method Description: -// - Allows setting a callback for when the background color is changed -// Arguments: -// - pfn: a function callback that takes a color -void Terminal::SetBackgroundCallback(std::function pfn) noexcept -{ - _pfnBackgroundColorChanged.swap(pfn); -} - // Method Description: // - Allows settings a callback for settings the taskbar progress indicator // Arguments: diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index af936f550f6..99419b2b6f6 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -7,16 +7,14 @@ #include "../../inc/DefaultSettings.h" #include "../../buffer/out/textBuffer.hpp" -#include "../../types/inc/sgrStack.hpp" #include "../../renderer/inc/IRenderData.hpp" -#include "../../renderer/inc/RenderSettings.hpp" +#include "../../terminal/adapter/ITerminalApi.hpp" #include "../../terminal/parser/StateMachine.hpp" #include "../../terminal/input/terminalInput.hpp" #include "../../types/inc/Viewport.hpp" #include "../../types/inc/GlyphWidth.hpp" #include "../../types/IUiaData.h" -#include "../../cascadia/terminalcore/ITerminalApi.hpp" #include "../../cascadia/terminalcore/ITerminalInput.hpp" #include @@ -34,6 +32,11 @@ namespace winrt::Microsoft::Terminal::Core struct Scheme; } +namespace Microsoft::Console::VirtualTerminal +{ + class AdaptDispatch; +} + namespace Microsoft::Terminal::Core { class Terminal; @@ -51,7 +54,7 @@ namespace TerminalCoreUnitTests #endif class Microsoft::Terminal::Core::Terminal final : - public Microsoft::Terminal::Core::ITerminalApi, + public Microsoft::Console::VirtualTerminal::ITerminalApi, public Microsoft::Terminal::Core::ITerminalInput, public Microsoft::Console::Render::IRenderData, public Microsoft::Console::Types::IUiaData @@ -76,6 +79,10 @@ class Microsoft::Terminal::Core::Terminal final : void UpdateSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings); void UpdateAppearance(const winrt::Microsoft::Terminal::Core::ICoreAppearance& appearance); void SetFontInfo(const FontInfo& fontInfo); + void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle); + void EraseScrollback(); + bool IsXtermBracketedPasteModeEnabled() const; + std::wstring_view GetWorkingDirectory(); // Write comes from the PTY and goes to our parser to be stored in the output buffer void Write(std::wstring_view stringView); @@ -96,53 +103,33 @@ class Microsoft::Terminal::Core::Terminal final : #pragma region ITerminalApi // These methods are defined in TerminalApi.cpp - void PrintString(std::wstring_view stringView) override; - bool ReturnResponse(std::wstring_view responseString) override; - TextAttribute GetTextAttributes() const override; + void PrintString(const std::wstring_view string) override; + void ReturnResponse(const std::wstring_view response) override; + Microsoft::Console::VirtualTerminal::StateMachine& GetStateMachine() override; + TextBuffer& GetTextBuffer() override; + til::rect GetViewport() const override; + void SetViewportPosition(const til::point position) override; void SetTextAttributes(const TextAttribute& attrs) override; - Microsoft::Console::Types::Viewport GetBufferSize() override; - void SetCursorPosition(til::point pos) override; - til::point GetCursorPosition() override; - void SetCursorVisibility(const bool visible) override; - void EnableCursorBlinking(const bool enable) override; - void CursorLineFeed(const bool withReturn) override; - void DeleteCharacter(const til::CoordType count) override; - void InsertCharacter(const til::CoordType count) override; - void EraseCharacters(const til::CoordType numChars) override; - bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override; - bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override; + void SetAutoWrapMode(const bool wrapAtEOL) override; + void SetScrollingRegion(const til::inclusive_rect& scrollMargins) override; void WarningBell() override; - void SetWindowTitle(std::wstring_view title) override; - COLORREF GetColorTableEntry(const size_t tableIndex) const override; - void SetColorTableEntry(const size_t tableIndex, const COLORREF color) override; - void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) override; - void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) override; - - void SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override; - void SetRenderMode(const ::Microsoft::Console::Render::RenderSettings::Mode mode, const bool enabled) override; - + bool GetLineFeedMode() const override; + void LineFeed(const bool withReturn) override; + void SetWindowTitle(const std::wstring_view title) override; + CursorType GetUserDefaultCursorStyle() const override; + bool ResizeWindow(const size_t width, const size_t height) override; + void SetConsoleOutputCP(const unsigned int codepage) override; + unsigned int GetConsoleOutputCP() const override; void EnableXtermBracketedPasteMode(const bool enabled) override; - bool IsXtermBracketedPasteModeEnabled() const override; - - bool IsVtInputEnabled() const override; - void CopyToClipboard(std::wstring_view content) override; - - void AddHyperlink(std::wstring_view uri, std::wstring_view params) override; - void EndHyperlink() override; - void SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) override; void SetWorkingDirectory(std::wstring_view uri) override; - std::wstring_view GetWorkingDirectory() override; - - void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override; - void PopGraphicsRendition() override; - void ShowWindow(bool showOrHide) override; - void UseAlternateScreenBuffer() override; void UseMainScreenBuffer() override; - + bool IsConsolePty() const override; + bool IsVtInputEnabled() const override; + void NotifyAccessibilityChange(const til::rect& changedRect) override; #pragma endregion #pragma region ITerminalInput @@ -169,8 +156,8 @@ class Microsoft::Terminal::Core::Terminal final : #pragma region IBaseData(base to IRenderData and IUiaData) Microsoft::Console::Types::Viewport GetViewport() noexcept override; COORD GetTextBufferEndPosition() const noexcept override; - const TextBuffer& GetTextBuffer() noexcept override; - const FontInfo& GetFontInfo() noexcept override; + const TextBuffer& GetTextBuffer() const noexcept override; + const FontInfo& GetFontInfo() const noexcept override; void LockConsole() noexcept override; void UnlockConsole() noexcept override; @@ -213,7 +200,6 @@ class Microsoft::Terminal::Core::Terminal final : void SetCopyToClipboardCallback(std::function pfn) noexcept; void SetScrollPositionChangedCallback(std::function pfn) noexcept; void SetCursorPositionChangedCallback(std::function pfn) noexcept; - void SetBackgroundCallback(std::function pfn) noexcept; void TaskbarProgressChangedCallback(std::function pfn) noexcept; void SetShowWindowCallback(std::function pfn) noexcept; @@ -279,7 +265,6 @@ class Microsoft::Terminal::Core::Terminal final : #endif std::function _pfnScrollPositionChanged; - std::function _pfnBackgroundColorChanged; std::function _pfnCursorPositionChanged; std::function)> _pfnTabColorChanged; std::function _pfnTaskbarProgressChanged; @@ -404,8 +389,6 @@ class Microsoft::Terminal::Core::Terminal final : void _MoveByBuffer(SelectionDirection direction, COORD& pos); #pragma endregion - Microsoft::Console::VirtualTerminal::SgrStack _sgrStack; - #ifdef UNIT_TESTING friend class TerminalCoreUnitTests::TerminalBufferTests; friend class TerminalCoreUnitTests::TerminalApiTest; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index ff04aff29fd..c8af8f07b2b 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -11,307 +11,84 @@ using namespace Microsoft::Console::Types; using namespace Microsoft::Console::VirtualTerminal; // Print puts the text in the buffer and moves the cursor -void Terminal::PrintString(std::wstring_view stringView) +void Terminal::PrintString(const std::wstring_view string) { - _WriteBuffer(stringView); + _WriteBuffer(string); } -TextAttribute Terminal::GetTextAttributes() const +void Terminal::ReturnResponse(const std::wstring_view response) { - return _activeBuffer().GetCurrentAttributes(); -} - -bool Terminal::ReturnResponse(std::wstring_view responseString) -{ - if (!_pfnWriteInput) + if (_pfnWriteInput) { - return false; + _pfnWriteInput(response); } - _pfnWriteInput(responseString); - return true; } -void Terminal::SetTextAttributes(const TextAttribute& attrs) +Microsoft::Console::VirtualTerminal::StateMachine& Terminal::GetStateMachine() { - _activeBuffer().SetCurrentAttributes(attrs); + return *_stateMachine; } -Viewport Terminal::GetBufferSize() +TextBuffer& Terminal::GetTextBuffer() { - return _activeBuffer().GetSize(); + return _activeBuffer(); } -void Terminal::SetCursorPosition(til::point pos) +til::rect Terminal::GetViewport() const { - const auto viewport = _GetMutableViewport(); - const til::point viewOrigin{ viewport.Origin() }; - auto newPos = til::unwrap_coord(viewOrigin + pos); - viewport.Clamp(newPos); - _activeBuffer().GetCursor().SetPosition(newPos); + return til::rect{ _GetMutableViewport().ToInclusive() }; } -til::point Terminal::GetCursorPosition() +void Terminal::SetViewportPosition(const til::point position) { - const til::point absoluteCursorPos{ _activeBuffer().GetCursor().GetPosition() }; - const auto viewport = _GetMutableViewport(); - const til::point viewOrigin{ viewport.Origin() }; - // TODO assert that the coord is > (0, 0) && <(view.W, view.H) - return absoluteCursorPos - viewOrigin; + const auto dimensions = _GetMutableViewport().Dimensions(); + _mutableViewport = Viewport::FromDimensions(position.to_win32_coord(), dimensions); + Terminal::_NotifyScrollEvent(); } -// Method Description: -// - Moves the cursor down one line, and possibly also to the leftmost column. -// Arguments: -// - withReturn, set to true if a carriage return should be performed as well. -// Return value: -// - -void Terminal::CursorLineFeed(const bool withReturn) +void Terminal::SetTextAttributes(const TextAttribute& attrs) { - auto cursorPos = _activeBuffer().GetCursor().GetPosition(); - - // since we explicitly just moved down a row, clear the wrap status on the - // row we just came from - _activeBuffer().GetRowByOffset(cursorPos.Y).SetWrapForced(false); - - cursorPos.Y++; - if (withReturn) - { - cursorPos.X = 0; - } - _AdjustCursorPosition(cursorPos); + _activeBuffer().SetCurrentAttributes(attrs); } -// Method Description: -// - deletes count characters starting from the cursor's current position -// - it moves over the remaining text to 'replace' the deleted text -// - for example, if the buffer looks like this ('|' is the cursor): [abc|def] -// - calling DeleteCharacter(1) will change it to: [abc|ef], -// - i.e. the 'd' gets deleted and the 'ef' gets shifted over 1 space and **retain their previous text attributes** -// Arguments: -// - count, the number of characters to delete -// Return value: -// - -void Terminal::DeleteCharacter(const til::CoordType count) +void Terminal::SetAutoWrapMode(const bool /*wrapAtEOL*/) { - const auto cursorPos = _activeBuffer().GetCursor().GetPosition(); - const auto copyToPos = cursorPos; - const til::point copyFromPos{ cursorPos.X + count, cursorPos.Y }; - const auto viewport = _GetMutableViewport(); - - const auto sourceWidth = viewport.RightExclusive() - copyFromPos.X; - - // Get a rectangle of the source - auto source = Viewport::FromDimensions(til::unwrap_coord(copyFromPos), gsl::narrow(sourceWidth), 1); - - // Get a rectangle of the target - const auto target = Viewport::FromDimensions(copyToPos, source.Dimensions()); - const auto walkDirection = Viewport::DetermineWalkDirection(source, target); - - auto sourcePos = source.GetWalkOrigin(walkDirection); - auto targetPos = target.GetWalkOrigin(walkDirection); - - // Iterate over the source cell data and copy it over to the target - do - { - const auto data = OutputCell(*(_activeBuffer().GetCellDataAt(sourcePos))); - _activeBuffer().Write(OutputCellIterator({ &data, 1 }), targetPos); - } while (source.WalkInBounds(sourcePos, walkDirection) && target.WalkInBounds(targetPos, walkDirection)); + // TODO: This will be needed to support DECAWM. } -// Method Description: -// - Inserts count spaces starting from the cursor's current position, moving over the existing text -// - for example, if the buffer looks like this ('|' is the cursor): [abc|def] -// - calling InsertCharacter(1) will change it to: [abc| def], -// - i.e. the 'def' gets shifted over 1 space and **retain their previous text attributes** -// Arguments: -// - count, the number of spaces to insert -// Return value: -// - -void Terminal::InsertCharacter(const til::CoordType count) +void Terminal::SetScrollingRegion(const til::inclusive_rect& /*scrollMargins*/) { - // NOTE: the code below is _extremely_ similar to DeleteCharacter - // We will want to use this same logic and implement a helper function instead - // that does the 'move a region from here to there' operation - // TODO: GitHub issue #2163 - const auto cursorPos = _activeBuffer().GetCursor().GetPosition(); - const auto copyFromPos = cursorPos; - const til::point copyToPos{ cursorPos.X + count, cursorPos.Y }; - const auto viewport = _GetMutableViewport(); - const auto sourceWidth = viewport.RightExclusive() - copyFromPos.X; - - // Get a rectangle of the source - auto source = Viewport::FromDimensions(copyFromPos, gsl::narrow(sourceWidth), 1); - - // Get a rectangle of the target - const auto target = Viewport::FromDimensions(til::unwrap_coord(copyToPos), source.Dimensions()); - const auto walkDirection = Viewport::DetermineWalkDirection(source, target); - - auto sourcePos = source.GetWalkOrigin(walkDirection); - auto targetPos = target.GetWalkOrigin(walkDirection); - - // Iterate over the source cell data and copy it over to the target - do - { - const auto data = OutputCell(*(_activeBuffer().GetCellDataAt(sourcePos))); - _activeBuffer().Write(OutputCellIterator({ &data, 1 }), targetPos); - } while (source.WalkInBounds(sourcePos, walkDirection) && target.WalkInBounds(targetPos, walkDirection)); - const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _activeBuffer().GetCurrentAttributes(), count); - _activeBuffer().Write(eraseIter, cursorPos); + // TODO: This will be needed to fully support DECSTBM. } -void Terminal::EraseCharacters(const til::CoordType numChars) +void Terminal::WarningBell() { - const auto absoluteCursorPos = _activeBuffer().GetCursor().GetPosition(); - const auto viewport = _GetMutableViewport(); - const auto distanceToRight = viewport.RightExclusive() - absoluteCursorPos.X; - const auto fillLimit = std::min(numChars, distanceToRight); - const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _activeBuffer().GetCurrentAttributes(), fillLimit); - _activeBuffer().Write(eraseIter, absoluteCursorPos); + _pfnWarningBell(); } -// Method description: -// - erases a line of text, either from -// 1. beginning to the cursor's position -// 2. cursor's position to end -// 3. beginning to end -// - depending on the erase type -// Arguments: -// - the erase type -// Return value: -// - true if succeeded, false otherwise -bool Terminal::EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) +bool Terminal::GetLineFeedMode() const { - const auto cursorPos = _activeBuffer().GetCursor().GetPosition(); - const auto viewport = _GetMutableViewport(); - til::point startPos; - startPos.Y = cursorPos.Y; - // nlength determines the number of spaces we need to write - DWORD nlength = 0; - - // Determine startPos.X and nlength by the eraseType - switch (eraseType) - { - case DispatchTypes::EraseType::FromBeginning: - nlength = cursorPos.X - viewport.Left() + 1; - break; - case DispatchTypes::EraseType::ToEnd: - startPos.X = cursorPos.X; - nlength = viewport.RightExclusive() - startPos.X; - break; - case DispatchTypes::EraseType::All: - startPos.X = viewport.Left(); - nlength = viewport.RightExclusive() - startPos.X; - break; - default: - return false; - } - - const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _activeBuffer().GetCurrentAttributes(), nlength); - - // Explicitly turn off end-of-line wrap-flag-setting when erasing cells. - _activeBuffer().Write(eraseIter, til::unwrap_coord(startPos), false); - return true; + // TODO: This will be needed to support LNM. + return false; } -// Method description: -// - erases text in the buffer in two ways depending on erase type -// 1. 'erases' all text visible to the user (i.e. the text in the viewport) -// 2. erases all the text in the scrollback -// Arguments: -// - the erase type -// Return Value: -// - true if succeeded, false otherwise -bool Terminal::EraseInDisplay(const DispatchTypes::EraseType eraseType) +void Terminal::LineFeed(const bool withReturn) { - // Store the relative cursor position so we can restore it later after we move the viewport - const auto cursorPos = _activeBuffer().GetCursor().GetPosition(); -#pragma warning(suppress : 26496) // This is written by ConvertToOrigin, cpp core checks is wrong saying it should be const. - auto relativeCursor = cursorPos; - const auto viewport = _GetMutableViewport(); - - viewport.ConvertToOrigin(&relativeCursor); - - // Initialize the new location of the viewport - // the top and bottom parameters are determined by the eraseType - SMALL_RECT newWin; - newWin.Left = viewport.Left(); - newWin.Right = viewport.RightExclusive(); - - if (eraseType == DispatchTypes::EraseType::All) - { - // If we're in the alt buffer, take a shortcut. Just increment the buffer enough to cycle the whole thing out and start fresh. This - if (_inAltBuffer()) - { - for (auto i = 0; i < viewport.Height(); i++) - { - _activeBuffer().IncrementCircularBuffer(); - } - return true; - } - // In this case, we simply move the viewport down, effectively pushing whatever text was on the screen into the scrollback - // and thus 'erasing' the text visible to the user - const auto coordLastChar = _activeBuffer().GetLastNonSpaceCharacter(viewport); - if (coordLastChar.X == 0 && coordLastChar.Y == 0) - { - // Nothing to clear, just return - return true; - } - - short sNewTop = coordLastChar.Y + 1; - - // Increment the circular buffer only if the new location of the viewport would be 'below' the buffer - const auto delta = (sNewTop + viewport.Height()) - (_activeBuffer().GetSize().Height()); - for (auto i = 0; i < delta; i++) - { - _activeBuffer().IncrementCircularBuffer(); - sNewTop--; - } - - newWin.Top = sNewTop; - newWin.Bottom = sNewTop + viewport.Height(); - } - else if (eraseType == DispatchTypes::EraseType::Scrollback) - { - // We only want to erase the scrollback, and leave everything else on the screen as it is - // so we grab the text in the viewport and rotate it up to the top of the buffer - COORD scrollFromPos{ 0, 0 }; - viewport.ConvertFromOrigin(&scrollFromPos); - _activeBuffer().ScrollRows(scrollFromPos.Y, viewport.Height(), -scrollFromPos.Y); - - // Since we only did a rotation, the text that was in the scrollback is now _below_ where we are going to move the viewport - // and we have to make sure we erase that text - const auto eraseStart = viewport.Height(); - const auto eraseEnd = _activeBuffer().GetLastNonSpaceCharacter(viewport).Y; - for (auto i = eraseStart; i <= eraseEnd; i++) - { - _activeBuffer().GetRowByOffset(i).Reset(_activeBuffer().GetCurrentAttributes()); - } + auto cursorPos = _activeBuffer().GetCursor().GetPosition(); - // Reset the scroll offset now because there's nothing for the user to 'scroll' to - _scrollOffset = 0; + // since we explicitly just moved down a row, clear the wrap status on the + // row we just came from + _activeBuffer().GetRowByOffset(cursorPos.Y).SetWrapForced(false); - newWin.Top = 0; - newWin.Bottom = viewport.Height(); - } - else + cursorPos.Y++; + if (withReturn) { - return false; + cursorPos.X = 0; } - - // Move the viewport, adjust the scroll bar if needed, and restore the old cursor position - _mutableViewport = Viewport::FromExclusive(newWin); - Terminal::_NotifyScrollEvent(); - SetCursorPosition(til::point{ relativeCursor }); - - return true; -} - -void Terminal::WarningBell() -{ - _pfnWarningBell(); + _AdjustCursorPosition(cursorPos); } -void Terminal::SetWindowTitle(std::wstring_view title) +void Terminal::SetWindowTitle(const std::wstring_view title) { if (!_suppressApplicationTitle) { @@ -320,112 +97,26 @@ void Terminal::SetWindowTitle(std::wstring_view title) } } -// Method Description: -// - Retrieves the value in the colortable at the specified index. -// Arguments: -// - tableIndex: the index of the color table to retrieve. -// Return Value: -// - the COLORREF value for the color at that index in the table. -COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const +CursorType Terminal::GetUserDefaultCursorStyle() const { - return _renderSettings.GetColorTableEntry(tableIndex); + return _defaultCursorShape; } -// Method Description: -// - Updates the value in the colortable at index tableIndex to the new color -// color. color is a COLORREF, format 0x00BBGGRR. -// Arguments: -// - tableIndex: the index of the color table to update. -// - color: the new COLORREF to use as that color table value. -// Return Value: -// - -void Terminal::SetColorTableEntry(const size_t tableIndex, const COLORREF color) -{ - _renderSettings.SetColorTableEntry(tableIndex, color); - - if (tableIndex == _renderSettings.GetColorAliasIndex(ColorAlias::DefaultBackground)) - { - _pfnBackgroundColorChanged(color); - } - - // Repaint everything - the colors might have changed - _activeBuffer().TriggerRedrawAll(); -} - -// Method Description: -// - Sets the position in the color table for the given color alias. -// Arguments: -// - alias: the color alias to update. -// - tableIndex: the new position of the alias in the color table. -// Return Value: -// - -void Terminal::SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) +bool Terminal::ResizeWindow(const size_t /*width*/, const size_t /*height*/) { - _renderSettings.SetColorAliasIndex(alias, tableIndex); -} - -// Method Description: -// - Sets the cursor style to the given style. -// Arguments: -// - cursorStyle: the style to be set for the cursor -// Return Value: -// - -void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) -{ - auto finalCursorType = CursorType::Legacy; - auto shouldBlink = false; - - switch (cursorStyle) - { - case DispatchTypes::CursorStyle::UserDefault: - finalCursorType = _defaultCursorShape; - shouldBlink = true; - break; - case DispatchTypes::CursorStyle::BlinkingBlock: - finalCursorType = CursorType::FullBox; - shouldBlink = true; - break; - case DispatchTypes::CursorStyle::SteadyBlock: - finalCursorType = CursorType::FullBox; - shouldBlink = false; - break; - case DispatchTypes::CursorStyle::BlinkingUnderline: - finalCursorType = CursorType::Underscore; - shouldBlink = true; - break; - case DispatchTypes::CursorStyle::SteadyUnderline: - finalCursorType = CursorType::Underscore; - shouldBlink = false; - break; - case DispatchTypes::CursorStyle::BlinkingBar: - finalCursorType = CursorType::VerticalBar; - shouldBlink = true; - break; - case DispatchTypes::CursorStyle::SteadyBar: - finalCursorType = CursorType::VerticalBar; - shouldBlink = false; - break; - - default: - // Invalid argument should be ignored. - return; - } - - _activeBuffer().GetCursor().SetType(finalCursorType); - _activeBuffer().GetCursor().SetBlinkingAllowed(shouldBlink); + // TODO: This will be needed to support various resizing sequences. See also GH#1860. + return false; } -void Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) +void Terminal::SetConsoleOutputCP(const unsigned int /*codepage*/) { - _terminalInput->SetInputMode(mode, enabled); + // TODO: This will be needed to support 8-bit charsets and DOCS sequences. } -void Terminal::SetRenderMode(const RenderSettings::Mode mode, const bool enabled) +unsigned int Terminal::GetConsoleOutputCP() const { - _renderSettings.SetRenderMode(mode, enabled); - - // Repaint everything - the colors will have changed - _activeBuffer().TriggerRedrawAll(); + // TODO: See SetConsoleOutputCP above. + return CP_UTF8; } void Terminal::EnableXtermBracketedPasteMode(const bool enabled) @@ -433,67 +124,11 @@ void Terminal::EnableXtermBracketedPasteMode(const bool enabled) _bracketedPasteMode = enabled; } -bool Terminal::IsXtermBracketedPasteModeEnabled() const -{ - return _bracketedPasteMode; -} - -bool Terminal::IsVtInputEnabled() const -{ - // We should never be getting this call in Terminal. - FAIL_FAST(); -} - -void Terminal::SetCursorVisibility(const bool visible) -{ - _activeBuffer().GetCursor().SetIsVisible(visible); -} - -void Terminal::EnableCursorBlinking(const bool enable) -{ - _activeBuffer().GetCursor().SetBlinkingAllowed(enable); - - // GH#2642 - From what we've gathered from other terminals, when blinking is - // disabled, the cursor should remain On always, and have the visibility - // controlled by the IsVisible property. So when you do a printf "\e[?12l" - // to disable blinking, the cursor stays stuck On. At this point, only the - // cursor visibility property controls whether the user can see it or not. - // (Yes, the cursor can be On and NOT Visible) - _activeBuffer().GetCursor().SetIsOn(true); -} - void Terminal::CopyToClipboard(std::wstring_view content) { _pfnCopyToClipboard(content); } -// Method Description: -// - Updates the buffer's current text attributes to start a hyperlink -// Arguments: -// - The hyperlink URI -// - The customID provided (if there was one) -// Return Value: -// - -void Terminal::AddHyperlink(std::wstring_view uri, std::wstring_view params) -{ - auto attr = _activeBuffer().GetCurrentAttributes(); - const auto id = _activeBuffer().GetHyperlinkId(uri, params); - attr.SetHyperlinkId(id); - _activeBuffer().SetCurrentAttributes(attr); - _activeBuffer().AddHyperlinkToMap(uri, id); -} - -// Method Description: -// - Updates the buffer's current text attributes to end a hyperlink -// Return Value: -// - -void Terminal::EndHyperlink() -{ - auto attr = _activeBuffer().GetCurrentAttributes(); - attr.SetHyperlinkId(0); - _activeBuffer().SetCurrentAttributes(attr); -} - // Method Description: // - Updates the taskbar progress indicator // Arguments: @@ -549,37 +184,6 @@ void Terminal::SetWorkingDirectory(std::wstring_view uri) _workingDirectory = uri; } -std::wstring_view Terminal::GetWorkingDirectory() -{ - return _workingDirectory; -} - -// Method Description: -// - Saves the current text attributes to an internal stack. -// Arguments: -// - options, cOptions: if present, specify which portions of the current text attributes -// should be saved. Only a small subset of GraphicsOptions are actually supported; -// others are ignored. If no options are specified, all attributes are stored. -// Return Value: -// - -void Terminal::PushGraphicsRendition(const VTParameters options) -{ - _sgrStack.Push(_activeBuffer().GetCurrentAttributes(), options); -} - -// Method Description: -// - Restores text attributes from the internal stack. If only portions of text attributes -// were saved, combines those with the current attributes. -// Arguments: -// - -// Return Value: -// - -void Terminal::PopGraphicsRendition() -{ - const auto current = _activeBuffer().GetCurrentAttributes(); - _activeBuffer().SetCurrentAttributes(_sgrStack.Pop(current)); -} - void Terminal::UseAlternateScreenBuffer() { // the new alt buffer is exactly the size of the viewport. @@ -698,3 +302,18 @@ void Terminal::ShowWindow(bool showOrHide) _pfnShowWindowChanged(showOrHide); } } + +bool Terminal::IsConsolePty() const +{ + return false; +} + +bool Terminal::IsVtInputEnabled() const +{ + return false; +} + +void Terminal::NotifyAccessibilityChange(const til::rect& /*changedRect*/) +{ + // This is only needed in conhost. Terminal handles accessibility in another way. +} diff --git a/src/cascadia/TerminalCore/TerminalDispatch.cpp b/src/cascadia/TerminalCore/TerminalDispatch.cpp deleted file mode 100644 index aff4f4efce7..00000000000 --- a/src/cascadia/TerminalCore/TerminalDispatch.cpp +++ /dev/null @@ -1,893 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include "TerminalDispatch.hpp" -#include "../../types/inc/utils.hpp" - -using namespace Microsoft::Console; -using namespace ::Microsoft::Terminal::Core; -using namespace ::Microsoft::Console::Render; -using namespace ::Microsoft::Console::VirtualTerminal; - -// NOTE: -// Functions related to Set Graphics Renditions (SGR) are in -// TerminalDispatchGraphics.cpp, not this file - -TerminalDispatch::TerminalDispatch(ITerminalApi& terminalApi) noexcept : - _terminalApi{ terminalApi } -{ -} - -void TerminalDispatch::Print(const wchar_t wchPrintable) -{ - _terminalApi.PrintString({ &wchPrintable, 1 }); -} - -void TerminalDispatch::PrintString(const std::wstring_view string) -{ - _terminalApi.PrintString(string); -} - -bool TerminalDispatch::CursorPosition(VTInt line, - VTInt column) -{ - _terminalApi.SetCursorPosition({ column - 1, line - 1 }); - return true; -} - -bool TerminalDispatch::CursorVisibility(const bool isVisible) -{ - _terminalApi.SetCursorVisibility(isVisible); - return true; -} - -bool TerminalDispatch::EnableCursorBlinking(const bool enable) -{ - _terminalApi.EnableCursorBlinking(enable); - return true; -} - -bool TerminalDispatch::CursorForward(const VTInt distance) -{ - const auto cursorPos = _terminalApi.GetCursorPosition(); - _terminalApi.SetCursorPosition({ cursorPos.X + distance, cursorPos.Y }); - return true; -} - -bool TerminalDispatch::CursorBackward(const VTInt distance) -{ - const auto cursorPos = _terminalApi.GetCursorPosition(); - _terminalApi.SetCursorPosition({ cursorPos.X - distance, cursorPos.Y }); - return true; -} - -bool TerminalDispatch::CursorUp(const VTInt distance) -{ - const auto cursorPos = _terminalApi.GetCursorPosition(); - _terminalApi.SetCursorPosition({ cursorPos.X, cursorPos.Y + distance }); - return true; -} - -bool TerminalDispatch::LineFeed(const DispatchTypes::LineFeedType lineFeedType) -{ - switch (lineFeedType) - { - case DispatchTypes::LineFeedType::DependsOnMode: - // There is currently no need for mode-specific line feeds in the Terminal, - // so for now we just treat them as a line feed without carriage return. - case DispatchTypes::LineFeedType::WithoutReturn: - _terminalApi.CursorLineFeed(false); - return true; - case DispatchTypes::LineFeedType::WithReturn: - _terminalApi.CursorLineFeed(true); - return true; - default: - return false; - } -} - -bool TerminalDispatch::EraseCharacters(const VTInt numChars) -{ - _terminalApi.EraseCharacters(numChars); - return true; -} - -bool TerminalDispatch::WarningBell() -{ - _terminalApi.WarningBell(); - return true; -} - -bool TerminalDispatch::CarriageReturn() -{ - const auto cursorPos = _terminalApi.GetCursorPosition(); - _terminalApi.SetCursorPosition({ 0, cursorPos.Y }); - return true; -} - -bool TerminalDispatch::SetWindowTitle(std::wstring_view title) -{ - _terminalApi.SetWindowTitle(title); - return true; -} - -bool TerminalDispatch::HorizontalTabSet() -{ - const auto width = _terminalApi.GetBufferSize().Dimensions().X; - const auto column = _terminalApi.GetCursorPosition().X; - - _InitTabStopsForWidth(width); - _tabStopColumns.at(column) = true; - return true; -} - -bool TerminalDispatch::ForwardTab(const VTInt numTabs) -{ - const auto width = _terminalApi.GetBufferSize().Dimensions().X; - const auto cursorPosition = _terminalApi.GetCursorPosition(); - auto column = cursorPosition.X; - const auto row = cursorPosition.Y; - VTInt tabsPerformed = 0; - _InitTabStopsForWidth(width); - while (column + 1 < width && tabsPerformed < numTabs) - { - column++; - if (til::at(_tabStopColumns, column)) - { - tabsPerformed++; - } - } - - _terminalApi.SetCursorPosition({ column, row }); - return true; -} - -bool TerminalDispatch::BackwardsTab(const VTInt numTabs) -{ - const auto width = _terminalApi.GetBufferSize().Dimensions().X; - const auto cursorPosition = _terminalApi.GetCursorPosition(); - auto column = cursorPosition.X; - const auto row = cursorPosition.Y; - VTInt tabsPerformed = 0; - _InitTabStopsForWidth(width); - while (column > 0 && tabsPerformed < numTabs) - { - column--; - if (til::at(_tabStopColumns, column)) - { - tabsPerformed++; - } - } - - _terminalApi.SetCursorPosition({ column, row }); - return true; -} - -bool TerminalDispatch::TabClear(const DispatchTypes::TabClearType clearType) -{ - switch (clearType) - { - case DispatchTypes::TabClearType::ClearCurrentColumn: - _ClearSingleTabStop(); - return true; - case DispatchTypes::TabClearType::ClearAllColumns: - _ClearAllTabStops(); - return true; - default: - return false; - } -} - -// Method Description: -// - Sets a single entry of the colortable to a new value -// Arguments: -// - tableIndex: The VT color table index -// - color: The new RGB color value to use. -// Return Value: -// - True. -bool TerminalDispatch::SetColorTableEntry(const size_t tableIndex, - const DWORD color) -{ - _terminalApi.SetColorTableEntry(tableIndex, color); - return true; -} - -bool TerminalDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) -{ - _terminalApi.SetCursorStyle(cursorStyle); - return true; -} - -bool TerminalDispatch::SetCursorColor(const DWORD color) -{ - _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color); - return true; -} - -bool TerminalDispatch::SetClipboard(std::wstring_view content) -{ - _terminalApi.CopyToClipboard(content); - return true; -} - -// Method Description: -// - Sets the default foreground color to a new value -// Arguments: -// - color: The new RGB color value to use, in 0x00BBGGRR form -// Return Value: -// - True. -bool TerminalDispatch::SetDefaultForeground(const DWORD color) -{ - _terminalApi.SetColorAliasIndex(ColorAlias::DefaultForeground, TextColor::DEFAULT_FOREGROUND); - _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color); - return true; -} - -// Method Description: -// - Sets the default background color to a new value -// Arguments: -// - color: The new RGB color value to use, in 0x00BBGGRR form -// Return Value: -// - True. -bool TerminalDispatch::SetDefaultBackground(const DWORD color) -{ - _terminalApi.SetColorAliasIndex(ColorAlias::DefaultBackground, TextColor::DEFAULT_BACKGROUND); - _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color); - return true; -} - -// Method Description: -// - Erases characters in the buffer depending on the erase type -// Arguments: -// - eraseType: the erase type (from beginning, to end, or all) -// Return Value: -// True if handled successfully. False otherwise. -bool TerminalDispatch::EraseInLine(const DispatchTypes::EraseType eraseType) -{ - return _terminalApi.EraseInLine(eraseType); -} - -// Method Description: -// - Deletes count number of characters starting from where the cursor is currently -// Arguments: -// - count, the number of characters to delete -// Return Value: -// - True. -bool TerminalDispatch::DeleteCharacter(const VTInt count) -{ - _terminalApi.DeleteCharacter(count); - return true; -} - -// Method Description: -// - Adds count number of spaces starting from where the cursor is currently -// Arguments: -// - count, the number of spaces to add -// Return Value: -// - True. -bool TerminalDispatch::InsertCharacter(const VTInt count) -{ - _terminalApi.InsertCharacter(count); - return true; -} - -// Method Description: -// - Moves the viewport and erases text from the buffer depending on the eraseType -// Arguments: -// - eraseType: the desired erase type -// Return Value: -// True if handled successfully. False otherwise -bool TerminalDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType) -{ - return _terminalApi.EraseInDisplay(eraseType); -} - -// - DECKPAM, DECKPNM - Sets the keypad input mode to either Application mode or Numeric mode (true, false respectively) -// Arguments: -// - applicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input. -// Return Value: -// - True. -bool TerminalDispatch::SetKeypadMode(const bool applicationMode) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::Keypad, applicationMode); - return true; -} - -// - DECCKM - Sets the cursor keys input mode to either Application mode or Normal mode (true, false respectively) -// Arguments: -// - applicationMode - set to true to enable Application Mode Input, false for Normal Mode Input. -// Return Value: -// - True. -bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::CursorKey, applicationMode); - return true; -} - -// Routine Description: -// - DECSCNM - Sets the screen mode to either normal or reverse. -// When in reverse screen mode, the background and foreground colors are switched. -// Arguments: -// - reverseMode - set to true to enable reverse screen mode, false for normal mode. -// Return Value: -// - True. -bool TerminalDispatch::SetScreenMode(const bool reverseMode) -{ - _terminalApi.SetRenderMode(RenderSettings::Mode::ScreenReversed, reverseMode); - return true; -} - -// Method Description: -// - win32-input-mode: Enable sending full input records encoded as a string of -// characters to the client application. -// Arguments: -// - win32InputMode - set to true to enable win32-input-mode, false to disable. -// Return Value: -// - True. -bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::Win32, win32Mode); - return true; -} - -//Routine Description: -// Enable VT200 Mouse Mode - Enables/disables the mouse input handler in default tracking mode. -//Arguments: -// - enabled - true to enable, false to disable. -// Return value: -// - True. -bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::DefaultMouseTracking, enabled); - return true; -} - -//Routine Description: -// Enable UTF-8 Extended Encoding - this changes the encoding scheme for sequences -// emitted by the mouse input handler. Does not enable/disable mouse mode on its own. -//Arguments: -// - enabled - true to enable, false to disable. -// Return value: -// - True. -bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, enabled); - return true; -} - -//Routine Description: -// Enable SGR Extended Encoding - this changes the encoding scheme for sequences -// emitted by the mouse input handler. Does not enable/disable mouse mode on its own. -//Arguments: -// - enabled - true to enable, false to disable. -// Return value: -// - True. -bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::SgrMouseEncoding, enabled); - return true; -} - -//Routine Description: -// Enable Button Event mode - send mouse move events WITH A BUTTON PRESSED to the input. -//Arguments: -// - enabled - true to enable, false to disable. -// Return value: -// - True. -bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, enabled); - return true; -} - -//Routine Description: -// Enable Any Event mode - send all mouse events to the input. -//Arguments: -// - enabled - true to enable, false to disable. -// Return value: -// - True. -bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, enabled); - return true; -} - -// Method Description: -// - Enables/disables focus event mode. A client may enable this if they want to -// receive focus events. -// - ConPTY always enables this mode and never disables it. For more details, see GH#12900. -// Arguments: -// - enabled - true to enable, false to disable. -// Return Value: -// - True if handled successfully. False otherwise. -bool TerminalDispatch::EnableFocusEventMode(const bool enabled) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::FocusEvent, enabled); - return true; -} - -//Routine Description: -// Enable Alternate Scroll Mode - When in the Alt Buffer, send CUP and CUD on -// scroll up/down events instead of the usual sequences -//Arguments: -// - enabled - true to enable, false to disable. -// Return value: -// - True. -bool TerminalDispatch::EnableAlternateScroll(const bool enabled) -{ - _terminalApi.SetInputMode(TerminalInput::Mode::AlternateScroll, enabled); - return true; -} - -//Routine Description: -// Enable Bracketed Paste Mode - this changes the behavior of pasting. -// See: https://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode -//Arguments: -// - enabled - true to enable, false to disable. -// Return value: -// - True. -bool TerminalDispatch::EnableXtermBracketedPasteMode(const bool enabled) -{ - _terminalApi.EnableXtermBracketedPasteMode(enabled); - return true; -} - -bool TerminalDispatch::SetMode(const DispatchTypes::ModeParams param) -{ - return _ModeParamsHelper(param, true); -} - -bool TerminalDispatch::ResetMode(const DispatchTypes::ModeParams param) -{ - return _ModeParamsHelper(param, false); -} - -// Routine Description: -// - DSR - Reports status of a console property back to the STDIN based on the type of status requested. -// - This particular routine responds to ANSI status patterns only (CSI # n), not the DEC format (CSI ? # n) -// Arguments: -// - statusType - ANSI status type indicating what property we should report back -// Return Value: -// - True if handled successfully. False otherwise. -bool TerminalDispatch::DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType) -{ - auto success = false; - - switch (statusType) - { - case DispatchTypes::AnsiStatusType::OS_OperatingStatus: - success = _OperatingStatus(); - break; - case DispatchTypes::AnsiStatusType::CPR_CursorPositionReport: - success = _CursorPositionReport(); - break; - } - - return success; -} - -// Routine Description: -// - DSR-OS - Reports the operating status back to the input channel -// Arguments: -// - -// Return Value: -// - True if handled successfully. False otherwise. -bool TerminalDispatch::_OperatingStatus() const -{ - // We always report a good operating condition. - return _WriteResponse(L"\x1b[0n"); -} - -// Routine Description: -// - DSR-CPR - Reports the current cursor position within the viewport back to the input channel -// Arguments: -// - -// Return Value: -// - True if handled successfully. False otherwise. -bool TerminalDispatch::_CursorPositionReport() const -{ - // Now send it back into the input channel of the console. - // First format the response string. - const auto pos = _terminalApi.GetCursorPosition(); - // VT has origin at 1,1 where as we use 0,0 internally - const auto response = wil::str_printf(L"\x1b[%d;%dR", pos.Y + 1, pos.X + 1); - return _WriteResponse(response); -} - -// Method Description: -// - Start a hyperlink -// Arguments: -// - uri - the hyperlink URI -// - params - the optional custom ID -// Return Value: -// - true -bool TerminalDispatch::AddHyperlink(const std::wstring_view uri, const std::wstring_view params) -{ - _terminalApi.AddHyperlink(uri, params); - return true; -} - -// Method Description: -// - End a hyperlink -// Return Value: -// - true -bool TerminalDispatch::EndHyperlink() -{ - _terminalApi.EndHyperlink(); - return true; -} - -// Method Description: -// - Performs a ConEmu action -// - Currently, the only action we support is setting the taskbar state/progress -// Arguments: -// - string: contains the parameters that define which action we do -// Return Value: -// - true -bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) -{ - unsigned int state = 0; - unsigned int progress = 0; - - const auto parts = Utils::SplitString(string, L';'); - unsigned int subParam = 0; - - if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam)) - { - return false; - } - - // 4 is SetProgressBar, which sets the taskbar state/progress. - if (subParam == 4) - { - if (parts.size() >= 2) - { - // A state parameter is defined, parse it out - const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state); - if (!stateSuccess && !til::at(parts, 1).empty()) - { - return false; - } - if (parts.size() >= 3) - { - // A progress parameter is also defined, parse it out - const auto progressSuccess = Utils::StringToUint(til::at(parts, 2), progress); - if (!progressSuccess && !til::at(parts, 2).empty()) - { - return false; - } - } - } - - if (state > TaskbarMaxState) - { - // state is out of bounds, return false - return false; - } - if (progress > TaskbarMaxProgress) - { - // progress is greater than the maximum allowed value, clamp it to the max - progress = TaskbarMaxProgress; - } - _terminalApi.SetTaskbarProgress(static_cast(state), progress); - return true; - } - // 9 is SetWorkingDirectory, which informs the terminal about the current working directory. - else if (subParam == 9) - { - if (parts.size() >= 2) - { - const auto path = til::at(parts, 1); - // The path should be surrounded with '"' according to the documentation of ConEmu. - // An example: 9;"D:/" - if (path.at(0) == L'"' && path.at(path.size() - 1) == L'"' && path.size() >= 3) - { - _terminalApi.SetWorkingDirectory(path.substr(1, path.size() - 2)); - } - else - { - // If we fail to find the surrounding quotation marks, we'll give the path a try anyway. - // ConEmu also does this. - _terminalApi.SetWorkingDirectory(path); - } - return true; - } - } - - return false; -} - -// Routine Description: -// - Helper to send a string reply to the input stream of the console. -// - Used by various commands where the program attached would like a reply to one of the commands issued. -// Arguments: -// - reply - The reply string to transmit back to the input stream -// Return Value: -// - True if the string was sent to the connected application. False otherwise. -bool TerminalDispatch::_WriteResponse(const std::wstring_view reply) const -{ - return _terminalApi.ReturnResponse(reply); -} - -// Routine Description: -// - Support routine for routing private mode parameters to be set/reset as flags -// Arguments: -// - param - mode parameter to set/reset -// - enable - True for set, false for unset. -// Return Value: -// - True if handled successfully. False otherwise. -bool TerminalDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param, const bool enable) -{ - auto success = false; - switch (param) - { - case DispatchTypes::ModeParams::DECCKM_CursorKeysMode: - // set - Enable Application Mode, reset - Normal mode - success = SetCursorKeysMode(enable); - break; - case DispatchTypes::ModeParams::DECSCNM_ScreenMode: - success = SetScreenMode(enable); - break; - case DispatchTypes::ModeParams::VT200_MOUSE_MODE: - success = EnableVT200MouseMode(enable); - break; - case DispatchTypes::ModeParams::BUTTON_EVENT_MOUSE_MODE: - success = EnableButtonEventMouseMode(enable); - break; - case DispatchTypes::ModeParams::ANY_EVENT_MOUSE_MODE: - success = EnableAnyEventMouseMode(enable); - break; - case DispatchTypes::ModeParams::UTF8_EXTENDED_MODE: - success = EnableUTF8ExtendedMouseMode(enable); - break; - case DispatchTypes::ModeParams::SGR_EXTENDED_MODE: - success = EnableSGRExtendedMouseMode(enable); - break; - case DispatchTypes::ModeParams::FOCUS_EVENT_MODE: - success = EnableFocusEventMode(enable); - break; - case DispatchTypes::ModeParams::ALTERNATE_SCROLL: - success = EnableAlternateScroll(enable); - break; - case DispatchTypes::ModeParams::DECTCEM_TextCursorEnableMode: - success = CursorVisibility(enable); - break; - case DispatchTypes::ModeParams::ATT610_StartCursorBlink: - success = EnableCursorBlinking(enable); - break; - case DispatchTypes::ModeParams::XTERM_BracketedPasteMode: - success = EnableXtermBracketedPasteMode(enable); - break; - 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; - break; - } - return success; -} - -void TerminalDispatch::_ClearSingleTabStop() -{ - const auto width = _terminalApi.GetBufferSize().Dimensions().X; - const auto column = _terminalApi.GetCursorPosition().X; - - _InitTabStopsForWidth(width); - _tabStopColumns.at(column) = false; -} - -void TerminalDispatch::_ClearAllTabStops() -{ - _tabStopColumns.clear(); - _initDefaultTabStops = false; -} - -void TerminalDispatch::_ResetTabStops() -{ - _tabStopColumns.clear(); - _initDefaultTabStops = true; -} - -void TerminalDispatch::_InitTabStopsForWidth(const size_t width) -{ - const auto initialWidth = _tabStopColumns.size(); - if (width > initialWidth) - { - _tabStopColumns.resize(width); - if (_initDefaultTabStops) - { - for (auto column = 8u; column < _tabStopColumns.size(); column += 8) - { - if (column >= initialWidth) - { - til::at(_tabStopColumns, column) = true; - } - } - } - } -} - -bool TerminalDispatch::SoftReset() -{ - // TODO:GH#1883 much of this method is not yet implemented in the Terminal, - // because the Terminal _doesn't need to_ yet. The terminal is only ever - // connected to conpty, so it doesn't implement most of these things that - // Hard/Soft Reset would reset. As those things are implemented, they should - - // also get cleared here. - // - // This code is left here (from its original form in conhost) as a reminder - // of what needs to be done. - - CursorVisibility(true); // Cursor enabled. - // SetOriginMode(false); // Absolute cursor addressing. - // SetAutoWrapMode(true); // Wrap at end of line. - SetCursorKeysMode(false); // Normal characters. - SetKeypadMode(false); // Numeric characters. - - // // Top margin = 1; bottom margin = page length. - // _DoSetTopBottomScrollingMargins(0, 0); - - // _termOutput = {}; // Reset all character set designations. - // if (_initialCodePage.has_value()) - // { - // // Restore initial code page if previously changed by a DOCS sequence. - // _pConApi->SetConsoleOutputCP(_initialCodePage.value()); - // } - - SetGraphicsRendition({}); // Normal rendition. - - // // Reset the saved cursor state. - // // Note that XTerm only resets the main buffer state, but that - // // seems likely to be a bug. Most other terminals reset both. - // _savedCursorState.at(0) = {}; // Main buffer - // _savedCursorState.at(1) = {}; // Alt buffer - - return true; -} - -bool TerminalDispatch::HardReset() -{ - // TODO:GH#1883 much of this method is not yet implemented in the Terminal, - // because the Terminal _doesn't need to_ yet. The terminal is only ever - // connected to conpty, so it doesn't implement most of these things that - // Hard/Soft Reset would reset. As those things ar implemented, they should - // also get cleared here. - // - // This code is left here (from its original form in conhost) as a reminder - // of what needs to be done. - - // // If in the alt buffer, switch back to main before doing anything else. - // if (_usingAltBuffer) - // { - // _pConApi->PrivateUseMainScreenBuffer(); - // _usingAltBuffer = false; - // } - - // Sets the SGR state to normal - this must be done before EraseInDisplay - // to ensure that it clears with the default background color. - SoftReset(); - - // Clears the screen - Needs to be done in two operations. - EraseInDisplay(DispatchTypes::EraseType::All); - EraseInDisplay(DispatchTypes::EraseType::Scrollback); - - // Set the DECSCNM screen mode back to normal. - SetScreenMode(false); - - // Cursor to 1,1 - the Soft Reset guarantees this is absolute - CursorPosition(1, 1); - - // Reset the mouse mode - EnableSGRExtendedMouseMode(false); - EnableAnyEventMouseMode(false); - - // Delete all current tab stops and reapply - _ResetTabStops(); - - return true; -} - -bool TerminalDispatch::WindowManipulation(const DispatchTypes::WindowManipulationType function, - const VTParameter /*parameter1*/, - const VTParameter /*parameter2*/) -{ - switch (function) - { - case DispatchTypes::WindowManipulationType::DeIconifyWindow: - _terminalApi.ShowWindow(true); - return true; - case DispatchTypes::WindowManipulationType::IconifyWindow: - _terminalApi.ShowWindow(false); - return true; - default: - return false; - } -} - -// Routine Description: -// - DECSC - Saves the current "cursor state" into a memory buffer. This -// includes the cursor position, origin mode, graphic rendition, and -// active character set. -// Arguments: -// - -// Return Value: -// - True. -bool TerminalDispatch::CursorSaveState() -{ - // TODO GH#3849: When de-duplicating this, the AdaptDispatch version of this - // is more elaborate. - const auto attributes = _terminalApi.GetTextAttributes(); - const auto coordCursor = _terminalApi.GetCursorPosition(); - // The cursor is given to us by the API as relative to current viewport top. - - // VT is also 1 based, not 0 based, so correct by 1. - auto& savedCursorState = _savedCursorState.at(_usingAltBuffer); - savedCursorState.Column = coordCursor.X + 1; - savedCursorState.Row = coordCursor.Y + 1; - savedCursorState.Attributes = attributes; - - return true; -} - -// Routine Description: -// - DECRC - Restores a saved "cursor state" from the DECSC command back into -// the console state. This includes the cursor position, origin mode, graphic -// rendition, and active character set. -// Arguments: -// - -// Return Value: -// - True. -bool TerminalDispatch::CursorRestoreState() -{ - // TODO GH#3849: When de-duplicating this, the AdaptDispatch version of this - // is more elaborate. - auto& savedCursorState = _savedCursorState.at(_usingAltBuffer); - - auto row = savedCursorState.Row; - const auto col = savedCursorState.Column; - - // The saved coordinates are always absolute, so we need reset the origin mode temporarily. - CursorPosition(row, col); - - // Restore text attributes. - _terminalApi.SetTextAttributes(savedCursorState.Attributes); - - 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() -{ - 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; - CursorRestoreState(); - return true; -} diff --git a/src/cascadia/TerminalCore/TerminalDispatch.hpp b/src/cascadia/TerminalCore/TerminalDispatch.hpp deleted file mode 100644 index 064a1fce9d1..00000000000 --- a/src/cascadia/TerminalCore/TerminalDispatch.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "../../terminal/adapter/termDispatch.hpp" -#include "ITerminalApi.hpp" - -static constexpr size_t TaskbarMaxState{ 4 }; -static constexpr size_t TaskbarMaxProgress{ 100 }; - -class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatch -{ - using VTInt = Microsoft::Console::VirtualTerminal::VTInt; - -public: - TerminalDispatch(::Microsoft::Terminal::Core::ITerminalApi& terminalApi) noexcept; - - void Print(const wchar_t wchPrintable) override; - void PrintString(const std::wstring_view string) override; - - bool SetGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override; - - bool PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override; - bool PopGraphicsRendition() override; - - bool CursorPosition(const VTInt line, - const VTInt column) override; // CUP - - bool EnableWin32InputMode(const bool win32InputMode) override; // win32-input-mode - - bool CursorVisibility(const bool isVisible) override; // DECTCEM - bool EnableCursorBlinking(const bool enable) override; // ATT610 - - bool CursorForward(const VTInt distance) override; - bool CursorBackward(const VTInt distance) override; - bool CursorUp(const VTInt distance) override; - - bool LineFeed(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::LineFeedType lineFeedType) override; - - bool EraseCharacters(const VTInt numChars) override; - bool WarningBell() override; - 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 VTInt numTabs) override; // CHT, HT - bool BackwardsTab(const VTInt numTabs) override; // CBT - bool TabClear(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TabClearType clearType) override; // TBC - - bool SetColorTableEntry(const size_t tableIndex, const DWORD color) override; - bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) override; - bool SetCursorColor(const DWORD color) override; - - bool SetClipboard(std::wstring_view content) override; - - bool SetDefaultForeground(const DWORD color) override; - bool SetDefaultBackground(const DWORD color) override; - bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override; // ED - bool DeleteCharacter(const VTInt count) override; - bool InsertCharacter(const VTInt count) override; - bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override; - - bool SetCursorKeysMode(const bool applicationMode) override; // DECCKM - bool SetKeypadMode(const bool applicationMode) override; // DECKPAM, DECKPNM - bool SetScreenMode(const bool reverseMode) override; // DECSCNM - - bool SoftReset() override; // DECSTR - bool HardReset() override; // RIS - - // DTTERM_WindowManipulation - bool WindowManipulation(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::WindowManipulationType /*function*/, - const ::Microsoft::Console::VirtualTerminal::VTParameter /*parameter1*/, - const ::Microsoft::Console::VirtualTerminal::VTParameter /*parameter2*/) override; - - bool EnableVT200MouseMode(const bool enabled) override; // ?1000 - bool EnableUTF8ExtendedMouseMode(const bool enabled) override; // ?1005 - bool EnableSGRExtendedMouseMode(const bool enabled) override; // ?1006 - bool EnableButtonEventMouseMode(const bool enabled) override; // ?1002 - bool EnableAnyEventMouseMode(const bool enabled) override; // ?1003 - bool EnableFocusEventMode(const bool enabled) override; // ?1004 - bool EnableAlternateScroll(const bool enabled) override; // ?1007 - bool EnableXtermBracketedPasteMode(const bool enabled) override; // ?2004 - - bool SetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) override; // DECSET - bool ResetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) override; // DECRST - - bool DeviceStatusReport(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::AnsiStatusType /*statusType*/) override; // DSR, DSR-OS, DSR-CPR - - bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) override; - bool EndHyperlink() override; - - bool DoConEmuAction(const std::wstring_view string) override; - - bool CursorSaveState() override; - bool CursorRestoreState() override; - -private: - ::Microsoft::Terminal::Core::ITerminalApi& _terminalApi; - - // Dramatically simplified version of AdaptDispatch::CursorState - struct CursorState - { - unsigned int Row = 1; - unsigned int Column = 1; - TextAttribute Attributes = {}; - }; - - std::vector _tabStopColumns; - bool _initDefaultTabStops = true; - - // We have two instances of the saved cursor state, because we need - // one for the main buffer (at index 0), and another for the alt buffer - // (at index 1). The _usingAltBuffer property keeps tracks of which - // buffer is active, so can be used as an index into this array to - // obtain the saved state that should be currently active. - std::array _savedCursorState; - bool _usingAltBuffer = false; - - size_t _SetRgbColorsHelper(const ::Microsoft::Console::VirtualTerminal::VTParameters options, - TextAttribute& attr, - const bool isForeground); - - bool _WriteResponse(const std::wstring_view reply) const; - bool _ModeParamsHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams param, const bool enable); - - bool _OperatingStatus() const; - bool _CursorPositionReport() const; - - void _ClearSingleTabStop(); - void _ClearAllTabStops(); - void _ResetTabStops(); - void _InitTabStopsForWidth(const size_t width); -}; diff --git a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp b/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp deleted file mode 100644 index aec05b066ff..00000000000 --- a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include "TerminalDispatch.hpp" - -using namespace Microsoft::Console::VirtualTerminal; -using namespace Microsoft::Console::VirtualTerminal::DispatchTypes; - -// Routine Description: -// - Helper to parse extended graphics options, which start with 38 (FG) or 48 (BG) -// These options are followed by either a 2 (RGB) or 5 (xterm index) -// RGB sequences then take 3 MORE params to designate the R, G, B parts of the color -// Xterm index will use the param that follows to use a color from the preset 256 color xterm color table. -// Arguments: -// - options - An array of options that will be used to generate the RGB color -// - attr - The attribute that will be updated with the parsed color. -// - isForeground - Whether or not the parsed color is for the foreground. -// Return Value: -// - The number of options consumed, not including the initial 38/48. -size_t TerminalDispatch::_SetRgbColorsHelper(const VTParameters options, - TextAttribute& attr, - const bool isForeground) -{ - size_t optionsConsumed = 1; - const DispatchTypes::GraphicsOptions typeOpt = options.at(0); - if (typeOpt == DispatchTypes::GraphicsOptions::RGBColorOrFaint) - { - optionsConsumed = 4; - const size_t red = options.at(1).value_or(0); - const size_t green = options.at(2).value_or(0); - const size_t blue = options.at(3).value_or(0); - // ensure that each value fits in a byte - if (red <= 255 && green <= 255 && blue <= 255) - { - const auto rgbColor = RGB(red, green, blue); - attr.SetColor(rgbColor, isForeground); - } - } - else if (typeOpt == DispatchTypes::GraphicsOptions::BlinkOrXterm256Index) - { - optionsConsumed = 2; - const size_t tableIndex = options.at(1).value_or(0); - if (tableIndex <= 255) - { - const auto adjustedIndex = gsl::narrow_cast(tableIndex); - if (isForeground) - { - attr.SetIndexedForeground256(adjustedIndex); - } - else - { - attr.SetIndexedBackground256(adjustedIndex); - } - } - } - return optionsConsumed; -} - -// Routine Description: -// - SGR - Modifies the graphical rendering options applied to the next -// characters written into the buffer. -// - Options include colors, invert, underlines, and other "font style" -// type options. -// Arguments: -// - options - An array of options that will be applied from 0 to N, in order, -// one at a time by setting or removing flags in the font style properties. -// Return Value: -// - True if handled successfully. False otherwise. -bool TerminalDispatch::SetGraphicsRendition(const VTParameters options) -{ - auto attr = _terminalApi.GetTextAttributes(); - - // Run through the graphics options and apply them - for (size_t i = 0; i < options.size(); i++) - { - const GraphicsOptions opt = options.at(i); - switch (opt) - { - case Off: - attr.SetDefaultForeground(); - attr.SetDefaultBackground(); - attr.SetDefaultMetaAttrs(); - break; - case ForegroundDefault: - attr.SetDefaultForeground(); - break; - case BackgroundDefault: - attr.SetDefaultBackground(); - break; - case Intense: - attr.SetIntense(true); - break; - case RGBColorOrFaint: - attr.SetFaint(true); - break; - case NotIntenseOrFaint: - attr.SetIntense(false); - attr.SetFaint(false); - break; - case Italics: - attr.SetItalic(true); - break; - case NotItalics: - attr.SetItalic(false); - break; - case BlinkOrXterm256Index: - case RapidBlink: // We just interpret rapid blink as an alias of blink. - attr.SetBlinking(true); - break; - case Steady: - attr.SetBlinking(false); - break; - case Invisible: - attr.SetInvisible(true); - break; - case Visible: - attr.SetInvisible(false); - break; - case CrossedOut: - attr.SetCrossedOut(true); - break; - case NotCrossedOut: - attr.SetCrossedOut(false); - break; - case Negative: - attr.SetReverseVideo(true); - break; - case Positive: - attr.SetReverseVideo(false); - break; - case Underline: - attr.SetUnderlined(true); - break; - case DoublyUnderlined: - attr.SetDoublyUnderlined(true); - break; - case NoUnderline: - attr.SetUnderlined(false); - attr.SetDoublyUnderlined(false); - break; - case Overline: - attr.SetOverlined(true); - break; - case NoOverline: - attr.SetOverlined(false); - break; - case ForegroundBlack: - attr.SetIndexedForeground(TextColor::DARK_BLACK); - break; - case ForegroundBlue: - attr.SetIndexedForeground(TextColor::DARK_BLUE); - break; - case ForegroundGreen: - attr.SetIndexedForeground(TextColor::DARK_GREEN); - break; - case ForegroundCyan: - attr.SetIndexedForeground(TextColor::DARK_CYAN); - break; - case ForegroundRed: - attr.SetIndexedForeground(TextColor::DARK_RED); - break; - case ForegroundMagenta: - attr.SetIndexedForeground(TextColor::DARK_MAGENTA); - break; - case ForegroundYellow: - attr.SetIndexedForeground(TextColor::DARK_YELLOW); - break; - case ForegroundWhite: - attr.SetIndexedForeground(TextColor::DARK_WHITE); - break; - case BackgroundBlack: - attr.SetIndexedBackground(TextColor::DARK_BLACK); - break; - case BackgroundBlue: - attr.SetIndexedBackground(TextColor::DARK_BLUE); - break; - case BackgroundGreen: - attr.SetIndexedBackground(TextColor::DARK_GREEN); - break; - case BackgroundCyan: - attr.SetIndexedBackground(TextColor::DARK_CYAN); - break; - case BackgroundRed: - attr.SetIndexedBackground(TextColor::DARK_RED); - break; - case BackgroundMagenta: - attr.SetIndexedBackground(TextColor::DARK_MAGENTA); - break; - case BackgroundYellow: - attr.SetIndexedBackground(TextColor::DARK_YELLOW); - break; - case BackgroundWhite: - attr.SetIndexedBackground(TextColor::DARK_WHITE); - break; - case BrightForegroundBlack: - attr.SetIndexedForeground(TextColor::BRIGHT_BLACK); - break; - case BrightForegroundBlue: - attr.SetIndexedForeground(TextColor::BRIGHT_BLUE); - break; - case BrightForegroundGreen: - attr.SetIndexedForeground(TextColor::BRIGHT_GREEN); - break; - case BrightForegroundCyan: - attr.SetIndexedForeground(TextColor::BRIGHT_CYAN); - break; - case BrightForegroundRed: - attr.SetIndexedForeground(TextColor::BRIGHT_RED); - break; - case BrightForegroundMagenta: - attr.SetIndexedForeground(TextColor::BRIGHT_MAGENTA); - break; - case BrightForegroundYellow: - attr.SetIndexedForeground(TextColor::BRIGHT_YELLOW); - break; - case BrightForegroundWhite: - attr.SetIndexedForeground(TextColor::BRIGHT_WHITE); - break; - case BrightBackgroundBlack: - attr.SetIndexedBackground(TextColor::BRIGHT_BLACK); - break; - case BrightBackgroundBlue: - attr.SetIndexedBackground(TextColor::BRIGHT_BLUE); - break; - case BrightBackgroundGreen: - attr.SetIndexedBackground(TextColor::BRIGHT_GREEN); - break; - case BrightBackgroundCyan: - attr.SetIndexedBackground(TextColor::BRIGHT_CYAN); - break; - case BrightBackgroundRed: - attr.SetIndexedBackground(TextColor::BRIGHT_RED); - break; - case BrightBackgroundMagenta: - attr.SetIndexedBackground(TextColor::BRIGHT_MAGENTA); - break; - case BrightBackgroundYellow: - attr.SetIndexedBackground(TextColor::BRIGHT_YELLOW); - break; - case BrightBackgroundWhite: - attr.SetIndexedBackground(TextColor::BRIGHT_WHITE); - break; - case ForegroundExtended: - i += _SetRgbColorsHelper(options.subspan(i + 1), attr, true); - break; - case BackgroundExtended: - i += _SetRgbColorsHelper(options.subspan(i + 1), attr, false); - break; - } - } - - _terminalApi.SetTextAttributes(attr); - return true; -} - -bool TerminalDispatch::PushGraphicsRendition(const VTParameters options) -{ - _terminalApi.PushGraphicsRendition(options); - return true; -} - -bool TerminalDispatch::PopGraphicsRendition() -{ - _terminalApi.PopGraphicsRendition(); - return true; -} diff --git a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj index 7488acf941f..c5d9c969d19 100644 --- a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj +++ b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj @@ -39,6 +39,9 @@ {af0a096a-8b3a-4949-81ef-7df8f0fee91f} + + {dcf55140-ef6a-4736-a403-957e4f7430bb} + {3ae13314-1939-4dfa-9c14-38ca0834050c} diff --git a/src/cascadia/TerminalCore/terminalcore-common.vcxitems b/src/cascadia/TerminalCore/terminalcore-common.vcxitems index 5b777af15c0..7feb43f7d5d 100644 --- a/src/cascadia/TerminalCore/terminalcore-common.vcxitems +++ b/src/cascadia/TerminalCore/terminalcore-common.vcxitems @@ -2,8 +2,6 @@ - - @@ -15,8 +13,6 @@ - - diff --git a/src/cascadia/TerminalCore/terminalrenderdata.cpp b/src/cascadia/TerminalCore/terminalrenderdata.cpp index b2ae0af0991..56b6a058072 100644 --- a/src/cascadia/TerminalCore/terminalrenderdata.cpp +++ b/src/cascadia/TerminalCore/terminalrenderdata.cpp @@ -23,12 +23,12 @@ COORD Terminal::GetTextBufferEndPosition() const noexcept return endPosition; } -const TextBuffer& Terminal::GetTextBuffer() noexcept +const TextBuffer& Terminal::GetTextBuffer() const noexcept { return _activeBuffer(); } -const FontInfo& Terminal::GetFontInfo() noexcept +const FontInfo& Terminal::GetFontInfo() const noexcept { return _fontInfo; } diff --git a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp index c9035f91d9b..60d8a725153 100644 --- a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp @@ -238,7 +238,7 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final std::deque expectedOutput; std::unique_ptr m_state; - std::unique_ptr _pConApi; + std::unique_ptr _pConApi; // Tests can set these variables how they link to configure the behavior of the test harness. bool _checkConptyOutput{ true }; // If true, the test class will check that the output from conpty was expected diff --git a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp index 291185203ed..7b458aa06a7 100644 --- a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp @@ -394,7 +394,7 @@ namespace TerminalCoreUnitTests const auto burrito = L"\xD83C\xDF2F"; // Insert wide glyph at position (4,10) - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(burrito); // Simulate click at (x,y) = (5,10) @@ -417,7 +417,7 @@ namespace TerminalCoreUnitTests const auto burrito = L"\xD83C\xDF2F"; // Insert wide glyph at position (4,10) - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(burrito); // Simulate click at (x,y) = (5,10) @@ -440,11 +440,11 @@ namespace TerminalCoreUnitTests const auto burrito = L"\xD83C\xDF2F"; // Insert wide glyph at position (4,10) - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(burrito); // Insert wide glyph at position (7,11) - term.SetCursorPosition({ 7, 11 }); + term.GetTextBuffer().GetCursor().SetPosition({ 7, 11 }); term.Write(burrito); // Simulate ALT + click at (x,y) = (5,8) @@ -496,7 +496,7 @@ namespace TerminalCoreUnitTests // Insert text at position (4,10) const std::wstring_view text = L"doubleClickMe"; - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(text); // Simulate double click at (x,y) = (5,10) @@ -540,7 +540,7 @@ namespace TerminalCoreUnitTests // Insert text at position (4,10) const std::wstring_view text = L"C:\\Terminal>"; - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(text); // Simulate click at (x,y) = (15,10) @@ -568,7 +568,7 @@ namespace TerminalCoreUnitTests // Insert text at position (4,10) const std::wstring_view text = L"doubleClickMe dragThroughHere"; - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(text); // Simulate double click at (x,y) = (5,10) @@ -597,7 +597,7 @@ namespace TerminalCoreUnitTests // Insert text at position (21,10) const std::wstring_view text = L"doubleClickMe dragThroughHere"; - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(text); // Simulate double click at (x,y) = (21,10) @@ -685,7 +685,7 @@ namespace TerminalCoreUnitTests // Insert text at position (4,10) const std::wstring_view text = L"doubleClickMe dragThroughHere"; - term.SetCursorPosition({ 4, 10 }); + term.GetTextBuffer().GetCursor().SetPosition({ 4, 10 }); term.Write(text); // Step 1: Create a selection on "doubleClickMe" diff --git a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp index f6d736781c8..384be1034eb 100644 --- a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp @@ -55,11 +55,11 @@ void TerminalApiTest::SetColorTableEntry() auto settings = winrt::make(100, 100, 100); term.UpdateSettings(settings); - VERIFY_NO_THROW(term.SetColorTableEntry(0, 100)); - VERIFY_NO_THROW(term.SetColorTableEntry(128, 100)); - VERIFY_NO_THROW(term.SetColorTableEntry(255, 100)); + VERIFY_NO_THROW(term._renderSettings.SetColorTableEntry(0, 100)); + VERIFY_NO_THROW(term._renderSettings.SetColorTableEntry(128, 100)); + VERIFY_NO_THROW(term._renderSettings.SetColorTableEntry(255, 100)); - VERIFY_THROWS(term.SetColorTableEntry(512, 100), std::exception); + VERIFY_THROWS(term._renderSettings.SetColorTableEntry(512, 100), std::exception); } // Terminal::_WriteBuffer used to enter infinite loops under certain conditions. @@ -152,7 +152,7 @@ void TerminalApiTest::CursorVisibility() VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsOn()); VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsBlinkingAllowed()); - term.SetCursorVisibility(false); + term.GetTextBuffer().GetCursor().SetIsVisible(false); VERIFY_IS_FALSE(term._mainBuffer->GetCursor().IsVisible()); VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsOn()); VERIFY_IS_TRUE(term._mainBuffer->GetCursor().IsBlinkingAllowed()); @@ -242,19 +242,19 @@ void TerminalApiTest::CheckDoubleWidthCursor() stateMachine.ProcessString(doubleWidthText); // The last 'A' - term.SetCursorPosition({ 97, 0 }); + cursor.SetPosition({ 97, 0 }); VERIFY_IS_FALSE(term.IsCursorDoubleWidth()); // This and the next CursorPos are taken up by '我‘ - term.SetCursorPosition({ 98, 0 }); + cursor.SetPosition({ 98, 0 }); VERIFY_IS_TRUE(term.IsCursorDoubleWidth()); - term.SetCursorPosition({ 99, 0 }); + cursor.SetPosition({ 99, 0 }); VERIFY_IS_TRUE(term.IsCursorDoubleWidth()); // This and the next CursorPos are taken up by ’愛‘ - term.SetCursorPosition({ 0, 1 }); + cursor.SetPosition({ 0, 1 }); VERIFY_IS_TRUE(term.IsCursorDoubleWidth()); - term.SetCursorPosition({ 1, 1 }); + cursor.SetPosition({ 1, 1 }); VERIFY_IS_TRUE(term.IsCursorDoubleWidth()); } diff --git a/src/host/PtySignalInputThread.cpp b/src/host/PtySignalInputThread.cpp index 2f39e80e398..9f3bd98c2cc 100644 --- a/src/host/PtySignalInputThread.cpp +++ b/src/host/PtySignalInputThread.cpp @@ -20,12 +20,11 @@ using namespace Microsoft::Console::VirtualTerminal; PtySignalInputThread::PtySignalInputThread(wil::unique_hfile hPipe) : _hFile{ std::move(hPipe) }, _hThread{}, - _pConApi{ std::make_unique(ServiceLocator::LocateGlobals().getConsoleInformation()) }, + _api{ ServiceLocator::LocateGlobals().getConsoleInformation() }, _dwThreadId{ 0 }, _consoleConnected{ false } { THROW_HR_IF(E_HANDLE, _hFile.get() == INVALID_HANDLE_VALUE); - THROW_HR_IF_NULL(E_INVALIDARG, _pConApi.get()); } PtySignalInputThread::~PtySignalInputThread() @@ -199,7 +198,7 @@ void PtySignalInputThread::ConnectConsole() noexcept // - void PtySignalInputThread::_DoResizeWindow(const ResizeWindowData& data) { - if (_pConApi->ResizeWindow(data.sx, data.sy)) + if (_api.ResizeWindow(data.sx, data.sy)) { auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); THROW_IF_FAILED(gci.GetVtIo()->SuppressResizeRepaint()); @@ -214,7 +213,7 @@ void PtySignalInputThread::_DoClearBuffer() void PtySignalInputThread::_DoShowHide(const bool show) { - _pConApi->ShowWindow(show); + _api.ShowWindow(show); } // Method Description: @@ -228,7 +227,16 @@ void PtySignalInputThread::_DoShowHide(const bool show) // - void PtySignalInputThread::_DoSetWindowParent(const SetParentData& data) { - _pConApi->ReparentWindow(data.handle); + // This will initialize s_interactivityFactory for us. It will also + // conveniently return 0 when we're on OneCore. + // + // If the window hasn't been created yet, by some other call to + // LocatePseudoWindow, then this will also initialize the owner of the + // window. + if (const auto pseudoHwnd{ ServiceLocator::LocatePseudoWindow(reinterpret_cast(data.handle)) }) + { + LOG_LAST_ERROR_IF_NULL(::SetParent(pseudoHwnd, reinterpret_cast(data.handle))); + } } // Method Description: diff --git a/src/host/PtySignalInputThread.hpp b/src/host/PtySignalInputThread.hpp index 4de50e53e9a..1ac12f44f33 100644 --- a/src/host/PtySignalInputThread.hpp +++ b/src/host/PtySignalInputThread.hpp @@ -15,10 +15,7 @@ Author(s): --*/ #pragma once -namespace Microsoft::Console::VirtualTerminal -{ - class ConGetSet; -} +#include "outputStream.hpp" namespace Microsoft::Console { @@ -76,7 +73,7 @@ namespace Microsoft::Console bool _consoleConnected; std::optional _earlyResize; std::optional _initialShowHide; - std::unique_ptr _pConApi; + ConhostInternalGetSet _api; public: std::optional _earlyReparent; diff --git a/src/host/VtInputThread.cpp b/src/host/VtInputThread.cpp index ad6d86be861..8706ff6f87a 100644 --- a/src/host/VtInputThread.cpp +++ b/src/host/VtInputThread.cpp @@ -8,7 +8,6 @@ #include "../interactivity/inc/ServiceLocator.hpp" #include "input.h" #include "../terminal/parser/InputStateMachineEngine.hpp" -#include "outputStream.hpp" // For ConhostInternalGetSet #include "../terminal/adapter/InteractDispatch.hpp" #include "../types/inc/convert.hpp" #include "server.h" @@ -36,11 +35,7 @@ VtInputThread::VtInputThread(_In_ wil::unique_hfile hPipe, { THROW_HR_IF(E_HANDLE, _hFile.get() == INVALID_HANDLE_VALUE); - auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); - - auto pGetSet = std::make_unique(gci); - - auto dispatch = std::make_unique(std::move(pGetSet)); + auto dispatch = std::make_unique(); auto engine = std::make_unique(std::move(dispatch), inheritCursor); diff --git a/src/host/outputStream.cpp b/src/host/outputStream.cpp index f19e1c13ea5..4074139d3a2 100644 --- a/src/host/outputStream.cpp +++ b/src/host/outputStream.cpp @@ -15,8 +15,8 @@ #pragma hdrstop using namespace Microsoft::Console; +using namespace Microsoft::Console::VirtualTerminal; using Microsoft::Console::Interactivity::ServiceLocator; -using Microsoft::Console::VirtualTerminal::StateMachine; ConhostInternalGetSet::ConhostInternalGetSet(_In_ IIoProvider& io) : _io{ io } @@ -56,6 +56,36 @@ void ConhostInternalGetSet::PrintString(const std::wstring_view string) THROW_IF_NTSTATUS_FAILED(ntstatus); } +// - Sends a string response to the input stream of the console. +// - Used by various commands where the program attached would like a reply to one of the commands issued. +// - This will generate two "key presses" (one down, one up) for every character in the string and place them into the head of the console's input stream. +// Arguments: +// - response - The response string to transmit back to the input stream +// Return Value: +// - +void ConhostInternalGetSet::ReturnResponse(const std::wstring_view response) +{ + std::deque> inEvents; + + // generate a paired key down and key up event for every + // character to be sent into the console's input buffer + for (const auto& wch : response) + { + // This wasn't from a real keyboard, so we're leaving key/scan codes blank. + KeyEvent keyEvent{ TRUE, 1, 0, 0, wch, 0 }; + + inEvents.push_back(std::make_unique(keyEvent)); + keyEvent.SetKeyDown(false); + inEvents.push_back(std::make_unique(keyEvent)); + } + + // TODO GH#4954 During the input refactor we may want to add a "priority" input list + // to make sure that "response" input is spooled directly into the application. + // We switched this to an append (vs. a prepend) to fix GH#1637, a bug where two CPR + // could collide with each other. + _io.GetActiveInputBuffer()->Write(inEvents); +} + // Routine Description: // - Retrieves the state machine for the active output buffer. // Arguments: @@ -115,19 +145,6 @@ void ConhostInternalGetSet::SetTextAttributes(const TextAttribute& attrs) _io.GetActiveOutputBuffer().SetAttributes(attrs); } -// Routine Description: -// - Writes events to the input buffer already formed into IInputEvents -// Arguments: -// - events - the input events to be copied into the head of the input -// buffer for the underlying attached process -// - eventsWritten - on output, the number of events written -// Return Value: -// - -void ConhostInternalGetSet::WriteInput(std::deque>& events, size_t& eventsWritten) -{ - eventsWritten = _io.GetActiveInputBuffer()->Write(events); -} - // Routine Description: // - Sets the ENABLE_WRAP_AT_EOL_OUTPUT mode. This controls whether the cursor moves // to the beginning of the next row when it reaches the end of the current row. @@ -293,6 +310,51 @@ unsigned int ConhostInternalGetSet::GetConsoleOutputCP() const return ServiceLocator::LocateGlobals().getConsoleInformation().OutputCP; } +// Routine Description: +// - Sets the XTerm bracketed paste mode. This controls whether pasted content is +// bracketed with control sequences to differentiate it from typed text. +// Arguments: +// - enable - set to true to enable bracketing, false to disable. +// Return Value: +// - +void ConhostInternalGetSet::EnableXtermBracketedPasteMode(const bool /*enabled*/) +{ + // TODO +} + +// Routine Description: +// - Copies the given content to the clipboard. +// Arguments: +// - content - the text to be copied. +// Return Value: +// - +void ConhostInternalGetSet::CopyToClipboard(const std::wstring_view /*content*/) +{ + // TODO +} + +// Routine Description: +// - Updates the taskbar progress indicator. +// Arguments: +// - state: indicates the progress state +// - progress: indicates the progress value +// Return Value: +// - +void ConhostInternalGetSet::SetTaskbarProgress(const DispatchTypes::TaskbarState /*state*/, const size_t /*progress*/) +{ + // TODO +} + +// Routine Description: +// - Set the active working directory. Not used in conhost. +// Arguments: +// - content - the text to be copied. +// Return Value: +// - +void ConhostInternalGetSet::SetWorkingDirectory(const std::wstring_view /*uri*/) +{ +} + // Routine Description: // - Resizes the window to the specified dimensions, in characters. // Arguments: @@ -392,17 +454,3 @@ void ConhostInternalGetSet::NotifyAccessibilityChange(const til::rect& changedRe gsl::narrow_cast(changedRect.bottom - 1)); } } - -void ConhostInternalGetSet::ReparentWindow(const uint64_t handle) -{ - // This will initialize s_interactivityFactory for us. It will also - // conveniently return 0 when we're on OneCore. - // - // If the window hasn't been created yet, by some other call to - // LocatePseudoWindow, then this will also initialize the owner of the - // window. - if (const auto pseudoHwnd{ ServiceLocator::LocatePseudoWindow(reinterpret_cast(handle)) }) - { - LOG_LAST_ERROR_IF_NULL(::SetParent(pseudoHwnd, reinterpret_cast(handle))); - } -} diff --git a/src/host/outputStream.hpp b/src/host/outputStream.hpp index 65f2fde5643..79316f78ea5 100644 --- a/src/host/outputStream.hpp +++ b/src/host/outputStream.hpp @@ -14,7 +14,7 @@ Module Name: #pragma once -#include "../terminal/adapter/conGetSet.hpp" +#include "../terminal/adapter/ITerminalApi.hpp" #include "../types/inc/IInputEvent.hpp" #include "../inc/conattrs.hpp" #include "IIoProvider.hpp" @@ -24,12 +24,13 @@ Module Name: // the kernelbase/32 exposed public APIs and routed by the console driver (condrv) to this console host. // But since we're trying to call them from *inside* the console host itself, we need to get in the way and route them straight to the // v-table inside this process instance. -class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::ConGetSet +class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::ITerminalApi { public: ConhostInternalGetSet(_In_ Microsoft::Console::IIoProvider& io); void PrintString(const std::wstring_view string) override; + void ReturnResponse(const std::wstring_view response) override; Microsoft::Console::VirtualTerminal::StateMachine& GetStateMachine() override; TextBuffer& GetTextBuffer() override; @@ -38,8 +39,6 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal:: void SetTextAttributes(const TextAttribute& attrs) override; - void WriteInput(std::deque>& events, size_t& eventsWritten) override; - void SetAutoWrapMode(const bool wrapAtEOL) override; void SetScrollingRegion(const til::inclusive_rect& scrollMargins) override; @@ -64,13 +63,16 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal:: void SetConsoleOutputCP(const unsigned int codepage) override; unsigned int GetConsoleOutputCP() const override; + void EnableXtermBracketedPasteMode(const bool enabled) override; + void CopyToClipboard(const std::wstring_view content) override; + void SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) override; + void SetWorkingDirectory(const std::wstring_view uri) override; + bool IsConsolePty() const override; bool IsVtInputEnabled() const override; void NotifyAccessibilityChange(const til::rect& changedRect) override; - void ReparentWindow(const uint64_t handle); - private: Microsoft::Console::IIoProvider& _io; }; diff --git a/src/host/renderData.cpp b/src/host/renderData.cpp index 381198bd039..bb7f7135720 100644 --- a/src/host/renderData.cpp +++ b/src/host/renderData.cpp @@ -44,7 +44,7 @@ COORD RenderData::GetTextBufferEndPosition() const noexcept // the appropriate windowing. // Return Value: // - Text buffer with cell information for display -const TextBuffer& RenderData::GetTextBuffer() noexcept +const TextBuffer& RenderData::GetTextBuffer() const noexcept { const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); return gci.GetActiveOutputBuffer().GetTextBuffer(); @@ -54,7 +54,7 @@ const TextBuffer& RenderData::GetTextBuffer() noexcept // - Describes which font should be used for presenting text // Return Value: // - Font description structure -const FontInfo& RenderData::GetFontInfo() noexcept +const FontInfo& RenderData::GetFontInfo() const noexcept { const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); return gci.GetActiveOutputBuffer().GetCurrentFont(); diff --git a/src/host/renderData.hpp b/src/host/renderData.hpp index 7958bc5bf21..bdceed55f8a 100644 --- a/src/host/renderData.hpp +++ b/src/host/renderData.hpp @@ -26,8 +26,8 @@ class RenderData final : #pragma region BaseData Microsoft::Console::Types::Viewport GetViewport() noexcept override; COORD GetTextBufferEndPosition() const noexcept override; - const TextBuffer& GetTextBuffer() noexcept override; - const FontInfo& GetFontInfo() noexcept override; + const TextBuffer& GetTextBuffer() const noexcept override; + const FontInfo& GetFontInfo() const noexcept override; std::vector GetSelectionRects() noexcept override; diff --git a/src/host/screenInfo.cpp b/src/host/screenInfo.cpp index 2c5f2f4c9b3..e4130641172 100644 --- a/src/host/screenInfo.cpp +++ b/src/host/screenInfo.cpp @@ -46,6 +46,7 @@ SCREEN_INFORMATION::SCREEN_INFORMATION( ScrollScale{ 1ul }, _pConsoleWindowMetrics{ pMetrics }, _pAccessibilityNotifier{ pNotifier }, + _api{ *this }, _stateMachine{ nullptr }, _scrollMargins{ Viewport::FromCoord({ 0 }) }, _viewport(Viewport::Empty()), @@ -259,8 +260,7 @@ void SCREEN_INFORMATION::s_RemoveScreenBuffer(_In_ SCREEN_INFORMATION* const pSc auto& renderer = *g.pRender; auto& renderSettings = gci.GetRenderSettings(); auto& terminalInput = gci.GetActiveInputBuffer()->GetTerminalInput(); - auto getset = std::make_unique(*this); - auto adapter = std::make_unique(std::move(getset), renderer, renderSettings, terminalInput); + auto adapter = std::make_unique(_api, renderer, renderSettings, terminalInput); auto engine = std::make_unique(std::move(adapter)); // Note that at this point in the setup, we haven't determined if we're // in VtIo mode or not yet. We'll set the OutputStateMachine's diff --git a/src/host/screenInfo.hpp b/src/host/screenInfo.hpp index 0042c55b530..a9d344a3a4f 100644 --- a/src/host/screenInfo.hpp +++ b/src/host/screenInfo.hpp @@ -266,6 +266,8 @@ class SCREEN_INFORMATION : public ConsoleObjectHeader, public Microsoft::Console bool _IsInPtyMode() const; bool _IsInVTMode() const; + ConhostInternalGetSet _api; + std::shared_ptr _stateMachine; Microsoft::Console::Types::Viewport _scrollMargins; //The margins of the VT specified scroll region. Left and Right are currently unused, but could be in the future. diff --git a/src/host/ut_host/ScreenBufferTests.cpp b/src/host/ut_host/ScreenBufferTests.cpp index 030e8f46d8a..27c887d699c 100644 --- a/src/host/ut_host/ScreenBufferTests.cpp +++ b/src/host/ut_host/ScreenBufferTests.cpp @@ -2707,8 +2707,7 @@ void ScreenBufferTests::BackspaceDefaultAttrsInPrompt() stateMachine.ProcessString(L"\x1b[2D"); stateMachine.ProcessString(L"\x1b[P"); - COORD expectedCursor{ 1, 1 }; // We're expecting y=1, because the 2J above - // should have moved the viewport down a line. + COORD expectedCursor{ 1, 0 }; VERIFY_ARE_EQUAL(expectedCursor, cursor.GetPosition()); const std::vector attrs{ attrRow->begin(), attrRow->end() }; diff --git a/src/host/ut_host/VtIoTests.cpp b/src/host/ut_host/VtIoTests.cpp index 8946990d978..dc464dc1fc0 100644 --- a/src/host/ut_host/VtIoTests.cpp +++ b/src/host/ut_host/VtIoTests.cpp @@ -267,12 +267,12 @@ class MockRenderData : public IRenderData, IUiaData return COORD{}; } - const TextBuffer& GetTextBuffer() noexcept override + const TextBuffer& GetTextBuffer() const noexcept override { FAIL_FAST_HR(E_NOTIMPL); } - const FontInfo& GetFontInfo() noexcept override + const FontInfo& GetFontInfo() const noexcept override { FAIL_FAST_HR(E_NOTIMPL); } diff --git a/src/renderer/base/renderer.cpp b/src/renderer/base/renderer.cpp index e1e1195d316..73991da11e9 100644 --- a/src/renderer/base/renderer.cpp +++ b/src/renderer/base/renderer.cpp @@ -298,10 +298,10 @@ void Renderer::TriggerRedrawCursor(const COORD* const pcoord) // - Called when something that changes the output state has occurred and the entire frame is now potentially invalid. // - NOTE: Use sparingly. Try to reduce the refresh region where possible. Only use when a global state change has occurred. // Arguments: -// - +// - backgroundChanged - Set to true if the background color has changed. // Return Value: // - -void Renderer::TriggerRedrawAll() +void Renderer::TriggerRedrawAll(const bool backgroundChanged) { FOREACH_ENGINE(pEngine) { @@ -309,6 +309,11 @@ void Renderer::TriggerRedrawAll() } NotifyPaintFrame(); + + if (backgroundChanged && _pfnBackgroundColorChanged) + { + _pfnBackgroundColorChanged(); + } } // Method Description: @@ -1332,6 +1337,17 @@ void Renderer::AddRenderEngine(_In_ IRenderEngine* const pEngine) THROW_HR_MSG(E_UNEXPECTED, "engines array is full"); } +// Method Description: +// - Registers a callback for when the background color is changed +// Arguments: +// - pfn: the callback +// Return Value: +// - +void Renderer::SetBackgroundColorChangedCallback(std::function pfn) +{ + _pfnBackgroundColorChanged = std::move(pfn); +} + // Method Description: // - Registers a callback that will be called when this renderer gives up. // An application consuming a renderer can use this to display auxiliary Retry UI diff --git a/src/renderer/base/renderer.hpp b/src/renderer/base/renderer.hpp index 1d7bb8b6856..ff9bcebd943 100644 --- a/src/renderer/base/renderer.hpp +++ b/src/renderer/base/renderer.hpp @@ -52,7 +52,7 @@ namespace Microsoft::Console::Render void TriggerRedraw(const Microsoft::Console::Types::Viewport& region); void TriggerRedraw(const COORD* const pcoord); void TriggerRedrawCursor(const COORD* const pcoord); - void TriggerRedrawAll(); + void TriggerRedrawAll(const bool backgroundChanged = false); void TriggerTeardown() noexcept; void TriggerSelection(); @@ -84,6 +84,7 @@ namespace Microsoft::Console::Render void AddRenderEngine(_In_ IRenderEngine* const pEngine); + void SetBackgroundColorChangedCallback(std::function pfn); void SetRendererEnteredErrorStateCallback(std::function pfn); void ResetErrorStateAndResume(); @@ -121,6 +122,7 @@ namespace Microsoft::Console::Render Microsoft::Console::Types::Viewport _viewport; std::vector _clusterBuffer; std::vector _previousSelection; + std::function _pfnBackgroundColorChanged; std::function _pfnRendererEnteredErrorState; bool _destructing = false; bool _forceUpdateViewport = true; diff --git a/src/terminal/adapter/conGetSet.hpp b/src/terminal/adapter/ITerminalApi.hpp similarity index 67% rename from src/terminal/adapter/conGetSet.hpp rename to src/terminal/adapter/ITerminalApi.hpp index 2b1cee923c9..c2f0d7f71e9 100644 --- a/src/terminal/adapter/conGetSet.hpp +++ b/src/terminal/adapter/ITerminalApi.hpp @@ -3,11 +3,10 @@ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: -- conGetSet.hpp +- ITerminalApi.hpp Abstract: -- This serves as an abstraction layer for the adapters to connect to the console API functions. -- The abstraction allows for the substitution of the functions for internal/external to Conhost.exe use as well as easy testing. +- This serves as an abstraction layer for the dispatch class to connect to conhost/terminal API functions. Author(s): - Michael Niksa (MiNiksa) 30-July-2015 @@ -20,21 +19,26 @@ Author(s): #include "../../buffer/out/LineRendition.hpp" #include "../../buffer/out/textBuffer.hpp" #include "../../renderer/inc/RenderSettings.hpp" -#include "../../inc/conattrs.hpp" #include #include namespace Microsoft::Console::VirtualTerminal { - class ConGetSet + class ITerminalApi { using RenderSettings = Microsoft::Console::Render::RenderSettings; public: - virtual ~ConGetSet() = default; + virtual ~ITerminalApi() = default; + ITerminalApi() = default; + ITerminalApi(const ITerminalApi&) = delete; + ITerminalApi(ITerminalApi&&) = delete; + ITerminalApi& operator=(const ITerminalApi&) = delete; + ITerminalApi& operator=(ITerminalApi&&) = delete; virtual void PrintString(const std::wstring_view string) = 0; + virtual void ReturnResponse(const std::wstring_view response) = 0; virtual StateMachine& GetStateMachine() = 0; virtual TextBuffer& GetTextBuffer() = 0; @@ -45,8 +49,6 @@ namespace Microsoft::Console::VirtualTerminal virtual void SetTextAttributes(const TextAttribute& attrs) = 0; - virtual void WriteInput(std::deque>& events, size_t& eventsWritten) = 0; - virtual void SetAutoWrapMode(const bool wrapAtEOL) = 0; virtual void SetScrollingRegion(const til::inclusive_rect& scrollMargins) = 0; @@ -64,11 +66,14 @@ namespace Microsoft::Console::VirtualTerminal virtual void SetConsoleOutputCP(const unsigned int codepage) = 0; virtual unsigned int GetConsoleOutputCP() const = 0; + virtual void EnableXtermBracketedPasteMode(const bool enabled) = 0; + virtual void CopyToClipboard(const std::wstring_view content) = 0; + virtual void SetTaskbarProgress(const DispatchTypes::TaskbarState state, const size_t progress) = 0; + virtual void SetWorkingDirectory(const std::wstring_view uri) = 0; + virtual bool ResizeWindow(const size_t width, const size_t height) = 0; virtual bool IsConsolePty() const = 0; virtual void NotifyAccessibilityChange(const til::rect& changedRect) = 0; - - virtual void ReparentWindow(const uint64_t handle) = 0; }; } diff --git a/src/terminal/adapter/InteractDispatch.cpp b/src/terminal/adapter/InteractDispatch.cpp index 1c4cb2f5bcb..6c205d3508b 100644 --- a/src/terminal/adapter/InteractDispatch.cpp +++ b/src/terminal/adapter/InteractDispatch.cpp @@ -10,7 +10,6 @@ #pragma warning(disable : 26455) #include "InteractDispatch.hpp" -#include "conGetSet.hpp" #include "../../host/conddkrefs.h" #include "../../interactivity/inc/ServiceLocator.hpp" #include "../../interactivity/inc/EventSynthesis.hpp" @@ -21,11 +20,9 @@ using namespace Microsoft::Console::Interactivity; using namespace Microsoft::Console::Types; using namespace Microsoft::Console::VirtualTerminal; -// takes ownership of pConApi -InteractDispatch::InteractDispatch(std::unique_ptr pConApi) : - _pConApi(std::move(pConApi)) +InteractDispatch::InteractDispatch() : + _api{ ServiceLocator::LocateGlobals().getConsoleInformation() } { - THROW_HR_IF_NULL(E_INVALIDARG, _pConApi.get()); } // Method Description: @@ -40,8 +37,8 @@ InteractDispatch::InteractDispatch(std::unique_ptr pConApi) : // - True. bool InteractDispatch::WriteInput(std::deque>& inputEvents) { - size_t written = 0; - _pConApi->WriteInput(inputEvents, written); + const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); + gci.GetActiveInputBuffer()->Write(inputEvents); return true; } @@ -71,7 +68,7 @@ bool InteractDispatch::WriteString(const std::wstring_view string) { if (!string.empty()) { - const auto codepage = _pConApi->GetConsoleOutputCP(); + const auto codepage = _api.GetConsoleOutputCP(); std::deque> keyEvents; for (const auto& wch : string) @@ -110,18 +107,18 @@ bool InteractDispatch::WindowManipulation(const DispatchTypes::WindowManipulatio switch (function) { case DispatchTypes::WindowManipulationType::DeIconifyWindow: - _pConApi->ShowWindow(true); + _api.ShowWindow(true); return true; case DispatchTypes::WindowManipulationType::IconifyWindow: - _pConApi->ShowWindow(false); + _api.ShowWindow(false); return true; case DispatchTypes::WindowManipulationType::RefreshWindow: - _pConApi->GetTextBuffer().TriggerRedrawAll(); + _api.GetTextBuffer().TriggerRedrawAll(); return true; case DispatchTypes::WindowManipulationType::ResizeWindowInCharacters: // TODO:GH#1765 We should introduce a better `ResizeConpty` function to - // the ConGetSet interface, that specifically handles a conpty resize. - if (_pConApi->ResizeWindow(parameter2.value_or(0), parameter1.value_or(0))) + // ConhostInternalGetSet, that specifically handles a conpty resize. + if (_api.ResizeWindow(parameter2.value_or(0), parameter1.value_or(0))) { auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); THROW_IF_FAILED(gci.GetVtIo()->SuppressResizeRepaint()); @@ -143,7 +140,7 @@ bool InteractDispatch::WindowManipulation(const DispatchTypes::WindowManipulatio bool InteractDispatch::MoveCursor(const VTInt row, const VTInt col) { // First retrieve some information about the buffer - const auto viewport = _pConApi->GetViewport(); + const auto viewport = _api.GetViewport(); // In VT, the origin is 1,1. For our array, it's 0,0. So subtract 1. // Apply boundary tests to ensure the cursor isn't outside the viewport rectangle. @@ -158,7 +155,7 @@ bool InteractDispatch::MoveCursor(const VTInt row, const VTInt col) RETURN_IF_FAILED(gci.GetVtIo()->SetCursorPosition(coordCursorShort)); // Finally, attempt to set the adjusted cursor position back into the console. - auto& cursor = _pConApi->GetTextBuffer().GetCursor(); + auto& cursor = _api.GetTextBuffer().GetCursor(); cursor.SetPosition(coordCursorShort); cursor.SetHasMoved(true); return true; @@ -172,7 +169,7 @@ bool InteractDispatch::MoveCursor(const VTInt row, const VTInt col) // - true if enabled (see IsInVirtualTerminalInputMode). false otherwise. bool InteractDispatch::IsVtInputEnabled() const { - return _pConApi->IsVtInputEnabled(); + return _api.IsVtInputEnabled(); } // Method Description: diff --git a/src/terminal/adapter/InteractDispatch.hpp b/src/terminal/adapter/InteractDispatch.hpp index 704e51dd1c9..8fd34868211 100644 --- a/src/terminal/adapter/InteractDispatch.hpp +++ b/src/terminal/adapter/InteractDispatch.hpp @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: -- adaptDispatch.hpp +- InteractDispatch.hpp Abstract: - This serves as the Windows Console API-specific implementation of the @@ -16,14 +16,14 @@ Author(s): #include "DispatchTypes.hpp" #include "IInteractDispatch.hpp" -#include "conGetSet.hpp" +#include "../../host/outputStream.hpp" namespace Microsoft::Console::VirtualTerminal { class InteractDispatch : public IInteractDispatch { public: - InteractDispatch(std::unique_ptr pConApi); + InteractDispatch(); bool WriteInput(std::deque>& inputEvents) override; bool WriteCtrlKey(const KeyEvent& event) override; @@ -38,6 +38,6 @@ namespace Microsoft::Console::VirtualTerminal bool FocusChanged(const bool focused) const override; private: - std::unique_ptr _pConApi; + ConhostInternalGetSet _api; }; } diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index 4b493a1f21f..2dca06ebe4b 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -4,7 +4,6 @@ #include "precomp.h" #include "adaptDispatch.hpp" -#include "conGetSet.hpp" #include "../../renderer/base/renderer.hpp" #include "../../types/inc/Viewport.hpp" #include "../../types/inc/utils.hpp" @@ -15,20 +14,8 @@ using namespace Microsoft::Console::Types; using namespace Microsoft::Console::Render; using namespace Microsoft::Console::VirtualTerminal; -// Routine Description: -// - No Operation helper. It's just here to make sure they're always all the same. -// Arguments: -// - -// Return Value: -// - Always false to signify we didn't handle it. -bool NoOp() noexcept -{ - return false; -} - -// Note: AdaptDispatch will take ownership of pConApi and pDefaults -AdaptDispatch::AdaptDispatch(std::unique_ptr pConApi, Renderer& renderer, RenderSettings& renderSettings, TerminalInput& terminalInput) : - _pConApi{ std::move(pConApi) }, +AdaptDispatch::AdaptDispatch(ITerminalApi& api, Renderer& renderer, RenderSettings& renderSettings, TerminalInput& terminalInput) : + _api{ api }, _renderer{ renderer }, _renderSettings{ renderSettings }, _terminalInput{ terminalInput }, @@ -37,7 +24,6 @@ AdaptDispatch::AdaptDispatch(std::unique_ptr pConApi, Renderer& rende _isDECCOLMAllowed(false), // by default, DECCOLM is not allowed. _termOutput() { - THROW_HR_IF_NULL(E_INVALIDARG, _pConApi.get()); _scrollMargins = { 0 }; // initially, there are no scroll margins. } @@ -56,7 +42,7 @@ void AdaptDispatch::Print(const wchar_t wchPrintable) // a character is only output if the DEL is translated to something else. if (wchTranslated != AsciiChars::DEL) { - _pConApi->PrintString({ &wchTranslated, 1 }); + _api.PrintString({ &wchTranslated, 1 }); } } @@ -77,11 +63,11 @@ void AdaptDispatch::PrintString(const std::wstring_view string) { buffer.push_back(_termOutput.TranslateKey(wch)); } - _pConApi->PrintString(buffer); + _api.PrintString(buffer); } else { - _pConApi->PrintString(string); + _api.PrintString(string); } } @@ -177,7 +163,7 @@ std::pair AdaptDispatch::_GetVerticalMargins(const til::rect& viewport if (_scrollMargins.Top >= bottommostRow) { _scrollMargins.Top = _scrollMargins.Bottom = 0; - _pConApi->SetScrollingRegion(_scrollMargins); + _api.SetScrollingRegion(_scrollMargins); } // If margins aren't set, use the full extent of the viewport. const auto marginsSet = _scrollMargins.Top < _scrollMargins.Bottom; @@ -204,8 +190,8 @@ std::pair AdaptDispatch::_GetVerticalMargins(const til::rect& viewport bool AdaptDispatch::_CursorMovePosition(const Offset rowOffset, const Offset colOffset, const bool clampInMargins) { // First retrieve some information about the buffer - const auto viewport = _pConApi->GetViewport(); - auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + auto& textBuffer = _api.GetTextBuffer(); auto& cursor = textBuffer.GetCursor(); const auto cursorPosition = cursor.GetPosition(); const auto [topMargin, bottomMargin] = _GetVerticalMargins(viewport, true); @@ -352,8 +338,8 @@ bool AdaptDispatch::CursorPosition(const VTInt line, const VTInt column) bool AdaptDispatch::CursorSaveState() { // First retrieve some information about the buffer - const auto viewport = _pConApi->GetViewport(); - const auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + const auto& textBuffer = _api.GetTextBuffer(); const auto attributes = textBuffer.GetCurrentAttributes(); // The cursor is given to us by the API as relative to the whole buffer. @@ -369,7 +355,7 @@ bool AdaptDispatch::CursorSaveState() savedCursorState.Attributes = attributes; savedCursorState.TermOutput = _termOutput; savedCursorState.C1ControlsAccepted = _GetParserMode(StateMachine::Mode::AcceptC1); - savedCursorState.CodePage = _pConApi->GetConsoleOutputCP(); + savedCursorState.CodePage = _api.GetConsoleOutputCP(); return true; } @@ -393,7 +379,7 @@ bool AdaptDispatch::CursorRestoreState() // position is clamped within the margins. if (savedCursorState.IsOriginModeRelative) { - const auto viewport = _pConApi->GetViewport(); + const auto viewport = _api.GetViewport(); const auto [topMargin, bottomMargin] = _GetVerticalMargins(viewport, false); // VT origin is at 1,1 so we need to add 1 to these margins. row = std::clamp(row, topMargin + 1, bottomMargin + 1); @@ -407,7 +393,7 @@ bool AdaptDispatch::CursorRestoreState() _isOriginModeRelative = savedCursorState.IsOriginModeRelative; // Restore text attributes. - _pConApi->SetTextAttributes(savedCursorState.Attributes); + _api.SetTextAttributes(savedCursorState.Attributes); // Restore designated character set. _termOutput = savedCursorState.TermOutput; @@ -418,7 +404,7 @@ bool AdaptDispatch::CursorRestoreState() // Restore the code page if it was previously saved. if (savedCursorState.CodePage != 0) { - _pConApi->SetConsoleOutputCP(savedCursorState.CodePage); + _api.SetConsoleOutputCP(savedCursorState.CodePage); } return true; @@ -432,7 +418,7 @@ bool AdaptDispatch::CursorRestoreState() // - True. bool AdaptDispatch::CursorVisibility(const bool fIsVisible) { - _pConApi->GetTextBuffer().GetCursor().SetIsVisible(fIsVisible); + _api.GetTextBuffer().GetCursor().SetIsVisible(fIsVisible); return true; } @@ -521,7 +507,7 @@ void AdaptDispatch::_ScrollRectHorizontally(TextBuffer& textBuffer, const til::r // - void AdaptDispatch::_InsertDeleteCharacterHelper(const VTInt delta) { - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); const auto row = textBuffer.GetCursor().GetPosition().Y; const auto startCol = textBuffer.GetCursor().GetPosition().X; const auto endCol = textBuffer.GetLineWidth(row); @@ -574,7 +560,7 @@ void AdaptDispatch::_FillRect(TextBuffer& textBuffer, const til::rect& fillRect, { textBuffer.WriteLine(fillData, COORD{ col, row }, false); } - _pConApi->NotifyAccessibilityChange(fillRect); + _api.NotifyAccessibilityChange(fillRect); } } @@ -589,7 +575,7 @@ void AdaptDispatch::_FillRect(TextBuffer& textBuffer, const til::rect& fillRect, // - True. bool AdaptDispatch::EraseCharacters(const VTInt numChars) { - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); const auto row = textBuffer.GetCursor().GetPosition().Y; const auto startCol = textBuffer.GetCursor().GetPosition().X; const auto endCol = std::min(startCol + numChars, textBuffer.GetLineWidth(row)); @@ -627,7 +613,7 @@ bool AdaptDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType) // make the state machine propagate this ED sequence to the connected // terminal application. While we're in conpty mode, we don't really // have a scrollback, but the attached terminal might. - return !_pConApi->IsConsolePty(); + return !_api.IsConsolePty(); } else if (eraseType == DispatchTypes::EraseType::All) { @@ -638,11 +624,11 @@ bool AdaptDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType) // connected terminal to do the same thing, so that the terminal will // move it's own buffer contents into the scrollback. _EraseAll(); - return !_pConApi->IsConsolePty(); + return !_api.IsConsolePty(); } - const auto viewport = _pConApi->GetViewport(); - auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + auto& textBuffer = _api.GetTextBuffer(); const auto bufferWidth = textBuffer.GetSize().Width(); const auto row = textBuffer.GetCursor().GetPosition().Y; const auto col = textBuffer.GetCursor().GetPosition().X; @@ -680,7 +666,7 @@ bool AdaptDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType) // - True if handled successfully. False otherwise. bool AdaptDispatch::EraseInLine(const DispatchTypes::EraseType eraseType) { - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); const auto row = textBuffer.GetCursor().GetPosition().Y; const auto col = textBuffer.GetCursor().GetPosition().X; @@ -711,7 +697,7 @@ bool AdaptDispatch::EraseInLine(const DispatchTypes::EraseType eraseType) // - True. bool AdaptDispatch::SetLineRendition(const LineRendition rendition) { - _pConApi->GetTextBuffer().SetCurrentLineRendition(rendition); + _api.GetTextBuffer().SetCurrentLineRendition(rendition); return true; } @@ -747,7 +733,7 @@ bool AdaptDispatch::DeviceStatusReport(const DispatchTypes::AnsiStatusType statu bool AdaptDispatch::DeviceAttributes() { // See: http://vt100.net/docs/vt100-ug/chapter3.html#DA - _WriteResponse(L"\x1b[?1;0c"); + _api.ReturnResponse(L"\x1b[?1;0c"); return true; } @@ -762,7 +748,7 @@ bool AdaptDispatch::DeviceAttributes() // - True. bool AdaptDispatch::SecondaryDeviceAttributes() { - _WriteResponse(L"\x1b[>0;10;1c"); + _api.ReturnResponse(L"\x1b[>0;10;1c"); return true; } @@ -775,7 +761,7 @@ bool AdaptDispatch::SecondaryDeviceAttributes() // - True. bool AdaptDispatch::TertiaryDeviceAttributes() { - _WriteResponse(L"\x1bP!|00000000\x1b\\"); + _api.ReturnResponse(L"\x1bP!|00000000\x1b\\"); return true; } @@ -789,7 +775,7 @@ bool AdaptDispatch::TertiaryDeviceAttributes() // - True. bool AdaptDispatch::Vt52DeviceAttributes() { - _WriteResponse(L"\x1b/Z"); + _api.ReturnResponse(L"\x1b/Z"); return true; } @@ -819,10 +805,10 @@ bool AdaptDispatch::RequestTerminalParameters(const DispatchTypes::ReportingPerm switch (permission) { case DispatchTypes::ReportingPermission::Unsolicited: - _WriteResponse(L"\x1b[2;1;1;128;128;1;0x"); + _api.ReturnResponse(L"\x1b[2;1;1;128;128;1;0x"); return true; case DispatchTypes::ReportingPermission::Solicited: - _WriteResponse(L"\x1b[3;1;1;128;128;1;0x"); + _api.ReturnResponse(L"\x1b[3;1;1;128;128;1;0x"); return true; default: return false; @@ -838,7 +824,7 @@ bool AdaptDispatch::RequestTerminalParameters(const DispatchTypes::ReportingPerm void AdaptDispatch::_OperatingStatus() const { // We always report a good operating condition. - _WriteResponse(L"\x1b[0n"); + _api.ReturnResponse(L"\x1b[0n"); } // Routine Description: @@ -849,8 +835,8 @@ void AdaptDispatch::_OperatingStatus() const // - void AdaptDispatch::_CursorPositionReport() { - const auto viewport = _pConApi->GetViewport(); - const auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + const auto& textBuffer = _api.GetTextBuffer(); // First pull the cursor position relative to the entire buffer out of the console. til::point cursorPosition{ textBuffer.GetCursor().GetPosition() }; @@ -872,39 +858,7 @@ void AdaptDispatch::_CursorPositionReport() // Now send it back into the input channel of the console. // First format the response string. const auto response = wil::str_printf(L"\x1b[%d;%dR", cursorPosition.Y, cursorPosition.X); - _WriteResponse(response); -} - -// Routine Description: -// - Helper to send a string reply to the input stream of the console. -// - Used by various commands where the program attached would like a reply to one of the commands issued. -// - This will generate two "key presses" (one down, one up) for every character in the string and place them into the head of the console's input stream. -// Arguments: -// - reply - The reply string to transmit back to the input stream -// Return Value: -// - -void AdaptDispatch::_WriteResponse(const std::wstring_view reply) const -{ - std::deque> inEvents; - - // generate a paired key down and key up event for every - // character to be sent into the console's input buffer - for (const auto& wch : reply) - { - // This wasn't from a real keyboard, so we're leaving key/scan codes blank. - KeyEvent keyEvent{ TRUE, 1, 0, 0, wch, 0 }; - - inEvents.push_back(std::make_unique(keyEvent)); - keyEvent.SetKeyDown(false); - inEvents.push_back(std::make_unique(keyEvent)); - } - - size_t eventsWritten; - // TODO GH#4954 During the input refactor we may want to add a "priority" input list - // to make sure that "response" input is spooled directly into the application. - // We switched this to an append (vs. a prepend) to fix GH#1637, a bug where two CPR - // could collide with each other. - _pConApi->WriteInput(inEvents, eventsWritten); + _api.ReturnResponse(response); } // Routine Description: @@ -915,8 +869,8 @@ void AdaptDispatch::_WriteResponse(const std::wstring_view reply) const // - void AdaptDispatch::_ScrollMovement(const VTInt delta) { - const auto viewport = _pConApi->GetViewport(); - auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + auto& textBuffer = _api.GetTextBuffer(); const auto bufferWidth = textBuffer.GetSize().Width(); const auto [topMargin, bottomMargin] = _GetVerticalMargins(viewport, true); _ScrollRectVertically(textBuffer, { 0, topMargin, bufferWidth, bottomMargin + 1 }, delta); @@ -956,9 +910,9 @@ bool AdaptDispatch::ScrollDown(const VTInt uiDistance) // - True. bool AdaptDispatch::SetColumns(const VTInt columns) { - const auto viewport = _pConApi->GetViewport(); + const auto viewport = _api.GetViewport(); const auto viewportHeight = viewport.bottom - viewport.top; - _pConApi->ResizeWindow(columns, viewportHeight); + _api.ResizeWindow(columns, viewportHeight); return true; } @@ -991,7 +945,7 @@ bool AdaptDispatch::_DoDECCOLMHelper(const VTInt columns) // - true if the mode is enabled. false if disabled. bool AdaptDispatch::_GetParserMode(const StateMachine::Mode mode) const { - return _pConApi->GetStateMachine().GetParserMode(mode); + return _api.GetStateMachine().GetParserMode(mode); } // Routine Description: @@ -1003,7 +957,7 @@ bool AdaptDispatch::_GetParserMode(const StateMachine::Mode mode) const // - void AdaptDispatch::_SetParserMode(const StateMachine::Mode mode, const bool enable) { - _pConApi->GetStateMachine().SetParserMode(mode, enable); + _api.GetStateMachine().SetParserMode(mode, enable); } // Routine Description: @@ -1029,14 +983,14 @@ bool AdaptDispatch::_SetInputMode(const TerminalInput::Mode mode, const bool ena // GH#12799 - If the app requested that we disable focus events, DON'T pass // that through. ConPTY would _always_ like to know about focus events. - return !_pConApi->IsConsolePty() || - !_pConApi->IsVtInputEnabled() || + return !_api.IsConsolePty() || + !_api.IsVtInputEnabled() || (!enable && mode == TerminalInput::Mode::FocusEvent); // Another way of writing the above statement is: // - // const bool inConpty = _pConApi->IsConsolePty(); - // const bool shouldPassthrough = inConpty && _pConApi->IsVtInputEnabled(); + // const bool inConpty = _api.IsConsolePty(); + // const bool shouldPassthrough = inConpty && _api.IsVtInputEnabled(); // const bool disabledFocusEvents = inConpty && (!enable && mode == TerminalInput::Mode::FocusEvent); // return !shouldPassthrough || disabledFocusEvents; // @@ -1110,6 +1064,9 @@ bool AdaptDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param, con case DispatchTypes::ModeParams::ASB_AlternateScreenBuffer: success = enable ? UseAlternateScreenBuffer() : UseMainScreenBuffer(); break; + case DispatchTypes::ModeParams::XTERM_BracketedPasteMode: + success = EnableXtermBracketedPasteMode(enable); + break; case DispatchTypes::ModeParams::W32IM_Win32InputMode: success = EnableWin32InputMode(enable); break; @@ -1182,7 +1139,7 @@ bool AdaptDispatch::SetCursorKeysMode(const bool applicationMode) // - True if handled successfully. False otherwise. bool AdaptDispatch::EnableCursorBlinking(const bool enable) { - auto& cursor = _pConApi->GetTextBuffer().GetCursor(); + auto& cursor = _api.GetTextBuffer().GetCursor(); cursor.SetBlinkingAllowed(enable); // GH#2642 - From what we've gathered from other terminals, when blinking is @@ -1193,7 +1150,7 @@ bool AdaptDispatch::EnableCursorBlinking(const bool enable) // (Yes, the cursor can be On and NOT Visible) cursor.SetIsOn(true); - return !_pConApi->IsConsolePty(); + return !_api.IsConsolePty(); } // Routine Description: @@ -1205,8 +1162,8 @@ bool AdaptDispatch::EnableCursorBlinking(const bool enable) // - void AdaptDispatch::_InsertDeleteLineHelper(const int32_t delta) { - const auto viewport = _pConApi->GetViewport(); - auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + auto& textBuffer = _api.GetTextBuffer(); const auto bufferWidth = textBuffer.GetSize().Width(); auto& cursor = textBuffer.GetCursor(); @@ -1286,7 +1243,7 @@ bool AdaptDispatch::SetAnsiMode(const bool ansiMode) bool AdaptDispatch::SetScreenMode(const bool reverseMode) { // If we're a conpty, always return false - if (_pConApi->IsConsolePty()) + if (_api.IsConsolePty()) { return false; } @@ -1319,7 +1276,7 @@ bool AdaptDispatch::SetOriginMode(const bool relativeMode) noexcept // - True. bool AdaptDispatch::SetAutoWrapMode(const bool wrapAtEOL) { - _pConApi->SetAutoWrapMode(wrapAtEOL); + _api.SetAutoWrapMode(wrapAtEOL); return true; } @@ -1346,7 +1303,7 @@ void AdaptDispatch::_DoSetTopBottomScrollingMargins(const VTInt topMargin, THROW_IF_FAILED(SizeTToShort(topMargin, &actualTop)); THROW_IF_FAILED(SizeTToShort(bottomMargin, &actualBottom)); - const auto viewport = _pConApi->GetViewport(); + const auto viewport = _api.GetViewport(); const auto screenHeight = gsl::narrow_cast(viewport.bottom - viewport.top); // The default top margin is line 1 if (actualTop == 0) @@ -1379,7 +1336,7 @@ void AdaptDispatch::_DoSetTopBottomScrollingMargins(const VTInt topMargin, } _scrollMargins.Top = actualTop; _scrollMargins.Bottom = actualBottom; - _pConApi->SetScrollingRegion(_scrollMargins); + _api.SetScrollingRegion(_scrollMargins); } } @@ -1412,7 +1369,7 @@ bool AdaptDispatch::SetTopBottomScrollingMargins(const VTInt topMargin, // - True. bool AdaptDispatch::WarningBell() { - _pConApi->WarningBell(); + _api.WarningBell(); return true; } @@ -1440,13 +1397,13 @@ bool AdaptDispatch::LineFeed(const DispatchTypes::LineFeedType lineFeedType) switch (lineFeedType) { case DispatchTypes::LineFeedType::DependsOnMode: - _pConApi->LineFeed(_pConApi->GetLineFeedMode()); + _api.LineFeed(_api.GetLineFeedMode()); return true; case DispatchTypes::LineFeedType::WithoutReturn: - _pConApi->LineFeed(false); + _api.LineFeed(false); return true; case DispatchTypes::LineFeedType::WithReturn: - _pConApi->LineFeed(true); + _api.LineFeed(true); return true; default: return false; @@ -1462,8 +1419,8 @@ bool AdaptDispatch::LineFeed(const DispatchTypes::LineFeedType lineFeedType) // - True. bool AdaptDispatch::ReverseLineFeed() { - const auto viewport = _pConApi->GetViewport(); - auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + auto& textBuffer = _api.GetTextBuffer(); auto& cursor = textBuffer.GetCursor(); const auto cursorPosition = cursor.GetPosition(); const auto [topMargin, bottomMargin] = _GetVerticalMargins(viewport, true); @@ -1493,7 +1450,7 @@ bool AdaptDispatch::ReverseLineFeed() // - True. bool AdaptDispatch::SetWindowTitle(std::wstring_view title) { - _pConApi->SetWindowTitle(title); + _api.SetWindowTitle(title); return true; } @@ -1507,7 +1464,7 @@ bool AdaptDispatch::SetWindowTitle(std::wstring_view title) bool AdaptDispatch::UseAlternateScreenBuffer() { CursorSaveState(); - _pConApi->UseAlternateScreenBuffer(); + _api.UseAlternateScreenBuffer(); _usingAltBuffer = true; return true; } @@ -1521,7 +1478,7 @@ bool AdaptDispatch::UseAlternateScreenBuffer() // - True. bool AdaptDispatch::UseMainScreenBuffer() { - _pConApi->UseMainScreenBuffer(); + _api.UseMainScreenBuffer(); _usingAltBuffer = false; CursorRestoreState(); return true; @@ -1535,7 +1492,7 @@ bool AdaptDispatch::UseMainScreenBuffer() // - True. bool AdaptDispatch::HorizontalTabSet() { - const auto& textBuffer = _pConApi->GetTextBuffer(); + const auto& textBuffer = _api.GetTextBuffer(); const auto width = textBuffer.GetSize().Dimensions().X; const auto column = textBuffer.GetCursor().GetPosition().X; @@ -1556,7 +1513,7 @@ bool AdaptDispatch::HorizontalTabSet() // - True. bool AdaptDispatch::ForwardTab(const VTInt numTabs) { - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); auto& cursor = textBuffer.GetCursor(); const auto width = textBuffer.GetLineWidth(cursor.GetPosition().Y); auto column = cursor.GetPosition().X; @@ -1586,7 +1543,7 @@ bool AdaptDispatch::ForwardTab(const VTInt numTabs) // - True. bool AdaptDispatch::BackwardsTab(const VTInt numTabs) { - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); auto& cursor = textBuffer.GetCursor(); const auto width = textBuffer.GetLineWidth(cursor.GetPosition().Y); auto column = cursor.GetPosition().X; @@ -1638,7 +1595,7 @@ bool AdaptDispatch::TabClear(const DispatchTypes::TabClearType clearType) // - void AdaptDispatch::_ClearSingleTabStop() { - const auto& textBuffer = _pConApi->GetTextBuffer(); + const auto& textBuffer = _api.GetTextBuffer(); const auto width = textBuffer.GetSize().Dimensions().X; const auto column = textBuffer.GetCursor().GetPosition().X; @@ -1716,18 +1673,18 @@ bool AdaptDispatch::DesignateCodingSystem(const VTID codingSystem) // This will be used to restore the code page in response to a reset. if (!_initialCodePage.has_value()) { - _initialCodePage = _pConApi->GetConsoleOutputCP(); + _initialCodePage = _api.GetConsoleOutputCP(); } switch (codingSystem) { case DispatchTypes::CodingSystem::ISO2022: - _pConApi->SetConsoleOutputCP(28591); + _api.SetConsoleOutputCP(28591); AcceptC1Controls(true); _termOutput.EnableGrTranslation(true); return true; case DispatchTypes::CodingSystem::UTF8: - _pConApi->SetConsoleOutputCP(CP_UTF8); + _api.SetConsoleOutputCP(CP_UTF8); AcceptC1Controls(false); _termOutput.EnableGrTranslation(false); return true; @@ -1857,7 +1814,7 @@ bool AdaptDispatch::SoftReset() if (_initialCodePage.has_value()) { // Restore initial code page if previously changed by a DOCS sequence. - _pConApi->SetConsoleOutputCP(_initialCodePage.value()); + _api.SetConsoleOutputCP(_initialCodePage.value()); } // Disable parsing of C1 control codes. AcceptC1Controls(false); @@ -1870,7 +1827,7 @@ bool AdaptDispatch::SoftReset() _savedCursorState.at(0) = {}; // Main buffer _savedCursorState.at(1) = {}; // Alt buffer - return !_pConApi->IsConsolePty(); + return !_api.IsConsolePty(); } //Routine Description: @@ -1900,7 +1857,7 @@ bool AdaptDispatch::HardReset() // If in the alt buffer, switch back to main before doing anything else. if (_usingAltBuffer) { - _pConApi->UseMainScreenBuffer(); + _api.UseMainScreenBuffer(); _usingAltBuffer = false; } @@ -1933,7 +1890,7 @@ bool AdaptDispatch::HardReset() // make the state machine propagate this RIS sequence to the connected // terminal application. We've reset our state, but the connected terminal // might need to do more. - return !_pConApi->IsConsolePty(); + return !_api.IsConsolePty(); } // Routine Description: @@ -1946,8 +1903,8 @@ bool AdaptDispatch::HardReset() // - True. bool AdaptDispatch::ScreenAlignmentPattern() { - const auto viewport = _pConApi->GetViewport(); - auto& textBuffer = _pConApi->GetTextBuffer(); + const auto viewport = _api.GetViewport(); + auto& textBuffer = _api.GetTextBuffer(); const auto bufferWidth = textBuffer.GetSize().Dimensions().X; // Fill the screen with the letter E using the default attributes. @@ -1957,7 +1914,7 @@ bool AdaptDispatch::ScreenAlignmentPattern() // Reset the meta/extended attributes (but leave the colors unchanged). auto attr = textBuffer.GetCurrentAttributes(); attr.SetStandardErase(); - _pConApi->SetTextAttributes(attr); + _api.SetTextAttributes(attr); // Reset the origin mode to absolute. SetOriginMode(false); // Clear the scrolling margins. @@ -1982,10 +1939,10 @@ bool AdaptDispatch::ScreenAlignmentPattern() // - void AdaptDispatch::_EraseScrollback() { - const auto viewport = _pConApi->GetViewport(); + const auto viewport = _api.GetViewport(); const auto top = gsl::narrow_cast(viewport.top); const auto height = gsl::narrow_cast(viewport.bottom - viewport.top); - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); const auto bufferSize = textBuffer.GetSize().Dimensions(); auto& cursor = textBuffer.GetCursor(); const auto row = cursor.GetPosition().Y; @@ -1997,7 +1954,7 @@ void AdaptDispatch::_EraseScrollback() // Also reset the line rendition for all of the cleared rows. textBuffer.ResetLineRenditionRange(height, bufferSize.Y); // Move the viewport - _pConApi->SetViewportPosition({ viewport.left, 0 }); + _api.SetViewportPosition({ viewport.left, 0 }); // Move the cursor to the same relative location. cursor.SetYPosition(row - top); cursor.SetHasMoved(true); @@ -2017,9 +1974,9 @@ void AdaptDispatch::_EraseScrollback() // - void AdaptDispatch::_EraseAll() { - const auto viewport = _pConApi->GetViewport(); + const auto viewport = _api.GetViewport(); const auto viewportHeight = gsl::narrow_cast(viewport.bottom - viewport.top); - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); const auto bufferSize = textBuffer.GetSize(); // Stash away the current position of the cursor within the viewport. @@ -2028,9 +1985,12 @@ void AdaptDispatch::_EraseAll() auto& cursor = textBuffer.GetCursor(); const auto row = cursor.GetPosition().Y - viewport.top; - // Calculate new viewport position - short newViewportTop = textBuffer.GetLastNonSpaceCharacter().Y + 1; - const short newViewportBottom = newViewportTop + viewportHeight; + // Calculate new viewport position. Typically we want to move one line below + // the last non-space row, but if the last non-space character is the very + // start of the buffer, then we shouldn't move down at all. + const til::point lastChar{ textBuffer.GetLastNonSpaceCharacter() }; + auto newViewportTop = lastChar == til::point{} ? 0 : lastChar.Y + 1; + const auto newViewportBottom = newViewportTop + viewportHeight; const auto delta = newViewportBottom - (bufferSize.Height()); for (auto i = 0; i < delta; i++) { @@ -2038,7 +1998,7 @@ void AdaptDispatch::_EraseAll() newViewportTop--; } // Move the viewport - _pConApi->SetViewportPosition({ viewport.left, newViewportTop }); + _api.SetViewportPosition({ viewport.left, newViewportTop }); // Restore the relative cursor position cursor.SetYPosition(row + newViewportTop); cursor.SetHasMoved(true); @@ -2154,9 +2114,16 @@ bool AdaptDispatch::EnableAlternateScroll(const bool enabled) // - enabled - true to enable, false to disable. // Return value: // True if handled successfully. False otherwise. -bool AdaptDispatch::EnableXtermBracketedPasteMode(const bool /*enabled*/) noexcept +bool AdaptDispatch::EnableXtermBracketedPasteMode(const bool enabled) { - return NoOp(); + // Return false to forward the operation to the hosting terminal, + // since ConPTY can't handle this itself. + if (_api.IsConsolePty()) + { + return false; + } + _api.EnableXtermBracketedPasteMode(enabled); + return true; } //Routine Description: @@ -2175,7 +2142,7 @@ bool AdaptDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) { case DispatchTypes::CursorStyle::UserDefault: fEnableBlinking = true; - actualType = _pConApi->GetUserDefaultCursorStyle(); + actualType = _api.GetUserDefaultCursorStyle(); break; case DispatchTypes::CursorStyle::BlinkingBlock: fEnableBlinking = true; @@ -2209,14 +2176,14 @@ bool AdaptDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) return false; } - auto& cursor = _pConApi->GetTextBuffer().GetCursor(); + auto& cursor = _api.GetTextBuffer().GetCursor(); cursor.SetType(actualType); cursor.SetBlinkingAllowed(fEnableBlinking); cursor.SetIsOn(true); // If we're a conpty, always return false, so that this cursor state will be // sent to the connected terminal - return !_pConApi->IsConsolePty(); + return !_api.IsConsolePty(); } // Method Description: @@ -2237,9 +2204,16 @@ bool AdaptDispatch::SetCursorColor(const COLORREF cursorColor) // - content - The content to copy to clipboard. Must be null terminated. // Return Value: // - True if handled successfully. False otherwise. -bool AdaptDispatch::SetClipboard(const std::wstring_view /*content*/) noexcept +bool AdaptDispatch::SetClipboard(const std::wstring_view content) { - return false; + // Return false to forward the operation to the hosting terminal, + // since ConPTY can't handle this itself. + if (_api.IsConsolePty()) + { + return false; + } + _api.CopyToClipboard(content); + return true; } // Method Description: @@ -2257,14 +2231,19 @@ bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwCo // value to the terminal. Still handle the sequence so apps that use // the API or VT to query the values of the color table still read the // correct color. - if (_pConApi->IsConsolePty()) + if (_api.IsConsolePty()) { return false; } + // If we're updating the background color, we need to let the renderer + // know, since it may want to repaint the window background to match. + const auto backgroundIndex = _renderSettings.GetColorAliasIndex(ColorAlias::DefaultBackground); + const auto backgroundChanged = (tableIndex == backgroundIndex); + // Update the screen colors if we're not a pty // No need to force a redraw in pty mode. - _renderer.TriggerRedrawAll(); + _renderer.TriggerRedrawAll(backgroundChanged); return true; } @@ -2314,16 +2293,16 @@ bool AdaptDispatch::WindowManipulation(const DispatchTypes::WindowManipulationTy switch (function) { case DispatchTypes::WindowManipulationType::DeIconifyWindow: - _pConApi->ShowWindow(true); + _api.ShowWindow(true); return true; case DispatchTypes::WindowManipulationType::IconifyWindow: - _pConApi->ShowWindow(false); + _api.ShowWindow(false); return true; case DispatchTypes::WindowManipulationType::RefreshWindow: - _pConApi->GetTextBuffer().TriggerRedrawAll(); + _api.GetTextBuffer().TriggerRedrawAll(); return true; case DispatchTypes::WindowManipulationType::ResizeWindowInCharacters: - _pConApi->ResizeWindow(parameter2.value_or(0), parameter1.value_or(0)); + _api.ResizeWindow(parameter2.value_or(0), parameter1.value_or(0)); return true; default: return false; @@ -2338,7 +2317,7 @@ bool AdaptDispatch::WindowManipulation(const DispatchTypes::WindowManipulationTy // - true bool AdaptDispatch::AddHyperlink(const std::wstring_view uri, const std::wstring_view params) { - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); auto attr = textBuffer.GetCurrentAttributes(); const auto id = textBuffer.GetHyperlinkId(uri, params); attr.SetHyperlinkId(id); @@ -2353,7 +2332,7 @@ bool AdaptDispatch::AddHyperlink(const std::wstring_view uri, const std::wstring // - true bool AdaptDispatch::EndHyperlink() { - auto& textBuffer = _pConApi->GetTextBuffer(); + auto& textBuffer = _api.GetTextBuffer(); auto attr = textBuffer.GetCurrentAttributes(); attr.SetHyperlinkId(0); textBuffer.SetCurrentAttributes(attr); @@ -2361,12 +2340,93 @@ bool AdaptDispatch::EndHyperlink() } // Method Description: -// - Ascribes to the ITermDispatch interface -// - Not actually used in conhost +// - Performs a ConEmu action +// Currently, the only actions we support are setting the taskbar state/progress +// and setting the working directory. +// Arguments: +// - string - contains the parameters that define which action we do // Return Value: -// - false (so that the command gets flushed to terminal) -bool AdaptDispatch::DoConEmuAction(const std::wstring_view /*string*/) noexcept +// - True if handled successfully. False otherwise. +bool AdaptDispatch::DoConEmuAction(const std::wstring_view string) { + // Return false to forward the operation to the hosting terminal, + // since ConPTY can't handle this itself. + if (_api.IsConsolePty()) + { + return false; + } + + constexpr size_t TaskbarMaxState{ 4 }; + constexpr size_t TaskbarMaxProgress{ 100 }; + + unsigned int state = 0; + unsigned int progress = 0; + + const auto parts = Utils::SplitString(string, L';'); + unsigned int subParam = 0; + + if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam)) + { + return false; + } + + // 4 is SetProgressBar, which sets the taskbar state/progress. + if (subParam == 4) + { + if (parts.size() >= 2) + { + // A state parameter is defined, parse it out + const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state); + if (!stateSuccess && !til::at(parts, 1).empty()) + { + return false; + } + if (parts.size() >= 3) + { + // A progress parameter is also defined, parse it out + const auto progressSuccess = Utils::StringToUint(til::at(parts, 2), progress); + if (!progressSuccess && !til::at(parts, 2).empty()) + { + return false; + } + } + } + + if (state > TaskbarMaxState) + { + // state is out of bounds, return false + return false; + } + if (progress > TaskbarMaxProgress) + { + // progress is greater than the maximum allowed value, clamp it to the max + progress = TaskbarMaxProgress; + } + _api.SetTaskbarProgress(static_cast(state), progress); + return true; + } + // 9 is SetWorkingDirectory, which informs the terminal about the current working directory. + else if (subParam == 9) + { + if (parts.size() >= 2) + { + const auto path = til::at(parts, 1); + // The path should be surrounded with '"' according to the documentation of ConEmu. + // An example: 9;"D:/" + if (path.at(0) == L'"' && path.at(path.size() - 1) == L'"' && path.size() >= 3) + { + _api.SetWorkingDirectory(path.substr(1, path.size() - 2)); + } + else + { + // If we fail to find the surrounding quotation marks, we'll give the path a try anyway. + // ConEmu also does this. + _api.SetWorkingDirectory(path); + } + return true; + } + } + return false; } @@ -2397,7 +2457,7 @@ ITermDispatch::StringHandler AdaptDispatch::DownloadDRCS(const VTInt fontNumber, // If we're a conpty, we're just going to ignore the operation for now. // There's no point in trying to pass it through without also being able // to pass through the character set designations. - if (_pConApi->IsConsolePty()) + if (_api.IsConsolePty()) { return nullptr; } @@ -2482,7 +2542,7 @@ ITermDispatch::StringHandler AdaptDispatch::RequestSetting() _ReportDECSTBMSetting(); break; default: - _WriteResponse(L"\033P0$r\033\\"); + _api.ReturnResponse(L"\033P0$r\033\\"); break; } return false; @@ -2513,7 +2573,7 @@ void AdaptDispatch::_ReportSGRSetting() const fmt::basic_memory_buffer response; response.append(L"\033P1$r0"sv); - const auto attr = _pConApi->GetTextBuffer().GetCurrentAttributes(); + const auto attr = _api.GetTextBuffer().GetCurrentAttributes(); // For each boolean attribute that is set, we add the appropriate // parameter value to the response string. const auto addAttribute = [&](const auto& parameter, const auto enabled) { @@ -2560,7 +2620,7 @@ void AdaptDispatch::_ReportSGRSetting() const // The 'm' indicates this is an SGR response, and ST ends the sequence. response.append(L"m\033\\"sv); - _WriteResponse({ response.data(), response.size() }); + _api.ReturnResponse({ response.data(), response.size() }); } // Method Description: @@ -2577,12 +2637,12 @@ void AdaptDispatch::_ReportDECSTBMSetting() fmt::basic_memory_buffer response; response.append(L"\033P1$r"sv); - const auto viewport = _pConApi->GetViewport(); + const auto viewport = _api.GetViewport(); const auto [marginTop, marginBottom] = _GetVerticalMargins(viewport, false); // VT origin is at 1,1 so we need to add 1 to these margins. fmt::format_to(std::back_inserter(response), FMT_COMPILE(L"{};{}"), marginTop + 1, marginBottom + 1); // The 'r' indicates this is an DECSTBM response, and ST ends the sequence. response.append(L"r\033\\"sv); - _WriteResponse({ response.data(), response.size() }); + _api.ReturnResponse({ response.data(), response.size() }); } diff --git a/src/terminal/adapter/adaptDispatch.hpp b/src/terminal/adapter/adaptDispatch.hpp index 3cf677b1947..722645dc1a5 100644 --- a/src/terminal/adapter/adaptDispatch.hpp +++ b/src/terminal/adapter/adaptDispatch.hpp @@ -15,7 +15,7 @@ Author(s): #pragma once #include "termDispatch.hpp" -#include "conGetSet.hpp" +#include "ITerminalApi.hpp" #include "FontBuffer.hpp" #include "terminalOutput.hpp" #include "../input/terminalInput.hpp" @@ -29,7 +29,7 @@ namespace Microsoft::Console::VirtualTerminal using RenderSettings = Microsoft::Console::Render::RenderSettings; public: - AdaptDispatch(std::unique_ptr pConApi, Renderer& renderer, RenderSettings& renderSettings, TerminalInput& terminalInput); + AdaptDispatch(ITerminalApi& api, Renderer& renderer, RenderSettings& renderSettings, TerminalInput& terminalInput); void Print(const wchar_t wchPrintable) override; void PrintString(const std::wstring_view string) override; @@ -109,11 +109,11 @@ namespace Microsoft::Console::VirtualTerminal bool EnableAnyEventMouseMode(const bool enabled) override; // ?1003 bool EnableFocusEventMode(const bool enabled) override; // ?1004 bool EnableAlternateScroll(const bool enabled) override; // ?1007 - bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override; // ?2004 + bool EnableXtermBracketedPasteMode(const bool enabled) override; // ?2004 bool SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) override; // DECSCUSR bool SetCursorColor(const COLORREF cursorColor) override; - bool SetClipboard(const std::wstring_view content) noexcept override; // OSCSetClipboard + bool SetClipboard(const std::wstring_view content) override; // OSCSetClipboard bool SetColorTableEntry(const size_t tableIndex, const DWORD color) override; // OSCColorTable @@ -127,7 +127,7 @@ namespace Microsoft::Console::VirtualTerminal bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) override; bool EndHyperlink() override; - bool DoConEmuAction(const std::wstring_view string) noexcept override; + bool DoConEmuAction(const std::wstring_view string) override; StringHandler DownloadDRCS(const VTInt fontNumber, const VTParameter startChar, @@ -184,7 +184,6 @@ namespace Microsoft::Console::VirtualTerminal void _OperatingStatus() const; void _CursorPositionReport(); - void _WriteResponse(const std::wstring_view reply) const; bool _GetParserMode(const StateMachine::Mode mode) const; void _SetParserMode(const StateMachine::Mode mode, const bool enable); bool _SetInputMode(const TerminalInput::Mode mode, const bool enable); @@ -202,7 +201,7 @@ namespace Microsoft::Console::VirtualTerminal std::vector _tabStopColumns; bool _initDefaultTabStops = true; - std::unique_ptr _pConApi; + ITerminalApi& _api; Renderer& _renderer; RenderSettings& _renderSettings; TerminalInput& _terminalInput; diff --git a/src/terminal/adapter/adaptDispatchGraphics.cpp b/src/terminal/adapter/adaptDispatchGraphics.cpp index 8caac1d6194..12485f9227a 100644 --- a/src/terminal/adapter/adaptDispatchGraphics.cpp +++ b/src/terminal/adapter/adaptDispatchGraphics.cpp @@ -4,7 +4,6 @@ #include #include "adaptDispatch.hpp" -#include "conGetSet.hpp" #include "../../types/inc/utils.hpp" #define ENABLE_INTSAFE_SIGNED_FUNCTIONS @@ -75,7 +74,7 @@ size_t AdaptDispatch::_SetRgbColorsHelper(const VTParameters options, // - True. bool AdaptDispatch::SetGraphicsRendition(const VTParameters options) { - auto attr = _pConApi->GetTextBuffer().GetCurrentAttributes(); + auto attr = _api.GetTextBuffer().GetCurrentAttributes(); // Run through the graphics options and apply them for (size_t i = 0; i < options.size(); i++) @@ -255,7 +254,7 @@ bool AdaptDispatch::SetGraphicsRendition(const VTParameters options) break; } } - _pConApi->SetTextAttributes(attr); + _api.SetTextAttributes(attr); return true; } @@ -270,7 +269,7 @@ bool AdaptDispatch::SetGraphicsRendition(const VTParameters options) // - True. bool AdaptDispatch::PushGraphicsRendition(const VTParameters options) { - const auto currentAttributes = _pConApi->GetTextBuffer().GetCurrentAttributes(); + const auto currentAttributes = _api.GetTextBuffer().GetCurrentAttributes(); _sgrStack.Push(currentAttributes, options); return true; } @@ -284,7 +283,7 @@ bool AdaptDispatch::PushGraphicsRendition(const VTParameters options) // - True. bool AdaptDispatch::PopGraphicsRendition() { - const auto currentAttributes = _pConApi->GetTextBuffer().GetCurrentAttributes(); - _pConApi->SetTextAttributes(_sgrStack.Pop(currentAttributes)); + const auto currentAttributes = _api.GetTextBuffer().GetCurrentAttributes(); + _api.SetTextAttributes(_sgrStack.Pop(currentAttributes)); return true; } diff --git a/src/terminal/adapter/lib/adapter.vcxproj b/src/terminal/adapter/lib/adapter.vcxproj index 0a6b1205790..63953f218a9 100644 --- a/src/terminal/adapter/lib/adapter.vcxproj +++ b/src/terminal/adapter/lib/adapter.vcxproj @@ -28,7 +28,7 @@ - + diff --git a/src/terminal/adapter/lib/adapter.vcxproj.filters b/src/terminal/adapter/lib/adapter.vcxproj.filters index 1f333e76af3..10a5aa55ff7 100644 --- a/src/terminal/adapter/lib/adapter.vcxproj.filters +++ b/src/terminal/adapter/lib/adapter.vcxproj.filters @@ -44,7 +44,7 @@ Header Files - + Header Files diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index 29b27f10dbf..ae1a926d54e 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -57,13 +57,29 @@ enum class AbsolutePosition : Microsoft::Console::VirtualTerminal::VTInt using namespace Microsoft::Console::VirtualTerminal; -class TestGetSet final : public ConGetSet +class TestGetSet final : public ITerminalApi { public: void PrintString(const std::wstring_view /*string*/) override { } + void ReturnResponse(const std::wstring_view response) override + { + Log::Comment(L"ReturnResponse MOCK called..."); + + THROW_HR_IF(E_FAIL, !_returnResponseResult); + + if (_retainResponse) + { + _response += response; + } + else + { + _response = response; + } + } + StateMachine& GetStateMachine() override { return *_stateMachine; @@ -103,27 +119,6 @@ class TestGetSet final : public ConGetSet _textBuffer->SetCurrentAttributes(attrs); } - void WriteInput(std::deque>& events, size_t& eventsWritten) override - { - Log::Comment(L"WriteInput MOCK called..."); - - THROW_HR_IF(E_FAIL, !_writeInputResult); - - // move all the input events we were given into local storage so we can test against them - Log::Comment(NoThrowString().Format(L"Moving %zu input events into local storage...", events.size())); - - if (_retainInput) - { - std::move(events.begin(), events.end(), std::back_inserter(_events)); - } - else - { - _events.clear(); - _events.swap(events); - } - eventsWritten = _events.size(); - } - void SetScrollingRegion(const til::inclusive_rect& scrollMargins) override { Log::Comment(L"SetScrollingRegion MOCK called..."); @@ -206,6 +201,26 @@ class TestGetSet final : public ConGetSet return _expectedOutputCP; } + void EnableXtermBracketedPasteMode(const bool /*enabled*/) + { + Log::Comment(L"EnableXtermBracketedPasteMode MOCK called..."); + } + + void CopyToClipboard(const std::wstring_view /*content*/) + { + Log::Comment(L"CopyToClipboard MOCK called..."); + } + + void SetTaskbarProgress(const DispatchTypes::TaskbarState /*state*/, const size_t /*progress*/) + { + Log::Comment(L"SetTaskbarProgress MOCK called..."); + } + + void SetWorkingDirectory(const std::wstring_view /*uri*/) + { + Log::Comment(L"SetWorkingDirectory MOCK called..."); + } + bool IsConsolePty() const override { Log::Comment(L"IsConsolePty MOCK called..."); @@ -217,11 +232,6 @@ class TestGetSet final : public ConGetSet Log::Comment(L"NotifyAccessibilityChange MOCK called..."); } - void ReparentWindow(const uint64_t /*handle*/) - { - Log::Comment(L"ReparentWindow MOCK called..."); - } - void PrepData() { PrepData(CursorDirection::UP); // if called like this, the cursor direction doesn't matter. @@ -252,7 +262,7 @@ class TestGetSet final : public ConGetSet // APIs succeed by default _setTextAttributesResult = TRUE; - _writeInputResult = TRUE; + _returnResponseResult = TRUE; _textBuffer = std::make_unique(COORD{ 100, 600 }, TextAttribute{}, 0, false, _renderer); @@ -269,8 +279,8 @@ class TestGetSet final : public ConGetSet _textBuffer->SetCurrentAttributes(TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED }); _expectedAttribute = _textBuffer->GetCurrentAttributes(); - _events.clear(); - _retainInput = false; + _response.clear(); + _retainResponse = false; } void PrepCursor(CursorX xact, CursorY yact) @@ -323,28 +333,7 @@ class TestGetSet final : public ConGetSet void ValidateInputEvent(_In_ PCWSTR pwszExpectedResponse) { - const auto cchResponse = wcslen(pwszExpectedResponse); - const auto eventCount = _events.size(); - - VERIFY_ARE_EQUAL(cchResponse * 2, eventCount, L"We should receive TWO input records for every character in the expected string. Key down and key up."); - - for (size_t iInput = 0; iInput < eventCount; iInput++) - { - const auto wch = pwszExpectedResponse[iInput / 2]; // the same portion of the string will be used twice. 0/2 = 0. 1/2 = 0. 2/2 = 1. 3/2 = 1. and so on. - - VERIFY_ARE_EQUAL(InputEventType::KeyEvent, _events[iInput]->EventType()); - - const auto keyEvent = static_cast(_events[iInput].get()); - - // every even key is down. every odd key is up. DOWN = 0, UP = 1. DOWN = 2, UP = 3. and so on. - VERIFY_ARE_EQUAL((bool)!(iInput % 2), keyEvent->IsKeyDown()); - VERIFY_ARE_EQUAL(0u, keyEvent->GetActiveModifierKeys()); - Log::Comment(NoThrowString().Format(L"Comparing '%c' with '%c'...", wch, keyEvent->GetCharData())); - VERIFY_ARE_EQUAL(wch, keyEvent->GetCharData()); - VERIFY_ARE_EQUAL(1u, keyEvent->GetRepeatCount()); - VERIFY_ARE_EQUAL(0u, keyEvent->GetVirtualKeyCode()); - VERIFY_ARE_EQUAL(0u, keyEvent->GetVirtualScanCode()); - } + VERIFY_ARE_EQUAL(pwszExpectedResponse, _response); } void _SetMarginsHelper(til::inclusive_rect* rect, til::CoordType top, til::CoordType bottom) @@ -366,15 +355,15 @@ class TestGetSet final : public ConGetSet static const WORD s_wDefaultAttribute = 0; static const WORD s_defaultFill = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; // dark gray on black. - std::deque> _events; - bool _retainInput{ false }; + std::wstring _response; + bool _retainResponse{ false }; auto EnableInputRetentionInScope() { - auto oldRetainValue{ _retainInput }; - _retainInput = true; + auto oldRetainValue{ _retainResponse }; + _retainResponse = true; return wil::scope_exit([oldRetainValue, this] { - _retainInput = oldRetainValue; + _retainResponse = oldRetainValue; }); } @@ -392,7 +381,7 @@ class TestGetSet final : public ConGetSet bool _isPty = false; bool _setTextAttributesResult = false; - bool _writeInputResult = false; + bool _returnResponseResult = false; bool _setScrollingRegionResult = false; bool _getLineFeedModeResult = false; @@ -422,12 +411,11 @@ class AdapterTest fSuccess = api.get() != nullptr; if (fSuccess) { - // give AdaptDispatch ownership of _testGetSet - _testGetSet = api.get(); // keep a copy for us but don't manage its lifetime anymore. + _testGetSet = std::move(api); _terminalInput = TerminalInput{ nullptr }; auto& renderer = _testGetSet->_renderer; auto& renderSettings = renderer._renderSettings; - auto adapter = std::make_unique(std::move(api), renderer, renderSettings, _terminalInput); + auto adapter = std::make_unique(*_testGetSet, renderer, renderSettings, _terminalInput); fSuccess = adapter.get() != nullptr; if (fSuccess) @@ -1448,9 +1436,9 @@ class AdapterTest auto pwszExpectedResponse = L"\x1b[?1;0c"; _testGetSet->ValidateInputEvent(pwszExpectedResponse); - Log::Comment(L"Test 2: Verify failure when WriteInput doesn't work."); + Log::Comment(L"Test 2: Verify failure when ReturnResponse doesn't work."); _testGetSet->PrepData(); - _testGetSet->_writeInputResult = FALSE; + _testGetSet->_returnResponseResult = FALSE; VERIFY_THROWS(_pDispatch->DeviceAttributes(), std::exception); } @@ -1466,9 +1454,9 @@ class AdapterTest auto pwszExpectedResponse = L"\x1b[>0;10;1c"; _testGetSet->ValidateInputEvent(pwszExpectedResponse); - Log::Comment(L"Test 2: Verify failure when WriteInput doesn't work."); + Log::Comment(L"Test 2: Verify failure when ReturnResponse doesn't work."); _testGetSet->PrepData(); - _testGetSet->_writeInputResult = FALSE; + _testGetSet->_returnResponseResult = FALSE; VERIFY_THROWS(_pDispatch->SecondaryDeviceAttributes(), std::exception); } @@ -1484,9 +1472,9 @@ class AdapterTest auto pwszExpectedResponse = L"\x1bP!|00000000\x1b\\"; _testGetSet->ValidateInputEvent(pwszExpectedResponse); - Log::Comment(L"Test 2: Verify failure when WriteInput doesn't work."); + Log::Comment(L"Test 2: Verify failure when ReturnResponse doesn't work."); _testGetSet->PrepData(); - _testGetSet->_writeInputResult = FALSE; + _testGetSet->_returnResponseResult = FALSE; VERIFY_THROWS(_pDispatch->TertiaryDeviceAttributes(), std::exception); } @@ -1509,9 +1497,9 @@ class AdapterTest _testGetSet->PrepData(); VERIFY_IS_FALSE(_pDispatch->RequestTerminalParameters((DispatchTypes::ReportingPermission)2)); - Log::Comment(L"Test 4: Verify failure when WriteInput doesn't work."); + Log::Comment(L"Test 4: Verify failure when ReturnResponse doesn't work."); _testGetSet->PrepData(); - _testGetSet->_writeInputResult = FALSE; + _testGetSet->_returnResponseResult = FALSE; VERIFY_THROWS(_pDispatch->RequestTerminalParameters(DispatchTypes::ReportingPermission::Unsolicited), std::exception); } @@ -2256,7 +2244,7 @@ class AdapterTest private: TerminalInput _terminalInput{ nullptr }; - TestGetSet* _testGetSet; // non-ownership pointer + std::unique_ptr _testGetSet; AdaptDispatch* _pDispatch; // non-ownership pointer std::unique_ptr _stateMachine; }; diff --git a/src/terminal/parser/OutputStateMachineEngine.cpp b/src/terminal/parser/OutputStateMachineEngine.cpp index e1d11693c25..864aa8555b5 100644 --- a/src/terminal/parser/OutputStateMachineEngine.cpp +++ b/src/terminal/parser/OutputStateMachineEngine.cpp @@ -267,19 +267,19 @@ bool OutputStateMachineEngine::ActionEscDispatch(const VTID id) TermTelemetry::Instance().Log(TermTelemetry::Codes::DECAC1); break; case EscActionCodes::DECDHL_DoubleHeightLineTop: - _dispatch->SetLineRendition(LineRendition::DoubleHeightTop); + success = _dispatch->SetLineRendition(LineRendition::DoubleHeightTop); TermTelemetry::Instance().Log(TermTelemetry::Codes::DECDHL); break; case EscActionCodes::DECDHL_DoubleHeightLineBottom: - _dispatch->SetLineRendition(LineRendition::DoubleHeightBottom); + success = _dispatch->SetLineRendition(LineRendition::DoubleHeightBottom); TermTelemetry::Instance().Log(TermTelemetry::Codes::DECDHL); break; case EscActionCodes::DECSWL_SingleWidthLine: - _dispatch->SetLineRendition(LineRendition::SingleWidth); + success = _dispatch->SetLineRendition(LineRendition::SingleWidth); TermTelemetry::Instance().Log(TermTelemetry::Codes::DECSWL); break; case EscActionCodes::DECDWL_DoubleWidthLine: - _dispatch->SetLineRendition(LineRendition::DoubleWidth); + success = _dispatch->SetLineRendition(LineRendition::DoubleWidth); TermTelemetry::Instance().Log(TermTelemetry::Codes::DECDWL); break; case EscActionCodes::DECALN_ScreenAlignmentPattern: diff --git a/src/types/IBaseData.h b/src/types/IBaseData.h index d8ba21d8711..676994cab57 100644 --- a/src/types/IBaseData.h +++ b/src/types/IBaseData.h @@ -36,8 +36,8 @@ namespace Microsoft::Console::Types public: virtual Microsoft::Console::Types::Viewport GetViewport() noexcept = 0; virtual COORD GetTextBufferEndPosition() const noexcept = 0; - virtual const TextBuffer& GetTextBuffer() noexcept = 0; - virtual const FontInfo& GetFontInfo() noexcept = 0; + virtual const TextBuffer& GetTextBuffer() const noexcept = 0; + virtual const FontInfo& GetFontInfo() const noexcept = 0; virtual std::vector GetSelectionRects() noexcept = 0;