LibreOffice Module desktop (master) 1
lokclipboard.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 */
9
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>
17#include <com/sun/star/uno/XComponentContext.hpp>
18
19using namespace css;
20using namespace css::uno;
21
22/* static */ osl::Mutex LOKClipboardFactory::gMutex;
24
26{
27 int nViewId = SfxLokHelper::getView(); // currently active.
28
29 osl::MutexGuard aGuard(gMutex);
30
31 auto it = gClipboards.get()->find(nViewId);
32 if (it != gClipboards.get()->end())
33 {
34 SAL_INFO("lok", "Got clip: " << it->second.get() << " from " << nViewId);
35 return it->second;
36 }
38 (*gClipboards.get())[nViewId] = xClip;
39 SAL_INFO("lok", "Created clip: " << xClip.get() << " for viewId " << nViewId);
40 return xClip;
41}
42
44{
45 osl::MutexGuard aGuard(gMutex);
46
47 if (nViewId < 0) // clear all
48 {
49 gClipboards.get()->clear();
50 SAL_INFO("lok", "Released all clipboards on doc destroy\n");
51 }
52 else if (gClipboards.get())
53 {
54 auto it = gClipboards.get()->find(nViewId);
55 if (it != gClipboards.get()->end())
56 {
57 SAL_INFO("lok", "Releasing clip: " << it->second.get() << " for destroyed " << nViewId);
58 gClipboards.get()->erase(it);
59 }
60 }
61}
62
64 SAL_CALL LOKClipboardFactory::createInstanceWithArguments(const Sequence<Any>& /* rArgs */)
65{
66 return { static_cast<cppu::OWeakObject*>(getClipboardForCurView().get()) };
67}
68
70 : cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
71 css::lang::XServiceInfo>(m_aMutex)
72{
73 // Encourage 'paste' menu items to always show up.
76}
77
79{
80 Sequence<OUString> aRet{ "com.sun.star.datatransfer.clipboard.LokClipboard" };
81 return aRet;
82}
83
84OUString LOKClipboard::getImplementationName() { return "com.sun.star.datatransfer.LOKClipboard"; }
85
87{
89}
90
91sal_Bool LOKClipboard::supportsService(const OUString& ServiceName)
92{
94}
95
96Reference<css::datatransfer::XTransferable> LOKClipboard::getContents() { return m_xTransferable; }
97
99 const Reference<css::datatransfer::XTransferable>& xTrans,
100 const Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
101{
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;
107
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);
112
113 aGuard.clear();
114
115 if (xOldOwner.is() && xOldOwner != xClipboardOwner)
116 xOldOwner->lostOwnership(this, xOldContents);
117 for (auto const& listener : aListeners)
118 {
119 listener->changedContents(aEv);
120 }
121}
122
124 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
125{
126 osl::ClearableMutexGuard aGuard(m_aMutex);
127 m_aListeners.push_back(listener);
128}
129
131 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
132{
133 osl::ClearableMutexGuard aGuard(m_aMutex);
134 m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener),
135 m_aListeners.end());
136}
137LOKTransferable::LOKTransferable(const OUString& sMimeType,
138 const css::uno::Sequence<sal_Int8>& aSequence)
139{
140 m_aContent.reserve(1);
141 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
142 initFlavourFromMime(m_aFlavors.getArray()[0], sMimeType);
143
144 uno::Any aContent;
146 {
147 auto pText = reinterpret_cast<const char*>(aSequence.getConstArray());
148 aContent <<= OUString(pText, aSequence.getLength(), RTL_TEXTENCODING_UTF8);
149 }
150 else
151 aContent <<= aSequence;
152 m_aContent.push_back(aContent);
153}
154
157{
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);
164}
165
166// cf. sot/source/base/exchange.cxx for these two exceptional types.
167void LOKTransferable::initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor,
168 OUString aMimeType)
169{
170 if (aMimeType.startsWith("text/plain"))
171 {
172 aMimeType = "text/plain;charset=utf-16";
173 rFlavor.DataType = cppu::UnoType<OUString>::get();
174 }
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;
181}
182
183LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeTypes,
184 const size_t* pInSizes, const char** pInStreams)
185{
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)
190 {
191 initFlavourFromMime(p_aFlavors[i], OUString::fromUtf8(pInMimeTypes[i]));
192
193 uno::Any aContent;
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);
200 }
201}
202
203uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
204{
205 assert(m_aContent.size() == static_cast<size_t>(m_aFlavors.getLength()));
206 for (size_t i = 0; i < m_aContent.size(); ++i)
207 {
208 if (m_aFlavors[i].MimeType == rFlavor.MimeType)
209 {
210 if (m_aFlavors[i].DataType != rFlavor.DataType)
211 SAL_WARN("lok", "Horror type mismatch!");
212 return m_aContent[i];
213 }
214 }
215 return {};
216}
217
219{
220 return m_aFlavors;
221}
222
223sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor)
224{
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;
228 })
229 != std::cend(m_aFlavors);
230}
231
232extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
233desktop_LOKClipboard_get_implementation(css::uno::XComponentContext*,
234 css::uno::Sequence<css::uno::Any> const& /*args*/)
235{
236 SolarMutexGuard aGuard;
237
239
240 pClipboard->acquire();
241 return pClipboard;
242}
243
244/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static rtl::Reference< LOKClipboard > getClipboardForCurView()
Fetch clipboard from the global pool.
static void releaseClipboardForView(int nViewId)
Release a clipboard before its document dies, nViewId of -1 clears all.
static osl::Mutex gMutex
css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const css::uno::Sequence< css::uno::Any > &) override
A clipboard implementation for LibreOfficeKit.
OUString SAL_CALL getImplementationName() override
static Sequence< OUString > getSupportedServiceNames_static()
osl::Mutex m_aMutex
void SAL_CALL setContents(const css::uno::Reference< css::datatransfer::XTransferable > &xTransferable, const css::uno::Reference< css::datatransfer::clipboard::XClipboardOwner > &xClipboardOwner) override
std::vector< css::uno::Reference< css::datatransfer::clipboard::XClipboardListener > > m_aListeners
void SAL_CALL addClipboardListener(const css::uno::Reference< css::datatransfer::clipboard::XClipboardListener > &listener) override
void SAL_CALL removeClipboardListener(const css::uno::Reference< css::datatransfer::clipboard::XClipboardListener > &listener) override
css::uno::Reference< css::datatransfer::clipboard::XClipboardOwner > m_aOwner
css::uno::Reference< css::datatransfer::XTransferable > SAL_CALL getContents() override
Sequence< OUString > SAL_CALL getSupportedServiceNames() override
sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
css::uno::Reference< css::datatransfer::XTransferable > m_xTransferable
Represents the contents of LOKClipboard.
LOKTransferable()
Use to ensure we have some dummy content on the clipboard to allow a 1st 'paste'.
css::uno::Sequence< css::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors() override
sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor &rFlavor) override
static void initFlavourFromMime(css::datatransfer::DataFlavor &rFlavor, OUString aMimeType)
css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor &rFlavor) override
css::uno::Sequence< css::datatransfer::DataFlavor > m_aFlavors
std::vector< css::uno::Any > m_aContent
static int getView(const SfxViewShell *pViewShell=nullptr)
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
css::uno::Type const & get()
Listeners aListeners
std::mutex m_aMutex
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * desktop_LOKClipboard_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
static vcl::DeleteOnDeinit< std::unordered_map< int, rtl::Reference< LOKClipboard > > > gClipboards
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
DataType
const sal_Unicode *const aMimeType[]
unsigned char sal_Bool
signed char sal_Int8