diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 6db40713c9a..5b035f38ebe 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -278,6 +278,55 @@ namespace winrt::TerminalApp::implementation args.Handled(true); } + void TerminalPage::_HandleScrollToMark(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + if (const auto& realArgs = args.ActionArgs().try_as()) + { + _ApplyToActiveControls([&realArgs](auto& control) { + control.ScrollToMark(realArgs.Direction()); + }); + } + args.Handled(true); + } + void TerminalPage::_HandleAddMark(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + if (const auto& realArgs = args.ActionArgs().try_as()) + { + _ApplyToActiveControls([realArgs](auto& control) { + Control::ScrollMark mark; + if (realArgs.Color()) + { + mark.Color.Color = realArgs.Color().Value(); + mark.Color.HasValue = true; + } + else + { + mark.Color.HasValue = false; + } + control.AddMark(mark); + }); + } + args.Handled(true); + } + void TerminalPage::_HandleClearMark(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + _ApplyToActiveControls([](auto& control) { + control.ClearMark(); + }); + args.Handled(true); + } + void TerminalPage::_HandleClearAllMarks(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + _ApplyToActiveControls([](auto& control) { + control.ClearAllMarks(); + }); + args.Handled(true); + } + void TerminalPage::_HandleFindMatch(const IInspectable& /*sender*/, const ActionEventArgs& args) { diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 9d98115c912..ec470a31dd6 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -37,6 +37,28 @@ constexpr const auto UpdatePatternLocationsInterval = std::chrono::milliseconds( namespace winrt::Microsoft::Terminal::Control::implementation { + static winrt::Microsoft::Terminal::Core::OptionalColor OptionalFromColor(const til::color& c) + { + Core::OptionalColor result; + result.Color = c; + result.HasValue = true; + return result; + } + static winrt::Microsoft::Terminal::Core::OptionalColor OptionalFromColor(const std::optional& c) + { + Core::OptionalColor result; + if (c.has_value()) + { + result.Color = *c; + result.HasValue = true; + } + else + { + result.HasValue = false; + } + return result; + } + // Helper static function to ensure that all ambiguous-width glyphs are reported as narrow. // See microsoft/terminal#2066 for more info. static bool _IsGlyphWideForceNarrowFallback(const std::wstring_view /* glyph */) @@ -1196,6 +1218,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation const int viewHeight, const int bufferSize) { + if (!_initializedTerminal) + { + return; + } // Clear the regex pattern tree so the renderer does not try to render them while scrolling // We're **NOT** taking the lock here unlike _scrollbarChangeHandler because // we are already under lock (since this usually happens as a result of writing). @@ -1854,4 +1880,140 @@ namespace winrt::Microsoft::Terminal::Control::implementation // transparency, or our acrylic, or our image. return Opacity() < 1.0f || UseAcrylic() || !_settings->BackgroundImage().empty() || _settings->UseBackgroundImageForWindow(); } + + Windows::Foundation::Collections::IVector ControlCore::ScrollMarks() const + { + auto internalMarks{ _terminal->GetScrollMarks() }; + auto v = winrt::single_threaded_observable_vector(); + for (const auto& mark : internalMarks) + { + Control::ScrollMark m{}; + + // sneaky: always evaluate the color of the mark to a real value + // before shoving it into the optional. If the mark doesn't have a + // specific color set, we'll use the value from the color table + // that's appropriate for this category of mark. If we do have a + // color set, then great we'll use that. The TermControl can then + // always use the value in the Mark regardless if it was actually + // set or not. + m.Color = OptionalFromColor(_terminal->GetColorForMark(mark)); + m.Start = mark.start.to_core_point(); + m.End = mark.end.to_core_point(); + + v.Append(m); + } + + return v; + } + + void ControlCore::AddMark(const Control::ScrollMark& mark) + { + ::Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark m{}; + + if (mark.Color.HasValue) + { + m.color = til::color{ mark.Color.Color }; + } + + if (HasSelection()) + { + m.start = til::point{ _terminal->GetSelectionAnchor() }; + m.end = til::point{ _terminal->GetSelectionEnd() }; + } + else + { + m.start = m.end = til::point{ _terminal->GetTextBuffer().GetCursor().GetPosition() }; + } + + // The version of this that only accepts a ScrollMark will automatically + // set the start & end to the cursor position. + _terminal->AddMark(m, m.start, m.end); + } + void ControlCore::ClearMark() { _terminal->ClearMark(); } + void ControlCore::ClearAllMarks() { _terminal->ClearAllMarks(); } + + void ControlCore::ScrollToMark(const Control::ScrollToMarkDirection& direction) + { + const auto currentOffset = ScrollOffset(); + const auto& marks{ _terminal->GetScrollMarks() }; + + std::optional tgt; + + switch (direction) + { + case ScrollToMarkDirection::Last: + { + int highest = currentOffset; + for (const auto& mark : marks) + { + const auto newY = mark.start.y; + if (newY > highest) + { + tgt = mark; + highest = newY; + } + } + break; + } + case ScrollToMarkDirection::First: + { + int lowest = currentOffset; + for (const auto& mark : marks) + { + const auto newY = mark.start.y; + if (newY < lowest) + { + tgt = mark; + lowest = newY; + } + } + break; + } + case ScrollToMarkDirection::Next: + { + int minDistance = INT_MAX; + for (const auto& mark : marks) + { + const auto delta = mark.start.y - currentOffset; + if (delta > 0 && delta < minDistance) + { + tgt = mark; + minDistance = delta; + } + } + break; + } + case ScrollToMarkDirection::Previous: + default: + { + int minDistance = INT_MAX; + for (const auto& mark : marks) + { + const auto delta = currentOffset - mark.start.y; + if (delta > 0 && delta < minDistance) + { + tgt = mark; + minDistance = delta; + } + } + break; + } + } + + if (tgt.has_value()) + { + UserScrollViewport(tgt->start.y); + } + else + { + if (direction == ScrollToMarkDirection::Last || direction == ScrollToMarkDirection::Next) + { + UserScrollViewport(BufferHeight()); + } + else if (direction == ScrollToMarkDirection::First || direction == ScrollToMarkDirection::Previous) + { + UserScrollViewport(0); + } + } + } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index b3c8afa8a98..5f20493db17 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -119,6 +119,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation int BufferHeight() const; bool BracketedPasteEnabled() const noexcept; + + Windows::Foundation::Collections::IVector ScrollMarks() const; + void AddMark(const Control::ScrollMark& mark); + void ClearMark(); + void ClearAllMarks(); + void ScrollToMark(const Control::ScrollToMarkDirection& direction); + #pragma endregion #pragma region ITerminalInput diff --git a/src/cascadia/TerminalControl/ControlCore.idl b/src/cascadia/TerminalControl/ControlCore.idl index ac47a729554..13bd83c8550 100644 --- a/src/cascadia/TerminalControl/ControlCore.idl +++ b/src/cascadia/TerminalControl/ControlCore.idl @@ -22,7 +22,6 @@ namespace Microsoft.Terminal.Control IsRightButtonDown = 0x4 }; - enum ClearBufferType { Screen, diff --git a/src/cascadia/TerminalControl/IControlSettings.idl b/src/cascadia/TerminalControl/IControlSettings.idl index 2fb8c598519..66ea5a33625 100644 --- a/src/cascadia/TerminalControl/IControlSettings.idl +++ b/src/cascadia/TerminalControl/IControlSettings.idl @@ -56,6 +56,7 @@ namespace Microsoft.Terminal.Control // Experimental Settings Boolean ForceFullRepaintRendering { get; }; Boolean SoftwareRendering { get; }; + Boolean ShowMarks { get; }; Boolean UseBackgroundImageForWindow { get; }; }; } diff --git a/src/cascadia/TerminalControl/ICoreState.idl b/src/cascadia/TerminalControl/ICoreState.idl index fd11bda8f14..4d4d2e2e4ed 100644 --- a/src/cascadia/TerminalControl/ICoreState.idl +++ b/src/cascadia/TerminalControl/ICoreState.idl @@ -3,6 +3,32 @@ namespace Microsoft.Terminal.Control { + enum MarkCategory + { + Prompt = 0, + Error = 1, + Warning = 2, + Info = 3 + }; + + struct ScrollMark + { + // There are other members of DispatchTypes::ScrollMark, but these are + // all we need to expose up and set downwards currently. Additional + // members can be bubbled as necessary. + Microsoft.Terminal.Core.Point Start; + Microsoft.Terminal.Core.Point End; // exclusive + Microsoft.Terminal.Core.OptionalColor Color; + }; + + enum ScrollToMarkDirection + { + Previous, + Next, + First, + Last + }; + // These are properties of the TerminalCore that should be queryable by the // rest of the app. interface ICoreState @@ -27,5 +53,11 @@ namespace Microsoft.Terminal.Control UInt64 OwningHwnd; + void AddMark(ScrollMark mark); + void ClearMark(); + void ClearAllMarks(); + void ScrollToMark(ScrollToMarkDirection direction); + IVector ScrollMarks { get; }; + }; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 5fe54d6accf..53a8f9f7785 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -124,20 +124,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation [weakThis = get_weak()](const auto& update) { if (auto control{ weakThis.get() }; !control->_IsClosing()) { - control->_isInternalScrollBarUpdate = true; - - auto scrollBar = control->ScrollBar(); - if (update.newValue) - { - scrollBar.Value(*update.newValue); - } - scrollBar.Maximum(update.newMaximum); - scrollBar.Minimum(update.newMinimum); - scrollBar.ViewportSize(update.newViewportSize); - // scroll one full screen worth at a time when the scroll bar is clicked - scrollBar.LargeChange(std::max(update.newViewportSize - 1, 0.)); - - control->_isInternalScrollBarUpdate = false; + control->_throttledUpdateScrollbar(update); } }); @@ -148,6 +135,57 @@ namespace winrt::Microsoft::Terminal::Control::implementation _ApplyUISettings(); } + void TermControl::_throttledUpdateScrollbar(const ScrollBarUpdate& update) + { + // Assumptions: + // * we're already not closing + // * caller already checked weak ptr to make sure we're still alive + + _isInternalScrollBarUpdate = true; + + auto scrollBar = ScrollBar(); + if (update.newValue) + { + scrollBar.Value(*update.newValue); + } + scrollBar.Maximum(update.newMaximum); + scrollBar.Minimum(update.newMinimum); + scrollBar.ViewportSize(update.newViewportSize); + // scroll one full screen worth at a time when the scroll bar is clicked + scrollBar.LargeChange(std::max(update.newViewportSize - 1, 0.)); + + _isInternalScrollBarUpdate = false; + + if (_showMarksInScrollbar) + { + // Update scrollbar marks + ScrollBarCanvas().Children().Clear(); + const auto marks{ _core.ScrollMarks() }; + const auto fullHeight{ ScrollBarCanvas().ActualHeight() }; + const auto totalBufferRows{ update.newMaximum + update.newViewportSize }; + + for (const auto m : marks) + { + Windows::UI::Xaml::Shapes::Rectangle r; + Media::SolidColorBrush brush{}; + // Sneaky: technically, a mark doesn't need to have a color set, + // it might want to just use the color from the palette for that + // kind of mark. Fortunately, ControlCore is kind enough to + // pre-evaluate that for us, and shove the real value into the + // Color member, regardless if the mark has a literal value set. + brush.Color(static_cast(m.Color.Color)); + r.Fill(brush); + r.Width(16.0f / 3.0f); // pip width - 1/3rd of the scrollbar width. + r.Height(2); + const auto markRow = m.Start.Y; + const auto fractionalHeight = markRow / totalBufferRows; + const auto relativePos = fractionalHeight * fullHeight; + ScrollBarCanvas().Children().Append(r); + Windows::UI::Xaml::Controls::Canvas::SetTop(r, relativePos); + } + } + } + // Method Description: // - Loads the search box from the xaml UI and focuses it. void TermControl::CreateSearchBoxControl() @@ -404,6 +442,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation newMargin.Right, newMargin.Bottom }); } + + _showMarksInScrollbar = settings.ShowMarks(); + // Clear out all the current marks + ScrollBarCanvas().Children().Clear(); + // When we hot reload the settings, the core will send us a scrollbar + // update. If we enabled scrollbar marks, then great, when we handle + // that message, we'll redraw them. } // Method Description: @@ -2863,4 +2908,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation return _core.OwningHwnd(); } + void TermControl::AddMark(const Control::ScrollMark& mark) + { + _core.AddMark(mark); + } + void TermControl::ClearMark() { _core.ClearMark(); } + void TermControl::ClearAllMarks() { _core.ClearAllMarks(); } + void TermControl::ScrollToMark(const Control::ScrollToMarkDirection& direction) { _core.ScrollToMark(direction); } + + Windows::Foundation::Collections::IVector TermControl::ScrollMarks() const + { + return _core.ScrollMarks(); + } + } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 8816472e016..de091b67484 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -67,6 +67,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation uint64_t OwningHwnd(); void OwningHwnd(uint64_t owner); + + Windows::Foundation::Collections::IVector ScrollMarks() const; + void AddMark(const Control::ScrollMark& mark); + void ClearMark(); + void ClearAllMarks(); + void ScrollToMark(const Control::ScrollToMarkDirection& direction); + #pragma endregion void ScrollViewport(int viewTop); @@ -195,6 +202,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::optional _blinkTimer; winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; + bool _showMarksInScrollbar{ false }; inline bool _IsClosing() const noexcept { @@ -287,6 +295,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args); void _coreWarningBell(const IInspectable& sender, const IInspectable& args); void _coreFoundMatch(const IInspectable& sender, const Control::FoundResultsArgs& args); + void _throttledUpdateScrollbar(const ScrollBarUpdate& update); }; } diff --git a/src/cascadia/TerminalControl/TermControl.xaml b/src/cascadia/TerminalControl/TermControl.xaml index 94afdb9c438..dcb24c353b3 100644 --- a/src/cascadia/TerminalControl/TermControl.xaml +++ b/src/cascadia/TerminalControl/TermControl.xaml @@ -1243,6 +1243,30 @@ Style="{StaticResource ForkedScrollbarTemplate}" ValueChanged="_ScrollbarChangeHandler" ViewportSize="10" /> + + + + + + + + + + + + + + #include #include +#include #include #include diff --git a/src/cascadia/TerminalCore/ICoreAppearance.idl b/src/cascadia/TerminalCore/ICoreAppearance.idl index 131410be780..5e5ed3ff721 100644 --- a/src/cascadia/TerminalCore/ICoreAppearance.idl +++ b/src/cascadia/TerminalCore/ICoreAppearance.idl @@ -24,6 +24,15 @@ namespace Microsoft.Terminal.Core UInt8 A; }; + // Yes, this is also just an IReference. However, IReference has some + // weird ownership semantics that just make it a pain for something as + // simple as "maybe this color doesn't have a value set". + struct OptionalColor + { + Boolean HasValue; + Microsoft.Terminal.Core.Color Color; + }; + // TerminalCore declares its own Color struct to avoid depending on // Windows.UI. Windows.Foundation.Point also exists, but it's composed of // floating-point coordinates, when we almost always need integer coordinates. diff --git a/src/cascadia/TerminalCore/ICoreSettings.idl b/src/cascadia/TerminalCore/ICoreSettings.idl index 5b05a72c05e..1f3c78aa09b 100644 --- a/src/cascadia/TerminalCore/ICoreSettings.idl +++ b/src/cascadia/TerminalCore/ICoreSettings.idl @@ -26,6 +26,9 @@ namespace Microsoft.Terminal.Core Windows.Foundation.IReference TabColor; Windows.Foundation.IReference StartingTabColor; + + Boolean AutoMarkPrompts; + }; } diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index bc4b01e608d..cead8dd5d87 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -49,7 +49,8 @@ Terminal::Terminal() : _selection{ std::nullopt }, _taskbarState{ 0 }, _taskbarProgress{ 0 }, - _trimBlockSelection{ false } + _trimBlockSelection{ false }, + _autoMarkPrompts{ false } { auto passAlongInput = [&](std::deque>& inEventsToWrite) { if (!_pfnWriteInput) @@ -121,6 +122,7 @@ void Terminal::UpdateSettings(ICoreSettings settings) _suppressApplicationTitle = settings.SuppressApplicationTitle(); _startingTitle = settings.StartingTitle(); _trimBlockSelection = settings.TrimBlockSelection(); + _autoMarkPrompts = settings.AutoMarkPrompts(); _terminalInput->ForceDisableWin32InputMode(settings.ForceVTInput()); @@ -211,6 +213,11 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance) } _defaultCursorShape = cursorShape; + + // Tell the control that the scrollbar has somehow changed. Used as a + // workaround to force the control to redraw any scrollbar marks whose color + // may have changed. + _NotifyScrollEvent(); } void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) @@ -750,6 +757,22 @@ bool Terminal::SendCharEvent(const wchar_t ch, const WORD scanCode, const Contro vkey = _VirtualKeyFromCharacter(ch); } + // GH#1527: When the user has auto mark prompts enabled, we're going to try + // and heuristically detect if this was the line the prompt was on. + // * If the key was an Enter keypress (Terminal.app also marks ^C keypresses + // as prompts. That's omitted for now.) + // * AND we're not in the alt buffer + // + // Then treat this line like it's a prompt mark. + if (_autoMarkPrompts && vkey == VK_RETURN && !_inAltBuffer()) + { + DispatchTypes::ScrollMark mark; + mark.category = DispatchTypes::MarkCategory::Prompt; + // Don't set the color - we'll automatically use the DEFAULT_FOREGROUND + // color for any MarkCategory::Prompt marks without one set. + AddMark(mark); + } + // Unfortunately, the UI doesn't give us both a character down and a // character up event, only a character received event. So fake sending both // to the terminal input translator. Unless it's in win32-input-mode, it'll @@ -1198,6 +1221,17 @@ void Terminal::_AdjustCursorPosition(const til::point proposedPosition) if (rowsPushedOffTopOfBuffer != 0) { + if (_scrollMarks.size() > 0) + { + for (auto& mark : _scrollMarks) + { + mark.start.y -= rowsPushedOffTopOfBuffer; + } + _scrollMarks.erase(std::remove_if(_scrollMarks.begin(), + _scrollMarks.end(), + [](const VirtualTerminal::DispatchTypes::ScrollMark& m) { return m.start.y < 0; }), + _scrollMarks.end()); + } // We have to report the delta here because we might have circled the text buffer. // That didn't change the viewport and therefore the TriggerScroll(void) // method can't detect the delta on its own. @@ -1450,6 +1484,11 @@ void Terminal::ApplyScheme(const Scheme& colorScheme) _renderSettings.SetColorTableEntry(TextColor::CURSOR_COLOR, til::color{ colorScheme.CursorColor }); _renderSettings.MakeAdjustedColorArray(); + + // Tell the control that the scrollbar has somehow changed. Used as a + // workaround to force the control to redraw any scrollbar marks whose color + // may have changed. + _NotifyScrollEvent(); } bool Terminal::_inAltBuffer() const noexcept @@ -1476,3 +1515,101 @@ void Terminal::_updateUrlDetection() ClearPatternTree(); } } + +void Terminal::AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark, + const til::point& start, + const til::point& end) +{ + if (_inAltBuffer()) + { + return; + } + + DispatchTypes::ScrollMark m = mark; + m.start = start; + m.end = end; + + _scrollMarks.push_back(m); + + // Tell the control that the scrollbar has somehow changed. Used as a + // workaround to force the control to redraw any scrollbar marks + _NotifyScrollEvent(); +} + +void Terminal::ClearMark() +{ + // Look for one where the cursor is, or where the selection is if we have + // one. Any mark that intersects the cursor/selection, on either side + // (inclusive), will get cleared. + const til::point cursor{ _activeBuffer().GetCursor().GetPosition() }; + til::point start{ cursor }; + til::point end{ cursor }; + + if (IsSelectionActive()) + { + start = til::point{ GetSelectionAnchor() }; + end = til::point{ GetSelectionEnd() }; + } + + _scrollMarks.erase(std::remove_if(_scrollMarks.begin(), + _scrollMarks.end(), + [&start, &end](const auto& m) { + return (m.start >= start && m.start <= end) || + (m.end >= start && m.end <= end); + }), + _scrollMarks.end()); + + // Tell the control that the scrollbar has somehow changed. Used as a + // workaround to force the control to redraw any scrollbar marks + _NotifyScrollEvent(); +} +void Terminal::ClearAllMarks() +{ + _scrollMarks.clear(); + // Tell the control that the scrollbar has somehow changed. Used as a + // workaround to force the control to redraw any scrollbar marks + _NotifyScrollEvent(); +} + +const std::vector& Terminal::GetScrollMarks() const +{ + // TODO: GH#11000 - when the marks are stored per-buffer, get rid of this. + // We want to return _no_ marks when we're in the alt buffer, to effectively + // hide them. We need to return a reference, so we can't just ctor an empty + // list here just for when we're in the alt buffer. + static std::vector _altBufferMarks{}; + return _inAltBuffer() ? _altBufferMarks : _scrollMarks; +} + +til::color Terminal::GetColorForMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) const +{ + if (mark.color.has_value()) + { + return *mark.color; + } + + switch (mark.category) + { + case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Prompt: + { + return _renderSettings.GetColorAlias(ColorAlias::DefaultForeground); + } + case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Error: + { + return _renderSettings.GetColorTableEntry(TextColor::BRIGHT_RED); + } + case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Warning: + { + return _renderSettings.GetColorTableEntry(TextColor::BRIGHT_YELLOW); + } + case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Success: + { + return _renderSettings.GetColorTableEntry(TextColor::BRIGHT_GREEN); + } + default: + case Microsoft::Console::VirtualTerminal::DispatchTypes::MarkCategory::Info: + { + return _renderSettings.GetColorAlias(ColorAlias::DefaultForeground); + } + } +} diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 509f2c326c6..ba4c43d34cd 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -102,6 +102,11 @@ class Microsoft::Terminal::Core::Terminal final : RenderSettings& GetRenderSettings() noexcept { return _renderSettings; }; const RenderSettings& GetRenderSettings() const noexcept { return _renderSettings; }; + const std::vector& GetScrollMarks() const; + void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark, + const til::point& start, + const til::point& end); + #pragma region ITerminalApi // These methods are defined in TerminalApi.cpp void PrintString(const std::wstring_view string) override; @@ -129,11 +134,18 @@ class Microsoft::Terminal::Core::Terminal final : void ShowWindow(bool showOrHide) override; void UseAlternateScreenBuffer() override; void UseMainScreenBuffer() override; + + void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) override; + bool IsConsolePty() const override; bool IsVtInputEnabled() const override; void NotifyAccessibilityChange(const til::rect& changedRect) override; #pragma endregion + void ClearMark(); + void ClearAllMarks(); + til::color GetColorForMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) const; + #pragma region ITerminalInput // These methods are defined in Terminal.cpp bool SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states, const bool keyDown) override; @@ -290,6 +302,7 @@ class Microsoft::Terminal::Core::Terminal final : bool _suppressApplicationTitle; bool _bracketedPasteMode; bool _trimBlockSelection; + bool _autoMarkPrompts; size_t _taskbarState; size_t _taskbarProgress; @@ -356,6 +369,8 @@ class Microsoft::Terminal::Core::Terminal final : }; std::optional _lastKeyEventCodes; + std::vector _scrollMarks; + static WORD _ScanCodeFromVirtualKey(const WORD vkey) noexcept; static WORD _VirtualKeyFromScanCode(const WORD scanCode) noexcept; static WORD _VirtualKeyFromCharacter(const wchar_t ch) noexcept; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index 06df2d809ce..01894b0522d 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -298,6 +298,12 @@ void Terminal::UseMainScreenBuffer() CATCH_LOG(); } +void Terminal::AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) +{ + const til::point cursorPos{ _activeBuffer().GetCursor().GetPosition() }; + AddMark(mark, cursorPos, cursorPos); +} + // Method Description: // - Reacts to a client asking us to show or hide the window. // Arguments: diff --git a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp index 148d77fb376..1b49cc3dd4c 100644 --- a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp @@ -39,6 +39,10 @@ static constexpr std::string_view ScrollUpKey{ "scrollUp" }; static constexpr std::string_view ScrollUpPageKey{ "scrollUpPage" }; static constexpr std::string_view ScrollToTopKey{ "scrollToTop" }; static constexpr std::string_view ScrollToBottomKey{ "scrollToBottom" }; +static constexpr std::string_view ScrollToMarkKey{ "scrollToMark" }; +static constexpr std::string_view AddMarkKey{ "addMark" }; +static constexpr std::string_view ClearMarkKey{ "clearMark" }; +static constexpr std::string_view ClearAllMarksKey{ "clearAllMarks" }; static constexpr std::string_view SendInputKey{ "sendInput" }; static constexpr std::string_view SetColorSchemeKey{ "setColorScheme" }; static constexpr std::string_view SetTabColorKey{ "setTabColor" }; @@ -354,6 +358,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { ShortcutAction::ScrollUpPage, RS_(L"ScrollUpPageCommandKey") }, { ShortcutAction::ScrollToTop, RS_(L"ScrollToTopCommandKey") }, { ShortcutAction::ScrollToBottom, RS_(L"ScrollToBottomCommandKey") }, + { ShortcutAction::ScrollToMark, RS_(L"ScrollToPreviousMarkCommandKey") }, + { ShortcutAction::AddMark, RS_(L"AddMarkCommandKey") }, + { ShortcutAction::ClearMark, RS_(L"ClearMarkCommandKey") }, + { ShortcutAction::ClearAllMarks, RS_(L"ClearAllMarksCommandKey") }, { ShortcutAction::SendInput, L"" }, { ShortcutAction::SetColorScheme, L"" }, { ShortcutAction::SetTabColor, RS_(L"ResetTabColorCommandKey") }, diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp index 42898ee1668..3b3c56543a1 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp @@ -29,6 +29,8 @@ #include "CloseTabsAfterArgs.g.cpp" #include "CloseTabArgs.g.cpp" #include "MoveTabArgs.g.cpp" +#include "ScrollToMarkArgs.g.cpp" +#include "AddMarkArgs.g.cpp" #include "FindMatchArgs.g.cpp" #include "ToggleCommandPaletteArgs.g.cpp" #include "NewWindowArgs.g.cpp" @@ -611,6 +613,38 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation return RS_(L"ScrollDownCommandKey"); } + winrt::hstring ScrollToMarkArgs::GenerateName() const + { + switch (Direction()) + { + case Microsoft::Terminal::Control::ScrollToMarkDirection::Last: + return winrt::hstring{ RS_(L"ScrollToLastMarkCommandKey") }; + case Microsoft::Terminal::Control::ScrollToMarkDirection::First: + return winrt::hstring{ RS_(L"ScrollToFirstMarkCommandKey") }; + case Microsoft::Terminal::Control::ScrollToMarkDirection::Next: + return winrt::hstring{ RS_(L"ScrollToNextMarkCommandKey") }; + case Microsoft::Terminal::Control::ScrollToMarkDirection::Previous: + default: + return winrt::hstring{ RS_(L"ScrollToPreviousMarkCommandKey") }; + } + return winrt::hstring{ RS_(L"ScrollToPreviousMarkCommandKey") }; + } + + winrt::hstring AddMarkArgs::GenerateName() const + { + if (Color()) + { + return winrt::hstring{ + fmt::format(std::wstring_view(RS_(L"AddMarkWithColorCommandKey")), + til::color{ Color().Value() }.ToHexString(true)) + }; + } + else + { + return RS_(L"AddMarkCommandKey"); + } + } + winrt::hstring MoveTabArgs::GenerateName() const { winrt::hstring directionString; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index 05bd831a3ae..03f69252561 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -30,6 +30,8 @@ #include "CloseTabArgs.g.h" #include "ScrollUpArgs.g.h" #include "ScrollDownArgs.g.h" +#include "ScrollToMarkArgs.g.h" +#include "AddMarkArgs.g.h" #include "MoveTabArgs.g.h" #include "ToggleCommandPaletteArgs.g.h" #include "FindMatchArgs.g.h" @@ -180,6 +182,14 @@ private: #define SCROLL_DOWN_ARGS(X) \ X(Windows::Foundation::IReference, RowsToScroll, "rowsToScroll", false, nullptr) +//////////////////////////////////////////////////////////////////////////////// +#define SCROLL_TO_MARK_ARGS(X) \ + X(Microsoft::Terminal::Control::ScrollToMarkDirection, Direction, "direction", false, Microsoft::Terminal::Control::ScrollToMarkDirection::Previous) + +//////////////////////////////////////////////////////////////////////////////// +#define ADD_MARK_ARGS(X) \ + X(Windows::Foundation::IReference, Color, "color", false, nullptr) + //////////////////////////////////////////////////////////////////////////////// #define TOGGLE_COMMAND_PALETTE_ARGS(X) \ X(CommandPaletteLaunchMode, LaunchMode, "launchMode", false, CommandPaletteLaunchMode::Action) @@ -612,6 +622,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation ACTION_ARGS_STRUCT(ScrollDownArgs, SCROLL_DOWN_ARGS); + ACTION_ARGS_STRUCT(ScrollToMarkArgs, SCROLL_TO_MARK_ARGS); + + ACTION_ARGS_STRUCT(AddMarkArgs, ADD_MARK_ARGS); + ACTION_ARGS_STRUCT(ToggleCommandPaletteArgs, TOGGLE_COMMAND_PALETTE_ARGS); ACTION_ARGS_STRUCT(FindMatchArgs, FIND_MATCH_ARGS); diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index ddc05c28dc9..77c817315b6 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -290,6 +290,17 @@ namespace Microsoft.Terminal.Settings.Model Windows.Foundation.IReference RowsToScroll { get; }; }; + + [default_interface] runtimeclass ScrollToMarkArgs : IActionArgs + { + Microsoft.Terminal.Control.ScrollToMarkDirection Direction { get; }; + }; + + [default_interface] runtimeclass AddMarkArgs : IActionArgs + { + Windows.Foundation.IReference Color { get; }; + }; + [default_interface] runtimeclass ToggleCommandPaletteArgs : IActionArgs { CommandPaletteLaunchMode LaunchMode { get; }; diff --git a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h index d6a23dc203d..c9bd6bd2076 100644 --- a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h +++ b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h @@ -47,6 +47,10 @@ ON_ALL_ACTIONS(ScrollDownPage) \ ON_ALL_ACTIONS(ScrollToTop) \ ON_ALL_ACTIONS(ScrollToBottom) \ + ON_ALL_ACTIONS(ScrollToMark) \ + ON_ALL_ACTIONS(AddMark) \ + ON_ALL_ACTIONS(ClearMark) \ + ON_ALL_ACTIONS(ClearAllMarks) \ ON_ALL_ACTIONS(ResizePane) \ ON_ALL_ACTIONS(MoveFocus) \ ON_ALL_ACTIONS(MovePane) \ @@ -119,6 +123,8 @@ ON_ALL_ACTIONS_WITH_ARGS(ResizePane) \ ON_ALL_ACTIONS_WITH_ARGS(ScrollDown) \ ON_ALL_ACTIONS_WITH_ARGS(ScrollUp) \ + ON_ALL_ACTIONS_WITH_ARGS(ScrollToMark) \ + ON_ALL_ACTIONS_WITH_ARGS(AddMark) \ ON_ALL_ACTIONS_WITH_ARGS(SendInput) \ ON_ALL_ACTIONS_WITH_ARGS(SetColorScheme) \ ON_ALL_ACTIONS_WITH_ARGS(SetTabColor) \ diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index 5c90f6e5fb3..e425bdfd877 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -78,7 +78,9 @@ Author(s): X(bool, UseAtlasEngine, "experimental.useAtlasEngine", false) \ X(Windows::Foundation::Collections::IVector, BellSound, "bellSound", nullptr) \ X(bool, Elevate, "elevate", false) \ - X(bool, VtPassthrough, "experimental.connection.passthroughMode", false) + X(bool, VtPassthrough, "experimental.connection.passthroughMode", false) \ + X(bool, AutoMarkPrompts, "experimental.autoMarkPrompts", false) \ + X(bool, ShowMarks, "experimental.showMarksOnScrollbar", false) // Intentionally omitted Profile settings: // * Name diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index f8f3dc8d1cd..76357b65898 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -84,5 +84,7 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_PROFILE_SETTING(Windows.Foundation.Collections.IVector, BellSound); INHERITABLE_PROFILE_SETTING(Boolean, Elevate); + INHERITABLE_PROFILE_SETTING(Boolean, AutoMarkPrompts); + INHERITABLE_PROFILE_SETTING(Boolean, ShowMarks); } } diff --git a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw index ec3868faa5c..9b7e6fbe661 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw @@ -368,6 +368,31 @@ Scroll to the bottom of history + + Scroll to the the previous mark + + + Scroll to the next mark + + + Scroll to the first mark + + + Scroll to the last mark + + + Add a scroll mark + + + Add a scroll mark, color:{0} + {Locked="color"}. "color" is a literal parameter name that shouldn't be translated. {0} will be replaced with a color in hexadecimal format, like `#123456` + + + Clear mark + + + Clear all marks + Send Input: "{0}" {0} will be replaced with a string of input as defined by the user @@ -536,4 +561,4 @@ Toggle block selection - \ No newline at end of file + diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp index e8f0aa3d2ce..0ba57857303 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp @@ -281,6 +281,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } _Elevate = profile.Elevate(); + _AutoMarkPrompts = Feature_ScrollbarMarks::IsEnabled() && profile.AutoMarkPrompts(); + _ShowMarks = Feature_ScrollbarMarks::IsEnabled() && profile.ShowMarks(); } // Method Description: diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.h b/src/cascadia/TerminalSettingsModel/TerminalSettings.h index 3b5ca2d0852..9786af8aa03 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.h @@ -158,6 +158,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::TerminalSettings, bool, Elevate, false); + INHERITABLE_SETTING(Model::TerminalSettings, bool, AutoMarkPrompts, false); + INHERITABLE_SETTING(Model::TerminalSettings, bool, ShowMarks, false); + private: std::optional> _ColorTable; gsl::span _getColorTableImpl(); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index 65df15cdbd5..9dd273ee3c9 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -546,3 +546,14 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage) pair_type{ "setAsDefault", ValueType::SetAsDefault }, }; }; + +// Possible ScrollToMarkDirection values +JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::ScrollToMarkDirection) +{ + JSON_MAPPINGS(4) = { + pair_type{ "previous", ValueType::Previous }, + pair_type{ "next", ValueType::Next }, + pair_type{ "first", ValueType::First }, + pair_type{ "last", ValueType::Last }, + }; +}; diff --git a/src/cascadia/inc/ControlProperties.h b/src/cascadia/inc/ControlProperties.h index f9c880e83db..6d3b42a4dbd 100644 --- a/src/cascadia/inc/ControlProperties.h +++ b/src/cascadia/inc/ControlProperties.h @@ -46,7 +46,8 @@ X(bool, ForceVTInput, false) \ X(winrt::hstring, StartingTitle) \ X(bool, DetectURLs, true) \ - X(bool, VtPassthrough, false) + X(bool, VtPassthrough, false) \ + X(bool, AutoMarkPrompts) // --------------------------- Control Settings --------------------------- // All of these settings are defined in IControlSettings. @@ -68,5 +69,6 @@ X(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \ X(bool, ForceFullRepaintRendering, false) \ X(bool, SoftwareRendering, false) \ + X(bool, UseAtlasEngine, false) \ X(bool, UseBackgroundImageForWindow, false) \ - X(bool, UseAtlasEngine, false) + X(bool, ShowMarks, false) diff --git a/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest b/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest index 8e1afe241f0..8a61b53a59d 100644 --- a/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest +++ b/src/cascadia/ut_app/TerminalApp.Unit.Tests.manifest @@ -27,6 +27,7 @@ PerMonitorV2 true + SegmentHeap diff --git a/src/features.xml b/src/features.xml index 985297e10f4..cbe55f3a5ad 100644 --- a/src/features.xml +++ b/src/features.xml @@ -116,4 +116,16 @@ Preview + + + Feature_ScrollbarMarks + Enables the experimental scrollbar marks feature. + AlwaysDisabled + + + Dev + Preview + + + diff --git a/src/host/outputStream.cpp b/src/host/outputStream.cpp index e91241336d3..900869af2a8 100644 --- a/src/host/outputStream.cpp +++ b/src/host/outputStream.cpp @@ -481,3 +481,8 @@ void ConhostInternalGetSet::NotifyAccessibilityChange(const til::rect& changedRe changedRect.bottom - 1); } } + +void ConhostInternalGetSet::AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& /*mark*/) +{ + // Not implemented for conhost. +} diff --git a/src/host/outputStream.hpp b/src/host/outputStream.hpp index 9a3bc2a0bdd..2acd85ae295 100644 --- a/src/host/outputStream.hpp +++ b/src/host/outputStream.hpp @@ -74,6 +74,8 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal:: void NotifyAccessibilityChange(const til::rect& changedRect) override; + void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) override; + private: Microsoft::Console::IIoProvider& _io; }; diff --git a/src/terminal/adapter/DispatchTypes.hpp b/src/terminal/adapter/DispatchTypes.hpp index 2ae3b67a6ab..afa1de0f797 100644 --- a/src/terminal/adapter/DispatchTypes.hpp +++ b/src/terminal/adapter/DispatchTypes.hpp @@ -496,4 +496,22 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes constexpr VTInt s_sDECCOLMSetColumns = 132; constexpr VTInt s_sDECCOLMResetColumns = 80; + enum class MarkCategory : size_t + { + Prompt = 0, + Error = 1, + Warning = 2, + Success = 3, + Info = 4 + }; + + struct ScrollMark + { + std::optional color; + til::point start; + til::point end; // exclusive + MarkCategory category{ MarkCategory::Info }; + // Other things we may want to think about in the future are listed in + // GH#11000 + }; } diff --git a/src/terminal/adapter/ITermDispatch.hpp b/src/terminal/adapter/ITermDispatch.hpp index bf6cdbbb934..17c7374c309 100644 --- a/src/terminal/adapter/ITermDispatch.hpp +++ b/src/terminal/adapter/ITermDispatch.hpp @@ -135,6 +135,8 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch virtual bool DoConEmuAction(const std::wstring_view string) = 0; + virtual bool DoITerm2Action(const std::wstring_view string) = 0; + virtual StringHandler DownloadDRCS(const VTInt fontNumber, const VTParameter startChar, const DispatchTypes::DrcsEraseControl eraseControl, diff --git a/src/terminal/adapter/ITerminalApi.hpp b/src/terminal/adapter/ITerminalApi.hpp index 277a07fafdc..32910133560 100644 --- a/src/terminal/adapter/ITerminalApi.hpp +++ b/src/terminal/adapter/ITerminalApi.hpp @@ -76,5 +76,7 @@ namespace Microsoft::Console::VirtualTerminal virtual bool IsConsolePty() const = 0; virtual void NotifyAccessibilityChange(const til::rect& changedRect) = 0; + + virtual void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark) = 0; }; } diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index 0531b4aef66..a94b4f0c6a4 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -2465,6 +2465,50 @@ bool AdaptDispatch::DoConEmuAction(const std::wstring_view string) return false; } +// Method Description: +// - Performs a iTerm2 action +// - Ascribes to the ITermDispatch interface +// - Currently, the actions we support are: +// * `OSC1337;SetMark`: mark a line as a prompt line +// - Not actually used in conhost +// Arguments: +// - string: contains the parameters that define which action we do +// Return Value: +// - false in conhost, true for the SetMark action, otherwise false. +bool AdaptDispatch::DoITerm2Action(const std::wstring_view string) +{ + // This is not implemented in conhost. + if (_api.IsConsolePty()) + { + // Flush the frame manually, to make sure marks end up on the right line, like the alt buffer sequence. + _renderer.TriggerFlush(false); + return false; + } + + if constexpr (!Feature_ScrollbarMarks::IsEnabled()) + { + return false; + } + + const auto parts = Utils::SplitString(string, L';'); + + if (parts.size() < 1) + { + return false; + } + + const auto action = til::at(parts, 0); + + if (action == L"SetMark") + { + DispatchTypes::ScrollMark mark; + mark.category = DispatchTypes::MarkCategory::Prompt; + _api.AddMark(mark); + return true; + } + return false; +} + // Method Description: // - DECDLD - Downloads one or more characters of a dynamically redefinable // character set (DRCS) with a specified pixel pattern. The pixel array is diff --git a/src/terminal/adapter/adaptDispatch.hpp b/src/terminal/adapter/adaptDispatch.hpp index 41e91885e25..ca6a221fc76 100644 --- a/src/terminal/adapter/adaptDispatch.hpp +++ b/src/terminal/adapter/adaptDispatch.hpp @@ -130,6 +130,8 @@ namespace Microsoft::Console::VirtualTerminal bool DoConEmuAction(const std::wstring_view string) override; + bool DoITerm2Action(const std::wstring_view string) override; + StringHandler DownloadDRCS(const VTInt fontNumber, const VTParameter startChar, const DispatchTypes::DrcsEraseControl eraseControl, diff --git a/src/terminal/adapter/termDispatch.hpp b/src/terminal/adapter/termDispatch.hpp index 6da351861f2..49c690aabbd 100644 --- a/src/terminal/adapter/termDispatch.hpp +++ b/src/terminal/adapter/termDispatch.hpp @@ -128,6 +128,8 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons bool DoConEmuAction(const std::wstring_view /*string*/) override { return false; } + bool DoITerm2Action(const std::wstring_view /*string*/) override { return false; } + StringHandler DownloadDRCS(const VTInt /*fontNumber*/, const VTParameter /*startChar*/, const DispatchTypes::DrcsEraseControl /*eraseControl*/, diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index 8475f181542..64454ca0367 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -237,6 +237,11 @@ class TestGetSet final : public ITerminalApi Log::Comment(L"NotifyAccessibilityChange MOCK called..."); } + void AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& /*mark*/) override + { + Log::Comment(L"AddMark MOCK called..."); + } + void PrepData() { PrepData(CursorDirection::UP); // if called like this, the cursor direction doesn't matter. diff --git a/src/terminal/parser/OutputStateMachineEngine.cpp b/src/terminal/parser/OutputStateMachineEngine.cpp index 5e0a9e14f3d..08972476e7e 100644 --- a/src/terminal/parser/OutputStateMachineEngine.cpp +++ b/src/terminal/parser/OutputStateMachineEngine.cpp @@ -837,6 +837,11 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/, success = _dispatch->DoConEmuAction(string); break; } + case OscActionCodes::ITerm2Action: + { + success = _dispatch->DoITerm2Action(string); + break; + } default: // If no functions to call, overall dispatch was a failure. success = false; diff --git a/src/terminal/parser/OutputStateMachineEngine.hpp b/src/terminal/parser/OutputStateMachineEngine.hpp index 21055d09bc1..f37843e2495 100644 --- a/src/terminal/parser/OutputStateMachineEngine.hpp +++ b/src/terminal/parser/OutputStateMachineEngine.hpp @@ -187,7 +187,8 @@ namespace Microsoft::Console::VirtualTerminal SetClipboard = 52, ResetForegroundColor = 110, // Not implemented ResetBackgroundColor = 111, // Not implemented - ResetCursorColor = 112 + ResetCursorColor = 112, + ITerm2Action = 1337, }; bool _GetOscTitle(const std::wstring_view string,