// 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&& e) { _receivedKeyDown = true; // GH#9632 - mark navigation buttons as handled. // This should prevent the tab view to use this key for navigation between tabs if (e.OriginalKey() == Windows::System::VirtualKey::Down || e.OriginalKey() == Windows::System::VirtualKey::Up || e.OriginalKey() == Windows::System::VirtualKey::Left || e.OriginalKey() == Windows::System::VirtualKey::Right) { e.Handled(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: // - Returns true if we're in the middle of a tab rename. This is used to // mitigate GH#10112. // Arguments: // - // Return Value: // - true if the renamer is open. bool TabHeaderControl::InRename() { return Windows::UI::Xaml::Visibility::Visible == HeaderRenamerTextBox().Visibility(); } // 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); } } }