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