Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/components/dtranscomp.cxx
Line
Count
Source
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
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sal/config.h>
21
22
#include <comphelper/lok.hxx>
23
#include <comphelper/processfactory.hxx>
24
#include <o3tl/test_info.hxx>
25
#include <osl/mutex.hxx>
26
#include <tools/debug.hxx>
27
#include <vcl/svapp.hxx>
28
29
#include <svdata.hxx>
30
#include <salinst.hxx>
31
32
#include <com/sun/star/lang/IllegalArgumentException.hpp>
33
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
34
#include <com/sun/star/lang/XServiceInfo.hpp>
35
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
36
#include <com/sun/star/lang/XInitialization.hpp>
37
#include <com/sun/star/datatransfer/XTransferable.hpp>
38
#include <com/sun/star/datatransfer/clipboard/LokClipboard.hpp>
39
#include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp>
40
#include <com/sun/star/datatransfer/clipboard/XSystemClipboard.hpp>
41
#include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
42
#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
43
#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
44
45
#include <comphelper/compbase.hxx>
46
#include <cppuhelper/supportsservice.hxx>
47
48
using namespace com::sun::star;
49
using namespace com::sun::star::uno;
50
using namespace com::sun::star::lang;
51
52
namespace vcl
53
{
54
namespace {
55
56
// generic implementation to satisfy SalInstance
57
class GenericClipboard :
58
        public comphelper::WeakComponentImplHelper<
59
        datatransfer::clipboard::XSystemClipboard,
60
        XServiceInfo
61
        >
62
{
63
    Reference< css::datatransfer::XTransferable >                           m_aContents;
64
    Reference< css::datatransfer::clipboard::XClipboardOwner >              m_aOwner;
65
    std::vector< Reference< css::datatransfer::clipboard::XClipboardListener > > m_aListeners;
66
67
public:
68
69
    GenericClipboard()
70
0
    {}
71
72
    /*
73
     * XServiceInfo
74
     */
75
76
    virtual OUString SAL_CALL getImplementationName() override;
77
    virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
78
    virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
79
80
    static Sequence< OUString > getSupportedServiceNames_static();
81
82
    /*
83
     * XClipboard
84
     */
85
86
    virtual Reference< css::datatransfer::XTransferable > SAL_CALL getContents() override;
87
88
    virtual void SAL_CALL setContents(
89
        const Reference< css::datatransfer::XTransferable >& xTrans,
90
        const Reference< css::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner ) override;
91
92
    virtual OUString SAL_CALL getName() override;
93
94
    /*
95
     * XClipboardEx
96
     */
97
98
    virtual sal_Int8 SAL_CALL getRenderingCapabilities() override;
99
100
    /*
101
     * XClipboardNotifier
102
     */
103
    virtual void SAL_CALL addClipboardListener(
104
        const Reference< css::datatransfer::clipboard::XClipboardListener >& listener ) override;
105
106
    virtual void SAL_CALL removeClipboardListener(
107
        const Reference< css::datatransfer::clipboard::XClipboardListener >& listener ) override;
108
};
109
110
}
111
112
Sequence< OUString > GenericClipboard::getSupportedServiceNames_static()
113
0
{
114
0
    Sequence< OUString > aRet { u"com.sun.star.datatransfer.clipboard.SystemClipboard"_ustr };
115
0
    return aRet;
116
0
}
117
118
OUString GenericClipboard::getImplementationName()
119
0
{
120
0
    return u"com.sun.star.datatransfer.VCLGenericClipboard"_ustr;
121
0
}
122
123
Sequence< OUString > GenericClipboard::getSupportedServiceNames()
124
0
{
125
0
    return getSupportedServiceNames_static();
126
0
}
127
128
sal_Bool GenericClipboard::supportsService( const OUString& ServiceName )
129
0
{
130
0
    return cppu::supportsService(this, ServiceName);
131
0
}
132
133
Reference< css::datatransfer::XTransferable > GenericClipboard::getContents()
134
0
{
135
0
    std::unique_lock aGuard(m_aMutex);
136
0
    return m_aContents;
137
0
}
138
139
void GenericClipboard::setContents(
140
        const Reference< css::datatransfer::XTransferable >& xTrans,
141
        const Reference< css::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner )
142
0
{
143
0
    std::unique_lock aGuard( m_aMutex );
144
0
    Reference< datatransfer::clipboard::XClipboardOwner > xOldOwner( m_aOwner );
145
0
    Reference< datatransfer::XTransferable > xOldContents( m_aContents );
146
0
    m_aContents = xTrans;
147
0
    m_aOwner = xClipboardOwner;
148
149
0
    std::vector< Reference< datatransfer::clipboard::XClipboardListener > > aListeners( m_aListeners );
150
0
    datatransfer::clipboard::ClipboardEvent aEv;
151
0
    aEv.Contents = m_aContents;
152
153
0
    aGuard.unlock();
154
155
0
    if( xOldOwner.is() && xOldOwner != xClipboardOwner )
156
0
        xOldOwner->lostOwnership( this, xOldContents );
157
0
    for (auto const& listener : aListeners)
158
0
    {
159
0
        listener->changedContents( aEv );
160
0
    }
161
0
}
162
163
OUString GenericClipboard::getName()
164
0
{
165
0
    return u"CLIPBOARD"_ustr;
166
0
}
167
168
sal_Int8 GenericClipboard::getRenderingCapabilities()
169
0
{
170
0
    return 0;
171
0
}
172
173
void GenericClipboard::addClipboardListener( const Reference< datatransfer::clipboard::XClipboardListener >& listener )
174
0
{
175
0
    std::unique_lock aGuard(m_aMutex);
176
177
0
    m_aListeners.push_back( listener );
178
0
}
179
180
void GenericClipboard::removeClipboardListener( const Reference< datatransfer::clipboard::XClipboardListener >& listener )
181
0
{
182
0
    std::unique_lock aGuard(m_aMutex);
183
184
0
    std::erase(m_aListeners, listener);
185
0
}
186
187
188
189
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
190
vcl_SystemClipboard_get_implementation(
191
    css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& args)
192
0
{
193
0
    SolarMutexGuard aGuard;
194
0
    auto xClipboard = ImplGetSVData()->mpDefInst->CreateClipboard( args );
195
0
    if (xClipboard.is())
196
0
        xClipboard->acquire();
197
0
    return xClipboard.get();
198
0
}
199
200
namespace {
201
202
/*
203
*   generic DragSource dummy
204
*/
205
class GenericDragSource : public ::comphelper::WeakComponentImplHelper<
206
            datatransfer::dnd::XDragSource,
207
            XInitialization,
208
            css::lang::XServiceInfo
209
            >
210
{
211
    css::uno::Reference<css::datatransfer::XTransferable> m_xTrans;
212
public:
213
0
    GenericDragSource() {}
214
215
    // XDragSource
216
    virtual sal_Bool    SAL_CALL isDragImageSupported() override;
217
    virtual sal_Int32   SAL_CALL getDefaultCursor( sal_Int8 dragAction ) override;
218
    virtual void        SAL_CALL startDrag(
219
                                     const datatransfer::dnd::DragGestureEvent& trigger,
220
                                     sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image,
221
                                     const Reference< datatransfer::XTransferable >& transferable,
222
                                     const Reference< datatransfer::dnd::XDragSourceListener >& listener
223
                                     ) override;
224
225
    // XInitialization
226
    virtual void        SAL_CALL initialize( const Sequence< Any >& arguments ) override;
227
228
    OUString SAL_CALL getImplementationName() override
229
0
    { return u"com.sun.star.datatransfer.dnd.VclGenericDragSource"_ustr; }
230
231
    sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
232
0
    { return cppu::supportsService(this, ServiceName); }
233
234
    css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
235
0
    { return getSupportedServiceNames_static(); }
236
237
    static Sequence< OUString > getSupportedServiceNames_static()
238
0
    {
239
0
       return { u"com.sun.star.datatransfer.dnd.GenericDragSource"_ustr };
240
0
    }
241
};
242
243
}
244
245
sal_Bool GenericDragSource::isDragImageSupported()
246
0
{
247
0
    return false;
248
0
}
249
250
sal_Int32 GenericDragSource::getDefaultCursor( sal_Int8 )
251
0
{
252
0
    return 0;
253
0
}
254
255
void GenericDragSource::startDrag( const datatransfer::dnd::DragGestureEvent&,
256
                                   sal_Int8 /*sourceActions*/, sal_Int32 /*cursor*/, sal_Int32 /*image*/,
257
                                   const Reference< datatransfer::XTransferable >& rTrans,
258
                                   const Reference< datatransfer::dnd::XDragSourceListener >& listener
259
                                   )
260
0
{
261
0
    if (comphelper::LibreOfficeKit::isActive()) {
262
0
        m_xTrans = rTrans;
263
0
        return;
264
0
    }
265
266
0
    datatransfer::dnd::DragSourceDropEvent aEv;
267
0
    aEv.DropAction = datatransfer::dnd::DNDConstants::ACTION_COPY;
268
0
    aEv.DropSuccess = false;
269
0
    listener->dragDropEnd( aEv );
270
0
}
271
272
void GenericDragSource::initialize( const Sequence< Any >& )
273
0
{
274
0
}
275
276
/*
277
*   generic DragSource dummy
278
*/
279
280
namespace {
281
282
class GenericDropTarget : public comphelper::WeakComponentImplHelper<
283
                                           datatransfer::dnd::XDropTarget,
284
                                           XInitialization,
285
                                           css::lang::XServiceInfo
286
                                           >
287
{
288
public:
289
0
    GenericDropTarget() {}
290
291
    // XInitialization
292
    virtual void        SAL_CALL initialize( const Sequence< Any >& args ) override;
293
294
    // XDropTarget
295
    virtual void        SAL_CALL addDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& ) override;
296
    virtual void        SAL_CALL removeDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& ) override;
297
    virtual sal_Bool    SAL_CALL isActive() override;
298
    virtual void        SAL_CALL setActive( sal_Bool active ) override;
299
    virtual sal_Int8    SAL_CALL getDefaultActions() override;
300
    virtual void        SAL_CALL setDefaultActions( sal_Int8 actions ) override;
301
302
    OUString SAL_CALL getImplementationName() override
303
0
    { return u"com.sun.star.datatransfer.dnd.VclGenericDropTarget"_ustr; }
304
305
    sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
306
0
    { return cppu::supportsService(this, ServiceName); }
307
308
    css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
309
0
    { return getSupportedServiceNames_static(); }
310
311
    static Sequence< OUString > getSupportedServiceNames_static()
312
0
    {
313
0
      return { u"com.sun.star.datatransfer.dnd.GenericDropTarget"_ustr };
314
0
    }
315
};
316
317
}
318
319
void GenericDropTarget::initialize( const Sequence< Any >& )
320
0
{
321
0
}
322
323
void GenericDropTarget::addDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& )
324
0
{
325
0
}
326
327
void GenericDropTarget::removeDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& )
328
0
{
329
0
}
330
331
sal_Bool GenericDropTarget::isActive()
332
0
{
333
0
    return false;
334
0
}
335
336
void GenericDropTarget::setActive( sal_Bool )
337
0
{
338
0
}
339
340
sal_Int8 GenericDropTarget::getDefaultActions()
341
0
{
342
0
    return 0;
343
0
}
344
345
void GenericDropTarget::setDefaultActions( sal_Int8)
346
0
{
347
0
}
348
349
} // namespace vcl
350
351
/*
352
*   SalInstance generic
353
*/
354
Reference<css::datatransfer::clipboard::XClipboard>
355
SalInstance::CreateClipboard(const Sequence<Any>& arguments)
356
0
{
357
0
    if (arguments.hasElements()) {
358
0
        throw css::lang::IllegalArgumentException(
359
0
            u"non-empty SalInstance::CreateClipboard arguments"_ustr, {}, -1);
360
0
    }
361
#ifdef IOS
362
    return new vcl::GenericClipboard();
363
#else
364
0
    if (comphelper::LibreOfficeKit::isActive()) {
365
        // In LOK, each document view shall have its own clipboard instance (whereas
366
        // in non-LOK below we keep handing out one single instance; see also
367
        // <https://lists.freedesktop.org/archives/libreoffice/2020-April/084824.html> "Re: Linux
368
        // SAL_USE_VCLPLUGIN=svp and the clipboard"):
369
0
        css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard =
370
0
            css::datatransfer::clipboard::LokClipboard::create(
371
0
                comphelper::getProcessComponentContext());
372
0
        return xClipboard;
373
0
    }
374
0
#endif
375
0
    DBG_TESTSOLARMUTEX();
376
0
    if (!m_clipboard.is()) {
377
0
        m_clipboard = new vcl::GenericClipboard();
378
0
    }
379
0
    return m_clipboard;
380
0
}
381
382
css::uno::Reference<css::datatransfer::dnd::XDragSource>
383
SalInstance::ImplCreateDragSource(const SystemEnvData&)
384
0
{
385
0
    return nullptr;
386
0
}
387
388
css::uno::Reference<css::datatransfer::dnd::XDragSource>
389
SalInstance::CreateDragSource(const SystemEnvData& rSysEnv)
390
0
{
391
    // We run unit tests in parallel, which is a problem when touching a shared resource
392
    // the system clipboard, so rather use the dummy GenericClipboard.
393
0
    if (Application::IsHeadlessModeEnabled() || o3tl::IsRunningUnitTest() || o3tl::IsRunningUITest())
394
0
        return new vcl::GenericDragSource();
395
0
    return ImplCreateDragSource(rSysEnv);
396
0
}
397
398
css::uno::Reference<css::datatransfer::dnd::XDropTarget>
399
SalInstance::ImplCreateDropTarget(const SystemEnvData&)
400
0
{
401
0
    return nullptr;
402
0
}
403
404
css::uno::Reference<css::datatransfer::dnd::XDropTarget>
405
SalInstance::CreateDropTarget(const SystemEnvData& rSysEnv)
406
0
{
407
    // see SalInstance::CreateDragSource
408
0
    if (Application::IsHeadlessModeEnabled() || o3tl::IsRunningUnitTest() || o3tl::IsRunningUITest())
409
0
        return new vcl::GenericDropTarget();
410
0
    return ImplCreateDropTarget(rSysEnv);
411
0
}
412
413
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */