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