LibreOffice Module vcl (master)  1
transfer2.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 <config_features.h>
21 
22 #include <osl/mutex.hxx>
23 #include <sot/exchange.hxx>
24 #include <tools/debug.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/window.hxx>
28 #include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
29 #include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
30 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
31 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
32 #include <com/sun/star/uno/DeploymentException.hpp>
33 #include <svl/urlbmk.hxx>
34 #include <vcl/transfer.hxx>
35 
36 #include <svdata.hxx>
37 
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::io;
41 using namespace ::com::sun::star::datatransfer;
43 using namespace ::com::sun::star::datatransfer::dnd;
44 
45 
47  mrParent( rDragSourceHelper )
48 {
49 }
50 
51 
53 {
54 }
55 
56 
57 void SAL_CALL DragSourceHelper::DragGestureListener::disposing( const EventObject& )
58 {
59 }
60 
61 
62 void SAL_CALL DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent& rDGE )
63 {
64  const SolarMutexGuard aGuard;
65 
66  const Point aPtPixel( rDGE.DragOriginX, rDGE.DragOriginY );
67  mrParent.StartDrag( rDGE.DragAction, aPtPixel );
68 }
69 
70 
72  mxDragGestureRecognizer( pWindow->GetDragGestureRecognizer() )
73 {
74  if( mxDragGestureRecognizer.is() )
75  {
77  mxDragGestureRecognizer->addDragGestureListener( mxDragGestureListener );
78  }
79 }
80 
81 
83 {
84  Reference<XDragGestureRecognizer> xTmp;
85  {
86  osl::MutexGuard aGuard( maMutex );
89  }
90  if( xTmp.is() )
91  xTmp->removeDragGestureListener( mxDragGestureListener );
92 }
93 
95 {
96  dispose();
97 }
98 
99 
101 {
102 }
103 
104 
106  mrParent( rDropTargetHelper )
107 {
108 }
109 
110 
112 {
113 }
114 
115 
116 void SAL_CALL DropTargetHelper::DropTargetListener::disposing( const EventObject& )
117 {
118 }
119 
120 
121 void SAL_CALL DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent& rDTDE )
122 {
123  const SolarMutexGuard aGuard;
124 
125  try
126  {
127  AcceptDropEvent aAcceptEvent;
128  ExecuteDropEvent aExecuteEvt( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
129 
130  aExecuteEvt.mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
131 
132  // in case of a default action, call ::AcceptDrop first and use the returned
133  // accepted action as the execute action in the call to ::ExecuteDrop
134  aAcceptEvent.mnAction = aExecuteEvt.mnAction;
135  aAcceptEvent.maPosPixel = aExecuteEvt.maPosPixel;
136  static_cast<DropTargetEvent&>(const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent )) = rDTDE;
137  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).DropAction = rDTDE.DropAction;
138  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).LocationX = rDTDE.LocationX;
139  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).LocationY = rDTDE.LocationY;
140  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).SourceActions = rDTDE.SourceActions;
141  aAcceptEvent.mbLeaving = false;
142  aAcceptEvent.mbDefault = aExecuteEvt.mbDefault;
143 
144  sal_Int8 nRet = mrParent.AcceptDrop( aAcceptEvent );
145 
146  if( DNDConstants::ACTION_NONE != nRet )
147  {
148  rDTDE.Context->acceptDrop( nRet );
149 
150  if( aExecuteEvt.mbDefault )
151  aExecuteEvt.mnAction = nRet;
152 
153  nRet = mrParent.ExecuteDrop( aExecuteEvt );
154  }
155 
156  rDTDE.Context->dropComplete( DNDConstants::ACTION_NONE != nRet );
157 
158  mpLastDragOverEvent.reset();
159  }
160  catch( const css::uno::Exception& )
161  {
162  }
163 }
164 
165 
166 void SAL_CALL DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent& rDTDEE )
167 {
168  const SolarMutexGuard aGuard;
169 
170  try
171  {
172  mrParent.ImplBeginDrag( rDTDEE.SupportedDataFlavors );
173  }
174  catch( const css::uno::Exception& )
175  {
176  }
177 
178  dragOver( rDTDEE );
179 }
180 
181 
182 void SAL_CALL DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent& rDTDE )
183 {
184  const SolarMutexGuard aGuard;
185 
186  try
187  {
188  mpLastDragOverEvent.reset( new AcceptDropEvent( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE ) );
189  mpLastDragOverEvent->mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
190 
191  const sal_Int8 nRet = mrParent.AcceptDrop( *mpLastDragOverEvent );
192 
193  if( DNDConstants::ACTION_NONE == nRet )
194  rDTDE.Context->rejectDrag();
195  else
196  rDTDE.Context->acceptDrag( nRet );
197  }
198  catch( const css::uno::Exception& )
199  {
200  }
201 }
202 
203 
204 void SAL_CALL DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent& )
205 {
206  const SolarMutexGuard aGuard;
207 
208  try
209  {
210  if( mpLastDragOverEvent )
211  {
212  mpLastDragOverEvent->mbLeaving = true;
213  mrParent.AcceptDrop( *mpLastDragOverEvent );
214  mpLastDragOverEvent.reset();
215  }
216 
217  mrParent.ImplEndDrag();
218  }
219  catch( const css::uno::Exception& )
220  {
221  }
222 }
223 
224 
225 void SAL_CALL DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent& )
226 {
227 }
228 
229 
231  mxDropTarget( pWindow->GetDropTarget() )
232 {
233  ImplConstruct();
234 }
235 
236 
237 DropTargetHelper::DropTargetHelper( const Reference< XDropTarget >& rxDropTarget ) :
238  mxDropTarget( rxDropTarget )
239 {
240  ImplConstruct();
241 }
242 
243 
245 {
246  Reference< XDropTarget > xTmp;
247  {
248  osl::MutexGuard aGuard( maMutex );
249  xTmp = mxDropTarget;
250  mxDropTarget.clear();
251  }
252  if( xTmp.is() )
253  xTmp->removeDropTargetListener( mxDropTargetListener );
254 }
255 
257 {
258  dispose();
259 }
260 
261 
263 {
264  if( mxDropTarget.is() )
265  {
267  mxDropTarget->addDropTargetListener( mxDropTargetListener );
268  mxDropTarget->setActive( true );
269  }
270 }
271 
272 
273 void DropTargetHelper::ImplBeginDrag( const Sequence< DataFlavor >& rSupportedDataFlavors )
274 {
275  maFormats.clear();
277 }
278 
279 
281 {
282  maFormats.clear();
283 }
284 
285 
287 {
288  return DNDConstants::ACTION_NONE;
289 }
290 
291 
293 {
294  return DNDConstants::ACTION_NONE;
295 }
296 
297 
299 {
300  return std::any_of(maFormats.begin(), maFormats.end(),
301  [&](const DataFlavorEx& data) { return data.mnSotId == nFormat; });
302 }
303 
304 
305 // TransferDataContainer
306 
307 namespace {
308 
309 struct TDataCntnrEntry_Impl
310 {
311  css::uno::Any aAny;
313 };
314 
315 }
316 
318 {
319  std::vector< TDataCntnrEntry_Impl > aFmtList;
321  std::unique_ptr<INetBookmark> pBookmk;
322 
324  {
325  }
326 };
327 
328 
330  : pImpl( new TransferDataContainer_Impl )
331 {
332 }
333 
334 
336 {
337 }
338 
339 
341 {
342 }
343 
344 
346  const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
347 {
348  bool bFnd = false;
349  SotClipboardFormatId nFmtId = SotExchange::GetFormat( rFlavor );
350 
351  // test first the list
352  for (auto const& format : pImpl->aFmtList)
353  {
354  if( nFmtId == format.nId )
355  {
356  bFnd = SetAny( format.aAny );
357  break;
358  }
359  }
360 
361  // test second the bookmark pointer
362  if( !bFnd )
363  switch( nFmtId )
364  {
365  case SotClipboardFormatId::STRING:
366  case SotClipboardFormatId::SOLK:
367  case SotClipboardFormatId::NETSCAPE_BOOKMARK:
368  case SotClipboardFormatId::FILECONTENT:
369  case SotClipboardFormatId::FILEGRPDESCRIPTOR:
370  case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
371  if( pImpl->pBookmk )
372  bFnd = SetINetBookmark( *pImpl->pBookmk, rFlavor );
373  break;
374 
375  default: break;
376  }
377 
378  return bFnd;
379 }
380 
381 
383 {
384  if( !pImpl->pBookmk )
385  pImpl->pBookmk.reset( new INetBookmark( rBkmk ) );
386  else
387  *pImpl->pBookmk = rBkmk;
388 
389  AddFormat( SotClipboardFormatId::STRING );
390  AddFormat( SotClipboardFormatId::SOLK );
391  AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
392  AddFormat( SotClipboardFormatId::FILECONTENT );
393  AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
394  AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
395 }
396 
397 
399  const char* pData, sal_uLong nLen )
400 {
401  if( nLen )
402  {
403  TDataCntnrEntry_Impl aEntry;
404  aEntry.nId = nFormatId;
405 
406  Sequence< sal_Int8 > aSeq( nLen );
407  memcpy( aSeq.getArray(), pData, nLen );
408  aEntry.aAny <<= aSeq;
409  pImpl->aFmtList.push_back( aEntry );
410  AddFormat( nFormatId );
411  }
412 }
413 
414 
416  const OString& rStr )
417 {
418  CopyAnyData( nFormatId, rStr.getStr(), rStr.getLength() );
419 }
420 
421 
422 void TransferDataContainer::CopyString( SotClipboardFormatId nFmt, const OUString& rStr )
423 {
424  if( !rStr.isEmpty() )
425  {
426  TDataCntnrEntry_Impl aEntry;
427  aEntry.nId = nFmt;
428  aEntry.aAny <<= rStr;
429  pImpl->aFmtList.push_back( aEntry );
430  AddFormat( aEntry.nId );
431  }
432 }
433 
434 
435 void TransferDataContainer::CopyString( const OUString& rStr )
436 {
437  CopyString( SotClipboardFormatId::STRING, rStr );
438 }
439 
440 
442 {
443  return !pImpl->aFmtList.empty() ||
444  nullptr != pImpl->pBookmk;
445 }
446 
447 
449  vcl::Window* pWindow, sal_Int8 nDragSourceActions,
450  const Link<sal_Int8,void>& rLnk )
451 {
452  pImpl->aFinshedLnk = rLnk;
453  TransferableHelper::StartDrag( pWindow, nDragSourceActions );
454 }
455 
456 
458 {
459  pImpl->aFinshedLnk.Call( nDropAction );
460 }
461 
462 Reference<XClipboard> GetSystemClipboard()
463 {
464  // On Windows, the css.datatransfer.clipboard.SystemClipboard UNO service is implemented as a
465  // single-instance service (sysdtrans_component_getFactory,
466  // dtrans/source/win32/clipb/wcbentry.cxx) that needs timely disposing to join a spawned thread
467  // (done in DeInitVCL, vcl/source/app/svmain.cxx), while on other platforms it is implemented as
468  // a multi-instance service (ClipboardFactory, vcl/source/components/dtranscomp.cxx) so we
469  // should not hold on to a single instance here:
470 #if defined _WIN32
472  auto const data = ImplGetSVData();
473  if (!data->m_xSystemClipboard.is())
474  {
475  try
476  {
477  data->m_xSystemClipboard = css::datatransfer::clipboard::SystemClipboard::create(
479  }
480  catch (DeploymentException const &) {}
481  }
482  return data->m_xSystemClipboard;
483 #else
484  Reference<XClipboard> xClipboard;
485  try
486  {
487  xClipboard = css::datatransfer::clipboard::SystemClipboard::create(
489  }
490  catch (DeploymentException const &) {}
491  return xClipboard;
492 #endif
493 }
494 
495 Reference<XClipboard> GetSystemPrimarySelection()
496 {
497  Reference<XClipboard> xSelection;
498  try
499  {
501 #if HAVE_FEATURE_X11
502  // A hack, making the primary selection available as an instance
503  // of the SystemClipboard service on X11:
504  Sequence< Any > args(1);
505  args[0] <<= OUString("PRIMARY");
506  xSelection.set(xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
507  "com.sun.star.datatransfer.clipboard.SystemClipboard", args, xContext), UNO_QUERY_THROW);
508 #else
509  static Reference< XClipboard > s_xSelection(
510  xContext->getServiceManager()->createInstanceWithContext(
511  "com.sun.star.datatransfer.clipboard.GenericClipboard", xContext), UNO_QUERY);
512  xSelection = s_xSelection;
513 #endif
514  }
515  catch (RuntimeException const &) {}
516  return xSelection;
517 }
518 
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< INetBookmark > pBookmk
Definition: transfer2.cxx:321
virtual ~DragGestureListener() override
Definition: transfer2.cxx:52
void CopyINetBookmark(const INetBookmark &rBkmk)
Definition: transfer2.cxx:382
DropTargetHelper()=delete
signed char sal_Int8
std::vector< TDataCntnrEntry_Impl > aFmtList
Definition: transfer2.cxx:319
sal_uIntPtr sal_uLong
css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > mxDragGestureRecognizer
Definition: transfer.hxx:402
virtual void DragFinished(sal_Int8 nDropAction) override
Definition: transfer2.cxx:457
DropTargetListener(DropTargetHelper &rDropTargetHelper)
Definition: transfer2.cxx:105
sal_Int16 nId
virtual void StartDrag(sal_Int8 nAction, const Point &rPosPixel)
Definition: transfer2.cxx:100
tuple args
void CopyByteString(SotClipboardFormatId nFormatId, const OString &rStr)
Definition: transfer2.cxx:415
css::uno::Reference< css::datatransfer::dnd::XDropTarget > mxDropTarget
Definition: transfer.hxx:451
void ImplBeginDrag(const css::uno::Sequence< css::datatransfer::DataFlavor > &rSupportedDataFlavors)
Definition: transfer2.cxx:273
DragSourceHelper(vcl::Window *pWindow)
Definition: transfer2.cxx:71
bool SetINetBookmark(const INetBookmark &rBmk, const css::datatransfer::DataFlavor &rFlavor)
Definition: transfer.cxx:771
void AddFormat(SotClipboardFormatId nFormat)
Definition: transfer.cxx:548
osl::Mutex maMutex
Definition: transfer.hxx:401
void ImplConstruct()
Definition: transfer2.cxx:262
SotClipboardFormatId
void StartDrag(vcl::Window *pWindow, sal_Int8 nDragSourceActions, const Link< sal_Int8, void > &rCallbck)
Definition: transfer2.cxx:448
std::unique_ptr< TransferDataContainer_Impl > pImpl
Definition: transfer.hxx:489
virtual ~TransferDataContainer() override
Definition: transfer2.cxx:335
virtual void SAL_CALL dragGestureRecognized(const css::datatransfer::dnd::DragGestureEvent &rDGE) override
Definition: transfer2.cxx:62
virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent &rEvt)
Definition: transfer2.cxx:292
sal_Int8 mnAction
Definition: transfer.hxx:114
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
void CopyAnyData(SotClipboardFormatId nFormatId, const char *pData, sal_uLong nLen)
Definition: transfer2.cxx:398
virtual sal_Int8 AcceptDrop(const AcceptDropEvent &rEvt)
Definition: transfer2.cxx:286
virtual void SAL_CALL dragOver(const css::datatransfer::dnd::DropTargetDragEvent &dtde) override
Definition: transfer2.cxx:182
virtual ~DropTargetHelper()
Definition: transfer2.cxx:256
void CopyString(const OUString &rStr)
Definition: transfer2.cxx:435
void StartDrag(vcl::Window *pWindow, sal_Int8 nDragSourceActions)
Definition: transfer.cxx:992
Reference< XClipboard > GetSystemClipboard()
Definition: transfer2.cxx:462
osl::Mutex maMutex
Definition: transfer.hxx:450
DragGestureListener(DragSourceHelper &rDragSourceHelper)
Definition: transfer2.cxx:46
exports com.sun.star.chart2. data
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: transfer2.cxx:57
static SotClipboardFormatId GetFormat(const css::datatransfer::DataFlavor &rFlavor)
virtual void SAL_CALL dragExit(const css::datatransfer::dnd::DropTargetEvent &dte) override
Definition: transfer2.cxx:204
static void FillDataFlavorExVector(const css::uno::Sequence< css::datatransfer::DataFlavor > &rDataFlavorSeq, DataFlavorExVector &rDataFlavorExVector)
Definition: transfer.cxx:1225
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: transfer2.cxx:116
virtual void SAL_CALL dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent &dtdee) override
Definition: transfer2.cxx:166
css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > mxDropTargetListener
Definition: transfer.hxx:453
virtual void SAL_CALL drop(const css::datatransfer::dnd::DropTargetDropEvent &dtde) override
Definition: transfer2.cxx:121
Point maPosPixel
Definition: transfer.hxx:92
Reference< XComponentContext > getProcessComponentContext()
Sequence< sal_Int8 > aSeq
virtual void AddSupportedFormats() override
Definition: transfer2.cxx:340
css::uno::Reference< css::datatransfer::dnd::XDragGestureListener > mxDragGestureListener
Definition: transfer.hxx:404
bool IsDropFormatSupported(SotClipboardFormatId nFormat) const
Definition: transfer2.cxx:298
virtual ~DragSourceHelper()
Definition: transfer2.cxx:94
virtual bool GetData(const css::datatransfer::DataFlavor &rFlavor, const OUString &rDestDoc) override
Definition: transfer2.cxx:345
virtual ~DropTargetListener() override
Definition: transfer2.cxx:111
bool HasAnyData() const
Definition: transfer2.cxx:441
DataFlavorExVector maFormats
Definition: transfer.hxx:454
#define DBG_TESTSOLARMUTEX()
bool SetAny(const css::uno::Any &rAny)
Definition: transfer.cxx:645
sal_Int8 mnAction
Definition: transfer.hxx:91
BaseContainerNodeSharedPtr & mrParent
virtual void SAL_CALL dropActionChanged(const css::datatransfer::dnd::DropTargetDragEvent &dtde) override
Definition: transfer2.cxx:225
const css::datatransfer::dnd::DropTargetDragEvent maDragEvent
Definition: transfer.hxx:93
Link< sal_Int8, void > aFinshedLnk
Definition: transfer2.cxx:320
Reference< XClipboard > GetSystemPrimarySelection()
Definition: transfer2.cxx:495