From 53ed45c5755168781f1b0f4c9b97f8eaae1094c9 Mon Sep 17 00:00:00 2001 From: Marco Pelagatti <1140981+mpela81@users.noreply.github.com> Date: Fri, 7 Jul 2023 12:50:17 +0200 Subject: [PATCH 1/5] Flag closed connection state on tab --- src/cascadia/TerminalApp/Pane.cpp | 12 +++++++ src/cascadia/TerminalApp/Pane.h | 1 + .../TerminalApp/TabHeaderControl.xaml | 6 ++++ src/cascadia/TerminalApp/TerminalTab.cpp | 31 +++++++++++++++++++ src/cascadia/TerminalApp/TerminalTab.h | 3 ++ src/cascadia/TerminalApp/TerminalTabStatus.h | 1 + .../TerminalApp/TerminalTabStatus.idl | 1 + 7 files changed, 55 insertions(+) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index c70b3fa27da..936a87c9895 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -1381,6 +1381,18 @@ Profile Pane::GetFocusedProfile() return lastFocused ? lastFocused->_profile : nullptr; } +// Method Description: +// - Gets the connection state of this pane. If this Pane is not a leaf this will +// return NotConnected. +// Arguments: +// - +// Return Value: +// - The connection state of this Pane. +winrt::Microsoft::Terminal::TerminalConnection::ConnectionState Pane::GetConnectionState() const +{ + return _connectionState; +} + // Method Description: // - Returns true if this pane was the last pane to be focused in a tree of panes. // Arguments: diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index a6137534dac..7a5630eda9c 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -75,6 +75,7 @@ class Pane : public std::enable_shared_from_this winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl(); winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl(); winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile(); + winrt::Microsoft::Terminal::TerminalConnection::ConnectionState GetConnectionState() const; // Method Description: // - If this is a leaf pane, return its profile. diff --git a/src/cascadia/TerminalApp/TabHeaderControl.xaml b/src/cascadia/TerminalApp/TabHeaderControl.xaml index 5fde709ecbf..3c5c7f7f053 100644 --- a/src/cascadia/TerminalApp/TabHeaderControl.xaml +++ b/src/cascadia/TerminalApp/TabHeaderControl.xaml @@ -43,6 +43,12 @@ FontSize="12" Glyph="" Visibility="{x:Bind TabStatus.IsReadOnlyActive, Mode=OneWay}" /> + winrt::fire_and_forget { + co_await wil::resume_foreground(dispatcher); + if (auto tab{ weakThis.get() }) + { + tab->_UpdateConnectionClosedState(); + } + }); + events.readOnlyToken = control.ReadOnlyChanged([dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget { co_await wil::resume_foreground(dispatcher); if (auto tab{ weakThis.get() }) @@ -1053,6 +1063,26 @@ namespace winrt::TerminalApp::implementation _TaskbarProgressChangedHandlers(nullptr, nullptr); } + // Method Description: + // - Set an indicator on the tab if any pane is in a closed connection state + // Arguments: + // - + // Return Value: + // - + void TerminalTab::_UpdateConnectionClosedState() + { + ASSERT_UI_THREAD(); + + if (_rootPane) + { + const bool isClosed = _rootPane->WalkTree([&](const auto& p) { + return p->GetConnectionState() >= ConnectionState::Closed; + }); + + _tabStatus.IsConnectionClosed(isClosed); + } + } + // Method Description: // - Mark the given pane as the active pane in this tab. All other panes // will be marked as inactive. We'll also update our own UI state to @@ -1071,6 +1101,7 @@ namespace winrt::TerminalApp::implementation // Update our own title text to match the newly-active pane. UpdateTitle(); _UpdateProgressState(); + _UpdateConnectionClosedState(); // We need to move the pane to the top of our mru list // If its already somewhere in the list, remove it first diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index d7c1cede718..3dcb719d483 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -132,6 +132,7 @@ namespace winrt::TerminalApp::implementation winrt::event_token titleToken; winrt::event_token colorToken; winrt::event_token taskbarToken; + winrt::event_token stateToken; winrt::event_token readOnlyToken; winrt::event_token focusToken; @@ -180,6 +181,8 @@ namespace winrt::TerminalApp::implementation void _UpdateProgressState(); + void _UpdateConnectionClosedState(); + void _DuplicateTab(); virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override; diff --git a/src/cascadia/TerminalApp/TerminalTabStatus.h b/src/cascadia/TerminalApp/TerminalTabStatus.h index 95080935a38..838a909df22 100644 --- a/src/cascadia/TerminalApp/TerminalTabStatus.h +++ b/src/cascadia/TerminalApp/TerminalTabStatus.h @@ -12,6 +12,7 @@ namespace winrt::TerminalApp::implementation TerminalTabStatus() = default; WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); + WINRT_OBSERVABLE_PROPERTY(bool, IsConnectionClosed, _PropertyChangedHandlers); WINRT_OBSERVABLE_PROPERTY(bool, IsPaneZoomed, _PropertyChangedHandlers); WINRT_OBSERVABLE_PROPERTY(bool, IsProgressRingActive, _PropertyChangedHandlers); WINRT_OBSERVABLE_PROPERTY(bool, IsProgressRingIndeterminate, _PropertyChangedHandlers); diff --git a/src/cascadia/TerminalApp/TerminalTabStatus.idl b/src/cascadia/TerminalApp/TerminalTabStatus.idl index 57f4e05fa1a..5dc69ffe59b 100644 --- a/src/cascadia/TerminalApp/TerminalTabStatus.idl +++ b/src/cascadia/TerminalApp/TerminalTabStatus.idl @@ -7,6 +7,7 @@ namespace TerminalApp { TerminalTabStatus(); + Boolean IsConnectionClosed { get; set; }; Boolean IsPaneZoomed { get; set; }; Boolean IsProgressRingActive { get; set; }; Boolean IsProgressRingIndeterminate { get; set; }; From 7310d39b4183e39f04c2949ca099cb14aad52295 Mon Sep 17 00:00:00 2001 From: Marco Pelagatti <1140981+mpela81@users.noreply.github.com> Date: Wed, 12 Jul 2023 01:21:11 +0200 Subject: [PATCH 2/5] Add restart connection to context menu --- src/cascadia/TerminalApp/Resources/en-US/Resources.resw | 5 ++++- src/cascadia/TerminalApp/TerminalPage.cpp | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 80f0a9df574..cd2d24a1db7 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -840,4 +840,7 @@ Run as Administrator This text is displayed on context menu for profile entries in add new tab button. - \ No newline at end of file + + Restart Connection + + diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 8140af22b3e..4516fcdf897 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4664,8 +4664,7 @@ namespace winrt::TerminalApp::implementation const bool withSelection) { // withSelection can be used to add actions that only appear if there's - // selected text, like "search the web". In this initial draft, it's not - // actually augmented by the TerminalPage, so it's left commented out. + // selected text, like "search the web" const auto& menu{ sender.try_as() }; if (!menu) @@ -4718,6 +4717,11 @@ namespace winrt::TerminalApp::implementation makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr }); } + if (const auto& control{ _GetActiveControl() }; control.ConnectionState() >= ConnectionState::Closed) + { + makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr }); + } + if (withSelection) { makeItem(RS_(L"SearchWebText"), L"\xF6FA", ActionAndArgs{ ShortcutAction::SearchForText, nullptr }); From 04efe8fc15c9f63403c8a3fd13f54fa9c8dd9b6f Mon Sep 17 00:00:00 2001 From: Marco Pelagatti <1140981+mpela81@users.noreply.github.com> Date: Sat, 15 Jul 2023 12:48:41 +0200 Subject: [PATCH 3/5] Add Restart Connection to tab context menu --- .../Resources/en-US/Resources.resw | 3 ++ src/cascadia/TerminalApp/TerminalTab.cpp | 39 ++++++++++++++++++- src/cascadia/TerminalApp/TerminalTab.h | 4 +- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index cd2d24a1db7..a513a71d856 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -843,4 +843,7 @@ Restart Connection + + Restart the active pane connection + diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 19b26cda55a..c2e4ee6b326 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -35,6 +35,7 @@ namespace winrt::TerminalApp::implementation _activePane = nullptr; _closePaneMenuItem.Visibility(WUX::Visibility::Collapsed); + _restartConnectionMenuItem.Visibility(WUX::Visibility::Collapsed); auto firstId = _nextPaneId; @@ -1064,7 +1065,8 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Set an indicator on the tab if any pane is in a closed connection state + // - Set an indicator on the tab if any pane is in a closed connection state. + // - Show/hide the Restart Connection context menu entry depending on active pane's state. // Arguments: // - // Return Value: @@ -1081,6 +1083,18 @@ namespace winrt::TerminalApp::implementation _tabStatus.IsConnectionClosed(isClosed); } + + if (_activePane) + { + const bool isClosed = _activePane->GetConnectionState() >= ConnectionState::Closed; + _restartConnectionMenuItem.Visibility(isClosed ? WUX::Visibility::Visible : WUX::Visibility::Collapsed); + } + } + + void TerminalTab::_RestartActivePaneConnection() + { + ActionAndArgs restartConnection{ ShortcutAction::RestartConnection, nullptr }; + _dispatch.DoAction(restartConnection); } // Method Description: @@ -1461,6 +1475,28 @@ namespace winrt::TerminalApp::implementation Automation::AutomationProperties::SetHelpText(findMenuItem, findToolTip); } + Controls::MenuFlyoutItem restartConnectionMenuItem = _restartConnectionMenuItem; + { + // "Restart Connection" + Controls::FontIcon restartConnectionSymbol; + restartConnectionSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); + restartConnectionSymbol.Glyph(L"\xE72C"); + + restartConnectionMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + tab->_RestartActivePaneConnection(); + } + }); + restartConnectionMenuItem.Text(RS_(L"RestartConnectionText")); + restartConnectionMenuItem.Icon(restartConnectionSymbol); + + const auto restartConnectionToolTip = RS_(L"RestartConnectionToolTip"); + + WUX::Controls::ToolTipService::SetToolTip(restartConnectionMenuItem, box_value(restartConnectionToolTip)); + Automation::AutomationProperties::SetHelpText(restartConnectionMenuItem, restartConnectionToolTip); + } + // Build the menu Controls::MenuFlyout contextMenuFlyout; Controls::MenuFlyoutSeparator menuSeparator; @@ -1471,6 +1507,7 @@ namespace winrt::TerminalApp::implementation contextMenuFlyout.Items().Append(moveTabToNewWindowMenuItem); contextMenuFlyout.Items().Append(exportTabMenuItem); contextMenuFlyout.Items().Append(findMenuItem); + contextMenuFlyout.Items().Append(restartConnectionMenuItem); contextMenuFlyout.Items().Append(menuSeparator); // GH#5750 - When the context menu is dismissed with ESC, toss the focus diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index 3dcb719d483..3a4b87ec7c6 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -116,6 +116,7 @@ namespace winrt::TerminalApp::implementation std::shared_ptr _zoomedPane{ nullptr }; Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem; + Windows::UI::Xaml::Controls::MenuFlyoutItem _restartConnectionMenuItem; winrt::hstring _lastIconPath{}; std::optional _runtimeTabColor{}; @@ -155,8 +156,6 @@ namespace winrt::TerminalApp::implementation bool _inRename{ false }; winrt::Windows::UI::Xaml::Controls::TextBox::LayoutUpdated_revoker _tabRenameBoxLayoutUpdatedRevoker; - winrt::TerminalApp::ShortcutActionDispatch _dispatch; - void _Setup(); std::optional _bellIndicatorTimer; @@ -182,6 +181,7 @@ namespace winrt::TerminalApp::implementation void _UpdateProgressState(); void _UpdateConnectionClosedState(); + void _RestartActivePaneConnection(); void _DuplicateTab(); From 536e97e0906625c1d17c17501262f53d060593ce Mon Sep 17 00:00:00 2001 From: Marco Pelagatti <1140981+mpela81@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:26:25 +0200 Subject: [PATCH 4/5] Refactor isConnectionClose --- src/cascadia/TerminalApp/Pane.cpp | 10 +++++----- src/cascadia/TerminalApp/Pane.h | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 7 +++++-- src/cascadia/TerminalApp/TerminalTab.cpp | 7 ++++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 936a87c9895..c12ee640b81 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -1382,15 +1382,15 @@ Profile Pane::GetFocusedProfile() } // Method Description: -// - Gets the connection state of this pane. If this Pane is not a leaf this will -// return NotConnected. +// - Returns true if the connection state of this pane is closed. If this Pane is not a leaf this will +// return false. // Arguments: // - // Return Value: -// - The connection state of this Pane. -winrt::Microsoft::Terminal::TerminalConnection::ConnectionState Pane::GetConnectionState() const +// - true if the connection state of this Pane is closed. +bool Pane::IsConnectionClosed() const { - return _connectionState; + return _connectionState >= ConnectionState::Closed; } // Method Description: diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 7a5630eda9c..68f03db389a 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -75,7 +75,7 @@ class Pane : public std::enable_shared_from_this winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl(); winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl(); winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile(); - winrt::Microsoft::Terminal::TerminalConnection::ConnectionState GetConnectionState() const; + bool IsConnectionClosed() const; // Method Description: // - If this is a leaf pane, return its profile. diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 4516fcdf897..2adcc9cf195 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4717,9 +4717,12 @@ namespace winrt::TerminalApp::implementation makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr }); } - if (const auto& control{ _GetActiveControl() }; control.ConnectionState() >= ConnectionState::Closed) + if (const auto pane{ _GetFocusedTabImpl()->GetActivePane() }) { - makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr }); + if (pane->IsConnectionClosed()) + { + makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr }); + } } if (withSelection) diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index c2e4ee6b326..0a2d64fc8d1 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -1078,7 +1078,7 @@ namespace winrt::TerminalApp::implementation if (_rootPane) { const bool isClosed = _rootPane->WalkTree([&](const auto& p) { - return p->GetConnectionState() >= ConnectionState::Closed; + return p->IsConnectionClosed(); }); _tabStatus.IsConnectionClosed(isClosed); @@ -1086,8 +1086,9 @@ namespace winrt::TerminalApp::implementation if (_activePane) { - const bool isClosed = _activePane->GetConnectionState() >= ConnectionState::Closed; - _restartConnectionMenuItem.Visibility(isClosed ? WUX::Visibility::Visible : WUX::Visibility::Collapsed); + _restartConnectionMenuItem.Visibility(_activePane->IsConnectionClosed() ? + WUX::Visibility::Visible : + WUX::Visibility::Collapsed); } } From 2ede0cde6097a16fdb02f771b0975d75f6a094a0 Mon Sep 17 00:00:00 2001 From: Marco Pelagatti <1140981+mpela81@users.noreply.github.com> Date: Mon, 4 Sep 2023 19:51:03 +0200 Subject: [PATCH 5/5] Update to latest main --- src/cascadia/TerminalApp/Pane.cpp | 2 +- src/cascadia/TerminalApp/TerminalTab.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 71939a74a42..8cf6567f37a 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -1393,7 +1393,7 @@ Profile Pane::GetFocusedProfile() // - true if the connection state of this Pane is closed. bool Pane::IsConnectionClosed() const { - return _connectionState >= ConnectionState::Closed; + return _control && _control.ConnectionState() >= ConnectionState::Closed; } // Method Description: diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index bdb0618646b..4286db604e1 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -1096,7 +1096,7 @@ namespace winrt::TerminalApp::implementation void TerminalTab::_RestartActivePaneConnection() { ActionAndArgs restartConnection{ ShortcutAction::RestartConnection, nullptr }; - _dispatch.DoAction(restartConnection); + _dispatch.DoAction(*this, restartConnection); } // Method Description: