lok: cleanup clipboards associated with a view on destruction.
[LibreOffice.git] / desktop / source / lib / lokclipboard.cxx
blob18b728c2343a65f003bce40c975b15d77665b0e0
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 <vcl/lazydelete.hxx>
12 #include <sfx2/lokhelper.hxx>
13 #include <cppuhelper/supportsservice.hxx>
15 using namespace css;
16 using namespace css::uno;
18 /* static */ osl::Mutex LOKClipboardFactory::gMutex;
19 static vcl::DeleteOnDeinit<std::unordered_map<int, rtl::Reference<LOKClipboard>>>
20 gClipboards(new std::unordered_map<int, rtl::Reference<LOKClipboard>>);
22 rtl::Reference<LOKClipboard> LOKClipboardFactory::getClipboardForCurView()
24 int nViewId = SfxLokHelper::getView(); // currently active.
26 osl::MutexGuard aGuard(gMutex);
28 auto it = gClipboards.get()->find(nViewId);
29 if (it != gClipboards.get()->end())
31 SAL_INFO("lok", "Got clip: " << it->second.get() << " from " << nViewId);
32 return it->second;
34 rtl::Reference<LOKClipboard> xClip(new LOKClipboard());
35 (*gClipboards.get())[nViewId] = xClip;
36 SAL_INFO("lok", "Created clip: " << xClip.get() << " for viewId " << nViewId);
37 return xClip;
40 /// FIXME: should really copy and stash its content for a bit.
41 void LOKClipboardFactory::releaseClipboardForView(int nViewId)
43 osl::MutexGuard aGuard(gMutex);
45 if (nViewId < 0) // clear all
47 gClipboards.get()->clear();
48 SAL_INFO("lok", "Released all clipboards on doc destroy\n");
50 else
52 auto it = gClipboards.get()->find(nViewId);
53 if (it != gClipboards.get()->end())
55 gClipboards.get()->erase(it);
56 SAL_INFO("lok", "Released clip: " << it->second.get() << " for destroyed " << nViewId);
61 uno::Reference<uno::XInterface>
62 SAL_CALL LOKClipboardFactory::createInstanceWithArguments(const Sequence<Any>& /* rArgs */)
64 return uno::Reference<uno::XInterface>(
65 static_cast<cppu::OWeakObject*>(getClipboardForCurView().get()));
68 LOKClipboard::LOKClipboard()
69 : cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
70 css::lang::XServiceInfo>(m_aMutex)
74 Sequence<OUString> LOKClipboard::getSupportedServiceNames_static()
76 Sequence<OUString> aRet{ "com.sun.star.datatransfer.clipboard.SystemClipboard" };
77 return aRet;
80 OUString LOKClipboard::getImplementationName()
82 return OUString("com.sun.star.datatransfer.LOKClipboard");
85 Sequence<OUString> LOKClipboard::getSupportedServiceNames()
87 return getSupportedServiceNames_static();
90 sal_Bool LOKClipboard::supportsService(const OUString& ServiceName)
92 return cppu::supportsService(this, ServiceName);
95 Reference<css::datatransfer::XTransferable> LOKClipboard::getContents() { return m_xTransferable; }
97 void LOKClipboard::setContents(
98 const Reference<css::datatransfer::XTransferable>& xTrans,
99 const Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
101 osl::ClearableMutexGuard aGuard(m_aMutex);
102 Reference<datatransfer::clipboard::XClipboardOwner> xOldOwner(m_aOwner);
103 Reference<datatransfer::XTransferable> xOldContents(m_xTransferable);
104 m_xTransferable = xTrans;
105 m_aOwner = xClipboardOwner;
107 std::vector<Reference<datatransfer::clipboard::XClipboardListener>> aListeners(m_aListeners);
108 datatransfer::clipboard::ClipboardEvent aEv;
109 aEv.Contents = m_xTransferable;
110 SAL_INFO("lok", "Clip: " << this << " set contents to " << m_xTransferable);
112 aGuard.clear();
114 if (xOldOwner.is() && xOldOwner != xClipboardOwner)
115 xOldOwner->lostOwnership(this, xOldContents);
116 for (auto const& listener : aListeners)
118 listener->changedContents(aEv);
122 void LOKClipboard::addClipboardListener(
123 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
125 osl::ClearableMutexGuard aGuard(m_aMutex);
126 m_aListeners.push_back(listener);
129 void LOKClipboard::removeClipboardListener(
130 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
132 osl::ClearableMutexGuard aGuard(m_aMutex);
133 m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener),
134 m_aListeners.end());
136 LOKTransferable::LOKTransferable(const OUString& sMimeType,
137 const css::uno::Sequence<sal_Int8>& aSequence)
139 m_aContent.reserve(1);
140 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
141 initFlavourFromMime(m_aFlavors[0], sMimeType);
143 uno::Any aContent;
144 if (m_aFlavors[0].DataType == cppu::UnoType<OUString>::get())
146 auto pText = reinterpret_cast<const sal_Char*>(aSequence.getConstArray());
147 aContent <<= OUString(pText, aSequence.getLength(), RTL_TEXTENCODING_UTF8);
149 else
150 aContent <<= aSequence;
151 m_aContent.push_back(aContent);
153 // cf. sot/source/base/exchange.cxx for these two exceptional types.
154 void LOKTransferable::initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor,
155 OUString aMimeType)
157 if (aMimeType.startsWith("text/plain"))
159 aMimeType = "text/plain;charset=utf-16";
160 rFlavor.DataType = cppu::UnoType<OUString>::get();
162 else if (aMimeType == "application/x-libreoffice-tsvc")
163 rFlavor.DataType = cppu::UnoType<OUString>::get();
164 else
165 rFlavor.DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
166 rFlavor.MimeType = aMimeType;
167 rFlavor.HumanPresentableName = aMimeType;
170 LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeTypes,
171 const size_t* pInSizes, const char** pInStreams)
173 m_aContent.reserve(nInCount);
174 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(nInCount);
175 for (size_t i = 0; i < nInCount; ++i)
177 OUString aMimeType = OUString::fromUtf8(pInMimeTypes[i]);
179 // cf. sot/source/base/exchange.cxx for these two exceptional types.
180 if (aMimeType.startsWith("text/plain"))
182 aMimeType = "text/plain;charset=utf-16";
183 m_aFlavors[i].DataType = cppu::UnoType<OUString>::get();
185 else if (aMimeType == "application/x-libreoffice-tsvc")
186 m_aFlavors[i].DataType = cppu::UnoType<OUString>::get();
187 else
188 m_aFlavors[i].DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
189 m_aFlavors[i].MimeType = aMimeType;
190 m_aFlavors[i].HumanPresentableName = aMimeType;
192 uno::Any aContent;
193 if (m_aFlavors[i].DataType == cppu::UnoType<OUString>::get())
194 aContent <<= OUString(pInStreams[i], pInSizes[i], RTL_TEXTENCODING_UTF8);
195 else
196 aContent <<= css::uno::Sequence<sal_Int8>(
197 reinterpret_cast<const sal_Int8*>(pInStreams[i]), pInSizes[i]);
198 m_aContent.push_back(aContent);
202 uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
204 assert(m_aContent.size() == static_cast<size_t>(m_aFlavors.getLength()));
205 for (size_t i = 0; i < m_aContent.size(); ++i)
207 if (m_aFlavors[i].MimeType == rFlavor.MimeType)
209 if (m_aFlavors[i].DataType != rFlavor.DataType)
210 SAL_WARN("lok", "Horror type mismatch!");
211 return m_aContent[i];
214 return uno::Any();
217 uno::Sequence<datatransfer::DataFlavor> SAL_CALL LOKTransferable::getTransferDataFlavors()
219 return m_aFlavors;
222 sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor)
224 return std::find_if(m_aFlavors.begin(), m_aFlavors.end(),
225 [&rFlavor](const datatransfer::DataFlavor& i) {
226 return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType;
228 != m_aFlavors.end();
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */