diff --git a/src/cascadia/TerminalCore/ITerminalApi.hpp b/src/cascadia/TerminalCore/ITerminalApi.hpp index 2bb6376a9..24e484ddf 100644 --- a/src/cascadia/TerminalCore/ITerminalApi.hpp +++ b/src/cascadia/TerminalCore/ITerminalApi.hpp @@ -67,7 +67,7 @@ namespace Microsoft::Terminal::Core virtual bool AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept = 0; virtual bool EndHyperlink() noexcept = 0; - virtual bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept = 0; + virtual bool SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) noexcept = 0; virtual bool SetWorkingDirectory(std::wstring_view uri) noexcept = 0; virtual std::wstring_view GetWorkingDirectory() noexcept = 0; diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 9516f7320..502bfd1b1 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -17,6 +17,8 @@ #include "../../cascadia/terminalcore/ITerminalApi.hpp" #include "../../cascadia/terminalcore/ITerminalInput.hpp" +static constexpr size_t TaskbarMinProgress{ 10 }; + // You have to forward decl the ICoreSettings here, instead of including the header. // If you include the header, there will be compilation errors with other // headers that include Terminal.hpp @@ -125,7 +127,7 @@ public: bool AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept override; bool EndHyperlink() noexcept override; - bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept override; + bool SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) noexcept override; bool SetWorkingDirectory(std::wstring_view uri) noexcept override; std::wstring_view GetWorkingDirectory() noexcept override; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index f58a143a1..1fc36389d 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -629,10 +629,43 @@ bool Terminal::EndHyperlink() noexcept // - progress: indicates the progress value // Return Value: // - true -bool Terminal::SetTaskbarProgress(const size_t state, const size_t progress) noexcept +bool Terminal::SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) noexcept { - _taskbarState = state; - _taskbarProgress = progress; + _taskbarState = static_cast(state); + + switch (state) + { + case DispatchTypes::TaskbarState::Clear: + // Always set progress to 0 in this case + _taskbarProgress = 0; + break; + case DispatchTypes::TaskbarState::Set: + // Always set progress to the value given in this case + _taskbarProgress = progress; + break; + case DispatchTypes::TaskbarState::Indeterminate: + // Leave the progress value unchanged in this case + break; + case DispatchTypes::TaskbarState::Error: + case DispatchTypes::TaskbarState::Paused: + // In these 2 cases, if the given progress value is 0, then + // leave the progress value unchanged, unless the current progress + // value is 0, in which case set it to a 'minimum' value (10 in our case); + // if the given progress value is greater than 0, then set the progress value + if (progress == 0) + { + if (_taskbarProgress == 0) + { + _taskbarProgress = TaskbarMinProgress; + } + } + else + { + _taskbarProgress = progress; + } + break; + } + if (_pfnTaskbarProgressChanged) { _pfnTaskbarProgressChanged(); diff --git a/src/cascadia/TerminalCore/TerminalDispatch.cpp b/src/cascadia/TerminalCore/TerminalDispatch.cpp index 338c6b2ea..f52776d2e 100644 --- a/src/cascadia/TerminalCore/TerminalDispatch.cpp +++ b/src/cascadia/TerminalCore/TerminalDispatch.cpp @@ -510,7 +510,7 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept { // A state parameter is defined, parse it out const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state); - if (!stateSuccess) + if (!stateSuccess && !til::at(parts, 1).empty()) { return false; } @@ -518,7 +518,7 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept { // A progress parameter is also defined, parse it out const auto progressSuccess = Utils::StringToUint(til::at(parts, 2), progress); - if (!progressSuccess) + if (!progressSuccess && !til::at(parts, 2).empty()) { return false; } @@ -535,7 +535,7 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept // progress is greater than the maximum allowed value, clamp it to the max progress = TaskbarMaxProgress; } - return _terminalApi.SetTaskbarProgress(state, progress); + return _terminalApi.SetTaskbarProgress(static_cast(state), progress); } // 9 is SetWorkingDirectory, which informs the terminal about the current working directory. else if (subParam == 9) diff --git a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp index ecbffd826..e3c63a9cc 100644 --- a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp @@ -388,6 +388,30 @@ void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress() // Additional params should be ignored, state and progress still set normally VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow(1)); VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow(80)); + + // Edge cases + trailing semicolon testing + stateMachine.ProcessString(L"\x1b]9;4;2;\x9c"); + // String should be processed correctly despite the trailing semicolon, + // taskbar progress should remain unchanged from previous value + VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow(2)); + VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow(80)); + + stateMachine.ProcessString(L"\x1b]9;4;3;75\x9c"); + // Given progress value should be ignored because this is the indeterminate state, + // so the progress value should remain unchanged + VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow(3)); + VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow(80)); + + stateMachine.ProcessString(L"\x1b]9;4;0;50\x9c"); + // Taskbar progress should be 0 (the given value should be ignored) + VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow(0)); + VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow(0)); + + stateMachine.ProcessString(L"\x1b]9;4;2;\x9c"); + // String should be processed correctly despite the trailing semicolon, + // taskbar progress should be set to a 'minimum', non-zero value + VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow(2)); + VERIFY_IS_GREATER_THAN(term.GetTaskbarProgress(), gsl::narrow(0)); } void TerminalCoreUnitTests::TerminalApiTest::SetWorkingDirectory() diff --git a/src/terminal/adapter/DispatchTypes.hpp b/src/terminal/adapter/DispatchTypes.hpp index e28dde682..1938791d4 100644 --- a/src/terminal/adapter/DispatchTypes.hpp +++ b/src/terminal/adapter/DispatchTypes.hpp @@ -249,6 +249,15 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes Scrollback = 3 }; + enum class TaskbarState : size_t + { + Clear = 0, + Set = 1, + Error = 2, + Indeterminate = 3, + Paused = 4 + }; + enum GraphicsOptions : size_t { Off = 0,