1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/awt/MouseButton.hpp>
24 #include "rtl/ustring.hxx"
26 #include "comphelper/makesequence.hxx"
27 #include <cppuhelper/supportsservice.hxx>
29 #include "DragSource.hxx"
30 #include "DragSourceContext.hxx"
31 #include "clipboard.hxx"
32 #include "DragActionConversion.hxx"
34 #include "osx/salframe.h"
41 using namespace com::sun::star
;
42 using namespace com::sun::star::datatransfer
;
43 using namespace com::sun::star::datatransfer::clipboard
;
44 using namespace com::sun::star::datatransfer::dnd
;
45 using namespace com::sun::star::datatransfer::dnd::DNDConstants
;
46 using namespace com::sun::star::uno
;
47 using namespace com::sun::star::awt::MouseButton
;
48 using namespace com::sun::star::awt
;
49 using namespace com::sun::star::lang
;
50 using namespace comphelper
;
53 // For OOo internal D&D we provide the Transferable without NSDragPboard
54 // interference as a shortcut
55 uno::Reference
<XTransferable
> DragSource::g_XTransferable
;
56 NSView
* DragSource::g_DragSourceView
= nil
;
57 bool DragSource::g_DropSuccessSet
= false;
58 bool DragSource::g_DropSuccess
= false;
60 OUString
dragSource_getImplementationName()
62 return OUString("com.sun.star.comp.datatransfer.dnd.OleDragSource_V1");
65 Sequence
<OUString
> dragSource_getSupportedServiceNames()
67 return makeSequence(OUString("com.sun.star.datatransfer.dnd.OleDragSource"));
70 @implementation DragSourceHelper
;
72 -(DragSourceHelper
*)initWithDragSource
: (DragSource
*) pds
84 -(void)mouseDown
: (NSEvent
*)theEvent
86 mDragSource
->saveMouseEvent(theEvent
);
89 -(void)mouseDragged
: (NSEvent
*)theEvent
91 mDragSource
->saveMouseEvent(theEvent
);
94 -(unsigned int)draggingSourceOperationMaskForLocal
: (BOOL
)isLocal
96 return mDragSource
->getSupportedDragOperations(isLocal
);
99 -(void)draggedImage
:(NSImage
*)anImage beganAt
:(NSPoint
)aPoint
103 DragSourceDragEvent
dsde(static_cast<OWeakObject
*>(mDragSource
),
104 new DragSourceContext
,
106 DNDConstants::ACTION_COPY
,
107 DNDConstants::ACTION_COPY
);
109 mDragSource
->mXDragSrcListener
->dragEnter(dsde
);
112 -(void)draggedImage
:(NSImage
*)anImage endedAt
:(NSPoint
)aPoint operation
:(NSDragOperation
)operation
116 // an internal drop can accept the drop but fail with dropComplete( false )
117 // this is different than the Cocoa API
118 bool bDropSuccess
= operation
!= NSDragOperationNone
;
119 if( DragSource::g_DropSuccessSet
)
120 bDropSuccess
= DragSource::g_DropSuccess
;
122 DragSourceDropEvent
dsde(static_cast<OWeakObject
*>(mDragSource
),
123 new DragSourceContext
,
124 static_cast< XDragSource
* >(mDragSource
),
125 SystemToOfficeDragActions(operation
),
128 mDragSource
->mXDragSrcListener
->dragDropEnd(dsde
);
129 mDragSource
->mXDragSrcListener
= uno::Reference
<XDragSourceListener
>();
132 -(void)draggedImage
:(NSImage
*)draggedImage movedTo
:(NSPoint
)screenPoint
136 DragSourceDragEvent
dsde(static_cast<OWeakObject
*>(mDragSource
),
137 new DragSourceContext
,
139 DNDConstants::ACTION_COPY
,
140 DNDConstants::ACTION_COPY
);
142 mDragSource
->mXDragSrcListener
->dragOver(dsde
);
147 DragSource::DragSource():
148 WeakComponentImplHelper3
<XDragSource
, XInitialization
, XServiceInfo
>(m_aMutex
),
151 mLastMouseEventBeforeStartDrag(nil
),
156 DragSource::~DragSource()
158 if( mpFrame
&& AquaSalFrame::isAlive( mpFrame
) )
159 [(id
<MouseEventListener
>)mView unregisterMouseEventListener
: mDragSourceHelper
];
160 [mDragSourceHelper release
];
163 void SAL_CALL
DragSource::initialize(const Sequence
< Any
>& aArguments
)
164 throw(Exception
, std::exception
)
166 if (aArguments
.getLength() < 2)
168 throw Exception("DragSource::initialize: Not enough parameter.",
169 static_cast<OWeakObject
*>(this));
172 Any pNSView
= aArguments
[1];
175 mView
= reinterpret_cast<NSView
*>(tmp
);
177 /* All SalFrameView the base class for all VCL system views inherits from
178 NSView in order to get mouse and other events. This is the only way to
179 get these events. In order to start a drag operation we need to provide
180 the mouse event which was the trigger. SalFrameView therefore implements
181 a hook mechanism so that we can get mouse events for our purpose.
183 if (![mView respondsToSelector
: @
selector(registerMouseEventListener
:)] ||
184 ![mView respondsToSelector
: @
selector(unregisterMouseEventListener
:)])
186 throw Exception("DragSource::initialize: Provided view doesn't support mouse listener",
187 static_cast<OWeakObject
*>(this));
189 NSWindow
* pWin
= [mView window
];
190 if( ! pWin
|| ![pWin respondsToSelector
: @
selector(getSalFrame
)] )
192 throw Exception("DragSource::initialize: Provided view is not attached to a vcl frame",
193 static_cast<OWeakObject
*>(this));
195 mpFrame
= reinterpret_cast<AquaSalFrame
*>([pWin performSelector
: @
selector(getSalFrame
)]);
197 mDragSourceHelper
= [[DragSourceHelper alloc
] initWithDragSource
: this];
199 if (mDragSourceHelper
== nil
)
201 throw Exception("DragSource::initialize: Cannot initialize DragSource",
202 static_cast<OWeakObject
*>(this));
205 [(id
<MouseEventListener
>)mView registerMouseEventListener
: mDragSourceHelper
];
208 sal_Bool SAL_CALL
DragSource::isDragImageSupported( )
209 throw(RuntimeException
, std::exception
)
214 sal_Int32 SAL_CALL
DragSource::getDefaultCursor( sal_Int8
/*dragAction*/ )
215 throw( IllegalArgumentException
, RuntimeException
, std::exception
)
220 void SAL_CALL
DragSource::startDrag(const DragGestureEvent
& trigger
,
221 sal_Int8 sourceActions
,
222 sal_Int32
/*cursor*/,
224 const uno::Reference
<XTransferable
>& transferable
,
225 const uno::Reference
<XDragSourceListener
>& listener
)
226 throw( RuntimeException
, std::exception
)
228 MutexGuard
guard(m_aMutex
);
230 assert(listener
.is() && "DragSource::startDrag: No XDragSourceListener provided\n");
231 assert(transferable
.is() && "DragSource::startDrag: No transferable provided\n");
233 trigger
.Event
>>= mMouseEvent
;
234 m_MouseButton
= mMouseEvent
.Buttons
;
235 mXDragSrcListener
= listener
;
236 mXCurrentContext
= static_cast<XDragSourceContext
*>(new DragSourceContext
);
237 unique_ptr
<AquaClipboard
> clipb(new AquaClipboard(NULL
, false));
238 g_XTransferable
= transferable
;
239 clipb
->setContents(g_XTransferable
, uno::Reference
<XClipboardOwner
>());
240 mDragSourceActions
= sourceActions
;
241 g_DragSourceView
= mView
;
248 dragImage
= [[NSImage alloc
] initWithSize
: sz
];
251 bounds
.origin
= NSMakePoint(0,0);
254 [dragImage lockFocus
];
255 [[NSColor blackColor
] set
];
256 [NSBezierPath fillRect
: bounds
];
257 [dragImage unlockFocus
];
259 NSPoint pInWnd
= [mLastMouseEventBeforeStartDrag locationInWindow
];
261 p
= [mView convertPoint
: pInWnd fromView
: nil
];
262 p
.x
= p
.x
- sz
.width
/2;
263 p
.y
= p
.y
- sz
.height
/2;
265 // reset drop success flags
266 g_DropSuccessSet
= false;
267 g_DropSuccess
= false;
269 SAL_WNODEPRECATED_DECLARATIONS_PUSH
270 //TODO: 10.7 dragImage:at:offset:event:pasteboard:source:slideBack:
271 [mView dragImage
: dragImage
273 offset
: NSMakeSize(0,0)
274 event
: mLastMouseEventBeforeStartDrag
275 pasteboard
: clipb
->getPasteboard()
276 source
: mDragSourceHelper
278 SAL_WNODEPRECATED_DECLARATIONS_POP
282 g_XTransferable
= uno::Reference
<XTransferable
>();
283 g_DragSourceView
= nil
;
285 // reset drop success flags
286 g_DropSuccessSet
= false;
287 g_DropSuccess
= false;
290 // In order to initiate a D&D operation we need to
291 // provide the triggering mouse event which we get
292 // from the SalFrameView that is associated with
294 void DragSource::saveMouseEvent(NSEvent
* theEvent
)
296 if (mLastMouseEventBeforeStartDrag
!= nil
)
298 [mLastMouseEventBeforeStartDrag release
];
301 mLastMouseEventBeforeStartDrag
= theEvent
;
304 /* isLocal indicates whether or not the DnD operation is OOo
307 unsigned int DragSource::getSupportedDragOperations(bool isLocal
) const
309 unsigned int srcActions
= OfficeToSystemDragActions(mDragSourceActions
);
313 // Support NSDragOperation generic which means we can
314 // decide which D&D operation to choose. We map
315 // NSDragOperationGenric to DNDConstants::ACTION_DEFAULT
316 // in SystemToOfficeDragActions to signal this and
317 // use it in DropTarget::determineDropAction
318 srcActions
|= NSDragOperationGeneric
;
322 // Mask out link and move operations on external DnD
323 srcActions
&= ~(NSDragOperationMove
| NSDragOperationLink
);
329 OUString SAL_CALL
DragSource::getImplementationName( ) throw (RuntimeException
, std::exception
)
331 return dragSource_getImplementationName();
334 sal_Bool SAL_CALL
DragSource::supportsService( const OUString
& ServiceName
) throw (RuntimeException
, std::exception
)
336 return cppu::supportsService(this, ServiceName
);
339 Sequence
< OUString
> SAL_CALL
DragSource::getSupportedServiceNames() throw (RuntimeException
, std::exception
)
341 return dragSource_getSupportedServiceNames();
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */