Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / desktop / source / lib / lokclipboard.cxx
blob6a04f386ce17d2e856c06f12432ad47753551140
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "lokclipboard.hxx"
11 #include <unordered_map>
12 #include <vcl/lazydelete.hxx>
13 #include <vcl/svapp.hxx>
14 #include <sfx2/lokhelper.hxx>
15 #include <sal/log.hxx>
16 #include <cppuhelper/supportsservice.hxx>
17 #include <com/sun/star/uno/XComponentContext.hpp>
19 using namespace css;
20 using namespace css::uno;
22 /* static */ osl::Mutex LOKClipboardFactory::gMutex;
23 static vcl::DeleteOnDeinit<std::unordered_map<int, rtl::Reference<LOKClipboard>>> gClipboards{};
25 rtl::Reference<LOKClipboard> LOKClipboardFactory::getClipboardForCurView()
27 int nViewId = SfxLokHelper::getView(); // currently active.
29 osl::MutexGuard aGuard(gMutex);
31 auto it = gClipboards.get()->find(nViewId);
32 if (it != gClipboards.get()->end())
34 SAL_INFO("lok", "Got clip: " << it->second.get() << " from " << nViewId);
35 return it->second;
37 rtl::Reference<LOKClipboard> xClip(new LOKClipboard());
38 (*gClipboards.get())[nViewId] = xClip;
39 SAL_INFO("lok", "Created clip: " << xClip.get() << " for viewId " << nViewId);
40 return xClip;
43 void LOKClipboardFactory::releaseClipboardForView(int nViewId)
45 osl::MutexGuard aGuard(gMutex);
47 if (nViewId < 0) // clear all
49 gClipboards.get()->clear();
50 SAL_INFO("lok", "Released all clipboards on doc destroy\n");
52 else if (gClipboards.get())
54 auto it = gClipboards.get()->find(nViewId);
55 if (it != gClipboards.get()->end())
57 SAL_INFO("lok", "Releasing clip: " << it->second.get() << " for destroyed " << nViewId);
58 gClipboards.get()->erase(it);
63 uno::Reference<uno::XInterface>
64 SAL_CALL LOKClipboardFactory::createInstanceWithArguments(const Sequence<Any>& /* rArgs */)
66 return { static_cast<cppu::OWeakObject*>(getClipboardForCurView().get()) };
69 LOKClipboard::LOKClipboard()
70 : cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
71 css::lang::XServiceInfo>(m_aMutex)
73 // Encourage 'paste' menu items to always show up.
74 uno::Reference<datatransfer::XTransferable> xTransferable(new LOKTransferable());
75 setContents(xTransferable, uno::Reference<datatransfer::clipboard::XClipboardOwner>());
78 Sequence<OUString> LOKClipboard::getSupportedServiceNames_static()
80 Sequence<OUString> aRet{ "com.sun.star.datatransfer.clipboard.LokClipboard" };
81 return aRet;
84 OUString LOKClipboard::getImplementationName() { return "com.sun.star.datatransfer.LOKClipboard"; }
86 Sequence<OUString> LOKClipboard::getSupportedServiceNames()
88 return getSupportedServiceNames_static();
91 sal_Bool LOKClipboard::supportsService(const OUString& ServiceName)
93 return cppu::supportsService(this, ServiceName);
96 Reference<css::datatransfer::XTransferable> LOKClipboard::getContents() { return m_xTransferable; }
98 void LOKClipboard::setContents(
99 const Reference<css::datatransfer::XTransferable>& xTrans,
100 const Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
102 osl::ClearableMutexGuard aGuard(m_aMutex);
103 Reference<datatransfer::clipboard::XClipboardOwner> xOldOwner(m_aOwner);
104 Reference<datatransfer::XTransferable> xOldContents(m_xTransferable);
105 m_xTransferable = xTrans;
106 m_aOwner = xClipboardOwner;
108 std::vector<Reference<datatransfer::clipboard::XClipboardListener>> aListeners(m_aListeners);
109 datatransfer::clipboard::ClipboardEvent aEv;
110 aEv.Contents = m_xTransferable;
111 SAL_INFO("lok", "Clip: " << this << " set contents to " << m_xTransferable);
113 aGuard.clear();
115 if (xOldOwner.is() && xOldOwner != xClipboardOwner)
116 xOldOwner->lostOwnership(this, xOldContents);
117 for (auto const& listener : aListeners)
119 listener->changedContents(aEv);
123 void LOKClipboard::addClipboardListener(
124 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
126 osl::ClearableMutexGuard aGuard(m_aMutex);
127 m_aListeners.push_back(listener);
130 void LOKClipboard::removeClipboardListener(
131 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
133 osl::ClearableMutexGuard aGuard(m_aMutex);
134 m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener),
135 m_aListeners.end());
137 LOKTransferable::LOKTransferable(const OUString& sMimeType,
138 const css::uno::Sequence<sal_Int8>& aSequence)
140 m_aContent.reserve(1);
141 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
142 initFlavourFromMime(m_aFlavors.getArray()[0], sMimeType);
144 uno::Any aContent;
145 if (m_aFlavors[0].DataType == cppu::UnoType<OUString>::get())
147 auto pText = reinterpret_cast<const char*>(aSequence.getConstArray());
148 aContent <<= OUString(pText, aSequence.getLength(), RTL_TEXTENCODING_UTF8);
150 else
151 aContent <<= aSequence;
152 m_aContent.push_back(aContent);
155 /// Use to ensure we have some dummy content on the clipboard to allow a 1st 'paste'
156 LOKTransferable::LOKTransferable()
158 m_aContent.reserve(1);
159 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
160 initFlavourFromMime(m_aFlavors.getArray()[0], "text/plain");
161 uno::Any aContent;
162 aContent <<= OUString();
163 m_aContent.push_back(aContent);
166 // cf. sot/source/base/exchange.cxx for these two exceptional types.
167 void LOKTransferable::initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor,
168 OUString aMimeType)
170 if (aMimeType.startsWith("text/plain"))
172 aMimeType = "text/plain;charset=utf-16";
173 rFlavor.DataType = cppu::UnoType<OUString>::get();
175 else if (aMimeType == "application/x-libreoffice-tsvc")
176 rFlavor.DataType = cppu::UnoType<OUString>::get();
177 else
178 rFlavor.DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
179 rFlavor.MimeType = aMimeType;
180 rFlavor.HumanPresentableName = aMimeType;
183 LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeTypes,
184 const size_t* pInSizes, const char** pInStreams)
186 m_aContent.reserve(nInCount);
187 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(nInCount);
188 auto p_aFlavors = m_aFlavors.getArray();
189 for (size_t i = 0; i < nInCount; ++i)
191 initFlavourFromMime(p_aFlavors[i], OUString::fromUtf8(pInMimeTypes[i]));
193 uno::Any aContent;
194 if (m_aFlavors[i].DataType == cppu::UnoType<OUString>::get())
195 aContent <<= OUString(pInStreams[i], pInSizes[i], RTL_TEXTENCODING_UTF8);
196 else
197 aContent <<= css::uno::Sequence<sal_Int8>(
198 reinterpret_cast<const sal_Int8*>(pInStreams[i]), pInSizes[i]);
199 m_aContent.push_back(aContent);
203 uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
205 assert(m_aContent.size() == static_cast<size_t>(m_aFlavors.getLength()));
206 for (size_t i = 0; i < m_aContent.size(); ++i)
208 if (m_aFlavors[i].MimeType == rFlavor.MimeType)
210 if (m_aFlavors[i].DataType != rFlavor.DataType)
211 SAL_WARN("lok", "Horror type mismatch!");
212 return m_aContent[i];
215 return {};
218 uno::Sequence<datatransfer::DataFlavor> SAL_CALL LOKTransferable::getTransferDataFlavors()
220 return m_aFlavors;
223 sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor)
225 return std::find_if(std::cbegin(m_aFlavors), std::cend(m_aFlavors),
226 [&rFlavor](const datatransfer::DataFlavor& i) {
227 return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType;
229 != std::cend(m_aFlavors);
232 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
233 desktop_LOKClipboard_get_implementation(css::uno::XComponentContext*,
234 css::uno::Sequence<css::uno::Any> const& /*args*/)
236 SolarMutexGuard aGuard;
238 cppu::OWeakObject* pClipboard = LOKClipboardFactory::getClipboardForCurView().get();
240 pClipboard->acquire();
241 return pClipboard;
244 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */