From 267c6f2ac71f92999e969232431ba04678e7437e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 07:54:39 +0200 Subject: Adding upstream version 4:24.2.0. Signed-off-by: Daniel Baumann --- desktop/source/lib/lokclipboard.cxx | 243 ++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 desktop/source/lib/lokclipboard.cxx (limited to 'desktop/source/lib/lokclipboard.cxx') diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx new file mode 100644 index 0000000000..f7d52ba466 --- /dev/null +++ b/desktop/source/lib/lokclipboard.cxx @@ -0,0 +1,243 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "lokclipboard.hxx" +#include +#include +#include +#include +#include +#include +#include + +using namespace css; +using namespace css::uno; + +/* static */ osl::Mutex LOKClipboardFactory::gMutex; +static vcl::DeleteOnDeinit>> gClipboards{}; + +rtl::Reference LOKClipboardFactory::getClipboardForCurView() +{ + int nViewId = SfxLokHelper::getView(); // currently active. + + osl::MutexGuard aGuard(gMutex); + + auto it = gClipboards.get()->find(nViewId); + if (it != gClipboards.get()->end()) + { + SAL_INFO("lok", "Got clip: " << it->second.get() << " from " << nViewId); + return it->second; + } + rtl::Reference xClip(new LOKClipboard()); + (*gClipboards.get())[nViewId] = xClip; + SAL_INFO("lok", "Created clip: " << xClip.get() << " for viewId " << nViewId); + return xClip; +} + +void LOKClipboardFactory::releaseClipboardForView(int nViewId) +{ + osl::MutexGuard aGuard(gMutex); + + if (nViewId < 0) // clear all + { + gClipboards.get()->clear(); + SAL_INFO("lok", "Released all clipboards on doc destroy\n"); + } + else if (gClipboards.get()) + { + auto it = gClipboards.get()->find(nViewId); + if (it != gClipboards.get()->end()) + { + SAL_INFO("lok", "Releasing clip: " << it->second.get() << " for destroyed " << nViewId); + gClipboards.get()->erase(it); + } + } +} + +uno::Reference + SAL_CALL LOKClipboardFactory::createInstanceWithArguments(const Sequence& /* rArgs */) +{ + return { static_cast(getClipboardForCurView().get()) }; +} + +LOKClipboard::LOKClipboard() + : cppu::WeakComponentImplHelper(m_aMutex) +{ + // Encourage 'paste' menu items to always show up. + uno::Reference xTransferable(new LOKTransferable()); + setContents(xTransferable, uno::Reference()); +} + +Sequence LOKClipboard::getSupportedServiceNames_static() +{ + Sequence aRet{ "com.sun.star.datatransfer.clipboard.LokClipboard" }; + return aRet; +} + +OUString LOKClipboard::getImplementationName() { return "com.sun.star.datatransfer.LOKClipboard"; } + +Sequence LOKClipboard::getSupportedServiceNames() +{ + return getSupportedServiceNames_static(); +} + +sal_Bool LOKClipboard::supportsService(const OUString& ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +Reference LOKClipboard::getContents() { return m_xTransferable; } + +void LOKClipboard::setContents( + const Reference& xTrans, + const Reference& xClipboardOwner) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + Reference xOldOwner(m_aOwner); + Reference xOldContents(m_xTransferable); + m_xTransferable = xTrans; + m_aOwner = xClipboardOwner; + + std::vector> aListeners(m_aListeners); + datatransfer::clipboard::ClipboardEvent aEv; + aEv.Contents = m_xTransferable; + SAL_INFO("lok", "Clip: " << this << " set contents to " << m_xTransferable); + + aGuard.clear(); + + if (xOldOwner.is() && xOldOwner != xClipboardOwner) + xOldOwner->lostOwnership(this, xOldContents); + for (auto const& listener : aListeners) + { + listener->changedContents(aEv); + } +} + +void LOKClipboard::addClipboardListener( + const Reference& listener) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + m_aListeners.push_back(listener); +} + +void LOKClipboard::removeClipboardListener( + const Reference& listener) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + std::erase(m_aListeners, listener); +} +LOKTransferable::LOKTransferable(const OUString& sMimeType, + const css::uno::Sequence& aSequence) +{ + m_aContent.reserve(1); + m_aFlavors = css::uno::Sequence(1); + initFlavourFromMime(m_aFlavors.getArray()[0], sMimeType); + + uno::Any aContent; + if (m_aFlavors[0].DataType == cppu::UnoType::get()) + { + auto pText = reinterpret_cast(aSequence.getConstArray()); + aContent <<= OUString(pText, aSequence.getLength(), RTL_TEXTENCODING_UTF8); + } + else + aContent <<= aSequence; + m_aContent.push_back(aContent); +} + +/// Use to ensure we have some dummy content on the clipboard to allow a 1st 'paste' +LOKTransferable::LOKTransferable() +{ + m_aContent.reserve(1); + m_aFlavors = css::uno::Sequence(1); + initFlavourFromMime(m_aFlavors.getArray()[0], "text/plain"); + uno::Any aContent; + aContent <<= OUString(); + m_aContent.push_back(aContent); +} + +// cf. sot/source/base/exchange.cxx for these two exceptional types. +void LOKTransferable::initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor, + OUString aMimeType) +{ + if (aMimeType.startsWith("text/plain")) + { + aMimeType = "text/plain;charset=utf-16"; + rFlavor.DataType = cppu::UnoType::get(); + } + else if (aMimeType == "application/x-libreoffice-tsvc") + rFlavor.DataType = cppu::UnoType::get(); + else + rFlavor.DataType = cppu::UnoType>::get(); + rFlavor.MimeType = aMimeType; + rFlavor.HumanPresentableName = aMimeType; +} + +LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeTypes, + const size_t* pInSizes, const char** pInStreams) +{ + m_aContent.reserve(nInCount); + m_aFlavors = css::uno::Sequence(nInCount); + auto p_aFlavors = m_aFlavors.getArray(); + for (size_t i = 0; i < nInCount; ++i) + { + initFlavourFromMime(p_aFlavors[i], OUString::fromUtf8(pInMimeTypes[i])); + + uno::Any aContent; + if (m_aFlavors[i].DataType == cppu::UnoType::get()) + aContent <<= OUString(pInStreams[i], pInSizes[i], RTL_TEXTENCODING_UTF8); + else + aContent <<= css::uno::Sequence( + reinterpret_cast(pInStreams[i]), pInSizes[i]); + m_aContent.push_back(aContent); + } +} + +uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor) +{ + assert(m_aContent.size() == static_cast(m_aFlavors.getLength())); + for (size_t i = 0; i < m_aContent.size(); ++i) + { + if (m_aFlavors[i].MimeType == rFlavor.MimeType) + { + if (m_aFlavors[i].DataType != rFlavor.DataType) + SAL_WARN("lok", "Horror type mismatch!"); + return m_aContent[i]; + } + } + return {}; +} + +uno::Sequence SAL_CALL LOKTransferable::getTransferDataFlavors() +{ + return m_aFlavors; +} + +sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor) +{ + return std::find_if(std::cbegin(m_aFlavors), std::cend(m_aFlavors), + [&rFlavor](const datatransfer::DataFlavor& i) { + return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType; + }) + != std::cend(m_aFlavors); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +desktop_LOKClipboard_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence const& /*args*/) +{ + SolarMutexGuard aGuard; + + cppu::OWeakObject* pClipboard = LOKClipboardFactory::getClipboardForCurView().get(); + + pClipboard->acquire(); + return pClipboard; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3