Files
terminal/src/cascadia/TerminalApp/TabHeaderControl.cpp
Don-Vito d33dd1ffce Teach tab to focus terminal after rename (#9162)
## Summary of the Pull Request
After rename ends (either by enter or escape) the rename box
gets collapsed and the focus moves to the next tab stop
in the TabView (e.g., new tab button).

To overcome this:
* Added RenameEnded event to TabHeaderControl
* Forwarded it as RenamerDeactivated from TerminalTab
* Registered in the TerminalPage to focus the active control upon
RenamerDeactivated if focus didn't move to tab menu.

This means, no matter how you close the renamer,
the current terminal gains the focus.

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9160
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

(cherry picked from commit 00d1dc99e4)
2021-02-23 15:55:10 -08:00

117 lines
4.8 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "TabHeaderControl.h"
#include "TabHeaderControl.g.cpp"
using namespace winrt;
using namespace winrt::Microsoft::UI::Xaml;
namespace winrt::TerminalApp::implementation
{
TabHeaderControl::TabHeaderControl()
{
InitializeComponent();
// We'll only process the KeyUp event if we received an initial KeyDown event first.
// Avoids issue immediately closing the tab rename when we see the enter KeyUp event that was
// sent to the command palette to trigger the openTabRenamer action in the first place.
HeaderRenamerTextBox().KeyDown([&](auto&&, auto&&) {
_receivedKeyDown = true;
});
// NOTE: (Preview)KeyDown does not work here. If you use that, we'll
// remove the TextBox from the UI tree, then the following KeyUp
// will bubble to the NewTabButton, which we don't want to have
// happen.
HeaderRenamerTextBox().KeyUp([&](auto&&, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e) {
if (_receivedKeyDown)
{
if (e.OriginalKey() == Windows::System::VirtualKey::Enter)
{
// User is done making changes, close the rename box
_CloseRenameBox();
}
else if (e.OriginalKey() == Windows::System::VirtualKey::Escape)
{
// User wants to discard the changes they made,
// set _renameCancelled to true and close the rename box
_renameCancelled = true;
_CloseRenameBox();
}
}
});
}
// Method Description:
// - Show the tab rename box for the user to rename the tab title
// - We automatically use the previous title as the initial text of the box
void TabHeaderControl::BeginRename()
{
_receivedKeyDown = false;
_renameCancelled = false;
HeaderTextBlock().Visibility(Windows::UI::Xaml::Visibility::Collapsed);
HeaderRenamerTextBox().Visibility(Windows::UI::Xaml::Visibility::Visible);
HeaderRenamerTextBox().Text(Title());
HeaderRenamerTextBox().SelectAll();
HeaderRenamerTextBox().Focus(Windows::UI::Xaml::FocusState::Programmatic);
TraceLoggingWrite(
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
"TabRenamerOpened",
TraceLoggingDescription("Event emitted when the tab renamer is opened"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
}
// Method Description:
// - Event handler for when the rename box loses focus
// - When the rename box loses focus, we send a request for the title change depending
// on whether the rename was cancelled
void TabHeaderControl::RenameBoxLostFocusHandler(Windows::Foundation::IInspectable const& /*sender*/,
Windows::UI::Xaml::RoutedEventArgs const& /*e*/)
{
// If the context menu associated with the renamer text box is open we know it gained the focus.
// In this case we ignore this event (we will regain the focus once the menu will be closed).
const auto flyout = HeaderRenamerTextBox().ContextFlyout();
if (flyout && flyout.IsOpen())
{
return;
}
// Log the data here, rather than in _CloseRenameBox. If we do it there,
// it'll get fired twice, once when the key is pressed to commit/cancel,
// and then again when the focus is lost
TraceLoggingWrite(
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
"TabRenamerClosed",
TraceLoggingDescription("Event emitted when the tab renamer is closed"),
TraceLoggingBoolean(_renameCancelled, "CancelledRename", "True if the user cancelled the rename, false if they committed."),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
_CloseRenameBox();
if (!_renameCancelled)
{
_TitleChangeRequestedHandlers(HeaderRenamerTextBox().Text());
}
}
// Method Description:
// - Hides the rename box and displays the title text block
void TabHeaderControl::_CloseRenameBox()
{
if (HeaderRenamerTextBox().Visibility() == Windows::UI::Xaml::Visibility::Visible)
{
HeaderRenamerTextBox().Visibility(Windows::UI::Xaml::Visibility::Collapsed);
HeaderTextBlock().Visibility(Windows::UI::Xaml::Visibility::Visible);
_RenameEndedHandlers(*this, nullptr);
}
}
}