Update ooo320-m1
[ooovba.git] / vcl / unx / source / dtrans / X11_selection.hxx
blob59f6539b3cfcde3e41237c53b4dd1ac2beafcf4b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: X11_selection.hxx,v $
10 * $Revision: 1.37 $
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>
46 #endif
48 #include <hash_map>
49 #include <list>
51 #include <X11/Xlib.h>
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;
58 namespace x11 {
60 class PixmapHolder; // in bmp.hxx
62 // ------------------------------------------------------------------------
63 rtl_TextEncoding getTextPlainEncoding( const ::rtl::OUString& rMimeType );
65 class SelectionAdaptor
67 public:
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
76 class DropTarget :
77 public ::cppu::WeakComponentImplHelper3<
78 ::com::sun::star::datatransfer::dnd::XDropTarget,
79 ::com::sun::star::lang::XInitialization,
80 ::com::sun::star::lang::XServiceInfo
83 public:
84 ::osl::Mutex m_aMutex;
85 bool m_bActive;
86 sal_Int8 m_nDefaultActions;
87 Window m_aTargetWindow;
88 class SelectionManager* m_pSelectionManager;
89 Reference< ::com::sun::star::datatransfer::dnd::XDragSource >
90 m_xSelectionManager;
91 ::std::list< Reference< ::com::sun::star::datatransfer::dnd::XDropTargetListener > >
92 m_aListeners;
94 DropTarget();
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();
103 // XInitialization
104 virtual void SAL_CALL initialize( const Sequence< Any >& args ) throw ( ::com::sun::star::uno::Exception );
106 // XDropTarget
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();
114 // XServiceInfo
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 >
130 m_xRealDragSource;
131 public:
132 SelectionManagerHolder();
133 virtual ~SelectionManagerHolder();
135 // XServiceInfo
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();
141 // XInitialization
142 virtual void SAL_CALL initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception );
144 // XDragSource
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
152 ) throw();
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;
177 int m_nBufferPos;
178 Window m_aRequestor;
179 Atom m_aProperty;
180 Atom m_aTarget;
181 int m_nFormat;
182 int m_nTransferStartTime;
184 int m_nIncrementalThreshold;
186 // a struct to hold the data associated with a selection
187 struct Selection
189 enum State
191 Inactive, WaitingForResponse, WaitingForData, IncrementalTransfer
194 State m_eState;
195 SelectionAdaptor* m_pAdaptor;
196 Atom m_aAtom;
197 ::osl::Condition m_aDataArrived;
198 Sequence< sal_Int8 > m_aData;
199 Sequence< ::com::sun::star::datatransfer::DataFlavor >
200 m_aTypes;
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;
208 bool m_bHaveUTF16;
209 Atom m_aUTF8Type;
210 bool m_bHaveCompound;
211 bool m_bOwner;
212 Window m_aLastOwner;
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 ),
219 m_pAdaptor( NULL ),
220 m_aAtom( None ),
221 m_aRequestedType( None ),
222 m_nLastTimestamp( 0 ),
223 m_bHaveUTF16( false ),
224 m_aUTF8Type( None ),
225 m_bHaveCompound( false ),
226 m_bOwner( false ),
227 m_aLastOwner( None ),
228 m_pPixmap( NULL ),
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; }
255 // internal data
256 Display* m_pDisplay;
257 oslThread m_aThread;
258 oslThread m_aDragExecuteThread;
259 ::osl::Condition m_aDragRunning;
260 Window m_aWindow;
261 Reference< ::com::sun::star::awt::XDisplayConnection >
262 m_xDisplayConnection;
263 Reference< com::sun::star::script::XInvocation >
264 m_xBitmapConverter;
265 sal_Int32 m_nSelectionTimeout;
266 Time m_nSelectionTimestamp;
269 // members used for Xdnd
271 // drop only
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
283 Time m_nDropTime;
284 sal_Int8 m_nLastDropAction;
285 // XTransferable for Xdnd with foreign drag source
286 Reference< ::com::sun::star::datatransfer::XTransferable >
287 m_xDropTransferable;
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;
296 // drag only
298 // None if no Dnd action is running with us as source
299 Window m_aDropWindow;
300 // either m_aDropWindow or its XdndProxy
301 Window m_aDropProxy;
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;
308 // root coordinates
309 int m_nLastDragX, m_nLastDragY;
310 Sequence< ::com::sun::star::datatransfer::DataFlavor >
311 m_aDragFlavors;
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;
320 bool m_bDropSuccess;
321 bool m_bDropSent;
322 time_t m_nDropTimeout;
323 bool m_bWaitingForPrimaryConversion;
324 Time m_nDragTimestamp;
326 // drag cursors
327 Cursor m_aMoveCursor;
328 Cursor m_aCopyCursor;
329 Cursor m_aLinkCursor;
330 Cursor m_aNoneCursor;
331 Cursor m_aCurrentCursor;
334 // drag and drop
336 int m_nCurrentProtocolVersion;
337 ::std::hash_map< Window, DropTargetEntry >
338 m_aDropTargets;
341 // some special atoms that are needed often
342 Atom m_nCLIPBOARDAtom;
343 Atom m_nTARGETSAtom;
344 Atom m_nTIMESTAMPAtom;
345 Atom m_nTEXTAtom;
346 Atom m_nINCRAtom;
347 Atom m_nCOMPOUNDAtom;
348 Atom m_nMULTIPLEAtom;
349 Atom m_nUTF16Atom;
350 Atom m_nImageBmpAtom;
351 Atom m_nXdndAware;
352 Atom m_nXdndEnter;
353 Atom m_nXdndLeave;
354 Atom m_nXdndPosition;
355 Atom m_nXdndStatus;
356 Atom m_nXdndDrop;
357 Atom m_nXdndFinished;
358 Atom m_nXdndSelection;
359 Atom m_nXdndTypeList;
360 Atom m_nXdndProxy;
361 Atom m_nXdndActionCopy;
362 Atom m_nXdndActionMove;
363 Atom m_nXdndActionLink;
364 Atom m_nXdndActionAsk;
365 Atom m_nXdndActionPrivate;
367 // caching for atoms
368 ::std::hash_map< Atom, ::rtl::OUString >
369 m_aAtomToString;
370 ::std::hash_map< ::rtl::OUString, Atom, ::rtl::OUStringHash >
371 m_aStringToAtom;
373 // the registered selections
374 ::std::hash_map< Atom, Selection* >
375 m_aSelections;
376 // IncrementalTransfers in progress
377 std::hash_map< Window, std::hash_map< Atom, IncrementalTransfer > >
378 m_aIncrementals;
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;
385 SelectionManager();
386 ~SelectionManager();
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 );
399 // dnd helpers
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,
411 Atom nType,
412 Atom nSelection,
413 int & rFormat,
414 Sequence< sal_Int8 >& rData );
415 bool sendData( SelectionAdaptor* pAdaptor, Window requestor, Atom target, Atom property, Atom selection );
417 // thread dispatch loop
418 public:
419 // public for extern "C" stub
420 static void run( void* );
421 private:
422 void dispatchEvent( int millisec );
423 // drag thread dispatch
424 public:
425 // public for extern "C" stub
426 static void runDragExecute( void* );
427 private:
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();
437 public:
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 );
455 // type conversion
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();
481 // XInitialization
482 virtual void SAL_CALL initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception );
484 // XEventHandler
485 virtual sal_Bool SAL_CALL handleEvent( const Any& event ) throw();
487 // XDragSource
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
495 ) throw();
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 // ------------------------------------------------------------------------
518 #endif