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