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