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