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