diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 44b427a48bfb..f61bdaf3a3e7 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1115,6 +1115,13 @@ namespace winrt::TerminalApp::implementation if (profileGuid.has_value()) { const auto settings{ winrt::make(_settings, profileGuid.value(), *_bindings) }; + const auto workingDirectory = terminalTab->GetActiveTerminalControl().WorkingDirectory(); + const auto validWorkingDirectory = !workingDirectory.empty(); + if (validWorkingDirectory) + { + settings.StartingDirectory(workingDirectory); + } + _CreateNewTabFromSettings(profileGuid.value(), settings); } } @@ -1638,6 +1645,12 @@ namespace winrt::TerminalApp::implementation { profileFound = true; controlSettings = { winrt::make(_settings, current_guid.value(), *_bindings) }; + const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory(); + const auto validWorkingDirectory = !workingDirectory.empty(); + if (validWorkingDirectory) + { + controlSettings.StartingDirectory(workingDirectory); + } realGuid = current_guid.value(); } // TODO: GH#5047 - In the future, we should get the Profile of diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index b73735c087f9..44a4e49a6588 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2460,6 +2460,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return _settings.ProfileName(); } + hstring TermControl::WorkingDirectory() const + { + hstring hstr{ _terminal->GetWorkingDirectory() }; + return hstr; + } + // Method Description: // - Given a copy-able selection, get the selected text from the buffer and send it to the // Windows Clipboard (CascadiaWin32:main.cpp). diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index a90bea21cc54..288dea233dc2 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -106,6 +106,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation hstring Title(); hstring GetProfileName() const; + hstring WorkingDirectory() const; bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference& formats); void PasteTextFromClipboard(); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index bbce21748158..59c42773d1e6 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -110,6 +110,8 @@ namespace Microsoft.Terminal.TerminalControl UInt64 TaskbarState { get; }; UInt64 TaskbarProgress { get; }; + String WorkingDirectory { get; }; + Windows.Foundation.IReference TabColor { get; }; event Windows.Foundation.TypedEventHandler TabColorChanged; } diff --git a/src/cascadia/TerminalCore/ITerminalApi.hpp b/src/cascadia/TerminalCore/ITerminalApi.hpp index f9f0f06868df..39cccb83c352 100644 --- a/src/cascadia/TerminalCore/ITerminalApi.hpp +++ b/src/cascadia/TerminalCore/ITerminalApi.hpp @@ -65,6 +65,9 @@ namespace Microsoft::Terminal::Core virtual bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept = 0; + virtual bool SetWorkingDirectory(std::wstring_view uri) noexcept = 0; + virtual std::wstring_view GetWorkingDirectory() noexcept = 0; + protected: ITerminalApi() = default; }; diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 395293f58737..2b19f71e8dfd 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -117,6 +117,8 @@ class Microsoft::Terminal::Core::Terminal final : bool EndHyperlink() noexcept override; bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept override; + bool SetWorkingDirectory(std::wstring_view uri) noexcept override; + std::wstring_view GetWorkingDirectory() noexcept override; #pragma endregion #pragma region ITerminalInput @@ -253,6 +255,7 @@ class Microsoft::Terminal::Core::Terminal final : size_t _hyperlinkPatternId; + std::wstring _workingDirectory; #pragma region Text Selection // a selection is represented as a range between two COORDs (start and end) // the pivot is the COORD that remains selected when you extend a selection in any direction diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index cccd9856a8c2..e5821be1c582 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -618,3 +618,14 @@ bool Terminal::SetTaskbarProgress(const size_t state, const size_t progress) noe } return true; } + +bool Terminal::SetWorkingDirectory(std::wstring_view uri) noexcept +{ + _workingDirectory = uri; + return true; +} + +std::wstring_view Terminal::GetWorkingDirectory() noexcept +{ + return _workingDirectory; +} diff --git a/src/cascadia/TerminalCore/TerminalDispatch.cpp b/src/cascadia/TerminalCore/TerminalDispatch.cpp index fd74ab690cf8..8485ed89d565 100644 --- a/src/cascadia/TerminalCore/TerminalDispatch.cpp +++ b/src/cascadia/TerminalCore/TerminalDispatch.cpp @@ -417,43 +417,55 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept const auto parts = Utils::SplitString(string, L';'); unsigned int subParam = 0; - // For now, the only ConEmu action we support is setting the taskbar state/progress, - // which has a sub param value of 4 - if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam) || subParam != 4) + if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam)) { return false; } - if (parts.size() >= 2) + // 4 is SetProgressBar, which sets the taskbar state/progress. + if (subParam == 4) { - // A state parameter is defined, parse it out - const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state); - if (!stateSuccess) + if (parts.size() >= 2) { - 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) + // A state parameter is defined, parse it out + const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state); + if (!stateSuccess) { 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) + { + return false; + } + } } - } - if (state > TaskbarMaxState) - { - // state is out of bounds, return false - 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; + } + return _terminalApi.SetTaskbarProgress(state, progress); } - if (progress > TaskbarMaxProgress) + // 9 is SetWorkingDirectory, which informs the terminal about the current working directory. + else if (subParam == 9) { - // progress is greater than the maximum allowed value, clamp it to the max - progress = TaskbarMaxProgress; + if (parts.size() >= 2) + { + return _terminalApi.SetWorkingDirectory(til::at(parts, 1)); + } } - return _terminalApi.SetTaskbarProgress(state, progress); + + return false; } // Routine Description: