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