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 <sfx2/lokhelper.hxx>
14#include <sal/log.hxx>
16
17using namespace css;
18using namespace css::uno;
19
20/* static */ osl::Mutex LOKClipboardFactory::gMutex;
22
24{
25 int nViewId = SfxLokHelper::getView(); // currently active.
26
27 osl::MutexGuard aGuard(gMutex);
28
29 auto it = gClipboards.get()->find(nViewId);
30 if (it != gClipboards.get()->end())
31 {
32 SAL_INFO("lok", "Got clip: " << it->second.get() << " from " << nViewId);
33 return it->second;
34 }
36 (*gClipboards.get())[nViewId] = xClip;
37 SAL_INFO("lok", "Created clip: " << xClip.get() << " for viewId " << nViewId);
38 return xClip;
39}
40
42{
43 osl::MutexGuard aGuard(gMutex);
44
45 if (nViewId < 0) // clear all
46 {
47 gClipboards.get()->clear();
48 SAL_INFO("lok", "Released all clipboards on doc destroy\n");
49 }
50 else if (gClipboards.get())
51 {
52 auto it = gClipboards.get()->find(nViewId);
53 if (it != gClipboards.get()->end())
54 {
55 SAL_INFO("lok", "Releasing clip: " << it->second.get() << " for destroyed " << nViewId);
56 gClipboards.get()->erase(it);
57 }
58 }
59}
60
62 SAL_CALL LOKClipboardFactory::createInstanceWithArguments(const Sequence<Any>& /* rArgs */)
63{
64 return { static_cast<cppu::OWeakObject*>(getClipboardForCurView().get()) };
65}
66
68 : cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard,
69 css::lang::XServiceInfo>(m_aMutex)
70{
71 // Encourage 'paste' menu items to always show up.
74}
75
77{
78 Sequence<OUString> aRet{ "com.sun.star.datatransfer.clipboard.SystemClipboard" };
79 return aRet;
80}
81
82OUString LOKClipboard::getImplementationName() { return "com.sun.star.datatransfer.LOKClipboard"; }
83
85{
87}
88
89sal_Bool LOKClipboard::supportsService(const OUString& ServiceName)
90{
92}
93
94Reference<css::datatransfer::XTransferable> LOKClipboard::getContents() { return m_xTransferable; }
95
97 const Reference<css::datatransfer::XTransferable>& xTrans,
98 const Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner)
99{
100 osl::ClearableMutexGuard aGuard(m_aMutex);
101 Reference<datatransfer::clipboard::XClipboardOwner> xOldOwner(m_aOwner);
102 Reference<datatransfer::XTransferable> xOldContents(m_xTransferable);
103 m_xTransferable = xTrans;
104 m_aOwner = xClipboardOwner;
105
106 std::vector<Reference<datatransfer::clipboard::XClipboardListener>> aListeners(m_aListeners);
107 datatransfer::clipboard::ClipboardEvent aEv;
108 aEv.Contents = m_xTransferable;
109 SAL_INFO("lok", "Clip: " << this << " set contents to " << m_xTransferable);
110
111 aGuard.clear();
112
113 if (xOldOwner.is() && xOldOwner != xClipboardOwner)
114 xOldOwner->lostOwnership(this, xOldContents);
115 for (auto const& listener : aListeners)
116 {
117 listener->changedContents(aEv);
118 }
119}
120
122 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
123{
124 osl::ClearableMutexGuard aGuard(m_aMutex);
125 m_aListeners.push_back(listener);
126}
127
129 const Reference<datatransfer::clipboard::XClipboardListener>& listener)
130{
131 osl::ClearableMutexGuard aGuard(m_aMutex);
132 m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener),
133 m_aListeners.end());
134}
135LOKTransferable::LOKTransferable(const OUString& sMimeType,
136 const css::uno::Sequence<sal_Int8>& aSequence)
137{
138 m_aContent.reserve(1);
139 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
140 initFlavourFromMime(m_aFlavors.getArray()[0], sMimeType);
141
142 uno::Any aContent;
144 {
145 auto pText = reinterpret_cast<const char*>(aSequence.getConstArray());
146 aContent <<= OUString(pText, aSequence.getLength(), RTL_TEXTENCODING_UTF8);
147 }
148 else
149 aContent <<= aSequence;
150 m_aContent.push_back(aContent);
151}
152
155{
156 m_aContent.reserve(1);
157 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(1);
158 initFlavourFromMime(m_aFlavors.getArray()[0], "text/plain");
159 uno::Any aContent;
160 aContent <<= OUString();
161 m_aContent.push_back(aContent);
162}
163
164// cf. sot/source/base/exchange.cxx for these two exceptional types.
165void LOKTransferable::initFlavourFromMime(css::datatransfer::DataFlavor& rFlavor,
166 OUString aMimeType)
167{
168 if (aMimeType.startsWith("text/plain"))
169 {
170 aMimeType = "text/plain;charset=utf-16";
171 rFlavor.DataType = cppu::UnoType<OUString>::get();
172 }
173 else if (aMimeType == "application/x-libreoffice-tsvc")
174 rFlavor.DataType = cppu::UnoType<OUString>::get();
175 else
176 rFlavor.DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
177 rFlavor.MimeType = aMimeType;
178 rFlavor.HumanPresentableName = aMimeType;
179}
180
181LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeTypes,
182 const size_t* pInSizes, const char** pInStreams)
183{
184 m_aContent.reserve(nInCount);
185 m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(nInCount);
186 auto p_aFlavors = m_aFlavors.getArray();
187 for (size_t i = 0; i < nInCount; ++i)
188 {
189 initFlavourFromMime(p_aFlavors[i], OUString::fromUtf8(pInMimeTypes[i]));
190
191 uno::Any aContent;
193 aContent <<= OUString(pInStreams[i], pInSizes[i], RTL_TEXTENCODING_UTF8);
194 else
195 aContent <<= css::uno::Sequence<sal_Int8>(
196 reinterpret_cast<const sal_Int8*>(pInStreams[i]), pInSizes[i]);
197 m_aContent.push_back(aContent);
198 }
199}
200
201uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
202{
203 assert(m_aContent.size() == static_cast<size_t>(m_aFlavors.getLength()));
204 for (size_t i = 0; i < m_aContent.size(); ++i)
205 {
206 if (m_aFlavors[i].MimeType == rFlavor.MimeType)
207 {
208 if (m_aFlavors[i].DataType != rFlavor.DataType)
209 SAL_WARN("lok", "Horror type mismatch!");
210 return m_aContent[i];
211 }
212 }
213 return {};
214}
215
217{
218 return m_aFlavors;
219}
220
221sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor)
222{
223 return std::find_if(std::cbegin(m_aFlavors), std::cend(m_aFlavors),
224 [&rFlavor](const datatransfer::DataFlavor& i) {
225 return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType;
226 })
227 != std::cend(m_aFlavors);
228}
229
230/* 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)
css::uno::Type const & get()
Listeners aListeners
std::mutex m_aMutex
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
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