Enable Terminal closing with ALT + F4 and warning of multiple open tabs (#2526)
* ALT+F4 to close the terminal app window and warn user of multiple tabs * Fix indent issue * Indentation issue fix 2 * add some comments * move close window warning texts to resources * CR feedback changes - 8/28 * fix resource file space issue * Fix resource file space issue 2 * Fix resource file space issue * minor CR changes * update comments * Sync to the latest master branch * CR changes round 2 * Format fix * fix type conversion warning * CR changes on 9-12 * CR feedback changes on 9-12 * add comments why we remove tabs in reverse order * Fix warnings
This commit is contained in:
parent
2d0608d8c0
commit
5806cdab52
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
|
@ -26,36 +26,36 @@
|
|||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
@ -193,4 +193,13 @@ Temporarily using the Windows Terminal default settings.
|
|||
<data name="SettingsMenuItem" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="Cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="CloseAll" xml:space="preserve">
|
||||
<value>Close all</value>
|
||||
</data>
|
||||
<data name="CloseWindowWarningTitle" xml:space="preserve">
|
||||
<value>Do you want to close all tabs?</value>
|
||||
</data>
|
||||
</root>
|
|
@ -184,6 +184,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
|
||||
|
@ -513,6 +536,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 });
|
||||
|
@ -603,25 +627,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<decltype(focusedTabIndex)>(_tabs.size());
|
||||
if (focusedTabIndex >= tabCount)
|
||||
|
@ -771,9 +806,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<Tab> focusedTab{ _tabs[focusedTabIndex] };
|
||||
_RemoveTabViewItem(focusedTab->GetTabViewItem());
|
||||
uint32_t focusedTabIndex = _GetFocusedTabIndex();
|
||||
_RemoveTabViewItemByIndex(focusedTabIndex);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -787,6 +821,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
|
||||
|
@ -1205,6 +1265,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
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace winrt::TerminalApp::implementation
|
|||
std::shared_ptr<ScopedResourceLoader> _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<Tab> 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
|
||||
|
@ -142,6 +147,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
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue