docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / desktop / source / lib / lokclipboard.cxx
blobc64a9ecd9cb2ba063bd420cb64dacc1b68fc0e1c
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 <tools/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 tools::DeleteOnDeinit<std::unordered_map<int, rtl::Reference<LOKClipboard>>>& getClipboards()
25 static tools::DeleteOnDeinit<std::unordered_map<int, rtl::Reference<LOKClipboard>>>
26 gClipboards{};
27 return gClipboards;
30 rtl::Reference<LOKClipboard> LOKClipboardFactory::getClipboardForCurView()
32 int nViewId = SfxLokHelper::getView(); // currently active.
34 osl::MutexGuard aGuard(gMutex);
36 auto& gClipboards = getClipboards();
37 auto it = gClipboards.get()->find(nViewId);
38 if (it != gClipboards.get()->end())
40 SAL_INFO("lok", "Got clip: " << it->second.get() << " from " << nViewId);
41 return it->second;
43 rtl::Reference<LOKClipboard> xClip(new LOKClipboard());
44 (*gClipboards.get())[nViewId] = xClip;
45 SAL_INFO("lok", "Created clip: " << xClip.get() << " for viewId " << nViewId);
46 return xClip;
49 void LOKClipboardFactory::releaseClipboardForView(int nViewId)
51 osl::MutexGuard aGuard(gMutex);
53 auto& gClipboards = getClipboards();
54 if (nViewId < 0) // clear all
56 gClipboards.get()->clear();
57 SAL_INFO("lok", "Released all clipboards on doc destroy\n");
59 else if (gClipboards.get())
61 auto it = gClipboards.get()->find(nViewId);
62 if (it != gClipboards.get()->end())
64 SAL_INFO("lok", "Releasing clip: " << it->second.get() << " for destroyed " << nViewId);
65 gClipboards.get()->erase(it);
70 uno::Reference<uno::XInterface>
71 SAL_CALL LOKClipboardFactory::createInstanceWithArguments(const Sequence<Any>& /* rArgs */)
73 return { static_cast<cppu::OWeakObject*>(getClipboardForCurView().get()) };
76 LOKClipboard::LOKClipboard()
77 : cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
78 css::lang::XServiceInfo>(m_aMutex)
80 // Encourage 'paste' menu items to always show up.
81 uno::Reference<datatransfer::XTransferable> xTransferable(new LOKTransferable());
82 setContents(xTransferable, uno::Reference<datatransfer::clipboard::XClipboardOwner>());
85 Sequence<OUString> LOKClipboard::getSupportedServiceNames_static()
87 Sequence<OUString> aRet{ u"com.sun.star.datatransfer.clipboard.LokClipboard"_ustr };
88 return aRet;
91 OUString LOKClipboard::getImplementationName()
93 return u"com.sun.star.datatransfer.LOKClipboard"_ustr;
96 Sequence<OUString> LOKClipboard::getSupportedServiceNames()
98 return getSupportedServiceNames_static();
101 sal_Bool LOKClipboard::supportsService(const OUString& ServiceName)
103 return cppu::supportsService(this, ServiceName);
106 Reference<css::datatransfer::XTransferable> LOKClipboard::getContents() { return m_xTransferable; }
108 void LOKClipboard::setContents(
109 const Reference<css::datatransfer::XTransferable>& xTrans,
110 const Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
112 osl::ClearableMutexGuard aGuard(m_aMutex);
113 Reference<datatransfer::clipboard::XClipboardOwner> xOldOwner(m_aOwner);
114 Reference<datatransfer::XTransferable> xOldContents(m_xTransferable);
115 m_xTransferable = xTrans;
116 m_aOwner = xClipboardOwner;
118 std::vector<Reference<datatransfer::clipboard::XClipboardListener>> aListeners(m_aListeners);
119 datatransfer::clipboard::ClipboardEvent aEv;
120 aEv.Contents = m_xTransferable;
121 SAL_INFO("lok", "Clip: " << this << " set contents to " << m_xTransferable);
123 aGuard.clear();
125 if (xOldOwner.is() && xOldOwner != xClipboardOwner)
126 xOldOwner->lostOwnership(this, xOldContents);
127 for (auto const& listener : aListeners)
129 listener->changedContents(aEv);
133 void LOKClipboard::addClipboardListener(
134 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
136 osl::ClearableMutexGuard aGuard(m_aMutex);
137 m_aListeners.push_back(listener);
140 void LOKClipboard::removeClipboardListener(
141 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
143 osl::ClearableMutexGuard aGuard(m_aMutex);
144 std::erase(m_aListeners, listener);
146 LOKTransferable::LOKTransferable(const OUString& sMimeType,
147 const css::uno::Sequence<sal_Int8>& aSequence)
149 m_aContent.reserve(1);
150 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
151 initFlavourFromMime(m_aFlavors.getArray()[0], sMimeType);
153 uno::Any aContent;
154 if (m_aFlavors[0].DataType == cppu::UnoType<OUString>::get())
156 auto pText = reinterpret_cast<const char*>(aSequence.getConstArray());
157 aContent <<= OUString(pText, aSequence.getLength(), RTL_TEXTENCODING_UTF8);
159 else
160 aContent <<= aSequence;
161 m_aContent.push_back(aContent);
164 /// Use to ensure we have some dummy content on the clipboard to allow a 1st 'paste'
165 LOKTransferable::LOKTransferable()
167 m_aContent.reserve(1);
168 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
169 initFlavourFromMime(m_aFlavors.getArray()[0], u"text/plain"_ustr);
170 uno::Any aContent;
171 aContent <<= OUString();
172 m_aContent.push_back(aContent);
175 // cf. sot/source/base/exchange.cxx for these two exceptional types.
176 void LOKTransferable::initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor,
177 OUString aMimeType)
179 if (aMimeType.startsWith("text/plain"))
181 aMimeType = "text/plain;charset=utf-16";
182 rFlavor.DataType = cppu::UnoType<OUString>::get();
184 else if (aMimeType == "application/x-libreoffice-tsvc")
185 rFlavor.DataType = cppu::UnoType<OUString>::get();
186 else
187 rFlavor.DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
188 rFlavor.MimeType = aMimeType;
189 rFlavor.HumanPresentableName = aMimeType;
192 LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeTypes,
193 const size_t* pInSizes, const char** pInStreams)
195 m_aContent.reserve(nInCount);
196 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(nInCount);
197 auto p_aFlavors = m_aFlavors.getArray();
198 for (size_t i = 0; i < nInCount; ++i)
200 initFlavourFromMime(p_aFlavors[i], OUString::fromUtf8(pInMimeTypes[i]));
202 uno::Any aContent;
203 if (m_aFlavors[i].DataType == cppu::UnoType<OUString>::get())
204 aContent <<= OUString(pInStreams[i], pInSizes[i], RTL_TEXTENCODING_UTF8);
205 else
206 aContent <<= css::uno::Sequence<sal_Int8>(
207 reinterpret_cast<const sal_Int8*>(pInStreams[i]), pInSizes[i]);
208 m_aContent.push_back(aContent);
212 uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
214 assert(m_aContent.size() == static_cast<size_t>(m_aFlavors.getLength()));
215 for (size_t i = 0; i < m_aContent.size(); ++i)
217 if (m_aFlavors[i].MimeType == rFlavor.MimeType)
219 if (m_aFlavors[i].DataType != rFlavor.DataType)
220 SAL_WARN("lok", "Horror type mismatch!");
221 return m_aContent[i];
224 return {};
227 uno::Sequence<datatransfer::DataFlavor> SAL_CALL LOKTransferable::getTransferDataFlavors()
229 return m_aFlavors;
232 sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor)
234 return std::find_if(std::cbegin(m_aFlavors), std::cend(m_aFlavors),
235 [&rFlavor](const datatransfer::DataFlavor& i) {
236 return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType;
238 != std::cend(m_aFlavors);
241 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
242 desktop_LOKClipboard_get_implementation(css::uno::XComponentContext*,
243 css::uno::Sequence<css::uno::Any> const& /*args*/)
245 SolarMutexGuard aGuard;
247 cppu::OWeakObject* pClipboard = LOKClipboardFactory::getClipboardForCurView().get();
249 pClipboard->acquire();
250 return pClipboard;
253 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */