From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- desktop/source/lib/lokclipboard.cxx | 231 ++++++++++++++++++++++++++++++++++++ 1 file changed, 231 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 000000000..7efaca9ab --- /dev/null +++ b/desktop/source/lib/lokclipboard.cxx @@ -0,0 +1,231 @@ +/* -*- 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 + +using namespace css; +using namespace css::uno; + +/* static */ osl::Mutex LOKClipboardFactory::gMutex; +static vcl::DeleteOnDeinit>> +gClipboards(new std::unordered_map>); + +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 uno::Reference( + 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.SystemClipboard" }; + 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); + m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener), + m_aListeners.end()); +} +LOKTransferable::LOKTransferable(const OUString& sMimeType, + const css::uno::Sequence& aSequence) +{ + m_aContent.reserve(1); + m_aFlavors = css::uno::Sequence(1); + initFlavourFromMime(m_aFlavors[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[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); + for (size_t i = 0; i < nInCount; ++i) + { + initFlavourFromMime(m_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::Any(); +} + +uno::Sequence SAL_CALL LOKTransferable::getTransferDataFlavors() +{ + return m_aFlavors; +} + +sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor) +{ + return std::find_if(m_aFlavors.begin(), m_aFlavors.end(), + [&rFlavor](const datatransfer::DataFlavor& i) { + return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType; + }) + != m_aFlavors.end(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3