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