xref: /AOO41X/main/vcl/unx/generic/dtrans/X11_selection.cxx (revision 024fb564ad8d4d8ae344f6355df7cd6e03f59e9a)
1c82f2877SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3c82f2877SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4c82f2877SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5c82f2877SAndrew Rist  * distributed with this work for additional information
6c82f2877SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7c82f2877SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8c82f2877SAndrew Rist  * "License"); you may not use this file except in compliance
9c82f2877SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11c82f2877SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13c82f2877SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14c82f2877SAndrew Rist  * software distributed under the License is distributed on an
15c82f2877SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16c82f2877SAndrew Rist  * KIND, either express or implied.  See the License for the
17c82f2877SAndrew Rist  * specific language governing permissions and limitations
18c82f2877SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20c82f2877SAndrew Rist  *************************************************************/
21c82f2877SAndrew Rist 
22c82f2877SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "unx/saldisp.hxx"
28cdf0e10cSrcweir #include "unx/saldata.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <unistd.h>
31cdf0e10cSrcweir #include <stdio.h>
32cdf0e10cSrcweir #include <string.h>
33cdf0e10cSrcweir #include <sys/time.h>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include "tools/prex.h"
36cdf0e10cSrcweir #include <X11/Xatom.h>
37cdf0e10cSrcweir #include <X11/keysym.h>
38cdf0e10cSrcweir #include <X11/Xutil.h>
39cdf0e10cSrcweir #include "tools/postx.h"
40cdf0e10cSrcweir #if defined(LINUX) || defined(NETBSD) || defined (FREEBSD)
41cdf0e10cSrcweir #include <sys/poll.h>
42cdf0e10cSrcweir #else
43cdf0e10cSrcweir #include <poll.h>
44cdf0e10cSrcweir #endif
45cdf0e10cSrcweir #include <sal/alloca.h>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include <X11_selection.hxx>
48cdf0e10cSrcweir #include <X11_clipboard.hxx>
49cdf0e10cSrcweir #include <X11_transferable.hxx>
50cdf0e10cSrcweir #include <X11_dndcontext.hxx>
51cdf0e10cSrcweir #include <bmp.hxx>
52cdf0e10cSrcweir 
53cdf0e10cSrcweir #include "vcl/svapp.hxx"
54cdf0e10cSrcweir 
55cdf0e10cSrcweir // pointer bitmaps
56cdf0e10cSrcweir #include <copydata_curs.h>
57cdf0e10cSrcweir #include <copydata_mask.h>
58cdf0e10cSrcweir #include <movedata_curs.h>
59cdf0e10cSrcweir #include <movedata_mask.h>
60cdf0e10cSrcweir #include <linkdata_curs.h>
61cdf0e10cSrcweir #include <linkdata_mask.h>
62cdf0e10cSrcweir #include <nodrop_curs.h>
63cdf0e10cSrcweir #include <nodrop_mask.h>
64cdf0e10cSrcweir #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
65cdf0e10cSrcweir #include <com/sun/star/awt/MouseEvent.hpp>
66cdf0e10cSrcweir #include <com/sun/star/awt/MouseButton.hpp>
67cdf0e10cSrcweir #include <rtl/tencinfo.h>
68cdf0e10cSrcweir #include <osl/process.h>
69cdf0e10cSrcweir 
70cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
71cdf0e10cSrcweir #include <vos/mutex.hxx>
72cdf0e10cSrcweir 
73cdf0e10cSrcweir #define DRAG_EVENT_MASK	ButtonPressMask			|\
74cdf0e10cSrcweir 						  	ButtonReleaseMask		|\
75cdf0e10cSrcweir 						  	PointerMotionMask		|\
76cdf0e10cSrcweir 						  	EnterWindowMask			|\
77cdf0e10cSrcweir 						  	LeaveWindowMask
78cdf0e10cSrcweir 
79cdf0e10cSrcweir namespace {
80cdf0e10cSrcweir 
81cdf0e10cSrcweir namespace css = com::sun::star;
82cdf0e10cSrcweir 
83cdf0e10cSrcweir }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir using namespace com::sun::star::datatransfer;
86cdf0e10cSrcweir using namespace com::sun::star::datatransfer::dnd;
87cdf0e10cSrcweir using namespace com::sun::star::lang;
88cdf0e10cSrcweir using namespace com::sun::star::awt;
89cdf0e10cSrcweir using namespace com::sun::star::uno;
90cdf0e10cSrcweir using namespace com::sun::star::frame;
91cdf0e10cSrcweir using namespace cppu;
92cdf0e10cSrcweir using namespace osl;
93cdf0e10cSrcweir using namespace rtl;
94cdf0e10cSrcweir 
95cdf0e10cSrcweir using namespace x11;
96cdf0e10cSrcweir 
97cdf0e10cSrcweir // stubs to satisfy solaris compiler's rather rigid linking warning
98cdf0e10cSrcweir extern "C"
99cdf0e10cSrcweir {
call_SelectionManager_run(void * pMgr)100cdf0e10cSrcweir     static void call_SelectionManager_run( void * pMgr )
101cdf0e10cSrcweir     {
102cdf0e10cSrcweir         SelectionManager::run( pMgr );
103cdf0e10cSrcweir     }
104cdf0e10cSrcweir 
call_SelectionManager_runDragExecute(void * pMgr)105cdf0e10cSrcweir     static void call_SelectionManager_runDragExecute( void * pMgr )
106cdf0e10cSrcweir     {
107cdf0e10cSrcweir         SelectionManager::runDragExecute( pMgr );
108cdf0e10cSrcweir     }
109cdf0e10cSrcweir }
110cdf0e10cSrcweir 
111cdf0e10cSrcweir 
112cdf0e10cSrcweir static const long nXdndProtocolRevision = 5;
113cdf0e10cSrcweir 
114cdf0e10cSrcweir // mapping between mime types (or what the office thinks of mime types)
115cdf0e10cSrcweir // and X convention types
116cdf0e10cSrcweir struct NativeTypeEntry
117cdf0e10cSrcweir {
118cdf0e10cSrcweir 	Atom			nAtom;
119cdf0e10cSrcweir 	const char*		pType;				// Mime encoding on our side
120cdf0e10cSrcweir 	const char*		pNativeType;		// string corresponding to nAtom for the case of nAtom being uninitialized
121cdf0e10cSrcweir 	int				nFormat;			// the corresponding format
122cdf0e10cSrcweir };
123cdf0e10cSrcweir 
124cdf0e10cSrcweir // the convention for Xdnd is mime types as specified by the corresponding
125cdf0e10cSrcweir // RFC's with the addition that text/plain without charset tag contains iso8859-1
126cdf0e10cSrcweir // sadly some applications (e.g. gtk) do not honor the mimetype only rule,
127cdf0e10cSrcweir // so for compatibility add UTF8_STRING
128cdf0e10cSrcweir static NativeTypeEntry aXdndConversionTab[] =
129cdf0e10cSrcweir {
130cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-1", "text/plain", 8 },
131cdf0e10cSrcweir     { 0, "text/plain;charset=utf-8", "UTF8_STRING", 8 }
132cdf0e10cSrcweir };
133cdf0e10cSrcweir 
134cdf0e10cSrcweir // for clipboard and primary selections there is only a convention for text
135cdf0e10cSrcweir // that the encoding name of the text is taken as type in all capitalized letters
136cdf0e10cSrcweir static NativeTypeEntry aNativeConversionTab[] =
137cdf0e10cSrcweir {
138cdf0e10cSrcweir 	{ 0, "text/plain;charset=utf-16", "ISO10646-1", 16 },
139cdf0e10cSrcweir 	{ 0, "text/plain;charset=utf-8", "UTF8_STRING", 8 },
140cdf0e10cSrcweir 	{ 0, "text/plain;charset=utf-8", "UTF-8", 8 },
141cdf0e10cSrcweir 	{ 0, "text/plain;charset=utf-8", "text/plain;charset=UTF-8", 8 },
142cdf0e10cSrcweir 	// ISO encodings
143cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-2", "ISO8859-2", 8 },
144cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-3", "ISO8859-3", 8 },
145cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-4", "ISO8859-4", 8 },
146cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-5", "ISO8859-5", 8 },
147cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-6", "ISO8859-6", 8 },
148cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-7", "ISO8859-7", 8 },
149cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-8", "ISO8859-8", 8 },
150cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-9", "ISO8859-9", 8 },
151cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-10", "ISO8859-10", 8 },
152cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-13", "ISO8859-13", 8 },
153cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-14", "ISO8859-14", 8 },
154cdf0e10cSrcweir 	{ 0, "text/plain;charset=iso8859-15", "ISO8859-15", 8 },
155cdf0e10cSrcweir 	// asian encodings
156cdf0e10cSrcweir 	{ 0, "text/plain;charset=jisx0201.1976-0", "JISX0201.1976-0", 8 },
157cdf0e10cSrcweir 	{ 0, "text/plain;charset=jisx0208.1983-0", "JISX0208.1983-0", 8 },
158cdf0e10cSrcweir 	{ 0, "text/plain;charset=jisx0208.1990-0", "JISX0208.1990-0", 8 },
159cdf0e10cSrcweir 	{ 0, "text/plain;charset=jisx0212.1990-0", "JISX0212.1990-0", 8 },
160cdf0e10cSrcweir 	{ 0, "text/plain;charset=gb2312.1980-0", "GB2312.1980-0", 8 },
161cdf0e10cSrcweir 	{ 0, "text/plain;charset=ksc5601.1992-0", "KSC5601.1992-0", 8 },
162cdf0e10cSrcweir 	// eastern european encodings
163cdf0e10cSrcweir 	{ 0, "text/plain;charset=koi8-r", "KOI8-R", 8 },
164cdf0e10cSrcweir 	{ 0, "text/plain;charset=koi8-u", "KOI8-U", 8 },
165cdf0e10cSrcweir 	// String (== iso8859-1)
166cdf0e10cSrcweir 	{ XA_STRING, "text/plain;charset=iso8859-1", "STRING", 8 },
167cdf0e10cSrcweir     // special for compound text
168cdf0e10cSrcweir     { 0, "text/plain;charset=compound_text", "COMPOUND_TEXT", 8 },
169cdf0e10cSrcweir 
170cdf0e10cSrcweir     // PIXMAP
171cdf0e10cSrcweir     { XA_PIXMAP, "image/bmp", "PIXMAP", 32 }
172cdf0e10cSrcweir };
173cdf0e10cSrcweir 
getTextPlainEncoding(const OUString & rMimeType)174cdf0e10cSrcweir rtl_TextEncoding x11::getTextPlainEncoding( const OUString& rMimeType )
175cdf0e10cSrcweir {
176cdf0e10cSrcweir 	rtl_TextEncoding aEncoding = RTL_TEXTENCODING_DONTKNOW;
177cdf0e10cSrcweir 	OUString aMimeType( rMimeType.toAsciiLowerCase() );
178cdf0e10cSrcweir     sal_Int32 nIndex = 0;
179cdf0e10cSrcweir 	if( aMimeType.getToken( 0, ';', nIndex ).equalsAsciiL( "text/plain" , 10 ) )
180cdf0e10cSrcweir 	{
181cdf0e10cSrcweir 		if( aMimeType.getLength() == 10 ) // only "text/plain"
182cdf0e10cSrcweir 			aEncoding = RTL_TEXTENCODING_ISO_8859_1;
183cdf0e10cSrcweir 		else
184cdf0e10cSrcweir 		{
185cdf0e10cSrcweir             while( nIndex != -1 )
186cdf0e10cSrcweir 			{
187cdf0e10cSrcweir 				OUString aToken = aMimeType.getToken( 0, ';', nIndex );
188cdf0e10cSrcweir                 sal_Int32 nPos = 0;
189cdf0e10cSrcweir 				if( aToken.getToken( 0, '=', nPos ).equalsAsciiL( "charset", 7 ) )
190cdf0e10cSrcweir 				{
191cdf0e10cSrcweir 					OString aEncToken = OUStringToOString( aToken.getToken( 0, '=', nPos ), RTL_TEXTENCODING_ISO_8859_1 );
192cdf0e10cSrcweir 					aEncoding = rtl_getTextEncodingFromUnixCharset( aEncToken.getStr() );
193cdf0e10cSrcweir 					if( aEncoding == RTL_TEXTENCODING_DONTKNOW )
194cdf0e10cSrcweir 					{
195cdf0e10cSrcweir 						if( aEncToken.equalsIgnoreAsciiCase( "utf-8" ) )
196cdf0e10cSrcweir 							aEncoding = RTL_TEXTENCODING_UTF8;
197cdf0e10cSrcweir 					}
198cdf0e10cSrcweir 					if( aEncoding != RTL_TEXTENCODING_DONTKNOW )
199cdf0e10cSrcweir 						break;
200cdf0e10cSrcweir 				}
201cdf0e10cSrcweir 			}
202cdf0e10cSrcweir 		}
203cdf0e10cSrcweir 	}
204cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
205cdf0e10cSrcweir     if( aEncoding == RTL_TEXTENCODING_DONTKNOW )
206cdf0e10cSrcweir         fprintf( stderr, "getTextPlainEncoding( %s ) failed\n", OUStringToOString( rMimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
207cdf0e10cSrcweir #endif
208cdf0e10cSrcweir 	return aEncoding;
209cdf0e10cSrcweir }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir // ------------------------------------------------------------------------
212cdf0e10cSrcweir 
getInstances()213cdf0e10cSrcweir ::std::hash_map< OUString, SelectionManager*, OUStringHash >& SelectionManager::getInstances()
214cdf0e10cSrcweir {
215cdf0e10cSrcweir     static ::std::hash_map< OUString, SelectionManager*, OUStringHash > aInstances;
216cdf0e10cSrcweir     return aInstances;
217cdf0e10cSrcweir }
218cdf0e10cSrcweir 
219cdf0e10cSrcweir // ------------------------------------------------------------------------
220cdf0e10cSrcweir 
SelectionManager()221cdf0e10cSrcweir SelectionManager::SelectionManager() :
222cdf0e10cSrcweir         m_nIncrementalThreshold( 15*1024 ),
223cdf0e10cSrcweir         m_pDisplay( NULL ),
224cdf0e10cSrcweir         m_aThread( NULL ),
225cdf0e10cSrcweir         m_aDragExecuteThread( NULL ),
226cdf0e10cSrcweir         m_aWindow( None ),
227cdf0e10cSrcweir         m_nSelectionTimeout( 0 ),
228cdf0e10cSrcweir         m_nSelectionTimestamp( CurrentTime ),
229cdf0e10cSrcweir         m_bDropEnterSent( true ),
230cdf0e10cSrcweir         m_aCurrentDropWindow( None ),
231cdf0e10cSrcweir         m_nDropTime( None ),
232cdf0e10cSrcweir         m_nLastDropAction( 0 ),
233cdf0e10cSrcweir         m_nLastX( 0 ),
234cdf0e10cSrcweir         m_nLastY( 0 ),
235cdf0e10cSrcweir         m_nDropTimestamp( 0 ),
236cdf0e10cSrcweir         m_bDropWaitingForCompletion( false ),
237cdf0e10cSrcweir         m_aDropWindow( None ),
238cdf0e10cSrcweir         m_aDropProxy( None ),
239cdf0e10cSrcweir         m_aDragSourceWindow( None ),
240cdf0e10cSrcweir         m_nLastDragX( 0 ),
241cdf0e10cSrcweir         m_nLastDragY( 0 ),
242cdf0e10cSrcweir         m_nNoPosX( 0 ),
243cdf0e10cSrcweir         m_nNoPosY( 0 ),
244cdf0e10cSrcweir         m_nNoPosWidth( 0 ),
245cdf0e10cSrcweir         m_nNoPosHeight( 0 ),
246cdf0e10cSrcweir         m_nDragButton( 0 ),
247cdf0e10cSrcweir         m_nUserDragAction( 0 ),
248cdf0e10cSrcweir         m_nTargetAcceptAction( 0 ),
249cdf0e10cSrcweir         m_nSourceActions( 0 ),
250cdf0e10cSrcweir         m_bLastDropAccepted( false ),
251cdf0e10cSrcweir         m_bDropSuccess( false ),
252cdf0e10cSrcweir         m_bDropSent( false ),
253cdf0e10cSrcweir         m_bWaitingForPrimaryConversion( false ),
254cdf0e10cSrcweir         m_nDragTimestamp( None ),
255cdf0e10cSrcweir         m_aMoveCursor( None ),
256cdf0e10cSrcweir         m_aCopyCursor( None ),
257cdf0e10cSrcweir         m_aLinkCursor( None ),
258cdf0e10cSrcweir         m_aNoneCursor( None ),
259cdf0e10cSrcweir         m_aCurrentCursor( None ),
260cdf0e10cSrcweir         m_nCurrentProtocolVersion( nXdndProtocolRevision ),
261cdf0e10cSrcweir         m_nCLIPBOARDAtom( None ),
262cdf0e10cSrcweir         m_nTARGETSAtom( None ),
263cdf0e10cSrcweir         m_nTIMESTAMPAtom( None ),
264cdf0e10cSrcweir         m_nTEXTAtom( None ),
265cdf0e10cSrcweir         m_nINCRAtom( None ),
266cdf0e10cSrcweir         m_nCOMPOUNDAtom( None ),
267cdf0e10cSrcweir         m_nMULTIPLEAtom( None ),
268cdf0e10cSrcweir         m_nUTF16Atom( None ),
269cdf0e10cSrcweir         m_nImageBmpAtom( None ),
270cdf0e10cSrcweir         m_nXdndAware( None ),
271cdf0e10cSrcweir         m_nXdndEnter( None ),
272cdf0e10cSrcweir         m_nXdndLeave( None ),
273cdf0e10cSrcweir         m_nXdndPosition( None ),
274cdf0e10cSrcweir         m_nXdndStatus( None ),
275cdf0e10cSrcweir         m_nXdndDrop( None ),
276cdf0e10cSrcweir         m_nXdndFinished( None ),
277cdf0e10cSrcweir         m_nXdndSelection( None ),
278cdf0e10cSrcweir         m_nXdndTypeList( None ),
279cdf0e10cSrcweir         m_nXdndProxy( None ),
280cdf0e10cSrcweir         m_nXdndActionCopy( None ),
281cdf0e10cSrcweir         m_nXdndActionMove( None ),
282cdf0e10cSrcweir         m_nXdndActionLink( None ),
283cdf0e10cSrcweir         m_nXdndActionAsk( None ),
284cdf0e10cSrcweir         m_nXdndActionPrivate( None ),
285cdf0e10cSrcweir         m_bShutDown( false )
286cdf0e10cSrcweir {
287cdf0e10cSrcweir 	m_aDropEnterEvent.data.l[0]	= None;
288cdf0e10cSrcweir     m_aDragRunning.reset();
289cdf0e10cSrcweir }
290cdf0e10cSrcweir 
createCursor(const char * pPointerData,const char * pMaskData,int width,int height,int hotX,int hotY)291cdf0e10cSrcweir XLIB_Cursor SelectionManager::createCursor( const char* pPointerData, const char* pMaskData, int width, int height, int hotX, int hotY )
292cdf0e10cSrcweir {
293cdf0e10cSrcweir 	Pixmap aPointer;
294cdf0e10cSrcweir 	Pixmap aMask;
295cdf0e10cSrcweir 	XColor aBlack, aWhite;
296cdf0e10cSrcweir 
297cdf0e10cSrcweir 	aBlack.pixel = BlackPixel( m_pDisplay, 0 );
298cdf0e10cSrcweir 	aBlack.red = aBlack.green = aBlack.blue = 0;
299cdf0e10cSrcweir 	aBlack.flags = DoRed | DoGreen | DoBlue;
300cdf0e10cSrcweir 
301cdf0e10cSrcweir 	aWhite.pixel = WhitePixel( m_pDisplay, 0 );
302cdf0e10cSrcweir 	aWhite.red = aWhite.green = aWhite.blue = 0xffff;
303cdf0e10cSrcweir 	aWhite.flags = DoRed | DoGreen | DoBlue;
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 	aPointer =
306cdf0e10cSrcweir 		XCreateBitmapFromData( m_pDisplay,
307cdf0e10cSrcweir 							   m_aWindow,
308cdf0e10cSrcweir 							   pPointerData,
309cdf0e10cSrcweir 							   width,
310cdf0e10cSrcweir 							   height );
311cdf0e10cSrcweir 	aMask
312cdf0e10cSrcweir 		= XCreateBitmapFromData( m_pDisplay,
313cdf0e10cSrcweir 								 m_aWindow,
314cdf0e10cSrcweir 								 pMaskData,
315cdf0e10cSrcweir 								 width,
316cdf0e10cSrcweir 								 height );
317cdf0e10cSrcweir 	XLIB_Cursor aCursor =
318cdf0e10cSrcweir 		XCreatePixmapCursor( m_pDisplay, aPointer, aMask,
319cdf0e10cSrcweir 							 &aBlack, &aWhite,
320cdf0e10cSrcweir 							 hotX,
321cdf0e10cSrcweir 							 hotY );
322cdf0e10cSrcweir 	XFreePixmap( m_pDisplay, aPointer );
323cdf0e10cSrcweir 	XFreePixmap( m_pDisplay, aMask );
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 	return aCursor;
326cdf0e10cSrcweir }
327cdf0e10cSrcweir 
initialize(const Sequence<Any> & arguments)328cdf0e10cSrcweir void SelectionManager::initialize( const Sequence< Any >& arguments ) throw (::com::sun::star::uno::Exception)
329cdf0e10cSrcweir {
330cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 	if( ! m_xDisplayConnection.is() )
333cdf0e10cSrcweir 	{
334cdf0e10cSrcweir 		/*
335cdf0e10cSrcweir 		 *	first argument must be a ::com::sun::star::awt::XDisplayConnection
336cdf0e10cSrcweir 		 *	from this we will get the XEvents of the vcl event loop by
337cdf0e10cSrcweir 		 *	registering us as XEventHandler on it.
338cdf0e10cSrcweir 		 *
339cdf0e10cSrcweir 		 *	implementor's note:
340cdf0e10cSrcweir          *  FIXME:
341cdf0e10cSrcweir          *  finally the clipboard and XDND service is back in the module it belongs
342cdf0e10cSrcweir          *  now cleanup and sharing of resources with the normal vcl event loop
343cdf0e10cSrcweir          *  needs to be added. The display used whould be that of the normal event loop
344cdf0e10cSrcweir          *  and synchronization should be done via the SolarMutex.
345cdf0e10cSrcweir 		 */
346cdf0e10cSrcweir 		if( arguments.getLength() > 0 )
347cdf0e10cSrcweir 			arguments.getConstArray()[0] >>= m_xDisplayConnection;
348cdf0e10cSrcweir 		if( ! m_xDisplayConnection.is() )
349cdf0e10cSrcweir 		{
350cdf0e10cSrcweir #if 0
351cdf0e10cSrcweir 			// for the time being try to live without XDisplayConnection
352cdf0e10cSrcweir 			// for the sake of clipboard service
353cdf0e10cSrcweir 			// clipboard service should be initialized with a XDisplayConnection
354cdf0e10cSrcweir 			// in the future
355cdf0e10cSrcweir 			Exception aExc;
356cdf0e10cSrcweir 			aExc.Message = OUString::createFromAscii( "initialize me with a valid XDisplayConnection" );
357cdf0e10cSrcweir 			aExc.Context = static_cast< OWeakObject* >(this);
358cdf0e10cSrcweir 			throw aExc;
359cdf0e10cSrcweir #endif
360cdf0e10cSrcweir 		}
361cdf0e10cSrcweir 		else
362cdf0e10cSrcweir 			m_xDisplayConnection->addEventHandler( Any(), this, ~0 );
363cdf0e10cSrcweir 	}
364cdf0e10cSrcweir 
365cdf0e10cSrcweir     if( !m_xBitmapConverter.is() )
366cdf0e10cSrcweir     {
367cdf0e10cSrcweir         if( arguments.getLength() > 2 )
368cdf0e10cSrcweir             arguments.getConstArray()[2] >>= m_xBitmapConverter;
369cdf0e10cSrcweir     }
370cdf0e10cSrcweir 
371cdf0e10cSrcweir     OUString aParam;
372cdf0e10cSrcweir 	if( ! m_pDisplay )
373cdf0e10cSrcweir 	{
374cdf0e10cSrcweir 		OUString aUDisplay;
375cdf0e10cSrcweir 		if( m_xDisplayConnection.is() )
376cdf0e10cSrcweir 		{
377cdf0e10cSrcweir 			Any aIdentifier;
378cdf0e10cSrcweir 			aIdentifier = m_xDisplayConnection->getIdentifier();
379cdf0e10cSrcweir 			aIdentifier >>= aUDisplay;
380cdf0e10cSrcweir 		}
381cdf0e10cSrcweir 
382cdf0e10cSrcweir 		OString aDisplayName( OUStringToOString( aUDisplay, RTL_TEXTENCODING_ISO_8859_1 ) );
383cdf0e10cSrcweir 
384cdf0e10cSrcweir 		m_pDisplay = XOpenDisplay( aDisplayName.getLength() ? aDisplayName.getStr() : NULL );
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 		if( m_pDisplay )
387cdf0e10cSrcweir 		{
388cdf0e10cSrcweir #ifdef SYNCHRONIZE
389cdf0e10cSrcweir 			XSynchronize( m_pDisplay, True );
390cdf0e10cSrcweir #endif
391cdf0e10cSrcweir 			// clipboard selection
392cdf0e10cSrcweir 			m_nCLIPBOARDAtom	= getAtom( OUString::createFromAscii( "CLIPBOARD" ) );
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 			// special targets
395cdf0e10cSrcweir 			m_nTARGETSAtom		= getAtom( OUString::createFromAscii( "TARGETS" ) );
396cdf0e10cSrcweir             m_nTIMESTAMPAtom    = getAtom( OUString::createFromAscii( "TIMESTAMP" ) );
397cdf0e10cSrcweir 			m_nTEXTAtom			= getAtom( OUString::createFromAscii( "TEXT" ) );
398cdf0e10cSrcweir 			m_nINCRAtom			= getAtom( OUString::createFromAscii( "INCR" ) );
399cdf0e10cSrcweir             m_nCOMPOUNDAtom		= getAtom( OUString::createFromAscii( "COMPOUND_TEXT" ) );
400cdf0e10cSrcweir             m_nMULTIPLEAtom		= getAtom( OUString::createFromAscii( "MULTIPLE" ) );
401cdf0e10cSrcweir             m_nUTF16Atom		= getAtom( OUString::createFromAscii( "ISO10646-1" ) );
402cdf0e10cSrcweir //            m_nUTF16Atom		= getAtom( OUString::createFromAscii( "text/plain;charset=ISO-10646-UCS-2" ) );
403cdf0e10cSrcweir             m_nImageBmpAtom     = getAtom( OUString::createFromAscii( "image/bmp" ) );
404cdf0e10cSrcweir 
405cdf0e10cSrcweir 			// Atoms for Xdnd protocol
406cdf0e10cSrcweir 			m_nXdndAware		= getAtom( OUString::createFromAscii( "XdndAware" ) );
407cdf0e10cSrcweir 			m_nXdndEnter		= getAtom( OUString::createFromAscii( "XdndEnter" ) );
408cdf0e10cSrcweir 			m_nXdndLeave		= getAtom( OUString::createFromAscii( "XdndLeave" ) );
409cdf0e10cSrcweir 			m_nXdndPosition		= getAtom( OUString::createFromAscii( "XdndPosition" ) );
410cdf0e10cSrcweir 			m_nXdndStatus		= getAtom( OUString::createFromAscii( "XdndStatus" ) );
411cdf0e10cSrcweir 			m_nXdndDrop			= getAtom( OUString::createFromAscii( "XdndDrop" ) );
412cdf0e10cSrcweir 			m_nXdndFinished		= getAtom( OUString::createFromAscii( "XdndFinished" ) );
413cdf0e10cSrcweir 			m_nXdndSelection	= getAtom( OUString::createFromAscii( "XdndSelection" ) );
414cdf0e10cSrcweir 			m_nXdndTypeList		= getAtom( OUString::createFromAscii( "XdndTypeList" ) );
415cdf0e10cSrcweir 			m_nXdndProxy		= getAtom( OUString::createFromAscii( "XdndProxy" ) );
416cdf0e10cSrcweir 			m_nXdndActionCopy	= getAtom( OUString::createFromAscii( "XdndActionCopy" ) );
417cdf0e10cSrcweir 			m_nXdndActionMove	= getAtom( OUString::createFromAscii( "XdndActionMove" ) );
418cdf0e10cSrcweir 			m_nXdndActionLink	= getAtom( OUString::createFromAscii( "XdndActionLink" ) );
419cdf0e10cSrcweir 			m_nXdndActionAsk	= getAtom( OUString::createFromAscii( "XdndActionAsk" ) );
420cdf0e10cSrcweir 			m_nXdndActionPrivate= getAtom( OUString::createFromAscii( "XdndActionPrivate" ) );
421cdf0e10cSrcweir 
422cdf0e10cSrcweir 			// initialize map with member none
423cdf0e10cSrcweir 			m_aAtomToString[ 0 ]= OUString::createFromAscii( "None" );
424cdf0e10cSrcweir             m_aAtomToString[ XA_PRIMARY ] = OUString::createFromAscii( "PRIMARY" );
425cdf0e10cSrcweir 
426cdf0e10cSrcweir 			// create a (invisible) message window
427cdf0e10cSrcweir 			m_aWindow = XCreateSimpleWindow( m_pDisplay, DefaultRootWindow( m_pDisplay ),
428cdf0e10cSrcweir 											 10, 10, 10, 10, 0, 0, 1 );
429cdf0e10cSrcweir 
430cdf0e10cSrcweir             // initialize threshold for incremetal transfers
431cdf0e10cSrcweir             // ICCCM says it should be smaller that the max request size
432cdf0e10cSrcweir             // which in turn is guaranteed to be at least 16k bytes
433cdf0e10cSrcweir             m_nIncrementalThreshold = XMaxRequestSize( m_pDisplay ) - 1024;
434cdf0e10cSrcweir 
435cdf0e10cSrcweir 			if( m_aWindow )
436cdf0e10cSrcweir 			{
43730c1b1efSHerbert Dürr #define	createCursorFromXPM(name) createCursor((const char*)name##curs##_bits, (const char*)name##mask##_bits, name##curs_width, name##curs_height, name##curs_x_hot, name##curs_y_hot );
438cdf0e10cSrcweir 				// initialize default cursors
43930c1b1efSHerbert Dürr 				m_aMoveCursor = createCursorFromXPM( movedata_);
44030c1b1efSHerbert Dürr 				m_aCopyCursor = createCursorFromXPM( copydata_);
44130c1b1efSHerbert Dürr 				m_aLinkCursor = createCursorFromXPM( linkdata_);
44230c1b1efSHerbert Dürr 				m_aNoneCursor = createCursorFromXPM( nodrop_);
443cdf0e10cSrcweir 
444cdf0e10cSrcweir 				// just interested in SelectionClear/Notify/Request and PropertyChange
445cdf0e10cSrcweir 				XSelectInput( m_pDisplay, m_aWindow, PropertyChangeMask );
446cdf0e10cSrcweir 				// create the transferable for Drag operations
447cdf0e10cSrcweir 				m_xDropTransferable = new X11Transferable( *this, static_cast< OWeakObject* >(this), m_nXdndSelection );
448cdf0e10cSrcweir 				registerHandler( m_nXdndSelection, *this );
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 				m_aThread = osl_createSuspendedThread( call_SelectionManager_run, this );
451cdf0e10cSrcweir     			if( m_aThread )
452cdf0e10cSrcweir         			osl_resumeThread( m_aThread );
453cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
454cdf0e10cSrcweir 				else
455cdf0e10cSrcweir 					fprintf( stderr, "SelectionManager::initialize: creation of dispatch thread failed !\n" );
456cdf0e10cSrcweir #endif
457cdf0e10cSrcweir 			}
458cdf0e10cSrcweir 		}
459cdf0e10cSrcweir 	}
460cdf0e10cSrcweir }
461cdf0e10cSrcweir 
462cdf0e10cSrcweir // ------------------------------------------------------------------------
463cdf0e10cSrcweir 
~SelectionManager()464cdf0e10cSrcweir SelectionManager::~SelectionManager()
465cdf0e10cSrcweir {
466cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
467cdf0e10cSrcweir 	fprintf( stderr, "SelectionManager::~SelectionManager (%s)\n", m_pDisplay ? DisplayString(m_pDisplay) : "no display" );
468cdf0e10cSrcweir #endif
469cdf0e10cSrcweir 	{
470cdf0e10cSrcweir 		MutexGuard aGuard( *Mutex::getGlobalMutex() );
471cdf0e10cSrcweir 
472cdf0e10cSrcweir 		::std::hash_map< OUString, SelectionManager*, OUStringHash >::iterator it;
473cdf0e10cSrcweir 		for( it = getInstances().begin(); it != getInstances().end(); ++it )
474cdf0e10cSrcweir 			if( it->second == this )
475cdf0e10cSrcweir 			{
476cdf0e10cSrcweir 				getInstances().erase( it );
477cdf0e10cSrcweir 				break;
478cdf0e10cSrcweir 			}
479cdf0e10cSrcweir 	}
480cdf0e10cSrcweir 
481cdf0e10cSrcweir 	if( m_aThread )
482cdf0e10cSrcweir 	{
483cdf0e10cSrcweir 		osl_terminateThread( m_aThread );
484cdf0e10cSrcweir 		osl_joinWithThread( m_aThread );
485cdf0e10cSrcweir 		osl_destroyThread( m_aThread );
486cdf0e10cSrcweir 	}
487cdf0e10cSrcweir 
488cdf0e10cSrcweir 	if( m_aDragExecuteThread )
489cdf0e10cSrcweir 	{
490cdf0e10cSrcweir 		osl_terminateThread( m_aDragExecuteThread );
491cdf0e10cSrcweir 		osl_joinWithThread( m_aDragExecuteThread );
492cdf0e10cSrcweir         m_aDragExecuteThread = NULL;
493cdf0e10cSrcweir 		// thread handle is freed in dragDoDispatch()
494cdf0e10cSrcweir 	}
495cdf0e10cSrcweir 
496cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
497cdf0e10cSrcweir 
498cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
499cdf0e10cSrcweir 	fprintf( stderr, "shutting down SelectionManager\n" );
500cdf0e10cSrcweir #endif
501cdf0e10cSrcweir 
502cdf0e10cSrcweir     if( m_xDisplayConnection.is() )
503cdf0e10cSrcweir     {
504cdf0e10cSrcweir         m_xDisplayConnection->removeEventHandler( Any(), this );
505cdf0e10cSrcweir         m_xDisplayConnection.clear();
506cdf0e10cSrcweir     }
507cdf0e10cSrcweir 
508cdf0e10cSrcweir 	if( m_pDisplay )
509cdf0e10cSrcweir 	{
510cdf0e10cSrcweir 		deregisterHandler( m_nXdndSelection );
511cdf0e10cSrcweir 		// destroy message window
512cdf0e10cSrcweir 		if( m_aWindow )
513cdf0e10cSrcweir 			XDestroyWindow( m_pDisplay, m_aWindow );
514cdf0e10cSrcweir 		// release cursors
515cdf0e10cSrcweir 		if (m_aMoveCursor != None)
516cdf0e10cSrcweir 			XFreeCursor(m_pDisplay, m_aMoveCursor);
517cdf0e10cSrcweir 		if (m_aCopyCursor != None)
518cdf0e10cSrcweir 			XFreeCursor(m_pDisplay, m_aCopyCursor);
519cdf0e10cSrcweir 		if (m_aLinkCursor != None)
520cdf0e10cSrcweir 			XFreeCursor(m_pDisplay, m_aLinkCursor);
521cdf0e10cSrcweir 		if (m_aNoneCursor != None)
522cdf0e10cSrcweir 			XFreeCursor(m_pDisplay, m_aNoneCursor);
523cdf0e10cSrcweir 
524cdf0e10cSrcweir         // paranoia setting, the drag thread should have
525cdf0e10cSrcweir         // done that already
526cdf0e10cSrcweir 		XUngrabPointer( m_pDisplay, CurrentTime );
527cdf0e10cSrcweir 		XUngrabKeyboard( m_pDisplay, CurrentTime );
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 		XCloseDisplay( m_pDisplay );
530cdf0e10cSrcweir 	}
531cdf0e10cSrcweir }
532cdf0e10cSrcweir 
533cdf0e10cSrcweir // ------------------------------------------------------------------------
534cdf0e10cSrcweir 
getAdaptor(Atom selection)535cdf0e10cSrcweir SelectionAdaptor* SelectionManager::getAdaptor( Atom selection )
536cdf0e10cSrcweir {
537cdf0e10cSrcweir 	::std::hash_map< Atom, Selection* >::iterator it =
538cdf0e10cSrcweir 		  m_aSelections.find( selection );
539cdf0e10cSrcweir 	return it != m_aSelections.end() ? it->second->m_pAdaptor : NULL;
540cdf0e10cSrcweir }
541cdf0e10cSrcweir 
542cdf0e10cSrcweir // ------------------------------------------------------------------------
543cdf0e10cSrcweir 
convertFromCompound(const char * pText,int nLen)544cdf0e10cSrcweir OUString SelectionManager::convertFromCompound( const char* pText, int nLen )
545cdf0e10cSrcweir {
546cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
547cdf0e10cSrcweir     OUString aRet;
548cdf0e10cSrcweir     if( nLen < 0 )
549cdf0e10cSrcweir         nLen = strlen( pText );
550cdf0e10cSrcweir 
551cdf0e10cSrcweir     char** pTextList = NULL;
552cdf0e10cSrcweir     int nTexts = 0;
553cdf0e10cSrcweir 
554cdf0e10cSrcweir     XTextProperty aProp;
555cdf0e10cSrcweir     aProp.value		= (unsigned char*)pText;
556cdf0e10cSrcweir     aProp.encoding	= m_nCOMPOUNDAtom;
557cdf0e10cSrcweir     aProp.format	= 8;
558cdf0e10cSrcweir     aProp.nitems	= nLen;
559cdf0e10cSrcweir     XmbTextPropertyToTextList( m_pDisplay,
560cdf0e10cSrcweir                                &aProp,
561cdf0e10cSrcweir                                &pTextList,
562cdf0e10cSrcweir                                &nTexts );
563cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
564cdf0e10cSrcweir     for( int i = 0; i < nTexts; i++ )
565cdf0e10cSrcweir         aRet += OStringToOUString( pTextList[i], aEncoding );
566cdf0e10cSrcweir 
567cdf0e10cSrcweir     if( pTextList )
568cdf0e10cSrcweir         XFreeStringList( pTextList );
569cdf0e10cSrcweir 
570cdf0e10cSrcweir     return aRet;
571cdf0e10cSrcweir }
572cdf0e10cSrcweir 
573cdf0e10cSrcweir // ------------------------------------------------------------------------
574cdf0e10cSrcweir 
convertToCompound(const OUString & rText)575cdf0e10cSrcweir OString SelectionManager::convertToCompound( const OUString& rText )
576cdf0e10cSrcweir {
577cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
578cdf0e10cSrcweir     XTextProperty aProp;
579cdf0e10cSrcweir     aProp.value = NULL;
580cdf0e10cSrcweir     aProp.encoding = XA_STRING;
581cdf0e10cSrcweir     aProp.format = 8;
582cdf0e10cSrcweir     aProp.nitems = 0;
583cdf0e10cSrcweir 
584cdf0e10cSrcweir     OString aRet( rText.getStr(), rText.getLength(), osl_getThreadTextEncoding() );
585cdf0e10cSrcweir     char* pT = const_cast<char*>(aRet.getStr());
586cdf0e10cSrcweir 
587cdf0e10cSrcweir     XmbTextListToTextProperty( m_pDisplay,
588cdf0e10cSrcweir                                &pT,
589cdf0e10cSrcweir                                1,
590cdf0e10cSrcweir                                XCompoundTextStyle,
591cdf0e10cSrcweir                                &aProp );
592cdf0e10cSrcweir     if( aProp.value )
593cdf0e10cSrcweir     {
594cdf0e10cSrcweir         aRet = (char*)aProp.value;
595cdf0e10cSrcweir         XFree( aProp.value );
596cdf0e10cSrcweir #ifdef SOLARIS
597cdf0e10cSrcweir         /*  #97070#
598cdf0e10cSrcweir          *  for currently unknown reasons XmbTextListToTextProperty on Solaris returns
599cdf0e10cSrcweir          *  no data in ISO8859-n encodings (at least for n = 1, 15)
600cdf0e10cSrcweir          *  in these encodings the directly converted text does the
601cdf0e10cSrcweir          *  trick, also.
602cdf0e10cSrcweir          */
603cdf0e10cSrcweir         if( ! aRet.getLength() && rText.getLength() )
604cdf0e10cSrcweir             aRet = OUStringToOString( rText, osl_getThreadTextEncoding() );
605cdf0e10cSrcweir #endif
606cdf0e10cSrcweir     }
607cdf0e10cSrcweir     else
608cdf0e10cSrcweir         aRet = OString();
609cdf0e10cSrcweir 
610cdf0e10cSrcweir     return aRet;
611cdf0e10cSrcweir }
612cdf0e10cSrcweir 
613cdf0e10cSrcweir // ------------------------------------------------------------------------
614cdf0e10cSrcweir 
convertData(const css::uno::Reference<XTransferable> & xTransferable,Atom nType,Atom nSelection,int & rFormat,Sequence<sal_Int8> & rData)615cdf0e10cSrcweir bool SelectionManager::convertData(
616cdf0e10cSrcweir                                    const css::uno::Reference< XTransferable >& xTransferable,
617cdf0e10cSrcweir                                    Atom nType,
618cdf0e10cSrcweir                                    Atom nSelection,
619cdf0e10cSrcweir                                    int& rFormat,
620cdf0e10cSrcweir                                    Sequence< sal_Int8 >& rData )
621cdf0e10cSrcweir {
622cdf0e10cSrcweir 	bool bSuccess = false;
623cdf0e10cSrcweir 
624cdf0e10cSrcweir 	if( ! xTransferable.is() )
625cdf0e10cSrcweir 		return bSuccess;
626cdf0e10cSrcweir 
627cdf0e10cSrcweir     try
628cdf0e10cSrcweir     {
629cdf0e10cSrcweir 
630cdf0e10cSrcweir         DataFlavor aFlavor;
631cdf0e10cSrcweir         aFlavor.MimeType = convertTypeFromNative( nType, nSelection, rFormat );
632cdf0e10cSrcweir 
633cdf0e10cSrcweir         sal_Int32 nIndex = 0;
634cdf0e10cSrcweir         if( aFlavor.MimeType.getToken( 0, ';', nIndex ).compareToAscii( "text/plain" ) == 0 )
635cdf0e10cSrcweir         {
636cdf0e10cSrcweir             if( aFlavor.MimeType.getToken( 0, ';', nIndex ).compareToAscii( "charset=utf-16" ) == 0 )
637cdf0e10cSrcweir                 aFlavor.DataType = getCppuType( (OUString *) 0 );
638cdf0e10cSrcweir             else
639cdf0e10cSrcweir                 aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
640cdf0e10cSrcweir         }
641cdf0e10cSrcweir         else
642cdf0e10cSrcweir             aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
643cdf0e10cSrcweir 
644cdf0e10cSrcweir         if( xTransferable->isDataFlavorSupported( aFlavor ) )
645cdf0e10cSrcweir         {
646cdf0e10cSrcweir             Any aValue( xTransferable->getTransferData( aFlavor ) );
647cdf0e10cSrcweir             if( aValue.getValueTypeClass() == TypeClass_STRING )
648cdf0e10cSrcweir             {
649cdf0e10cSrcweir                 OUString aString;
650cdf0e10cSrcweir                 aValue >>= aString;
651cdf0e10cSrcweir                 rData = Sequence< sal_Int8 >( (sal_Int8*)aString.getStr(), aString.getLength() * sizeof( sal_Unicode ) );
652cdf0e10cSrcweir                 bSuccess = true;
653cdf0e10cSrcweir             }
654cdf0e10cSrcweir             else if( aValue.getValueType() == getCppuType( (Sequence< sal_Int8 >*)0 ) )
655cdf0e10cSrcweir             {
656cdf0e10cSrcweir                 aValue >>= rData;
657cdf0e10cSrcweir                 bSuccess = true;
658cdf0e10cSrcweir             }
659cdf0e10cSrcweir         }
660cdf0e10cSrcweir         else if( aFlavor.MimeType.compareToAscii( "text/plain", 10 ) == 0 )
661cdf0e10cSrcweir         {
662cdf0e10cSrcweir             rtl_TextEncoding aEncoding = RTL_TEXTENCODING_DONTKNOW;
663cdf0e10cSrcweir             bool bCompoundText = false;
664cdf0e10cSrcweir             if( nType == m_nCOMPOUNDAtom )
665cdf0e10cSrcweir                 bCompoundText = true;
666cdf0e10cSrcweir             else
667cdf0e10cSrcweir                 aEncoding = getTextPlainEncoding( aFlavor.MimeType );
668cdf0e10cSrcweir             if( aEncoding != RTL_TEXTENCODING_DONTKNOW || bCompoundText )
669cdf0e10cSrcweir             {
670cdf0e10cSrcweir                 aFlavor.MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
671cdf0e10cSrcweir                 aFlavor.DataType = getCppuType( (OUString *) 0 );
672cdf0e10cSrcweir                 if( xTransferable->isDataFlavorSupported( aFlavor ) )
673cdf0e10cSrcweir                 {
674cdf0e10cSrcweir                     Any aValue( xTransferable->getTransferData( aFlavor ) );
675cdf0e10cSrcweir                     OUString aString;
676cdf0e10cSrcweir                     aValue >>= aString;
677cdf0e10cSrcweir                     OString aByteString( bCompoundText ? convertToCompound( aString ) : OUStringToOString( aString, aEncoding ) );
678cdf0e10cSrcweir                     rData = Sequence< sal_Int8 >( (sal_Int8*)aByteString.getStr(), aByteString.getLength() * sizeof( sal_Char ) );
679cdf0e10cSrcweir                     bSuccess = true;
680cdf0e10cSrcweir                 }
681cdf0e10cSrcweir             }
682cdf0e10cSrcweir         }
683cdf0e10cSrcweir     }
684cdf0e10cSrcweir     // various exceptions possible ... which all lead to a failed conversion
685cdf0e10cSrcweir     // so simplify here to a catch all
686cdf0e10cSrcweir     catch(...)
687cdf0e10cSrcweir     {
688cdf0e10cSrcweir     }
689cdf0e10cSrcweir 
690cdf0e10cSrcweir 	return bSuccess;
691cdf0e10cSrcweir }
692cdf0e10cSrcweir 
693cdf0e10cSrcweir // ------------------------------------------------------------------------
694cdf0e10cSrcweir 
get(const OUString & rDisplayName)695cdf0e10cSrcweir SelectionManager& SelectionManager::get( const OUString& rDisplayName )
696cdf0e10cSrcweir {
697cdf0e10cSrcweir 	MutexGuard aGuard( *Mutex::getGlobalMutex() );
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     OUString aDisplayName( rDisplayName );
700cdf0e10cSrcweir     if( ! aDisplayName.getLength() )
701cdf0e10cSrcweir         aDisplayName = OStringToOUString( getenv( "DISPLAY" ), RTL_TEXTENCODING_ISO_8859_1 );
702cdf0e10cSrcweir 	SelectionManager* pInstance = NULL;
703cdf0e10cSrcweir 
704cdf0e10cSrcweir 	::std::hash_map< OUString, SelectionManager*, OUStringHash >::iterator it = getInstances().find( aDisplayName );
705cdf0e10cSrcweir 	if( it != getInstances().end() )
706cdf0e10cSrcweir 		pInstance = it->second;
707cdf0e10cSrcweir 	else pInstance = getInstances()[ aDisplayName ] = new SelectionManager();
708cdf0e10cSrcweir 
709cdf0e10cSrcweir 	return *pInstance;
710cdf0e10cSrcweir }
711cdf0e10cSrcweir 
712cdf0e10cSrcweir // ------------------------------------------------------------------------
713cdf0e10cSrcweir 
getString(Atom aAtom)714cdf0e10cSrcweir const OUString& SelectionManager::getString( Atom aAtom )
715cdf0e10cSrcweir {
716cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
717cdf0e10cSrcweir 
718cdf0e10cSrcweir 	::std::hash_map< Atom, OUString >::const_iterator it;
719cdf0e10cSrcweir 	if( ( it = m_aAtomToString.find( aAtom ) ) == m_aAtomToString.end() )
720cdf0e10cSrcweir 	{
721cdf0e10cSrcweir 		static OUString aEmpty;
722cdf0e10cSrcweir 		char* pAtom = m_pDisplay ? XGetAtomName( m_pDisplay, aAtom ) : NULL;
723cdf0e10cSrcweir 		if( ! pAtom )
724cdf0e10cSrcweir 			return aEmpty;
725cdf0e10cSrcweir 		OUString aString( OStringToOUString( pAtom, RTL_TEXTENCODING_ISO_8859_1 ) );
726cdf0e10cSrcweir 		XFree( pAtom );
727cdf0e10cSrcweir 		m_aStringToAtom[ aString ] = aAtom;
728cdf0e10cSrcweir 		m_aAtomToString[ aAtom ] = aString;
729cdf0e10cSrcweir 	}
730cdf0e10cSrcweir 	return m_aAtomToString[ aAtom ];
731cdf0e10cSrcweir }
732cdf0e10cSrcweir 
733cdf0e10cSrcweir // ------------------------------------------------------------------------
734cdf0e10cSrcweir 
getAtom(const OUString & rString)735cdf0e10cSrcweir Atom SelectionManager::getAtom( const OUString& rString )
736cdf0e10cSrcweir {
737cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
738cdf0e10cSrcweir 
739cdf0e10cSrcweir 	::std::hash_map< OUString, Atom, OUStringHash >::const_iterator it;
740cdf0e10cSrcweir 	if( ( it = m_aStringToAtom.find( rString ) ) == m_aStringToAtom.end() )
741cdf0e10cSrcweir 	{
742cdf0e10cSrcweir 		static Atom nNoDisplayAtoms = 1;
74324c56ab9SHerbert Dürr 		Atom aAtom = m_pDisplay ? XInternAtom( m_pDisplay, OUStringToOString( rString, RTL_TEXTENCODING_ISO_8859_1).getStr(), False ) : nNoDisplayAtoms++;
744cdf0e10cSrcweir 		m_aStringToAtom[ rString ] = aAtom;
745cdf0e10cSrcweir 		m_aAtomToString[ aAtom ] = rString;
746cdf0e10cSrcweir 	}
747cdf0e10cSrcweir 	return m_aStringToAtom[ rString ];
748cdf0e10cSrcweir }
749cdf0e10cSrcweir 
750cdf0e10cSrcweir // ------------------------------------------------------------------------
751cdf0e10cSrcweir 
requestOwnership(Atom selection)752cdf0e10cSrcweir bool SelectionManager::requestOwnership( Atom selection )
753cdf0e10cSrcweir {
754cdf0e10cSrcweir 	bool bSuccess = false;
755cdf0e10cSrcweir 	if( m_pDisplay && m_aWindow )
756cdf0e10cSrcweir 	{
757cdf0e10cSrcweir 		MutexGuard aGuard(m_aMutex);
758cdf0e10cSrcweir 
759cdf0e10cSrcweir 		SelectionAdaptor* pAdaptor = getAdaptor( selection );
760cdf0e10cSrcweir 		if( pAdaptor )
761cdf0e10cSrcweir 		{
762cdf0e10cSrcweir 			XSetSelectionOwner( m_pDisplay, selection, m_aWindow, CurrentTime );
763cdf0e10cSrcweir 			if( XGetSelectionOwner( m_pDisplay, selection ) == m_aWindow )
764cdf0e10cSrcweir 				bSuccess = true;
765cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
766cdf0e10cSrcweir 			fprintf( stderr, "%s ownership for selection %s\n",
767cdf0e10cSrcweir 					 bSuccess ? "acquired" : "failed to acquire",
768cdf0e10cSrcweir 					 OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
769cdf0e10cSrcweir #endif
770cdf0e10cSrcweir             Selection* pSel = m_aSelections[ selection ];
771cdf0e10cSrcweir             pSel->m_bOwner = bSuccess;
772cdf0e10cSrcweir             delete pSel->m_pPixmap;
773cdf0e10cSrcweir             pSel->m_pPixmap = NULL;
774cdf0e10cSrcweir             pSel->m_nOrigTimestamp = m_nSelectionTimestamp;
775cdf0e10cSrcweir 		}
776cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
777cdf0e10cSrcweir 		else
778cdf0e10cSrcweir 			fprintf( stderr, "no adaptor for selection %s\n",
779cdf0e10cSrcweir 					 OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
780cdf0e10cSrcweir 
781cdf0e10cSrcweir         if( pAdaptor->getTransferable().is() )
782cdf0e10cSrcweir         {
783cdf0e10cSrcweir             Sequence< DataFlavor > aTypes = pAdaptor->getTransferable()->getTransferDataFlavors();
784cdf0e10cSrcweir             for( int i = 0; i < aTypes.getLength(); i++ )
785cdf0e10cSrcweir             {
786cdf0e10cSrcweir                 fprintf( stderr, "   %s\n", OUStringToOString( aTypes.getConstArray()[i].MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
787cdf0e10cSrcweir             }
788cdf0e10cSrcweir         }
789cdf0e10cSrcweir #endif
790cdf0e10cSrcweir 	}
791cdf0e10cSrcweir 	return bSuccess;
792cdf0e10cSrcweir }
793cdf0e10cSrcweir 
794cdf0e10cSrcweir // ------------------------------------------------------------------------
795cdf0e10cSrcweir 
convertTypeToNative(const OUString & rType,Atom selection,int & rFormat,::std::list<Atom> & rConversions,bool bPushFront)796cdf0e10cSrcweir void SelectionManager::convertTypeToNative( const OUString& rType, Atom selection, int& rFormat, ::std::list< Atom >& rConversions, bool bPushFront )
797cdf0e10cSrcweir {
798cdf0e10cSrcweir 	NativeTypeEntry* pTab = selection == m_nXdndSelection ? aXdndConversionTab : aNativeConversionTab;
799cdf0e10cSrcweir 	int nTabEntries = selection == m_nXdndSelection
800cdf0e10cSrcweir 		? sizeof(aXdndConversionTab)/sizeof(aXdndConversionTab[0]) :
801cdf0e10cSrcweir 		sizeof(aNativeConversionTab)/sizeof(aNativeConversionTab[0]);
802cdf0e10cSrcweir 
803cdf0e10cSrcweir 	OString aType( OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ) );
804cdf0e10cSrcweir     rFormat = 0;
805cdf0e10cSrcweir 	for( int i = 0; i < nTabEntries; i++ )
806cdf0e10cSrcweir 	{
807cdf0e10cSrcweir 		if( aType.equalsIgnoreAsciiCase( pTab[i].pType ) )
808cdf0e10cSrcweir 		{
809cdf0e10cSrcweir 			if( ! pTab[i].nAtom )
810cdf0e10cSrcweir 				pTab[i].nAtom = getAtom( OStringToOUString( pTab[i].pNativeType, RTL_TEXTENCODING_ISO_8859_1 ) );
811cdf0e10cSrcweir 			rFormat = pTab[i].nFormat;
812cdf0e10cSrcweir             if( bPushFront )
813cdf0e10cSrcweir                 rConversions.push_front( pTab[i].nAtom );
814cdf0e10cSrcweir             else
815cdf0e10cSrcweir                 rConversions.push_back( pTab[i].nAtom );
816cdf0e10cSrcweir             if( pTab[i].nFormat == XA_PIXMAP )
817cdf0e10cSrcweir             {
818cdf0e10cSrcweir                 if( bPushFront )
819cdf0e10cSrcweir                 {
820cdf0e10cSrcweir                     rConversions.push_front( XA_VISUALID );
821cdf0e10cSrcweir                     rConversions.push_front( XA_COLORMAP );
822cdf0e10cSrcweir                 }
823cdf0e10cSrcweir                 else
824cdf0e10cSrcweir                 {
825cdf0e10cSrcweir                     rConversions.push_back( XA_VISUALID );
826cdf0e10cSrcweir                     rConversions.push_back( XA_COLORMAP );
827cdf0e10cSrcweir                 }
828cdf0e10cSrcweir             }
829cdf0e10cSrcweir 		}
830cdf0e10cSrcweir 	}
831cdf0e10cSrcweir     if( ! rFormat )
832cdf0e10cSrcweir         rFormat = 8; // byte buffer
833cdf0e10cSrcweir     if( bPushFront )
834cdf0e10cSrcweir         rConversions.push_front( getAtom( rType ) );
835cdf0e10cSrcweir     else
836cdf0e10cSrcweir         rConversions.push_back( getAtom( rType ) );
837cdf0e10cSrcweir };
838cdf0e10cSrcweir 
839cdf0e10cSrcweir // ------------------------------------------------------------------------
840cdf0e10cSrcweir 
getNativeTypeList(const Sequence<DataFlavor> & rTypes,std::list<Atom> & rOutTypeList,Atom targetselection)841cdf0e10cSrcweir void SelectionManager::getNativeTypeList( const Sequence< DataFlavor >& rTypes, std::list< Atom >& rOutTypeList, Atom targetselection )
842cdf0e10cSrcweir {
843cdf0e10cSrcweir     rOutTypeList.clear();
844cdf0e10cSrcweir 
845cdf0e10cSrcweir     int nFormat;
846cdf0e10cSrcweir     int nFlavors = rTypes.getLength();
847cdf0e10cSrcweir     const DataFlavor* pFlavors = rTypes.getConstArray();
848cdf0e10cSrcweir     bool bHaveText = false;
849cdf0e10cSrcweir     for( int i = 0; i < nFlavors; i++ )
850cdf0e10cSrcweir     {
851cdf0e10cSrcweir         if( pFlavors[i].MimeType.compareToAscii( "text/plain", 10 ) == 0)
852cdf0e10cSrcweir             bHaveText = true;
853cdf0e10cSrcweir         else
854cdf0e10cSrcweir             convertTypeToNative( pFlavors[i].MimeType, targetselection, nFormat, rOutTypeList );
855cdf0e10cSrcweir     }
856cdf0e10cSrcweir     if( bHaveText )
857cdf0e10cSrcweir     {
858cdf0e10cSrcweir         if( targetselection != m_nXdndSelection )
859cdf0e10cSrcweir         {
860cdf0e10cSrcweir             // only mimetypes should go into Xdnd type list
861cdf0e10cSrcweir             rOutTypeList.push_front( XA_STRING );
862cdf0e10cSrcweir             rOutTypeList.push_front( m_nCOMPOUNDAtom );
863cdf0e10cSrcweir         }
864cdf0e10cSrcweir         convertTypeToNative( OUString::createFromAscii( "text/plain;charset=utf-8" ), targetselection, nFormat, rOutTypeList, true );
865cdf0e10cSrcweir     }
866cdf0e10cSrcweir     if( targetselection != m_nXdndSelection )
867cdf0e10cSrcweir         rOutTypeList.push_back( m_nMULTIPLEAtom );
868cdf0e10cSrcweir }
869cdf0e10cSrcweir 
870cdf0e10cSrcweir // ------------------------------------------------------------------------
871cdf0e10cSrcweir 
convertTypeFromNative(Atom nType,Atom selection,int & rFormat)872cdf0e10cSrcweir OUString SelectionManager::convertTypeFromNative( Atom nType, Atom selection, int& rFormat )
873cdf0e10cSrcweir {
874cdf0e10cSrcweir 	NativeTypeEntry* pTab = selection == m_nXdndSelection ? aXdndConversionTab : aNativeConversionTab;
875cdf0e10cSrcweir 	int nTabEntries = selection == m_nXdndSelection
876cdf0e10cSrcweir 		? sizeof(aXdndConversionTab)/sizeof(aXdndConversionTab[0]) :
877cdf0e10cSrcweir 		sizeof(aNativeConversionTab)/sizeof(aNativeConversionTab[0]);
878cdf0e10cSrcweir 
879cdf0e10cSrcweir 	for( int i = 0; i < nTabEntries; i++ )
880cdf0e10cSrcweir 	{
881cdf0e10cSrcweir 		if( ! pTab[i].nAtom )
882cdf0e10cSrcweir 			pTab[i].nAtom = getAtom( OStringToOUString( pTab[i].pNativeType, RTL_TEXTENCODING_ISO_8859_1 ) );
883cdf0e10cSrcweir 		if( nType == pTab[i].nAtom )
884cdf0e10cSrcweir         {
885cdf0e10cSrcweir             rFormat = pTab[i].nFormat;
886cdf0e10cSrcweir 			return OStringToOUString( pTab[i].pType, RTL_TEXTENCODING_ISO_8859_1 );
887cdf0e10cSrcweir         }
888cdf0e10cSrcweir 	}
889cdf0e10cSrcweir     rFormat = 8;
890cdf0e10cSrcweir 	return getString( nType );
891cdf0e10cSrcweir }
892cdf0e10cSrcweir 
893cdf0e10cSrcweir // ------------------------------------------------------------------------
894cdf0e10cSrcweir 
getPasteData(Atom selection,Atom type,Sequence<sal_Int8> & rData)895cdf0e10cSrcweir bool SelectionManager::getPasteData( Atom selection, Atom type, Sequence< sal_Int8 >& rData )
896cdf0e10cSrcweir {
897cdf0e10cSrcweir     ResettableMutexGuard aGuard(m_aMutex);
898cdf0e10cSrcweir 	::std::hash_map< Atom, Selection* >::iterator it;
899cdf0e10cSrcweir 	bool bSuccess = false;
900cdf0e10cSrcweir 
901cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
902cdf0e10cSrcweir     OUString aSelection( getString( selection ) );
903cdf0e10cSrcweir     OUString aType( getString( type ) );
904cdf0e10cSrcweir     fprintf( stderr, "getPasteData( %s, native: %s )\n",
905cdf0e10cSrcweir              OUStringToOString( aSelection, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
906cdf0e10cSrcweir              OUStringToOString( aType, RTL_TEXTENCODING_ISO_8859_1 ).getStr()
907cdf0e10cSrcweir              );
908cdf0e10cSrcweir #endif
909cdf0e10cSrcweir 
910cdf0e10cSrcweir     if( ! m_pDisplay )
911cdf0e10cSrcweir         return false;
912cdf0e10cSrcweir 
913cdf0e10cSrcweir     it = m_aSelections.find( selection );
914cdf0e10cSrcweir     if( it == m_aSelections.end() )
915cdf0e10cSrcweir         return false;
916cdf0e10cSrcweir 
917cdf0e10cSrcweir     XLIB_Window aSelectionOwner = XGetSelectionOwner( m_pDisplay, selection );
918cdf0e10cSrcweir     if( aSelectionOwner == None )
919cdf0e10cSrcweir         return false;
920cdf0e10cSrcweir     if( aSelectionOwner == m_aWindow )
921cdf0e10cSrcweir     {
922cdf0e10cSrcweir         // probably bad timing led us here
923cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
924cdf0e10cSrcweir         fprintf( stderr, "Innere Nabelschau\n" );
925cdf0e10cSrcweir #endif
926cdf0e10cSrcweir         return false;
927cdf0e10cSrcweir     }
928cdf0e10cSrcweir 
929cdf0e10cSrcweir     // ICCCM recommends to destroy property before convert request unless
930cdf0e10cSrcweir     // parameters are transported; we do only in case of MULTIPLE,
931cdf0e10cSrcweir     // so destroy property unless target is MULTIPLE
932cdf0e10cSrcweir     if( type != m_nMULTIPLEAtom )
933cdf0e10cSrcweir         XDeleteProperty( m_pDisplay, m_aWindow, selection );
934cdf0e10cSrcweir 
935cdf0e10cSrcweir     XConvertSelection( m_pDisplay, selection, type, selection, m_aWindow, selection == m_nXdndSelection ? m_nDropTime : CurrentTime );
936cdf0e10cSrcweir     it->second->m_eState			= Selection::WaitingForResponse;
937cdf0e10cSrcweir     it->second->m_aRequestedType	= type;
938cdf0e10cSrcweir     it->second->m_aData				= Sequence< sal_Int8 >();
939cdf0e10cSrcweir     it->second->m_aDataArrived.reset();
940cdf0e10cSrcweir     // really start the request; if we don't flush the
941cdf0e10cSrcweir     // queue the request won't leave it because there are no more
942cdf0e10cSrcweir     // X calls after this until the data arrived or timeout
943cdf0e10cSrcweir     XFlush( m_pDisplay );
944cdf0e10cSrcweir 
945cdf0e10cSrcweir 	// do a reschedule
946cdf0e10cSrcweir     struct timeval tv_last, tv_current;
947cdf0e10cSrcweir     gettimeofday( &tv_last, NULL );
948cdf0e10cSrcweir     tv_current = tv_last;
949cdf0e10cSrcweir 
950cdf0e10cSrcweir     XEvent aEvent;
951cdf0e10cSrcweir 	do
952cdf0e10cSrcweir 	{
953cdf0e10cSrcweir         bool bAdjustTime = false;
954cdf0e10cSrcweir         {
955cdf0e10cSrcweir             bool bHandle = false;
956cdf0e10cSrcweir 
957cdf0e10cSrcweir             if( XCheckTypedEvent( m_pDisplay,
958cdf0e10cSrcweir                                   PropertyNotify,
959cdf0e10cSrcweir                                   &aEvent
960cdf0e10cSrcweir                                   ) )
961cdf0e10cSrcweir             {
962cdf0e10cSrcweir                 bHandle = true;
963cdf0e10cSrcweir                 if( aEvent.xproperty.window == m_aWindow
964cdf0e10cSrcweir                     && aEvent.xproperty.atom == selection )
965cdf0e10cSrcweir                     bAdjustTime = true;
966cdf0e10cSrcweir             }
967cdf0e10cSrcweir             else
968cdf0e10cSrcweir             if( XCheckTypedEvent( m_pDisplay,
969cdf0e10cSrcweir                                   SelectionClear,
970cdf0e10cSrcweir                                   &aEvent
971cdf0e10cSrcweir                                   ) )
972cdf0e10cSrcweir             {
973cdf0e10cSrcweir                 bHandle = true;
974cdf0e10cSrcweir             }
975cdf0e10cSrcweir             else
976cdf0e10cSrcweir             if( XCheckTypedEvent( m_pDisplay,
977cdf0e10cSrcweir                                   SelectionRequest,
978cdf0e10cSrcweir                                   &aEvent
979cdf0e10cSrcweir                                   ) )
980cdf0e10cSrcweir                 bHandle = true;
981cdf0e10cSrcweir             else
982cdf0e10cSrcweir             if( XCheckTypedEvent( m_pDisplay,
983cdf0e10cSrcweir                                   SelectionNotify,
984cdf0e10cSrcweir                                   &aEvent
985cdf0e10cSrcweir                                   ) )
986cdf0e10cSrcweir             {
987cdf0e10cSrcweir                 bHandle = true;
988cdf0e10cSrcweir                 if( aEvent.xselection.selection == selection
989cdf0e10cSrcweir                     && ( aEvent.xselection.requestor == m_aWindow ||
990cdf0e10cSrcweir                          aEvent.xselection.requestor == m_aCurrentDropWindow )
991cdf0e10cSrcweir                     )
992cdf0e10cSrcweir                     bAdjustTime = true;
993cdf0e10cSrcweir             }
994cdf0e10cSrcweir             else
995cdf0e10cSrcweir             {
996cdf0e10cSrcweir                 TimeValue aTVal;
997cdf0e10cSrcweir                 aTVal.Seconds = 0;
998cdf0e10cSrcweir                 aTVal.Nanosec = 100000000;
999cdf0e10cSrcweir                 aGuard.clear();
1000cdf0e10cSrcweir                 osl_waitThread( &aTVal );
1001cdf0e10cSrcweir                 aGuard.reset();
1002cdf0e10cSrcweir             }
1003cdf0e10cSrcweir             if( bHandle )
1004cdf0e10cSrcweir             {
1005cdf0e10cSrcweir                 aGuard.clear();
1006cdf0e10cSrcweir                 handleXEvent( aEvent );
1007cdf0e10cSrcweir                 aGuard.reset();
1008cdf0e10cSrcweir             }
1009cdf0e10cSrcweir         }
1010cdf0e10cSrcweir         gettimeofday( &tv_current, NULL );
1011cdf0e10cSrcweir         if( bAdjustTime )
1012cdf0e10cSrcweir             tv_last = tv_current;
1013cdf0e10cSrcweir 	} while( ! it->second->m_aDataArrived.check() && (tv_current.tv_sec - tv_last.tv_sec) < getSelectionTimeout() );
1014cdf0e10cSrcweir 
1015cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1016cdf0e10cSrcweir     if( (tv_current.tv_sec - tv_last.tv_sec) > getSelectionTimeout() )
1017cdf0e10cSrcweir         fprintf( stderr, "timed out\n" );
1018cdf0e10cSrcweir #endif
1019cdf0e10cSrcweir 	if( it->second->m_aDataArrived.check() &&
1020cdf0e10cSrcweir 		it->second->m_aData.getLength() )
1021cdf0e10cSrcweir 	{
1022cdf0e10cSrcweir 		rData = it->second->m_aData;
1023cdf0e10cSrcweir 		bSuccess = true;
1024cdf0e10cSrcweir 	}
1025cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1026cdf0e10cSrcweir     else
1027cdf0e10cSrcweir         fprintf( stderr, "conversion unsuccessfull\n" );
1028cdf0e10cSrcweir #endif
1029cdf0e10cSrcweir 	return bSuccess;
1030cdf0e10cSrcweir }
1031cdf0e10cSrcweir 
1032cdf0e10cSrcweir // ------------------------------------------------------------------------
1033cdf0e10cSrcweir 
getPasteData(Atom selection,const::rtl::OUString & rType,Sequence<sal_Int8> & rData)1034cdf0e10cSrcweir bool SelectionManager::getPasteData( Atom selection, const ::rtl::OUString& rType, Sequence< sal_Int8 >& rData )
1035cdf0e10cSrcweir {
1036cdf0e10cSrcweir 	int nFormat;
1037cdf0e10cSrcweir 	bool bSuccess = false;
1038cdf0e10cSrcweir 
1039cdf0e10cSrcweir     ::std::hash_map< Atom, Selection* >::iterator it;
1040cdf0e10cSrcweir     {
1041cdf0e10cSrcweir         MutexGuard aGuard(m_aMutex);
1042cdf0e10cSrcweir 
1043cdf0e10cSrcweir         it = m_aSelections.find( selection );
1044cdf0e10cSrcweir         if( it == m_aSelections.end() )
1045cdf0e10cSrcweir             return false;
1046cdf0e10cSrcweir     }
1047cdf0e10cSrcweir 
1048cdf0e10cSrcweir     if( it->second->m_aTypes.getLength() == 0 )
1049cdf0e10cSrcweir     {
1050cdf0e10cSrcweir         Sequence< DataFlavor > aFlavors;
1051cdf0e10cSrcweir         getPasteDataTypes( selection, aFlavors );
1052cdf0e10cSrcweir         if( it->second->m_aTypes.getLength() == 0 )
1053cdf0e10cSrcweir             return false;
1054cdf0e10cSrcweir     }
1055cdf0e10cSrcweir 
1056cdf0e10cSrcweir     const Sequence< DataFlavor >& rTypes( it->second->m_aTypes );
1057cdf0e10cSrcweir     const std::vector< Atom >& rNativeTypes( it->second->m_aNativeTypes );
1058cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1059cdf0e10cSrcweir     fprintf( stderr, "getPasteData( \"%s\", \"%s\" )\n",
1060cdf0e10cSrcweir              OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1061cdf0e10cSrcweir              OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1062cdf0e10cSrcweir #endif
1063cdf0e10cSrcweir 
1064cdf0e10cSrcweir 	if( rType.equalsAsciiL( "text/plain;charset=utf-16", 25 ) )
1065cdf0e10cSrcweir 	{
1066cdf0e10cSrcweir 		// lets see if we have UTF16 else try to find something convertible
1067cdf0e10cSrcweir 		if( it->second->m_aTypes.getLength() && ! it->second->m_bHaveUTF16 )
1068cdf0e10cSrcweir 		{
1069cdf0e10cSrcweir 			Sequence< sal_Int8 > aData;
1070cdf0e10cSrcweir 			if( it->second->m_aUTF8Type != None &&
1071cdf0e10cSrcweir 				getPasteData( selection,
1072cdf0e10cSrcweir 							  it->second->m_aUTF8Type,
1073cdf0e10cSrcweir 							  aData )
1074cdf0e10cSrcweir 				)
1075cdf0e10cSrcweir 			{
1076cdf0e10cSrcweir 			  OUString aRet( (const sal_Char*)aData.getConstArray(), aData.getLength(), RTL_TEXTENCODING_UTF8 );
1077cdf0e10cSrcweir 			  rData = Sequence< sal_Int8 >( (sal_Int8*)aRet.getStr(), (aRet.getLength()+1)*sizeof( sal_Unicode ) );
1078cdf0e10cSrcweir 			  bSuccess = true;
1079cdf0e10cSrcweir 			}
1080cdf0e10cSrcweir             else if( it->second->m_bHaveCompound &&
1081cdf0e10cSrcweir                 getPasteData( selection,
1082cdf0e10cSrcweir                               m_nCOMPOUNDAtom,
1083cdf0e10cSrcweir                               aData )
1084cdf0e10cSrcweir                 )
1085cdf0e10cSrcweir             {
1086cdf0e10cSrcweir                 OUString aRet( convertFromCompound( (const char*)aData.getConstArray(), aData.getLength() ) );
1087cdf0e10cSrcweir                 rData = Sequence< sal_Int8 >( (sal_Int8*)aRet.getStr(), (aRet.getLength()+1)*sizeof( sal_Unicode ) );
1088cdf0e10cSrcweir                 bSuccess = true;
1089cdf0e10cSrcweir             }
1090cdf0e10cSrcweir             else
1091cdf0e10cSrcweir             {
1092cdf0e10cSrcweir                 for( int i = 0; i < rTypes.getLength(); i++ )
1093cdf0e10cSrcweir                 {
1094cdf0e10cSrcweir                     rtl_TextEncoding aEncoding = getTextPlainEncoding( rTypes.getConstArray()[i].MimeType );
1095cdf0e10cSrcweir                     if( aEncoding != RTL_TEXTENCODING_DONTKNOW	&&
1096cdf0e10cSrcweir                         aEncoding != RTL_TEXTENCODING_UNICODE	&&
1097cdf0e10cSrcweir                         getPasteData( selection,
1098cdf0e10cSrcweir                                       rNativeTypes[i],
1099cdf0e10cSrcweir                                       aData )
1100cdf0e10cSrcweir                         )
1101cdf0e10cSrcweir                     {
1102cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1103cdf0e10cSrcweir                         fprintf( stderr, "using \"%s\" instead of \"%s\"\n",
1104cdf0e10cSrcweir                                  OUStringToOString( rTypes.getConstArray()[i].MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1105cdf0e10cSrcweir                                  OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ).getStr()
1106cdf0e10cSrcweir                                  );
1107cdf0e10cSrcweir #endif
1108cdf0e10cSrcweir                         OString aConvert( (sal_Char*)aData.getConstArray(), aData.getLength() );
1109cdf0e10cSrcweir                         OUString aUTF( OStringToOUString( aConvert, aEncoding ) );
1110cdf0e10cSrcweir                         rData = Sequence< sal_Int8 >( (sal_Int8*)aUTF.getStr(), (aUTF.getLength()+1)*sizeof( sal_Unicode ) );
1111cdf0e10cSrcweir                         bSuccess = true;
1112cdf0e10cSrcweir                         break;
1113cdf0e10cSrcweir                     }
1114cdf0e10cSrcweir                 }
1115cdf0e10cSrcweir             }
1116cdf0e10cSrcweir         }
1117cdf0e10cSrcweir     }
1118cdf0e10cSrcweir     else if( rType.equalsAsciiL( "image/bmp", 9 ) )
1119cdf0e10cSrcweir     {
1120cdf0e10cSrcweir         // #i83376# try if someone has the data in image/bmp already before
1121cdf0e10cSrcweir         // doing the PIXMAP stuff (e.g. the gimp has this)
1122cdf0e10cSrcweir         bSuccess = getPasteData( selection, m_nImageBmpAtom, rData );
1123cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
1124cdf0e10cSrcweir         if( bSuccess )
1125cdf0e10cSrcweir             fprintf( stderr, "got %d bytes of image/bmp\n", (int)rData.getLength() );
1126cdf0e10cSrcweir         #endif
1127cdf0e10cSrcweir         if( ! bSuccess )
1128cdf0e10cSrcweir         {
1129cdf0e10cSrcweir             Pixmap aPixmap = None;
1130cdf0e10cSrcweir             Colormap aColormap = None;
1131cdf0e10cSrcweir 
1132cdf0e10cSrcweir             // prepare property for MULTIPLE request
1133cdf0e10cSrcweir             Sequence< sal_Int8 > aData;
1134cdf0e10cSrcweir             Atom pTypes[4] = { XA_PIXMAP, XA_PIXMAP,
1135cdf0e10cSrcweir             XA_COLORMAP, XA_COLORMAP };
1136cdf0e10cSrcweir             {
1137cdf0e10cSrcweir                 MutexGuard aGuard(m_aMutex);
1138cdf0e10cSrcweir 
1139cdf0e10cSrcweir                 XChangeProperty( m_pDisplay,
1140cdf0e10cSrcweir                     m_aWindow,
1141cdf0e10cSrcweir                     selection,
1142cdf0e10cSrcweir                     XA_ATOM,
1143cdf0e10cSrcweir                     32,
1144cdf0e10cSrcweir                     PropModeReplace,
1145cdf0e10cSrcweir                     (unsigned char*)pTypes,
1146cdf0e10cSrcweir                     4 );
1147cdf0e10cSrcweir             }
1148cdf0e10cSrcweir 
1149cdf0e10cSrcweir             // try MULTIPLE request
1150cdf0e10cSrcweir             if( getPasteData( selection, m_nMULTIPLEAtom, aData ) )
1151cdf0e10cSrcweir             {
1152cdf0e10cSrcweir                 Atom* pReturnedTypes = (Atom*)aData.getArray();
1153cdf0e10cSrcweir                 if( pReturnedTypes[0] == XA_PIXMAP && pReturnedTypes[1] == XA_PIXMAP )
1154cdf0e10cSrcweir                 {
1155cdf0e10cSrcweir                     MutexGuard aGuard(m_aMutex);
1156cdf0e10cSrcweir 
1157cdf0e10cSrcweir                     Atom type = None;
1158cdf0e10cSrcweir                     int format = 0;
1159cdf0e10cSrcweir                     unsigned long nItems = 0;
1160cdf0e10cSrcweir                     unsigned long nBytes = 0;
1161cdf0e10cSrcweir                     unsigned char* pReturn = NULL;
1162cdf0e10cSrcweir                     XGetWindowProperty( m_pDisplay, m_aWindow, XA_PIXMAP, 0, 1, True, XA_PIXMAP, &type, &format, &nItems, &nBytes, &pReturn );
1163cdf0e10cSrcweir                     if( pReturn )
1164cdf0e10cSrcweir                     {
1165cdf0e10cSrcweir                         if( type == XA_PIXMAP )
1166cdf0e10cSrcweir                             aPixmap = *(Pixmap*)pReturn;
1167cdf0e10cSrcweir                         XFree( pReturn );
1168cdf0e10cSrcweir                         pReturn = NULL;
1169cdf0e10cSrcweir                         if( pReturnedTypes[2] == XA_COLORMAP && pReturnedTypes[3] == XA_COLORMAP )
1170cdf0e10cSrcweir                         {
1171cdf0e10cSrcweir                             XGetWindowProperty( m_pDisplay, m_aWindow, XA_COLORMAP, 0, 1, True, XA_COLORMAP, &type, &format, &nItems, &nBytes, &pReturn );
1172cdf0e10cSrcweir                             if( pReturn )
1173cdf0e10cSrcweir                             {
1174cdf0e10cSrcweir                                 if( type == XA_COLORMAP )
1175cdf0e10cSrcweir                                     aColormap = *(Colormap*)pReturn;
1176cdf0e10cSrcweir                                 XFree( pReturn );
1177cdf0e10cSrcweir                             }
1178cdf0e10cSrcweir                         }
1179cdf0e10cSrcweir                     }
1180cdf0e10cSrcweir                     #if OSL_DEBUG_LEVEL > 1
1181cdf0e10cSrcweir                     else
1182cdf0e10cSrcweir                     {
1183cdf0e10cSrcweir                         fprintf( stderr, "could not get PIXMAP property: type=%s, format=%d, items=%ld, bytes=%ld, ret=0x%p\n", OUStringToOString( getString( type ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(), format, nItems, nBytes, pReturn );
1184cdf0e10cSrcweir                     }
1185cdf0e10cSrcweir                     #endif
1186cdf0e10cSrcweir                 }
1187cdf0e10cSrcweir             }
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir             if( aPixmap == None )
1190cdf0e10cSrcweir             {
1191cdf0e10cSrcweir                 // perhaps two normal requests will work
1192cdf0e10cSrcweir                 if( getPasteData( selection, XA_PIXMAP, aData ) )
1193cdf0e10cSrcweir                 {
1194cdf0e10cSrcweir                     aPixmap = *(Pixmap*)aData.getArray();
1195cdf0e10cSrcweir                     if( aColormap == None && getPasteData( selection, XA_COLORMAP, aData ) )
1196cdf0e10cSrcweir                         aColormap = *(Colormap*)aData.getArray();
1197cdf0e10cSrcweir                 }
1198cdf0e10cSrcweir             }
1199cdf0e10cSrcweir 
1200cdf0e10cSrcweir             // convert data if possible
1201cdf0e10cSrcweir             if( aPixmap != None )
1202cdf0e10cSrcweir             {
1203cdf0e10cSrcweir                 MutexGuard aGuard(m_aMutex);
1204cdf0e10cSrcweir 
1205cdf0e10cSrcweir                 sal_Int32 nOutSize = 0;
1206cdf0e10cSrcweir                 sal_uInt8* pBytes = X11_getBmpFromPixmap( m_pDisplay, aPixmap, aColormap, nOutSize );
1207cdf0e10cSrcweir                 if( pBytes && nOutSize )
1208cdf0e10cSrcweir                 {
1209cdf0e10cSrcweir                     rData = Sequence< sal_Int8 >( nOutSize );
1210cdf0e10cSrcweir                     memcpy( rData.getArray(), pBytes, nOutSize );
1211cdf0e10cSrcweir                     X11_freeBmp( pBytes );
1212cdf0e10cSrcweir                     bSuccess = true;
1213cdf0e10cSrcweir                 }
1214cdf0e10cSrcweir             }
1215cdf0e10cSrcweir         }
1216cdf0e10cSrcweir     }
1217cdf0e10cSrcweir 
1218cdf0e10cSrcweir 	if( ! bSuccess )
1219cdf0e10cSrcweir     {
1220cdf0e10cSrcweir         ::std::list< Atom > aTypes;
1221cdf0e10cSrcweir         convertTypeToNative( rType, selection, nFormat, aTypes );
1222cdf0e10cSrcweir         ::std::list< Atom >::const_iterator type_it;
1223cdf0e10cSrcweir         Atom nSelectedType = None;
1224cdf0e10cSrcweir         for( type_it = aTypes.begin(); type_it != aTypes.end() && nSelectedType == None; ++type_it )
1225cdf0e10cSrcweir         {
1226cdf0e10cSrcweir             for( unsigned int i = 0; i < rNativeTypes.size() && nSelectedType == None; i++ )
1227cdf0e10cSrcweir                 if( rNativeTypes[i] == *type_it )
1228cdf0e10cSrcweir                     nSelectedType = *type_it;
1229cdf0e10cSrcweir         }
1230cdf0e10cSrcweir         if( nSelectedType != None )
1231cdf0e10cSrcweir             bSuccess = getPasteData( selection, nSelectedType, rData );
1232cdf0e10cSrcweir     }
1233cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1234cdf0e10cSrcweir 	fprintf( stderr, "getPasteData for selection %s and data type %s returns %s, returned sequence has length %ld\n",
1235cdf0e10cSrcweir 			 OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1236cdf0e10cSrcweir 			 OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1237cdf0e10cSrcweir 			 bSuccess ? "true" : "false",
1238cdf0e10cSrcweir 			 rData.getLength()
1239cdf0e10cSrcweir 			 );
1240cdf0e10cSrcweir #endif
1241cdf0e10cSrcweir 	return bSuccess;
1242cdf0e10cSrcweir }
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir // ------------------------------------------------------------------------
1245cdf0e10cSrcweir 
getPasteDataTypes(Atom selection,Sequence<DataFlavor> & rTypes)1246cdf0e10cSrcweir bool SelectionManager::getPasteDataTypes( Atom selection, Sequence< DataFlavor >& rTypes )
1247cdf0e10cSrcweir {
1248cdf0e10cSrcweir 	::std::hash_map< Atom, Selection* >::iterator it;
1249cdf0e10cSrcweir 	{
1250cdf0e10cSrcweir 		MutexGuard aGuard(m_aMutex);
1251cdf0e10cSrcweir 
1252cdf0e10cSrcweir 		it = m_aSelections.find( selection );
1253cdf0e10cSrcweir 		if( it != m_aSelections.end()							&&
1254cdf0e10cSrcweir 			it->second->m_aTypes.getLength()					&&
1255cdf0e10cSrcweir 			abs( it->second->m_nLastTimestamp - time( NULL ) ) < 2
1256cdf0e10cSrcweir 			)
1257cdf0e10cSrcweir 		{
1258cdf0e10cSrcweir 			rTypes = it->second->m_aTypes;
1259cdf0e10cSrcweir 			return true;
1260cdf0e10cSrcweir 		}
1261cdf0e10cSrcweir 	}
1262cdf0e10cSrcweir 
1263cdf0e10cSrcweir 	bool bSuccess = false;
1264cdf0e10cSrcweir 	bool bHaveUTF16 = false;
1265cdf0e10cSrcweir 	Atom aUTF8Type = None;
1266cdf0e10cSrcweir     bool bHaveCompound = false;
1267cdf0e10cSrcweir 	bool bHaveText = false;
1268cdf0e10cSrcweir 	Sequence< sal_Int8 > aAtoms;
1269cdf0e10cSrcweir 
1270cdf0e10cSrcweir 	if( selection == m_nXdndSelection )
1271cdf0e10cSrcweir 	{
1272cdf0e10cSrcweir 		// xdnd sends first three types with XdndEnter
1273cdf0e10cSrcweir 		// if more than three types are supported then the XDndTypeList
1274cdf0e10cSrcweir 		// property on the source window is used
1275cdf0e10cSrcweir 		if( m_aDropEnterEvent.data.l[0] && m_aCurrentDropWindow )
1276cdf0e10cSrcweir 		{
1277cdf0e10cSrcweir 			if( m_aDropEnterEvent.data.l[1] & 1 )
1278cdf0e10cSrcweir 			{
1279cdf0e10cSrcweir 				const unsigned int atomcount = 256;
1280cdf0e10cSrcweir 				// more than three types; look in property
1281cdf0e10cSrcweir 				MutexGuard aGuard(m_aMutex);
1282cdf0e10cSrcweir 
1283cdf0e10cSrcweir 				Atom nType;
1284cdf0e10cSrcweir 				int nFormat;
1285cdf0e10cSrcweir 				unsigned long nItems, nBytes;
1286cdf0e10cSrcweir 				unsigned char* pBytes = NULL;
1287cdf0e10cSrcweir 
1288cdf0e10cSrcweir 				XGetWindowProperty( m_pDisplay, m_aDropEnterEvent.data.l[0],
1289cdf0e10cSrcweir 									m_nXdndTypeList, 0, atomcount, False,
1290cdf0e10cSrcweir 									XA_ATOM,
1291cdf0e10cSrcweir 									&nType, &nFormat, &nItems, &nBytes, &pBytes );
1292cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1293cdf0e10cSrcweir 				fprintf( stderr, "have %ld data types in XdndTypeList\n", nItems );
1294cdf0e10cSrcweir #endif
1295cdf0e10cSrcweir 				if( nItems == atomcount && nBytes > 0 )
1296cdf0e10cSrcweir 				{
1297cdf0e10cSrcweir 					// wow ... more than 256 types !
1298cdf0e10cSrcweir 					aAtoms.realloc( sizeof( Atom )*atomcount+nBytes );
1299cdf0e10cSrcweir 					memcpy( aAtoms.getArray(), pBytes, sizeof( Atom )*atomcount );
1300cdf0e10cSrcweir 					XFree( pBytes );
1301cdf0e10cSrcweir 					pBytes = NULL;
1302cdf0e10cSrcweir 					XGetWindowProperty( m_pDisplay, m_aDropEnterEvent.data.l[0],
1303cdf0e10cSrcweir 										m_nXdndTypeList, atomcount, nBytes/sizeof(Atom),
1304cdf0e10cSrcweir 										False, XA_ATOM,
1305cdf0e10cSrcweir 										&nType, &nFormat, &nItems, &nBytes, &pBytes );
1306cdf0e10cSrcweir 					{
1307cdf0e10cSrcweir 						memcpy( aAtoms.getArray()+atomcount*sizeof(Atom), pBytes, nItems*sizeof(Atom) );
1308cdf0e10cSrcweir 						XFree( pBytes );
1309cdf0e10cSrcweir 					}
1310cdf0e10cSrcweir 				}
1311cdf0e10cSrcweir 				else
1312cdf0e10cSrcweir 				{
1313cdf0e10cSrcweir 					aAtoms.realloc( sizeof(Atom)*nItems );
1314cdf0e10cSrcweir 					memcpy( aAtoms.getArray(), pBytes, nItems*sizeof(Atom) );
1315cdf0e10cSrcweir 					XFree( pBytes );
1316cdf0e10cSrcweir 				}
1317cdf0e10cSrcweir 			}
1318cdf0e10cSrcweir 			else
1319cdf0e10cSrcweir 			{
1320cdf0e10cSrcweir 				// one to three types
1321cdf0e10cSrcweir 				int n = 0, i;
1322cdf0e10cSrcweir 				for( i = 0; i < 3; i++ )
1323cdf0e10cSrcweir 					if( m_aDropEnterEvent.data.l[2+i] )
1324cdf0e10cSrcweir 						n++;
1325cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1326cdf0e10cSrcweir 				fprintf( stderr, "have %d data types in XdndEnter\n", n );
1327cdf0e10cSrcweir #endif
1328cdf0e10cSrcweir 				aAtoms.realloc( sizeof(Atom)*n );
1329cdf0e10cSrcweir 				for( i = 0, n = 0; i < 3; i++ )
1330cdf0e10cSrcweir 					if( m_aDropEnterEvent.data.l[2+i] )
1331cdf0e10cSrcweir 						((Atom*)aAtoms.getArray())[n++] = m_aDropEnterEvent.data.l[2+i];
1332cdf0e10cSrcweir 			}
1333cdf0e10cSrcweir 		}
1334cdf0e10cSrcweir 	}
1335cdf0e10cSrcweir 	// get data of type TARGETS
1336cdf0e10cSrcweir 	else if( ! getPasteData( selection, m_nTARGETSAtom, aAtoms ) )
1337cdf0e10cSrcweir 		aAtoms = Sequence< sal_Int8 >();
1338cdf0e10cSrcweir 
1339cdf0e10cSrcweir 	std::vector< Atom > aNativeTypes;
1340cdf0e10cSrcweir 	if( aAtoms.getLength() )
1341cdf0e10cSrcweir 	{
1342cdf0e10cSrcweir 		sal_Int32 nAtoms = aAtoms.getLength() / sizeof(Atom);
1343cdf0e10cSrcweir 		Atom* pAtoms = (Atom*)aAtoms.getArray();
1344cdf0e10cSrcweir 		rTypes.realloc( nAtoms );
1345cdf0e10cSrcweir 		aNativeTypes.resize( nAtoms );
1346cdf0e10cSrcweir 		DataFlavor* pFlavors = rTypes.getArray();
1347cdf0e10cSrcweir 		sal_Int32 nNativeTypesIndex = 0;
1348cdf0e10cSrcweir 		while( nAtoms-- )
1349cdf0e10cSrcweir 		{
1350cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1351cdf0e10cSrcweir             if( *pAtoms && *pAtoms < 0x01000000 )
1352cdf0e10cSrcweir                 fprintf( stderr, "native type: %s\n", OUStringToOString( getString( *pAtoms ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1353cdf0e10cSrcweir #endif
1354cdf0e10cSrcweir             if( *pAtoms == m_nCOMPOUNDAtom )
1355cdf0e10cSrcweir                 bHaveText = bHaveCompound = true;
1356cdf0e10cSrcweir 			else if( *pAtoms && *pAtoms < 0x01000000 )
1357cdf0e10cSrcweir 			{
1358cdf0e10cSrcweir                 int nFormat;
1359cdf0e10cSrcweir 				pFlavors->MimeType = convertTypeFromNative( *pAtoms, selection, nFormat );
1360cdf0e10cSrcweir 				pFlavors->DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
1361cdf0e10cSrcweir                 sal_Int32 nIndex = 0;
1362cdf0e10cSrcweir 				if( pFlavors->MimeType.getToken( 0, ';', nIndex ).equalsAsciiL( "text/plain", 10 ) )
1363cdf0e10cSrcweir 				{
1364cdf0e10cSrcweir                     OUString aToken(pFlavors->MimeType.getToken( 0, ';', nIndex ));
1365cdf0e10cSrcweir                     // omit text/plain;charset=unicode since it is not well defined
1366cdf0e10cSrcweir 					if( aToken.compareToAscii( "charset=unicode" ) == 0 )
1367cdf0e10cSrcweir                     {
1368cdf0e10cSrcweir                         pAtoms++;
1369cdf0e10cSrcweir                         continue;
1370cdf0e10cSrcweir                     }
1371cdf0e10cSrcweir 					bHaveText = true;
1372cdf0e10cSrcweir 					if( aToken.compareToAscii( "charset=utf-16" ) == 0 )
1373cdf0e10cSrcweir 					{
1374cdf0e10cSrcweir 						bHaveUTF16 = true;
1375cdf0e10cSrcweir 						pFlavors->DataType = getCppuType( (OUString*)0 );
1376cdf0e10cSrcweir 					}
1377cdf0e10cSrcweir 					else if( aToken.compareToAscii( "charset=utf-8" ) == 0 )
1378cdf0e10cSrcweir 					{
1379cdf0e10cSrcweir 					    aUTF8Type = *pAtoms;
1380cdf0e10cSrcweir 					}
1381cdf0e10cSrcweir 				}
1382cdf0e10cSrcweir                 pFlavors++;
1383cdf0e10cSrcweir                 aNativeTypes[ nNativeTypesIndex ] = *pAtoms;
1384cdf0e10cSrcweir                 nNativeTypesIndex++;
1385cdf0e10cSrcweir 			}
1386cdf0e10cSrcweir 			pAtoms++;
1387cdf0e10cSrcweir 		}
1388cdf0e10cSrcweir         if( (pFlavors - rTypes.getArray()) < rTypes.getLength() )
1389cdf0e10cSrcweir             rTypes.realloc(pFlavors - rTypes.getArray());
1390cdf0e10cSrcweir 		bSuccess = rTypes.getLength() ? true : false;
1391cdf0e10cSrcweir 		if( bHaveText && ! bHaveUTF16 )
1392cdf0e10cSrcweir 		{
1393cdf0e10cSrcweir                int i = 0;
1394cdf0e10cSrcweir 
1395cdf0e10cSrcweir 			int nNewFlavors = rTypes.getLength()+1;
1396cdf0e10cSrcweir 			Sequence< DataFlavor > aTemp( nNewFlavors );
1397cdf0e10cSrcweir 			for( i = 0; i < nNewFlavors-1; i++ )
1398cdf0e10cSrcweir 				aTemp.getArray()[i+1] = rTypes.getConstArray()[i];
1399cdf0e10cSrcweir 			aTemp.getArray()[0].MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
1400cdf0e10cSrcweir 			aTemp.getArray()[0].DataType = getCppuType( (OUString*)0 );
1401cdf0e10cSrcweir 			rTypes = aTemp;
1402cdf0e10cSrcweir 
1403cdf0e10cSrcweir 			std::vector< Atom > aNativeTemp( nNewFlavors );
1404cdf0e10cSrcweir 			for( i = 0; i < nNewFlavors-1; i++ )
1405cdf0e10cSrcweir 				aNativeTemp[ i + 1 ] = aNativeTypes[ i ];
1406cdf0e10cSrcweir 			aNativeTemp[0] = None;
1407cdf0e10cSrcweir 			aNativeTypes = aNativeTemp;
1408cdf0e10cSrcweir 		}
1409cdf0e10cSrcweir 	}
1410cdf0e10cSrcweir 
1411cdf0e10cSrcweir 	{
1412cdf0e10cSrcweir 		MutexGuard aGuard(m_aMutex);
1413cdf0e10cSrcweir 
1414cdf0e10cSrcweir 		it = m_aSelections.find( selection );
1415cdf0e10cSrcweir 		if( it != m_aSelections.end() )
1416cdf0e10cSrcweir 		{
1417cdf0e10cSrcweir 			if( bSuccess )
1418cdf0e10cSrcweir 			{
1419cdf0e10cSrcweir 				it->second->m_aTypes			= rTypes;
1420cdf0e10cSrcweir                 it->second->m_aNativeTypes		= aNativeTypes;
1421cdf0e10cSrcweir 				it->second->m_nLastTimestamp	= time( NULL );
1422cdf0e10cSrcweir 				it->second->m_bHaveUTF16		= bHaveUTF16;
1423cdf0e10cSrcweir 				it->second->m_aUTF8Type         = aUTF8Type;
1424cdf0e10cSrcweir                 it->second->m_bHaveCompound		= bHaveCompound;
1425cdf0e10cSrcweir 			}
1426cdf0e10cSrcweir 			else
1427cdf0e10cSrcweir 			{
1428cdf0e10cSrcweir 				it->second->m_aTypes			= Sequence< DataFlavor >();
1429cdf0e10cSrcweir 				it->second->m_aNativeTypes		= std::vector< Atom >();
1430cdf0e10cSrcweir 				it->second->m_nLastTimestamp	= 0;
1431cdf0e10cSrcweir 				it->second->m_bHaveUTF16		= false;
1432cdf0e10cSrcweir 				it->second->m_aUTF8Type         = None;
1433cdf0e10cSrcweir                 it->second->m_bHaveCompound		= false;
1434cdf0e10cSrcweir 			}
1435cdf0e10cSrcweir 		}
1436cdf0e10cSrcweir 	}
1437cdf0e10cSrcweir 
1438cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1439cdf0e10cSrcweir //    if( selection != m_nCLIPBOARDAtom )
1440cdf0e10cSrcweir     {
1441cdf0e10cSrcweir         fprintf( stderr, "SelectionManager::getPasteDataTypes( %s ) = %s\n", OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(), bSuccess ? "true" : "false" );
1442cdf0e10cSrcweir         for( int i = 0; i < rTypes.getLength(); i++ )
1443cdf0e10cSrcweir             fprintf( stderr, "type: %s\n", OUStringToOString( rTypes.getConstArray()[i].MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1444cdf0e10cSrcweir     }
1445cdf0e10cSrcweir #endif
1446cdf0e10cSrcweir 
1447cdf0e10cSrcweir 	return bSuccess;
1448cdf0e10cSrcweir }
1449cdf0e10cSrcweir 
1450cdf0e10cSrcweir // ------------------------------------------------------------------------
1451cdf0e10cSrcweir 
getPixmapHolder(Atom selection)1452cdf0e10cSrcweir PixmapHolder* SelectionManager::getPixmapHolder( Atom selection )
1453cdf0e10cSrcweir {
1454cdf0e10cSrcweir     std::hash_map< Atom, Selection* >::const_iterator it = m_aSelections.find( selection );
1455cdf0e10cSrcweir     if( it == m_aSelections.end() )
1456cdf0e10cSrcweir         return NULL;
1457cdf0e10cSrcweir     if( ! it->second->m_pPixmap )
1458cdf0e10cSrcweir         it->second->m_pPixmap = new PixmapHolder( m_pDisplay );
1459cdf0e10cSrcweir     return it->second->m_pPixmap;
1460cdf0e10cSrcweir }
1461cdf0e10cSrcweir 
GetTrueFormatSize(int nFormat)1462cdf0e10cSrcweir static sal_Size GetTrueFormatSize(int nFormat)
1463cdf0e10cSrcweir {
1464cdf0e10cSrcweir 	// http://mail.gnome.org/archives/wm-spec-list/2003-March/msg00067.html
1465cdf0e10cSrcweir 	return nFormat == 32 ? sizeof(long) : nFormat/8;
1466cdf0e10cSrcweir }
1467cdf0e10cSrcweir 
sendData(SelectionAdaptor * pAdaptor,XLIB_Window requestor,Atom target,Atom property,Atom selection)1468cdf0e10cSrcweir bool SelectionManager::sendData( SelectionAdaptor* pAdaptor,
1469cdf0e10cSrcweir                                  XLIB_Window requestor,
1470cdf0e10cSrcweir                                  Atom target,
1471cdf0e10cSrcweir                                  Atom property,
1472cdf0e10cSrcweir                                  Atom selection )
1473cdf0e10cSrcweir {
1474cdf0e10cSrcweir     ResettableMutexGuard aGuard( m_aMutex );
1475cdf0e10cSrcweir 
1476cdf0e10cSrcweir     // handle targets related to image/bmp
1477cdf0e10cSrcweir     if( target == XA_COLORMAP || target == XA_PIXMAP || target == XA_BITMAP || target == XA_VISUALID )
1478cdf0e10cSrcweir     {
1479cdf0e10cSrcweir         PixmapHolder* pPixmap = getPixmapHolder( selection );
1480cdf0e10cSrcweir         if( ! pPixmap ) return false;
1481cdf0e10cSrcweir         XID nValue = None;
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir         // handle colormap request
1484cdf0e10cSrcweir         if( target == XA_COLORMAP )
1485cdf0e10cSrcweir             nValue = (XID)pPixmap->getColormap();
1486cdf0e10cSrcweir         else if( target == XA_VISUALID )
1487cdf0e10cSrcweir             nValue = (XID)pPixmap->getVisualID();
1488cdf0e10cSrcweir         else if( target == XA_PIXMAP || target == XA_BITMAP )
1489cdf0e10cSrcweir         {
1490cdf0e10cSrcweir             nValue = (XID)pPixmap->getPixmap();
1491cdf0e10cSrcweir             if( nValue == None )
1492cdf0e10cSrcweir             {
1493cdf0e10cSrcweir                 // first conversion
1494cdf0e10cSrcweir                 Sequence< sal_Int8 > aData;
1495cdf0e10cSrcweir                 int nFormat;
1496cdf0e10cSrcweir                 aGuard.clear();
1497cdf0e10cSrcweir                 bool bConverted = convertData( pAdaptor->getTransferable(), target, selection, nFormat, aData );
1498cdf0e10cSrcweir                 aGuard.reset();
1499cdf0e10cSrcweir                 if( bConverted )
1500cdf0e10cSrcweir                 {
1501cdf0e10cSrcweir 				    // get pixmap again since clearing the guard could have invalidated
1502cdf0e10cSrcweir 					// the pixmap in another thread
1503cdf0e10cSrcweir         			pPixmap = getPixmapHolder( selection );
1504cdf0e10cSrcweir                     // conversion succeeded, so aData contains image/bmp now
1505cdf0e10cSrcweir                     if( pPixmap->needsConversion( (const sal_uInt8*)aData.getConstArray() )
1506cdf0e10cSrcweir                         && m_xBitmapConverter.is() )
1507cdf0e10cSrcweir                     {
1508cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1509cdf0e10cSrcweir                         fprintf( stderr, "trying bitmap conversion\n" );
1510cdf0e10cSrcweir #endif
1511cdf0e10cSrcweir                         css::uno::Reference<XBitmap> xBM( new BmpTransporter( aData ) );
1512cdf0e10cSrcweir                         Sequence<Any> aArgs(2), aOutArgs;
1513cdf0e10cSrcweir                         Sequence<sal_Int16> aOutIndex;
1514cdf0e10cSrcweir                         aArgs.getArray()[0] = makeAny( xBM );
1515cdf0e10cSrcweir                         aArgs.getArray()[1] = makeAny( (sal_uInt16)pPixmap->getDepth() );
1516cdf0e10cSrcweir                         aGuard.clear();
1517cdf0e10cSrcweir                         try
1518cdf0e10cSrcweir                         {
1519cdf0e10cSrcweir                             Any aResult =
1520cdf0e10cSrcweir                                 m_xBitmapConverter->invoke( OUString::createFromAscii( "convert-bitmap-depth" ),
1521cdf0e10cSrcweir                                                             aArgs, aOutIndex, aOutArgs );
1522cdf0e10cSrcweir                             if( aResult >>= xBM )
1523cdf0e10cSrcweir                                 aData = xBM->getDIB();
1524cdf0e10cSrcweir                         }
1525cdf0e10cSrcweir                         catch(...)
1526cdf0e10cSrcweir                         {
1527cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1528cdf0e10cSrcweir                             fprintf( stderr, "exception in bitmap converter\n" );
1529cdf0e10cSrcweir #endif
1530cdf0e10cSrcweir                         }
1531cdf0e10cSrcweir                         aGuard.reset();
1532cdf0e10cSrcweir                     }
1533cdf0e10cSrcweir 				    // get pixmap again since clearing the guard could have invalidated
1534cdf0e10cSrcweir 					// the pixmap in another thread
1535cdf0e10cSrcweir         			pPixmap = getPixmapHolder( selection );
1536cdf0e10cSrcweir                     nValue = (XID)pPixmap->setBitmapData( (const sal_uInt8*)aData.getConstArray() );
1537cdf0e10cSrcweir                 }
1538cdf0e10cSrcweir                 if( nValue == None )
1539cdf0e10cSrcweir                     return false;
1540cdf0e10cSrcweir             }
1541cdf0e10cSrcweir             if( target == XA_BITMAP )
1542cdf0e10cSrcweir                 nValue = (XID)pPixmap->getBitmap();
1543cdf0e10cSrcweir         }
1544cdf0e10cSrcweir 
1545cdf0e10cSrcweir         XChangeProperty( m_pDisplay,
1546cdf0e10cSrcweir                          requestor,
1547cdf0e10cSrcweir                          property,
1548cdf0e10cSrcweir                          target,
1549cdf0e10cSrcweir                          32,
1550cdf0e10cSrcweir                          PropModeReplace,
1551cdf0e10cSrcweir                          (const unsigned char*)&nValue,
1552cdf0e10cSrcweir                          1);
1553cdf0e10cSrcweir         return true;
1554cdf0e10cSrcweir     }
1555cdf0e10cSrcweir 
1556cdf0e10cSrcweir     /*
1557cdf0e10cSrcweir      *  special target TEXT allows us to transfer
1558cdf0e10cSrcweir      *  the data in an encoding of our choice
1559cdf0e10cSrcweir      *  COMPOUND_TEXT will work with most applications
1560cdf0e10cSrcweir      */
1561cdf0e10cSrcweir     if( target == m_nTEXTAtom )
1562cdf0e10cSrcweir         target = m_nCOMPOUNDAtom;
1563cdf0e10cSrcweir 
1564cdf0e10cSrcweir     Sequence< sal_Int8 > aData;
1565cdf0e10cSrcweir     int nFormat;
1566cdf0e10cSrcweir     aGuard.clear();
1567cdf0e10cSrcweir     bool bConverted = convertData( pAdaptor->getTransferable(), target, selection, nFormat, aData );
1568cdf0e10cSrcweir     aGuard.reset();
1569cdf0e10cSrcweir     if( bConverted )
1570cdf0e10cSrcweir     {
1571cdf0e10cSrcweir         // conversion succeeded
1572cdf0e10cSrcweir         if( aData.getLength() > m_nIncrementalThreshold )
1573cdf0e10cSrcweir         {
1574cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1575cdf0e10cSrcweir             fprintf( stderr, "using INCR protocol\n" );
1576cdf0e10cSrcweir             std::hash_map< XLIB_Window, std::hash_map< Atom, IncrementalTransfer > >::const_iterator win_it = m_aIncrementals.find( requestor );
1577cdf0e10cSrcweir             if( win_it != m_aIncrementals.end() )
1578cdf0e10cSrcweir             {
1579cdf0e10cSrcweir                 std::hash_map< Atom, IncrementalTransfer >::const_iterator inc_it = win_it->second.find( property );
1580cdf0e10cSrcweir                 if( inc_it != win_it->second.end() )
1581cdf0e10cSrcweir                 {
1582cdf0e10cSrcweir                     const IncrementalTransfer& rInc = inc_it->second;
1583cdf0e10cSrcweir                     fprintf( stderr, "premature end and new start for INCR transfer for window 0x%lx, property %s, type %s\n",
1584cdf0e10cSrcweir                              rInc.m_aRequestor,
1585cdf0e10cSrcweir                              OUStringToOString( getString( rInc.m_aProperty ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1586cdf0e10cSrcweir                              OUStringToOString( getString( rInc.m_aTarget ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
1587cdf0e10cSrcweir                              );
1588cdf0e10cSrcweir                 }
1589cdf0e10cSrcweir             }
1590cdf0e10cSrcweir #endif
1591cdf0e10cSrcweir 
1592cdf0e10cSrcweir             // insert IncrementalTransfer
1593cdf0e10cSrcweir             IncrementalTransfer& rInc	= m_aIncrementals[ requestor ][ property ];
1594cdf0e10cSrcweir             rInc.m_aData				= aData;
1595cdf0e10cSrcweir             rInc.m_nBufferPos			= 0;
1596cdf0e10cSrcweir             rInc.m_aRequestor			= requestor;
1597cdf0e10cSrcweir             rInc.m_aProperty			= property;
1598cdf0e10cSrcweir             rInc.m_aTarget				= target;
1599cdf0e10cSrcweir             rInc.m_nFormat				= nFormat;
1600cdf0e10cSrcweir             rInc.m_nTransferStartTime	= time( NULL );
1601cdf0e10cSrcweir 
1602cdf0e10cSrcweir             // use incr protocol, signal start to requestor
1603cdf0e10cSrcweir             long nMinSize = m_nIncrementalThreshold;
1604cdf0e10cSrcweir             XSelectInput( m_pDisplay, requestor, PropertyChangeMask );
1605cdf0e10cSrcweir             XChangeProperty( m_pDisplay, requestor, property,
1606cdf0e10cSrcweir                              m_nINCRAtom, 32,  PropModeReplace, (unsigned char*)&nMinSize, 1 );
1607cdf0e10cSrcweir             XFlush( m_pDisplay );
1608cdf0e10cSrcweir         }
1609cdf0e10cSrcweir         else
1610cdf0e10cSrcweir         {
1611cdf0e10cSrcweir             sal_Size nUnitSize = GetTrueFormatSize(nFormat);
1612cdf0e10cSrcweir             XChangeProperty( m_pDisplay,
1613cdf0e10cSrcweir                              requestor,
1614cdf0e10cSrcweir                              property,
1615cdf0e10cSrcweir                              target,
1616cdf0e10cSrcweir                              nFormat,
1617cdf0e10cSrcweir                              PropModeReplace,
1618cdf0e10cSrcweir                              (const unsigned char*)aData.getConstArray(),
1619cdf0e10cSrcweir                              aData.getLength()/nUnitSize );
1620cdf0e10cSrcweir             }
1621cdf0e10cSrcweir     }
1622cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1623cdf0e10cSrcweir     else
1624cdf0e10cSrcweir         fprintf( stderr, "convertData failed for type: %s \n",
1625cdf0e10cSrcweir                  OUStringToOString( convertTypeFromNative( target, selection, nFormat ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1626cdf0e10cSrcweir #endif
1627cdf0e10cSrcweir     return bConverted;
1628cdf0e10cSrcweir }
1629cdf0e10cSrcweir 
1630cdf0e10cSrcweir // ------------------------------------------------------------------------
1631cdf0e10cSrcweir 
handleSelectionRequest(XSelectionRequestEvent & rRequest)1632cdf0e10cSrcweir bool SelectionManager::handleSelectionRequest( XSelectionRequestEvent& rRequest )
1633cdf0e10cSrcweir {
1634cdf0e10cSrcweir     ResettableMutexGuard aGuard( m_aMutex );
1635cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1636cdf0e10cSrcweir 	fprintf( stderr, "handleSelectionRequest for selection %s and target %s\n",
1637cdf0e10cSrcweir 			 OUStringToOString( getString( rRequest.selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1638cdf0e10cSrcweir 			 OUStringToOString( getString( rRequest.target ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
1639cdf0e10cSrcweir 			 );
1640cdf0e10cSrcweir #endif
1641cdf0e10cSrcweir 
1642cdf0e10cSrcweir 	XEvent aNotify;
1643cdf0e10cSrcweir 
1644cdf0e10cSrcweir 	aNotify.type                  = SelectionNotify;
1645cdf0e10cSrcweir 	aNotify.xselection.display    = rRequest.display;
1646cdf0e10cSrcweir 	aNotify.xselection.send_event = True;
1647cdf0e10cSrcweir 	aNotify.xselection.requestor  = rRequest.requestor;
1648cdf0e10cSrcweir 	aNotify.xselection.selection  = rRequest.selection;
1649cdf0e10cSrcweir 	aNotify.xselection.time       = rRequest.time;
1650cdf0e10cSrcweir 	aNotify.xselection.target     = rRequest.target;
1651cdf0e10cSrcweir 	aNotify.xselection.property   = None;
1652cdf0e10cSrcweir 
1653cdf0e10cSrcweir 	SelectionAdaptor* pAdaptor = getAdaptor( rRequest.selection );
1654cdf0e10cSrcweir 	// ensure that we still own that selection
1655cdf0e10cSrcweir 	if( pAdaptor &&
1656cdf0e10cSrcweir 		XGetSelectionOwner( m_pDisplay, rRequest.selection ) == m_aWindow )
1657cdf0e10cSrcweir 	{
1658cdf0e10cSrcweir         css::uno::Reference< XTransferable > xTrans( pAdaptor->getTransferable() );
1659cdf0e10cSrcweir 		if( rRequest.target == m_nTARGETSAtom )
1660cdf0e10cSrcweir 		{
1661cdf0e10cSrcweir 			// someone requests our types
1662cdf0e10cSrcweir 			if( xTrans.is() )
1663cdf0e10cSrcweir 			{
1664cdf0e10cSrcweir                 aGuard.clear();
1665cdf0e10cSrcweir 				Sequence< DataFlavor > aFlavors = xTrans->getTransferDataFlavors();
1666cdf0e10cSrcweir                 aGuard.reset();
1667cdf0e10cSrcweir 
1668cdf0e10cSrcweir                 ::std::list< Atom > aConversions;
1669cdf0e10cSrcweir                 getNativeTypeList( aFlavors, aConversions, rRequest.selection );
1670cdf0e10cSrcweir 
1671cdf0e10cSrcweir                 int i, nTypes = aConversions.size();
1672cdf0e10cSrcweir 				Atom* pTypes = (Atom*)alloca( nTypes * sizeof( Atom ) );
1673cdf0e10cSrcweir                 std::list< Atom >::const_iterator it;
1674cdf0e10cSrcweir 				for( i = 0, it = aConversions.begin(); i < nTypes; i++, ++it )
1675cdf0e10cSrcweir 					pTypes[i] = *it;
1676cdf0e10cSrcweir 				XChangeProperty( m_pDisplay, rRequest.requestor, rRequest.property,
1677cdf0e10cSrcweir 								 XA_ATOM, 32, PropModeReplace, (const unsigned char*)pTypes, nTypes );
1678cdf0e10cSrcweir 				aNotify.xselection.property = rRequest.property;
1679cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1680cdf0e10cSrcweir                 fprintf( stderr, "sending type list:\n" );
1681cdf0e10cSrcweir                 for( int k = 0; k < nTypes; k++ )
1682cdf0e10cSrcweir                     fprintf( stderr, "   %s\n", pTypes[k] ? XGetAtomName( m_pDisplay, pTypes[k] ) : "<None>" );
1683cdf0e10cSrcweir #endif
1684cdf0e10cSrcweir 			}
1685cdf0e10cSrcweir 		}
1686cdf0e10cSrcweir         else if( rRequest.target == m_nTIMESTAMPAtom )
1687cdf0e10cSrcweir         {
1688cdf0e10cSrcweir             long nTimeStamp = (long)m_aSelections[rRequest.selection]->m_nOrigTimestamp;
1689cdf0e10cSrcweir             XChangeProperty( m_pDisplay, rRequest.requestor, rRequest.property,
1690cdf0e10cSrcweir                              XA_INTEGER, 32, PropModeReplace, (const unsigned char*)&nTimeStamp, 1 );
1691cdf0e10cSrcweir             aNotify.xselection.property = rRequest.property;
1692cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1693cdf0e10cSrcweir                 fprintf( stderr, "sending timestamp: %d\n", (int)nTimeStamp );
1694cdf0e10cSrcweir #endif
1695cdf0e10cSrcweir         }
1696cdf0e10cSrcweir 		else
1697cdf0e10cSrcweir 		{
1698cdf0e10cSrcweir             bool bEventSuccess = false;
1699cdf0e10cSrcweir             if( rRequest.target == m_nMULTIPLEAtom )
1700cdf0e10cSrcweir             {
1701cdf0e10cSrcweir                 // get all targets
1702cdf0e10cSrcweir                 Atom nType = None;
1703cdf0e10cSrcweir                 int nFormat = 0;
1704cdf0e10cSrcweir                 unsigned long nItems = 0, nBytes = 0;
1705cdf0e10cSrcweir                 unsigned char* pData = NULL;
1706cdf0e10cSrcweir 
1707cdf0e10cSrcweir                 // get number of atoms
1708cdf0e10cSrcweir                 XGetWindowProperty( m_pDisplay,
1709cdf0e10cSrcweir                                     rRequest.requestor,
1710cdf0e10cSrcweir                                     rRequest.property,
1711cdf0e10cSrcweir                                     0, 0,
1712cdf0e10cSrcweir                                     False,
1713cdf0e10cSrcweir                                     AnyPropertyType,
1714cdf0e10cSrcweir                                     &nType, &nFormat,
1715cdf0e10cSrcweir                                     &nItems, &nBytes,
1716cdf0e10cSrcweir                                     &pData );
1717cdf0e10cSrcweir                 if( nFormat == 32 && nBytes/4 )
1718cdf0e10cSrcweir                 {
1719cdf0e10cSrcweir                     if( pData ) // ?? should not happen
1720cdf0e10cSrcweir                     {
1721cdf0e10cSrcweir                         XFree( pData );
1722cdf0e10cSrcweir                         pData = NULL;
1723cdf0e10cSrcweir                     }
1724cdf0e10cSrcweir                     XGetWindowProperty( m_pDisplay,
1725cdf0e10cSrcweir                                         rRequest.requestor,
1726cdf0e10cSrcweir                                         rRequest.property,
1727cdf0e10cSrcweir                                         0, nBytes/4,
1728cdf0e10cSrcweir                                         False,
1729cdf0e10cSrcweir                                         nType,
1730cdf0e10cSrcweir                                         &nType, &nFormat,
1731cdf0e10cSrcweir                                         &nItems, &nBytes,
1732cdf0e10cSrcweir                                         &pData );
1733cdf0e10cSrcweir                     if( pData && nItems )
1734cdf0e10cSrcweir                     {
1735cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1736cdf0e10cSrcweir                         fprintf( stderr, "found %ld atoms in MULTIPLE request\n", nItems );
1737cdf0e10cSrcweir #endif
1738cdf0e10cSrcweir                         bEventSuccess = true;
1739cdf0e10cSrcweir                         bool bResetAtoms = false;
1740cdf0e10cSrcweir                         Atom* pAtoms = (Atom*)pData;
1741cdf0e10cSrcweir                         aGuard.clear();
1742cdf0e10cSrcweir                         for( unsigned int i = 0; i < nItems; i += 2 )
1743cdf0e10cSrcweir                         {
1744cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1745cdf0e10cSrcweir                             fprintf( stderr, "   %s => %s: ",
1746cdf0e10cSrcweir                                      OUStringToOString( getString( pAtoms[i] ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1747cdf0e10cSrcweir                                      OUStringToOString( getString( pAtoms[i+1] ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1748cdf0e10cSrcweir #endif
1749cdf0e10cSrcweir                             bool bSuccess = sendData( pAdaptor, rRequest.requestor, pAtoms[i], pAtoms[i+1], rRequest.selection );
1750cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1751cdf0e10cSrcweir                             fprintf( stderr, "%s\n", bSuccess ? "succeeded" : "failed" );
1752cdf0e10cSrcweir #endif
1753cdf0e10cSrcweir                             if( ! bSuccess )
1754cdf0e10cSrcweir                             {
1755cdf0e10cSrcweir                                 pAtoms[i] = None;
1756cdf0e10cSrcweir                                 bResetAtoms = true;
1757cdf0e10cSrcweir                             }
1758cdf0e10cSrcweir                         }
1759cdf0e10cSrcweir                         aGuard.reset();
1760cdf0e10cSrcweir                         if( bResetAtoms )
1761cdf0e10cSrcweir                             XChangeProperty( m_pDisplay,
1762cdf0e10cSrcweir                                              rRequest.requestor,
1763cdf0e10cSrcweir                                              rRequest.property,
1764cdf0e10cSrcweir                                              XA_ATOM,
1765cdf0e10cSrcweir                                              32,
1766cdf0e10cSrcweir                                              PropModeReplace,
1767cdf0e10cSrcweir                                              pData,
1768cdf0e10cSrcweir                                              nBytes/4 );
1769cdf0e10cSrcweir                     }
1770cdf0e10cSrcweir                     if( pData )
1771cdf0e10cSrcweir                         XFree( pData );
1772cdf0e10cSrcweir                 }
1773cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1774cdf0e10cSrcweir                 else
1775cdf0e10cSrcweir                 {
1776cdf0e10cSrcweir                     fprintf( stderr, "could not get type list from \"%s\" of type \"%s\" on requestor 0x%lx, requestor has properties:",
1777cdf0e10cSrcweir                              OUStringToOString( getString( rRequest.property ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1778cdf0e10cSrcweir                              OUStringToOString( getString( nType ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1779cdf0e10cSrcweir                              rRequest.requestor );
1780cdf0e10cSrcweir                     int nProps = 0;
1781cdf0e10cSrcweir                     Atom* pProps = XListProperties( m_pDisplay, rRequest.requestor, &nProps );
1782cdf0e10cSrcweir                     if( pProps )
1783cdf0e10cSrcweir                     {
1784cdf0e10cSrcweir                         for( int i = 0; i < nProps; i++ )
1785cdf0e10cSrcweir                             fprintf( stderr, " \"%s\"", OUStringToOString( getString( pProps[i]), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1786cdf0e10cSrcweir                         XFree( pProps );
1787cdf0e10cSrcweir                     }
1788cdf0e10cSrcweir                 }
1789cdf0e10cSrcweir #endif
1790cdf0e10cSrcweir             }
1791cdf0e10cSrcweir             else
1792cdf0e10cSrcweir             {
1793cdf0e10cSrcweir                 aGuard.clear();
1794cdf0e10cSrcweir                 bEventSuccess = sendData( pAdaptor, rRequest.requestor, rRequest.target, rRequest.property, rRequest.selection );
1795cdf0e10cSrcweir                 aGuard.reset();
1796cdf0e10cSrcweir             }
1797cdf0e10cSrcweir             if( bEventSuccess )
1798cdf0e10cSrcweir             {
1799cdf0e10cSrcweir                 aNotify.xselection.target = rRequest.target;
1800cdf0e10cSrcweir                 aNotify.xselection.property = rRequest.property;
1801cdf0e10cSrcweir             }
1802cdf0e10cSrcweir 		}
1803cdf0e10cSrcweir         aGuard.clear();
1804cdf0e10cSrcweir         xTrans.clear();
1805cdf0e10cSrcweir         aGuard.reset();
1806cdf0e10cSrcweir 	}
1807cdf0e10cSrcweir 	XSendEvent( m_pDisplay, rRequest.requestor, False, 0, &aNotify );
1808cdf0e10cSrcweir 
1809cdf0e10cSrcweir 	if( rRequest.selection == XA_PRIMARY	&&
1810cdf0e10cSrcweir 		m_bWaitingForPrimaryConversion		&&
1811cdf0e10cSrcweir 		m_xDragSourceListener.is() )
1812cdf0e10cSrcweir 	{
1813cdf0e10cSrcweir 		DragSourceDropEvent dsde;
1814cdf0e10cSrcweir 		dsde.Source					= static_cast< OWeakObject* >(this);
1815cdf0e10cSrcweir 		dsde.DragSourceContext		= new DragSourceContext( m_aDropWindow, rRequest.time, *this );
1816cdf0e10cSrcweir 		dsde.DragSource				= static_cast< XDragSource* >(this);
1817cdf0e10cSrcweir 		if( aNotify.xselection.property != None )
1818cdf0e10cSrcweir 		{
1819cdf0e10cSrcweir 			dsde.DropAction			= DNDConstants::ACTION_COPY;
1820cdf0e10cSrcweir 			dsde.DropSuccess		= sal_True;
1821cdf0e10cSrcweir 		}
1822cdf0e10cSrcweir 		else
1823cdf0e10cSrcweir 		{
1824cdf0e10cSrcweir 			dsde.DropAction			= DNDConstants::ACTION_NONE;
1825cdf0e10cSrcweir 			dsde.DropSuccess		= sal_False;
1826cdf0e10cSrcweir 		}
1827cdf0e10cSrcweir         css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
1828cdf0e10cSrcweir 		m_xDragSourceListener.clear();
1829cdf0e10cSrcweir         aGuard.clear();
1830cdf0e10cSrcweir         if( xListener.is() )
1831cdf0e10cSrcweir             xListener->dragDropEnd( dsde );
1832cdf0e10cSrcweir 	}
1833cdf0e10cSrcweir 
1834cdf0e10cSrcweir     // we handled the event in any case by answering
1835cdf0e10cSrcweir     return true;
1836cdf0e10cSrcweir }
1837cdf0e10cSrcweir 
1838cdf0e10cSrcweir // ------------------------------------------------------------------------
1839cdf0e10cSrcweir 
handleReceivePropertyNotify(XPropertyEvent & rNotify)1840cdf0e10cSrcweir bool SelectionManager::handleReceivePropertyNotify( XPropertyEvent& rNotify )
1841cdf0e10cSrcweir {
1842cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
1843cdf0e10cSrcweir 	// data we requested arrived
1844cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1845cdf0e10cSrcweir 	fprintf( stderr, "handleReceivePropertyNotify for property %s\n",
1846cdf0e10cSrcweir 			 OUStringToOString( getString( rNotify.atom ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
1847cdf0e10cSrcweir #endif
1848cdf0e10cSrcweir     bool bHandled = false;
1849cdf0e10cSrcweir 
1850cdf0e10cSrcweir 	::std::hash_map< Atom, Selection* >::iterator it =
1851cdf0e10cSrcweir 		  m_aSelections.find( rNotify.atom );
1852cdf0e10cSrcweir 	if( it != m_aSelections.end() &&
1853cdf0e10cSrcweir 		rNotify.state == PropertyNewValue &&
1854cdf0e10cSrcweir 		( it->second->m_eState == Selection::WaitingForResponse		||
1855cdf0e10cSrcweir 		  it->second->m_eState == Selection::WaitingForData 		||
1856cdf0e10cSrcweir 		  it->second->m_eState == Selection::IncrementalTransfer
1857cdf0e10cSrcweir 		  )
1858cdf0e10cSrcweir 		)
1859cdf0e10cSrcweir 	{
1860cdf0e10cSrcweir         // MULTIPLE requests are only complete after selection notify
1861cdf0e10cSrcweir         if( it->second->m_aRequestedType == m_nMULTIPLEAtom &&
1862cdf0e10cSrcweir             ( it->second->m_eState == Selection::WaitingForResponse ||
1863cdf0e10cSrcweir               it->second->m_eState == Selection::WaitingForData ) )
1864cdf0e10cSrcweir             return false;
1865cdf0e10cSrcweir 
1866cdf0e10cSrcweir         bHandled = true;
1867cdf0e10cSrcweir 
1868cdf0e10cSrcweir 		Atom nType = None;
1869cdf0e10cSrcweir 		int nFormat = 0;
1870cdf0e10cSrcweir 		unsigned long nItems = 0, nBytes = 0;
1871cdf0e10cSrcweir 		unsigned char* pData = NULL;
1872cdf0e10cSrcweir 
1873cdf0e10cSrcweir 		// get type and length
1874cdf0e10cSrcweir 		XGetWindowProperty( m_pDisplay,
1875cdf0e10cSrcweir 							rNotify.window,
1876cdf0e10cSrcweir 							rNotify.atom,
1877cdf0e10cSrcweir 							0, 0,
1878cdf0e10cSrcweir 							False,
1879cdf0e10cSrcweir 							AnyPropertyType,
1880cdf0e10cSrcweir 							&nType, &nFormat,
1881cdf0e10cSrcweir 							&nItems, &nBytes,
1882cdf0e10cSrcweir 							&pData );
1883cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1884cdf0e10cSrcweir 		fprintf( stderr, "found %ld bytes data of type %s and format %d, items = %ld\n",
1885cdf0e10cSrcweir 				 nBytes,
1886cdf0e10cSrcweir 				 OUStringToOString( getString( nType ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1887cdf0e10cSrcweir 				 nFormat, nItems );
1888cdf0e10cSrcweir #endif
1889cdf0e10cSrcweir 		if( pData )
1890cdf0e10cSrcweir 		{
1891cdf0e10cSrcweir 			XFree( pData );
1892cdf0e10cSrcweir 			pData = NULL;
1893cdf0e10cSrcweir 		}
1894cdf0e10cSrcweir 
1895cdf0e10cSrcweir 		if( nType == m_nINCRAtom )
1896cdf0e10cSrcweir 		{
1897cdf0e10cSrcweir 			// start data transfer
1898cdf0e10cSrcweir 			XDeleteProperty( m_pDisplay, rNotify.window, rNotify.atom );
1899cdf0e10cSrcweir 			it->second->m_eState = Selection::IncrementalTransfer;
1900cdf0e10cSrcweir 		}
1901cdf0e10cSrcweir 		else if( nType != None )
1902cdf0e10cSrcweir 		{
1903cdf0e10cSrcweir 			XGetWindowProperty( m_pDisplay,
1904cdf0e10cSrcweir 								rNotify.window,
1905cdf0e10cSrcweir 								rNotify.atom,
1906cdf0e10cSrcweir 								0, nBytes/4 +1,
1907cdf0e10cSrcweir 								True,
1908cdf0e10cSrcweir 								nType,
1909cdf0e10cSrcweir 								&nType, &nFormat,
1910cdf0e10cSrcweir 								&nItems, &nBytes,
1911cdf0e10cSrcweir 								&pData );
1912cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1913cdf0e10cSrcweir 			fprintf( stderr, "read %ld items data of type %s and format %d, %ld bytes left in property\n",
1914cdf0e10cSrcweir 					 nItems,
1915cdf0e10cSrcweir 					 OUStringToOString( getString( nType ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1916cdf0e10cSrcweir 					 nFormat, nBytes );
1917cdf0e10cSrcweir #endif
1918cdf0e10cSrcweir 
1919cdf0e10cSrcweir 			sal_Size nUnitSize = GetTrueFormatSize(nFormat);
1920cdf0e10cSrcweir 
1921cdf0e10cSrcweir 			if( it->second->m_eState == Selection::WaitingForData ||
1922cdf0e10cSrcweir 				it->second->m_eState == Selection::WaitingForResponse )
1923cdf0e10cSrcweir 			{
1924cdf0e10cSrcweir 				// copy data
1925cdf0e10cSrcweir 				it->second->m_aData = Sequence< sal_Int8 >( (sal_Int8*)pData, nItems*nUnitSize );
1926cdf0e10cSrcweir 				it->second->m_eState = Selection::Inactive;
1927cdf0e10cSrcweir 				it->second->m_aDataArrived.set();
1928cdf0e10cSrcweir 			}
1929cdf0e10cSrcweir 			else if( it->second->m_eState == Selection::IncrementalTransfer )
1930cdf0e10cSrcweir 			{
1931cdf0e10cSrcweir                 if( nItems )
1932cdf0e10cSrcweir                 {
1933cdf0e10cSrcweir                     // append data
1934cdf0e10cSrcweir                     Sequence< sal_Int8 > aData( it->second->m_aData.getLength() + nItems*nUnitSize );
1935cdf0e10cSrcweir                     memcpy( aData.getArray(), it->second->m_aData.getArray(), it->second->m_aData.getLength() );
1936cdf0e10cSrcweir                     memcpy( aData.getArray() + it->second->m_aData.getLength(), pData, nItems*nUnitSize );
1937cdf0e10cSrcweir                     it->second->m_aData = aData;
1938cdf0e10cSrcweir                 }
1939cdf0e10cSrcweir                 else
1940cdf0e10cSrcweir                 {
1941cdf0e10cSrcweir                     it->second->m_eState = Selection::Inactive;
1942cdf0e10cSrcweir                     it->second->m_aDataArrived.set();
1943cdf0e10cSrcweir                 }
1944cdf0e10cSrcweir 			}
1945cdf0e10cSrcweir 			if( pData )
1946cdf0e10cSrcweir 				XFree( pData );
1947cdf0e10cSrcweir 		}
1948cdf0e10cSrcweir 		else if( it->second->m_eState == Selection::IncrementalTransfer )
1949cdf0e10cSrcweir 		{
1950cdf0e10cSrcweir 			it->second->m_eState = Selection::Inactive;
1951cdf0e10cSrcweir 			it->second->m_aDataArrived.set();
1952cdf0e10cSrcweir 		}
1953cdf0e10cSrcweir 	}
1954cdf0e10cSrcweir     return bHandled;
1955cdf0e10cSrcweir }
1956cdf0e10cSrcweir 
1957cdf0e10cSrcweir // ------------------------------------------------------------------------
1958cdf0e10cSrcweir 
handleSendPropertyNotify(XPropertyEvent & rNotify)1959cdf0e10cSrcweir bool SelectionManager::handleSendPropertyNotify( XPropertyEvent& rNotify )
1960cdf0e10cSrcweir {
1961cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
1962cdf0e10cSrcweir 
1963cdf0e10cSrcweir 	// ready for next part of a IncrementalTransfer
1964cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1965cdf0e10cSrcweir 	fprintf( stderr, "handleSendPropertyNotify for property %s (%s)\n",
1966cdf0e10cSrcweir 			 OUStringToOString( getString( rNotify.atom ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1967cdf0e10cSrcweir              rNotify.state == PropertyNewValue ? "new value" : ( rNotify.state == PropertyDelete ? "deleted" : "unknown")
1968cdf0e10cSrcweir              );
1969cdf0e10cSrcweir #endif
1970cdf0e10cSrcweir 
1971cdf0e10cSrcweir     bool bHandled = false;
1972cdf0e10cSrcweir     // feed incrementals
1973cdf0e10cSrcweir     if( rNotify.state == PropertyDelete )
1974cdf0e10cSrcweir     {
1975cdf0e10cSrcweir         std::hash_map< XLIB_Window, std::hash_map< Atom, IncrementalTransfer > >::iterator it;
1976cdf0e10cSrcweir         it = m_aIncrementals.find( rNotify.window );
1977cdf0e10cSrcweir         if( it != m_aIncrementals.end() )
1978cdf0e10cSrcweir         {
1979cdf0e10cSrcweir             bHandled = true;
1980cdf0e10cSrcweir             int nCurrentTime = time( NULL );
1981cdf0e10cSrcweir             std::hash_map< Atom, IncrementalTransfer >::iterator inc_it;
1982cdf0e10cSrcweir             // throw out aborted transfers
1983cdf0e10cSrcweir             std::list< Atom > aTimeouts;
1984cdf0e10cSrcweir             for( inc_it = it->second.begin(); inc_it != it->second.end(); ++inc_it )
1985cdf0e10cSrcweir             {
1986cdf0e10cSrcweir                 if( (nCurrentTime - inc_it->second.m_nTransferStartTime) > (getSelectionTimeout()+2) )
1987cdf0e10cSrcweir                 {
1988cdf0e10cSrcweir                     aTimeouts.push_back( inc_it->first );
1989cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1990cdf0e10cSrcweir                     const IncrementalTransfer& rInc = inc_it->second;
1991cdf0e10cSrcweir                     fprintf( stderr, "timeout on INCR transfer for window 0x%lx, property %s, type %s\n",
1992cdf0e10cSrcweir                              rInc.m_aRequestor,
1993cdf0e10cSrcweir                              OUStringToOString( getString( rInc.m_aProperty ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
1994cdf0e10cSrcweir                              OUStringToOString( getString( rInc.m_aTarget ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
1995cdf0e10cSrcweir                              );
1996cdf0e10cSrcweir #endif
1997cdf0e10cSrcweir                 }
1998cdf0e10cSrcweir             }
1999cdf0e10cSrcweir 
2000cdf0e10cSrcweir             while( aTimeouts.begin() != aTimeouts.end() )
2001cdf0e10cSrcweir             {
2002cdf0e10cSrcweir                 // transfer broken, might even be a new client with the
2003cdf0e10cSrcweir                 // same window id
2004cdf0e10cSrcweir                 it->second.erase( aTimeouts.front() );
2005cdf0e10cSrcweir                 aTimeouts.pop_front();
2006cdf0e10cSrcweir             }
2007cdf0e10cSrcweir 
2008cdf0e10cSrcweir             inc_it = it->second.find( rNotify.atom );
2009cdf0e10cSrcweir             if( inc_it != it->second.end() )
2010cdf0e10cSrcweir             {
2011cdf0e10cSrcweir                 IncrementalTransfer& rInc = inc_it->second;
2012cdf0e10cSrcweir 
2013cdf0e10cSrcweir                 int nBytes = rInc.m_aData.getLength() - rInc.m_nBufferPos;
2014cdf0e10cSrcweir                 nBytes = (nBytes > m_nIncrementalThreshold) ? m_nIncrementalThreshold : nBytes;
2015cdf0e10cSrcweir                 if( nBytes < 0 )  // sanity check
2016cdf0e10cSrcweir                     nBytes = 0;
2017cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2018cdf0e10cSrcweir                 fprintf( stderr, "pushing %d bytes: \"%.*s\"...\n",
2019cdf0e10cSrcweir                          nBytes, nBytes > 32 ? 32 : nBytes,
2020cdf0e10cSrcweir                          (const unsigned char*)rInc.m_aData.getConstArray()+rInc.m_nBufferPos );
2021cdf0e10cSrcweir #endif
2022cdf0e10cSrcweir 
2023cdf0e10cSrcweir 				sal_Size nUnitSize = GetTrueFormatSize(rInc.m_nFormat);
2024cdf0e10cSrcweir 
2025cdf0e10cSrcweir                 XChangeProperty( m_pDisplay,
2026cdf0e10cSrcweir                                  rInc.m_aRequestor,
2027cdf0e10cSrcweir                                  rInc.m_aProperty,
2028cdf0e10cSrcweir                                  rInc.m_aTarget,
2029cdf0e10cSrcweir                                  rInc.m_nFormat,
2030cdf0e10cSrcweir                                  PropModeReplace,
2031cdf0e10cSrcweir                                  (const unsigned char*)rInc.m_aData.getConstArray()+rInc.m_nBufferPos,
2032cdf0e10cSrcweir                                  nBytes/nUnitSize );
2033cdf0e10cSrcweir                 rInc.m_nBufferPos += nBytes;
2034cdf0e10cSrcweir                 rInc.m_nTransferStartTime = nCurrentTime;
2035cdf0e10cSrcweir 
2036cdf0e10cSrcweir                 if( nBytes == 0 ) // transfer finished
2037cdf0e10cSrcweir                 {
2038cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2039cdf0e10cSrcweir                     fprintf( stderr, "finished INCR transfer for window 0x%lx, property %s, type %s\n",
2040cdf0e10cSrcweir                              rInc.m_aRequestor,
2041cdf0e10cSrcweir                              OUStringToOString( getString( rInc.m_aProperty ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
2042cdf0e10cSrcweir                              OUStringToOString( getString( rInc.m_aTarget ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
2043cdf0e10cSrcweir                              );
2044cdf0e10cSrcweir #endif
2045cdf0e10cSrcweir                     it->second.erase( inc_it );
2046cdf0e10cSrcweir                 }
2047cdf0e10cSrcweir 
2048cdf0e10cSrcweir             }
2049cdf0e10cSrcweir             // eventually clean up the hash map
2050cdf0e10cSrcweir             if( it->second.begin() == it->second.end() )
2051cdf0e10cSrcweir                 m_aIncrementals.erase( it );
2052cdf0e10cSrcweir         }
2053cdf0e10cSrcweir     }
2054cdf0e10cSrcweir     return bHandled;
2055cdf0e10cSrcweir }
2056cdf0e10cSrcweir 
2057cdf0e10cSrcweir // ------------------------------------------------------------------------
2058cdf0e10cSrcweir 
handleSelectionNotify(XSelectionEvent & rNotify)2059cdf0e10cSrcweir bool SelectionManager::handleSelectionNotify( XSelectionEvent& rNotify )
2060cdf0e10cSrcweir {
2061cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
2062cdf0e10cSrcweir 
2063cdf0e10cSrcweir     bool bHandled = false;
2064cdf0e10cSrcweir 
2065cdf0e10cSrcweir 	// notification about success/failure of one of our conversion requests
2066cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2067cdf0e10cSrcweir     OUString aSelection( getString( rNotify.selection ) );
2068cdf0e10cSrcweir     OUString aProperty( OUString::createFromAscii( "None" ) );
2069cdf0e10cSrcweir     if( rNotify.property )
2070cdf0e10cSrcweir         aProperty = getString( rNotify.property );
2071cdf0e10cSrcweir 	fprintf( stderr, "handleSelectionNotify for selection %s and property %s (0x%lx)\n",
2072cdf0e10cSrcweir 			 OUStringToOString( aSelection, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
2073cdf0e10cSrcweir 			 OUStringToOString( aProperty, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
2074cdf0e10cSrcweir              rNotify.property
2075cdf0e10cSrcweir 			 );
2076cdf0e10cSrcweir     if( rNotify.requestor != m_aWindow && rNotify.requestor != m_aCurrentDropWindow )
2077cdf0e10cSrcweir         fprintf( stderr, "Warning: selection notify for unknown window 0x%lx\n", rNotify.requestor );
2078cdf0e10cSrcweir #endif
2079cdf0e10cSrcweir 	::std::hash_map< Atom, Selection* >::iterator it =
2080cdf0e10cSrcweir 		  m_aSelections.find( rNotify.selection );
2081cdf0e10cSrcweir     if (
2082cdf0e10cSrcweir         (rNotify.requestor == m_aWindow || rNotify.requestor == m_aCurrentDropWindow) &&
2083cdf0e10cSrcweir         it != m_aSelections.end() &&
2084cdf0e10cSrcweir         (
2085cdf0e10cSrcweir          (it->second->m_eState == Selection::WaitingForResponse) ||
2086cdf0e10cSrcweir          (it->second->m_eState == Selection::WaitingForData)
2087cdf0e10cSrcweir         )
2088cdf0e10cSrcweir        )
2089cdf0e10cSrcweir 	{
2090cdf0e10cSrcweir         bHandled = true;
2091cdf0e10cSrcweir         if( it->second->m_aRequestedType == m_nMULTIPLEAtom )
2092cdf0e10cSrcweir         {
2093cdf0e10cSrcweir             Atom nType = None;
2094cdf0e10cSrcweir             int nFormat = 0;
2095cdf0e10cSrcweir             unsigned long nItems = 0, nBytes = 0;
2096cdf0e10cSrcweir             unsigned char* pData = NULL;
2097cdf0e10cSrcweir 
2098cdf0e10cSrcweir             // get type and length
2099cdf0e10cSrcweir             XGetWindowProperty( m_pDisplay,
2100cdf0e10cSrcweir                                 rNotify.requestor,
2101cdf0e10cSrcweir                                 rNotify.property,
2102cdf0e10cSrcweir                                 0, 256,
2103cdf0e10cSrcweir                                 False,
2104cdf0e10cSrcweir                                 AnyPropertyType,
2105cdf0e10cSrcweir                                 &nType, &nFormat,
2106cdf0e10cSrcweir                                 &nItems, &nBytes,
2107cdf0e10cSrcweir                                 &pData );
2108cdf0e10cSrcweir             if( nBytes ) // HUGE request !!!
2109cdf0e10cSrcweir             {
2110cdf0e10cSrcweir                 if( pData )
2111cdf0e10cSrcweir                     XFree( pData );
2112cdf0e10cSrcweir                 XGetWindowProperty( m_pDisplay,
2113cdf0e10cSrcweir                                     rNotify.requestor,
2114cdf0e10cSrcweir                                     rNotify.property,
2115cdf0e10cSrcweir                                     0, 256+(nBytes+3)/4,
2116cdf0e10cSrcweir                                     False,
2117cdf0e10cSrcweir                                     AnyPropertyType,
2118cdf0e10cSrcweir                                     &nType, &nFormat,
2119cdf0e10cSrcweir                                     &nItems, &nBytes,
2120cdf0e10cSrcweir                                     &pData );
2121cdf0e10cSrcweir             }
2122cdf0e10cSrcweir             it->second->m_eState		= Selection::Inactive;
2123cdf0e10cSrcweir             sal_Size nUnitSize = GetTrueFormatSize(nFormat);
2124cdf0e10cSrcweir             it->second->m_aData			= Sequence< sal_Int8 >((sal_Int8*)pData, nItems * nUnitSize);
2125cdf0e10cSrcweir             it->second->m_aDataArrived.set();
2126cdf0e10cSrcweir             if( pData )
2127cdf0e10cSrcweir                 XFree( pData );
2128cdf0e10cSrcweir         }
2129cdf0e10cSrcweir         // WaitingForData can actually happen; some
2130cdf0e10cSrcweir         // applications (e.g. cmdtool on Solaris) first send
2131cdf0e10cSrcweir         // a success and then cancel it. Weird !
2132cdf0e10cSrcweir 		else if( rNotify.property == None )
2133cdf0e10cSrcweir 		{
2134cdf0e10cSrcweir             // conversion failed, stop transfer
2135cdf0e10cSrcweir 			it->second->m_eState		= Selection::Inactive;
2136cdf0e10cSrcweir 			it->second->m_aData			= Sequence< sal_Int8 >();
2137cdf0e10cSrcweir 			it->second->m_aDataArrived.set();
2138cdf0e10cSrcweir 		}
2139cdf0e10cSrcweir 		// get the bytes, by INCR if necessary
2140cdf0e10cSrcweir 		else
2141cdf0e10cSrcweir 			it->second->m_eState = Selection::WaitingForData;
2142cdf0e10cSrcweir 	}
2143cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2144cdf0e10cSrcweir     else if( it != m_aSelections.end() )
2145cdf0e10cSrcweir         fprintf( stderr, "Warning: selection in state %d\n", it->second->m_eState );
2146cdf0e10cSrcweir #endif
2147cdf0e10cSrcweir     return bHandled;
2148cdf0e10cSrcweir }
2149cdf0e10cSrcweir 
2150cdf0e10cSrcweir // ------------------------------------------------------------------------
2151cdf0e10cSrcweir 
handleDropEvent(XClientMessageEvent & rMessage)2152cdf0e10cSrcweir bool SelectionManager::handleDropEvent( XClientMessageEvent& rMessage )
2153cdf0e10cSrcweir {
2154cdf0e10cSrcweir     ResettableMutexGuard aGuard(m_aMutex);
2155cdf0e10cSrcweir 
2156cdf0e10cSrcweir 	// handle drop related events
2157cdf0e10cSrcweir 	XLIB_Window aSource = rMessage.data.l[0];
2158cdf0e10cSrcweir 	XLIB_Window aTarget = rMessage.window;
2159cdf0e10cSrcweir 
2160cdf0e10cSrcweir     bool bHandled = false;
2161cdf0e10cSrcweir 
2162cdf0e10cSrcweir 	::std::hash_map< XLIB_Window, DropTargetEntry >::iterator it =
2163cdf0e10cSrcweir 		  m_aDropTargets.find( aTarget );
2164cdf0e10cSrcweir 
2165cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2166cdf0e10cSrcweir 	if( rMessage.message_type == m_nXdndEnter     ||
2167cdf0e10cSrcweir 		rMessage.message_type == m_nXdndLeave     ||
2168cdf0e10cSrcweir 		rMessage.message_type == m_nXdndDrop      ||
2169cdf0e10cSrcweir 		rMessage.message_type == m_nXdndPosition  )
2170cdf0e10cSrcweir 	{
2171cdf0e10cSrcweir 		fprintf( stderr, "got drop event %s, ", OUStringToOString( getString( rMessage.message_type ), RTL_TEXTENCODING_ASCII_US).getStr() );
2172cdf0e10cSrcweir 		if( it == m_aDropTargets.end() )
2173cdf0e10cSrcweir 			fprintf( stderr, "but no target found\n" );
2174cdf0e10cSrcweir 		else if( ! it->second.m_pTarget->m_bActive )
2175cdf0e10cSrcweir 			fprintf( stderr, "but target is inactive\n" );
2176cdf0e10cSrcweir 		else if( m_aDropEnterEvent.data.l[0] != None && (XLIB_Window)m_aDropEnterEvent.data.l[0] != aSource )
2177cdf0e10cSrcweir 			fprintf( stderr, "but source 0x%lx is unknown (expected 0x%lx or 0)\n", aSource, m_aDropEnterEvent.data.l[0] );
2178cdf0e10cSrcweir 		else
2179cdf0e10cSrcweir 			fprintf( stderr, "processing.\n" );
2180cdf0e10cSrcweir 	}
2181cdf0e10cSrcweir #endif
2182cdf0e10cSrcweir 
2183cdf0e10cSrcweir     if( it != m_aDropTargets.end() && it->second.m_pTarget->m_bActive &&
2184cdf0e10cSrcweir         m_bDropWaitingForCompletion && m_aDropEnterEvent.data.l[0] )
2185cdf0e10cSrcweir     {
2186cdf0e10cSrcweir         bHandled = true;
2187cdf0e10cSrcweir         OSL_ENSURE( 0, "someone forgot to call dropComplete ?" );
2188cdf0e10cSrcweir         // some listener forgot to call dropComplete in the last operation
2189cdf0e10cSrcweir         // let us end it now and accept the new enter event
2190cdf0e10cSrcweir         aGuard.clear();
2191cdf0e10cSrcweir         dropComplete( sal_False, m_aCurrentDropWindow, m_nDropTime );
2192cdf0e10cSrcweir         aGuard.reset();
2193cdf0e10cSrcweir     }
2194cdf0e10cSrcweir 
2195cdf0e10cSrcweir 	if( it != m_aDropTargets.end() &&
2196cdf0e10cSrcweir 		it->second.m_pTarget->m_bActive &&
2197cdf0e10cSrcweir        ( m_aDropEnterEvent.data.l[0] == None || XLIB_Window(m_aDropEnterEvent.data.l[0]) == aSource )
2198cdf0e10cSrcweir 		)
2199cdf0e10cSrcweir 	{
2200cdf0e10cSrcweir 		if( rMessage.message_type == m_nXdndEnter )
2201cdf0e10cSrcweir 		{
2202cdf0e10cSrcweir             bHandled = true;
2203cdf0e10cSrcweir 			m_aDropEnterEvent			= rMessage;
2204cdf0e10cSrcweir 			m_bDropEnterSent			= false;
2205cdf0e10cSrcweir 			m_aCurrentDropWindow		= aTarget;
2206cdf0e10cSrcweir 			m_nCurrentProtocolVersion	= m_aDropEnterEvent.data.l[1] >> 24;
2207cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2208cdf0e10cSrcweir 			fprintf( stderr, "received XdndEnter on 0x%lx\n", aTarget );
2209cdf0e10cSrcweir #endif
2210cdf0e10cSrcweir 		}
2211cdf0e10cSrcweir 		else if(
2212cdf0e10cSrcweir                 rMessage.message_type == m_nXdndPosition &&
2213cdf0e10cSrcweir                 aSource == XLIB_Window(m_aDropEnterEvent.data.l[0])
2214cdf0e10cSrcweir                 )
2215cdf0e10cSrcweir 		{
2216cdf0e10cSrcweir             bHandled = true;
2217cdf0e10cSrcweir 			m_nDropTime = m_nCurrentProtocolVersion > 0 ? rMessage.data.l[3] : CurrentTime;
2218cdf0e10cSrcweir 			if( ! m_bDropEnterSent )
2219cdf0e10cSrcweir 				m_nDropTimestamp = m_nDropTime;
2220cdf0e10cSrcweir 
2221cdf0e10cSrcweir 			XLIB_Window aChild;
2222cdf0e10cSrcweir 			XTranslateCoordinates( m_pDisplay,
2223cdf0e10cSrcweir 								   it->second.m_aRootWindow,
2224cdf0e10cSrcweir 								   it->first,
2225cdf0e10cSrcweir 								   rMessage.data.l[2] >> 16,
2226cdf0e10cSrcweir 								   rMessage.data.l[2] & 0xffff,
2227cdf0e10cSrcweir 								   &m_nLastX, &m_nLastY,
2228cdf0e10cSrcweir 								   &aChild );
2229cdf0e10cSrcweir 
2230cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2231cdf0e10cSrcweir 			fprintf( stderr, "received XdndPosition on 0x%lx (%d, %d)\n", aTarget, m_nLastX, m_nLastY );
2232cdf0e10cSrcweir #endif
2233cdf0e10cSrcweir 			DropTargetDragEnterEvent aEvent;
2234cdf0e10cSrcweir 			aEvent.Source		= static_cast< XDropTarget* >(it->second.m_pTarget);
2235cdf0e10cSrcweir 			aEvent.Context		= new DropTargetDragContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
2236cdf0e10cSrcweir 			aEvent.LocationX	= m_nLastX;
2237cdf0e10cSrcweir 			aEvent.LocationY	= m_nLastY;
2238cdf0e10cSrcweir             aEvent.SourceActions = m_nSourceActions;
2239cdf0e10cSrcweir 			if( m_nCurrentProtocolVersion < 2 )
2240cdf0e10cSrcweir 				aEvent.DropAction = DNDConstants::ACTION_COPY;
2241cdf0e10cSrcweir 			else if( Atom(rMessage.data.l[4]) == m_nXdndActionCopy )
2242cdf0e10cSrcweir 				aEvent.DropAction = DNDConstants::ACTION_COPY;
2243cdf0e10cSrcweir 			else if( Atom(rMessage.data.l[4]) == m_nXdndActionMove )
2244cdf0e10cSrcweir 				aEvent.DropAction = DNDConstants::ACTION_MOVE;
2245cdf0e10cSrcweir 			else if( Atom(rMessage.data.l[4]) == m_nXdndActionLink )
2246cdf0e10cSrcweir 				aEvent.DropAction = DNDConstants::ACTION_LINK;
2247cdf0e10cSrcweir 			else if( Atom(rMessage.data.l[4]) == m_nXdndActionAsk )
2248cdf0e10cSrcweir 				// currently no interface to implement ask
2249cdf0e10cSrcweir 				aEvent.DropAction = ~0;
2250cdf0e10cSrcweir 			else
2251cdf0e10cSrcweir 				aEvent.DropAction = DNDConstants::ACTION_NONE;
2252cdf0e10cSrcweir 
2253cdf0e10cSrcweir 			m_nLastDropAction	= aEvent.DropAction;
2254cdf0e10cSrcweir 			if( ! m_bDropEnterSent )
2255cdf0e10cSrcweir 			{
2256cdf0e10cSrcweir 				m_bDropEnterSent = true;
2257cdf0e10cSrcweir 				aEvent.SupportedDataFlavors = m_xDropTransferable->getTransferDataFlavors();
2258cdf0e10cSrcweir                 aGuard.clear();
2259cdf0e10cSrcweir 				it->second->dragEnter( aEvent );
2260cdf0e10cSrcweir 			}
2261cdf0e10cSrcweir 			else
2262cdf0e10cSrcweir             {
2263cdf0e10cSrcweir                 aGuard.clear();
2264cdf0e10cSrcweir 				it->second->dragOver( aEvent );
2265cdf0e10cSrcweir             }
2266cdf0e10cSrcweir 		}
2267cdf0e10cSrcweir 		else if(
2268cdf0e10cSrcweir                 rMessage.message_type == m_nXdndLeave  &&
2269cdf0e10cSrcweir                 aSource == XLIB_Window(m_aDropEnterEvent.data.l[0])
2270cdf0e10cSrcweir                 )
2271cdf0e10cSrcweir 		{
2272cdf0e10cSrcweir             bHandled = true;
2273cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2274cdf0e10cSrcweir 			fprintf( stderr, "received XdndLeave on 0x%lx\n", aTarget );
2275cdf0e10cSrcweir #endif
2276cdf0e10cSrcweir 			DropTargetEvent aEvent;
2277cdf0e10cSrcweir 			aEvent.Source = static_cast< XDropTarget* >(it->second.m_pTarget);
2278cdf0e10cSrcweir 			m_aDropEnterEvent.data.l[0] = None;
2279cdf0e10cSrcweir 			if( m_aCurrentDropWindow == aTarget )
2280cdf0e10cSrcweir 				m_aCurrentDropWindow = None;
2281cdf0e10cSrcweir 			m_nCurrentProtocolVersion = nXdndProtocolRevision;
2282cdf0e10cSrcweir             aGuard.clear();
2283cdf0e10cSrcweir 			it->second->dragExit( aEvent );
2284cdf0e10cSrcweir 		}
2285cdf0e10cSrcweir 		else if(
2286cdf0e10cSrcweir                 rMessage.message_type == m_nXdndDrop &&
2287cdf0e10cSrcweir                 aSource == XLIB_Window(m_aDropEnterEvent.data.l[0])
2288cdf0e10cSrcweir                 )
2289cdf0e10cSrcweir 		{
2290cdf0e10cSrcweir             bHandled = true;
2291cdf0e10cSrcweir 			m_nDropTime = m_nCurrentProtocolVersion > 0 ? rMessage.data.l[2] : CurrentTime;
2292cdf0e10cSrcweir 
2293cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2294cdf0e10cSrcweir 			fprintf( stderr, "received XdndDrop on 0x%lx (%d, %d)\n", aTarget, m_nLastX, m_nLastY );
2295cdf0e10cSrcweir #endif
2296cdf0e10cSrcweir             if( m_bLastDropAccepted )
2297cdf0e10cSrcweir             {
2298cdf0e10cSrcweir                 DropTargetDropEvent aEvent;
2299cdf0e10cSrcweir                 aEvent.Source		= static_cast< XDropTarget* >(it->second.m_pTarget);
2300cdf0e10cSrcweir                 aEvent.Context		= new DropTargetDropContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
2301cdf0e10cSrcweir                 aEvent.LocationX	= m_nLastX;
2302cdf0e10cSrcweir                 aEvent.LocationY	= m_nLastY;
2303cdf0e10cSrcweir                 aEvent.DropAction	= m_nLastDropAction;
2304cdf0e10cSrcweir                 // there is nothing corresponding to source supported actions
2305cdf0e10cSrcweir                 // every source can do link, copy and move
2306cdf0e10cSrcweir                 aEvent.SourceActions= m_nLastDropAction;
2307cdf0e10cSrcweir                 aEvent.Transferable	= m_xDropTransferable;
2308cdf0e10cSrcweir 
2309cdf0e10cSrcweir                 m_bDropWaitingForCompletion = true;
2310cdf0e10cSrcweir                 aGuard.clear();
2311cdf0e10cSrcweir                 it->second->drop( aEvent );
2312cdf0e10cSrcweir             }
2313cdf0e10cSrcweir             else
2314cdf0e10cSrcweir             {
2315cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2316cdf0e10cSrcweir                 fprintf( stderr, "XdndDrop canceled due to m_bLastDropAccepted = fale\n" );
2317cdf0e10cSrcweir #endif
2318cdf0e10cSrcweir                 DropTargetEvent aEvent;
2319cdf0e10cSrcweir                 aEvent.Source = static_cast< XDropTarget* >(it->second.m_pTarget);
2320cdf0e10cSrcweir                 aGuard.clear();
2321cdf0e10cSrcweir                 it->second->dragExit( aEvent );
2322cdf0e10cSrcweir                 // reset the drop status, notify source
2323cdf0e10cSrcweir                 dropComplete( sal_False, m_aCurrentDropWindow, m_nDropTime );
2324cdf0e10cSrcweir             }
2325cdf0e10cSrcweir         }
2326cdf0e10cSrcweir 	}
2327cdf0e10cSrcweir     return bHandled;
2328cdf0e10cSrcweir }
2329cdf0e10cSrcweir 
2330cdf0e10cSrcweir /*
2331cdf0e10cSrcweir  *	methods for XDropTargetDropContext
2332cdf0e10cSrcweir  */
2333cdf0e10cSrcweir 
dropComplete(sal_Bool bSuccess,XLIB_Window aDropWindow,XLIB_Time)2334cdf0e10cSrcweir void SelectionManager::dropComplete( sal_Bool bSuccess, XLIB_Window aDropWindow, XLIB_Time )
2335cdf0e10cSrcweir {
2336cdf0e10cSrcweir 	ClearableMutexGuard aGuard(m_aMutex);
2337cdf0e10cSrcweir 
2338cdf0e10cSrcweir 	if( aDropWindow == m_aCurrentDropWindow )
2339cdf0e10cSrcweir 	{
2340cdf0e10cSrcweir 		if( m_xDragSourceListener.is() )
2341cdf0e10cSrcweir 		{
2342cdf0e10cSrcweir 			DragSourceDropEvent dsde;
2343cdf0e10cSrcweir 			dsde.Source				= static_cast< OWeakObject* >(this);
2344cdf0e10cSrcweir 			dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2345cdf0e10cSrcweir 			dsde.DragSource			= static_cast< XDragSource* >(this);
2346cdf0e10cSrcweir 			dsde.DropAction			= getUserDragAction();
2347cdf0e10cSrcweir 			dsde.DropSuccess		= bSuccess;
2348cdf0e10cSrcweir             css::uno::Reference< XDragSourceListener > xListener = m_xDragSourceListener;
2349cdf0e10cSrcweir 			m_xDragSourceListener.clear();
2350cdf0e10cSrcweir 
2351cdf0e10cSrcweir             aGuard.clear();
2352cdf0e10cSrcweir 			xListener->dragDropEnd( dsde );
2353cdf0e10cSrcweir 		}
2354cdf0e10cSrcweir 		else if( m_aDropEnterEvent.data.l[0] && m_aCurrentDropWindow )
2355cdf0e10cSrcweir 		{
2356cdf0e10cSrcweir 			XEvent aEvent;
2357cdf0e10cSrcweir 			aEvent.xclient.type			= ClientMessage;
2358cdf0e10cSrcweir 			aEvent.xclient.display		= m_pDisplay;
2359cdf0e10cSrcweir 			aEvent.xclient.window		= m_aDropEnterEvent.data.l[0];
2360cdf0e10cSrcweir 			aEvent.xclient.message_type	= m_nXdndFinished;
2361cdf0e10cSrcweir 			aEvent.xclient.format		= 32;
2362cdf0e10cSrcweir 			aEvent.xclient.data.l[0]	= m_aCurrentDropWindow;
2363cdf0e10cSrcweir 			aEvent.xclient.data.l[1]	= bSuccess ? 1 : 0;
2364cdf0e10cSrcweir 			aEvent.xclient.data.l[2]	= 0;
2365cdf0e10cSrcweir 			aEvent.xclient.data.l[3]	= 0;
2366cdf0e10cSrcweir 			aEvent.xclient.data.l[4]	= 0;
2367cdf0e10cSrcweir             if( bSuccess )
2368cdf0e10cSrcweir             {
2369cdf0e10cSrcweir                 if( m_nLastDropAction & DNDConstants::ACTION_MOVE )
2370cdf0e10cSrcweir                     aEvent.xclient.data.l[2] = m_nXdndActionMove;
2371cdf0e10cSrcweir                 else if( m_nLastDropAction & DNDConstants::ACTION_COPY )
2372cdf0e10cSrcweir                     aEvent.xclient.data.l[2] = m_nXdndActionCopy;
2373cdf0e10cSrcweir                 else if( m_nLastDropAction & DNDConstants::ACTION_LINK )
2374cdf0e10cSrcweir                     aEvent.xclient.data.l[2] = m_nXdndActionLink;
2375cdf0e10cSrcweir             }
2376cdf0e10cSrcweir 
2377cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2378cdf0e10cSrcweir 			fprintf( stderr, "Sending XdndFinished to 0x%lx\n",
2379cdf0e10cSrcweir 					 m_aDropEnterEvent.data.l[0]
2380cdf0e10cSrcweir 					 );
2381cdf0e10cSrcweir #endif
2382cdf0e10cSrcweir 
2383cdf0e10cSrcweir 			XSendEvent( m_pDisplay, m_aDropEnterEvent.data.l[0],
2384cdf0e10cSrcweir 						False, NoEventMask, & aEvent );
2385cdf0e10cSrcweir 
2386cdf0e10cSrcweir 			m_aDropEnterEvent.data.l[0]	= None;
2387cdf0e10cSrcweir 			m_aCurrentDropWindow		= None;
2388cdf0e10cSrcweir 			m_nCurrentProtocolVersion	= nXdndProtocolRevision;
2389cdf0e10cSrcweir 		}
2390cdf0e10cSrcweir         m_bDropWaitingForCompletion = false;
2391cdf0e10cSrcweir 	}
2392cdf0e10cSrcweir 	else
2393cdf0e10cSrcweir 		OSL_ASSERT( "dropComplete from invalid DropTargetDropContext" );
2394cdf0e10cSrcweir }
2395cdf0e10cSrcweir 
2396cdf0e10cSrcweir /*
2397cdf0e10cSrcweir  *	methods for XDropTargetDragContext
2398cdf0e10cSrcweir  */
2399cdf0e10cSrcweir 
2400cdf0e10cSrcweir // ------------------------------------------------------------------------
2401cdf0e10cSrcweir 
sendDragStatus(Atom nDropAction)2402cdf0e10cSrcweir void SelectionManager::sendDragStatus( Atom nDropAction )
2403cdf0e10cSrcweir {
2404cdf0e10cSrcweir 	ClearableMutexGuard aGuard(m_aMutex);
2405cdf0e10cSrcweir 
2406cdf0e10cSrcweir 	if( m_xDragSourceListener.is() )
2407cdf0e10cSrcweir 	{
2408cdf0e10cSrcweir 		sal_Int8 nNewDragAction;
2409cdf0e10cSrcweir 		if( nDropAction == m_nXdndActionMove )
2410cdf0e10cSrcweir 			nNewDragAction = DNDConstants::ACTION_MOVE;
2411cdf0e10cSrcweir 		else if( nDropAction == m_nXdndActionCopy )
2412cdf0e10cSrcweir 			nNewDragAction = DNDConstants::ACTION_COPY;
2413cdf0e10cSrcweir 		else if( nDropAction == m_nXdndActionLink )
2414cdf0e10cSrcweir 			nNewDragAction = DNDConstants::ACTION_LINK;
2415cdf0e10cSrcweir 		else
2416cdf0e10cSrcweir 			nNewDragAction = DNDConstants::ACTION_NONE;
2417cdf0e10cSrcweir         nNewDragAction &= m_nSourceActions;
2418cdf0e10cSrcweir 
2419cdf0e10cSrcweir         if( nNewDragAction != m_nTargetAcceptAction )
2420cdf0e10cSrcweir         {
2421cdf0e10cSrcweir             setCursor( getDefaultCursor( nNewDragAction ), m_aDropWindow, m_nDragTimestamp );
2422cdf0e10cSrcweir             m_nTargetAcceptAction = nNewDragAction;
2423cdf0e10cSrcweir         }
2424cdf0e10cSrcweir 
2425cdf0e10cSrcweir 		DragSourceDragEvent dsde;
2426cdf0e10cSrcweir 		dsde.Source				= static_cast< OWeakObject* >(this);
2427cdf0e10cSrcweir 		dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2428cdf0e10cSrcweir 		dsde.DragSource			= static_cast< XDragSource* >(this);
2429cdf0e10cSrcweir 		dsde.DropAction			= m_nSourceActions;
2430cdf0e10cSrcweir 		dsde.UserAction			= getUserDragAction();
2431cdf0e10cSrcweir 
2432cdf0e10cSrcweir         css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
2433cdf0e10cSrcweir         // caution: do not change anything after this
2434cdf0e10cSrcweir         aGuard.clear();
2435cdf0e10cSrcweir         if( xListener.is() )
2436cdf0e10cSrcweir             xListener->dragOver( dsde );
2437cdf0e10cSrcweir 	}
2438cdf0e10cSrcweir 	else if( m_aDropEnterEvent.data.l[0] && m_aCurrentDropWindow )
2439cdf0e10cSrcweir 	{
2440cdf0e10cSrcweir 		XEvent aEvent;
2441cdf0e10cSrcweir 		aEvent.xclient.type			= ClientMessage;
2442cdf0e10cSrcweir 		aEvent.xclient.display		= m_pDisplay;
2443cdf0e10cSrcweir 		aEvent.xclient.window		= m_aDropEnterEvent.data.l[0];
2444cdf0e10cSrcweir 		aEvent.xclient.message_type	= m_nXdndStatus;
2445cdf0e10cSrcweir 		aEvent.xclient.format		= 32;
2446cdf0e10cSrcweir 		aEvent.xclient.data.l[0]	= m_aCurrentDropWindow;
2447cdf0e10cSrcweir 		aEvent.xclient.data.l[1]	= 2;
2448cdf0e10cSrcweir 		if( nDropAction == m_nXdndActionMove	||
2449cdf0e10cSrcweir 			nDropAction == m_nXdndActionLink	||
2450cdf0e10cSrcweir 			nDropAction == m_nXdndActionCopy )
2451cdf0e10cSrcweir 			aEvent.xclient.data.l[1] |= 1;
2452cdf0e10cSrcweir 		aEvent.xclient.data.l[2] = 0;
2453cdf0e10cSrcweir 		aEvent.xclient.data.l[3] = 0;
2454cdf0e10cSrcweir 		aEvent.xclient.data.l[4] = m_nCurrentProtocolVersion > 1 ? nDropAction : 0;
2455cdf0e10cSrcweir 
2456cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2457cdf0e10cSrcweir 		fprintf( stderr, "Sending XdndStatus to 0x%lx with action %s\n",
2458cdf0e10cSrcweir 				 m_aDropEnterEvent.data.l[0],
2459cdf0e10cSrcweir 				 OUStringToOString( getString( nDropAction ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
2460cdf0e10cSrcweir 				 );
2461cdf0e10cSrcweir #endif
2462cdf0e10cSrcweir 
2463cdf0e10cSrcweir 		XSendEvent( m_pDisplay, m_aDropEnterEvent.data.l[0],
2464cdf0e10cSrcweir 					False, NoEventMask, & aEvent );
2465cdf0e10cSrcweir 		XFlush( m_pDisplay );
2466cdf0e10cSrcweir 	}
2467cdf0e10cSrcweir }
2468cdf0e10cSrcweir 
2469cdf0e10cSrcweir // ------------------------------------------------------------------------
2470cdf0e10cSrcweir 
getUserDragAction() const2471cdf0e10cSrcweir sal_Int8 SelectionManager::getUserDragAction() const
2472cdf0e10cSrcweir {
2473cdf0e10cSrcweir     return (m_nTargetAcceptAction != DNDConstants::ACTION_DEFAULT) ? m_nTargetAcceptAction : m_nUserDragAction;
2474cdf0e10cSrcweir }
2475cdf0e10cSrcweir 
2476cdf0e10cSrcweir // ------------------------------------------------------------------------
2477cdf0e10cSrcweir 
updateDragAction(int modifierState)2478cdf0e10cSrcweir bool SelectionManager::updateDragAction( int modifierState )
2479cdf0e10cSrcweir {
2480cdf0e10cSrcweir 	bool bRet = false;
2481cdf0e10cSrcweir 
2482cdf0e10cSrcweir 	sal_Int8 nNewDropAction = DNDConstants::ACTION_MOVE;
2483cdf0e10cSrcweir 	if( ( modifierState & ShiftMask ) && ! ( modifierState & ControlMask ) )
2484cdf0e10cSrcweir 		nNewDropAction = DNDConstants::ACTION_MOVE;
2485cdf0e10cSrcweir 	else if( ( modifierState & ControlMask ) && ! ( modifierState & ShiftMask ) )
2486cdf0e10cSrcweir 		nNewDropAction = DNDConstants::ACTION_COPY;
2487cdf0e10cSrcweir 	else if( ( modifierState & ShiftMask ) && ( modifierState & ControlMask ) )
2488cdf0e10cSrcweir 		nNewDropAction = DNDConstants::ACTION_LINK;
2489cdf0e10cSrcweir 	if( m_nCurrentProtocolVersion < 0 && m_aDropWindow != None )
2490cdf0e10cSrcweir 		nNewDropAction = DNDConstants::ACTION_COPY;
2491cdf0e10cSrcweir     nNewDropAction &= m_nSourceActions;
2492cdf0e10cSrcweir 
2493cdf0e10cSrcweir     if( ! ( modifierState & ( ControlMask | ShiftMask ) ) )
2494cdf0e10cSrcweir     {
2495cdf0e10cSrcweir         if( ! nNewDropAction )
2496cdf0e10cSrcweir         {
2497cdf0e10cSrcweir             // default to an action so the user does not have to press
2498cdf0e10cSrcweir             // keys explicitly
2499cdf0e10cSrcweir             if( m_nSourceActions & DNDConstants::ACTION_MOVE )
2500cdf0e10cSrcweir                 nNewDropAction = DNDConstants::ACTION_MOVE;
2501cdf0e10cSrcweir             else if( m_nSourceActions & DNDConstants::ACTION_COPY )
2502cdf0e10cSrcweir                 nNewDropAction = DNDConstants::ACTION_COPY;
2503cdf0e10cSrcweir             else if( m_nSourceActions & DNDConstants::ACTION_LINK )
2504cdf0e10cSrcweir                 nNewDropAction = DNDConstants::ACTION_LINK;
2505cdf0e10cSrcweir         }
2506cdf0e10cSrcweir         nNewDropAction |= DNDConstants::ACTION_DEFAULT;
2507cdf0e10cSrcweir     }
2508cdf0e10cSrcweir 
2509cdf0e10cSrcweir 	if( nNewDropAction != m_nUserDragAction || m_nTargetAcceptAction != DNDConstants::ACTION_DEFAULT )
2510cdf0e10cSrcweir 	{
2511cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2512cdf0e10cSrcweir         fprintf( stderr, "updateDragAction: %x -> %x\n", (int)m_nUserDragAction, (int)nNewDropAction );
2513cdf0e10cSrcweir #endif
2514cdf0e10cSrcweir 		bRet = true;
2515cdf0e10cSrcweir 		m_nUserDragAction = nNewDropAction;
2516cdf0e10cSrcweir 
2517cdf0e10cSrcweir 		DragSourceDragEvent dsde;
2518cdf0e10cSrcweir 		dsde.Source				= static_cast< OWeakObject* >(this);
2519cdf0e10cSrcweir 		dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2520cdf0e10cSrcweir 		dsde.DragSource			= static_cast< XDragSource* >(this);
2521cdf0e10cSrcweir 		dsde.DropAction			= m_nUserDragAction;
2522cdf0e10cSrcweir 		dsde.UserAction			= m_nUserDragAction;
2523cdf0e10cSrcweir         m_nTargetAcceptAction	= DNDConstants::ACTION_DEFAULT; // invalidate last accept
2524cdf0e10cSrcweir 		m_xDragSourceListener->dropActionChanged( dsde );
2525cdf0e10cSrcweir 	}
2526cdf0e10cSrcweir 	return bRet;
2527cdf0e10cSrcweir }
2528cdf0e10cSrcweir 
2529cdf0e10cSrcweir // ------------------------------------------------------------------------
2530cdf0e10cSrcweir 
sendDropPosition(bool bForce,XLIB_Time eventTime)2531cdf0e10cSrcweir void SelectionManager::sendDropPosition( bool bForce, XLIB_Time eventTime )
2532cdf0e10cSrcweir {
2533cdf0e10cSrcweir     ClearableMutexGuard aGuard(m_aMutex);
2534cdf0e10cSrcweir 
2535cdf0e10cSrcweir     if( m_bDropSent )
2536cdf0e10cSrcweir         return;
2537cdf0e10cSrcweir 
2538cdf0e10cSrcweir 	::std::hash_map< XLIB_Window, DropTargetEntry >::const_iterator it =
2539cdf0e10cSrcweir 		  m_aDropTargets.find( m_aDropWindow );
2540cdf0e10cSrcweir 	if( it != m_aDropTargets.end() )
2541cdf0e10cSrcweir 	{
2542cdf0e10cSrcweir 		if( it->second.m_pTarget->m_bActive )
2543cdf0e10cSrcweir 		{
2544cdf0e10cSrcweir 			int x, y;
2545cdf0e10cSrcweir 			XLIB_Window aChild;
2546cdf0e10cSrcweir 			XTranslateCoordinates( m_pDisplay, it->second.m_aRootWindow, m_aDropWindow, m_nLastDragX, m_nLastDragY, &x, &y, &aChild );
2547cdf0e10cSrcweir 			DropTargetDragEvent dtde;
2548cdf0e10cSrcweir 			dtde.Source			= static_cast< OWeakObject* >(it->second.m_pTarget );
2549cdf0e10cSrcweir 			dtde.Context		= new DropTargetDragContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
2550cdf0e10cSrcweir 			dtde.LocationX		= x;
2551cdf0e10cSrcweir 			dtde.LocationY		= y;
2552cdf0e10cSrcweir 			dtde.DropAction		= getUserDragAction();
2553cdf0e10cSrcweir 			dtde.SourceActions	= m_nSourceActions;
2554cdf0e10cSrcweir             aGuard.clear();
2555cdf0e10cSrcweir 			it->second->dragOver( dtde );
2556cdf0e10cSrcweir 		}
2557cdf0e10cSrcweir 	}
2558cdf0e10cSrcweir 	else if( bForce ||
2559cdf0e10cSrcweir 
2560cdf0e10cSrcweir 			 m_nLastDragX < m_nNoPosX || m_nLastDragX >= m_nNoPosX+m_nNoPosWidth ||
2561cdf0e10cSrcweir 			 m_nLastDragY < m_nNoPosY || m_nLastDragY >= m_nNoPosY+m_nNoPosHeight
2562cdf0e10cSrcweir 			 )
2563cdf0e10cSrcweir 	{
2564cdf0e10cSrcweir 		// send XdndPosition
2565cdf0e10cSrcweir 		XEvent aEvent;
2566cdf0e10cSrcweir 		aEvent.type = ClientMessage;
2567cdf0e10cSrcweir 		aEvent.xclient.display		= m_pDisplay;
2568cdf0e10cSrcweir 		aEvent.xclient.format		= 32;
2569cdf0e10cSrcweir 		aEvent.xclient.message_type	= m_nXdndPosition;
2570cdf0e10cSrcweir 		aEvent.xclient.window		= m_aDropWindow;
2571cdf0e10cSrcweir 		aEvent.xclient.data.l[0]	= m_aWindow;
2572cdf0e10cSrcweir 		aEvent.xclient.data.l[1]	= 0;
2573cdf0e10cSrcweir 		aEvent.xclient.data.l[2]	= m_nLastDragX << 16 | (m_nLastDragY&0xffff);
2574cdf0e10cSrcweir 		aEvent.xclient.data.l[3]	= eventTime;
2575cdf0e10cSrcweir 
2576cdf0e10cSrcweir 		if( m_nUserDragAction & DNDConstants::ACTION_COPY )
2577cdf0e10cSrcweir 			aEvent.xclient.data.l[4]=m_nXdndActionCopy;
2578cdf0e10cSrcweir 		else if( m_nUserDragAction & DNDConstants::ACTION_MOVE )
2579cdf0e10cSrcweir 			aEvent.xclient.data.l[4]=m_nXdndActionMove;
2580cdf0e10cSrcweir 		else if( m_nUserDragAction & DNDConstants::ACTION_LINK )
2581cdf0e10cSrcweir 			aEvent.xclient.data.l[4]=m_nXdndActionLink;
2582cdf0e10cSrcweir 		else
2583cdf0e10cSrcweir 			aEvent.xclient.data.l[4]=m_nXdndActionCopy;
2584cdf0e10cSrcweir 		XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
2585cdf0e10cSrcweir 		m_nNoPosX = m_nNoPosY = m_nNoPosWidth = m_nNoPosHeight = 0;
2586cdf0e10cSrcweir 	}
2587cdf0e10cSrcweir }
2588cdf0e10cSrcweir 
2589cdf0e10cSrcweir // ------------------------------------------------------------------------
2590cdf0e10cSrcweir 
handleDragEvent(XEvent & rMessage)2591cdf0e10cSrcweir bool SelectionManager::handleDragEvent( XEvent& rMessage )
2592cdf0e10cSrcweir {
2593cdf0e10cSrcweir 	if( ! m_xDragSourceListener.is() )
2594cdf0e10cSrcweir 		return false;
2595cdf0e10cSrcweir 
2596cdf0e10cSrcweir     ResettableMutexGuard aGuard(m_aMutex);
2597cdf0e10cSrcweir 
2598cdf0e10cSrcweir     bool bHandled = false;
2599cdf0e10cSrcweir 
2600cdf0e10cSrcweir 	// for shortcut
2601cdf0e10cSrcweir 	::std::hash_map< XLIB_Window, DropTargetEntry >::const_iterator it =
2602cdf0e10cSrcweir 		  m_aDropTargets.find( m_aDropWindow );
2603cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2604cdf0e10cSrcweir 	switch( rMessage.type )
2605cdf0e10cSrcweir 	{
2606cdf0e10cSrcweir 		case ClientMessage:
2607cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: %s\n", OUStringToOString( getString( rMessage.xclient.message_type ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
2608cdf0e10cSrcweir 			break;
2609cdf0e10cSrcweir 		case MotionNotify:
2610cdf0e10cSrcweir //			fprintf( stderr, "handleDragEvent: MotionNotify\n" );
2611cdf0e10cSrcweir 			break;
2612cdf0e10cSrcweir 		case EnterNotify:
2613cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: EnterNotify\n" );
2614cdf0e10cSrcweir 			break;
2615cdf0e10cSrcweir 		case LeaveNotify:
2616cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: LeaveNotify\n" );
2617cdf0e10cSrcweir 			break;
2618cdf0e10cSrcweir 		case ButtonPress:
2619cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: ButtonPress %d (m_nDragButton = %d)\n", rMessage.xbutton.button, m_nDragButton );
2620cdf0e10cSrcweir 			break;
2621cdf0e10cSrcweir 		case ButtonRelease:
2622cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: ButtonRelease %d (m_nDragButton = %d)\n", rMessage.xbutton.button, m_nDragButton );
2623cdf0e10cSrcweir 			break;
2624cdf0e10cSrcweir 		case XLIB_KeyPress:
2625cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: KeyPress\n" );
2626cdf0e10cSrcweir 			break;
2627cdf0e10cSrcweir 		case KeyRelease:
2628cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: KeyRelease\n" );
2629cdf0e10cSrcweir 			break;
2630cdf0e10cSrcweir 		default:
2631cdf0e10cSrcweir 			fprintf( stderr, "handleDragEvent: <unknown type %d>\n", rMessage.type );
2632cdf0e10cSrcweir 			break;
2633cdf0e10cSrcweir 	}
2634cdf0e10cSrcweir #endif
2635cdf0e10cSrcweir 
2636cdf0e10cSrcweir 	// handle drag related events
2637cdf0e10cSrcweir 	if( rMessage.type == ClientMessage )
2638cdf0e10cSrcweir 	{
2639cdf0e10cSrcweir 		if( Atom(rMessage.xclient.message_type) == m_nXdndStatus && Atom(rMessage.xclient.data.l[0]) == m_aDropWindow )
2640cdf0e10cSrcweir 		{
2641cdf0e10cSrcweir             bHandled = true;
2642cdf0e10cSrcweir 			DragSourceDragEvent dsde;
2643cdf0e10cSrcweir 			dsde.Source					= static_cast< OWeakObject* >(this);
2644cdf0e10cSrcweir 			dsde.DragSourceContext		= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2645cdf0e10cSrcweir 			dsde.DragSource				= static_cast< XDragSource* >( this );
2646cdf0e10cSrcweir             dsde.UserAction = getUserDragAction();
2647cdf0e10cSrcweir 			dsde.DropAction = DNDConstants::ACTION_NONE;
2648cdf0e10cSrcweir 			m_bDropSuccess = rMessage.xclient.data.l[1] & 1 ? true : false;
2649cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2650cdf0e10cSrcweir             fprintf( stderr, "status drop action: accept = %s, %s\n",
2651cdf0e10cSrcweir                      m_bDropSuccess ? "true" : "false",
2652cdf0e10cSrcweir                      OUStringToOString( getString( rMessage.xclient.data.l[4] ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
2653cdf0e10cSrcweir #endif
2654cdf0e10cSrcweir 			if( rMessage.xclient.data.l[1] & 1 )
2655cdf0e10cSrcweir 			{
2656cdf0e10cSrcweir 				if( m_nCurrentProtocolVersion > 1 )
2657cdf0e10cSrcweir 				{
2658cdf0e10cSrcweir 					if( Atom(rMessage.xclient.data.l[4]) == m_nXdndActionCopy )
2659cdf0e10cSrcweir 						dsde.DropAction = DNDConstants::ACTION_COPY;
2660cdf0e10cSrcweir 					else if( Atom(rMessage.xclient.data.l[4]) == m_nXdndActionMove )
2661cdf0e10cSrcweir 						dsde.DropAction = DNDConstants::ACTION_MOVE;
2662cdf0e10cSrcweir 					else if( Atom(rMessage.xclient.data.l[4]) == m_nXdndActionLink )
2663cdf0e10cSrcweir 						dsde.DropAction = DNDConstants::ACTION_LINK;
2664cdf0e10cSrcweir 				}
2665cdf0e10cSrcweir 				else
2666cdf0e10cSrcweir 					dsde.DropAction = DNDConstants::ACTION_COPY;
2667cdf0e10cSrcweir 			}
2668cdf0e10cSrcweir 			m_nTargetAcceptAction = dsde.DropAction;
2669cdf0e10cSrcweir 
2670cdf0e10cSrcweir 			if( ! ( rMessage.xclient.data.l[1] & 2 ) )
2671cdf0e10cSrcweir 			{
2672cdf0e10cSrcweir 				m_nNoPosX		= rMessage.xclient.data.l[2] >> 16;
2673cdf0e10cSrcweir 				m_nNoPosY		= rMessage.xclient.data.l[2] & 0xffff;
2674cdf0e10cSrcweir 				m_nNoPosWidth	= rMessage.xclient.data.l[3] >> 16;
2675cdf0e10cSrcweir 				m_nNoPosHeight	= rMessage.xclient.data.l[3] & 0xffff;
2676cdf0e10cSrcweir 			}
2677cdf0e10cSrcweir 			else
2678cdf0e10cSrcweir 				m_nNoPosX = m_nNoPosY = m_nNoPosWidth = m_nNoPosHeight = 0;
2679cdf0e10cSrcweir 
2680cdf0e10cSrcweir             setCursor( getDefaultCursor( dsde.DropAction ), m_aDropWindow, m_nDragTimestamp );
2681cdf0e10cSrcweir             aGuard.clear();
2682cdf0e10cSrcweir             m_xDragSourceListener->dragOver( dsde );
2683cdf0e10cSrcweir 		}
2684cdf0e10cSrcweir 		else if( Atom(rMessage.xclient.message_type) == m_nXdndFinished && m_aDropWindow == Atom(rMessage.xclient.data.l[0]) )
2685cdf0e10cSrcweir 		{
2686cdf0e10cSrcweir             bHandled = true;
2687cdf0e10cSrcweir 			// notify the listener
2688cdf0e10cSrcweir 			DragSourceDropEvent dsde;
2689cdf0e10cSrcweir 			dsde.Source				= static_cast< OWeakObject* >(this);
2690cdf0e10cSrcweir 			dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2691cdf0e10cSrcweir 			dsde.DragSource			= static_cast< XDragSource* >(this);
2692cdf0e10cSrcweir 			dsde.DropAction			= m_nTargetAcceptAction;
2693cdf0e10cSrcweir 			dsde.DropSuccess		= m_bDropSuccess;
2694cdf0e10cSrcweir             css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
2695cdf0e10cSrcweir 			m_xDragSourceListener.clear();
2696cdf0e10cSrcweir             aGuard.clear();
2697cdf0e10cSrcweir 			xListener->dragDropEnd( dsde );
2698cdf0e10cSrcweir 		}
2699cdf0e10cSrcweir 	}
2700cdf0e10cSrcweir 	else if( rMessage.type == MotionNotify ||
2701cdf0e10cSrcweir 			 rMessage.type == EnterNotify || rMessage.type == LeaveNotify
2702cdf0e10cSrcweir 			 )
2703cdf0e10cSrcweir 	{
2704cdf0e10cSrcweir         bHandled = true;
2705cdf0e10cSrcweir 		bool bForce = false;
2706cdf0e10cSrcweir 		int root_x	= rMessage.type == MotionNotify ? rMessage.xmotion.x_root : rMessage.xcrossing.x_root;
2707cdf0e10cSrcweir 		int root_y	= rMessage.type == MotionNotify ? rMessage.xmotion.y_root : rMessage.xcrossing.y_root;
2708cdf0e10cSrcweir 		XLIB_Window root = rMessage.type == MotionNotify ? rMessage.xmotion.root : rMessage.xcrossing.root;
2709cdf0e10cSrcweir 		m_nDragTimestamp = rMessage.type == MotionNotify ? rMessage.xmotion.time : rMessage.xcrossing.time;
2710cdf0e10cSrcweir 
2711cdf0e10cSrcweir         aGuard.clear();
2712cdf0e10cSrcweir 		if( rMessage.type == MotionNotify )
2713cdf0e10cSrcweir         {
2714cdf0e10cSrcweir 			bForce = updateDragAction( rMessage.xmotion.state );
2715cdf0e10cSrcweir         }
2716cdf0e10cSrcweir 		updateDragWindow( root_x, root_y, root );
2717cdf0e10cSrcweir         aGuard.reset();
2718cdf0e10cSrcweir 
2719cdf0e10cSrcweir 		if( m_nCurrentProtocolVersion >= 0 && m_aDropProxy != None )
2720cdf0e10cSrcweir         {
2721cdf0e10cSrcweir             aGuard.clear();
2722cdf0e10cSrcweir 			sendDropPosition( bForce, rMessage.type == MotionNotify ? rMessage.xmotion.time : rMessage.xcrossing.time );
2723cdf0e10cSrcweir         }
2724cdf0e10cSrcweir 	}
2725cdf0e10cSrcweir 	else if( rMessage.type == XLIB_KeyPress || rMessage.type == KeyRelease )
2726cdf0e10cSrcweir 	{
2727cdf0e10cSrcweir 		bHandled = true;
272885372600SHerbert Dürr 		const KeySym aKey = XkbKeycodeToKeysym( m_pDisplay, rMessage.xkey.keycode, 0, 0 );
2729cdf0e10cSrcweir 		if( aKey == XK_Escape )
2730cdf0e10cSrcweir 		{
2731cdf0e10cSrcweir 			// abort drag
2732cdf0e10cSrcweir 			if( it != m_aDropTargets.end() )
2733cdf0e10cSrcweir 			{
2734cdf0e10cSrcweir 				DropTargetEvent dte;
2735cdf0e10cSrcweir 				dte.Source = static_cast< OWeakObject* >( it->second.m_pTarget );
2736cdf0e10cSrcweir                 aGuard.clear();
2737cdf0e10cSrcweir 				it->second.m_pTarget->dragExit( dte );
2738cdf0e10cSrcweir 			}
2739cdf0e10cSrcweir 			else if( m_aDropProxy != None && m_nCurrentProtocolVersion >= 0 )
2740cdf0e10cSrcweir 			{
2741cdf0e10cSrcweir 				// send XdndLeave
2742cdf0e10cSrcweir 				XEvent aEvent;
2743cdf0e10cSrcweir 				aEvent.type = ClientMessage;
2744cdf0e10cSrcweir 				aEvent.xclient.display		= m_pDisplay;
2745cdf0e10cSrcweir 				aEvent.xclient.format		= 32;
2746cdf0e10cSrcweir 				aEvent.xclient.message_type	= m_nXdndLeave;
2747cdf0e10cSrcweir 				aEvent.xclient.window		= m_aDropWindow;
2748cdf0e10cSrcweir 				aEvent.xclient.data.l[0]	= m_aWindow;
2749cdf0e10cSrcweir 				memset( aEvent.xclient.data.l+1, 0, sizeof(long)*4);
2750cdf0e10cSrcweir 				m_aDropWindow = m_aDropProxy = None;
2751cdf0e10cSrcweir 				XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
2752cdf0e10cSrcweir 			}
2753cdf0e10cSrcweir 			// notify the listener
2754cdf0e10cSrcweir 			DragSourceDropEvent dsde;
2755cdf0e10cSrcweir 			dsde.Source				= static_cast< OWeakObject* >(this);
2756cdf0e10cSrcweir 			dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2757cdf0e10cSrcweir 			dsde.DragSource			= static_cast< XDragSource* >(this);
2758cdf0e10cSrcweir 			dsde.DropAction			= DNDConstants::ACTION_NONE;
2759cdf0e10cSrcweir 			dsde.DropSuccess		= sal_False;
2760cdf0e10cSrcweir             css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
2761cdf0e10cSrcweir 			m_xDragSourceListener.clear();
2762cdf0e10cSrcweir             aGuard.clear();
2763cdf0e10cSrcweir 			xListener->dragDropEnd( dsde );
2764cdf0e10cSrcweir 		}
2765cdf0e10cSrcweir 		else
2766cdf0e10cSrcweir 		{
2767cdf0e10cSrcweir 			/*
2768cdf0e10cSrcweir 			 *	man page says: state is state immediate PRIOR to the
2769cdf0e10cSrcweir 			 *	event. It would seem that this is a somewhat arguable
2770cdf0e10cSrcweir 			 *	design decision.
2771cdf0e10cSrcweir 			 */
2772cdf0e10cSrcweir 			int nState = rMessage.xkey.state;
2773cdf0e10cSrcweir 			int nNewState = 0;
2774cdf0e10cSrcweir 			switch( aKey )
2775cdf0e10cSrcweir 			{
2776cdf0e10cSrcweir 				case XK_Shift_R:
2777cdf0e10cSrcweir 				case XK_Shift_L: nNewState = ShiftMask;break;
2778cdf0e10cSrcweir 				case XK_Control_R:
2779cdf0e10cSrcweir 				case XK_Control_L: nNewState = ControlMask;break;
2780cdf0e10cSrcweir 					// just interested in shift and ctrl for dnd
2781cdf0e10cSrcweir 			}
2782cdf0e10cSrcweir 			if( rMessage.type == XLIB_KeyPress )
2783cdf0e10cSrcweir 				nState |= nNewState;
2784cdf0e10cSrcweir 			else
2785cdf0e10cSrcweir 				nState &= ~nNewState;
2786cdf0e10cSrcweir             aGuard.clear();
2787cdf0e10cSrcweir 			if( updateDragAction( nState ) )
2788cdf0e10cSrcweir 				sendDropPosition( true, rMessage.xkey.time );
2789cdf0e10cSrcweir 		}
2790cdf0e10cSrcweir 	}
2791cdf0e10cSrcweir 	else if(
2792cdf0e10cSrcweir             ( rMessage.type == ButtonPress || rMessage.type == ButtonRelease ) &&
2793cdf0e10cSrcweir             rMessage.xbutton.button == m_nDragButton )
2794cdf0e10cSrcweir 	{
2795cdf0e10cSrcweir 		bool bCancel = true;
2796cdf0e10cSrcweir 		if( m_aDropWindow != None )
2797cdf0e10cSrcweir 		{
2798cdf0e10cSrcweir 			if( it != m_aDropTargets.end() )
2799cdf0e10cSrcweir 			{
2800cdf0e10cSrcweir 				if( it->second.m_pTarget->m_bActive && m_nUserDragAction != DNDConstants::ACTION_NONE && m_bLastDropAccepted )
2801cdf0e10cSrcweir 				{
2802cdf0e10cSrcweir                     bHandled = true;
2803cdf0e10cSrcweir 					int x, y;
2804cdf0e10cSrcweir 					XLIB_Window aChild;
2805cdf0e10cSrcweir 					XTranslateCoordinates( m_pDisplay, rMessage.xbutton.root, m_aDropWindow, rMessage.xbutton.x_root, rMessage.xbutton.y_root, &x, &y, &aChild );
2806cdf0e10cSrcweir 					DropTargetDropEvent dtde;
2807cdf0e10cSrcweir 					dtde.Source			= static_cast< OWeakObject* >(it->second.m_pTarget );
2808cdf0e10cSrcweir 					dtde.Context		= new DropTargetDropContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
2809cdf0e10cSrcweir 					dtde.LocationX		= x;
2810cdf0e10cSrcweir 					dtde.LocationY		= y;
2811cdf0e10cSrcweir 					dtde.DropAction		= m_nUserDragAction;
2812cdf0e10cSrcweir 					dtde.SourceActions	= m_nSourceActions;
2813cdf0e10cSrcweir 					dtde.Transferable	= m_xDragSourceTransferable;
2814cdf0e10cSrcweir 					m_bDropSent					= true;
2815cdf0e10cSrcweir 					m_nDropTimeout				= time( NULL );
2816cdf0e10cSrcweir                     m_bDropWaitingForCompletion = true;
2817cdf0e10cSrcweir                     aGuard.clear();
2818cdf0e10cSrcweir 					it->second->drop( dtde );
2819cdf0e10cSrcweir 					bCancel = false;
2820cdf0e10cSrcweir 				}
2821cdf0e10cSrcweir 				else bCancel = true;
2822cdf0e10cSrcweir 			}
2823cdf0e10cSrcweir 			else if( m_nCurrentProtocolVersion >= 0 )
2824cdf0e10cSrcweir 			{
2825cdf0e10cSrcweir                 bHandled = true;
2826cdf0e10cSrcweir 
2827cdf0e10cSrcweir 				XEvent aEvent;
2828cdf0e10cSrcweir 				aEvent.type = ClientMessage;
2829cdf0e10cSrcweir 				aEvent.xclient.display		= m_pDisplay;
2830cdf0e10cSrcweir 				aEvent.xclient.format		= 32;
2831cdf0e10cSrcweir 				aEvent.xclient.message_type	= m_nXdndDrop;
2832cdf0e10cSrcweir 				aEvent.xclient.window		= m_aDropWindow;
2833cdf0e10cSrcweir 				aEvent.xclient.data.l[0]	= m_aWindow;
2834cdf0e10cSrcweir 				aEvent.xclient.data.l[1]	= 0;
2835cdf0e10cSrcweir 				aEvent.xclient.data.l[2]	= rMessage.xbutton.time;
2836cdf0e10cSrcweir 				aEvent.xclient.data.l[3]	= 0;
2837cdf0e10cSrcweir 				aEvent.xclient.data.l[4]	= 0;
2838cdf0e10cSrcweir 
2839cdf0e10cSrcweir 				m_bDropSent					= true;
2840cdf0e10cSrcweir 				m_nDropTimeout				= time( NULL );
2841cdf0e10cSrcweir 				XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
2842cdf0e10cSrcweir 				bCancel = false;
2843cdf0e10cSrcweir 			}
2844cdf0e10cSrcweir 			else
2845cdf0e10cSrcweir 			{
2846cdf0e10cSrcweir 				// dropping on non XdndWindows: acquire ownership of
2847cdf0e10cSrcweir 				// PRIMARY and send a middle mouse button click down/up to
2848cdf0e10cSrcweir 				// target window
2849cdf0e10cSrcweir 				SelectionAdaptor* pAdaptor = getAdaptor( XA_PRIMARY );
2850cdf0e10cSrcweir 				if( pAdaptor )
2851cdf0e10cSrcweir 				{
2852cdf0e10cSrcweir                     bHandled = true;
2853cdf0e10cSrcweir 
2854cdf0e10cSrcweir 					XLIB_Window aDummy;
2855cdf0e10cSrcweir 					XEvent aEvent;
2856cdf0e10cSrcweir 					aEvent.type = ButtonPress;
2857cdf0e10cSrcweir 					aEvent.xbutton.display		= m_pDisplay;
2858cdf0e10cSrcweir 					aEvent.xbutton.window		= m_aDropWindow;
2859cdf0e10cSrcweir 					aEvent.xbutton.root			= rMessage.xbutton.root;
2860cdf0e10cSrcweir 					aEvent.xbutton.subwindow	= m_aDropWindow;
2861cdf0e10cSrcweir 					aEvent.xbutton.time			= rMessage.xbutton.time+1;
2862cdf0e10cSrcweir 					aEvent.xbutton.x_root		= rMessage.xbutton.x_root;
2863cdf0e10cSrcweir 					aEvent.xbutton.y_root		= rMessage.xbutton.y_root;
2864cdf0e10cSrcweir 					aEvent.xbutton.state		= rMessage.xbutton.state;
2865cdf0e10cSrcweir 					aEvent.xbutton.button		= Button2;
2866cdf0e10cSrcweir 					aEvent.xbutton.same_screen	= True;
2867cdf0e10cSrcweir 					XTranslateCoordinates( m_pDisplay,
2868cdf0e10cSrcweir 										   rMessage.xbutton.root, m_aDropWindow,
2869cdf0e10cSrcweir 										   rMessage.xbutton.x_root, rMessage.xbutton.y_root,
2870cdf0e10cSrcweir 										   &aEvent.xbutton.x, &aEvent.xbutton.y,
2871cdf0e10cSrcweir 										   &aDummy );
2872cdf0e10cSrcweir 					XSendEvent( m_pDisplay, m_aDropWindow, False, ButtonPressMask, &aEvent );
2873cdf0e10cSrcweir 					aEvent.xbutton.type   = ButtonRelease;
2874cdf0e10cSrcweir 					aEvent.xbutton.time++;
2875cdf0e10cSrcweir 					aEvent.xbutton.state |= Button2Mask;
2876cdf0e10cSrcweir 					XSendEvent( m_pDisplay, m_aDropWindow, False, ButtonReleaseMask, &aEvent );
2877cdf0e10cSrcweir 
2878cdf0e10cSrcweir 					m_bDropSent					= true;
2879cdf0e10cSrcweir 					m_nDropTimeout				= time( NULL );
2880cdf0e10cSrcweir 					XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
2881cdf0e10cSrcweir 					m_bWaitingForPrimaryConversion	= true;
2882cdf0e10cSrcweir 					m_bDropSent						= true;
2883cdf0e10cSrcweir 					m_nDropTimeout					= time( NULL );
2884cdf0e10cSrcweir 					// HACK :-)
2885cdf0e10cSrcweir                     aGuard.clear();
2886cdf0e10cSrcweir 					static_cast< X11Clipboard* >( pAdaptor )->setContents( m_xDragSourceTransferable, css::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboardOwner >() );
2887cdf0e10cSrcweir                     aGuard.reset();
2888cdf0e10cSrcweir 					bCancel = false;
2889cdf0e10cSrcweir 				}
2890cdf0e10cSrcweir 			}
2891cdf0e10cSrcweir 		}
2892cdf0e10cSrcweir 		if( bCancel )
2893cdf0e10cSrcweir 		{
2894cdf0e10cSrcweir 			// cancel drag
2895cdf0e10cSrcweir 			DragSourceDropEvent dsde;
2896cdf0e10cSrcweir 			dsde.Source				= static_cast< OWeakObject* >(this);
2897cdf0e10cSrcweir 			dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2898cdf0e10cSrcweir 			dsde.DragSource			= static_cast< XDragSource* >(this);
2899cdf0e10cSrcweir 			dsde.DropAction			= DNDConstants::ACTION_NONE;
2900cdf0e10cSrcweir 			dsde.DropSuccess		= sal_False;
2901cdf0e10cSrcweir             css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
2902cdf0e10cSrcweir 			m_xDragSourceListener.clear();
2903cdf0e10cSrcweir             aGuard.clear();
2904cdf0e10cSrcweir 			xListener->dragDropEnd( dsde );
2905cdf0e10cSrcweir             bHandled = true;
2906cdf0e10cSrcweir 		}
2907cdf0e10cSrcweir 	}
2908cdf0e10cSrcweir     return bHandled;
2909cdf0e10cSrcweir }
2910cdf0e10cSrcweir 
2911cdf0e10cSrcweir // ------------------------------------------------------------------------
2912cdf0e10cSrcweir 
accept(sal_Int8 dragOperation,XLIB_Window aDropWindow,XLIB_Time)2913cdf0e10cSrcweir void SelectionManager::accept( sal_Int8 dragOperation, XLIB_Window aDropWindow, XLIB_Time )
2914cdf0e10cSrcweir {
2915cdf0e10cSrcweir 	if( aDropWindow == m_aCurrentDropWindow )
2916cdf0e10cSrcweir 	{
2917cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2918cdf0e10cSrcweir         fprintf( stderr, "accept: %x\n", dragOperation );
2919cdf0e10cSrcweir #endif
2920cdf0e10cSrcweir 		Atom nAction = None;
2921cdf0e10cSrcweir         dragOperation &= (DNDConstants::ACTION_MOVE | DNDConstants::ACTION_COPY | DNDConstants::ACTION_LINK);
2922cdf0e10cSrcweir         if( dragOperation & DNDConstants::ACTION_MOVE )
2923cdf0e10cSrcweir             nAction = m_nXdndActionMove;
2924cdf0e10cSrcweir         else if( dragOperation & DNDConstants::ACTION_COPY )
2925cdf0e10cSrcweir             nAction = m_nXdndActionCopy;
2926cdf0e10cSrcweir         else if( dragOperation & DNDConstants::ACTION_LINK )
2927cdf0e10cSrcweir             nAction = m_nXdndActionLink;
2928cdf0e10cSrcweir         m_bLastDropAccepted = true;
2929cdf0e10cSrcweir 		sendDragStatus( nAction );
2930cdf0e10cSrcweir 	}
2931cdf0e10cSrcweir }
2932cdf0e10cSrcweir 
2933cdf0e10cSrcweir // ------------------------------------------------------------------------
2934cdf0e10cSrcweir 
reject(XLIB_Window aDropWindow,XLIB_Time)2935cdf0e10cSrcweir void SelectionManager::reject( XLIB_Window aDropWindow, XLIB_Time )
2936cdf0e10cSrcweir {
2937cdf0e10cSrcweir 	if( aDropWindow == m_aCurrentDropWindow )
2938cdf0e10cSrcweir 	{
2939cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2940cdf0e10cSrcweir         fprintf( stderr, "reject\n" );
2941cdf0e10cSrcweir #endif
2942cdf0e10cSrcweir         m_bLastDropAccepted = false;
2943cdf0e10cSrcweir 		sendDragStatus( None );
2944cdf0e10cSrcweir 		if( m_bDropSent && m_xDragSourceListener.is() )
2945cdf0e10cSrcweir 		{
2946cdf0e10cSrcweir 			DragSourceDropEvent dsde;
2947cdf0e10cSrcweir 			dsde.Source				= static_cast< OWeakObject* >(this);
2948cdf0e10cSrcweir 			dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
2949cdf0e10cSrcweir 			dsde.DragSource			= static_cast< XDragSource* >(this);
2950cdf0e10cSrcweir 			dsde.DropAction			= DNDConstants::ACTION_NONE;
2951cdf0e10cSrcweir 			dsde.DropSuccess		= sal_False;
2952cdf0e10cSrcweir 			m_xDragSourceListener->dragDropEnd( dsde );
2953cdf0e10cSrcweir 			m_xDragSourceListener.clear();
2954cdf0e10cSrcweir 		}
2955cdf0e10cSrcweir 	}
2956cdf0e10cSrcweir }
2957cdf0e10cSrcweir 
2958cdf0e10cSrcweir /*
2959cdf0e10cSrcweir  *	XDragSource
2960cdf0e10cSrcweir  */
2961cdf0e10cSrcweir 
isDragImageSupported()2962cdf0e10cSrcweir sal_Bool SelectionManager::isDragImageSupported() throw()
2963cdf0e10cSrcweir {
2964cdf0e10cSrcweir 	return sal_False;
2965cdf0e10cSrcweir }
2966cdf0e10cSrcweir 
2967cdf0e10cSrcweir // ------------------------------------------------------------------------
2968cdf0e10cSrcweir 
getDefaultCursor(sal_Int8 dragAction)2969cdf0e10cSrcweir sal_Int32 SelectionManager::getDefaultCursor( sal_Int8 dragAction ) throw()
2970cdf0e10cSrcweir {
2971cdf0e10cSrcweir 	XLIB_Cursor aCursor = m_aNoneCursor;
2972cdf0e10cSrcweir 	if( dragAction & DNDConstants::ACTION_MOVE )
2973cdf0e10cSrcweir 		aCursor = m_aMoveCursor;
2974cdf0e10cSrcweir 	else if( dragAction & DNDConstants::ACTION_COPY )
2975cdf0e10cSrcweir 		aCursor = m_aCopyCursor;
2976cdf0e10cSrcweir 	else if( dragAction & DNDConstants::ACTION_LINK )
2977cdf0e10cSrcweir 		aCursor = m_aLinkCursor;
2978cdf0e10cSrcweir 	return aCursor;
2979cdf0e10cSrcweir }
2980cdf0e10cSrcweir 
2981cdf0e10cSrcweir // ------------------------------------------------------------------------
2982cdf0e10cSrcweir 
getXdndVersion(XLIB_Window aWindow,XLIB_Window & rProxy)2983cdf0e10cSrcweir int SelectionManager::getXdndVersion( XLIB_Window aWindow, XLIB_Window& rProxy )
2984cdf0e10cSrcweir {
2985cdf0e10cSrcweir 	Atom* pProperties = NULL;
2986cdf0e10cSrcweir 	int nProperties = 0;
2987cdf0e10cSrcweir 	Atom nType;
2988cdf0e10cSrcweir 	int nFormat;
2989cdf0e10cSrcweir 	unsigned long nItems, nBytes;
2990cdf0e10cSrcweir 	unsigned char* pBytes = NULL;
2991cdf0e10cSrcweir 
2992cdf0e10cSrcweir 	int nVersion = -1;
2993cdf0e10cSrcweir 	rProxy = None;
2994cdf0e10cSrcweir 
2995cdf0e10cSrcweir 	/*
2996cdf0e10cSrcweir 	 *	XListProperties is used here to avoid unnecessary XGetWindowProperty calls
2997cdf0e10cSrcweir 	 *	and therefore reducing latency penalty
2998cdf0e10cSrcweir 	 */
2999cdf0e10cSrcweir 	pProperties = XListProperties( m_pDisplay, aWindow, &nProperties );
3000cdf0e10cSrcweir 	// first look for proxy
3001cdf0e10cSrcweir 	int i;
3002cdf0e10cSrcweir 	for( i = 0; i < nProperties; i++ )
3003cdf0e10cSrcweir 	{
3004cdf0e10cSrcweir 		if( pProperties[i] == m_nXdndProxy )
3005cdf0e10cSrcweir 		{
3006cdf0e10cSrcweir 			XGetWindowProperty( m_pDisplay, aWindow, m_nXdndProxy, 0, 1, False, XA_WINDOW,
3007cdf0e10cSrcweir 								&nType, &nFormat, &nItems, &nBytes, &pBytes );
3008cdf0e10cSrcweir 			if( pBytes )
3009cdf0e10cSrcweir 			{
3010cdf0e10cSrcweir 				if( nType == XA_WINDOW )
3011cdf0e10cSrcweir 					rProxy = *(XLIB_Window*)pBytes;
3012cdf0e10cSrcweir 				XFree( pBytes );
3013cdf0e10cSrcweir 				pBytes = NULL;
3014cdf0e10cSrcweir 				if( rProxy != None )
3015cdf0e10cSrcweir 				{
3016cdf0e10cSrcweir 					// now check proxy wether it points to itself
3017cdf0e10cSrcweir 					XGetWindowProperty( m_pDisplay, rProxy, m_nXdndProxy, 0, 1, False, XA_WINDOW,
3018cdf0e10cSrcweir 										&nType, &nFormat, &nItems, &nBytes, &pBytes );
3019cdf0e10cSrcweir 					if( pBytes )
3020cdf0e10cSrcweir 					{
3021cdf0e10cSrcweir 						if( nType == XA_WINDOW && *(XLIB_Window*)pBytes != rProxy )
3022cdf0e10cSrcweir 							rProxy = None;
3023cdf0e10cSrcweir 						XFree( pBytes );
3024cdf0e10cSrcweir 						pBytes = NULL;
3025cdf0e10cSrcweir 					}
3026cdf0e10cSrcweir 					else
3027cdf0e10cSrcweir 						rProxy = None;
3028cdf0e10cSrcweir 				}
3029cdf0e10cSrcweir 			}
3030cdf0e10cSrcweir 			break;
3031cdf0e10cSrcweir 		}
3032cdf0e10cSrcweir 	}
3033cdf0e10cSrcweir 	XLIB_Window aAwareWindow = rProxy != None ? rProxy : aWindow;
3034cdf0e10cSrcweir 
3035cdf0e10cSrcweir 	XGetWindowProperty( m_pDisplay, aAwareWindow, m_nXdndAware, 0, 1, False, XA_ATOM,
3036cdf0e10cSrcweir 						&nType, &nFormat, &nItems, &nBytes, &pBytes );
3037cdf0e10cSrcweir 	if( pBytes )
3038cdf0e10cSrcweir 	{
3039cdf0e10cSrcweir 		if( nType == XA_ATOM )
3040cdf0e10cSrcweir 			nVersion = *(Atom*)pBytes;
3041cdf0e10cSrcweir 		XFree( pBytes );
3042cdf0e10cSrcweir 	}
3043cdf0e10cSrcweir 
3044cdf0e10cSrcweir 	nVersion = nVersion > nXdndProtocolRevision ? nXdndProtocolRevision : nVersion;
3045cdf0e10cSrcweir 
3046cdf0e10cSrcweir 	return nVersion;
3047cdf0e10cSrcweir }
3048cdf0e10cSrcweir 
3049cdf0e10cSrcweir // ------------------------------------------------------------------------
3050cdf0e10cSrcweir 
updateDragWindow(int nX,int nY,XLIB_Window aRoot)3051cdf0e10cSrcweir void SelectionManager::updateDragWindow( int nX, int nY, XLIB_Window aRoot )
3052cdf0e10cSrcweir {
3053cdf0e10cSrcweir     ResettableMutexGuard aGuard( m_aMutex );
3054cdf0e10cSrcweir 
3055cdf0e10cSrcweir     css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
3056cdf0e10cSrcweir 
3057cdf0e10cSrcweir 	m_nLastDragX = nX;
3058cdf0e10cSrcweir 	m_nLastDragY = nY;
3059cdf0e10cSrcweir 
3060cdf0e10cSrcweir 	XLIB_Window aParent = aRoot;
3061cdf0e10cSrcweir 	XLIB_Window aChild;
3062cdf0e10cSrcweir 	XLIB_Window aNewProxy = None, aNewCurrentWindow = None;
3063cdf0e10cSrcweir 	int nNewProtocolVersion = -1;
3064cdf0e10cSrcweir 	int nWinX, nWinY;
3065cdf0e10cSrcweir 
3066cdf0e10cSrcweir 	// find the first XdndAware window or check if root window is
3067cdf0e10cSrcweir 	// XdndAware or has XdndProxy
3068cdf0e10cSrcweir 	do
3069cdf0e10cSrcweir 	{
3070cdf0e10cSrcweir 		XTranslateCoordinates( m_pDisplay, aRoot, aParent, nX, nY, &nWinX, &nWinY, &aChild );
3071cdf0e10cSrcweir 		if( aChild != None )
3072cdf0e10cSrcweir 		{
3073cdf0e10cSrcweir 			if( aChild == m_aCurrentDropWindow && aChild != aRoot && m_nCurrentProtocolVersion >= 0 )
3074cdf0e10cSrcweir 			{
3075cdf0e10cSrcweir 				aParent = aChild;
3076cdf0e10cSrcweir 				break;
3077cdf0e10cSrcweir 			}
3078cdf0e10cSrcweir 			nNewProtocolVersion = getXdndVersion( aChild, aNewProxy );
3079cdf0e10cSrcweir 			aParent = aChild;
3080cdf0e10cSrcweir 		}
3081cdf0e10cSrcweir 	} while( aChild != None && nNewProtocolVersion < 0 );
3082cdf0e10cSrcweir 
3083cdf0e10cSrcweir 	aNewCurrentWindow = aParent;
3084cdf0e10cSrcweir 	if( aNewCurrentWindow == aRoot )
3085cdf0e10cSrcweir 	{
3086cdf0e10cSrcweir 		// no children, try root drop
3087cdf0e10cSrcweir 		nNewProtocolVersion = getXdndVersion( aNewCurrentWindow, aNewProxy );
3088cdf0e10cSrcweir 		if( nNewProtocolVersion < 3 )
3089cdf0e10cSrcweir 		{
3090cdf0e10cSrcweir 			aNewCurrentWindow = aNewProxy = None;
3091cdf0e10cSrcweir 			nNewProtocolVersion = nXdndProtocolRevision;
3092cdf0e10cSrcweir 		}
3093cdf0e10cSrcweir 	}
3094cdf0e10cSrcweir 
3095cdf0e10cSrcweir 
3096cdf0e10cSrcweir 	DragSourceDragEvent dsde;
3097cdf0e10cSrcweir 	dsde.Source				= static_cast< OWeakObject* >(this);
3098cdf0e10cSrcweir 	dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
3099cdf0e10cSrcweir 	dsde.DragSource			= static_cast< XDragSource* >(this);
3100cdf0e10cSrcweir 	dsde.DropAction			= nNewProtocolVersion >= 0 ? m_nUserDragAction : DNDConstants::ACTION_COPY;
3101cdf0e10cSrcweir 	dsde.UserAction			= nNewProtocolVersion >= 0 ? m_nUserDragAction : DNDConstants::ACTION_COPY;
3102cdf0e10cSrcweir 
3103cdf0e10cSrcweir 	::std::hash_map< XLIB_Window, DropTargetEntry >::const_iterator it;
3104cdf0e10cSrcweir 	if( aNewCurrentWindow != m_aDropWindow )
3105cdf0e10cSrcweir 	{
3106cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3107cdf0e10cSrcweir 		fprintf( stderr, "drag left window 0x%lx (rev. %d), entered window 0x%lx (rev %d)\n", m_aDropWindow, m_nCurrentProtocolVersion, aNewCurrentWindow, nNewProtocolVersion );
3108cdf0e10cSrcweir #endif
3109cdf0e10cSrcweir 
3110cdf0e10cSrcweir 		if( m_aDropWindow != None )
3111cdf0e10cSrcweir 		{
3112cdf0e10cSrcweir 			it = m_aDropTargets.find( m_aDropWindow );
3113cdf0e10cSrcweir 			if( it != m_aDropTargets.end() )
3114cdf0e10cSrcweir 				// shortcut for own drop targets
3115cdf0e10cSrcweir 			{
3116cdf0e10cSrcweir 				DropTargetEvent dte;
3117cdf0e10cSrcweir 				dte.Source	= static_cast< OWeakObject* >( it->second.m_pTarget );
3118cdf0e10cSrcweir                 aGuard.clear();
3119cdf0e10cSrcweir 				it->second.m_pTarget->dragExit( dte );
3120cdf0e10cSrcweir                 aGuard.reset();
3121cdf0e10cSrcweir 			}
3122cdf0e10cSrcweir 			else
3123cdf0e10cSrcweir 			{
3124cdf0e10cSrcweir 				// send old drop target a XdndLeave
3125cdf0e10cSrcweir 				XEvent aEvent;
3126cdf0e10cSrcweir 				aEvent.type = ClientMessage;
3127cdf0e10cSrcweir 				aEvent.xclient.display			= m_pDisplay;
3128cdf0e10cSrcweir 				aEvent.xclient.format			= 32;
3129cdf0e10cSrcweir 				aEvent.xclient.message_type		= m_nXdndLeave;
3130cdf0e10cSrcweir 				aEvent.xclient.window			= m_aDropWindow;
3131cdf0e10cSrcweir 				aEvent.xclient.data.l[0]		= m_aWindow;
3132cdf0e10cSrcweir 				aEvent.xclient.data.l[1]		= 0;
3133cdf0e10cSrcweir 				XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
3134cdf0e10cSrcweir 			}
3135cdf0e10cSrcweir             if( xListener.is() )
3136cdf0e10cSrcweir             {
3137cdf0e10cSrcweir                 aGuard.clear();
3138cdf0e10cSrcweir                 xListener->dragExit( dsde );
3139cdf0e10cSrcweir                 aGuard.reset();
3140cdf0e10cSrcweir             }
3141cdf0e10cSrcweir 		}
3142cdf0e10cSrcweir 
3143cdf0e10cSrcweir 		m_nCurrentProtocolVersion	= nNewProtocolVersion;
3144cdf0e10cSrcweir 		m_aDropWindow				= aNewCurrentWindow;
3145cdf0e10cSrcweir 		m_aDropProxy				= aNewProxy != None ? aNewProxy : m_aDropWindow;
3146cdf0e10cSrcweir 
3147cdf0e10cSrcweir 		it = m_aDropTargets.find( m_aDropWindow );
3148cdf0e10cSrcweir 		if( it != m_aDropTargets.end() && ! it->second.m_pTarget->m_bActive )
3149cdf0e10cSrcweir 			m_aDropProxy = None;
3150cdf0e10cSrcweir 
3151cdf0e10cSrcweir 		if( m_aDropProxy != None && xListener.is() )
3152cdf0e10cSrcweir         {
3153cdf0e10cSrcweir             aGuard.clear();
3154cdf0e10cSrcweir             xListener->dragEnter( dsde );
3155cdf0e10cSrcweir             aGuard.reset();
3156cdf0e10cSrcweir         }
3157cdf0e10cSrcweir 		// send XdndEnter
3158cdf0e10cSrcweir 		if( m_aDropProxy != None && m_nCurrentProtocolVersion >= 0 )
3159cdf0e10cSrcweir 		{
3160cdf0e10cSrcweir 			it = m_aDropTargets.find( m_aDropWindow );
3161cdf0e10cSrcweir 			if( it != m_aDropTargets.end() )
3162cdf0e10cSrcweir 			{
3163cdf0e10cSrcweir 				XTranslateCoordinates( m_pDisplay, aRoot, m_aDropWindow, nX, nY, &nWinX, &nWinY, &aChild );
3164cdf0e10cSrcweir 				DropTargetDragEnterEvent dtde;
3165cdf0e10cSrcweir 				dtde.Source					= static_cast< OWeakObject* >( it->second.m_pTarget );
3166cdf0e10cSrcweir 				dtde.Context				= new DropTargetDragContext( m_aCurrentDropWindow, m_nDropTimestamp, *this );
3167cdf0e10cSrcweir 				dtde.LocationX				= nWinX;
3168cdf0e10cSrcweir 				dtde.LocationY				= nWinY;
3169cdf0e10cSrcweir 				dtde.DropAction				= m_nUserDragAction;
3170cdf0e10cSrcweir                 dtde.SourceActions			= m_nSourceActions;
3171cdf0e10cSrcweir 				dtde.SupportedDataFlavors	= m_xDragSourceTransferable->getTransferDataFlavors();
3172cdf0e10cSrcweir                 aGuard.clear();
3173cdf0e10cSrcweir 				it->second.m_pTarget->dragEnter( dtde );
3174cdf0e10cSrcweir                 aGuard.reset();
3175cdf0e10cSrcweir 			}
3176cdf0e10cSrcweir 			else
3177cdf0e10cSrcweir 			{
3178cdf0e10cSrcweir 				XEvent aEvent;
3179cdf0e10cSrcweir 				aEvent.type = ClientMessage;
3180cdf0e10cSrcweir 				aEvent.xclient.display			= m_pDisplay;
3181cdf0e10cSrcweir 				aEvent.xclient.format			= 32;
3182cdf0e10cSrcweir 				aEvent.xclient.message_type	= m_nXdndEnter;
3183cdf0e10cSrcweir 				aEvent.xclient.window		= m_aDropWindow;
3184cdf0e10cSrcweir 				aEvent.xclient.data.l[0]	= m_aWindow;
3185cdf0e10cSrcweir 				aEvent.xclient.data.l[1]	= m_nCurrentProtocolVersion << 24;
3186cdf0e10cSrcweir 				memset( aEvent.xclient.data.l + 2, 0, sizeof( long )*3 );
3187cdf0e10cSrcweir 				// fill in data types
3188cdf0e10cSrcweir                 ::std::list< Atom > aConversions;
3189cdf0e10cSrcweir                 getNativeTypeList( m_aDragFlavors, aConversions, m_nXdndSelection );
3190cdf0e10cSrcweir 				if( aConversions.size() > 3 )
3191cdf0e10cSrcweir 					aEvent.xclient.data.l[1] |= 1;
3192cdf0e10cSrcweir                 ::std::list< Atom >::const_iterator type_it = aConversions.begin();
3193cdf0e10cSrcweir 				for( int i = 0; type_it != aConversions.end() && i < 3; i++, ++type_it )
3194cdf0e10cSrcweir 					aEvent.xclient.data.l[i+2] = *type_it;
3195cdf0e10cSrcweir 				XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
3196cdf0e10cSrcweir 			}
3197cdf0e10cSrcweir 		}
3198cdf0e10cSrcweir 		m_nNoPosX = m_nNoPosY = m_nNoPosWidth = m_nNoPosHeight = 0;
3199cdf0e10cSrcweir 	}
3200cdf0e10cSrcweir 	else if( m_aDropProxy != None && xListener.is() )
3201cdf0e10cSrcweir     {
3202cdf0e10cSrcweir         aGuard.clear();
3203cdf0e10cSrcweir 		// drag over for XdndAware windows comes when receiving XdndStatus
3204cdf0e10cSrcweir         xListener->dragOver( dsde );
3205cdf0e10cSrcweir     }
3206cdf0e10cSrcweir }
3207cdf0e10cSrcweir 
3208cdf0e10cSrcweir // ------------------------------------------------------------------------
3209cdf0e10cSrcweir 
startDrag(const DragGestureEvent & trigger,sal_Int8 sourceActions,sal_Int32,sal_Int32,const css::uno::Reference<XTransferable> & transferable,const css::uno::Reference<XDragSourceListener> & listener)3210cdf0e10cSrcweir void SelectionManager::startDrag(
3211cdf0e10cSrcweir                                  const DragGestureEvent& trigger,
3212cdf0e10cSrcweir                                  sal_Int8 sourceActions,
3213cdf0e10cSrcweir                                  sal_Int32,
3214cdf0e10cSrcweir                                  sal_Int32,
3215cdf0e10cSrcweir                                  const css::uno::Reference< XTransferable >& transferable,
3216cdf0e10cSrcweir                                  const css::uno::Reference< XDragSourceListener >& listener
3217cdf0e10cSrcweir                                  ) throw()
3218cdf0e10cSrcweir {
3219cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3220cdf0e10cSrcweir     fprintf( stderr, "startDrag( sourceActions = %x )\n", (int)sourceActions );
3221cdf0e10cSrcweir #endif
3222cdf0e10cSrcweir 
3223cdf0e10cSrcweir 	DragSourceDropEvent aDragFailedEvent;
3224cdf0e10cSrcweir 	aDragFailedEvent.Source				= static_cast< OWeakObject* >(this);
3225cdf0e10cSrcweir 	aDragFailedEvent.DragSource			= static_cast< XDragSource* >(this);
3226cdf0e10cSrcweir 	aDragFailedEvent.DragSourceContext	= new DragSourceContext( None, CurrentTime, *this );
3227cdf0e10cSrcweir 	aDragFailedEvent.DropAction			= DNDConstants::ACTION_NONE;
3228cdf0e10cSrcweir 	aDragFailedEvent.DropSuccess		= sal_False;
3229cdf0e10cSrcweir 
3230cdf0e10cSrcweir 	if( m_aDragRunning.check() )
3231cdf0e10cSrcweir 	{
3232cdf0e10cSrcweir 		if( listener.is() )
3233cdf0e10cSrcweir 			listener->dragDropEnd( aDragFailedEvent );
3234cdf0e10cSrcweir 
3235cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3236cdf0e10cSrcweir         fprintf( stderr, "*** ERROR *** second drag and drop started.\n" );
3237cdf0e10cSrcweir         if( m_xDragSourceListener.is() )
3238cdf0e10cSrcweir             fprintf( stderr, "*** ERROR *** drag source listener already set.\n" );
3239cdf0e10cSrcweir         else
3240cdf0e10cSrcweir             fprintf( stderr, "*** ERROR *** drag thread already running.\n" );
3241cdf0e10cSrcweir #endif
3242cdf0e10cSrcweir 		return;
3243cdf0e10cSrcweir 	}
3244cdf0e10cSrcweir 
3245cdf0e10cSrcweir     SalFrame* pCaptureFrame = NULL;
3246cdf0e10cSrcweir 
3247cdf0e10cSrcweir 	{
3248cdf0e10cSrcweir 		ClearableMutexGuard aGuard(m_aMutex);
3249cdf0e10cSrcweir 
3250cdf0e10cSrcweir         // first get the current pointer position and the window that
3251cdf0e10cSrcweir         // the pointer is located in. since said window should be one
3252cdf0e10cSrcweir         // of our DropTargets at the time of executeDrag we can use
3253cdf0e10cSrcweir         // them for a start
3254cdf0e10cSrcweir         XLIB_Window aRoot, aParent, aChild;
3255*024fb564SPedro Giffuni         int root_x(0), root_y(0), win_x, win_y;
3256*024fb564SPedro Giffuni         unsigned int mask(0);
3257cdf0e10cSrcweir 
3258cdf0e10cSrcweir 		::std::hash_map< XLIB_Window, DropTargetEntry >::const_iterator it;
3259cdf0e10cSrcweir 		it = m_aDropTargets.begin();
3260cdf0e10cSrcweir 		while( it != m_aDropTargets.end() )
3261cdf0e10cSrcweir 		{
3262cdf0e10cSrcweir 			if( XQueryPointer( m_pDisplay, it->second.m_aRootWindow,
3263cdf0e10cSrcweir 							   &aRoot, &aParent,
3264cdf0e10cSrcweir 							   &root_x, &root_y,
3265cdf0e10cSrcweir 							   &win_x, &win_y,
3266cdf0e10cSrcweir 							   &mask ) )
3267cdf0e10cSrcweir 			{
3268cdf0e10cSrcweir 				aParent = it->second.m_aRootWindow;
3269cdf0e10cSrcweir 				break;
3270cdf0e10cSrcweir 			}
3271cdf0e10cSrcweir 			++it;
3272cdf0e10cSrcweir 		}
3273cdf0e10cSrcweir 
3274cdf0e10cSrcweir         // don't start DnD if there is none of our windows on the same screen as
3275cdf0e10cSrcweir         // the pointer or if no mouse button is pressed
3276cdf0e10cSrcweir 		if( it == m_aDropTargets.end() || (mask & (Button1Mask|Button2Mask|Button3Mask)) == 0 )
3277cdf0e10cSrcweir 		{
3278cdf0e10cSrcweir             aGuard.clear();
3279cdf0e10cSrcweir 			if( listener.is() )
3280cdf0e10cSrcweir 				listener->dragDropEnd( aDragFailedEvent );
3281cdf0e10cSrcweir 			return;
3282cdf0e10cSrcweir 		}
3283cdf0e10cSrcweir 
3284cdf0e10cSrcweir         // try to find which of our drop targets is the drag source
3285cdf0e10cSrcweir         // if that drop target is deregistered we should stop executing
3286cdf0e10cSrcweir         // the drag (actually this is a poor substitute for an "endDrag"
3287cdf0e10cSrcweir         // method ).
3288cdf0e10cSrcweir         m_aDragSourceWindow = None;
3289cdf0e10cSrcweir         aParent = aRoot = it->second.m_aRootWindow;
3290cdf0e10cSrcweir         do
3291cdf0e10cSrcweir         {
3292cdf0e10cSrcweir             XTranslateCoordinates( m_pDisplay, aRoot, aParent, root_x, root_y, &win_x, &win_y, &aChild );
3293cdf0e10cSrcweir             if( aChild != None && m_aDropTargets.find( aChild ) != m_aDropTargets.end() )
3294cdf0e10cSrcweir             {
3295cdf0e10cSrcweir                 m_aDragSourceWindow = aChild;
3296cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3297cdf0e10cSrcweir                 fprintf( stderr, "found drag source window 0x%lx\n", m_aDragSourceWindow );
3298cdf0e10cSrcweir #endif
3299cdf0e10cSrcweir                 break;
3300cdf0e10cSrcweir             }
3301cdf0e10cSrcweir             aParent = aChild;
3302cdf0e10cSrcweir         } while( aChild != None );
3303cdf0e10cSrcweir 
3304cdf0e10cSrcweir 
3305cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3306cdf0e10cSrcweir 		fprintf( stderr, "try to grab pointer ... " );
3307cdf0e10cSrcweir #endif
3308cdf0e10cSrcweir 		int nPointerGrabSuccess =
3309cdf0e10cSrcweir 			XGrabPointer( m_pDisplay, it->second.m_aRootWindow, True,
3310cdf0e10cSrcweir 						  DRAG_EVENT_MASK,
3311cdf0e10cSrcweir 						  GrabModeAsync, GrabModeAsync,
3312cdf0e10cSrcweir 						  None,
3313cdf0e10cSrcweir 						  None,
3314cdf0e10cSrcweir 						  CurrentTime );
3315cdf0e10cSrcweir         /* if we could not grab the pointer here, there is a chance
3316cdf0e10cSrcweir            that the pointer is grabbed by the other vcl display (the main loop)
3317cdf0e10cSrcweir            so let's break that grab an reset it later
3318cdf0e10cSrcweir 
3319cdf0e10cSrcweir            remark: this whole code should really be molten into normal vcl so only
3320cdf0e10cSrcweir            one display is used ....
3321cdf0e10cSrcweir         */
3322cdf0e10cSrcweir         if( nPointerGrabSuccess != GrabSuccess )
3323cdf0e10cSrcweir         {
3324cdf0e10cSrcweir             vos::IMutex& rSolarMutex( Application::GetSolarMutex() );
3325cdf0e10cSrcweir             if( rSolarMutex.tryToAcquire() )
3326cdf0e10cSrcweir             {
3327cdf0e10cSrcweir                 pCaptureFrame = GetX11SalData()->GetDisplay()->GetCaptureFrame();
3328cdf0e10cSrcweir                 if( pCaptureFrame )
3329cdf0e10cSrcweir                 {
3330cdf0e10cSrcweir                     GetX11SalData()->GetDisplay()->CaptureMouse( NULL );
3331cdf0e10cSrcweir                     nPointerGrabSuccess =
3332cdf0e10cSrcweir                                 XGrabPointer( m_pDisplay, it->second.m_aRootWindow, True,
3333cdf0e10cSrcweir                                               DRAG_EVENT_MASK,
3334cdf0e10cSrcweir                                               GrabModeAsync, GrabModeAsync,
3335cdf0e10cSrcweir                                               None,
3336cdf0e10cSrcweir                                               None,
3337cdf0e10cSrcweir                                               CurrentTime );
3338cdf0e10cSrcweir                 }
3339cdf0e10cSrcweir             }
3340cdf0e10cSrcweir         }
3341cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3342cdf0e10cSrcweir 		fprintf( stderr, "%d\n", nPointerGrabSuccess );
3343cdf0e10cSrcweir #endif
3344cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3345cdf0e10cSrcweir 		fprintf( stderr, "try to grab keyboard ... " );
3346cdf0e10cSrcweir #endif
3347cdf0e10cSrcweir 		int nKeyboardGrabSuccess =
3348cdf0e10cSrcweir 			XGrabKeyboard( m_pDisplay, it->second.m_aRootWindow, True,
3349cdf0e10cSrcweir                            GrabModeAsync, GrabModeAsync, CurrentTime );
3350cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3351cdf0e10cSrcweir 		fprintf( stderr, "%d\n", nKeyboardGrabSuccess );
3352cdf0e10cSrcweir #endif
3353cdf0e10cSrcweir 		if( nPointerGrabSuccess != GrabSuccess || nKeyboardGrabSuccess != GrabSuccess )
3354cdf0e10cSrcweir 		{
3355cdf0e10cSrcweir 			if( nPointerGrabSuccess == GrabSuccess )
3356cdf0e10cSrcweir 				XUngrabPointer( m_pDisplay, CurrentTime );
3357cdf0e10cSrcweir 			if( nKeyboardGrabSuccess == GrabSuccess )
3358cdf0e10cSrcweir 				XUngrabKeyboard( m_pDisplay, CurrentTime );
3359cdf0e10cSrcweir             XFlush( m_pDisplay );
3360cdf0e10cSrcweir             aGuard.clear();
3361cdf0e10cSrcweir 			if( listener.is() )
3362cdf0e10cSrcweir 				listener->dragDropEnd( aDragFailedEvent );
3363cdf0e10cSrcweir             if( pCaptureFrame )
3364cdf0e10cSrcweir             {
3365cdf0e10cSrcweir                 vos::IMutex& rSolarMutex( Application::GetSolarMutex() );
3366cdf0e10cSrcweir                 if( rSolarMutex.tryToAcquire() )
3367cdf0e10cSrcweir                     GetX11SalData()->GetDisplay()->CaptureMouse( pCaptureFrame );
3368cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
3369cdf0e10cSrcweir                 else
3370cdf0e10cSrcweir                     OSL_ENSURE( 0, "failed to acquire SolarMutex to reset capture frame" );
3371cdf0e10cSrcweir #endif
3372cdf0e10cSrcweir             }
3373cdf0e10cSrcweir 			return;
3374cdf0e10cSrcweir 		}
3375cdf0e10cSrcweir 
3376cdf0e10cSrcweir 		m_xDragSourceTransferable	= transferable;
3377cdf0e10cSrcweir 		m_xDragSourceListener		= listener;
3378cdf0e10cSrcweir 		m_aDragFlavors				= transferable->getTransferDataFlavors();
3379cdf0e10cSrcweir 		m_aCurrentCursor			= None;
3380cdf0e10cSrcweir 
3381cdf0e10cSrcweir 		requestOwnership( m_nXdndSelection );
3382cdf0e10cSrcweir 
3383cdf0e10cSrcweir         ::std::list< Atom > aConversions;
3384cdf0e10cSrcweir         ::std::list< Atom >::const_iterator type_it;
3385cdf0e10cSrcweir         getNativeTypeList( m_aDragFlavors, aConversions, m_nXdndSelection );
3386cdf0e10cSrcweir 
3387cdf0e10cSrcweir         int nTypes = aConversions.size();
3388cdf0e10cSrcweir 		Atom* pTypes = (Atom*)alloca( sizeof(Atom)*nTypes );
3389cdf0e10cSrcweir         type_it = aConversions.begin();
3390cdf0e10cSrcweir         for( int n = 0; n < nTypes; n++, ++type_it )
3391cdf0e10cSrcweir             pTypes[n] = *type_it;
3392cdf0e10cSrcweir 
3393cdf0e10cSrcweir 		XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, nTypes );
3394cdf0e10cSrcweir 
3395cdf0e10cSrcweir 		m_nSourceActions				= sourceActions | DNDConstants::ACTION_DEFAULT;
3396cdf0e10cSrcweir 		m_nUserDragAction				= DNDConstants::ACTION_MOVE & m_nSourceActions;
3397cdf0e10cSrcweir         if( ! m_nUserDragAction )
3398cdf0e10cSrcweir             m_nUserDragAction			= DNDConstants::ACTION_COPY & m_nSourceActions;
3399cdf0e10cSrcweir         if( ! m_nUserDragAction )
3400cdf0e10cSrcweir             m_nUserDragAction			= DNDConstants::ACTION_LINK & m_nSourceActions;
3401cdf0e10cSrcweir         m_nTargetAcceptAction			= DNDConstants::ACTION_DEFAULT;
3402cdf0e10cSrcweir 		m_bDropSent						= false;
3403cdf0e10cSrcweir 		m_bDropSuccess					= false;
3404cdf0e10cSrcweir 		m_bWaitingForPrimaryConversion	= false;
3405cdf0e10cSrcweir 		m_nDragButton					= Button1; // default to left button
3406cdf0e10cSrcweir         com::sun::star::awt::MouseEvent aEvent;
3407cdf0e10cSrcweir 		if( trigger.Event >>= aEvent )
3408cdf0e10cSrcweir 		{
3409cdf0e10cSrcweir 			if( aEvent.Buttons & MouseButton::LEFT )
3410cdf0e10cSrcweir 				m_nDragButton = Button1;
3411cdf0e10cSrcweir 			else if( aEvent.Buttons & MouseButton::RIGHT )
3412cdf0e10cSrcweir 				m_nDragButton = Button3;
3413cdf0e10cSrcweir 			else if( aEvent.Buttons & MouseButton::MIDDLE )
3414cdf0e10cSrcweir 				m_nDragButton = Button2;
3415cdf0e10cSrcweir 		}
3416cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3417cdf0e10cSrcweir         fprintf( stderr, "m_nUserDragAction = %x\n", (int)m_nUserDragAction );
3418cdf0e10cSrcweir #endif
3419cdf0e10cSrcweir 		updateDragWindow( root_x, root_y, aRoot );
3420cdf0e10cSrcweir         m_nUserDragAction = ~0;
3421cdf0e10cSrcweir 		updateDragAction( mask );
3422cdf0e10cSrcweir 	}
3423cdf0e10cSrcweir 
3424cdf0e10cSrcweir     m_aDragRunning.set();
3425cdf0e10cSrcweir 	m_aDragExecuteThread = osl_createSuspendedThread( call_SelectionManager_runDragExecute, this );
3426cdf0e10cSrcweir     if( m_aDragExecuteThread )
3427cdf0e10cSrcweir         osl_resumeThread( m_aDragExecuteThread );
3428cdf0e10cSrcweir     else
3429cdf0e10cSrcweir     {
3430cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3431cdf0e10cSrcweir         fprintf( stderr, "osl_createSuspendedThread failed for drag execute\n" );
3432cdf0e10cSrcweir #endif
3433cdf0e10cSrcweir         m_xDragSourceListener.clear();
3434cdf0e10cSrcweir         m_xDragSourceTransferable.clear();
3435cdf0e10cSrcweir 
3436cdf0e10cSrcweir 		m_bDropSent							= false;
3437cdf0e10cSrcweir 		m_bDropSuccess						= false;
3438cdf0e10cSrcweir 		m_bWaitingForPrimaryConversion		= false;
3439cdf0e10cSrcweir 		m_aDropWindow						= None;
3440cdf0e10cSrcweir 		m_aDropProxy						= None;
3441cdf0e10cSrcweir 		m_nCurrentProtocolVersion			= nXdndProtocolRevision;
3442cdf0e10cSrcweir 		m_nNoPosX							= 0;
3443cdf0e10cSrcweir 		m_nNoPosY							= 0;
3444cdf0e10cSrcweir 		m_nNoPosWidth						= 0;
3445cdf0e10cSrcweir 		m_nNoPosHeight						= 0;
3446cdf0e10cSrcweir 		m_aCurrentCursor					= None;
3447cdf0e10cSrcweir 
3448cdf0e10cSrcweir 		XUngrabPointer( m_pDisplay, CurrentTime );
3449cdf0e10cSrcweir 		XUngrabKeyboard( m_pDisplay, CurrentTime );
3450cdf0e10cSrcweir         XFlush( m_pDisplay );
3451cdf0e10cSrcweir 
3452cdf0e10cSrcweir         if( pCaptureFrame )
3453cdf0e10cSrcweir         {
3454cdf0e10cSrcweir             vos::IMutex& rSolarMutex( Application::GetSolarMutex() );
3455cdf0e10cSrcweir             if( rSolarMutex.tryToAcquire() )
3456cdf0e10cSrcweir                 GetX11SalData()->GetDisplay()->CaptureMouse( pCaptureFrame );
3457cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
3458cdf0e10cSrcweir             else
3459cdf0e10cSrcweir                 OSL_ENSURE( 0, "failed to acquire SolarMutex to reset capture frame" );
3460cdf0e10cSrcweir #endif
3461cdf0e10cSrcweir         }
3462cdf0e10cSrcweir 
3463cdf0e10cSrcweir         m_aDragRunning.reset();
3464cdf0e10cSrcweir 
3465cdf0e10cSrcweir 		if( listener.is() )
3466cdf0e10cSrcweir 			listener->dragDropEnd( aDragFailedEvent );
3467cdf0e10cSrcweir     }
3468cdf0e10cSrcweir }
3469cdf0e10cSrcweir 
runDragExecute(void * pThis)3470cdf0e10cSrcweir void SelectionManager::runDragExecute( void* pThis )
3471cdf0e10cSrcweir {
3472cdf0e10cSrcweir 	SelectionManager* This = (SelectionManager*)pThis;
3473cdf0e10cSrcweir 	This->dragDoDispatch();
3474cdf0e10cSrcweir }
3475cdf0e10cSrcweir 
dragDoDispatch()3476cdf0e10cSrcweir void SelectionManager::dragDoDispatch()
3477cdf0e10cSrcweir {
3478cdf0e10cSrcweir 
3479cdf0e10cSrcweir 	// do drag
3480cdf0e10cSrcweir 	// m_xDragSourceListener will be cleared on finished drop
3481cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3482cdf0e10cSrcweir 	fprintf( stderr, "begin executeDrag dispatching\n" );
3483cdf0e10cSrcweir #endif
3484cdf0e10cSrcweir 	TimeValue aTVal;
3485cdf0e10cSrcweir 	aTVal.Seconds = 0;
3486cdf0e10cSrcweir 	aTVal.Nanosec = 200000000;
3487cdf0e10cSrcweir 	oslThread aThread = m_aDragExecuteThread;
3488cdf0e10cSrcweir 	while( m_xDragSourceListener.is() && ( ! m_bDropSent || time(NULL)-m_nDropTimeout < 5 ) && osl_scheduleThread( aThread ) )
3489cdf0e10cSrcweir 	{
3490cdf0e10cSrcweir         // let the thread in the run method do the dispatching
3491cdf0e10cSrcweir         // just look occasionally here whether drop timed out or is completed
3492cdf0e10cSrcweir 		osl_waitThread( &aTVal );
3493cdf0e10cSrcweir 	}
3494cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3495cdf0e10cSrcweir 	fprintf( stderr, "end executeDrag dispatching\n" );
3496cdf0e10cSrcweir #endif
3497cdf0e10cSrcweir 	{
3498cdf0e10cSrcweir 		ClearableMutexGuard aGuard(m_aMutex);
3499cdf0e10cSrcweir 
3500cdf0e10cSrcweir         css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
3501cdf0e10cSrcweir         css::uno::Reference< XTransferable > xTransferable( m_xDragSourceTransferable );
3502cdf0e10cSrcweir         m_xDragSourceListener.clear();
3503cdf0e10cSrcweir         m_xDragSourceTransferable.clear();
3504cdf0e10cSrcweir 
3505cdf0e10cSrcweir         DragSourceDropEvent dsde;
3506cdf0e10cSrcweir         dsde.Source				= static_cast< OWeakObject* >(this);
3507cdf0e10cSrcweir         dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
3508cdf0e10cSrcweir         dsde.DragSource			= static_cast< XDragSource* >(this);
3509cdf0e10cSrcweir         dsde.DropAction			= DNDConstants::ACTION_NONE;
3510cdf0e10cSrcweir         dsde.DropSuccess		= sal_False;
3511cdf0e10cSrcweir 
3512cdf0e10cSrcweir 		// cleanup after drag
3513cdf0e10cSrcweir 		if( m_bWaitingForPrimaryConversion )
3514cdf0e10cSrcweir 			getAdaptor( XA_PRIMARY )->clearTransferable();
3515cdf0e10cSrcweir 
3516cdf0e10cSrcweir 		m_bDropSent							= false;
3517cdf0e10cSrcweir 		m_bDropSuccess						= false;
3518cdf0e10cSrcweir 		m_bWaitingForPrimaryConversion		= false;
3519cdf0e10cSrcweir 		m_aDropWindow						= None;
3520cdf0e10cSrcweir 		m_aDropProxy						= None;
3521cdf0e10cSrcweir 		m_nCurrentProtocolVersion			= nXdndProtocolRevision;
3522cdf0e10cSrcweir 		m_nNoPosX							= 0;
3523cdf0e10cSrcweir 		m_nNoPosY							= 0;
3524cdf0e10cSrcweir 		m_nNoPosWidth						= 0;
3525cdf0e10cSrcweir 		m_nNoPosHeight						= 0;
3526cdf0e10cSrcweir 		m_aCurrentCursor					= None;
3527cdf0e10cSrcweir 
3528cdf0e10cSrcweir 		XUngrabPointer( m_pDisplay, CurrentTime );
3529cdf0e10cSrcweir 		XUngrabKeyboard( m_pDisplay, CurrentTime );
3530cdf0e10cSrcweir         XFlush( m_pDisplay );
3531cdf0e10cSrcweir 
3532cdf0e10cSrcweir 		m_aDragExecuteThread = NULL;
3533cdf0e10cSrcweir         m_aDragRunning.reset();
3534cdf0e10cSrcweir 
3535cdf0e10cSrcweir         aGuard.clear();
3536cdf0e10cSrcweir         if( xListener.is() )
3537cdf0e10cSrcweir 		{
3538cdf0e10cSrcweir             xTransferable.clear();
3539cdf0e10cSrcweir 			xListener->dragDropEnd( dsde );
3540cdf0e10cSrcweir 		}
3541cdf0e10cSrcweir 	}
3542cdf0e10cSrcweir 	osl_destroyThread( aThread );
3543cdf0e10cSrcweir }
3544cdf0e10cSrcweir 
3545cdf0e10cSrcweir /*
3546cdf0e10cSrcweir  *	XDragSourceContext
3547cdf0e10cSrcweir  */
3548cdf0e10cSrcweir 
getCurrentCursor()3549cdf0e10cSrcweir sal_Int32 SelectionManager::getCurrentCursor()
3550cdf0e10cSrcweir {
3551cdf0e10cSrcweir 	return m_aCurrentCursor;
3552cdf0e10cSrcweir }
3553cdf0e10cSrcweir 
3554cdf0e10cSrcweir // ------------------------------------------------------------------------
3555cdf0e10cSrcweir 
setCursor(sal_Int32 cursor,XLIB_Window aDropWindow,XLIB_Time)3556cdf0e10cSrcweir void SelectionManager::setCursor( sal_Int32 cursor, XLIB_Window aDropWindow, XLIB_Time )
3557cdf0e10cSrcweir {
3558cdf0e10cSrcweir     MutexGuard aGuard( m_aMutex );
3559cdf0e10cSrcweir 	if( aDropWindow == m_aDropWindow && XLIB_Cursor(cursor) != m_aCurrentCursor )
3560cdf0e10cSrcweir 	{
3561cdf0e10cSrcweir 		if( m_xDragSourceListener.is() && ! m_bDropSent )
3562cdf0e10cSrcweir 		{
3563cdf0e10cSrcweir 			m_aCurrentCursor = cursor;
3564cdf0e10cSrcweir 			XChangeActivePointerGrab( m_pDisplay, DRAG_EVENT_MASK, cursor, CurrentTime );
3565cdf0e10cSrcweir 			XFlush( m_pDisplay );
3566cdf0e10cSrcweir 		}
3567cdf0e10cSrcweir 	}
3568cdf0e10cSrcweir }
3569cdf0e10cSrcweir 
3570cdf0e10cSrcweir // ------------------------------------------------------------------------
3571cdf0e10cSrcweir 
setImage(sal_Int32,XLIB_Window,XLIB_Time)3572cdf0e10cSrcweir void SelectionManager::setImage( sal_Int32, XLIB_Window, XLIB_Time )
3573cdf0e10cSrcweir {
3574cdf0e10cSrcweir }
3575cdf0e10cSrcweir 
3576cdf0e10cSrcweir // ------------------------------------------------------------------------
3577cdf0e10cSrcweir 
transferablesFlavorsChanged()3578cdf0e10cSrcweir void SelectionManager::transferablesFlavorsChanged()
3579cdf0e10cSrcweir {
3580cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
3581cdf0e10cSrcweir 
3582cdf0e10cSrcweir 	m_aDragFlavors = m_xDragSourceTransferable->getTransferDataFlavors();
3583cdf0e10cSrcweir 	int i;
3584cdf0e10cSrcweir 
3585cdf0e10cSrcweir     std::list< Atom > aConversions;
3586cdf0e10cSrcweir     std::list< Atom >::const_iterator type_it;
3587cdf0e10cSrcweir 
3588cdf0e10cSrcweir     getNativeTypeList( m_aDragFlavors, aConversions, m_nXdndSelection );
3589cdf0e10cSrcweir 
3590cdf0e10cSrcweir     int nTypes = aConversions.size();
3591cdf0e10cSrcweir 	Atom* pTypes = (Atom*)alloca( sizeof(Atom)*aConversions.size() );
3592cdf0e10cSrcweir     for( i = 0, type_it = aConversions.begin(); type_it != aConversions.end(); ++type_it, i++ )
3593cdf0e10cSrcweir         pTypes[i] = *type_it;
3594cdf0e10cSrcweir 	XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, nTypes );
3595cdf0e10cSrcweir 
3596cdf0e10cSrcweir 	if( m_aCurrentDropWindow != None && m_nCurrentProtocolVersion >= 0 )
3597cdf0e10cSrcweir 	{
3598cdf0e10cSrcweir 		// send synthetic leave and enter events
3599cdf0e10cSrcweir 
3600cdf0e10cSrcweir 		XEvent aEvent;
3601cdf0e10cSrcweir 
3602cdf0e10cSrcweir 		aEvent.type = ClientMessage;
3603cdf0e10cSrcweir 		aEvent.xclient.display			= m_pDisplay;
3604cdf0e10cSrcweir 		aEvent.xclient.format			= 32;
3605cdf0e10cSrcweir 		aEvent.xclient.window			= m_aDropWindow;
3606cdf0e10cSrcweir 		aEvent.xclient.data.l[0]		= m_aWindow;
3607cdf0e10cSrcweir 
3608cdf0e10cSrcweir 		aEvent.xclient.message_type		= m_nXdndLeave;
3609cdf0e10cSrcweir 		aEvent.xclient.data.l[1]		= 0;
3610cdf0e10cSrcweir 		XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
3611cdf0e10cSrcweir 
3612cdf0e10cSrcweir 		aEvent.xclient.message_type	= m_nXdndEnter;
3613cdf0e10cSrcweir 		aEvent.xclient.data.l[1]	= m_nCurrentProtocolVersion << 24;
3614cdf0e10cSrcweir 		memset( aEvent.xclient.data.l + 2, 0, sizeof( long )*3 );
3615cdf0e10cSrcweir 		// fill in data types
3616cdf0e10cSrcweir 		if( nTypes > 3 )
3617cdf0e10cSrcweir 			aEvent.xclient.data.l[1] |= 1;
3618cdf0e10cSrcweir 		for( int j = 0; j < nTypes && j < 3; j++ )
3619cdf0e10cSrcweir 			aEvent.xclient.data.l[j+2] = pTypes[j];
3620cdf0e10cSrcweir 
3621cdf0e10cSrcweir 		XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
3622cdf0e10cSrcweir 	}
3623cdf0e10cSrcweir }
3624cdf0e10cSrcweir 
3625cdf0e10cSrcweir /*
3626cdf0e10cSrcweir  *	dispatch loop
3627cdf0e10cSrcweir  */
3628cdf0e10cSrcweir 
3629cdf0e10cSrcweir // ------------------------------------------------------------------------
3630cdf0e10cSrcweir 
handleXEvent(XEvent & rEvent)3631cdf0e10cSrcweir bool SelectionManager::handleXEvent( XEvent& rEvent )
3632cdf0e10cSrcweir {
3633cdf0e10cSrcweir 	/*
3634cdf0e10cSrcweir 	 *	since we are XConnectionListener to a second X display
3635cdf0e10cSrcweir 	 *	to get client messages it is essential not to dispatch
3636cdf0e10cSrcweir 	 *	events twice that we get on both connections
3637cdf0e10cSrcweir      *
3638cdf0e10cSrcweir      *  #95201# between dispatching ButtonPress and startDrag
3639cdf0e10cSrcweir      *  the user can already have released the mouse. The ButtonRelease
3640cdf0e10cSrcweir      *  will then be dispatched in VCLs queue and never turn up here.
3641cdf0e10cSrcweir      *  Which is not so good, since startDrag will XGrabPointer and
3642cdf0e10cSrcweir      *  XGrabKeyboard -> solid lock.
3643cdf0e10cSrcweir 	 */
3644cdf0e10cSrcweir 	if( rEvent.xany.display != m_pDisplay
3645cdf0e10cSrcweir         && rEvent.type != ClientMessage
3646cdf0e10cSrcweir         && rEvent.type != ButtonPress
3647cdf0e10cSrcweir         && rEvent.type != ButtonRelease
3648cdf0e10cSrcweir         )
3649cdf0e10cSrcweir 		return false;
3650cdf0e10cSrcweir 
3651cdf0e10cSrcweir     bool bHandled = false;
3652cdf0e10cSrcweir 	switch (rEvent.type)
3653cdf0e10cSrcweir 	{
3654cdf0e10cSrcweir 		case SelectionClear:
3655cdf0e10cSrcweir 		{
3656cdf0e10cSrcweir             ClearableMutexGuard aGuard(m_aMutex);
3657cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3658cdf0e10cSrcweir 			fprintf( stderr, "SelectionClear for selection %s\n",
3659cdf0e10cSrcweir 					 OUStringToOString( getString( rEvent.xselectionclear.selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr()
3660cdf0e10cSrcweir 					 );
3661cdf0e10cSrcweir #endif
3662cdf0e10cSrcweir 			SelectionAdaptor* pAdaptor = getAdaptor( rEvent.xselectionclear.selection );
3663cdf0e10cSrcweir             std::hash_map< Atom, Selection* >::iterator it( m_aSelections.find( rEvent.xselectionclear.selection ) );
3664cdf0e10cSrcweir             if( it != m_aSelections.end() )
3665cdf0e10cSrcweir                 it->second->m_bOwner = false;
3666cdf0e10cSrcweir             aGuard.clear();
3667cdf0e10cSrcweir 			if ( pAdaptor )
3668cdf0e10cSrcweir 				pAdaptor->clearTransferable();
3669cdf0e10cSrcweir 		}
3670cdf0e10cSrcweir 		break;
3671cdf0e10cSrcweir 
3672cdf0e10cSrcweir 		case SelectionRequest:
3673cdf0e10cSrcweir 			bHandled = handleSelectionRequest( rEvent.xselectionrequest );
3674cdf0e10cSrcweir 			break;
3675cdf0e10cSrcweir 		case PropertyNotify:
3676cdf0e10cSrcweir 			if( rEvent.xproperty.window == m_aWindow ||
3677cdf0e10cSrcweir 				rEvent.xproperty.window == m_aCurrentDropWindow
3678cdf0e10cSrcweir 				)
3679cdf0e10cSrcweir 				bHandled = handleReceivePropertyNotify( rEvent.xproperty );
3680cdf0e10cSrcweir 			else
3681cdf0e10cSrcweir 				bHandled = handleSendPropertyNotify( rEvent.xproperty );
3682cdf0e10cSrcweir 			break;
3683cdf0e10cSrcweir 		case SelectionNotify:
3684cdf0e10cSrcweir 			bHandled = handleSelectionNotify( rEvent.xselection );
3685cdf0e10cSrcweir 			break;
3686cdf0e10cSrcweir 		case ClientMessage:
3687cdf0e10cSrcweir 			// messages from drag target
3688cdf0e10cSrcweir 			if( rEvent.xclient.message_type == m_nXdndStatus ||
3689cdf0e10cSrcweir 				rEvent.xclient.message_type == m_nXdndFinished )
3690cdf0e10cSrcweir 				bHandled = handleDragEvent( rEvent );
3691cdf0e10cSrcweir 			// messages from drag source
3692cdf0e10cSrcweir 			else if(
3693cdf0e10cSrcweir                     rEvent.xclient.message_type == m_nXdndEnter		||
3694cdf0e10cSrcweir                     rEvent.xclient.message_type == m_nXdndLeave		||
3695cdf0e10cSrcweir                     rEvent.xclient.message_type == m_nXdndPosition	||
3696cdf0e10cSrcweir                     rEvent.xclient.message_type == m_nXdndDrop
3697cdf0e10cSrcweir                     )
3698cdf0e10cSrcweir 				bHandled = handleDropEvent( rEvent.xclient );
3699cdf0e10cSrcweir 			break;
3700cdf0e10cSrcweir 		case EnterNotify:
3701cdf0e10cSrcweir 		case LeaveNotify:
3702cdf0e10cSrcweir 		case MotionNotify:
3703cdf0e10cSrcweir 		case ButtonPress:
3704cdf0e10cSrcweir 		case ButtonRelease:
3705cdf0e10cSrcweir 		case XLIB_KeyPress:
3706cdf0e10cSrcweir 		case KeyRelease:
3707cdf0e10cSrcweir 			bHandled = handleDragEvent( rEvent );
3708cdf0e10cSrcweir 			break;
3709cdf0e10cSrcweir 		default:
3710cdf0e10cSrcweir 			;
3711cdf0e10cSrcweir 	}
3712cdf0e10cSrcweir     return bHandled;
3713cdf0e10cSrcweir }
3714cdf0e10cSrcweir 
3715cdf0e10cSrcweir // ------------------------------------------------------------------------
3716cdf0e10cSrcweir 
dispatchEvent(int millisec)3717cdf0e10cSrcweir void SelectionManager::dispatchEvent( int millisec )
3718cdf0e10cSrcweir {
3719cdf0e10cSrcweir 	pollfd aPollFD;
3720cdf0e10cSrcweir 	XEvent event;
3721cdf0e10cSrcweir 
3722cdf0e10cSrcweir 	// query socket handle to poll on
3723cdf0e10cSrcweir 	aPollFD.fd      = ConnectionNumber( m_pDisplay );
3724cdf0e10cSrcweir 	aPollFD.events  = POLLIN;
3725cdf0e10cSrcweir 	aPollFD.revents = 0;
3726cdf0e10cSrcweir 
3727cdf0e10cSrcweir 	// wait for activity (outside the xlib)
3728cdf0e10cSrcweir 	if( poll( &aPollFD, 1, millisec ) > 0 )
3729cdf0e10cSrcweir 	{
3730cdf0e10cSrcweir 		// now acquire the mutex to prevent other threads
3731cdf0e10cSrcweir 		// from using the same X connection
3732cdf0e10cSrcweir 		ResettableMutexGuard aGuard(m_aMutex);
3733cdf0e10cSrcweir 
3734cdf0e10cSrcweir 		// prevent that another thread already ate the input
3735cdf0e10cSrcweir 		// this can happen if e.g. another thread does
3736cdf0e10cSrcweir 		// an X request getting a response. the response
3737cdf0e10cSrcweir 		// would be removed from the queue and we would end up
3738cdf0e10cSrcweir 		// with an empty socket here
3739cdf0e10cSrcweir 		if( poll( &aPollFD, 1, 0 ) > 0 )
3740cdf0e10cSrcweir 		{
3741cdf0e10cSrcweir             int nPending = 1;
3742cdf0e10cSrcweir 			while( nPending )
3743cdf0e10cSrcweir 			{
3744cdf0e10cSrcweir                 nPending = XPending( m_pDisplay );
3745cdf0e10cSrcweir                 if( nPending )
3746cdf0e10cSrcweir                 {
3747cdf0e10cSrcweir                     XNextEvent( m_pDisplay, &event );
3748cdf0e10cSrcweir                     aGuard.clear();
3749cdf0e10cSrcweir                     handleXEvent( event );
3750cdf0e10cSrcweir                     aGuard.reset();
3751cdf0e10cSrcweir                 }
3752cdf0e10cSrcweir 			}
3753cdf0e10cSrcweir 		}
3754cdf0e10cSrcweir 	}
3755cdf0e10cSrcweir }
3756cdf0e10cSrcweir 
3757cdf0e10cSrcweir // ------------------------------------------------------------------------
3758cdf0e10cSrcweir 
run(void * pThis)3759cdf0e10cSrcweir void SelectionManager::run( void* pThis )
3760cdf0e10cSrcweir {
3761cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3762cdf0e10cSrcweir 	fprintf(stderr, "SelectionManager::run\n" );
3763cdf0e10cSrcweir #endif
3764cdf0e10cSrcweir 	// dispatch until the cows come home
3765cdf0e10cSrcweir 
3766cdf0e10cSrcweir 	SelectionManager* This = (SelectionManager*)pThis;
3767cdf0e10cSrcweir 
3768cdf0e10cSrcweir 	timeval aLast;
3769cdf0e10cSrcweir 	gettimeofday( &aLast, 0 );
3770cdf0e10cSrcweir 
3771cdf0e10cSrcweir 	css::uno::Reference< XMultiServiceFactory > xFact( ::comphelper::getProcessServiceFactory() );
3772cdf0e10cSrcweir 	if( xFact.is() )
3773cdf0e10cSrcweir 	{
3774cdf0e10cSrcweir 		css::uno::Reference< XDesktop > xDesktop( xFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );
3775cdf0e10cSrcweir 		if( xDesktop.is() )
3776cdf0e10cSrcweir 			xDesktop->addTerminateListener(This);
3777cdf0e10cSrcweir 	}
3778cdf0e10cSrcweir 
3779cdf0e10cSrcweir 	while( osl_scheduleThread(This->m_aThread) )
3780cdf0e10cSrcweir 	{
3781cdf0e10cSrcweir 		This->dispatchEvent( 1000 );
3782cdf0e10cSrcweir 
3783cdf0e10cSrcweir 		timeval aNow;
3784cdf0e10cSrcweir 		gettimeofday( &aNow, 0 );
3785cdf0e10cSrcweir 
3786cdf0e10cSrcweir         if( (aNow.tv_sec - aLast.tv_sec) > 0 )
3787cdf0e10cSrcweir         {
3788cdf0e10cSrcweir             ClearableMutexGuard aGuard(This->m_aMutex);
3789cdf0e10cSrcweir             std::list< std::pair< SelectionAdaptor*, css::uno::Reference< XInterface > > > aChangeList;
3790cdf0e10cSrcweir 
3791cdf0e10cSrcweir             for( std::hash_map< Atom, Selection* >::iterator it = This->m_aSelections.begin(); it != This->m_aSelections.end(); ++it )
3792cdf0e10cSrcweir             {
3793cdf0e10cSrcweir                 if( it->first != This->m_nXdndSelection && ! it->second->m_bOwner )
3794cdf0e10cSrcweir                 {
3795cdf0e10cSrcweir                     XLIB_Window aOwner = XGetSelectionOwner( This->m_pDisplay, it->first );
3796cdf0e10cSrcweir                     if( aOwner != it->second->m_aLastOwner )
3797cdf0e10cSrcweir                     {
3798cdf0e10cSrcweir                         it->second->m_aLastOwner = aOwner;
3799cdf0e10cSrcweir                         std::pair< SelectionAdaptor*, css::uno::Reference< XInterface > >
3800cdf0e10cSrcweir                             aKeep( it->second->m_pAdaptor, it->second->m_pAdaptor->getReference() );
3801cdf0e10cSrcweir                         aChangeList.push_back( aKeep );
3802cdf0e10cSrcweir                     }
3803cdf0e10cSrcweir                 }
3804cdf0e10cSrcweir             }
3805cdf0e10cSrcweir             aGuard.clear();
3806cdf0e10cSrcweir             while( aChangeList.begin() != aChangeList.end() )
3807cdf0e10cSrcweir             {
3808cdf0e10cSrcweir                 aChangeList.front().first->fireContentsChanged();
3809cdf0e10cSrcweir                 aChangeList.pop_front();
3810cdf0e10cSrcweir             }
3811cdf0e10cSrcweir             aLast = aNow;
3812cdf0e10cSrcweir         }
3813cdf0e10cSrcweir 	}
3814cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
3815cdf0e10cSrcweir 	fprintf(stderr, "SelectionManager::run end\n" );
3816cdf0e10cSrcweir #endif
3817cdf0e10cSrcweir }
3818cdf0e10cSrcweir 
shutdown()3819cdf0e10cSrcweir void SelectionManager::shutdown() throw()
3820cdf0e10cSrcweir {
3821cdf0e10cSrcweir     ResettableMutexGuard aGuard(m_aMutex);
3822cdf0e10cSrcweir     if( m_bShutDown )
3823cdf0e10cSrcweir     {
3824cdf0e10cSrcweir         return;
3825cdf0e10cSrcweir     }
3826cdf0e10cSrcweir     m_bShutDown = true;
3827cdf0e10cSrcweir     // stop dispatching
3828cdf0e10cSrcweir     if( m_aThread )
3829cdf0e10cSrcweir     {
3830cdf0e10cSrcweir         osl_terminateThread( m_aThread );
3831cdf0e10cSrcweir         /*
3832cdf0e10cSrcweir          * Allow thread to finish before app exits to avoid pulling the carpet
3833cdf0e10cSrcweir          * out from under it if pasting is occuring during shutdown
3834cdf0e10cSrcweir          *
3835cdf0e10cSrcweir          * a) allow it to have the Mutex and
3836cdf0e10cSrcweir          * b) reschedule to allow it to complete callbacks to any
3837cdf0e10cSrcweir          * Application::GetSolarMutex protected regions, etc. e.g.
3838cdf0e10cSrcweir          * TransferableHelper::getTransferDataFlavors (via
3839cdf0e10cSrcweir          * SelectionManager::handleSelectionRequest) which it might
3840cdf0e10cSrcweir          * currently be trying to enter.
3841cdf0e10cSrcweir          *
3842cdf0e10cSrcweir          * Otherwise the thread may be left still waiting on a GlobalMutex
3843cdf0e10cSrcweir          * when that gets destroyed, letting the thread blow up and die
3844cdf0e10cSrcweir          * when enters the section in a now dead OOo instance.
3845cdf0e10cSrcweir          */
3846cdf0e10cSrcweir         aGuard.clear();
3847cdf0e10cSrcweir         while (osl_isThreadRunning(m_aThread))
3848cdf0e10cSrcweir         {
3849cdf0e10cSrcweir             vos::OGuard guard2(Application::GetSolarMutex());
3850cdf0e10cSrcweir             Application::Reschedule();
3851cdf0e10cSrcweir         }
3852cdf0e10cSrcweir         osl_joinWithThread( m_aThread );
3853cdf0e10cSrcweir         osl_destroyThread( m_aThread );
3854cdf0e10cSrcweir         m_aThread = NULL;
3855cdf0e10cSrcweir         aGuard.reset();
3856cdf0e10cSrcweir     }
3857cdf0e10cSrcweir     m_xDisplayConnection->removeEventHandler( Any(), this );
3858cdf0e10cSrcweir     m_xDisplayConnection.clear();
3859cdf0e10cSrcweir }
3860cdf0e10cSrcweir 
3861cdf0e10cSrcweir // ------------------------------------------------------------------------
3862cdf0e10cSrcweir 
handleEvent(const Any & event)3863cdf0e10cSrcweir sal_Bool SelectionManager::handleEvent( const Any& event ) throw()
3864cdf0e10cSrcweir {
3865cdf0e10cSrcweir     Sequence< sal_Int8 > aSeq;
3866cdf0e10cSrcweir     if( (event >>= aSeq) )
3867cdf0e10cSrcweir     {
3868cdf0e10cSrcweir         XEvent* pEvent = (XEvent*)aSeq.getArray();
3869cdf0e10cSrcweir         XLIB_Time nTimestamp = CurrentTime;
3870cdf0e10cSrcweir         if( pEvent->type == ButtonPress || pEvent->type == ButtonRelease )
3871cdf0e10cSrcweir             nTimestamp = pEvent->xbutton.time;
3872cdf0e10cSrcweir         else if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease )
3873cdf0e10cSrcweir             nTimestamp = pEvent->xkey.time;
3874cdf0e10cSrcweir         else if( pEvent->type == MotionNotify )
3875cdf0e10cSrcweir             nTimestamp = pEvent->xmotion.time;
3876cdf0e10cSrcweir         else if( pEvent->type == PropertyNotify )
3877cdf0e10cSrcweir             nTimestamp = pEvent->xproperty.time;
3878cdf0e10cSrcweir 
3879cdf0e10cSrcweir         if( nTimestamp != CurrentTime )
3880cdf0e10cSrcweir         {
3881cdf0e10cSrcweir             MutexGuard aGuard(m_aMutex);
3882cdf0e10cSrcweir 
3883cdf0e10cSrcweir             m_nSelectionTimestamp = nTimestamp;
3884cdf0e10cSrcweir         }
3885cdf0e10cSrcweir 
3886cdf0e10cSrcweir         return sal_Bool( handleXEvent( *pEvent ) );
3887cdf0e10cSrcweir     }
3888cdf0e10cSrcweir     else
3889cdf0e10cSrcweir     {
3890cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
3891cdf0e10cSrcweir         fprintf( stderr, "SelectionManager got downing event\n" );
3892cdf0e10cSrcweir         #endif
3893cdf0e10cSrcweir         shutdown();
3894cdf0e10cSrcweir     }
3895cdf0e10cSrcweir     return sal_True;
3896cdf0e10cSrcweir }
3897cdf0e10cSrcweir 
disposing(const::com::sun::star::lang::EventObject &)3898cdf0e10cSrcweir void SAL_CALL SelectionManager::disposing( const ::com::sun::star::lang::EventObject& )
3899cdf0e10cSrcweir     throw( ::com::sun::star::uno::RuntimeException )
3900cdf0e10cSrcweir {
3901cdf0e10cSrcweir }
3902cdf0e10cSrcweir 
queryTermination(const::com::sun::star::lang::EventObject &)3903cdf0e10cSrcweir void SAL_CALL SelectionManager::queryTermination( const ::com::sun::star::lang::EventObject& )
3904cdf0e10cSrcweir     throw( ::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException )
3905cdf0e10cSrcweir {
3906cdf0e10cSrcweir }
3907cdf0e10cSrcweir 
3908cdf0e10cSrcweir /*
3909cdf0e10cSrcweir  * To be safe, shutdown needs to be called before the ~SfxApplication is called, waiting until
3910cdf0e10cSrcweir  * the downing event can be too late if paste are requested during shutdown and ~SfxApplication
3911cdf0e10cSrcweir  * has been called before vcl is shutdown
3912cdf0e10cSrcweir  */
notifyTermination(const::com::sun::star::lang::EventObject & rEvent)3913cdf0e10cSrcweir void SAL_CALL SelectionManager::notifyTermination( const ::com::sun::star::lang::EventObject& rEvent )
3914cdf0e10cSrcweir     throw( ::com::sun::star::uno::RuntimeException )
3915cdf0e10cSrcweir {
3916cdf0e10cSrcweir     css::uno::Reference< XDesktop > xDesktop( rEvent.Source, UNO_QUERY );
3917cdf0e10cSrcweir     if( xDesktop.is() == sal_True )
3918cdf0e10cSrcweir         xDesktop->removeTerminateListener( this );
3919cdf0e10cSrcweir     #if OSL_DEBUG_LEVEL > 1
3920cdf0e10cSrcweir     fprintf( stderr, "SelectionManager got app termination event\n" );
3921cdf0e10cSrcweir     #endif
3922cdf0e10cSrcweir     shutdown();
3923cdf0e10cSrcweir }
3924cdf0e10cSrcweir 
3925cdf0e10cSrcweir // ------------------------------------------------------------------------
3926cdf0e10cSrcweir 
registerHandler(Atom selection,SelectionAdaptor & rAdaptor)3927cdf0e10cSrcweir void SelectionManager::registerHandler( Atom selection, SelectionAdaptor& rAdaptor )
3928cdf0e10cSrcweir {
3929cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
3930cdf0e10cSrcweir 
3931cdf0e10cSrcweir 	Selection* pNewSelection	= new Selection();
3932cdf0e10cSrcweir 	pNewSelection->m_pAdaptor	= &rAdaptor;
3933cdf0e10cSrcweir 	pNewSelection->m_aAtom		= selection;
3934cdf0e10cSrcweir 	m_aSelections[ selection ]	= pNewSelection;
3935cdf0e10cSrcweir }
3936cdf0e10cSrcweir 
3937cdf0e10cSrcweir // ------------------------------------------------------------------------
3938cdf0e10cSrcweir 
deregisterHandler(Atom selection)3939cdf0e10cSrcweir void SelectionManager::deregisterHandler( Atom selection )
3940cdf0e10cSrcweir {
3941cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
3942cdf0e10cSrcweir 
3943cdf0e10cSrcweir 	::std::hash_map< Atom, Selection* >::iterator it =
3944cdf0e10cSrcweir 		  m_aSelections.find( selection );
3945cdf0e10cSrcweir 	if( it != m_aSelections.end() )
3946cdf0e10cSrcweir 	{
3947cdf0e10cSrcweir         delete it->second->m_pPixmap;
3948cdf0e10cSrcweir 		delete it->second;
3949cdf0e10cSrcweir 		m_aSelections.erase( it );
3950cdf0e10cSrcweir 	}
3951cdf0e10cSrcweir }
3952cdf0e10cSrcweir 
3953cdf0e10cSrcweir // ------------------------------------------------------------------------
3954cdf0e10cSrcweir 
3955cdf0e10cSrcweir static bool bWasError = false;
3956cdf0e10cSrcweir 
3957cdf0e10cSrcweir extern "C"
3958cdf0e10cSrcweir {
local_xerror_handler(Display *,XErrorEvent *)3959cdf0e10cSrcweir     int local_xerror_handler(Display* , XErrorEvent*)
3960cdf0e10cSrcweir     {
3961cdf0e10cSrcweir         bWasError = true;
3962cdf0e10cSrcweir         return 0;
3963cdf0e10cSrcweir     }
3964cdf0e10cSrcweir     typedef int(*xerror_hdl_t)(Display*,XErrorEvent*);
3965cdf0e10cSrcweir }
3966cdf0e10cSrcweir 
registerDropTarget(XLIB_Window aWindow,DropTarget * pTarget)3967cdf0e10cSrcweir void SelectionManager::registerDropTarget( XLIB_Window aWindow, DropTarget* pTarget )
3968cdf0e10cSrcweir {
3969cdf0e10cSrcweir 	MutexGuard aGuard(m_aMutex);
3970cdf0e10cSrcweir 
3971cdf0e10cSrcweir 	// sanity check
3972cdf0e10cSrcweir 	::std::hash_map< XLIB_Window, DropTargetEntry >::const_iterator it =
3973cdf0e10cSrcweir 		  m_aDropTargets.find( aWindow );
3974cdf0e10cSrcweir 	if( it != m_aDropTargets.end() )
3975cdf0e10cSrcweir 		OSL_ASSERT( "attempt to register window as drop target twice" );
3976cdf0e10cSrcweir 	else if( aWindow && m_pDisplay )
3977cdf0e10cSrcweir 	{
3978cdf0e10cSrcweir 		DropTargetEntry aEntry( pTarget );
3979cdf0e10cSrcweir         bWasError=false;
3980cdf0e10cSrcweir         /* #i100000# ugly workaround: gtk sets its own XErrorHandler which is not suitable for us
3981cdf0e10cSrcweir            unfortunately XErrorHandler is not per display, so this is just and ugly hack
3982cdf0e10cSrcweir            Need to remove separate display and integrate clipboard/dnd into vcl's unx code ASAP
3983cdf0e10cSrcweir         */
3984cdf0e10cSrcweir 		xerror_hdl_t pOldHandler = XSetErrorHandler( local_xerror_handler );
3985cdf0e10cSrcweir 		XSelectInput( m_pDisplay, aWindow, PropertyChangeMask );
3986cdf0e10cSrcweir         if( ! bWasError )
3987cdf0e10cSrcweir         {
3988cdf0e10cSrcweir 		    // set XdndAware
3989cdf0e10cSrcweir 		    XChangeProperty( m_pDisplay, aWindow, m_nXdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&nXdndProtocolRevision, 1 );
3990cdf0e10cSrcweir             if( ! bWasError )
3991cdf0e10cSrcweir             {
3992cdf0e10cSrcweir 		        // get root window of window (in 99.999% of all cases this will be
3993cdf0e10cSrcweir 		        // DefaultRootWindow( m_pDisplay )
3994cdf0e10cSrcweir 		        int x, y;
3995cdf0e10cSrcweir 		        unsigned int w, h, bw, d;
3996cdf0e10cSrcweir 		        XGetGeometry( m_pDisplay, aWindow, &aEntry.m_aRootWindow,
3997cdf0e10cSrcweir 			                  &x, &y, &w, &h, &bw, &d );
3998cdf0e10cSrcweir             }
3999cdf0e10cSrcweir         }
4000cdf0e10cSrcweir         XSetErrorHandler( pOldHandler );
4001cdf0e10cSrcweir         if(bWasError)
4002cdf0e10cSrcweir             return;
4003cdf0e10cSrcweir 		m_aDropTargets[ aWindow ] = aEntry;
4004cdf0e10cSrcweir 	}
4005cdf0e10cSrcweir 	else
4006cdf0e10cSrcweir 		OSL_ASSERT( "attempt to register None as drop target" );
4007cdf0e10cSrcweir }
4008cdf0e10cSrcweir 
4009cdf0e10cSrcweir // ------------------------------------------------------------------------
4010cdf0e10cSrcweir 
deregisterDropTarget(XLIB_Window aWindow)4011cdf0e10cSrcweir void SelectionManager::deregisterDropTarget( XLIB_Window aWindow )
4012cdf0e10cSrcweir {
4013cdf0e10cSrcweir 	ClearableMutexGuard aGuard(m_aMutex);
4014cdf0e10cSrcweir 
4015cdf0e10cSrcweir 	m_aDropTargets.erase( aWindow );
4016cdf0e10cSrcweir     if( aWindow == m_aDragSourceWindow && m_aDragRunning.check() )
4017cdf0e10cSrcweir     {
4018cdf0e10cSrcweir         // abort drag
4019cdf0e10cSrcweir         std::hash_map< XLIB_Window, DropTargetEntry >::const_iterator it =
4020cdf0e10cSrcweir             m_aDropTargets.find( m_aDropWindow );
4021cdf0e10cSrcweir         if( it != m_aDropTargets.end() )
4022cdf0e10cSrcweir         {
4023cdf0e10cSrcweir             DropTargetEvent dte;
4024cdf0e10cSrcweir             dte.Source = static_cast< OWeakObject* >( it->second.m_pTarget );
4025cdf0e10cSrcweir             aGuard.clear();
4026cdf0e10cSrcweir             it->second.m_pTarget->dragExit( dte );
4027cdf0e10cSrcweir         }
4028cdf0e10cSrcweir         else if( m_aDropProxy != None && m_nCurrentProtocolVersion >= 0 )
4029cdf0e10cSrcweir         {
4030cdf0e10cSrcweir             // send XdndLeave
4031cdf0e10cSrcweir             XEvent aEvent;
4032cdf0e10cSrcweir             aEvent.type = ClientMessage;
4033cdf0e10cSrcweir             aEvent.xclient.display		= m_pDisplay;
4034cdf0e10cSrcweir             aEvent.xclient.format		= 32;
4035cdf0e10cSrcweir             aEvent.xclient.message_type	= m_nXdndLeave;
4036cdf0e10cSrcweir             aEvent.xclient.window		= m_aDropWindow;
4037cdf0e10cSrcweir             aEvent.xclient.data.l[0]	= m_aWindow;
4038cdf0e10cSrcweir             memset( aEvent.xclient.data.l+1, 0, sizeof(long)*4);
4039cdf0e10cSrcweir             m_aDropWindow = m_aDropProxy = None;
4040cdf0e10cSrcweir             XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
4041cdf0e10cSrcweir         }
4042cdf0e10cSrcweir         // notify the listener
4043cdf0e10cSrcweir         DragSourceDropEvent dsde;
4044cdf0e10cSrcweir         dsde.Source				= static_cast< OWeakObject* >(this);
4045cdf0e10cSrcweir         dsde.DragSourceContext	= new DragSourceContext( m_aDropWindow, m_nDragTimestamp, *this );
4046cdf0e10cSrcweir         dsde.DragSource			= static_cast< XDragSource* >(this);
4047cdf0e10cSrcweir         dsde.DropAction			= DNDConstants::ACTION_NONE;
4048cdf0e10cSrcweir         dsde.DropSuccess		= sal_False;
4049cdf0e10cSrcweir         css::uno::Reference< XDragSourceListener > xListener( m_xDragSourceListener );
4050cdf0e10cSrcweir         m_xDragSourceListener.clear();
4051cdf0e10cSrcweir         aGuard.clear();
4052cdf0e10cSrcweir         xListener->dragDropEnd( dsde );
4053cdf0e10cSrcweir     }
4054cdf0e10cSrcweir }
4055cdf0e10cSrcweir 
4056cdf0e10cSrcweir /*
4057cdf0e10cSrcweir  *	SelectionAdaptor
4058cdf0e10cSrcweir  */
4059cdf0e10cSrcweir 
getTransferable()4060cdf0e10cSrcweir css::uno::Reference< XTransferable > SelectionManager::getTransferable() throw()
4061cdf0e10cSrcweir {
4062cdf0e10cSrcweir 	return m_xDragSourceTransferable;
4063cdf0e10cSrcweir }
4064cdf0e10cSrcweir 
4065cdf0e10cSrcweir // ------------------------------------------------------------------------
4066cdf0e10cSrcweir 
clearTransferable()4067cdf0e10cSrcweir void SelectionManager::clearTransferable() throw()
4068cdf0e10cSrcweir {
4069cdf0e10cSrcweir 	m_xDragSourceTransferable.clear();
4070cdf0e10cSrcweir }
4071cdf0e10cSrcweir 
4072cdf0e10cSrcweir // ------------------------------------------------------------------------
4073cdf0e10cSrcweir 
fireContentsChanged()4074cdf0e10cSrcweir void SelectionManager::fireContentsChanged() throw()
4075cdf0e10cSrcweir {
4076cdf0e10cSrcweir }
4077cdf0e10cSrcweir 
4078cdf0e10cSrcweir // ------------------------------------------------------------------------
4079cdf0e10cSrcweir 
getReference()4080cdf0e10cSrcweir css::uno::Reference< XInterface > SelectionManager::getReference() throw()
4081cdf0e10cSrcweir {
4082cdf0e10cSrcweir     return css::uno::Reference< XInterface >( static_cast<OWeakObject*>(this) );
4083cdf0e10cSrcweir }
4084cdf0e10cSrcweir 
4085cdf0e10cSrcweir // ------------------------------------------------------------------------
4086cdf0e10cSrcweir 
4087cdf0e10cSrcweir /*
4088cdf0e10cSrcweir  *	SelectionManagerHolder
4089cdf0e10cSrcweir  */
4090cdf0e10cSrcweir 
SelectionManagerHolder()4091cdf0e10cSrcweir SelectionManagerHolder::SelectionManagerHolder() :
4092cdf0e10cSrcweir 		::cppu::WeakComponentImplHelper3<
4093cdf0e10cSrcweir     XDragSource,
4094cdf0e10cSrcweir     XInitialization,
4095cdf0e10cSrcweir     XServiceInfo > (m_aMutex)
4096cdf0e10cSrcweir {
4097cdf0e10cSrcweir }
4098cdf0e10cSrcweir 
4099cdf0e10cSrcweir // ------------------------------------------------------------------------
4100cdf0e10cSrcweir 
~SelectionManagerHolder()4101cdf0e10cSrcweir SelectionManagerHolder::~SelectionManagerHolder()
4102cdf0e10cSrcweir {
4103cdf0e10cSrcweir }
4104cdf0e10cSrcweir 
4105cdf0e10cSrcweir // ------------------------------------------------------------------------
4106cdf0e10cSrcweir 
initialize(const Sequence<Any> & arguments)4107cdf0e10cSrcweir void SelectionManagerHolder::initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception )
4108cdf0e10cSrcweir {
4109cdf0e10cSrcweir 	OUString aDisplayName;
4110cdf0e10cSrcweir 
4111cdf0e10cSrcweir 	if( arguments.getLength() > 0 )
4112cdf0e10cSrcweir 	{
4113cdf0e10cSrcweir 		css::uno::Reference< XDisplayConnection > xConn;
4114cdf0e10cSrcweir 		arguments.getConstArray()[0] >>= xConn;
4115cdf0e10cSrcweir 		if( xConn.is() )
4116cdf0e10cSrcweir 		{
4117cdf0e10cSrcweir 			Any aIdentifier;
4118cdf0e10cSrcweir 			aIdentifier >>= aDisplayName;
4119cdf0e10cSrcweir 		}
4120cdf0e10cSrcweir 	}
4121cdf0e10cSrcweir 
4122cdf0e10cSrcweir 	SelectionManager& rManager = SelectionManager::get( aDisplayName );
4123cdf0e10cSrcweir 	rManager.initialize( arguments );
4124cdf0e10cSrcweir 	m_xRealDragSource = static_cast< XDragSource* >(&rManager);
4125cdf0e10cSrcweir }
4126cdf0e10cSrcweir 
4127cdf0e10cSrcweir /*
4128cdf0e10cSrcweir  * 	XDragSource
4129cdf0e10cSrcweir  */
4130cdf0e10cSrcweir 
isDragImageSupported()4131cdf0e10cSrcweir sal_Bool SelectionManagerHolder::isDragImageSupported() throw()
4132cdf0e10cSrcweir {
4133cdf0e10cSrcweir 	return m_xRealDragSource.is() ? m_xRealDragSource->isDragImageSupported() : sal_False;
4134cdf0e10cSrcweir }
4135cdf0e10cSrcweir 
4136cdf0e10cSrcweir // ------------------------------------------------------------------------
4137cdf0e10cSrcweir 
getDefaultCursor(sal_Int8 dragAction)4138cdf0e10cSrcweir sal_Int32 SelectionManagerHolder::getDefaultCursor( sal_Int8 dragAction ) throw()
4139cdf0e10cSrcweir {
4140cdf0e10cSrcweir 	return m_xRealDragSource.is() ? m_xRealDragSource->getDefaultCursor( dragAction ) : 0;
4141cdf0e10cSrcweir }
4142cdf0e10cSrcweir 
4143cdf0e10cSrcweir // ------------------------------------------------------------------------
4144cdf0e10cSrcweir 
startDrag(const::com::sun::star::datatransfer::dnd::DragGestureEvent & trigger,sal_Int8 sourceActions,sal_Int32 cursor,sal_Int32 image,const css::uno::Reference<::com::sun::star::datatransfer::XTransferable> & transferable,const css::uno::Reference<::com::sun::star::datatransfer::dnd::XDragSourceListener> & listener)4145cdf0e10cSrcweir void SelectionManagerHolder::startDrag(
4146cdf0e10cSrcweir                                        const ::com::sun::star::datatransfer::dnd::DragGestureEvent& trigger,
4147cdf0e10cSrcweir                                        sal_Int8 sourceActions, sal_Int32 cursor, sal_Int32 image,
4148cdf0e10cSrcweir                                        const css::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& transferable,
4149cdf0e10cSrcweir                                        const css::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener >& listener
4150cdf0e10cSrcweir                                        ) throw()
4151cdf0e10cSrcweir {
4152cdf0e10cSrcweir 	if( m_xRealDragSource.is() )
4153cdf0e10cSrcweir 		m_xRealDragSource->startDrag( trigger, sourceActions, cursor, image, transferable, listener );
4154cdf0e10cSrcweir }
4155cdf0e10cSrcweir 
4156cdf0e10cSrcweir // ------------------------------------------------------------------------
4157cdf0e10cSrcweir 
4158cdf0e10cSrcweir /*
4159cdf0e10cSrcweir  *	XServiceInfo
4160cdf0e10cSrcweir  */
4161cdf0e10cSrcweir 
4162cdf0e10cSrcweir // ------------------------------------------------------------------------
4163cdf0e10cSrcweir 
getImplementationName()4164cdf0e10cSrcweir OUString SelectionManagerHolder::getImplementationName() throw()
4165cdf0e10cSrcweir {
4166cdf0e10cSrcweir 	return OUString::createFromAscii(XDND_IMPLEMENTATION_NAME);
4167cdf0e10cSrcweir }
4168cdf0e10cSrcweir 
4169cdf0e10cSrcweir // ------------------------------------------------------------------------
4170cdf0e10cSrcweir 
supportsService(const OUString & ServiceName)4171cdf0e10cSrcweir sal_Bool SelectionManagerHolder::supportsService( const OUString& ServiceName ) throw()
4172cdf0e10cSrcweir {
4173cdf0e10cSrcweir 	Sequence < OUString > SupportedServicesNames = Xdnd_getSupportedServiceNames();
4174cdf0e10cSrcweir 
4175cdf0e10cSrcweir 	for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
4176cdf0e10cSrcweir 		if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
4177cdf0e10cSrcweir 			return sal_True;
4178cdf0e10cSrcweir 
4179cdf0e10cSrcweir 	return sal_False;
4180cdf0e10cSrcweir }
4181cdf0e10cSrcweir 
4182cdf0e10cSrcweir // ------------------------------------------------------------------------
4183cdf0e10cSrcweir 
getSupportedServiceNames()4184cdf0e10cSrcweir Sequence< OUString > SelectionManagerHolder::getSupportedServiceNames() throw()
4185cdf0e10cSrcweir {
4186cdf0e10cSrcweir 	return Xdnd_getSupportedServiceNames();
4187cdf0e10cSrcweir }
4188cdf0e10cSrcweir 
4189cdf0e10cSrcweir 
4190cdf0e10cSrcweir // ------------------------------------------------------------------------
4191cdf0e10cSrcweir 
4192