Repository: microsoft/terminal
File: src/cascadia/TerminalControl/TermControl.cpp (C++)

Code before:
        // when it doesn't currently compose characters. For instance writing "xin chaof" with the
        // Vietnamese IME should produce "xin chào". After writing "xin" it'll emit a composition
        // completion event and we'll write "xin" to the shell. It now has no input focus and won't know
        // about the whitespace. If you then write "chaof", it'll emit another composition completion
        // event for "xinchaof" and the resulting output in the shell will finally read "xinxinchaof".
        // A composition completion event technically doesn't mean that the completed text is now
        // immutable after all. We could (and probably should) inform TSF of any input changes,
        // but we technically aren't a text input field. The immediate solution was
        // to simply force TSF to clear its text whenever we have input focus.
        TSFInputControl().ClearBuffer();

        _HidePointerCursorHandlers(*this, nullptr);

        const auto ch = e.Character();
        const auto keyStatus = e.KeyStatus();
        const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
        auto modifiers = _GetPressedModifierKeys();

        if (keyStatus.IsExtendedKey)
        {
            modifiers |= ControlKeyStates::EnhancedKey;
        }

        // Broadcast the character to all listeners
        auto charSentArgs = winrt::make<CharSentEventArgs>(ch, scanCode, modifiers);
        _CharSentHandlers(*this, charSentArgs);

        const auto handled = BroadcastChar(ch, scanCode, modifiers);

        e.Handled(handled);
    }

    bool TermControl::BroadcastChar(const wchar_t character,
                                    const WORD scanCode,
                                    const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers)
    {
        const auto handled = _core.SendCharEvent(character, scanCode, modifiers);
        return handled;
    }

    // Method Description:
    // - Manually handles key events for certain keys that can't be passed to us
    //   normally. Namely, the keys we're concerned with are F7 down and Alt up.
    // Return value:
    // - Whether the key was handled.
    bool TermControl::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
    {
        // Short-circuit isReadOnly check to avoid warning dialog
        if (_core.IsInReadOnlyMode())
        {
            return false;

Review comment (performance):
one last thing I'd be way of is the object cost. Every character, every key, is getting another heap allocated object that is bubbled up to somebody who is listening. It's not likely to be a bottleneck -- human typing speed is limited, after all -- but it's worth considering.

Code after:
            auto noticeArgs = winrt::make<NoticeEventArgs>(NoticeLevel::Warning, std::move(message));
            control->_RaiseNoticeHandlers(*control, std::move(noticeArgs));
        }
    }

    void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle)
    {
        auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative2>();
        nativePanel->SetSwapChainHandle(swapChainHandle);
    }

    bool TermControl::_InitializeTerminal(const InitializeReason reason)
    {
        if (_initializedTerminal)
        {
            return false;
        }

        const auto panelWidth = static_cast<float>(SwapChainPanel().ActualWidth());
        const auto panelHeight = static_cast<float>(SwapChainPanel().ActualHeight());
        const auto panelScaleX = SwapChainPanel().CompositionScaleX();
        const auto panelScaleY = SwapChainPanel().CompositionScaleY();

        const auto windowWidth = panelWidth * panelScaleX;
        const auto windowHeight = panelHeight * panelScaleY;

        if (windowWidth == 0 || windowHeight == 0)
        {
            return false;
        }

        // If we're re-attaching an existing content, then we want to proceed even though the Terminal was already initialized.
        if (reason == InitializeReason::Create)
        {
            const auto coreInitialized = _core.Initialize(panelWidth,
                                                          panelHeight,
                                                          panelScaleX);
            if (!coreInitialized)
            {
                return false;
            }
            _interactivity.Initialize();
        }
        else
        {
            _core.SizeOrScaleChanged(panelWidth, panelHeight, panelScaleX);
        }

        _core.EnablePainting();

        auto bufferHeight = _core.BufferHeight();