mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-09 21:25:35 +00:00
Display connection state in tab and add context menu entry for restarting connection (#15760)
## Summary of the Pull Request When a connection is Closed, show an indicator in the respective tab. When the active pane's connection is Closed, show a "Restart Connection" action in the right-click context menu and in the tab context menu. ## Validation Steps Performed - Force close a connection, check the indicator is shown in the tab. - Right-click on pane shows the Restart Connection action if its connection is closed - Right-click on tab shows the Restart Connection action if the active pane's connection is closed - Indicator is cleared after connection is restarted (no panes in closed state) ## PR Checklist - [x] Closes #14909 - [x] Tests added/passed - [ ] Documentation updated - [ ] Schema updated (if necessary)
This commit is contained in:
@@ -1384,6 +1384,18 @@ Profile Pane::GetFocusedProfile()
|
||||
return lastFocused ? lastFocused->_profile : nullptr;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns true if the connection state of this pane is closed. If this Pane is not a leaf this will
|
||||
// return false.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - true if the connection state of this Pane is closed.
|
||||
bool Pane::IsConnectionClosed() const
|
||||
{
|
||||
return _control && _control.ConnectionState() >= ConnectionState::Closed;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns true if this pane was the last pane to be focused in a tree of panes.
|
||||
// Arguments:
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl();
|
||||
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
|
||||
bool IsConnectionClosed() const;
|
||||
|
||||
// Method Description:
|
||||
// - If this is a leaf pane, return its profile.
|
||||
|
||||
@@ -891,4 +891,10 @@
|
||||
<data name="CmdAppendCommandLineDesc" xml:space="preserve">
|
||||
<value>If set, the command will be appended to the profile's default command instead of replacing it.</value>
|
||||
</data>
|
||||
<data name="RestartConnectionText" xml:space="preserve">
|
||||
<value>Restart Connection</value>
|
||||
</data>
|
||||
<data name="RestartConnectionToolTip" xml:space="preserve">
|
||||
<value>Restart the active pane connection</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
FontSize="12"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind TabStatus.IsReadOnlyActive, Mode=OneWay}" />
|
||||
<FontIcon x:Name="HeaderClosedIcon"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind TabStatus.IsConnectionClosed, Mode=OneWay}" />
|
||||
<FontIcon x:Name="HeaderBroadcastIcon"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
|
||||
@@ -4810,8 +4810,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<MUX::Controls::CommandBarFlyout>() };
|
||||
if (!menu)
|
||||
@@ -4864,6 +4863,14 @@ namespace winrt::TerminalApp::implementation
|
||||
makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr });
|
||||
}
|
||||
|
||||
if (const auto pane{ _GetFocusedTabImpl()->GetActivePane() })
|
||||
{
|
||||
if (pane->IsConnectionClosed())
|
||||
{
|
||||
makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr });
|
||||
}
|
||||
}
|
||||
|
||||
if (withSelection)
|
||||
{
|
||||
makeItem(RS_(L"SearchWebText"), L"\xF6FA", ActionAndArgs{ ShortcutAction::SearchForText, nullptr });
|
||||
|
||||
@@ -15,6 +15,7 @@ using namespace winrt;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::System;
|
||||
@@ -35,6 +36,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_activePane = nullptr;
|
||||
|
||||
_closePaneMenuItem.Visibility(WUX::Visibility::Collapsed);
|
||||
_restartConnectionMenuItem.Visibility(WUX::Visibility::Collapsed);
|
||||
|
||||
auto firstId = _nextPaneId;
|
||||
|
||||
@@ -890,6 +892,7 @@ namespace winrt::TerminalApp::implementation
|
||||
control.TitleChanged(events.titleToken);
|
||||
control.TabColorChanged(events.colorToken);
|
||||
control.SetTaskbarProgress(events.taskbarToken);
|
||||
control.ConnectionStateChanged(events.stateToken);
|
||||
control.ReadOnlyChanged(events.readOnlyToken);
|
||||
control.FocusFollowMouseRequested(events.focusToken);
|
||||
|
||||
@@ -949,6 +952,14 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
events.stateToken = control.ConnectionStateChanged([dispatcher, weakThis](auto&&, auto&&) -> 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() })
|
||||
@@ -1054,6 +1065,40 @@ namespace winrt::TerminalApp::implementation
|
||||
_TaskbarProgressChangedHandlers(nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - 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:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_UpdateConnectionClosedState()
|
||||
{
|
||||
ASSERT_UI_THREAD();
|
||||
|
||||
if (_rootPane)
|
||||
{
|
||||
const bool isClosed = _rootPane->WalkTree([&](const auto& p) {
|
||||
return p->IsConnectionClosed();
|
||||
});
|
||||
|
||||
_tabStatus.IsConnectionClosed(isClosed);
|
||||
}
|
||||
|
||||
if (_activePane)
|
||||
{
|
||||
_restartConnectionMenuItem.Visibility(_activePane->IsConnectionClosed() ?
|
||||
WUX::Visibility::Visible :
|
||||
WUX::Visibility::Collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalTab::_RestartActivePaneConnection()
|
||||
{
|
||||
ActionAndArgs restartConnection{ ShortcutAction::RestartConnection, nullptr };
|
||||
_dispatch.DoAction(*this, restartConnection);
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -1072,6 +1117,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
|
||||
@@ -1393,6 +1439,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;
|
||||
@@ -1403,6 +1471,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
|
||||
|
||||
@@ -109,6 +109,7 @@ namespace winrt::TerminalApp::implementation
|
||||
std::shared_ptr<Pane> _zoomedPane{ nullptr };
|
||||
|
||||
Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem;
|
||||
Windows::UI::Xaml::Controls::MenuFlyoutItem _restartConnectionMenuItem;
|
||||
|
||||
winrt::hstring _lastIconPath{};
|
||||
std::optional<winrt::Windows::UI::Color> _runtimeTabColor{};
|
||||
@@ -125,6 +126,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;
|
||||
|
||||
@@ -171,6 +173,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _UpdateProgressState();
|
||||
|
||||
void _UpdateConnectionClosedState();
|
||||
void _RestartActivePaneConnection();
|
||||
|
||||
void _DuplicateTab();
|
||||
|
||||
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace TerminalApp
|
||||
{
|
||||
TerminalTabStatus();
|
||||
|
||||
Boolean IsConnectionClosed { get; set; };
|
||||
Boolean IsPaneZoomed { get; set; };
|
||||
Boolean IsProgressRingActive { get; set; };
|
||||
Boolean IsProgressRingIndeterminate { get; set; };
|
||||
|
||||
Reference in New Issue
Block a user