Repository: microsoft/terminal
File: src/cascadia/TerminalApp/TerminalPage.cpp (C++)

Code before:

                if (warningResult != ContentDialogResult::Primary)
                {
                    // user rejected the paste
                    co_return;
                }
            }

            co_await winrt::resume_background();
        }

        // This will end up calling ConptyConnection::WriteInput which calls WriteFile which may block for
        // an indefinite amount of time. Avoid freezes and deadlocks by running this on a background thread.
        assert(!dispatcher.HasThreadAccess());
        eventArgs.HandleClipboardData(std::move(text));
    }
    CATCH_LOG();

    // Method Description:
    // - This method is called when the user clicks the "export message history" button
    //   in the query palette
    // Arguments:
    // - text - the text to copy to the clipboard
    // Return Value:
    // - <none>
    void TerminalPage::_OnPasteToClipboardRequested(const IInspectable& /*sender*/, const winrt::hstring& text)
    {
        try
        {
            if (const auto clipboard = _openClipboard(nullptr))
            {
                EmptyClipboard();

                if (!text.empty())
                {
                    // As per: https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
                    //   CF_UNICODETEXT: [...] A null character signals the end of the data.
                    // --> We add +1 to the length. This works because .c_str() is null-terminated.
                    const auto bytes = (text.size() + 1) * sizeof(wchar_t);

                    wil::unique_hglobal handle{ THROW_LAST_ERROR_IF_NULL(GlobalAlloc(GMEM_MOVEABLE, bytes)) };

                    const auto locked = GlobalLock(handle.get());
                    memcpy(locked, text.c_str(), bytes);
                    GlobalUnlock(handle.get());

                    THROW_LAST_ERROR_IF_NULL(SetClipboardData(CF_UNICODETEXT, handle.get()));
                    handle.release();
                }
            }
        }

Review comment (suggestion):
I did not want to copy over the `_openClipboard` code/logic over to the ExtensionPalette (there are enough copies of that code already with one being in TermControl and one being in TerminalPage), so I figured we could have TerminalPage handle the request

Code after:
            const auto cap = DragQueryFileW(drop, 0, nullptr, 0);
            if (cap == 0)
            {
                return {};
            }

            auto buffer = winrt::impl::hstring_builder{ cap };
            const auto len = DragQueryFileW(drop, 0, buffer.data(), cap + 1);
            if (len == 0)
            {
                return {};
            }

            return buffer.to_hstring();
        }

        return {};
    }

    // Function Description:
    // - This function is called when the `TermControl` requests that we send
    //   it the clipboard's content.
    // - Retrieves the data from the Windows Clipboard and converts it to text.
    // - Shows warnings if the clipboard is too big or contains multiple lines
    //   of text.
    // - Sends the text back to the TermControl through the event's
    //   `HandleClipboardData` member function.
    // - Does some of this in a background thread, as to not hang/crash the UI thread.
    // Arguments:
    // - eventArgs: the PasteFromClipboard event sent from the TermControl
    fire_and_forget TerminalPage::_PasteFromClipboardHandler(const IInspectable /*sender*/, const PasteFromClipboardEventArgs eventArgs)
    try
    {
        // The old Win32 clipboard API as used below is somewhere in the order of 300-1000x faster than
        // the WinRT one on average, depending on CPU load. Don't use the WinRT clipboard API if you can.
        const auto weakThis = get_weak();
        const auto dispatcher = Dispatcher();
        const auto globalSettings = _settings.GlobalSettings();

        // GetClipboardData might block for up to 30s for delay-rendered contents.
        co_await winrt::resume_background();

        winrt::hstring text;
        if (const auto clipboard = _openClipboard(nullptr))
        {
            text = _extractClipboard();
        }

        if (globalSettings.TrimPaste())
        {
            text = { Utils::TrimPaste(text) };