1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: X11_selection.hxx,v $
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 #ifndef _DTRANS_X11_SELECTION_HXX_
32 #define _DTRANS_X11_SELECTION_HXX_
34 #include <cppuhelper/compbase3.hxx>
35 #include <com/sun/star/datatransfer/XTransferable.hpp>
36 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
37 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
38 #include <com/sun/star/awt/XDisplayConnection.hpp>
39 #include <com/sun/star/lang/XInitialization.hpp>
40 #include <com/sun/star/lang/XServiceInfo.hpp>
41 #include <com/sun/star/script/XInvocation.hpp>
42 #include <osl/thread.h>
44 #ifndef _OSL_CONDITION_HXX_
45 #include <osl/conditn.hxx>
53 #define XDND_IMPLEMENTATION_NAME "com.sun.star.datatransfer.dnd.XdndSupport"
54 #define XDND_DROPTARGET_IMPLEMENTATION_NAME "com.sun.star.datatransfer.dnd.XdndDropTarget"
56 using namespace ::com::sun::star::uno
;
60 class PixmapHolder
; // in bmp.hxx
62 // ------------------------------------------------------------------------
63 rtl_TextEncoding
getTextPlainEncoding( const ::rtl::OUString
& rMimeType
);
65 class SelectionAdaptor
68 virtual Reference
< ::com::sun::star::datatransfer::XTransferable
> getTransferable() = 0;
69 virtual void clearTransferable() = 0;
70 virtual void fireContentsChanged() = 0;
71 virtual Reference
< XInterface
> getReference() = 0;
72 // returns a reference that will keep the SelectionAdaptor alive until the
73 // refernce is released
77 public ::cppu::WeakComponentImplHelper3
<
78 ::com::sun::star::datatransfer::dnd::XDropTarget
,
79 ::com::sun::star::lang::XInitialization
,
80 ::com::sun::star::lang::XServiceInfo
84 ::osl::Mutex m_aMutex
;
86 sal_Int8 m_nDefaultActions
;
87 Window m_aTargetWindow
;
88 class SelectionManager
* m_pSelectionManager
;
89 Reference
< ::com::sun::star::datatransfer::dnd::XDragSource
>
91 ::std::list
< Reference
< ::com::sun::star::datatransfer::dnd::XDropTargetListener
> >
95 virtual ~DropTarget();
97 // convenience functions that loop over listeners
98 void dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent
& dtde
) throw();
99 void dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent
& dte
) throw();
100 void dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent
& dtde
) throw();
101 void drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent
& dtde
) throw();
104 virtual void SAL_CALL
initialize( const Sequence
< Any
>& args
) throw ( ::com::sun::star::uno::Exception
);
107 virtual void SAL_CALL
addDropTargetListener( const Reference
< ::com::sun::star::datatransfer::dnd::XDropTargetListener
>& ) throw();
108 virtual void SAL_CALL
removeDropTargetListener( const Reference
< ::com::sun::star::datatransfer::dnd::XDropTargetListener
>& ) throw();
109 virtual sal_Bool SAL_CALL
isActive() throw();
110 virtual void SAL_CALL
setActive( sal_Bool active
) throw();
111 virtual sal_Int8 SAL_CALL
getDefaultActions() throw();
112 virtual void SAL_CALL
setDefaultActions( sal_Int8 actions
) throw();
115 virtual ::rtl::OUString SAL_CALL
getImplementationName() throw();
116 virtual sal_Bool SAL_CALL
supportsService( const ::rtl::OUString
& ServiceName
) throw();
117 virtual ::com::sun::star::uno::Sequence
< ::rtl::OUString
>
118 SAL_CALL
getSupportedServiceNames() throw();
121 class SelectionManagerHolder
:
122 public ::cppu::WeakComponentImplHelper3
<
123 ::com::sun::star::datatransfer::dnd::XDragSource
,
124 ::com::sun::star::lang::XInitialization
,
125 ::com::sun::star::lang::XServiceInfo
128 ::osl::Mutex m_aMutex
;
129 Reference
< ::com::sun::star::datatransfer::dnd::XDragSource
>
132 SelectionManagerHolder();
133 virtual ~SelectionManagerHolder();
136 virtual ::rtl::OUString SAL_CALL
getImplementationName() throw();
137 virtual sal_Bool SAL_CALL
supportsService( const ::rtl::OUString
& ServiceName
) throw();
138 virtual ::com::sun::star::uno::Sequence
< ::rtl::OUString
>
139 SAL_CALL
getSupportedServiceNames() throw();
142 virtual void SAL_CALL
initialize( const Sequence
< Any
>& arguments
) throw( ::com::sun::star::uno::Exception
);
145 virtual sal_Bool SAL_CALL
isDragImageSupported() throw();
146 virtual sal_Int32 SAL_CALL
getDefaultCursor( sal_Int8 dragAction
) throw();
147 virtual void SAL_CALL
startDrag(
148 const ::com::sun::star::datatransfer::dnd::DragGestureEvent
& trigger
,
149 sal_Int8 sourceActions
, sal_Int32 cursor
, sal_Int32 image
,
150 const Reference
< ::com::sun::star::datatransfer::XTransferable
>& transferable
,
151 const Reference
< ::com::sun::star::datatransfer::dnd::XDragSourceListener
>& listener
157 class SelectionManager
:
158 public ::cppu::WeakImplHelper3
<
159 ::com::sun::star::datatransfer::dnd::XDragSource
,
160 ::com::sun::star::lang::XInitialization
,
161 ::com::sun::star::awt::XEventHandler
163 public SelectionAdaptor
165 static ::std::hash_map
< ::rtl::OUString
, SelectionManager
*, ::rtl::OUStringHash
>& getInstances();
167 // for INCR type selection transfer
168 // INCR protocol is used if the data cannot
169 // be transported at once but in parts
170 // IncrementalTransfer holds the bytes to be transmitted
171 // as well a the current position
172 // INCR triggers the delivery of the next part by deleting the
173 // property used to transfer the data
174 struct IncrementalTransfer
176 Sequence
< sal_Int8
> m_aData
;
182 int m_nTransferStartTime
;
184 int m_nIncrementalThreshold
;
186 // a struct to hold the data associated with a selection
191 Inactive
, WaitingForResponse
, WaitingForData
, IncrementalTransfer
195 SelectionAdaptor
* m_pAdaptor
;
197 ::osl::Condition m_aDataArrived
;
198 Sequence
< sal_Int8
> m_aData
;
199 Sequence
< ::com::sun::star::datatransfer::DataFlavor
>
201 std::vector
< Atom
> m_aNativeTypes
;
202 // this is used for caching
203 // m_aTypes is invalid after 2 seconds
204 // m_aNativeTypes contains the corresponding original atom
205 Atom m_aRequestedType
;
206 // m_aRequestedType is only valid while WaitingForResponse and WaitingFotData
207 int m_nLastTimestamp
;
210 bool m_bHaveCompound
;
213 PixmapHolder
* m_pPixmap
;
214 // m_nOrigTimestamp contains the timestamp at which the seclection
215 // was acquired; needed for TIMESTAMP target
216 Time m_nOrigTimestamp
;
218 Selection() : m_eState( Inactive
),
221 m_aRequestedType( None
),
222 m_nLastTimestamp( 0 ),
223 m_bHaveUTF16( false ),
225 m_bHaveCompound( false ),
227 m_aLastOwner( None
),
229 m_nOrigTimestamp( CurrentTime
)
233 // a struct to hold data associated with a XDropTarget
234 struct DropTargetEntry
236 DropTarget
* m_pTarget
;
237 Window m_aRootWindow
;
239 DropTargetEntry() : m_pTarget( NULL
), m_aRootWindow( None
) {}
240 DropTargetEntry( DropTarget
* pTarget
) :
241 m_pTarget( pTarget
),
242 m_aRootWindow( None
)
244 DropTargetEntry( const DropTargetEntry
& rEntry
) :
245 m_pTarget( rEntry
.m_pTarget
),
246 m_aRootWindow( rEntry
.m_aRootWindow
)
248 ~DropTargetEntry() {}
250 DropTarget
* operator->() const { return m_pTarget
; }
251 DropTargetEntry
& operator=(const DropTargetEntry
& rEntry
)
252 { m_pTarget
= rEntry
.m_pTarget
; m_aRootWindow
= rEntry
.m_aRootWindow
; return *this; }
258 oslThread m_aDragExecuteThread
;
259 ::osl::Condition m_aDragRunning
;
261 Reference
< ::com::sun::star::awt::XDisplayConnection
>
262 m_xDisplayConnection
;
263 Reference
< com::sun::star::script::XInvocation
>
265 sal_Int32 m_nSelectionTimeout
;
266 Time m_nSelectionTimestamp
;
269 // members used for Xdnd
273 // contains the XdndEnterEvent of a drop action running
274 // with one of our targets. The data.l[0] member
275 // (conatining the drag source window) is set
276 // to None while that is not the case
277 XClientMessageEvent m_aDropEnterEvent
;
278 // set to false on XdndEnter
279 // set to true on first XdndPosition or XdndLeave
280 bool m_bDropEnterSent
;
281 Window m_aCurrentDropWindow
;
282 // time code of XdndDrop
284 sal_Int8 m_nLastDropAction
;
285 // XTransferable for Xdnd with foreign drag source
286 Reference
< ::com::sun::star::datatransfer::XTransferable
>
288 int m_nLastX
, m_nLastY
;
289 Time m_nDropTimestamp
;
290 // set to true when calling drop()
291 // if another XdndEnter is received this shows that
292 // someone forgot to call dropComplete - we should reset
293 // and react to the new drop
294 bool m_bDropWaitingForCompletion
;
298 // None if no Dnd action is running with us as source
299 Window m_aDropWindow
;
300 // either m_aDropWindow or its XdndProxy
302 Window m_aDragSourceWindow
;
303 // XTransferable for Xdnd when we are drag source
304 Reference
< ::com::sun::star::datatransfer::XTransferable
>
305 m_xDragSourceTransferable
;
306 Reference
< ::com::sun::star::datatransfer::dnd::XDragSourceListener
>
307 m_xDragSourceListener
;
309 int m_nLastDragX
, m_nLastDragY
;
310 Sequence
< ::com::sun::star::datatransfer::DataFlavor
>
312 // the rectangle the pointer must leave until a new XdndPosition should
313 // be sent. empty unless the drop target told to fill
314 int m_nNoPosX
, m_nNoPosY
, m_nNoPosWidth
, m_nNoPosHeight
;
315 unsigned int m_nDragButton
;
316 sal_Int8 m_nUserDragAction
;
317 sal_Int8 m_nTargetAcceptAction
;
318 sal_Int8 m_nSourceActions
;
319 bool m_bLastDropAccepted
;
322 time_t m_nDropTimeout
;
323 bool m_bWaitingForPrimaryConversion
;
324 Time m_nDragTimestamp
;
327 Cursor m_aMoveCursor
;
328 Cursor m_aCopyCursor
;
329 Cursor m_aLinkCursor
;
330 Cursor m_aNoneCursor
;
331 Cursor m_aCurrentCursor
;
336 int m_nCurrentProtocolVersion
;
337 ::std::hash_map
< Window
, DropTargetEntry
>
341 // some special atoms that are needed often
342 Atom m_nCLIPBOARDAtom
;
344 Atom m_nTIMESTAMPAtom
;
347 Atom m_nCOMPOUNDAtom
;
348 Atom m_nMULTIPLEAtom
;
350 Atom m_nImageBmpAtom
;
354 Atom m_nXdndPosition
;
357 Atom m_nXdndFinished
;
358 Atom m_nXdndSelection
;
359 Atom m_nXdndTypeList
;
361 Atom m_nXdndActionCopy
;
362 Atom m_nXdndActionMove
;
363 Atom m_nXdndActionLink
;
364 Atom m_nXdndActionAsk
;
365 Atom m_nXdndActionPrivate
;
368 ::std::hash_map
< Atom
, ::rtl::OUString
>
370 ::std::hash_map
< ::rtl::OUString
, Atom
, ::rtl::OUStringHash
>
373 // the registered selections
374 ::std::hash_map
< Atom
, Selection
* >
376 // IncrementalTransfers in progress
377 std::hash_map
< Window
, std::hash_map
< Atom
, IncrementalTransfer
> >
380 // do not use X11 multithreading capabilities
381 // since this leads to deadlocks in different Xlib implentations
382 // (XFree as well as Xsun) use an own mutex instead
383 ::osl::Mutex m_aMutex
;
388 SelectionAdaptor
* getAdaptor( Atom selection
);
389 PixmapHolder
* getPixmapHolder( Atom selection
);
391 // handle various events
392 bool handleSelectionRequest( XSelectionRequestEvent
& rRequest
);
393 bool handleSendPropertyNotify( XPropertyEvent
& rNotify
);
394 bool handleReceivePropertyNotify( XPropertyEvent
& rNotify
);
395 bool handleSelectionNotify( XSelectionEvent
& rNotify
);
396 bool handleDragEvent( XEvent
& rMessage
);
397 bool handleDropEvent( XClientMessageEvent
& rMessage
);
400 void sendDragStatus( Atom nDropAction
);
401 void sendDropPosition( bool bForce
, Time eventTime
);
402 bool updateDragAction( int modifierState
);
403 int getXdndVersion( Window aWindow
, Window
& rProxy
);
404 Cursor
createCursor( const char* pPointerData
, const char* pMaskData
, int width
, int height
, int hotX
, int hotY
);
405 // coordinates on root window
406 void updateDragWindow( int nX
, int nY
, Window aRoot
);
408 bool getPasteData( Atom selection
, Atom type
, Sequence
< sal_Int8
>& rData
);
409 // returns true if conversion was successful
410 bool convertData( const Reference
< ::com::sun::star::datatransfer::XTransferable
>& xTransferable
,
414 Sequence
< sal_Int8
>& rData
);
415 bool sendData( SelectionAdaptor
* pAdaptor
, Window requestor
, Atom target
, Atom property
, Atom selection
);
417 // thread dispatch loop
419 // public for extern "C" stub
420 static void run( void* );
422 void dispatchEvent( int millisec
);
423 // drag thread dispatch
425 // public for extern "C" stub
426 static void runDragExecute( void* );
428 void dragDoDispatch();
429 bool handleXEvent( XEvent
& rEvent
);
431 // compound text conversion
432 ::rtl::OString
convertToCompound( const ::rtl::OUString
& rText
);
433 ::rtl::OUString
convertFromCompound( const char* pText
, int nLen
= -1 );
435 sal_Int8
getUserDragAction() const;
436 sal_Int32
getSelectionTimeout();
438 static SelectionManager
& get( const ::rtl::OUString
& rDisplayName
= ::rtl::OUString() );
440 Display
* getDisplay() { return m_pDisplay
; };
441 Window
getWindow() { return m_aWindow
; };
444 void registerHandler( Atom selection
, SelectionAdaptor
& rAdaptor
);
445 void deregisterHandler( Atom selection
);
446 bool requestOwnership( Atom selection
);
448 // allow for synchronization over one mutex for XClipboard
449 osl::Mutex
& getMutex() { return m_aMutex
; }
452 Atom
getAtom( const ::rtl::OUString
& rString
);
453 const ::rtl::OUString
& getString( Atom nAtom
);
456 // note: convertTypeToNative does NOT clear the list, so you can append
457 // multiple types to the same list
458 void convertTypeToNative( const ::rtl::OUString
& rType
, Atom selection
, int& rFormat
, ::std::list
< Atom
>& rConversions
, bool bPushFront
= false );
459 ::rtl::OUString
convertTypeFromNative( Atom nType
, Atom selection
, int& rFormat
);
460 void getNativeTypeList( const Sequence
< com::sun::star::datatransfer::DataFlavor
>& rTypes
, std::list
< Atom
>& rOutTypeList
, Atom targetselection
);
462 // methods for transferable
463 bool getPasteDataTypes( Atom selection
, Sequence
< ::com::sun::star::datatransfer::DataFlavor
>& rTypes
);
464 bool getPasteData( Atom selection
, const ::rtl::OUString
& rType
, Sequence
< sal_Int8
>& rData
);
466 // for XDropTarget to register/deregister itself
467 void registerDropTarget( Window aWindow
, DropTarget
* pTarget
);
468 void deregisterDropTarget( Window aWindow
);
470 // for XDropTarget{Drag|Drop}Context
471 void accept( sal_Int8 dragOperation
, Window aDropWindow
, Time aTimestamp
);
472 void reject( Window aDropWindow
, Time aTimestamp
);
473 void dropComplete( sal_Bool success
, Window aDropWindow
, Time aTimestamp
);
475 // for XDragSourceContext
476 sal_Int32
getCurrentCursor();
477 void setCursor( sal_Int32 cursor
, Window aDropWindow
, Time aTimestamp
);
478 void setImage( sal_Int32 image
, Window aDropWindow
, Time aTimestamp
);
479 void transferablesFlavorsChanged();
482 virtual void SAL_CALL
initialize( const Sequence
< Any
>& arguments
) throw( ::com::sun::star::uno::Exception
);
485 virtual sal_Bool SAL_CALL
handleEvent( const Any
& event
) throw();
488 virtual sal_Bool SAL_CALL
isDragImageSupported() throw();
489 virtual sal_Int32 SAL_CALL
getDefaultCursor( sal_Int8 dragAction
) throw();
490 virtual void SAL_CALL
startDrag(
491 const ::com::sun::star::datatransfer::dnd::DragGestureEvent
& trigger
,
492 sal_Int8 sourceActions
, sal_Int32 cursor
, sal_Int32 image
,
493 const Reference
< ::com::sun::star::datatransfer::XTransferable
>& transferable
,
494 const Reference
< ::com::sun::star::datatransfer::dnd::XDragSourceListener
>& listener
497 // SelectionAdaptor for XdndSelection Drag (we are drag source)
498 virtual Reference
< ::com::sun::star::datatransfer::XTransferable
> getTransferable() throw();
499 virtual void clearTransferable() throw();
500 virtual void fireContentsChanged() throw();
501 virtual Reference
< XInterface
> getReference() throw();
504 // ------------------------------------------------------------------------
506 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> SAL_CALL
Xdnd_getSupportedServiceNames();
507 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> SAL_CALL
Xdnd_createInstance(
508 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> & xMultiServiceFactory
);
510 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> SAL_CALL
Xdnd_dropTarget_getSupportedServiceNames();
511 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> SAL_CALL
Xdnd_dropTarget_createInstance(
512 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
> & xMultiServiceFactory
);
514 // ------------------------------------------------------------------------