tdf#151341 Use lzfse compression instead of bzip2
[LibreOffice.git] / vcl / osx / DropTarget.cxx
blob56407a40abe96b498de46a97005a387b52a94616
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>
23 #include <cppuhelper/interfacecontainer.hxx>
24 #include "clipboard.hxx"
25 #include "DropTarget.hxx"
26 #include "DragActionConversion.hxx"
27 #include "DragSource.hxx"
28 #include <rtl/ustring.h>
29 #include <premac.h>
30 #include <Carbon/Carbon.h>
31 #include <postmac.h>
32 #include <osx/salframe.h>
33 #include <osx/salframeview.h>
34 #include <cppuhelper/supportsservice.hxx>
36 using namespace cppu;
37 using namespace osl;
38 using namespace com::sun::star::datatransfer;
39 using namespace com::sun::star::datatransfer::dnd;
40 using namespace com::sun::star::datatransfer::dnd::DNDConstants;
41 using namespace com::sun::star::datatransfer::clipboard;
42 using namespace com::sun::star::lang;
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star;
45 using namespace comphelper;
47 static OUString dropTarget_getImplementationName()
49 return "com.sun.star.comp.datatransfer.dnd.OleDropTarget_V1";
52 static Sequence<OUString> dropTarget_getSupportedServiceNames()
54 return { OUString("com.sun.star.datatransfer.dnd.OleDropTarget") };
57 namespace /* private */
59 // Cocoa's coordinate system has its origin lower-left, VCL's
60 // coordinate system upper-left hence we need to transform
61 // coordinates
63 void CocoaToVCL(NSPoint& rPoint, const NSRect& bounds)
65 rPoint.y = bounds.size.height - rPoint.y;
69 @implementation DropTargetHelper
71 -(DropTargetHelper*)initWithDropTarget:(DropTarget*)pdt
73 self = [super init];
75 if (self)
77 mDropTarget = pdt;
80 return self;
83 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
85 return mDropTarget->draggingEntered(sender);
88 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
90 return mDropTarget->draggingUpdated(sender);
93 -(void)draggingExited:(id <NSDraggingInfo>)sender
95 mDropTarget->draggingExited(sender);
98 -(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
100 (void) sender;
101 return DropTarget::prepareForDragOperation();
104 -(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
106 (void) sender;
107 return mDropTarget->performDragOperation();
110 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
112 mDropTarget->concludeDragOperation(sender);
115 @end
117 DropTarget::DropTarget() :
118 WeakComponentImplHelper<XInitialization, XDropTarget, XDropTargetDragContext, XDropTargetDropContext, XServiceInfo>(m_aMutex),
119 mView(nil),
120 mpFrame(nullptr),
121 mDropTargetHelper(nil),
122 mbActive(false),
123 mDragSourceSupportedActions(DNDConstants::ACTION_NONE),
124 mSelectedDropAction(DNDConstants::ACTION_NONE),
125 mDefaultActions(DNDConstants::ACTION_COPY_OR_MOVE | DNDConstants::ACTION_LINK | DNDConstants::ACTION_DEFAULT)
127 mDataFlavorMapper = std::make_shared<DataFlavorMapper>();
130 DropTarget::~DropTarget()
132 if( AquaSalFrame::isAlive( mpFrame ) )
133 [static_cast<id <DraggingDestinationHandler>>(mView) unregisterDraggingDestinationHandler:mDropTargetHelper];
134 [mDropTargetHelper release];
137 sal_Int8 DropTarget::determineDropAction(sal_Int8 dropActions, id sender) const
139 sal_Int8 dropAct = dropActions;
140 bool srcAndDestEqual = false;
142 if ([sender draggingSource] != nil)
144 // Internal DnD
145 NSView* destView = [[sender draggingDestinationWindow] contentView];
146 srcAndDestEqual = (DragSource::g_DragSourceView == destView);
149 // If ACTION_DEFAULT is set this means NSDragOperationGeneric
150 // has been set and we map this to ACTION_MOVE or ACTION_COPY
151 // depending on whether or not source and dest are equal,
152 // this hopefully satisfies all parties
153 if( (dropActions == DNDConstants::ACTION_DEFAULT)
154 || ((dropActions == mDragSourceSupportedActions)
155 && !(~mDragSourceSupportedActions & DNDConstants::ACTION_COPY_OR_MOVE ) ) )
157 dropAct = srcAndDestEqual ? DNDConstants::ACTION_MOVE :
158 DNDConstants::ACTION_COPY;
160 // if more than one drop actions have been specified
161 // set ACTION_DEFAULT in order to let the drop target
162 // decide which one to use
163 else if (dropActions != DNDConstants::ACTION_NONE &&
164 dropActions != DNDConstants::ACTION_MOVE &&
165 dropActions != DNDConstants::ACTION_COPY &&
166 dropActions != DNDConstants::ACTION_LINK)
168 if (srcAndDestEqual)
170 dropAct = dropActions;
172 else // source and destination are different
174 if (dropActions & DNDConstants::ACTION_COPY)
175 dropAct = DNDConstants::ACTION_COPY;
176 else if (dropActions & DNDConstants::ACTION_MOVE)
177 dropAct = DNDConstants::ACTION_MOVE;
178 else if (dropActions & DNDConstants::ACTION_LINK)
179 dropAct = DNDConstants::ACTION_LINK;
182 dropAct |= DNDConstants::ACTION_DEFAULT;
185 return dropAct;
188 NSDragOperation DropTarget::draggingEntered(id sender)
190 // Initially when DnD will be started no modifier key can be pressed yet
191 // thus we are getting all actions that the drag source supports, we save
192 // this value because later the system masks the drag source actions if
193 // a modifier key will be pressed
194 mDragSourceSupportedActions = SystemToOfficeDragActions([sender draggingSourceOperationMask]);
196 // Only if the drop target is really interested in the drag actions
197 // supported by the source
198 if (mDragSourceSupportedActions & mDefaultActions)
200 sal_Int8 currentAction = determineDropAction(mDragSourceSupportedActions, sender);
202 NSRect bounds = [mView bounds];
203 NSPoint mouseLoc = [NSEvent mouseLocation];
205 id wnd = [mView window];
206 NSPoint dragLocation = [mView convertPoint:[wnd convertRectFromScreen:NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)].origin fromView:nil];
208 CocoaToVCL(dragLocation, bounds);
210 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
211 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
213 NSPasteboard* dragPboard = [sender draggingPasteboard];
214 mXCurrentDragClipboard = new AquaClipboard(dragPboard, false);
216 uno::Reference<XTransferable> xTransferable = DragSource::g_XTransferable.is() ?
217 DragSource::g_XTransferable : mXCurrentDragClipboard->getContents();
219 DropTargetDragEnterEvent dtdee(static_cast<OWeakObject*>(this),
221 this,
222 currentAction,
223 posX,
224 posY,
225 mDragSourceSupportedActions,
226 xTransferable->getTransferDataFlavors());
228 fire_dragEnter(dtdee);
231 return OfficeToSystemDragActions(mSelectedDropAction);
234 NSDragOperation DropTarget::draggingUpdated(id sender)
236 sal_Int8 currentDragSourceActions =
237 SystemToOfficeDragActions([sender draggingSourceOperationMask]);
238 NSDragOperation dragOp = NSDragOperationNone;
240 if (currentDragSourceActions & mDefaultActions)
242 sal_Int8 currentAction = determineDropAction(currentDragSourceActions, sender);
243 NSRect bounds = [mView bounds];
244 NSPoint mouseLoc = [NSEvent mouseLocation];
246 id wnd = [mView window];
247 NSPoint dragLocation = [mView convertPoint:[wnd convertRectFromScreen:NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)].origin fromView:nil];
249 CocoaToVCL(dragLocation, bounds);
251 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
252 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
254 DropTargetDragEvent dtde(static_cast<OWeakObject*>(this),
256 this,
257 currentAction,
258 posX,
259 posY,
260 mDragSourceSupportedActions);
262 fire_dragOver(dtde);
264 // drag over callbacks likely have rendered something
265 [mView setNeedsDisplay: true];
267 dragOp = OfficeToSystemDragActions(mSelectedDropAction);
269 //NSLog(@"Drag update: Source actions: %x proposed action %x selected action %x", mDragSourceSupportedActions, currentAction, mSelectedDropAction);
272 if (dragOp == NSDragOperationNone)
273 [[NSCursor operationNotAllowedCursor] set];
274 else if (dragOp == NSDragOperationCopy)
275 [[NSCursor dragCopyCursor] set];
276 else
277 [[NSCursor arrowCursor] set];
279 return dragOp;
282 void DropTarget::draggingExited(id /*sender*/)
284 DropTargetEvent dte(static_cast<OWeakObject*>(this), 0);
285 fire_dragExit(dte);
286 mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
287 mSelectedDropAction = DNDConstants::ACTION_NONE;
288 [[NSCursor arrowCursor] set];
291 BOOL DropTarget::prepareForDragOperation()
293 return true;
296 BOOL DropTarget::performDragOperation()
298 bool bSuccess = false;
300 if (mSelectedDropAction != DNDConstants::ACTION_NONE)
302 uno::Reference<XTransferable> xTransferable = DragSource::g_XTransferable;
304 if (!DragSource::g_XTransferable.is())
306 xTransferable = mXCurrentDragClipboard->getContents();
309 NSRect bounds = [mView bounds];
310 NSPoint mouseLoc = [NSEvent mouseLocation];
312 id wnd = [mView window];
313 NSPoint dragLocation = [mView convertPoint:[wnd convertRectFromScreen:NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)].origin fromView:nil];
315 CocoaToVCL(dragLocation, bounds);
317 sal_Int32 posX = static_cast<sal_Int32>(dragLocation.x);
318 sal_Int32 posY = static_cast<sal_Int32>(dragLocation.y);
320 DropTargetDropEvent dtde(static_cast<OWeakObject*>(this),
322 this,
323 mSelectedDropAction,
324 posX,
325 posY,
326 mDragSourceSupportedActions,
327 xTransferable);
329 fire_drop(dtde);
331 bSuccess = true;
334 return bSuccess;
337 void DropTarget::concludeDragOperation(id /*sender*/)
339 mDragSourceSupportedActions = DNDConstants::ACTION_NONE;
340 mSelectedDropAction = DNDConstants::ACTION_NONE;
341 mXCurrentDragClipboard.clear();
342 [[NSCursor arrowCursor] set];
345 // called from WeakComponentImplHelperX::dispose
346 // WeakComponentImplHelper calls disposing before it destroys
347 // itself.
348 void SAL_CALL DropTarget::disposing()
352 void SAL_CALL DropTarget::initialize(const Sequence< Any >& aArguments)
354 if (aArguments.getLength() < 2)
356 throw RuntimeException("DropTarget::initialize: Cannot install window event handler",
357 static_cast<OWeakObject*>(this));
360 Any pNSView = aArguments[0];
361 sal_uInt64 tmp = 0;
362 pNSView >>= tmp;
363 mView = reinterpret_cast<id>(tmp);
364 mpFrame = [static_cast<SalFrameView*>(mView) getSalFrame];
366 mDropTargetHelper = [[DropTargetHelper alloc] initWithDropTarget: this];
368 [static_cast<id <DraggingDestinationHandler>>(mView) registerDraggingDestinationHandler:mDropTargetHelper];
369 [mView registerForDraggedTypes: DataFlavorMapper::getAllSupportedPboardTypes()];
371 id wnd = [mView window];
372 NSWindow* parentWnd = [wnd parentWindow];
373 unsigned int topWndStyle = (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable);
374 unsigned int wndStyles = [wnd styleMask] & topWndStyle;
376 if (parentWnd == nil && (wndStyles == topWndStyle))
378 [wnd registerDraggingDestinationHandler:mDropTargetHelper];
379 SAL_WNODEPRECATED_DECLARATIONS_PUSH
380 // "'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 - Create
381 // multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead"
382 [wnd registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
383 SAL_WNODEPRECATED_DECLARATIONS_POP
387 void SAL_CALL DropTarget::addDropTargetListener(const uno::Reference<XDropTargetListener>& dtl)
389 rBHelper.addListener(cppu::UnoType<decltype(dtl)>::get(), dtl);
392 void SAL_CALL DropTarget::removeDropTargetListener(const uno::Reference<XDropTargetListener>& dtl)
394 rBHelper.removeListener(cppu::UnoType<decltype(dtl)>::get(), dtl);
397 sal_Bool SAL_CALL DropTarget::isActive( )
399 return mbActive;
402 void SAL_CALL DropTarget::setActive(sal_Bool active)
404 mbActive = active;
407 sal_Int8 SAL_CALL DropTarget::getDefaultActions()
409 return mDefaultActions;
412 void SAL_CALL DropTarget::setDefaultActions(sal_Int8 actions)
414 OSL_ENSURE( actions < 8, "No valid default actions");
415 mDefaultActions= actions;
418 void SAL_CALL DropTarget::acceptDrag(sal_Int8 dragOperation)
420 mSelectedDropAction = dragOperation;
423 void SAL_CALL DropTarget::rejectDrag()
425 mSelectedDropAction = DNDConstants::ACTION_NONE;
428 void SAL_CALL DropTarget::acceptDrop(sal_Int8 dropOperation)
430 mSelectedDropAction = dropOperation;
433 void SAL_CALL DropTarget::rejectDrop()
435 mSelectedDropAction = DNDConstants::ACTION_NONE;
438 void SAL_CALL DropTarget::dropComplete(sal_Bool success)
440 // Reset the internal transferable used as shortcut in case this is
441 // an internal D&D operation
442 DragSource::g_XTransferable.clear();
443 DragSource::g_DropSuccessSet = true;
444 DragSource::g_DropSuccess = success;
447 void DropTarget::fire_drop( const DropTargetDropEvent& dte)
449 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
450 if( pContainer)
452 OInterfaceIteratorHelper iter( *pContainer);
453 while( iter.hasMoreElements())
455 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
457 try { listener->drop( dte); }
458 catch(RuntimeException&) {}
463 void DropTarget::fire_dragEnter(const DropTargetDragEnterEvent& e)
465 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
466 if( pContainer)
468 OInterfaceIteratorHelper iter( *pContainer);
469 while( iter.hasMoreElements())
471 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
473 try { listener->dragEnter( e); }
474 catch (RuntimeException&) {}
479 void DropTarget::fire_dragExit(const DropTargetEvent& dte)
481 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
483 if( pContainer)
485 OInterfaceIteratorHelper iter( *pContainer);
486 while( iter.hasMoreElements())
488 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
490 try { listener->dragExit( dte); }
491 catch (RuntimeException&) {}
496 void DropTarget::fire_dragOver(const DropTargetDragEvent& dtde)
498 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
499 if( pContainer)
501 OInterfaceIteratorHelper iter( *pContainer );
502 while( iter.hasMoreElements())
504 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
506 try { listener->dragOver( dtde); }
507 catch (RuntimeException&) {}
512 void DropTarget::fire_dropActionChanged(const DropTargetDragEvent& dtde)
514 OInterfaceContainerHelper* pContainer= rBHelper.getContainer( cppu::UnoType<XDropTargetListener>::get());
515 if( pContainer)
517 OInterfaceIteratorHelper iter( *pContainer);
518 while( iter.hasMoreElements())
520 uno::Reference<XDropTargetListener> listener( static_cast<XDropTargetListener*>( iter.next()));
522 try { listener->dropActionChanged( dtde); }
523 catch (RuntimeException&) {}
528 OUString SAL_CALL DropTarget::getImplementationName()
530 return dropTarget_getImplementationName();
533 sal_Bool SAL_CALL DropTarget::supportsService( const OUString& ServiceName )
535 return cppu::supportsService(this, ServiceName);
538 Sequence< OUString > SAL_CALL DropTarget::getSupportedServiceNames( )
540 return dropTarget_getSupportedServiceNames();
543 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */