Repository: microsoft/terminal
File: src/cascadia/WindowsTerminal/AppHost.cpp (C++)

Code before:

    _window->MakeWindow();

    _GetWindowLayoutRequestedToken = _windowManager.GetWindowLayoutRequested([this](auto&&, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& args) {
        // The peasants are running on separate threads, so they'll need to
        // swap what context they are in to the ui thread to get the actual layout.
        args.WindowLayoutJsonAsync(_GetWindowLayoutAsync());
    });

    _revokers.BecameMonarch = _windowManager.BecameMonarch(winrt::auto_revoke, { this, &AppHost::_BecomeMonarch });
    if (_windowManager.IsMonarch())
    {
        _BecomeMonarch(nullptr, nullptr);
    }

    // Create a throttled function for updating the window state, to match the
    // one requested by the pty. A 200ms delay was chosen because it's the
    // typical animation timeout in Windows. This does result in a delay between
    // the PTY requesting a change to the window state and the Terminal
    // realizing it, but should mitigate issues where the Terminal and PTY get
    // de-sync'd.
    _showHideWindowThrottler.emplace(std::move(std::chrono::milliseconds(200)),
                                     std::move([this](const bool show) -> winrt::fire_and_forget {
                                         co_await wil::resume_foreground(_logic.GetRoot().Dispatcher());
                                         _window->ShowWindowChanged(show);
                                     }));
}

AppHost::~AppHost()
{
    // destruction order is important for proper teardown here

    // revoke ALL our event handlers. There's a large class of bugs where we
    // might get a callback to one of these when we call app.Close() below. Make
    // sure to revoke these first, so we won't get any more callbacks, then null
    // out the window, then close the app.
    _revokers = {};

    _showHideWindowThrottler.reset();

    _window = nullptr;
    _app.Close();
    _app = nullptr;
}

bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
{
    if (_logic)
    {
        return _logic.OnDirectKeyEvent(vkey, scanCode, down);
    }

Review comment (suggestion):
You can replace this with `ThrottledFuncTrailing` from WinRTUtils, which should be included here already. Use it like so:
```cpp
_showHideWindowThrottler.emplace(
    _logic.GetRoot().Dispatcher(),
    std::chrono::milliseconds(200),
    [this](const bool show) -> winrt::fire_and_forget {
        _window->ShowWindowChanged(show);
    });
```

Code after:

    _window->MakeWindow();

    _GetWindowLayoutRequestedToken = _windowManager.GetWindowLayoutRequested([this](auto&&, const winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs& args) {
        // The peasants are running on separate threads, so they'll need to
        // swap what context they are in to the ui thread to get the actual layout.
        args.WindowLayoutJsonAsync(_GetWindowLayoutAsync());
    });

    _revokers.BecameMonarch = _windowManager.BecameMonarch(winrt::auto_revoke, { this, &AppHost::_BecomeMonarch });
    if (_windowManager.IsMonarch())
    {
        _BecomeMonarch(nullptr, nullptr);
    }

    // Create a throttled function for updating the window state, to match the
    // one requested by the pty. A 200ms delay was chosen because it's the
    // typical animation timeout in Windows. This does result in a delay between
    // the PTY requesting a change to the window state and the Terminal
    // realizing it, but should mitigate issues where the Terminal and PTY get
    // de-sync'd.
    _showHideWindowThrottler = std::make_shared<ThrottledFuncTrailing<bool>>(
        winrt::Windows::System::DispatcherQueue::GetForCurrentThread(),
        std::chrono::milliseconds(200),
        [this](const bool show) {
            _window->ShowWindowChanged(show);
        });
}

AppHost::~AppHost()
{
    // destruction order is important for proper teardown here

    // revoke ALL our event handlers. There's a large class of bugs where we
    // might get a callback to one of these when we call app.Close() below. Make
    // sure to revoke these first, so we won't get any more callbacks, then null
    // out the window, then close the app.
    _revokers = {};

    _showHideWindowThrottler.reset();

    _window = nullptr;
    _app.Close();
    _app = nullptr;
}

bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
{
    if (_logic)
    {
        return _logic.OnDirectKeyEvent(vkey, scanCode, down);