diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt
index 01b64c42d78..73e9583499f 100644
--- a/.github/actions/spell-check/expect/expect.txt
+++ b/.github/actions/spell-check/expect/expect.txt
@@ -2053,6 +2053,7 @@ Scrollup
Scrolluppage
SCS
scursor
+sclose
sddl
sdeleted
sdk
diff --git a/doc/cascadia/SettingsSchema.md b/doc/cascadia/SettingsSchema.md
index 9c58edc89f4..bd740bb1ee4 100644
--- a/doc/cascadia/SettingsSchema.md
+++ b/doc/cascadia/SettingsSchema.md
@@ -23,6 +23,7 @@ Properties listed below affect the entire window, regardless of the profile sett
| `tabWidthMode` | Optional | String | `equal` | Sets the width of the tabs. Possible values:
- `"equal"`: sizes each tab to the same width
- `"titleLength"`: sizes each tab to the length of its title
- `"compact"`: sizes each tab to the length of its title when focused, and shrinks to the size of only the icon when the tab is unfocused.
|
| `wordDelimiters` | Optional | String | /\()"'-:,.;<>~!@#$%^&*|+=[]{}~?│
_(`│` is `U+2502 BOX DRAWINGS LIGHT VERTICAL`)_ | Determines the delimiters used in a double click selection. |
| `confirmCloseAllTabs` | Optional | Boolean | `true` | When set to `true` closing a window with multiple tabs open WILL require confirmation. When set to `false` closing a window with multiple tabs open WILL NOT require confirmation. |
+| `confirmCloseTab` | Optional | Boolean | `true`| When set to `true` closing a tab with multiple panes WILL require confirmation. When set to `false` closing a tab with multiple panes WILL NOT require confirmation. |
| `startOnUserLogin` | Optional | Boolean | `false` | When set to `true` enables the launch of Windows Terminal at startup. Setting to `false` will disable the startup task entry. Note: if the Windows Terminal startup task entry is disabled either by org policy or by user action this setting will have no effect. |
| `disabledProfileSources` | Optional | Array[String] | `[]` | Disables all the dynamic profile generators in this list, preventing them from adding their profiles to the list of profiles on startup. This array can contain any combination of `Windows.Terminal.Wsl`, `Windows.Terminal.Azure`, or `Windows.Terminal.PowershellCore`. For more information, see [UsingJsonSettings.md](https://github.com/microsoft/terminal/blob/master/doc/user-docs/UsingJsonSettings.md#dynamic-profiles) |
| `experimental.rendering.forceFullRepaint` | Optional | Boolean | `false` | When set to true, we will redraw the entire screen each frame. When set to false, we will render only the updates to the screen between frames. |
diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json
index 0ca40b685bd..5401b7011dd 100644
--- a/doc/cascadia/profiles.schema.json
+++ b/doc/cascadia/profiles.schema.json
@@ -479,6 +479,11 @@
"default": true,
"description": "When set to \"true\" closing a window with multiple tabs open will require confirmation. When set to \"false\", the confirmation dialog will not appear.",
"type": "boolean"
+ },
+ "confirmCloseTab": {
+ "default": true,
+ "description": "When set to \"true\" closing a tab with multiple panes open will require confirmation. When set to \"false\", the confirmation dialog will not appear.",
+ "type": "boolean"
}
},
"required": [
diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp
index dd3b17ae723..a8e386f3fad 100644
--- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp
+++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp
@@ -34,6 +34,7 @@ static constexpr std::string_view WarnAboutLargePasteKey{ "largePasteWarning" };
static constexpr std::string_view WarnAboutMultiLinePasteKey{ "multiLinePasteWarning" };
static constexpr std::string_view LaunchModeKey{ "launchMode" };
static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" };
+static constexpr std::string_view ConfirmCloseTabKey{ "confirmCloseTab" };
static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" };
static constexpr std::string_view EnableStartupTaskKey{ "startOnUserLogin" };
static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" };
@@ -140,6 +141,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs);
+ JsonUtils::GetValueForKey(json, ConfirmCloseTabKey, _ConfirmCloseTab);
+
JsonUtils::GetValueForKey(json, InitialRowsKey, _InitialRows);
JsonUtils::GetValueForKey(json, InitialColsKey, _InitialCols);
diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h
index 7491b433f41..822e413b4bc 100644
--- a/src/cascadia/TerminalApp/GlobalAppSettings.h
+++ b/src/cascadia/TerminalApp/GlobalAppSettings.h
@@ -63,6 +63,7 @@ class TerminalApp::GlobalAppSettings final
GETSET_PROPERTY(bool, AlwaysShowTabs, true);
GETSET_PROPERTY(bool, ShowTitleInTitlebar, true);
GETSET_PROPERTY(bool, ConfirmCloseAllTabs, true);
+ GETSET_PROPERTY(bool, ConfirmCloseTab, true);
GETSET_PROPERTY(winrt::Windows::UI::Xaml::ElementTheme, Theme, winrt::Windows::UI::Xaml::ElementTheme::Default);
GETSET_PROPERTY(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal);
GETSET_PROPERTY(bool, ShowTabsInTitlebar, true);
diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
index 6ca22a39ff0..5244b60bfa2 100644
--- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
@@ -595,4 +595,16 @@
Dark Gray
-
+
+ Cancel
+ Close button text for Close all pane warning
+
+
+ Close all panes
+ Primary button text for Close all pane warning
+
+
+ Do you want to close all panes?
+ Title for Close all pane warning
+
+
\ No newline at end of file
diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h
index a6752fe6bbe..8c69692d22e 100644
--- a/src/cascadia/TerminalApp/Tab.h
+++ b/src/cascadia/TerminalApp/Tab.h
@@ -49,6 +49,8 @@ namespace winrt::TerminalApp::implementation
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::TerminalSettings& settings, const GUID& profile);
winrt::hstring GetActiveTitle() const;
+ int _GetLeafPaneCount() const noexcept;
+
void Shutdown();
void ClosePane();
@@ -95,7 +97,6 @@ namespace winrt::TerminalApp::implementation
void _AttachEventHandlersToControl(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
void _AttachEventHandlersToPane(std::shared_ptr pane);
- int _GetLeafPaneCount() const noexcept;
void _UpdateActivePane(std::shared_ptr pane);
void _UpdateTabHeader();
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 81cfaf1735c..bf9d025e90f 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -380,6 +380,21 @@ namespace winrt::TerminalApp::implementation
co_return ContentDialogResult::None;
}
+ // Method Description:
+ // - Displays a dialog for warnings found while closing a terminal tab
+ // with multiple panes opened. Display messages to warn user
+ // that more than 1 pane is opened, and once the user clicks the OK button, remove
+ // all the panes and sclose the tab. 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::_ShowCloseTabDialog()
+ {
+ if (auto presenter{ _dialogPresenter.get() })
+ {
+ presenter.ShowDialog(FindName(L"CloseTabDialog").try_as());
+ }
+ }
+
// 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
@@ -1856,8 +1871,19 @@ namespace winrt::TerminalApp::implementation
// - eventArgs: the event's constituent arguments
void TerminalPage::_OnTabCloseRequested(const IInspectable& /*sender*/, const MUX::Controls::TabViewTabCloseRequestedEventArgs& eventArgs)
{
- const auto tabViewItem = eventArgs.Tab();
- _RemoveTabViewItem(tabViewItem);
+ if (auto index{ _GetFocusedTabIndex() })
+ {
+ auto focusedTab{ _GetStrongTabImpl(*index) };
+ if (focusedTab->_GetLeafPaneCount() == 1 || !_settings->GlobalSettings().ConfirmCloseTab())
+ {
+ const auto tabViewItem = eventArgs.Tab();
+ _RemoveTabViewItem(tabViewItem);
+ }
+ else if (focusedTab->_GetLeafPaneCount() > 1 && _settings->GlobalSettings().ConfirmCloseTab())
+ {
+ _ShowCloseTabDialog();
+ }
+ }
}
// Method Description:
@@ -1874,6 +1900,12 @@ namespace winrt::TerminalApp::implementation
_CloseAllTabs();
}
+ void TerminalPage::_CloseTabWarningPrimaryButtonOnClick(WUX::Controls::ContentDialog /* sender */,
+ WUX::Controls::ContentDialogButtonClickEventArgs /* eventArgs*/)
+ {
+ _CloseFocusedTab();
+ }
+
// 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 f78cfe86f23..5394d58dc07 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -114,6 +114,7 @@ namespace winrt::TerminalApp::implementation
void _ShowCloseWarningDialog();
winrt::Windows::Foundation::IAsyncOperation _ShowMultiLinePasteWarningDialog();
winrt::Windows::Foundation::IAsyncOperation _ShowLargePasteWarningDialog();
+ void _ShowCloseTabDialog();
void _CreateNewTabFlyout();
void _OpenNewTabDropdown();
@@ -124,6 +125,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 _CloseTabWarningPrimaryButtonOnClick(Windows::UI::Xaml::Controls::ContentDialog sender, Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs eventArgs);
void _CloseWarningPrimaryButtonOnClick(Windows::UI::Xaml::Controls::ContentDialog sender, Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs eventArgs);
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml
index c872b325029..f6ae2e654b4 100644
--- a/src/cascadia/TerminalApp/TerminalPage.xaml
+++ b/src/cascadia/TerminalApp/TerminalPage.xaml
@@ -68,6 +68,14 @@ the MIT License. See LICENSE in the project root for license information. -->
DefaultButton="Primary">
+
+
+