/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_dtrans.hxx" //------------------------------------------------------------------------ // includes //------------------------------------------------------------------------ #include #include "WinClipbImpl.hxx" #include #include "..\..\inc\DtObjFactory.hxx" #include "..\dtobj\APNDataObject.hxx" #include "WinClipboard.hxx" #include #include "..\dtobj\XNotifyingDataObject.hxx" #if defined _MSC_VER #pragma warning(push,1) #endif #include #include #include #if defined _MSC_VER #pragma warning(pop) #endif //------------------------------------------------------------------------ // namespace directives //------------------------------------------------------------------------ using namespace rtl; using namespace osl; using namespace std; using namespace cppu; using namespace com::sun::star::uno; using namespace com::sun::star::datatransfer; using namespace com::sun::star::datatransfer::clipboard; using namespace com::sun::star::datatransfer::clipboard::RenderingCapabilities; //------------------------------------------------------------------------ // deklarations //------------------------------------------------------------------------ // definition of static members CWinClipbImpl* CWinClipbImpl::s_pCWinClipbImpl = NULL; osl::Mutex CWinClipbImpl::s_aMutex; //------------------------------------------------------------------------ // //------------------------------------------------------------------------ CWinClipbImpl::CWinClipbImpl( const OUString& aClipboardName, CWinClipboard* theWinClipboard ) : m_itsName( aClipboardName ), m_pWinClipboard( theWinClipboard ), m_pCurrentClipContent( NULL ) { OSL_ASSERT( NULL != m_pWinClipboard ); // necessary to reassociate from // the static callback function s_pCWinClipbImpl = this; registerClipboardViewer( ); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ CWinClipbImpl::~CWinClipbImpl( ) { ClearableMutexGuard aGuard( s_aMutex ); s_pCWinClipbImpl = NULL; aGuard.clear( ); unregisterClipboardViewer( ); } //------------------------------------------------------------------------ // getContent //------------------------------------------------------------------------ Reference< XTransferable > SAL_CALL CWinClipbImpl::getContents( ) throw( RuntimeException ) { // use the shotcut or create a transferable from // system clipboard ClearableMutexGuard aGuard( m_ClipContentMutex ); if ( NULL != m_pCurrentClipContent ) { return m_pCurrentClipContent->m_XTransferable; } // release the mutex, so that the variable may be // changed by other threads aGuard.clear( ); Reference< XTransferable > rClipContent; // get the current dataobject from clipboard IDataObjectPtr pIDataObject; HRESULT hr = m_MtaOleClipboard.getClipboard( &pIDataObject ); if ( SUCCEEDED( hr ) ) { // create an apartment neutral dataobject and initialize it with a // com smart pointer to the IDataObject from clipboard IDataObjectPtr pIDo( new CAPNDataObject( pIDataObject ) ); CDTransObjFactory objFactory; // remeber pIDo destroys itself due to the smart pointer rClipContent = objFactory.createTransferableFromDataObj( m_pWinClipboard->m_SrvMgr, pIDo ); } return rClipContent; } //------------------------------------------------------------------------ // setContent //------------------------------------------------------------------------ void SAL_CALL CWinClipbImpl::setContents( const Reference< XTransferable >& xTransferable, const Reference< XClipboardOwner >& xClipboardOwner ) throw( RuntimeException ) { CDTransObjFactory objFactory; IDataObjectPtr pIDataObj; if ( xTransferable.is( ) ) { ClearableMutexGuard aGuard( m_ClipContentMutex ); m_pCurrentClipContent = new CXNotifyingDataObject( objFactory.createDataObjFromTransferable( m_pWinClipboard->m_SrvMgr , xTransferable ), xTransferable, xClipboardOwner, this ); aGuard.clear( ); pIDataObj = IDataObjectPtr( m_pCurrentClipContent ); } m_MtaOleClipboard.setClipboard(pIDataObj.get()); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ OUString SAL_CALL CWinClipbImpl::getName( ) throw( RuntimeException ) { return m_itsName; } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ sal_Int8 SAL_CALL CWinClipbImpl::getRenderingCapabilities( ) throw( RuntimeException ) { return ( Delayed | Persistant ); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ void SAL_CALL CWinClipbImpl::flushClipboard( ) throw( RuntimeException ) { // sollte eigentlich hier stehen: ClearableMutexGuard aGuard( m_ClipContentMutex ); // geht aber nicht, da FlushClipboard zurückruft und das DataObject // freigibt und damit würde es einen Deadlock in onReleaseDataObject geben // FlushClipboard muß synchron sein, damit das runterfahren ggf. erst weitergeht, // wenn alle Clipboard-Formate gerendert wurden // die Abfrage ist nötig, damit nur geflusht wird, wenn wir wirklich Clipboardowner // sind (ich weiss nicht genau was passiert, wenn man flusht und nicht Clipboard // owner ist). // eventuell kann man aber die Abfrage in den Clipboard STA Thread verlagern, indem // man sich dort das DataObject merkt und vor dem flushen OleIsCurrentClipboard ruft if ( NULL != m_pCurrentClipContent ) m_MtaOleClipboard.flushClipboard( ); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ void SAL_CALL CWinClipbImpl::registerClipboardViewer( ) { m_MtaOleClipboard.registerClipViewer( CWinClipbImpl::onClipboardContentChanged ); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ void SAL_CALL CWinClipbImpl::unregisterClipboardViewer( ) { m_MtaOleClipboard.registerClipViewer( NULL ); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ void SAL_CALL CWinClipbImpl::dispose() throw( RuntimeException ) { OSL_ENSURE( !m_pCurrentClipContent, "Clipboard was not flushed before shutdown!" ); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ void WINAPI CWinClipbImpl::onClipboardContentChanged( void ) { MutexGuard aGuard( s_aMutex ); // reassocition to instance through static member if ( NULL != s_pCWinClipbImpl ) s_pCWinClipbImpl->m_pWinClipboard->notifyAllClipboardListener( ); } //------------------------------------------------------------------------ // //------------------------------------------------------------------------ void SAL_CALL CWinClipbImpl::onReleaseDataObject( CXNotifyingDataObject* theCaller ) { OSL_ASSERT( NULL != theCaller ); if ( theCaller ) theCaller->lostOwnership( ); // if the current caller is the one we currently // hold, then set it to NULL because an external // source must be the clipboardowner now MutexGuard aGuard( m_ClipContentMutex ); if ( m_pCurrentClipContent == theCaller ) m_pCurrentClipContent = NULL; }