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