diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp
index 48ed69822a2..59cbd21d43c 100644
--- a/src/cascadia/TerminalApp/AppActionHandlers.cpp
+++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp
@@ -801,7 +801,7 @@ namespace winrt::TerminalApp::implementation
_RemoveTabs(tabsToRemove);
- actionArgs.Handled(true);
+ actionArgs.Handled(!tabsToRemove.empty());
}
}
@@ -837,7 +837,7 @@ namespace winrt::TerminalApp::implementation
// tab row, until you mouse over them. Probably has something to do
// with tabs not resizing down until there's a mouse exit event.
- actionArgs.Handled(true);
+ actionArgs.Handled(!tabsToRemove.empty());
}
}
diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
index 81ca7d51f83..9b165e1c481 100644
--- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
@@ -496,24 +496,48 @@
Third-Party notices
A hyperlink name for the Terminal's third-party notices
-
+
Cancel
-
- Close all
-
-
+
Do you want to close all windows?
-
- Cancel
-
-
+
Close all
-
+
Do you want to close all tabs?
+
+ Close all
+
+
+ Do you want to close this tab?
+
+
+ Close tab
+
+
+ Do you want to close this pane?
+
+
+ Close pane
+
+
+ Do you want to close these tabs?
+
+
+ Close tabs
+
+
+ Do you want to close these panes?
+
+
+ Close panes
+
+
+ Don't ask me again
+
Cancel
diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp
index 21e31fb6dd3..418a617cee2 100644
--- a/src/cascadia/TerminalApp/TabManagement.cpp
+++ b/src/cascadia/TerminalApp/TabManagement.cpp
@@ -391,10 +391,12 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
- // - Removes the tab (both TerminalControl and XAML) after prompting for approval
+ // - Removes the tab (both TerminalControl and XAML) after prompting for approval.
// Arguments:
- // - tab: the tab to remove
- winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab)
+ // - tab: the tab to remove.
+ // - skipConfirmClose: if true, skip the confirmCloseOn check. Used when
+ // an aggregate confirmation has already been shown (e.g. close other tabs).
+ winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab, bool skipConfirmClose)
{
winrt::com_ptr strong;
@@ -413,6 +415,24 @@ namespace winrt::TerminalApp::implementation
}
}
+ // Skip the per-tab confirmCloseOn check when the caller has already
+ // shown an aggregate confirmation dialog (e.g. _RemoveTabs).
+ if (!skipConfirmClose)
+ {
+ const auto tabImpl = _GetTabImpl(tab);
+ if (tabImpl && _ShouldWarnOnCloseTab(tabImpl))
+ {
+ const auto weak = get_weak();
+
+ auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::Tab);
+ strong = weak.get();
+ if (!strong || warningResult != ContentDialogResult::Primary)
+ {
+ co_return;
+ }
+ }
+ }
+
auto t = winrt::get_self(tab);
auto actions = t->BuildStartupActions(BuildStartupKind::None);
_AddPreviouslyClosedPaneOrTab(std::move(actions));
@@ -782,6 +802,22 @@ namespace winrt::TerminalApp::implementation
if (const auto pane{ activeTab->GetActivePane() })
{
const auto weak = get_weak();
+
+ // Check if we should warn before closing a single pane
+ // (only triggers on Always — Automatic doesn't warn for single pane)
+ const auto setting = _settings.GlobalSettings().ConfirmCloseOn();
+ if (setting == ConfirmCloseOn::Always)
+ {
+ // If this is the last pane, closing it closes the tab,
+ // so use the tab dialog text instead.
+ const auto kind = activeTab->GetLeafPaneCount() == 1 ? ConfirmCloseDialogKind::Tab : ConfirmCloseDialogKind::Pane;
+ auto warningResult = co_await _ShowConfirmCloseDialog(kind);
+ if (!weak.get() || warningResult != ContentDialogResult::Primary)
+ {
+ co_return;
+ }
+ }
+
if (co_await _PaneConfirmCloseReadOnly(pane))
{
if (const auto strong = weak.get())
@@ -794,15 +830,38 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
- // - Close all panes with the given IDs sequentially.
+ // - Closes provided panes one by one, showing a single aggregate
+ // confirmation dialog upfront if the confirmCloseOn setting warrants it.
// Arguments:
- // - weakTab: weak reference to the tab that the pane belongs to.
+ // - weakTab: weak reference to the tab that the panes belong to.
// - paneIds: collection of the IDs of the panes that are marked for removal.
- void TerminalPage::_ClosePanes(weak_ref weakTab, std::vector paneIds)
+ safe_void_coroutine TerminalPage::_ClosePanes(weak_ref weakTab, std::vector paneIds)
+ {
+ // Show a single aggregate confirmation for closing multiple panes.
+ if (_settings.GlobalSettings().ConfirmCloseOn() != ConfirmCloseOn::Never)
+ {
+ const auto weak = get_weak();
+ auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::MultiplePanes);
+ if (!weak.get() || warningResult != ContentDialogResult::Primary)
+ {
+ co_return;
+ }
+ }
+
+ _CloseRemainingPanes(weakTab, std::move(paneIds));
+ }
+
+ // Method Description:
+ // - Recursively closes panes by ID, chaining each close via the
+ // ClosedByParent callback. Called after confirmation has already
+ // been handled by _ClosePanes.
+ // Arguments:
+ // - weakTab: weak reference to the tab that the panes belong to.
+ // - paneIds: remaining pane IDs to close.
+ void TerminalPage::_CloseRemainingPanes(weak_ref weakTab, std::vector paneIds)
{
if (auto strongTab{ weakTab.get() })
{
- // Close all unfocused panes one by one
while (!paneIds.empty())
{
const auto id = paneIds.back();
@@ -813,11 +872,10 @@ namespace winrt::TerminalApp::implementation
pane->ClosedByParent([ids{ std::move(paneIds) }, weakThis{ get_weak() }, weakTab]() {
if (auto strongThis{ weakThis.get() })
{
- strongThis->_ClosePanes(weakTab, std::move(ids));
+ strongThis->_CloseRemainingPanes(weakTab, std::move(ids));
}
});
- // Close the pane which will eventually trigger the closed by parent event
_HandleClosePaneRequested(pane);
break;
}
@@ -840,19 +898,35 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
- // - Closes provided tabs one by one
+ // - Closes provided tabs one by one, showing a single aggregate
+ // confirmation dialog upfront if the confirmCloseOn setting warrants it.
// Arguments:
// - tabs - tabs to remove
safe_void_coroutine TerminalPage::_RemoveTabs(const std::vector tabs)
{
+ if (tabs.empty())
+ {
+ co_return;
+ }
+
const auto weak = get_weak();
+ // Show a single aggregate confirmation instead of per-tab dialogs.
+ if (_settings.GlobalSettings().ConfirmCloseOn() != ConfirmCloseOn::Never)
+ {
+ auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::MultipleTabs);
+ if (!weak.get() || warningResult != ContentDialogResult::Primary)
+ {
+ co_return;
+ }
+ }
+
for (auto& tab : tabs)
{
winrt::Windows::Foundation::IAsyncAction action{ nullptr };
if (const auto strong = weak.get())
{
- action = _HandleCloseTabRequested(tab);
+ action = _HandleCloseTabRequested(tab, true);
}
if (!action)
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index e98de6b9957..fa7e6ef8937 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -884,26 +884,63 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
- // - Displays a dialog to warn the user that they are about to close all open windows.
- // Once the user clicks the OK button, shut down the application.
- // If cancel is clicked, the dialog will close.
+ // - Displays the unified close confirmation dialog configured for the
+ // given scenario. Resets the "don't ask me again" checkbox before showing.
+ // If the user confirms and checked "don't ask me again", sets
+ // confirmCloseOn to Never and writes settings to disk.
// - Only one dialog can be visible at a time. If another dialog is visible
// when this is called, nothing happens. See _ShowDialog for details
- winrt::Windows::Foundation::IAsyncOperation TerminalPage::_ShowQuitDialog()
+ winrt::Windows::Foundation::IAsyncOperation TerminalPage::_ShowConfirmCloseDialog(ConfirmCloseDialogKind kind)
{
- return _ShowDialogHelper(L"QuitDialog");
- }
+ // Load the dialog (triggers x:Load) and configure its strings.
+ const auto dialog = FindName(L"ConfirmCloseDialog").as();
+ switch (kind)
+ {
+ case ConfirmCloseDialogKind::CloseAll:
+ dialog.Title(winrt::box_value(RS_(L"ConfirmCloseDialog_CloseAllTitle")));
+ dialog.PrimaryButtonText(RS_(L"ConfirmCloseDialog_CloseAllPrimary"));
+ break;
+ case ConfirmCloseDialogKind::Window:
+ dialog.Title(winrt::box_value(RS_(L"ConfirmCloseDialog_WindowTitle")));
+ dialog.PrimaryButtonText(RS_(L"ConfirmCloseDialog_WindowPrimary"));
+ break;
+ case ConfirmCloseDialogKind::Tab:
+ dialog.Title(winrt::box_value(RS_(L"ConfirmCloseDialog_TabTitle")));
+ dialog.PrimaryButtonText(RS_(L"ConfirmCloseDialog_TabPrimary"));
+ break;
+ case ConfirmCloseDialogKind::MultiplePanes:
+ dialog.Title(winrt::box_value(RS_(L"ConfirmCloseDialog_MultiplePanesTitle")));
+ dialog.PrimaryButtonText(RS_(L"ConfirmCloseDialog_MultiplePanesPrimary"));
+ break;
+ case ConfirmCloseDialogKind::MultipleTabs:
+ dialog.Title(winrt::box_value(RS_(L"ConfirmCloseDialog_MultipleTabsTitle")));
+ dialog.PrimaryButtonText(RS_(L"ConfirmCloseDialog_MultipleTabsPrimary"));
+ break;
+ case ConfirmCloseDialogKind::Pane:
+ dialog.Title(winrt::box_value(RS_(L"ConfirmCloseDialog_PaneTitle")));
+ dialog.PrimaryButtonText(RS_(L"ConfirmCloseDialog_PanePrimary"));
+ break;
+ }
+ dialog.CloseButtonText(RS_(L"ConfirmCloseDialog_Cancel"));
- // 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 opened, 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
- winrt::Windows::Foundation::IAsyncOperation TerminalPage::_ShowCloseWarningDialog()
- {
- return _ShowDialogHelper(L"CloseAllDialog");
+ // BODGY: After a ContentDialog is dismissed, FindName() can no longer
+ // resolve children inside it. Use Content() to get the checkbox directly.
+ const auto checkbox = dialog.Content().as();
+ checkbox.IsChecked(false);
+
+ auto result = ContentDialogResult::None;
+ if (auto presenter{ _dialogPresenter.get() })
+ {
+ result = co_await presenter.ShowDialog(dialog);
+ }
+
+ if (result == ContentDialogResult::Primary && checkbox.IsChecked().Value())
+ {
+ _settings.GlobalSettings().ConfirmCloseOn(ConfirmCloseOn::Never);
+ _settings.WriteSettingsToDisk();
+ }
+
+ co_return result;
}
// Method Description:
@@ -2210,12 +2247,13 @@ namespace winrt::TerminalApp::implementation
// signal that we want to close everything.
safe_void_coroutine TerminalPage::RequestQuit()
{
- if (!_displayingCloseDialog)
+ const auto setting = _settings.GlobalSettings().ConfirmCloseOn();
+ if (setting != ConfirmCloseOn::Never && !_displayingCloseDialog)
{
_displayingCloseDialog = true;
const auto weak = get_weak();
- auto warningResult = co_await _ShowQuitDialog();
+ auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::CloseAll);
const auto strong = weak.get();
if (!strong)
{
@@ -2228,9 +2266,9 @@ namespace winrt::TerminalApp::implementation
{
co_return;
}
-
- QuitRequested.raise(nullptr, nullptr);
}
+
+ QuitRequested.raise(nullptr, nullptr);
}
void TerminalPage::PersistState()
@@ -2308,12 +2346,75 @@ namespace winrt::TerminalApp::implementation
}
// Method Description:
- // - Close the terminal app. If there is more
- // than one tab opened, show a warning dialog.
+ // - Determines whether a close-window action should show a confirmation
+ // dialog, based on the confirmCloseOn setting and the current window state.
+ // Arguments:
+ // -
+ // Return Value:
+ // - true if a warning dialog should be shown before closing the window.
+ bool TerminalPage::_ShouldWarnOnClose() const
+ {
+ const auto setting = _settings.GlobalSettings().ConfirmCloseOn();
+
+ switch (setting)
+ {
+ case ConfirmCloseOn::Always:
+ return true;
+
+ case ConfirmCloseOn::Automatic:
+ {
+ // Warn if there's more than one tab.
+ if (_HasMultipleTabs())
+ {
+ return true;
+ }
+
+ // Warn if the one tab has more than one pane.
+ if (_GetTabImpl(_tabs.GetAt(0))->GetLeafPaneCount() > 1)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ case ConfirmCloseOn::Never:
+ default:
+ return false;
+ }
+ }
+
+ // Method Description:
+ // - Determines whether closing a specific tab should show a confirmation
+ // dialog, based on the confirmCloseOn setting and the tab's state.
+ // Arguments:
+ // - tab: The tab being closed.
+ // Return Value:
+ // - true if a warning dialog should be shown before closing the tab.
+ bool TerminalPage::_ShouldWarnOnCloseTab(const winrt::com_ptr& tab) const
+ {
+ const auto setting = _settings.GlobalSettings().ConfirmCloseOn();
+
+ switch (setting)
+ {
+ case ConfirmCloseOn::Always:
+ return true;
+
+ case ConfirmCloseOn::Automatic:
+ // Warn if this tab has more than one pane.
+ return tab->GetLeafPaneCount() > 1;
+
+ case ConfirmCloseOn::Never:
+ default:
+ return false;
+ }
+ }
+
+ // Method Description:
+ // - Close the terminal app. If the confirmCloseOn setting indicates we should
+ // warn for the current window state, show a warning dialog.
safe_void_coroutine TerminalPage::CloseWindow()
{
- if (_HasMultipleTabs() &&
- _settings.GlobalSettings().ConfirmCloseAllTabs() &&
+ if (_ShouldWarnOnClose() &&
!_displayingCloseDialog)
{
if (_newTabButton && _newTabButton.Flyout())
@@ -2322,7 +2423,14 @@ namespace winrt::TerminalApp::implementation
}
_DismissTabContextMenus();
_displayingCloseDialog = true;
- auto warningResult = co_await _ShowCloseWarningDialog();
+
+ const auto weak = get_weak();
+ auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::Window);
+ if (!weak.get())
+ {
+ co_return;
+ }
+
_displayingCloseDialog = false;
if (warningResult != ContentDialogResult::Primary)
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index 4b48cc0e9d9..78fc86ec4a7 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -54,6 +54,16 @@ namespace winrt::TerminalApp::implementation
ScrollDown = 1
};
+ enum class ConfirmCloseDialogKind
+ {
+ Pane,
+ Tab,
+ MultiplePanes,
+ MultipleTabs,
+ Window,
+ CloseAll
+ };
+
struct RenameWindowRequestedArgs : RenameWindowRequestedArgsT
{
WINRT_PROPERTY(winrt::hstring, ProposedName);
@@ -301,8 +311,7 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::Foundation::IAsyncOperation _ShowDialogHelper(const std::wstring_view& name);
void _ShowAboutDialog();
- winrt::Windows::Foundation::IAsyncOperation _ShowQuitDialog();
- winrt::Windows::Foundation::IAsyncOperation _ShowCloseWarningDialog();
+ winrt::Windows::Foundation::IAsyncOperation _ShowConfirmCloseDialog(ConfirmCloseDialogKind kind);
winrt::Windows::Foundation::IAsyncOperation _ShowCloseReadOnlyDialog();
winrt::Windows::Foundation::IAsyncOperation _ShowMultiLinePasteWarningDialog();
winrt::Windows::Foundation::IAsyncOperation _ShowLargePasteWarningDialog();
@@ -349,7 +358,7 @@ namespace winrt::TerminalApp::implementation
safe_void_coroutine _ExportTab(const Tab& tab, winrt::hstring filepath);
- winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::Tab tab);
+ winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::Tab tab, bool skipConfirmClose = false);
void _CloseTabAtIndex(uint32_t index);
void _RemoveTab(const winrt::TerminalApp::Tab& tab);
safe_void_coroutine _RemoveTabs(const std::vector tabs);
@@ -400,9 +409,12 @@ namespace winrt::TerminalApp::implementation
TerminalApp::Tab _GetTabByTabViewItem(const IInspectable& tabViewItem) const noexcept;
void _HandleClosePaneRequested(std::shared_ptr pane);
+ bool _ShouldWarnOnClose() const;
+ bool _ShouldWarnOnCloseTab(const winrt::com_ptr& tab) const;
safe_void_coroutine _SetFocusedTab(const winrt::TerminalApp::Tab tab);
safe_void_coroutine _CloseFocusedPane();
- void _ClosePanes(weak_ref weakTab, std::vector paneIds);
+ safe_void_coroutine _ClosePanes(weak_ref weakTab, std::vector paneIds);
+ void _CloseRemainingPanes(weak_ref weakTab, std::vector paneIds);
winrt::Windows::Foundation::IAsyncOperation _PaneConfirmCloseReadOnly(std::shared_ptr pane);
void _AddPreviouslyClosedPaneOrTab(std::vector&& args);
diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml
index 40e3b838c37..1808874b938 100644
--- a/src/cascadia/TerminalApp/TerminalPage.xaml
+++ b/src/cascadia/TerminalApp/TerminalPage.xaml
@@ -86,17 +86,12 @@
Grid.Row="2"
x:Load="False" />
-
-
-
+ DefaultButton="Primary">
+
+
-
-
-
+
+
+
diff --git a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp
index 55a239e8e5f..92eb744845c 100644
--- a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp
+++ b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.cpp
@@ -17,5 +17,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
INITIALIZE_BINDABLE_ENUM_SETTING(TabSwitcherMode, TabSwitcherMode, TabSwitcherMode, L"Globals_TabSwitcherMode", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING(CopyFormat, CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, L"Globals_CopyFormat", L"Content");
+ INITIALIZE_BINDABLE_ENUM_SETTING(ConfirmCloseOn, ConfirmCloseOn, Model::ConfirmCloseOn, L"Globals_ConfirmCloseOn", L"Content");
}
}
diff --git a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h
index c3e48715f7a..4cd40b128f9 100644
--- a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h
+++ b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.h
@@ -19,6 +19,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
GETSET_BINDABLE_ENUM_SETTING(TabSwitcherMode, Model::TabSwitcherMode, _GlobalSettings.TabSwitcherMode);
GETSET_BINDABLE_ENUM_SETTING(CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, _GlobalSettings.CopyFormatting);
+ GETSET_BINDABLE_ENUM_SETTING(ConfirmCloseOn, Model::ConfirmCloseOn, _GlobalSettings.ConfirmCloseOn);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, CopyOnSelect);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, TrimBlockSelection);
@@ -30,7 +31,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, DetectURLs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, SearchWebDefaultQueryUrl);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WordDelimiters);
- PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ConfirmCloseAllTabs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, InputServiceWarning);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutLargePaste);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutMultiLinePaste);
diff --git a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl
index ba77aec55f5..ff0778e19f3 100644
--- a/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl
+++ b/src/cascadia/TerminalSettingsEditor/InteractionViewModel.idl
@@ -12,10 +12,13 @@ namespace Microsoft.Terminal.Settings.Editor
InteractionViewModel(Microsoft.Terminal.Settings.Model.GlobalAppSettings globalSettings);
IInspectable CurrentTabSwitcherMode;
- Windows.Foundation.Collections.IObservableVector TabSwitcherModeList { get; };
+ Windows.Foundation.Collections.IObservableVector TabSwitcherModeList { get; };
IInspectable CurrentCopyFormat;
- Windows.Foundation.Collections.IObservableVector CopyFormatList { get; };
+ Windows.Foundation.Collections.IObservableVector CopyFormatList { get; };
+
+ IInspectable CurrentConfirmCloseOn;
+ Windows.Foundation.Collections.IObservableVector ConfirmCloseOnList { get; };
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, CopyOnSelect);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, TrimBlockSelection);
@@ -27,7 +30,6 @@ namespace Microsoft.Terminal.Settings.Editor
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DetectURLs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, SearchWebDefaultQueryUrl);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, WordDelimiters);
- PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ConfirmCloseAllTabs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, InputServiceWarning);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, WarnAboutLargePaste);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Microsoft.Terminal.Control.WarnAboutMultiLinePaste, WarnAboutMultiLinePaste);
diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
index dc20fbecbf7..ba5f5e59eb9 100644
--- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
@@ -2197,6 +2197,26 @@
Warn when closing more than one tab
Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.
+
+ Warn when closing
+ Header for a dropdown controlling when to show a confirmation dialog before closing.
+
+
+ Controls when a confirmation dialog appears before closing tabs or windows. "Always" presents the dialog when closing any pane.
+ Help text associated with Globals_ConfirmCloseOn. "Always" refers to Globals_ConfirmCloseOnAlways.Content.
+
+
+ Never
+ Option associated with Globals_ConfirmCloseOn. "Never" means that the system will never display a warning when closing.
+
+
+ Always
+ Option associated with Globals_ConfirmCloseOn. "Always" means that the system will always display a warning when closing.
+
+
+ Multiple tabs or panes
+ Option associated with Globals_ConfirmCloseOn. The system will display a warning when multiple tabs or panes are present.
+
Warn when "Touch Keyboard and Handwriting Panel Service" is disabled
diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp
index de1bf5185da..aaccce45f52 100644
--- a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp
+++ b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp
@@ -43,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::TextMeasurement, TextMeasurement);
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::AmbiguousWidth, AmbiguousWidth);
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::WarnAboutMultiLinePaste, WarnAboutMultiLinePaste);
+ DEFINE_ENUM_MAP(Model::ConfirmCloseOn, ConfirmCloseOn);
// Profile Settings
DEFINE_ENUM_MAP(Model::CloseOnExitMode, CloseOnExitMode);
diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.h b/src/cascadia/TerminalSettingsModel/EnumMappings.h
index 160c9a11b1f..3926313a5f8 100644
--- a/src/cascadia/TerminalSettingsModel/EnumMappings.h
+++ b/src/cascadia/TerminalSettingsModel/EnumMappings.h
@@ -40,6 +40,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static winrt::Windows::Foundation::Collections::IMap TextMeasurement();
static winrt::Windows::Foundation::Collections::IMap AmbiguousWidth();
static winrt::Windows::Foundation::Collections::IMap WarnAboutMultiLinePaste();
+ static winrt::Windows::Foundation::Collections::IMap ConfirmCloseOn();
// Profile Settings
static winrt::Windows::Foundation::Collections::IMap CloseOnExitMode();
diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.idl b/src/cascadia/TerminalSettingsModel/EnumMappings.idl
index 128260a507a..6c6df7e5939 100644
--- a/src/cascadia/TerminalSettingsModel/EnumMappings.idl
+++ b/src/cascadia/TerminalSettingsModel/EnumMappings.idl
@@ -22,6 +22,7 @@ namespace Microsoft.Terminal.Settings.Model
static Windows.Foundation.Collections.IMap TextMeasurement { get; };
static Windows.Foundation.Collections.IMap AmbiguousWidth { get; };
static Windows.Foundation.Collections.IMap WarnAboutMultiLinePaste { get; };
+ static Windows.Foundation.Collections.IMap ConfirmCloseOn { get; };
// Profile Settings
static Windows.Foundation.Collections.IMap CloseOnExitMode { get; };
diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp
index 254e52bdbcb..ac4c8d10cf9 100644
--- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp
+++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp
@@ -160,7 +160,16 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyInputServiceWarningKey, _InputServiceWarning) || _fixupsAppliedDuringLoad;
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutLargePasteKey, _WarnAboutLargePaste) || _fixupsAppliedDuringLoad;
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste) || _fixupsAppliedDuringLoad;
- _fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyConfirmCloseAllTabsKey, _ConfirmCloseAllTabs) || _fixupsAppliedDuringLoad;
+ // GH#6549 - Migrate legacy "confirmCloseAllTabs" boolean to the new
+ // "confirmCloseOn" enum. true -> Automatic, false -> Never.
+ {
+ std::optional legacyConfirmClose;
+ if (JsonUtils::GetValueForKey(json, LegacyConfirmCloseAllTabsKey, legacyConfirmClose))
+ {
+ _ConfirmCloseOn = legacyConfirmClose.value() ? ConfirmCloseOn::Automatic : ConfirmCloseOn::Never;
+ _fixupsAppliedDuringLoad = true;
+ }
+ }
#define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(json, jsonKey, _##name); \
diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl
index 77bcfc494da..b840822681d 100644
--- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl
+++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl
@@ -50,6 +50,13 @@ namespace Microsoft.Terminal.Settings.Model
AfterCurrentTab,
};
+ enum ConfirmCloseOn
+ {
+ Never = 0,
+ Automatic = 1,
+ Always = 2,
+ };
+
[default_interface] runtimeclass GlobalAppSettings {
Guid DefaultProfile;
@@ -61,7 +68,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, ShowTabsFullscreen);
INHERITABLE_SETTING(NewTabPosition, NewTabPosition);
INHERITABLE_SETTING(Boolean, ShowTitleInTitlebar);
- INHERITABLE_SETTING(Boolean, ConfirmCloseAllTabs);
+ INHERITABLE_SETTING(ConfirmCloseOn, ConfirmCloseOn);
INHERITABLE_SETTING(String, Language);
INHERITABLE_SETTING(Microsoft.UI.Xaml.Controls.TabViewWidthMode, TabWidthMode);
INHERITABLE_SETTING(Boolean, UseAcrylicInTabRow);
diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h
index 4f99bda187a..81f846d4941 100644
--- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h
+++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h
@@ -38,7 +38,7 @@ Author(s):
X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \
X(Model::NewTabPosition, NewTabPosition, "newTabPosition", Model::NewTabPosition::AfterLastTab) \
X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \
- X(bool, ConfirmCloseAllTabs, "warning.confirmCloseAllTabs", true) \
+ X(Model::ConfirmCloseOn, ConfirmCloseOn, "warning.confirmCloseOn", Model::ConfirmCloseOn::Automatic) \
X(Model::ThemePair, Theme, "theme") \
X(hstring, Language, "language") \
X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \
diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h
index 9c071945a29..c3a1daecd25 100644
--- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h
+++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h
@@ -88,6 +88,25 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::MatchMode)
};
};
+JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::ConfirmCloseOn)
+{
+ JSON_MAPPINGS(3) = {
+ pair_type{ "never", ValueType::Never },
+ pair_type{ "always", ValueType::Always },
+ pair_type{ "automatic", ValueType::Automatic },
+ };
+
+ auto FromJson(const Json::Value& json)
+ {
+ return BaseEnumMapper::FromJson(json);
+ }
+
+ bool CanConvert(const Json::Value& json)
+ {
+ return BaseEnumMapper::CanConvert(json);
+ }
+};
+
JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::BellStyle)
{
static constexpr std::array mappings = {
diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json
index 9d9474cd9c5..147ffc1e1ab 100644
--- a/src/cascadia/TerminalSettingsModel/defaults.json
+++ b/src/cascadia/TerminalSettingsModel/defaults.json
@@ -24,7 +24,7 @@
"showAdminShield": true,
// Miscellaneous
- "confirmCloseAllTabs": true,
+ "warning.confirmCloseOn": "automatic",
"theme": "dark",
"snapToGridOnResize": true,
"disableAnimations": false,
diff --git a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp
index 3112f83939e..a147842c1d7 100644
--- a/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp
+++ b/src/cascadia/UnitTests_SettingsModel/SerializationTests.cpp
@@ -125,7 +125,7 @@ namespace SettingsModelUnitTests
"trimPaste": true,
- "warning.confirmCloseAllTabs" : true,
+ "warning.confirmCloseOn": "automatic",
"warning.inputService" : true,
"warning.largePaste" : true,
"warning.multiLinePaste" : "automatic",