diff --git a/src/cascadia/TerminalApp/App.cpp b/src/cascadia/TerminalApp/App.cpp
index 421aa4577e1..70b60c00412 100644
--- a/src/cascadia/TerminalApp/App.cpp
+++ b/src/cascadia/TerminalApp/App.cpp
@@ -167,9 +167,12 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
- // - Show a ContentDialog with a single button to dismiss. Uses the
+ // - Show a ContentDialog with buttons to take further action. Uses the
// FrameworkElements provided as the title and content of this dialog, and
- // displays a single button to dismiss.
+ // displays buttons (or a single button). Two buttons (primary and secondary)
+ // will be displayed if this is an warning dialog for closing the termimal,
+ // this allows the users to abondon the closing action. Otherwise, a single
+ // close button will be displayed.
// - Only one dialog can be visible at a time. If another dialog is visible
// when this is called, nothing happens.
// Arguments:
diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp
index 1abce6291d3..908dce978c4 100644
--- a/src/cascadia/TerminalApp/AppActionHandlers.cpp
+++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp
@@ -60,6 +60,13 @@ namespace winrt::TerminalApp::implementation
args.Handled(true);
}
+ void TerminalPage::_HandleCloseWindow(const IInspectable& /*sender*/,
+ const TerminalApp::ActionEventArgs& args)
+ {
+ _CloseWindow();
+ args.Handled(true);
+ }
+
void TerminalPage::_HandleScrollUp(const IInspectable& /*sender*/,
const TerminalApp::ActionEventArgs& args)
{
diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
index c461da5b42b..46e0acbfbe7 100644
--- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
@@ -1,17 +1,17 @@
-
@@ -193,4 +193,13 @@ Temporarily using the Windows Terminal default settings.
Settings
-
+
+ Cancel
+
+
+ Close all
+
+
+ Do you want to close all tabs?
+
+
\ No newline at end of file
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 1fe835defec..99ad7e4bf4d 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -182,6 +182,29 @@ namespace winrt::TerminalApp::implementation
_showDialogHandlers(*this, dialog);
}
+ // Method Description:
+ // - Displays a dialog for warnings found while closing the terminal app using
+ // key binding with multiple tabs opened. Display messages to warn user
+ // that more than 1 tab is opend, and once the user clicks the OK button, remove
+ // all the tabs and shut down and app. If cancel is clicked, the dialog will close
+ // - Only one dialog can be visible at a time. If another dialog is visible
+ // when this is called, nothing happens. See _ShowDialog for details
+ void TerminalPage::_ShowCloseWarningDialog()
+ {
+ auto title = _resourceLoader->GetLocalizedString(L"CloseWindowWarningTitle");
+ auto primaryButtonText = _resourceLoader->GetLocalizedString(L"CloseAll");
+ auto secondaryButtonText = _resourceLoader->GetLocalizedString(L"Cancel");
+
+ Controls::ContentDialog dialog;
+ dialog.Title(winrt::box_value(title));
+
+ dialog.PrimaryButtonText(primaryButtonText);
+ dialog.SecondaryButtonText(secondaryButtonText);
+ auto token = dialog.PrimaryButtonClick({ this, &TerminalPage::_CloseWarningPrimaryButtonOnClick });
+
+ _showDialogHandlers(*this, dialog);
+ }
+
// Method Description:
// - Builds the flyout (dropdown) attached to the new tab button, and
// attaches it to the button. Populates the flyout with one entry per
@@ -500,6 +523,7 @@ namespace winrt::TerminalApp::implementation
bindings.DuplicateTab({ this, &TerminalPage::_HandleDuplicateTab });
bindings.CloseTab({ this, &TerminalPage::_HandleCloseTab });
bindings.ClosePane({ this, &TerminalPage::_HandleClosePane });
+ bindings.CloseWindow({ this, &TerminalPage::_HandleCloseWindow });
bindings.ScrollUp({ this, &TerminalPage::_HandleScrollUp });
bindings.ScrollDown({ this, &TerminalPage::_HandleScrollDown });
bindings.NextTab({ this, &TerminalPage::_HandleNextTab });
@@ -590,25 +614,36 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
- // - Removes the tab (both TerminalControl and XAML)
+ // - Look for the index of the input tabView in the tabs vector,
+ // and call _RemoveTabViewItemByIndex
// Arguments:
// - tabViewItem: the TabViewItem in the TabView that is being removed.
void TerminalPage::_RemoveTabViewItem(const IInspectable& tabViewItem)
+ {
+ uint32_t tabIndexFromControl = 0;
+ _tabView.Items().IndexOf(tabViewItem, tabIndexFromControl);
+
+ _RemoveTabViewItemByIndex(tabIndexFromControl);
+ }
+
+ // Method Description:
+ // - Removes the tab (both TerminalControl and XAML)
+ // Arguments:
+ // - tabIndex: the index of the tab to be removed
+ void TerminalPage::_RemoveTabViewItemByIndex(uint32_t tabIndex)
{
// To close the window here, we need to close the hosting window.
if (_tabs.size() == 1)
{
_lastTabClosedHandlers(*this, nullptr);
}
- uint32_t tabIndexFromControl = 0;
- _tabView.Items().IndexOf(tabViewItem, tabIndexFromControl);
- auto focusedTabIndex = _GetFocusedTabIndex();
// Removing the tab from the collection will destroy its control and disconnect its connection.
- _tabs.erase(_tabs.begin() + tabIndexFromControl);
- _tabView.Items().RemoveAt(tabIndexFromControl);
+ _tabs.erase(_tabs.begin() + tabIndex);
+ _tabView.Items().RemoveAt(tabIndex);
- if (tabIndexFromControl == focusedTabIndex)
+ auto focusedTabIndex = _GetFocusedTabIndex();
+ if (tabIndex == focusedTabIndex)
{
auto const tabCount = gsl::narrow_cast(_tabs.size());
if (focusedTabIndex >= tabCount)
@@ -758,9 +793,8 @@ namespace winrt::TerminalApp::implementation
// - Close the currently focused tab. Focus will move to the left, if possible.
void TerminalPage::_CloseFocusedTab()
{
- int focusedTabIndex = _GetFocusedTabIndex();
- std::shared_ptr focusedTab{ _tabs[focusedTabIndex] };
- _RemoveTabViewItem(focusedTab->GetTabViewItem());
+ uint32_t focusedTabIndex = _GetFocusedTabIndex();
+ _RemoveTabViewItemByIndex(focusedTabIndex);
}
// Method Description:
@@ -774,6 +808,32 @@ namespace winrt::TerminalApp::implementation
focusedTab->ClosePane();
}
+ // Method Description:
+ // - Close the terminal app with keys. If there is more
+ // than one tab opened, show a warning dialog.
+ void TerminalPage::_CloseWindow()
+ {
+ if (_tabs.size() > 1)
+ {
+ _ShowCloseWarningDialog();
+ }
+ else
+ {
+ _CloseAllTabs();
+ }
+ }
+
+ // Method Description:
+ // - Remove all the tabs opened and the terminal will terminate
+ // on its own when the last tab is closed.
+ void TerminalPage::_CloseAllTabs()
+ {
+ while (!_tabs.empty())
+ {
+ _RemoveTabViewItemByIndex(0);
+ }
+ }
+
// Method Description:
// - Move the viewport of the terminal of the currently focused tab up or
// down a number of lines. Negative values of `delta` will move the
@@ -1196,6 +1256,20 @@ namespace winrt::TerminalApp::implementation
eventArgs.Cancel(true);
}
+ // Method Description:
+ // - Called when the primary button of the content dialog is clicked.
+ // This calls _CloseAllTabs(), which closes all the tabs currently
+ // opened and then the Terminal app. This method will be called if
+ // the user confirms to close all the tabs.
+ // Arguments:
+ // - sender: unused
+ // - ContentDialogButtonClickEventArgs: unused
+ void TerminalPage::_CloseWarningPrimaryButtonOnClick(Windows::UI::Xaml::Controls::ContentDialog /* sender */,
+ Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs /* eventArgs*/)
+ {
+ _CloseAllTabs();
+ }
+
// Method Description:
// - Hook up keybindings, and refresh the UI of the terminal.
// This includes update the settings of all the tabs according
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index 244e8e25ddb..80022868c6e 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -61,6 +61,7 @@ namespace winrt::TerminalApp::implementation
std::shared_ptr _resourceLoader{ nullptr };
void _ShowAboutDialog();
+ void _ShowCloseWarningDialog();
void _CreateNewTabFlyout();
void _OpenNewTabDropdown();
@@ -71,6 +72,7 @@ namespace winrt::TerminalApp::implementation
void _SettingsButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _FeedbackButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _AboutButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
+ void _CloseWarningPrimaryButtonOnClick(Windows::UI::Xaml::Controls::ContentDialog sender, Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs eventArgs);
void _HookupKeyBindings(TerminalApp::AppKeyBindings bindings) noexcept;
@@ -79,6 +81,7 @@ namespace winrt::TerminalApp::implementation
void _UpdateTabView();
void _DuplicateTabViewItem();
void _RemoveTabViewItem(const IInspectable& tabViewItem);
+ void _RemoveTabViewItemByIndex(uint32_t tabIndex);
void _RegisterTerminalEvents(Microsoft::Terminal::TerminalControl::TermControl term, std::shared_ptr hostingTab);
@@ -91,6 +94,8 @@ namespace winrt::TerminalApp::implementation
void _SetFocusedTabIndex(int tabIndex);
void _CloseFocusedTab();
void _CloseFocusedPane();
+ void _CloseWindow();
+ void _CloseAllTabs();
// Todo: add more event implementations here
// MSFT:20641986: Add keybindings for New Window
@@ -143,6 +148,7 @@ namespace winrt::TerminalApp::implementation
void _HandleResizePane(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleMoveFocus(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
void _HandleCopyText(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
+ void _HandleCloseWindow(const IInspectable&, const TerminalApp::ActionEventArgs& args);
#pragma endregion
};
}