mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-24 15:12:02 +00:00
This PR automagically finds and replaces all[^1] usages of our
TYPED_EVENT macro with `til::event`. Benefits include:
* less macro magic
* editors are more easily able to figure out the relationship between
`til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this,
&Bar::FooHandler})` (whereas before the relationship between
`_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by
vscode & sublime.
Other find & replace work that had to be done:
* I added the `til::typed_event<>` == `<IInspectable, IInspectable>`
thing from #16170, since that is goodness
* I actually fixed `til::property_changed_event`, so you can use that
for your property changed events. They're all the same anyways.
* events had to come before `WINRT_PROPERTY`s, since the latter macro
leaves us in a `private:` block
* `Pane::SetupChildCloseHandlers` I had to swap _back_, because the
script thought that was an event 🤦
* `ProfileViewModel::DeleteProfile` had to be renamed
`DeleteProfileRequested`, since there was already a `DeleteProfile`
method on it.
* WindowManager.cpp was directly wiring up it's `winrt::event`s to the
monarch & peasant. That doesn't work with `til::event`s and I'm kinda
surprised it ever did
<details>
<summary>The script in question</summary>
```py
import os
import re
def replace_in_file(file_path, file_name):
with open(file_path, 'r', encoding="utf8") as file:
content = file.read()
found_matches = False
# Define the pattern for matching
pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);'
event_matches = re.findall(pattern, content)
if event_matches:
found_matches = True
print(f'found events in {file_path}:')
for match in event_matches:
name = match[0]
args = match[1]
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');'
new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;'
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);'
typed_matches = re.findall(typed_event_pattern, content)
if typed_matches:
found_matches = True
print(f'found typed_events in {file_path}:')
for match in typed_matches:
name = match[0]
args = match[1]
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = f'TYPED_EVENT({name}, {args});'
was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" )
new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};"
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
handlers_pattern = r'_(\w+)Handlers\('
handler_matches = re.findall(handlers_pattern, content)
if handler_matches:
found_matches = True
print(f'found handlers in {file_path}:')
for match in handler_matches:
name = match
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = f'_{name}Handlers('
new_declaration = f'{name}.raise('
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
if found_matches:
with open(file_path, 'w', encoding="utf8") as file:
file.write(content)
def find_and_replace(directory):
for root, dirs, files in os.walk(directory):
if 'Generated Files' in dirs:
dirs.remove('Generated Files') # Exclude the "Generated Files" directory
for file in files:
if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'):
file_path = os.path.join(root, file)
try:
replace_in_file(file_path, file)
except Exception as e:
print(f"error reading {file_path}")
if file == "TermControl.cpp":
print(e)
# raise e
# Replace in files within a specific directory
directory_path = 'D:\\dev\\public\\terminal\\src'
find_and_replace(directory_path)
```
</details>
[^1]: there are other macros we use that were also using this macro,
those weren't replaced.
---------
Co-authored-by: Dustin Howett <duhowett@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
139 lines
5.6 KiB
C++
139 lines
5.6 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&& 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&&, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& 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:
|
|
// - <none>
|
|
// 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(const Windows::Foundation::IInspectable& /*sender*/,
|
|
const Windows::UI::Xaml::RoutedEventArgs& /*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)
|
|
{
|
|
TitleChangeRequested.raise(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);
|
|
RenameEnded.raise(*this, nullptr);
|
|
}
|
|
}
|
|
}
|