LibreOffice Module vcl (master)  1
dtranscomp.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  * 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 <tools/debug.hxx>
24 #include <vcl/svapp.hxx>
25 
26 #include <factory.hxx>
27 #include <svdata.hxx>
28 #include <salinst.hxx>
29 
30 #include <com/sun/star/lang/IllegalArgumentException.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
34 #include <com/sun/star/lang/XInitialization.hpp>
35 #include <com/sun/star/datatransfer/XTransferable.hpp>
36 #include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp>
37 #include <com/sun/star/datatransfer/clipboard/XSystemClipboard.hpp>
38 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
39 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
40 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
41 
42 #include <comphelper/compbase.hxx>
44 
45 using namespace com::sun::star;
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::lang;
48 
49 namespace vcl
50 {
51 namespace {
52 
53 // generic implementation to satisfy SalInstance
54 class GenericClipboard :
56  datatransfer::clipboard::XSystemClipboard,
57  XServiceInfo
58  >
59 {
62  std::vector< Reference< css::datatransfer::clipboard::XClipboardListener > > m_aListeners;
63 
64 public:
65 
66  GenericClipboard()
67  {}
68 
69  /*
70  * XServiceInfo
71  */
72 
73  virtual OUString SAL_CALL getImplementationName() override;
74  virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
75  virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
76 
77  static Sequence< OUString > getSupportedServiceNames_static();
78 
79  /*
80  * XClipboard
81  */
82 
83  virtual Reference< css::datatransfer::XTransferable > SAL_CALL getContents() override;
84 
85  virtual void SAL_CALL setContents(
87  const Reference< css::datatransfer::clipboard::XClipboardOwner >& xClipboardOwner ) override;
88 
89  virtual OUString SAL_CALL getName() override;
90 
91  /*
92  * XClipboardEx
93  */
94 
95  virtual sal_Int8 SAL_CALL getRenderingCapabilities() override;
96 
97  /*
98  * XClipboardNotifier
99  */
100  virtual void SAL_CALL addClipboardListener(
102 
103  virtual void SAL_CALL removeClipboardListener(
105 };
106 
107 }
108 
109 Sequence< OUString > GenericClipboard::getSupportedServiceNames_static()
110 {
111  Sequence< OUString > aRet { "com.sun.star.datatransfer.clipboard.SystemClipboard" };
112  return aRet;
113 }
114 
115 OUString GenericClipboard::getImplementationName()
116 {
117  return "com.sun.star.datatransfer.VCLGenericClipboard";
118 }
119 
120 Sequence< OUString > GenericClipboard::getSupportedServiceNames()
121 {
122  return getSupportedServiceNames_static();
123 }
124 
125 sal_Bool GenericClipboard::supportsService( const OUString& ServiceName )
126 {
127  return cppu::supportsService(this, ServiceName);
128 }
129 
130 Reference< css::datatransfer::XTransferable > GenericClipboard::getContents()
131 {
132  return m_aContents;
133 }
134 
135 void GenericClipboard::setContents(
138 {
139  std::unique_lock aGuard( m_aMutex );
142  m_aContents = xTrans;
143  m_aOwner = xClipboardOwner;
144 
145  std::vector< Reference< datatransfer::clipboard::XClipboardListener > > aListeners( m_aListeners );
146  datatransfer::clipboard::ClipboardEvent aEv;
147  aEv.Contents = m_aContents;
148 
149  aGuard.unlock();
150 
151  if( xOldOwner.is() && xOldOwner != xClipboardOwner )
152  xOldOwner->lostOwnership( this, xOldContents );
153  for (auto const& listener : aListeners)
154  {
155  listener->changedContents( aEv );
156  }
157 }
158 
159 OUString GenericClipboard::getName()
160 {
161  return "CLIPBOARD";
162 }
163 
164 sal_Int8 GenericClipboard::getRenderingCapabilities()
165 {
166  return 0;
167 }
168 
169 void GenericClipboard::addClipboardListener( const Reference< datatransfer::clipboard::XClipboardListener >& listener )
170 {
171  std::unique_lock aGuard(m_aMutex);
172 
173  m_aListeners.push_back( listener );
174 }
175 
176 void GenericClipboard::removeClipboardListener( const Reference< datatransfer::clipboard::XClipboardListener >& listener )
177 {
178  std::unique_lock aGuard(m_aMutex);
179 
180  m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener), m_aListeners.end());
181 }
182 
183 
184 
185 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
187  css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& args)
188 {
189  SolarMutexGuard aGuard;
190  auto xClipboard = ImplGetSVData()->mpDefInst->CreateClipboard( args );
191  if (xClipboard.is())
192  xClipboard->acquire();
193  return xClipboard.get();
194 }
195 
196 namespace {
197 
198 /*
199 * generic DragSource dummy
200 */
201 class GenericDragSource : public ::comphelper::WeakComponentImplHelper<
202  datatransfer::dnd::XDragSource,
203  XInitialization,
204  css::lang::XServiceInfo
205  >
206 {
207  css::uno::Reference<css::datatransfer::XTransferable> m_xTrans;
208 public:
209  GenericDragSource() {}
210 
211  // XDragSource
212  virtual sal_Bool SAL_CALL isDragImageSupported() override;
213  virtual sal_Int32 SAL_CALL getDefaultCursor( sal_Int8 dragAction ) override;
214  virtual void SAL_CALL startDrag(
215  const datatransfer::dnd::DragGestureEvent& trigger,
216  sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image,
217  const Reference< datatransfer::XTransferable >& transferable,
219  ) override;
220 
221  // XInitialization
222  virtual void SAL_CALL initialize( const Sequence< Any >& arguments ) override;
223 
224  OUString SAL_CALL getImplementationName() override
225  { return "com.sun.star.datatransfer.dnd.VclGenericDragSource"; }
226 
227  sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
228  { return cppu::supportsService(this, ServiceName); }
229 
230  css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
231  { return getSupportedServiceNames_static(); }
232 
233  static Sequence< OUString > getSupportedServiceNames_static()
234  {
235  return { "com.sun.star.datatransfer.dnd.GenericDragSource" };
236  }
237 };
238 
239 }
240 
241 sal_Bool GenericDragSource::isDragImageSupported()
242 {
243  return false;
244 }
245 
246 sal_Int32 GenericDragSource::getDefaultCursor( sal_Int8 )
247 {
248  return 0;
249 }
250 
251 void GenericDragSource::startDrag( const datatransfer::dnd::DragGestureEvent&,
252  sal_Int8 /*sourceActions*/, sal_Int32 /*cursor*/, sal_Int32 /*image*/,
255  )
256 {
258  m_xTrans = rTrans;
259  return;
260  }
261 
262  datatransfer::dnd::DragSourceDropEvent aEv;
263  aEv.DropAction = datatransfer::dnd::DNDConstants::ACTION_COPY;
264  aEv.DropSuccess = false;
265  listener->dragDropEnd( aEv );
266 }
267 
268 void GenericDragSource::initialize( const Sequence< Any >& )
269 {
270 }
271 
273 {
274 #if defined MACOSX
275  return { "com.sun.star.datatransfer.dnd.OleDragSource" };
276 #elif defined UNX
277  return { "com.sun.star.datatransfer.dnd.X11DragSource" };
278 #else
279  return { "com.sun.star.datatransfer.dnd.VclGenericDragSource" };
280 #endif
281 }
282 
284 {
285 #if defined MACOSX
286  return "com.sun.star.comp.datatransfer.dnd.OleDragSource_V1";
287 #elif defined UNX
288  return "com.sun.star.datatransfer.dnd.XdndSupport";
289 #else
290  return "com.sun.star.datatransfer.dnd.VclGenericDragSource";
291 #endif
292 }
293 
295 {
296  SolarMutexGuard aGuard;
298  return xResult;
299 }
300 
301 /*
302 * generic DragSource dummy
303 */
304 
305 namespace {
306 
307 class GenericDropTarget : public comphelper::WeakComponentImplHelper<
308  datatransfer::dnd::XDropTarget,
309  XInitialization,
310  css::lang::XServiceInfo
311  >
312 {
313 public:
314  GenericDropTarget() {}
315 
316  // XInitialization
317  virtual void SAL_CALL initialize( const Sequence< Any >& args ) override;
318 
319  // XDropTarget
320  virtual void SAL_CALL addDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& ) override;
321  virtual void SAL_CALL removeDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& ) override;
322  virtual sal_Bool SAL_CALL isActive() override;
323  virtual void SAL_CALL setActive( sal_Bool active ) override;
324  virtual sal_Int8 SAL_CALL getDefaultActions() override;
325  virtual void SAL_CALL setDefaultActions( sal_Int8 actions ) override;
326 
327  OUString SAL_CALL getImplementationName() override
328  { return "com.sun.star.datatransfer.dnd.VclGenericDropTarget"; }
329 
330  sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
331  { return cppu::supportsService(this, ServiceName); }
332 
333  css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
334  { return getSupportedServiceNames_static(); }
335 
336  static Sequence< OUString > getSupportedServiceNames_static()
337  {
338  return { "com.sun.star.datatransfer.dnd.GenericDropTarget" };
339  }
340 };
341 
342 }
343 
344 void GenericDropTarget::initialize( const Sequence< Any >& )
345 {
346 }
347 
348 void GenericDropTarget::addDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& )
349 {
350 }
351 
352 void GenericDropTarget::removeDropTargetListener( const Reference< css::datatransfer::dnd::XDropTargetListener >& )
353 {
354 }
355 
356 sal_Bool GenericDropTarget::isActive()
357 {
358  return false;
359 }
360 
361 void GenericDropTarget::setActive( sal_Bool )
362 {
363 }
364 
365 sal_Int8 GenericDropTarget::getDefaultActions()
366 {
367  return 0;
368 }
369 
370 void GenericDropTarget::setDefaultActions( sal_Int8)
371 {
372 }
373 
375 {
376 #if defined MACOSX
377  return { "com.sun.star.datatransfer.dnd.OleDropTarget" };
378 #elif defined UNX
379  return { "com.sun.star.datatransfer.dnd.X11DropTarget" };
380 #else
381  return GenericDropTarget::getSupportedServiceNames_static();
382 #endif
383 }
384 
386 {
387  return
388  #if defined MACOSX
389  "com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1"
390  #elif defined UNX
391  "com.sun.star.datatransfer.dnd.XdndDropTarget"
392  #else
393  "com.sun.star.datatransfer.dnd.VclGenericDropTarget"
394  #endif
395  ;
396 }
397 
399 {
400  SolarMutexGuard aGuard;
402  return xResult;
403 }
404 
405 } // namespace vcl
406 
407 /*
408 * SalInstance generic
409 */
411 {
412  if (arguments.hasElements()) {
413  throw css::lang::IllegalArgumentException(
414  "non-empty SalInstance::CreateClipboard arguments", {}, -1);
415  }
416 #ifdef IOS
417  return Reference< XInterface >( static_cast<cppu::OWeakObject *>(new vcl::GenericClipboard()) );
418 #else
420  // In LOK, each document view shall have its own clipboard instance, and the way that
421  // (happens to?) work is that apparently this function is called at most once for each such
422  // document view, so it is OK if we hand out a fresh instance on each call in LOK (whereas
423  // in non-LOK below we keep handing out one single instance; see also
424  // <https://lists.freedesktop.org/archives/libreoffice/2020-April/084824.html> "Re: Linux
425  // SAL_USE_VCLPLUGIN=svp and the clipboard"):
426  return Reference< XInterface >( static_cast<cppu::OWeakObject *>(new vcl::GenericClipboard()) );
427  }
428 #endif
430  if (!m_clipboard.is()) {
431  m_clipboard = static_cast<cppu::OWeakObject *>(new vcl::GenericClipboard());
432  }
433  return m_clipboard;
434 }
435 
436 uno::Reference<uno::XInterface> SalInstance::ImplCreateDragSource(const SystemEnvData*)
437 {
438  return css::uno::Reference<css::uno::XInterface>();
439 }
440 
442 {
443  // We run unit tests in parallel, which is a problem when touching a shared resource
444  // the system clipboard, so rather use the dummy GenericClipboard.
445  if (Application::IsHeadlessModeEnabled() || IsRunningUnitTest())
446  return Reference<XInterface>(static_cast<cppu::OWeakObject*>(new vcl::GenericDragSource()));
447  return ImplCreateDragSource(pSysEnv);
448 }
449 
450 uno::Reference<uno::XInterface> SalInstance::ImplCreateDropTarget(const SystemEnvData*)
451 {
452  return css::uno::Reference<css::uno::XInterface>();
453 }
454 
456 {
457  // see SalInstance::CreateDragSource
458  if (Application::IsHeadlessModeEnabled() || IsRunningUnitTest())
459  return Reference<XInterface>(static_cast<cppu::OWeakObject*>(new vcl::GenericDropTarget()));
460  return ImplCreateDropTarget(pSysEnv);
461 }
462 
463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Reference< css::uno::XInterface > CreateClipboard(const css::uno::Sequence< css::uno::Any > &i_rArguments)
Definition: dtranscomp.cxx:410
signed char sal_Int8
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
OUString DragSource_getImplementationName()
Definition: dtranscomp.cxx:283
std::vector< Reference< css::datatransfer::clipboard::XClipboardListener > > m_aListeners
Definition: dtranscomp.cxx:62
Reference< css::datatransfer::XTransferable > m_aContents
Definition: dtranscomp.cxx:60
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Listeners aListeners
virtual css::uno::Reference< css::uno::XInterface > ImplCreateDropTarget(const SystemEnvData *)
Definition: dtranscomp.cxx:450
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
Sequence< OUString > DropTarget_getSupportedServiceNames()
Definition: dtranscomp.cxx:374
Reference< XInterface > DragSource_createInstance(const Reference< XMultiServiceFactory > &)
Definition: dtranscomp.cxx:294
css::uno::Reference< css::uno::XInterface > CreateDragSource(const SystemEnvData *=nullptr)
Definition: dtranscomp.cxx:441
unsigned char sal_Bool
virtual css::uno::Reference< css::uno::XInterface > ImplCreateDragSource(const SystemEnvData *)
Definition: dtranscomp.cxx:436
Sequence< OUString > DragSource_getSupportedServiceNames()
Definition: dtranscomp.cxx:272
css::uno::Reference< css::datatransfer::XTransferable > m_xTrans
Definition: dtranscomp.cxx:207
static bool IsHeadlessModeEnabled()
Determines if headless mode is enabled.
Definition: svapp.cxx:1656
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * vcl_SystemClipboard_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &args)
Definition: dtranscomp.cxx:186
OUString DropTarget_getImplementationName()
Definition: dtranscomp.cxx:385
void setActive(bool bActive)
#define DBG_TESTSOLARMUTEX()
css::uno::Reference< css::uno::XInterface > CreateDropTarget(const SystemEnvData *=nullptr)
Definition: dtranscomp.cxx:455
Reference< XInterface > DropTarget_createInstance(const Reference< XMultiServiceFactory > &)
Definition: dtranscomp.cxx:398
SalInstance * mpDefInst
Definition: svdata.hxx:390
Reference< css::datatransfer::clipboard::XClipboardOwner > m_aOwner
Definition: dtranscomp.cxx:61