Skip to content

Commit

Permalink
Display connection state in tab and add context menu entry for restar…
Browse files Browse the repository at this point in the history
…ting 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)
  • Loading branch information
mpela81 committed Sep 19, 2023
1 parent 3550e19 commit 2e91e9c
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/cascadia/TerminalApp/Pane.cpp
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/Pane.h
Expand Up @@ -75,6 +75,7 @@ class Pane : public std::enable_shared_from_this<Pane>
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.
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Expand Up @@ -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>
6 changes: 6 additions & 0 deletions src/cascadia/TerminalApp/TabHeaderControl.xaml
Expand Up @@ -43,6 +43,12 @@
FontSize="12"
Glyph="&#xE72E;"
Visibility="{x:Bind TabStatus.IsReadOnlyActive, Mode=OneWay}" />
<FontIcon x:Name="HeaderClosedIcon"
Margin="0,0,8,0"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="12"
Glyph="&#xEA39;"
Visibility="{x:Bind TabStatus.IsConnectionClosed, Mode=OneWay}" />
<FontIcon x:Name="HeaderBroadcastIcon"
Margin="0,0,8,0"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Expand Down
11 changes: 9 additions & 2 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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 });
Expand Down
69 changes: 69 additions & 0 deletions src/cascadia/TerminalApp/TerminalTab.cpp
Expand Up @@ -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;
Expand All @@ -35,6 +36,7 @@ namespace winrt::TerminalApp::implementation
_activePane = nullptr;

_closePaneMenuItem.Visibility(WUX::Visibility::Collapsed);
_restartConnectionMenuItem.Visibility(WUX::Visibility::Collapsed);

auto firstId = _nextPaneId;

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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() })
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/TerminalTab.h
Expand Up @@ -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{};
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalTabStatus.h
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalTabStatus.idl
Expand Up @@ -7,6 +7,7 @@ namespace TerminalApp
{
TerminalTabStatus();

Boolean IsConnectionClosed { get; set; };
Boolean IsPaneZoomed { get; set; };
Boolean IsProgressRingActive { get; set; };
Boolean IsProgressRingIndeterminate { get; set; };
Expand Down

0 comments on commit 2e91e9c

Please sign in to comment.