Update ooo320-m1
[ooovba.git] / vcl / aqua / source / dtrans / DropTarget.cxx
blob271352f6d42cbd5be07778dd2685b1447356ffb6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DropTarget.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
34 #include <com/sun/star/datatransfer/XTransferable.hpp>
35 #include <com/sun/star/datatransfer/dnd/DropTargetDragEnterEvent.hpp>
36 #include <rtl/unload.h>
38 #ifndef COMPHELPER_MAKESEQUENCE_HXX_INCLUDED
39 #include "comphelper/makesequence.hxx"
40 #endif
41 #include <cppuhelper/interfacecontainer.hxx>
43 #include "aqua_clipboard.hxx"
44 #include "DropTarget.hxx"
45 #include "DragActionConversion.hxx"
47 #include "DragSource.hxx"
49 #include <rtl/ustring.h>
50 #include <stdio.h>
52 #include <premac.h>
53 #include <Carbon/Carbon.h>
54 #include <postmac.h>
57 using namespace rtl;
58 using namespace cppu;
59 using namespace osl;
60 using namespace com::sun::star::datatransfer;
61 using namespace com::sun::star::datatransfer::dnd;
62 using namespace com::sun::star::datatransfer::dnd::DNDConstants;
63 using namespace com::sun::star::datatransfer::clipboard;
64 using namespace com::sun::star::lang;
65 using namespace com::sun::star::uno;
66 using namespace comphelper;
68 OUString dropTarget_getImplementationName()
70 return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1"));
74 Sequence<OUString> dropTarget_getSupportedServiceNames()
76 return makeSequence(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDropTarget")));
80 namespace /* private */
82 // Cocoa's coordinate system has its origin lower-left, VCL's
83 // coordinate system upper-left hence we need to transform
84 // coordinates
86 inline void CocoaToVCL(NSPoint& rPoint, const NSRect& bounds)
88 rPoint.y = bounds.size.height - rPoint.y;
91 inline void CocoaToVCL(NSRect& rRect, const NSRect& bounds)
93 rRect.origin.y = bounds.size.height - (rRect.origin.y + rRect.size.height);
98 @implementation DropTargetHelper
101 -(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt
103 self = [super init];
105 if (self)
107 mDropTarget = pdt;
110 return self;
114 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
116 return mDropTarget->draggingEntered(sender);
120 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
122 return mDropTarget->draggingUpdated(sender);
126 -(void)draggingExited:(id <NSDraggingInfo>)sender
128 mDropTarget->draggingExited(sender);
132 -(MacOSBOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
134 return mDropTarget->prepareForDragOperation(sender);
138 -(MacOSBOOL)performDragOperation:(id <NSDraggingInfo>)sender
140 return mDropTarget->performDragOperation(sender);
144 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
146 mDropTarget->concludeDragOperation(sender);
150 @end
153 DropTarget::DropTarget() :
154 WeakComponentImplHelper5<XInitialization, XDropTarget, XDropTargetDragContext, XDropTargetDropContext, XServiceInfo>(m_aMutex),
155 mDropTargetHelper(nil),
156 mbActive(false),
157 mDragSourceSupportedActions(DNDConstants::ACTION_NONE),
158 mSelectedDropAction(DNDConstants::ACTION_NONE),
159 mDefaultActions(DNDConstants::ACTION_COPY_OR_MOVE | DNDConstants::ACTION_LINK | DNDConstants::ACTION_DEFAULT)
161 mDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper());
165 DropTarget::~DropTarget()
167 [(id <DraggingDestinationHandler>)mView unregisterDraggingDestinationHandler:mDropTargetHelper];
168 [mDropTargetHelper release];
172 sal_Int8 DropTarget::determineDropAction(sal_Int8 dropActions, id sender) const
174 sal_Int8 dropAct = dropActions;
175 bool srcAndDestEqual = false;
177 if ([sender draggingSource] != nil)
179 // Internal DnD
180 NSView* destView = [[sender draggingDestinationWindow] contentView];
181 srcAndDestEqual = (DragSource::g_DragSourceView == destView);
184 // If ACTION_DEFAULT is set this means NSDragOperationGeneric
185 // has been set and we map this to ACTION_MOVE or ACTION_COPY
186 // depending on whether or not source and dest are equal,
187 // this hopefully satisfies all parties
188 if( (dropActions == DNDConstants::ACTION_DEFAULT)
189 || ((dropActions == mDragSourceSupportedActions)
190 && !(~mDragSourceSupportedActions & DNDConstants::ACTION_COPY_OR_MOVE ) ) )
192 dropAct = srcAndDestEqual ? DNDConstants::ACTION_MOVE :
193 DNDConstants::ACTION_COPY;
195 // if more than one drop actions have been specified
196 // set ACTION_DEFAULT in order to let the drop target
197 // decide which one to use
198 else if (dropActions != DNDConstants::ACTION_NONE &&
199 dropActions != DNDConstants::ACTION_MOVE &&
200 dropActions != DNDConstants::ACTION_COPY &&
201 dropActions != DNDConstants::ACTION_LINK)
203 if (srcAndDestEqual)
205 dropAct = dropActions;
207 else // source and destination are different
209 if (dropActions & DNDConstants::ACTION_COPY)
210 dropAct = DNDConstants::ACTION_COPY;
211 else if (dropActions & DNDConstants::ACTION_MOVE)
212 dropAct = DNDConstants::ACTION_MOVE;
213 else if (dropActions & DNDConstants::ACTION_LINK)
214 dropAct = DNDConstants::ACTION_LINK;
217 dropAct |= DNDConstants::ACTION_DEFAULT;
220 return dropAct;
224 NSDragOperation DropTarget::draggingEntered(id sender)
226 // Initially when DnD will be started no modifier key can be pressed yet
227 // thus we are getting all actions that the drag source supports, we save
228 // this value because later the system masks the drag source actions if
229 // a modifier key will be pressed
230 mDragSourceSupportedActions = SystemToOfficeDragActions([sender draggingSourceOperationMask]);
232 // Only if the drop target is really interessted in the drag actions
233 // supported by the source
234 if (mDragSourceSupportedActions & mDefaultActions)
236 sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender);
238 NSRect bounds = [mView bounds];
239 NSPoint dragLocation = [sender draggedImageLocation];
241 CocoaToVCL(dragLocation, bounds);
243 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
244 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
246 NSPasteboard* dragPboard = [sender draggingPasteboard];
247 mXCurrentDragClipboard = new AquaClipboard(dragPboard, false);
249 Reference<XTransferable> xTransferable = DragSource::g_XTransferable.is() ?
250 DragSource::g_XTransferable : mXCurrentDragClipboard->getContents();
252 DropTargetDragEnterEvent dtdee(static_cast<OWeakObject*>(this),
254 this,
255 currentAction,
256 posX,
257 posY,
258 mDragSourceSupportedActions,
259 xTransferable->getTransferDataFlavors());
261 fire_dragEnter(dtdee);
264 return OfficeToSystemDragActions(mSelectedDropAction);
268 NSDragOperation DropTarget::draggingUpdated(id sender)
270 sal_Int8 currentDragSourceActions =
271 SystemToOfficeDragActions([sender draggingSourceOperationMask]);
272 NSDragOperation dragOp = NSDragOperationNone;
274 if (currentDragSourceActions & mDefaultActions)
276 sal_Int8 currentAction = determineDropAction(currentDragSourceActions, sender);
277 NSRect bounds = [mView bounds];
278 NSPoint dragLocation = [sender draggedImageLocation];
280 CocoaToVCL(dragLocation, bounds);
282 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
283 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
285 DropTargetDragEvent dtde(static_cast<OWeakObject*>(this),
287 this,
288 currentAction,
289 posX,
290 posY,
291 mDragSourceSupportedActions);
293 fire_dragOver(dtde);
295 // drag over callbacks likely have rendered something
296 [mView setNeedsDisplay: TRUE];
298 dragOp = OfficeToSystemDragActions(mSelectedDropAction);
300 //NSLog(@"Drag update: Source actions: %x proposed action %x selected action %x", mDragSourceSupportedActions, currentAction, mSelectedDropAction);
303 // Weird but it appears as if there is no method in Cocoa
304 // to create a kThemeCopyArrowCursor hence we have to use
305 // Carbon to do it
306 if (dragOp == NSDragOperationNone)
307 SetThemeCursor(kThemeNotAllowedCursor);
308 else if (dragOp == NSDragOperationCopy)
309 SetThemeCursor(kThemeCopyArrowCursor);
310 else
311 SetThemeCursor(kThemeArrowCursor);
313 return dragOp;
317 void DropTarget::draggingExited(id sender)
319 DropTargetEvent dte(static_cast<OWeakObject*>(this), 0);
320 fire_dragExit(dte);
321 mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
322 mSelectedDropAction = DNDConstants::ACTION_NONE;
323 SetThemeCursor(kThemeArrowCursor);
327 MacOSBOOL DropTarget::prepareForDragOperation(id sender)
329 return 1;
333 MacOSBOOL DropTarget::performDragOperation(id sender)
335 bool bSuccess = false;
337 if (mSelectedDropAction != DNDConstants::ACTION_NONE)
339 Reference<XTransferable> xTransferable = DragSource::g_XTransferable;
341 if (!DragSource::g_XTransferable.is())
343 xTransferable = mXCurrentDragClipboard->getContents();
346 NSRect bounds = [mView bounds];
347 NSPoint dragLocation = [sender draggedImageLocation];
349 CocoaToVCL(dragLocation, bounds);
351 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
352 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
354 DropTargetDropEvent dtde(static_cast<OWeakObject*>(this),
356 this,
357 mSelectedDropAction,
358 posX,
359 posY,
360 mDragSourceSupportedActions,
361 xTransferable);
363 fire_drop(dtde);
365 bSuccess = true;
368 return bSuccess;
372 void DropTarget::concludeDragOperation(id sender)
374 mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
375 mSelectedDropAction = DNDConstants::ACTION_NONE;
376 mXCurrentDragClipboard = Reference<XClipboard>();
377 SetThemeCursor(kThemeArrowCursor);
381 // called from WeakComponentImplHelperX::dispose
382 // WeakComponentImplHelper calls disposing before it destroys
383 // itself.
384 void SAL_CALL DropTarget::disposing()
389 void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments)
390 throw(Exception)
392 if (aArguments.getLength() < 2)
394 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("DropTarget::initialize: Cannot install window event handler")),
395 static_cast<OWeakObject*>(this));
398 Any pNSView = aArguments[0];
399 sal_uInt64 tmp = 0;
400 pNSView >>= tmp;
401 mView = (id)tmp;
403 mDropTargetHelper = [[DropTargetHelper alloc] initWithDropTarget: this];
405 [(id <DraggingDestinationHandler>)mView registerDraggingDestinationHandler:mDropTargetHelper];
406 [mView registerForDraggedTypes: mDataFlavorMapper->getAllSupportedPboardTypes()];
408 id wnd = [mView window];
409 NSWindow* parentWnd = [wnd parentWindow];
410 unsigned int topWndStyle = (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask);
411 unsigned int wndStyles = [wnd styleMask] & topWndStyle;
413 if (parentWnd == nil && (wndStyles == topWndStyle))
415 [wnd registerDraggingDestinationHandler:mDropTargetHelper];
416 [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
421 void SAL_CALL DropTarget::addDropTargetListener(const Reference<XDropTargetListener>& dtl)
422 throw(RuntimeException)
424 rBHelper.addListener(::getCppuType(&dtl), dtl);
428 void SAL_CALL DropTarget::removeDropTargetListener(const Reference<XDropTargetListener>& dtl)
429 throw(RuntimeException)
431 rBHelper.removeListener(::getCppuType(&dtl), dtl);
435 sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException)
437 return mbActive;
441 void SAL_CALL DropTarget::setActive(sal_Bool active) throw(RuntimeException)
443 mbActive = active;
447 sal_Int8 SAL_CALL DropTarget::getDefaultActions() throw(RuntimeException)
449 return mDefaultActions;
453 void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions) throw(RuntimeException)
455 OSL_ENSURE( actions < 8, "No valid default actions");
456 mDefaultActions= actions;
460 // XDropTargetDragContext
462 void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation) throw (RuntimeException)
464 mSelectedDropAction = dragOperation;
468 void SAL_CALL DropTarget::rejectDrag() throw (RuntimeException)
470 mSelectedDropAction = DNDConstants::ACTION_NONE;
474 //XDropTargetDropContext
476 void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation) throw( RuntimeException)
478 mSelectedDropAction = dropOperation;
482 void SAL_CALL DropTarget::rejectDrop() throw (RuntimeException)
484 mSelectedDropAction = DNDConstants::ACTION_NONE;
488 void SAL_CALL DropTarget::dropComplete(sal_Bool success) throw (RuntimeException)
490 // Reset the internal transferable used as shortcut in case this is
491 // an internal D&D operation
492 DragSource::g_XTransferable = Reference<XTransferable>();
493 DragSource::g_DropSuccessSet = true;
494 DragSource::g_DropSuccess = success;
498 void DropTarget::fire_drop( const DropTargetDropEvent& dte)
500 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
501 if( pContainer)
503 OInterfaceIteratorHelper iter( *pContainer);
504 while( iter.hasMoreElements())
506 Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
508 try { listener->drop( dte); }
509 catch(RuntimeException&) {}
515 void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e)
517 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
518 if( pContainer)
520 OInterfaceIteratorHelper iter( *pContainer);
521 while( iter.hasMoreElements())
523 Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
525 try { listener->dragEnter( e); }
526 catch (RuntimeException&) {}
532 void DropTarget::fire_dragExit(const DropTargetEvent& dte)
534 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
536 if( pContainer)
538 OInterfaceIteratorHelper iter( *pContainer);
539 while( iter.hasMoreElements())
541 Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
543 try { listener->dragExit( dte); }
544 catch (RuntimeException&) {}
550 void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde)
552 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
553 if( pContainer)
555 OInterfaceIteratorHelper iter( *pContainer );
556 while( iter.hasMoreElements())
558 Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
560 try { listener->dragOver( dtde); }
561 catch (RuntimeException&) {}
567 void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde)
569 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (Reference<XDropTargetListener>* )0 ) );
570 if( pContainer)
572 OInterfaceIteratorHelper iter( *pContainer);
573 while( iter.hasMoreElements())
575 Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
577 try { listener->dropActionChanged( dtde); }
578 catch (RuntimeException&) {}
584 // XServiceInfo
586 OUString SAL_CALL DropTarget::getImplementationName() throw (RuntimeException)
588 return dropTarget_getImplementationName();
592 sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException)
594 return ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDropTarget")));
598 Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( ) throw (RuntimeException)
600 return dropTarget_getSupportedServiceNames();