bump product version to 4.2.0.1
[LibreOffice.git] / vcl / aqua / source / dtrans / DropTarget.cxx
blobfd762a9744c054ac235d726a3890db242613698f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
21 #include <com/sun/star/datatransfer/XTransferable.hpp>
22 #include <com/sun/star/datatransfer/dnd/DropTargetDragEnterEvent.hpp>
24 #include "comphelper/makesequence.hxx"
25 #include <cppuhelper/interfacecontainer.hxx>
27 #include "aqua_clipboard.hxx"
28 #include "DropTarget.hxx"
29 #include "DragActionConversion.hxx"
31 #include "DragSource.hxx"
33 #include <rtl/ustring.h>
34 #include <stdio.h>
36 #include <premac.h>
37 #include <Carbon/Carbon.h>
38 #include <postmac.h>
40 #include <aqua/salframe.h>
41 #include <aqua/salframeview.h>
43 using namespace cppu;
44 using namespace osl;
45 using namespace com::sun::star::datatransfer;
46 using namespace com::sun::star::datatransfer::dnd;
47 using namespace com::sun::star::datatransfer::dnd::DNDConstants;
48 using namespace com::sun::star::datatransfer::clipboard;
49 using namespace com::sun::star::lang;
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star;
52 using namespace comphelper;
55 OUString dropTarget_getImplementationName()
57 return OUString("com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1");
61 Sequence<OUString> dropTarget_getSupportedServiceNames()
63 return makeSequence(OUString("com.sun.star.datatransfer.dnd.OleDropTarget"));
67 namespace /* private */
69 // Cocoa's coordinate system has its origin lower-left, VCL's
70 // coordinate system upper-left hence we need to transform
71 // coordinates
73 inline void CocoaToVCL(NSPoint& rPoint, const NSRect& bounds)
75 rPoint.y = bounds.size.height - rPoint.y;
80 @implementation DropTargetHelper
83 -(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt
85 self = [super init];
87 if (self)
89 mDropTarget = pdt;
92 return self;
96 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
98 return mDropTarget->draggingEntered(sender);
102 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
104 return mDropTarget->draggingUpdated(sender);
108 -(void)draggingExited:(id <NSDraggingInfo>)sender
110 mDropTarget->draggingExited(sender);
114 -(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
116 return mDropTarget->prepareForDragOperation(sender);
120 -(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
122 return mDropTarget->performDragOperation(sender);
126 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
128 mDropTarget->concludeDragOperation(sender);
132 @end
135 DropTarget::DropTarget() :
136 WeakComponentImplHelper5<XInitialization, XDropTarget, XDropTargetDragContext, XDropTargetDropContext, XServiceInfo>(m_aMutex),
137 mView(nil),
138 mpFrame(NULL),
139 mDropTargetHelper(nil),
140 mbActive(false),
141 mDragSourceSupportedActions(DNDConstants::ACTION_NONE),
142 mSelectedDropAction(DNDConstants::ACTION_NONE),
143 mDefaultActions(DNDConstants::ACTION_COPY_OR_MOVE | DNDConstants::ACTION_LINK | DNDConstants::ACTION_DEFAULT)
145 mDataFlavorMapper = DataFlavorMapperPtr_t(new DataFlavorMapper());
149 DropTarget::~DropTarget()
151 if( AquaSalFrame::isAlive( mpFrame ) )
152 [(id <DraggingDestinationHandler>)mView unregisterDraggingDestinationHandler:mDropTargetHelper];
153 [mDropTargetHelper release];
157 sal_Int8 DropTarget::determineDropAction(sal_Int8 dropActions, id sender) const
159 sal_Int8 dropAct = dropActions;
160 bool srcAndDestEqual = false;
162 if ([sender draggingSource] != nil)
164 // Internal DnD
165 NSView* destView = [[sender draggingDestinationWindow] contentView];
166 srcAndDestEqual = (DragSource::g_DragSourceView == destView);
169 // If ACTION_DEFAULT is set this means NSDragOperationGeneric
170 // has been set and we map this to ACTION_MOVE or ACTION_COPY
171 // depending on whether or not source and dest are equal,
172 // this hopefully satisfies all parties
173 if( (dropActions == DNDConstants::ACTION_DEFAULT)
174 || ((dropActions == mDragSourceSupportedActions)
175 && !(~mDragSourceSupportedActions & DNDConstants::ACTION_COPY_OR_MOVE ) ) )
177 dropAct = srcAndDestEqual ? DNDConstants::ACTION_MOVE :
178 DNDConstants::ACTION_COPY;
180 // if more than one drop actions have been specified
181 // set ACTION_DEFAULT in order to let the drop target
182 // decide which one to use
183 else if (dropActions != DNDConstants::ACTION_NONE &&
184 dropActions != DNDConstants::ACTION_MOVE &&
185 dropActions != DNDConstants::ACTION_COPY &&
186 dropActions != DNDConstants::ACTION_LINK)
188 if (srcAndDestEqual)
190 dropAct = dropActions;
192 else // source and destination are different
194 if (dropActions & DNDConstants::ACTION_COPY)
195 dropAct = DNDConstants::ACTION_COPY;
196 else if (dropActions & DNDConstants::ACTION_MOVE)
197 dropAct = DNDConstants::ACTION_MOVE;
198 else if (dropActions & DNDConstants::ACTION_LINK)
199 dropAct = DNDConstants::ACTION_LINK;
202 dropAct |= DNDConstants::ACTION_DEFAULT;
205 return dropAct;
209 NSDragOperation DropTarget::draggingEntered(id sender)
211 // Initially when DnD will be started no modifier key can be pressed yet
212 // thus we are getting all actions that the drag source supports, we save
213 // this value because later the system masks the drag source actions if
214 // a modifier key will be pressed
215 mDragSourceSupportedActions = SystemToOfficeDragActions([sender draggingSourceOperationMask]);
217 // Only if the drop target is really interessted in the drag actions
218 // supported by the source
219 if (mDragSourceSupportedActions & mDefaultActions)
221 sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender);
223 NSRect bounds = [mView bounds];
224 NSPoint dragLocation = [sender draggedImageLocation];
226 CocoaToVCL(dragLocation, bounds);
228 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
229 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
231 NSPasteboard* dragPboard = [sender draggingPasteboard];
232 mXCurrentDragClipboard = new AquaClipboard(dragPboard, false);
234 uno::Reference<XTransferable> xTransferable = DragSource::g_XTransferable.is() ?
235 DragSource::g_XTransferable : mXCurrentDragClipboard->getContents();
237 DropTargetDragEnterEvent dtdee(static_cast<OWeakObject*>(this),
239 this,
240 currentAction,
241 posX,
242 posY,
243 mDragSourceSupportedActions,
244 xTransferable->getTransferDataFlavors());
246 fire_dragEnter(dtdee);
249 return OfficeToSystemDragActions(mSelectedDropAction);
253 NSDragOperation DropTarget::draggingUpdated(id sender)
255 sal_Int8 currentDragSourceActions =
256 SystemToOfficeDragActions([sender draggingSourceOperationMask]);
257 NSDragOperation dragOp = NSDragOperationNone;
259 if (currentDragSourceActions & mDefaultActions)
261 sal_Int8 currentAction = determineDropAction(currentDragSourceActions, sender);
262 NSRect bounds = [mView bounds];
263 NSPoint dragLocation = [sender draggedImageLocation];
265 CocoaToVCL(dragLocation, bounds);
267 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
268 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
270 DropTargetDragEvent dtde(static_cast<OWeakObject*>(this),
272 this,
273 currentAction,
274 posX,
275 posY,
276 mDragSourceSupportedActions);
278 fire_dragOver(dtde);
280 // drag over callbacks likely have rendered something
281 [mView setNeedsDisplay: TRUE];
283 dragOp = OfficeToSystemDragActions(mSelectedDropAction);
285 //NSLog(@"Drag update: Source actions: %x proposed action %x selected action %x", mDragSourceSupportedActions, currentAction, mSelectedDropAction);
288 #ifndef __LP64__
289 // Weird but it appears as if there is no method in Cocoa
290 // to create a kThemeCopyArrowCursor hence we have to use
291 // Carbon to do it
292 if (dragOp == NSDragOperationNone)
293 SetThemeCursor(kThemeNotAllowedCursor);
294 else if (dragOp == NSDragOperationCopy)
295 SetThemeCursor(kThemeCopyArrowCursor);
296 else
297 SetThemeCursor(kThemeArrowCursor);
298 #else
299 // FIXME: SetThemeCursor replacement?
300 #endif
301 return dragOp;
305 void DropTarget::draggingExited(id /*sender*/)
307 DropTargetEvent dte(static_cast<OWeakObject*>(this), 0);
308 fire_dragExit(dte);
309 mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
310 mSelectedDropAction = DNDConstants::ACTION_NONE;
311 #ifndef __LP64__
312 SetThemeCursor(kThemeArrowCursor);
313 #endif
317 BOOL DropTarget::prepareForDragOperation(id /*sender*/)
319 return 1;
323 BOOL DropTarget::performDragOperation(id sender)
325 bool bSuccess = false;
327 if (mSelectedDropAction != DNDConstants::ACTION_NONE)
329 uno::Reference<XTransferable> xTransferable = DragSource::g_XTransferable;
331 if (!DragSource::g_XTransferable.is())
333 xTransferable = mXCurrentDragClipboard->getContents();
336 NSRect bounds = [mView bounds];
337 NSPoint dragLocation = [sender draggedImageLocation];
339 CocoaToVCL(dragLocation, bounds);
341 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
342 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
344 DropTargetDropEvent dtde(static_cast<OWeakObject*>(this),
346 this,
347 mSelectedDropAction,
348 posX,
349 posY,
350 mDragSourceSupportedActions,
351 xTransferable);
353 fire_drop(dtde);
355 bSuccess = true;
358 return bSuccess;
362 void DropTarget::concludeDragOperation(id /*sender*/)
364 mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
365 mSelectedDropAction = DNDConstants::ACTION_NONE;
366 mXCurrentDragClipboard = uno::Reference<XClipboard>();
367 #ifndef __LP64__
368 SetThemeCursor(kThemeArrowCursor);
369 #endif
373 // called from WeakComponentImplHelperX::dispose
374 // WeakComponentImplHelper calls disposing before it destroys
375 // itself.
376 void SAL_CALL DropTarget::disposing()
381 void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments)
382 throw(Exception)
384 if (aArguments.getLength() < 2)
386 throw RuntimeException("DropTarget::initialize: Cannot install window event handler",
387 static_cast<OWeakObject*>(this));
390 Any pNSView = aArguments[0];
391 sal_uInt64 tmp = 0;
392 pNSView >>= tmp;
393 mView = (id)tmp;
394 mpFrame = [(SalFrameView*)mView getSalFrame];
396 mDropTargetHelper = [[DropTargetHelper alloc] initWithDropTarget: this];
398 [(id <DraggingDestinationHandler>)mView registerDraggingDestinationHandler:mDropTargetHelper];
399 [mView registerForDraggedTypes: mDataFlavorMapper->getAllSupportedPboardTypes()];
401 id wnd = [mView window];
402 NSWindow* parentWnd = [wnd parentWindow];
403 unsigned int topWndStyle = (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask);
404 unsigned int wndStyles = [wnd styleMask] & topWndStyle;
406 if (parentWnd == nil && (wndStyles == topWndStyle))
408 [wnd registerDraggingDestinationHandler:mDropTargetHelper];
409 [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
414 void SAL_CALL DropTarget::addDropTargetListener(const uno::Reference<XDropTargetListener>& dtl)
415 throw(RuntimeException)
417 rBHelper.addListener(::getCppuType(&dtl), dtl);
421 void SAL_CALL DropTarget::removeDropTargetListener(const uno::Reference<XDropTargetListener>& dtl)
422 throw(RuntimeException)
424 rBHelper.removeListener(::getCppuType(&dtl), dtl);
428 sal_Bool SAL_CALL DropTarget::isActive( ) throw(RuntimeException)
430 return mbActive;
434 void SAL_CALL DropTarget::setActive(sal_Bool active) throw(RuntimeException)
436 mbActive = active;
440 sal_Int8 SAL_CALL DropTarget::getDefaultActions() throw(RuntimeException)
442 return mDefaultActions;
446 void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions) throw(RuntimeException)
448 OSL_ENSURE( actions < 8, "No valid default actions");
449 mDefaultActions= actions;
453 // XDropTargetDragContext
455 void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation) throw (RuntimeException)
457 mSelectedDropAction = dragOperation;
461 void SAL_CALL DropTarget::rejectDrag() throw (RuntimeException)
463 mSelectedDropAction = DNDConstants::ACTION_NONE;
467 //XDropTargetDropContext
469 void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation) throw( RuntimeException)
471 mSelectedDropAction = dropOperation;
475 void SAL_CALL DropTarget::rejectDrop() throw (RuntimeException)
477 mSelectedDropAction = DNDConstants::ACTION_NONE;
481 void SAL_CALL DropTarget::dropComplete(sal_Bool success) throw (RuntimeException)
483 // Reset the internal transferable used as shortcut in case this is
484 // an internal D&D operation
485 DragSource::g_XTransferable = uno::Reference<XTransferable>();
486 DragSource::g_DropSuccessSet = true;
487 DragSource::g_DropSuccess = success;
491 void DropTarget::fire_drop( const DropTargetDropEvent& dte)
493 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) );
494 if( pContainer)
496 OInterfaceIteratorHelper iter( *pContainer);
497 while( iter.hasMoreElements())
499 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
501 try { listener->drop( dte); }
502 catch(RuntimeException&) {}
508 void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e)
510 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) );
511 if( pContainer)
513 OInterfaceIteratorHelper iter( *pContainer);
514 while( iter.hasMoreElements())
516 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
518 try { listener->dragEnter( e); }
519 catch (RuntimeException&) {}
525 void DropTarget::fire_dragExit(const DropTargetEvent& dte)
527 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) );
529 if( pContainer)
531 OInterfaceIteratorHelper iter( *pContainer);
532 while( iter.hasMoreElements())
534 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
536 try { listener->dragExit( dte); }
537 catch (RuntimeException&) {}
543 void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde)
545 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) );
546 if( pContainer)
548 OInterfaceIteratorHelper iter( *pContainer );
549 while( iter.hasMoreElements())
551 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
553 try { listener->dragOver( dtde); }
554 catch (RuntimeException&) {}
560 void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde)
562 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( getCppuType( (uno::Reference<XDropTargetListener>* )0 ) );
563 if( pContainer)
565 OInterfaceIteratorHelper iter( *pContainer);
566 while( iter.hasMoreElements())
568 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
570 try { listener->dropActionChanged( dtde); }
571 catch (RuntimeException&) {}
577 // XServiceInfo
579 OUString SAL_CALL DropTarget::getImplementationName() throw (RuntimeException)
581 return dropTarget_getImplementationName();
585 sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName ) throw (RuntimeException)
587 return ServiceName == "com.sun.star.datatransfer.dnd.OleDropTarget";
591 Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( ) throw (RuntimeException)
593 return dropTarget_getSupportedServiceNames();
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */