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 <vcl/svapp.hxx>
25 #include <vcl/window.hxx>
27 #include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
28 #include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
29 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
30 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
31 #include <com/sun/star/uno/DeploymentException.hpp>
32 #include <svl/urlbmk.hxx>
33 #include <vcl/transfer.hxx>
34 
35 
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::lang;
38 using namespace ::com::sun::star::io;
39 using namespace ::com::sun::star::datatransfer;
41 using namespace ::com::sun::star::datatransfer::dnd;
42 
43 
45  mrParent( rDragSourceHelper )
46 {
47 }
48 
49 
51 {
52 }
53 
54 
55 void SAL_CALL DragSourceHelper::DragGestureListener::disposing( const EventObject& )
56 {
57 }
58 
59 
60 void SAL_CALL DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent& rDGE )
61 {
62  const SolarMutexGuard aGuard;
63 
64  const Point aPtPixel( rDGE.DragOriginX, rDGE.DragOriginY );
65  mrParent.StartDrag( rDGE.DragAction, aPtPixel );
66 }
67 
68 
70  mxDragGestureRecognizer( pWindow->GetDragGestureRecognizer() )
71 {
72  if( mxDragGestureRecognizer.is() )
73  {
75  mxDragGestureRecognizer->addDragGestureListener( mxDragGestureListener );
76  }
77 }
78 
79 
81 {
82  Reference<XDragGestureRecognizer> xTmp;
83  {
84  osl::MutexGuard aGuard( maMutex );
87  }
88  if( xTmp.is() )
89  xTmp->removeDragGestureListener( mxDragGestureListener );
90 }
91 
93 {
94  dispose();
95 }
96 
97 
99 {
100 }
101 
102 
104  mrParent( rDropTargetHelper )
105 {
106 }
107 
108 
110 {
111 }
112 
113 
114 void SAL_CALL DropTargetHelper::DropTargetListener::disposing( const EventObject& )
115 {
116 }
117 
118 
119 void SAL_CALL DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent& rDTDE )
120 {
121  const SolarMutexGuard aGuard;
122 
123  try
124  {
125  AcceptDropEvent aAcceptEvent;
126  ExecuteDropEvent aExecuteEvt( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
127 
128  aExecuteEvt.mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
129 
130  // in case of a default action, call ::AcceptDrop first and use the returned
131  // accepted action as the execute action in the call to ::ExecuteDrop
132  aAcceptEvent.mnAction = aExecuteEvt.mnAction;
133  aAcceptEvent.maPosPixel = aExecuteEvt.maPosPixel;
134  static_cast<DropTargetEvent&>(const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent )) = rDTDE;
135  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).DropAction = rDTDE.DropAction;
136  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).LocationX = rDTDE.LocationX;
137  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).LocationY = rDTDE.LocationY;
138  const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).SourceActions = rDTDE.SourceActions;
139  aAcceptEvent.mbLeaving = false;
140  aAcceptEvent.mbDefault = aExecuteEvt.mbDefault;
141 
142  sal_Int8 nRet = mrParent.AcceptDrop( aAcceptEvent );
143 
144  if( DNDConstants::ACTION_NONE != nRet )
145  {
146  rDTDE.Context->acceptDrop( nRet );
147 
148  if( aExecuteEvt.mbDefault )
149  aExecuteEvt.mnAction = nRet;
150 
151  nRet = mrParent.ExecuteDrop( aExecuteEvt );
152  }
153 
154  rDTDE.Context->dropComplete( DNDConstants::ACTION_NONE != nRet );
155 
156  mpLastDragOverEvent.reset();
157  }
158  catch( const css::uno::Exception& )
159  {
160  }
161 }
162 
163 
164 void SAL_CALL DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent& rDTDEE )
165 {
166  const SolarMutexGuard aGuard;
167 
168  try
169  {
170  mrParent.ImplBeginDrag( rDTDEE.SupportedDataFlavors );
171  }
172  catch( const css::uno::Exception& )
173  {
174  }
175 
176  dragOver( rDTDEE );
177 }
178 
179 
180 void SAL_CALL DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent& rDTDE )
181 {
182  const SolarMutexGuard aGuard;
183 
184  try
185  {
186  mpLastDragOverEvent.reset( new AcceptDropEvent( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE ) );
187  mpLastDragOverEvent->mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
188 
189  const sal_Int8 nRet = mrParent.AcceptDrop( *mpLastDragOverEvent );
190 
191  if( DNDConstants::ACTION_NONE == nRet )
192  rDTDE.Context->rejectDrag();
193  else
194  rDTDE.Context->acceptDrag( nRet );
195  }
196  catch( const css::uno::Exception& )
197  {
198  }
199 }
200 
201 
202 void SAL_CALL DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent& )
203 {
204  const SolarMutexGuard aGuard;
205 
206  try
207  {
208  if( mpLastDragOverEvent )
209  {
210  mpLastDragOverEvent->mbLeaving = true;
211  mrParent.AcceptDrop( *mpLastDragOverEvent );
212  mpLastDragOverEvent.reset();
213  }
214 
215  mrParent.ImplEndDrag();
216  }
217  catch( const css::uno::Exception& )
218  {
219  }
220 }
221 
222 
223 void SAL_CALL DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent& )
224 {
225 }
226 
227 
229  mxDropTarget( pWindow->GetDropTarget() )
230 {
231  ImplConstruct();
232 }
233 
234 
235 DropTargetHelper::DropTargetHelper( const Reference< XDropTarget >& rxDropTarget ) :
236  mxDropTarget( rxDropTarget )
237 {
238  ImplConstruct();
239 }
240 
241 
243 {
244  Reference< XDropTarget > xTmp;
245  {
246  osl::MutexGuard aGuard( maMutex );
247  xTmp = mxDropTarget;
248  mxDropTarget.clear();
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 
307 {
308  css::uno::Any aAny;
310 };
311 
312 
313 typedef ::std::vector< TDataCntnrEntry_Impl > TDataCntnrEntryList;
314 
315 
317 {
320  std::unique_ptr<INetBookmark> pBookmk;
321 
323  {
324  }
325 };
326 
327 
329  : pImpl( new TransferDataContainer_Impl )
330 {
331 }
332 
333 
335 {
336 }
337 
338 
340 {
341 }
342 
343 
345  const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
346 {
347  bool bFnd = false;
348  SotClipboardFormatId nFmtId = SotExchange::GetFormat( rFlavor );
349 
350  // test first the list
351  for (auto const& format : pImpl->aFmtList)
352  {
353  if( nFmtId == format.nId )
354  {
355  bFnd = SetAny( format.aAny );
356  break;
357  }
358  }
359 
360  // test second the bookmark pointer
361  if( !bFnd )
362  switch( nFmtId )
363  {
364  case SotClipboardFormatId::STRING:
365  case SotClipboardFormatId::SOLK:
366  case SotClipboardFormatId::NETSCAPE_BOOKMARK:
367  case SotClipboardFormatId::FILECONTENT:
368  case SotClipboardFormatId::FILEGRPDESCRIPTOR:
369  case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
370  if( pImpl->pBookmk )
371  bFnd = SetINetBookmark( *pImpl->pBookmk, rFlavor );
372  break;
373 
374  default: break;
375  }
376 
377  return bFnd;
378 }
379 
380 
382 {
383  if( !pImpl->pBookmk )
384  pImpl->pBookmk.reset( new INetBookmark( rBkmk ) );
385  else
386  *pImpl->pBookmk = rBkmk;
387 
388  AddFormat( SotClipboardFormatId::STRING );
389  AddFormat( SotClipboardFormatId::SOLK );
390  AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
391  AddFormat( SotClipboardFormatId::FILECONTENT );
392  AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
393  AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
394 }
395 
396 
398  const sal_Char* pData, sal_uLong nLen )
399 {
400  if( nLen )
401  {
402  TDataCntnrEntry_Impl aEntry;
403  aEntry.nId = nFormatId;
404 
405  Sequence< sal_Int8 > aSeq( nLen );
406  memcpy( aSeq.getArray(), pData, nLen );
407  aEntry.aAny <<= aSeq;
408  pImpl->aFmtList.push_back( aEntry );
409  AddFormat( nFormatId );
410  }
411 }
412 
413 
415  const OString& rStr )
416 {
417  CopyAnyData( nFormatId, rStr.getStr(), rStr.getLength() );
418 }
419 
420 
421 void TransferDataContainer::CopyString( SotClipboardFormatId nFmt, const OUString& rStr )
422 {
423  if( !rStr.isEmpty() )
424  {
425  TDataCntnrEntry_Impl aEntry;
426  aEntry.nId = nFmt;
427  aEntry.aAny <<= rStr;
428  pImpl->aFmtList.push_back( aEntry );
429  AddFormat( aEntry.nId );
430  }
431 }
432 
433 
434 void TransferDataContainer::CopyString( const OUString& rStr )
435 {
436  CopyString( SotClipboardFormatId::STRING, rStr );
437 }
438 
439 
441 {
442  return !pImpl->aFmtList.empty() ||
443  nullptr != pImpl->pBookmk;
444 }
445 
446 
448  vcl::Window* pWindow, sal_Int8 nDragSourceActions,
449  const Link<sal_Int8,void>& rLnk )
450 {
451  pImpl->aFinshedLnk = rLnk;
452  TransferableHelper::StartDrag( pWindow, nDragSourceActions );
453 }
454 
455 
457 {
458  pImpl->aFinshedLnk.Call( nDropAction );
459 }
460 
461 Reference<XClipboard> GetSystemClipboard()
462 {
463  Reference<XClipboard> xClipboard;
464  try
465  {
466  xClipboard = css::datatransfer::clipboard::SystemClipboard::create(
468  }
469  catch (DeploymentException const &) {}
470  return xClipboard;
471 }
472 
473 Reference<XClipboard> GetSystemPrimarySelection()
474 {
475  Reference<XClipboard> xSelection;
476  try
477  {
479 #if HAVE_FEATURE_X11
480  // A hack, making the primary selection available as an instance
481  // of the SystemClipboard service on X11:
482  Sequence< Any > args(1);
483  args[0] <<= OUString("PRIMARY");
484  xSelection.set(xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
485  "com.sun.star.datatransfer.clipboard.SystemClipboard", args, xContext), UNO_QUERY_THROW);
486 #else
487  static Reference< XClipboard > s_xSelection(
488  xContext->getServiceManager()->createInstanceWithContext(
489  "com.sun.star.datatransfer.clipboard.GenericClipboard", xContext), UNO_QUERY);
490  xSelection = s_xSelection;
491 #endif
492  }
493  catch (RuntimeException const &) {}
494  return xSelection;
495 }
496 
497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< INetBookmark > pBookmk
Definition: transfer2.cxx:320
virtual ~DragGestureListener() override
Definition: transfer2.cxx:50
void CopyINetBookmark(const INetBookmark &rBkmk)
Definition: transfer2.cxx:381
DropTargetHelper()=delete
signed char sal_Int8
sal_uIntPtr sal_uLong
css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > mxDragGestureRecognizer
Definition: transfer.hxx:394
virtual void DragFinished(sal_Int8 nDropAction) override
Definition: transfer2.cxx:456
bool IsDropFormatSupported(SotClipboardFormatId nFormat)
Definition: transfer2.cxx:296
DropTargetListener(DropTargetHelper &rDropTargetHelper)
Definition: transfer2.cxx:103
void CopyAnyData(SotClipboardFormatId nFormatId, const sal_Char *pData, sal_uLong nLen)
Definition: transfer2.cxx:397
virtual void StartDrag(sal_Int8 nAction, const Point &rPosPixel)
Definition: transfer2.cxx:98
tuple args
void CopyByteString(SotClipboardFormatId nFormatId, const OString &rStr)
Definition: transfer2.cxx:414
css::uno::Reference< css::datatransfer::dnd::XDropTarget > mxDropTarget
Definition: transfer.hxx:443
void ImplBeginDrag(const css::uno::Sequence< css::datatransfer::DataFlavor > &rSupportedDataFlavors)
Definition: transfer2.cxx:271
DragSourceHelper(vcl::Window *pWindow)
Definition: transfer2.cxx:69
bool SetINetBookmark(const INetBookmark &rBmk, const css::datatransfer::DataFlavor &rFlavor)
Definition: transfer.cxx:761
TDataCntnrEntryList aFmtList
Definition: transfer2.cxx:318
void AddFormat(SotClipboardFormatId nFormat)
Definition: transfer.cxx:536
osl::Mutex maMutex
Definition: transfer.hxx:393
char sal_Char
SotClipboardFormatId nId
Definition: transfer2.cxx:309
void ImplConstruct()
Definition: transfer2.cxx:260
SotClipboardFormatId
void StartDrag(vcl::Window *pWindow, sal_Int8 nDragSourceActions, const Link< sal_Int8, void > &rCallbck)
Definition: transfer2.cxx:447
std::unique_ptr< TransferDataContainer_Impl > pImpl
Definition: transfer.hxx:481
virtual ~TransferDataContainer() override
Definition: transfer2.cxx:334
virtual void SAL_CALL dragGestureRecognized(const css::datatransfer::dnd::DragGestureEvent &rDGE) override
Definition: transfer2.cxx:60
virtual sal_Int8 ExecuteDrop(const ExecuteDropEvent &rEvt)
Definition: transfer2.cxx:290
sal_Int8 mnAction
Definition: transfer.hxx:114
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:180
virtual ~DropTargetHelper()
Definition: transfer2.cxx:254
void CopyString(const OUString &rStr)
Definition: transfer2.cxx:434
void StartDrag(vcl::Window *pWindow, sal_Int8 nDragSourceActions)
Definition: transfer.cxx:975
Reference< XClipboard > GetSystemClipboard()
Definition: transfer2.cxx:461
osl::Mutex maMutex
Definition: transfer.hxx:442
DragGestureListener(DragSourceHelper &rDragSourceHelper)
Definition: transfer2.cxx:44
css::uno::Any aAny
Definition: transfer2.cxx:308
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: transfer2.cxx:55
static SotClipboardFormatId GetFormat(const css::datatransfer::DataFlavor &rFlavor)
virtual void SAL_CALL dragExit(const css::datatransfer::dnd::DropTargetEvent &dte) override
Definition: transfer2.cxx:202
static void FillDataFlavorExVector(const css::uno::Sequence< css::datatransfer::DataFlavor > &rDataFlavorSeq, DataFlavorExVector &rDataFlavorExVector)
Definition: transfer.cxx:1205
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: transfer2.cxx:114
virtual void SAL_CALL dragEnter(const css::datatransfer::dnd::DropTargetDragEnterEvent &dtdee) override
Definition: transfer2.cxx:164
css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > mxDropTargetListener
Definition: transfer.hxx:445
virtual void SAL_CALL drop(const css::datatransfer::dnd::DropTargetDropEvent &dtde) override
Definition: transfer2.cxx:119
Point maPosPixel
Definition: transfer.hxx:92
Reference< XComponentContext > getProcessComponentContext()
virtual void AddSupportedFormats() override
Definition: transfer2.cxx:339
css::uno::Reference< css::datatransfer::dnd::XDragGestureListener > mxDragGestureListener
Definition: transfer.hxx:396
virtual ~DragSourceHelper()
Definition: transfer2.cxx:92
virtual bool GetData(const css::datatransfer::DataFlavor &rFlavor, const OUString &rDestDoc) override
Definition: transfer2.cxx:344
virtual ~DropTargetListener() override
Definition: transfer2.cxx:109
bool HasAnyData() const
Definition: transfer2.cxx:440
DataFlavorExVector maFormats
Definition: transfer.hxx:446
::std::vector< TDataCntnrEntry_Impl > TDataCntnrEntryList
Definition: transfer2.cxx:313
bool SetAny(const css::uno::Any &rAny)
Definition: transfer.cxx:633
sal_Int8 mnAction
Definition: transfer.hxx:91
BaseContainerNodeSharedPtr & mrParent
virtual void SAL_CALL dropActionChanged(const css::datatransfer::dnd::DropTargetDragEvent &dtde) override
Definition: transfer2.cxx:223
const css::datatransfer::dnd::DropTargetDragEvent maDragEvent
Definition: transfer.hxx:93
Link< sal_Int8, void > aFinshedLnk
Definition: transfer2.cxx:319
Reference< XClipboard > GetSystemPrimarySelection()
Definition: transfer2.cxx:473