1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*9f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*9f62ea84SAndrew Rist * distributed with this work for additional information
6*9f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*9f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*9f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*9f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
17*9f62ea84SAndrew Rist * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*9f62ea84SAndrew Rist *************************************************************/
21*9f62ea84SAndrew Rist
22*9f62ea84SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
28cdf0e10cSrcweir #include <com/sun/star/datatransfer/XTransferable.hpp>
29cdf0e10cSrcweir #include <com/sun/star/awt/MouseButton.hpp>
30cdf0e10cSrcweir
31cdf0e10cSrcweir #include "rtl/unload.h"
32cdf0e10cSrcweir #include "rtl/ustring.hxx"
33cdf0e10cSrcweir
34cdf0e10cSrcweir #include "comphelper/makesequence.hxx"
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include "DragSource.hxx"
37cdf0e10cSrcweir #include "DragSourceContext.hxx"
38cdf0e10cSrcweir #include "aqua_clipboard.hxx"
39cdf0e10cSrcweir #include "DragActionConversion.hxx"
40cdf0e10cSrcweir
41cdf0e10cSrcweir #include "aqua/salframe.h"
42cdf0e10cSrcweir
43cdf0e10cSrcweir #include <memory>
44cdf0e10cSrcweir
45cdf0e10cSrcweir
46cdf0e10cSrcweir using namespace rtl;
47cdf0e10cSrcweir using namespace cppu;
48cdf0e10cSrcweir using namespace osl;
49cdf0e10cSrcweir using namespace com::sun::star;
50cdf0e10cSrcweir using namespace com::sun::star::datatransfer;
51cdf0e10cSrcweir using namespace com::sun::star::datatransfer::clipboard;
52cdf0e10cSrcweir using namespace com::sun::star::datatransfer::dnd;
53cdf0e10cSrcweir using namespace com::sun::star::datatransfer::dnd::DNDConstants;
54cdf0e10cSrcweir using namespace com::sun::star::uno;
55cdf0e10cSrcweir using namespace com::sun::star::awt::MouseButton;
56cdf0e10cSrcweir using namespace com::sun::star::awt;
57cdf0e10cSrcweir using namespace com::sun::star::lang;
58cdf0e10cSrcweir using namespace comphelper;
59cdf0e10cSrcweir using namespace std;
60cdf0e10cSrcweir
61cdf0e10cSrcweir
62cdf0e10cSrcweir // For OOo internal D&D we provide the Transferable without NSDragPboard
63cdf0e10cSrcweir // interference as a shortcut
64cdf0e10cSrcweir uno::Reference<XTransferable> DragSource::g_XTransferable;
65cdf0e10cSrcweir NSView* DragSource::g_DragSourceView = nil;
66cdf0e10cSrcweir bool DragSource::g_DropSuccessSet = false;
67cdf0e10cSrcweir bool DragSource::g_DropSuccess = false;
68cdf0e10cSrcweir
69cdf0e10cSrcweir
dragSource_getImplementationName()70cdf0e10cSrcweir OUString dragSource_getImplementationName()
71cdf0e10cSrcweir {
72cdf0e10cSrcweir return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.datatransfer.dnd.OleDragSource_V1"));
73cdf0e10cSrcweir }
74cdf0e10cSrcweir
dragSource_getSupportedServiceNames()75cdf0e10cSrcweir Sequence<OUString> dragSource_getSupportedServiceNames()
76cdf0e10cSrcweir {
77cdf0e10cSrcweir return makeSequence(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDragSource")));
78cdf0e10cSrcweir }
79cdf0e10cSrcweir
80cdf0e10cSrcweir
81cdf0e10cSrcweir @implementation DragSourceHelper;
82cdf0e10cSrcweir
83cdf0e10cSrcweir -(DragSourceHelper*)initWithDragSource: (DragSource*) pds
84cdf0e10cSrcweir {
85cdf0e10cSrcweir self = [super init];
86cdf0e10cSrcweir
87cdf0e10cSrcweir if (self)
88cdf0e10cSrcweir {
89cdf0e10cSrcweir mDragSource = pds;
90cdf0e10cSrcweir }
91cdf0e10cSrcweir
92cdf0e10cSrcweir return self;
93cdf0e10cSrcweir }
94cdf0e10cSrcweir
95cdf0e10cSrcweir
96cdf0e10cSrcweir -(void)mouseDown: (NSEvent*)theEvent
97cdf0e10cSrcweir {
98cdf0e10cSrcweir mDragSource->saveMouseEvent(theEvent);
99cdf0e10cSrcweir }
100cdf0e10cSrcweir
101cdf0e10cSrcweir
102cdf0e10cSrcweir -(void)mouseDragged: (NSEvent*)theEvent
103cdf0e10cSrcweir {
104cdf0e10cSrcweir mDragSource->saveMouseEvent(theEvent);
105cdf0e10cSrcweir }
106cdf0e10cSrcweir
107cdf0e10cSrcweir
108cdf0e10cSrcweir -(unsigned int)draggingSourceOperationMaskForLocal: (BOOL)isLocal
109cdf0e10cSrcweir {
110cdf0e10cSrcweir return mDragSource->getSupportedDragOperations(isLocal);
111cdf0e10cSrcweir }
112cdf0e10cSrcweir
113cdf0e10cSrcweir
114cdf0e10cSrcweir -(void)draggedImage:(NSImage*)anImage beganAt:(NSPoint)aPoint
115cdf0e10cSrcweir {
116cdf0e10cSrcweir (void)anImage;
117cdf0e10cSrcweir (void)aPoint;
118cdf0e10cSrcweir DragSourceDragEvent dsde(static_cast<OWeakObject*>(mDragSource),
119cdf0e10cSrcweir new DragSourceContext(mDragSource),
120cdf0e10cSrcweir mDragSource,
121cdf0e10cSrcweir DNDConstants::ACTION_COPY,
122cdf0e10cSrcweir DNDConstants::ACTION_COPY);
123cdf0e10cSrcweir
124cdf0e10cSrcweir mDragSource->mXDragSrcListener->dragEnter(dsde);
125cdf0e10cSrcweir }
126cdf0e10cSrcweir
127cdf0e10cSrcweir
128cdf0e10cSrcweir -(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
129cdf0e10cSrcweir {
130cdf0e10cSrcweir (void)anImage;
131cdf0e10cSrcweir (void)aPoint;
132cdf0e10cSrcweir // an internal drop can accept the drop but fail with dropComplete( false )
133cdf0e10cSrcweir // this is different than the Cocoa API
134cdf0e10cSrcweir bool bDropSuccess = operation != NSDragOperationNone;
135cdf0e10cSrcweir if( DragSource::g_DropSuccessSet )
136cdf0e10cSrcweir bDropSuccess = DragSource::g_DropSuccess;
137cdf0e10cSrcweir
138cdf0e10cSrcweir DragSourceDropEvent dsde(static_cast<OWeakObject*>(mDragSource),
139cdf0e10cSrcweir new DragSourceContext(mDragSource),
140cdf0e10cSrcweir static_cast< XDragSource* >(mDragSource),
141cdf0e10cSrcweir SystemToOfficeDragActions(operation),
142cdf0e10cSrcweir bDropSuccess );
143cdf0e10cSrcweir
144cdf0e10cSrcweir mDragSource->mXDragSrcListener->dragDropEnd(dsde);
145cdf0e10cSrcweir mDragSource->mXDragSrcListener = uno::Reference<XDragSourceListener>();
146cdf0e10cSrcweir }
147cdf0e10cSrcweir
148cdf0e10cSrcweir
149cdf0e10cSrcweir -(void)draggedImage:(NSImage *)draggedImage movedTo:(NSPoint)screenPoint
150cdf0e10cSrcweir {
151cdf0e10cSrcweir (void)draggedImage;
152cdf0e10cSrcweir (void)screenPoint;
153cdf0e10cSrcweir DragSourceDragEvent dsde(static_cast<OWeakObject*>(mDragSource),
154cdf0e10cSrcweir new DragSourceContext(mDragSource),
155cdf0e10cSrcweir mDragSource,
156cdf0e10cSrcweir DNDConstants::ACTION_COPY,
157cdf0e10cSrcweir DNDConstants::ACTION_COPY);
158cdf0e10cSrcweir
159cdf0e10cSrcweir mDragSource->mXDragSrcListener->dragOver(dsde);
160cdf0e10cSrcweir }
161cdf0e10cSrcweir
162cdf0e10cSrcweir @end
163cdf0e10cSrcweir
164cdf0e10cSrcweir
DragSource()165cdf0e10cSrcweir DragSource::DragSource():
166cdf0e10cSrcweir WeakComponentImplHelper3<XDragSource, XInitialization, XServiceInfo>(m_aMutex),
167cdf0e10cSrcweir mView(NULL),
168cdf0e10cSrcweir mpFrame(NULL),
169cdf0e10cSrcweir mLastMouseEventBeforeStartDrag(nil),
170cdf0e10cSrcweir m_MouseButton(0)
171cdf0e10cSrcweir {
172cdf0e10cSrcweir }
173cdf0e10cSrcweir
174cdf0e10cSrcweir
~DragSource()175cdf0e10cSrcweir DragSource::~DragSource()
176cdf0e10cSrcweir {
177cdf0e10cSrcweir if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
178cdf0e10cSrcweir [(id <MouseEventListener>)mView unregisterMouseEventListener: mDragSourceHelper];
179cdf0e10cSrcweir [mDragSourceHelper release];
180cdf0e10cSrcweir }
181cdf0e10cSrcweir
182cdf0e10cSrcweir
initialize(const Sequence<Any> & aArguments)183cdf0e10cSrcweir void SAL_CALL DragSource::initialize(const Sequence< Any >& aArguments)
184cdf0e10cSrcweir throw(Exception)
185cdf0e10cSrcweir {
186cdf0e10cSrcweir if (aArguments.getLength() < 2)
187cdf0e10cSrcweir {
188cdf0e10cSrcweir throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Not enough parameter.")),
189cdf0e10cSrcweir static_cast<OWeakObject*>(this));
190cdf0e10cSrcweir }
191cdf0e10cSrcweir
192cdf0e10cSrcweir Any pNSView = aArguments[1];
193cdf0e10cSrcweir sal_uInt64 tmp = 0;
194cdf0e10cSrcweir pNSView >>= tmp;
195cdf0e10cSrcweir mView = (NSView*)tmp;
196cdf0e10cSrcweir
197cdf0e10cSrcweir /* All SalFrameView the base class for all VCL system views inherits from
198cdf0e10cSrcweir NSView in order to get mouse and other events. This is the only way to
199cdf0e10cSrcweir get these events. In order to start a drag operation we need to provide
200cdf0e10cSrcweir the mouse event which was the trigger. SalFrameView therefor implements
201cdf0e10cSrcweir a hook mechanism so that we can get mouse events for our purpose.
202cdf0e10cSrcweir */
203cdf0e10cSrcweir if (![mView respondsToSelector: @selector(registerMouseEventListener:)] ||
204cdf0e10cSrcweir ![mView respondsToSelector: @selector(unregisterMouseEventListener:)])
205cdf0e10cSrcweir {
206cdf0e10cSrcweir throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Provided view doesn't support mouse listener")),
207cdf0e10cSrcweir static_cast<OWeakObject*>(this));
208cdf0e10cSrcweir }
209cdf0e10cSrcweir NSWindow* pWin = [mView window];
210cdf0e10cSrcweir if( ! pWin || ![pWin respondsToSelector: @selector(getSalFrame)] )
211cdf0e10cSrcweir {
212cdf0e10cSrcweir throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Provided view is not attached to a vcl frame")),
213cdf0e10cSrcweir static_cast<OWeakObject*>(this));
214cdf0e10cSrcweir }
215cdf0e10cSrcweir mpFrame = (AquaSalFrame*)[pWin performSelector: @selector(getSalFrame)];
216cdf0e10cSrcweir
217cdf0e10cSrcweir mDragSourceHelper = [[DragSourceHelper alloc] initWithDragSource: this];
218cdf0e10cSrcweir
219cdf0e10cSrcweir if (mDragSourceHelper == nil)
220cdf0e10cSrcweir {
221cdf0e10cSrcweir throw Exception(OUString(RTL_CONSTASCII_USTRINGPARAM("DragSource::initialize: Cannot initialize DragSource")),
222cdf0e10cSrcweir static_cast<OWeakObject*>(this));
223cdf0e10cSrcweir }
224cdf0e10cSrcweir
225cdf0e10cSrcweir [(id <MouseEventListener>)mView registerMouseEventListener: mDragSourceHelper];
226cdf0e10cSrcweir }
227cdf0e10cSrcweir
228cdf0e10cSrcweir
229cdf0e10cSrcweir //----------------------------------------------------
230cdf0e10cSrcweir // XDragSource
231cdf0e10cSrcweir //----------------------------------------------------
232cdf0e10cSrcweir
isDragImageSupported()233cdf0e10cSrcweir sal_Bool SAL_CALL DragSource::isDragImageSupported( )
234cdf0e10cSrcweir throw(RuntimeException)
235cdf0e10cSrcweir {
236cdf0e10cSrcweir return true;
237cdf0e10cSrcweir }
238cdf0e10cSrcweir
239cdf0e10cSrcweir
getDefaultCursor(sal_Int8)240cdf0e10cSrcweir sal_Int32 SAL_CALL DragSource::getDefaultCursor( sal_Int8 /*dragAction*/ )
241cdf0e10cSrcweir throw( IllegalArgumentException, RuntimeException)
242cdf0e10cSrcweir {
243cdf0e10cSrcweir return 0;
244cdf0e10cSrcweir }
245cdf0e10cSrcweir
246cdf0e10cSrcweir
startDrag(const DragGestureEvent & trigger,sal_Int8 sourceActions,sal_Int32,sal_Int32,const uno::Reference<XTransferable> & transferable,const uno::Reference<XDragSourceListener> & listener)247cdf0e10cSrcweir void SAL_CALL DragSource::startDrag(const DragGestureEvent& trigger,
248cdf0e10cSrcweir sal_Int8 sourceActions,
249cdf0e10cSrcweir sal_Int32 /*cursor*/,
250cdf0e10cSrcweir sal_Int32 /*image*/,
251cdf0e10cSrcweir const uno::Reference<XTransferable >& transferable,
252cdf0e10cSrcweir const uno::Reference<XDragSourceListener >& listener )
253cdf0e10cSrcweir throw( RuntimeException)
254cdf0e10cSrcweir {
255cdf0e10cSrcweir MutexGuard guard(m_aMutex);
256cdf0e10cSrcweir
257cdf0e10cSrcweir OSL_ASSERT(listener.is() && "DragSource::startDrag: No XDragSourceListener provided\n");
258cdf0e10cSrcweir OSL_ASSERT(transferable.is() && "DragSource::startDrag: No transferable provided\n");
259cdf0e10cSrcweir
260cdf0e10cSrcweir trigger.Event >>= mMouseEvent;
261cdf0e10cSrcweir m_MouseButton= mMouseEvent.Buttons;
262cdf0e10cSrcweir mXDragSrcListener = listener;
263cdf0e10cSrcweir mXCurrentContext = static_cast<XDragSourceContext*>(new DragSourceContext(this));
264cdf0e10cSrcweir auto_ptr<AquaClipboard> clipb(new AquaClipboard(NULL, false));
265cdf0e10cSrcweir g_XTransferable = transferable;
266cdf0e10cSrcweir clipb->setContents(g_XTransferable, uno::Reference<XClipboardOwner>());
267cdf0e10cSrcweir mDragSourceActions = sourceActions;
268cdf0e10cSrcweir g_DragSourceView = mView;
269cdf0e10cSrcweir
270cdf0e10cSrcweir NSSize sz;
271cdf0e10cSrcweir sz.width = 5;
272cdf0e10cSrcweir sz.height = 5;
273cdf0e10cSrcweir
274cdf0e10cSrcweir NSImage* dragImage;
275cdf0e10cSrcweir dragImage = [[NSImage alloc] initWithSize: sz];
276cdf0e10cSrcweir
277cdf0e10cSrcweir NSRect bounds;
278cdf0e10cSrcweir bounds.origin = NSMakePoint(0,0);
279cdf0e10cSrcweir bounds.size = sz;
280cdf0e10cSrcweir
281cdf0e10cSrcweir [dragImage lockFocus];
282cdf0e10cSrcweir [[NSColor blackColor] set];
283cdf0e10cSrcweir [NSBezierPath fillRect: bounds];
284cdf0e10cSrcweir [dragImage unlockFocus];
285cdf0e10cSrcweir
286cdf0e10cSrcweir NSPoint pInWnd = [mLastMouseEventBeforeStartDrag locationInWindow];
287cdf0e10cSrcweir NSPoint p;
288cdf0e10cSrcweir p = [mView convertPoint: pInWnd fromView: nil];
289cdf0e10cSrcweir p.x = p.x - sz.width/2;
290cdf0e10cSrcweir p.y = p.y - sz.height/2;
291cdf0e10cSrcweir
292cdf0e10cSrcweir // reset drop success flags
293cdf0e10cSrcweir g_DropSuccessSet = false;
294cdf0e10cSrcweir g_DropSuccess = false;
295cdf0e10cSrcweir
296cdf0e10cSrcweir [mView dragImage: dragImage
297cdf0e10cSrcweir at: p
298cdf0e10cSrcweir offset: NSMakeSize(0,0)
299cdf0e10cSrcweir event: mLastMouseEventBeforeStartDrag
300cdf0e10cSrcweir pasteboard: clipb->getPasteboard()
301cdf0e10cSrcweir source: mDragSourceHelper
302cdf0e10cSrcweir slideBack: 1];
303cdf0e10cSrcweir
304cdf0e10cSrcweir [dragImage release];
305cdf0e10cSrcweir
306cdf0e10cSrcweir g_XTransferable = uno::Reference<XTransferable>();
307cdf0e10cSrcweir g_DragSourceView = nil;
308cdf0e10cSrcweir
309cdf0e10cSrcweir // reset drop success flags
310cdf0e10cSrcweir g_DropSuccessSet = false;
311cdf0e10cSrcweir g_DropSuccess = false;
312cdf0e10cSrcweir }
313cdf0e10cSrcweir
314cdf0e10cSrcweir
315cdf0e10cSrcweir // In order to initiate a D&D operation we need to
316cdf0e10cSrcweir // provide the triggering mouse event which we get
317cdf0e10cSrcweir // from the SalFrameView that is associated with
318cdf0e10cSrcweir // this DragSource
saveMouseEvent(NSEvent * theEvent)319cdf0e10cSrcweir void DragSource::saveMouseEvent(NSEvent* theEvent)
320cdf0e10cSrcweir {
321cdf0e10cSrcweir if (mLastMouseEventBeforeStartDrag != nil)
322cdf0e10cSrcweir {
323cdf0e10cSrcweir [mLastMouseEventBeforeStartDrag release];
324cdf0e10cSrcweir }
325cdf0e10cSrcweir
326cdf0e10cSrcweir mLastMouseEventBeforeStartDrag = theEvent;
327cdf0e10cSrcweir }
328cdf0e10cSrcweir
329cdf0e10cSrcweir
330cdf0e10cSrcweir /* isLocal indicates whether or not the DnD operation is OOo
331cdf0e10cSrcweir internal.
332cdf0e10cSrcweir */
getSupportedDragOperations(bool isLocal) const333cdf0e10cSrcweir unsigned int DragSource::getSupportedDragOperations(bool isLocal) const
334cdf0e10cSrcweir {
335cdf0e10cSrcweir unsigned int srcActions = OfficeToSystemDragActions(mDragSourceActions);
336cdf0e10cSrcweir
337cdf0e10cSrcweir if (isLocal)
338cdf0e10cSrcweir {
339cdf0e10cSrcweir // Support NSDragOperation generic which means we can
340cdf0e10cSrcweir // decide which D&D operation to choose. We map
341cdf0e10cSrcweir // NSDragOperationGenric to DNDConstants::ACTION_DEFAULT
342cdf0e10cSrcweir // in SystemToOfficeDragActions to signal this and
343cdf0e10cSrcweir // use it in DropTarget::determineDropAction
344cdf0e10cSrcweir srcActions |= NSDragOperationGeneric;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir else
347cdf0e10cSrcweir {
348cdf0e10cSrcweir // Mask out link and move operations on external DnD
349cdf0e10cSrcweir srcActions &= ~(NSDragOperationMove | NSDragOperationLink);
350cdf0e10cSrcweir }
351cdf0e10cSrcweir
352cdf0e10cSrcweir return srcActions;
353cdf0e10cSrcweir }
354cdf0e10cSrcweir
355cdf0e10cSrcweir
356cdf0e10cSrcweir //################################
357cdf0e10cSrcweir // XServiceInfo
358cdf0e10cSrcweir //################################
359cdf0e10cSrcweir
getImplementationName()360cdf0e10cSrcweir OUString SAL_CALL DragSource::getImplementationName( ) throw (RuntimeException)
361cdf0e10cSrcweir {
362cdf0e10cSrcweir return dragSource_getImplementationName();
363cdf0e10cSrcweir }
364cdf0e10cSrcweir
365cdf0e10cSrcweir
supportsService(const OUString & ServiceName)366cdf0e10cSrcweir sal_Bool SAL_CALL DragSource::supportsService( const OUString& ServiceName ) throw (RuntimeException)
367cdf0e10cSrcweir {
368cdf0e10cSrcweir return ServiceName.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.dnd.OleDragSource")));
369cdf0e10cSrcweir }
370cdf0e10cSrcweir
371cdf0e10cSrcweir
getSupportedServiceNames()372cdf0e10cSrcweir Sequence< OUString > SAL_CALL DragSource::getSupportedServiceNames() throw (RuntimeException)
373cdf0e10cSrcweir {
374cdf0e10cSrcweir return dragSource_getSupportedServiceNames();
375cdf0e10cSrcweir }
376cdf0e10cSrcweir
377cdf0e10cSrcweir
378cdf0e10cSrcweir
379cdf0e10cSrcweir
380