| /************************************************************** |
| * |
| * 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_vcl.hxx" |
| |
| #include <cppuhelper/compbase1.hxx> |
| |
| #include <tools/debug.hxx> |
| |
| #include <vcl/svapp.hxx> |
| |
| #include <svdata.hxx> |
| #include <salinst.hxx> |
| #include <salsession.hxx> |
| |
| #include <com/sun/star/frame/XSessionManagerClient.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/frame/XSessionManagerListener2.hpp> |
| |
| #include <list> |
| |
| namespace { |
| |
| namespace css = com::sun::star; |
| |
| } |
| |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::lang; |
| using namespace com::sun::star::frame; |
| using namespace rtl; |
| |
| SalSession::~SalSession() |
| { |
| } |
| |
| class VCLSession : public cppu::WeakComponentImplHelper1 < XSessionManagerClient > |
| { |
| struct Listener |
| { |
| css::uno::Reference< XSessionManagerListener > m_xListener; |
| bool m_bInteractionRequested; |
| bool m_bInteractionDone; |
| bool m_bSaveDone; |
| |
| Listener( const css::uno::Reference< XSessionManagerListener >& xListener ) |
| : m_xListener( xListener ), |
| m_bInteractionRequested( false ), |
| m_bInteractionDone( false ), |
| m_bSaveDone( false ) |
| {} |
| }; |
| |
| std::list< Listener > m_aListeners; |
| SalSession* m_pSession; |
| osl::Mutex m_aMutex; |
| bool m_bInteractionRequested; |
| bool m_bInteractionGranted; |
| bool m_bInteractionDone; |
| bool m_bSaveDone; |
| |
| static void SalSessionEventProc( SalSessionEvent* pEvent ); |
| static VCLSession* pOneInstance; |
| |
| void callSaveRequested( bool bShutdown, bool bCancelable ); |
| void callShutdownCancelled(); |
| void callInteractionGranted( bool bGranted ); |
| void callQuit(); |
| public: |
| VCLSession(); |
| virtual ~VCLSession(); |
| |
| virtual void SAL_CALL addSessionManagerListener( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException ); |
| virtual void SAL_CALL removeSessionManagerListener( const css::uno::Reference< XSessionManagerListener>& xListener ) throw( RuntimeException ); |
| virtual void SAL_CALL queryInteraction( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException ); |
| virtual void SAL_CALL interactionDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException ); |
| virtual void SAL_CALL saveDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException ); |
| virtual sal_Bool SAL_CALL cancelShutdown() throw( RuntimeException ); |
| }; |
| |
| VCLSession* VCLSession::pOneInstance = NULL; |
| |
| VCLSession::VCLSession() |
| : cppu::WeakComponentImplHelper1< XSessionManagerClient >( m_aMutex ), |
| m_bInteractionRequested( false ), |
| m_bInteractionGranted( false ), |
| m_bInteractionDone( false ), |
| m_bSaveDone( false ) |
| { |
| DBG_ASSERT( pOneInstance == 0, "One instance of VCLSession only !" ); |
| pOneInstance = this; |
| m_pSession = ImplGetSVData()->mpDefInst->CreateSalSession(); |
| if( m_pSession ) |
| m_pSession->SetCallback( SalSessionEventProc ); |
| } |
| |
| VCLSession::~VCLSession() |
| { |
| DBG_ASSERT( pOneInstance == this, "Another instance of VCLSession in destructor !" ); |
| pOneInstance = NULL; |
| delete m_pSession; |
| } |
| |
| void VCLSession::callSaveRequested( bool bShutdown, bool bCancelable ) |
| { |
| std::list< Listener > aListeners; |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| // reset listener states |
| for( std::list< Listener >::iterator it = m_aListeners.begin(); |
| it != m_aListeners.end(); ++it ) |
| { |
| it->m_bSaveDone = it->m_bInteractionRequested = it->m_bInteractionDone = false; |
| } |
| |
| // copy listener list since calling a listener may remove it. |
| aListeners = m_aListeners; |
| // set back interaction state |
| m_bSaveDone = false; |
| m_bInteractionDone = false; |
| // without session we assume UI is always possible, |
| // so it was reqeusted and granted |
| m_bInteractionRequested = m_bInteractionGranted = m_pSession ? false : true; |
| |
| // answer the session manager even if no listeners available anymore |
| DBG_ASSERT( ! aListeners.empty(), "saveRequested but no listeners !" ); |
| if( aListeners.empty() ) |
| { |
| if( m_pSession ) |
| m_pSession->saveDone(); |
| return; |
| } |
| } |
| |
| sal_uLong nAcquireCount = Application::ReleaseSolarMutex(); |
| for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it ) |
| it->m_xListener->doSave( bShutdown, bCancelable ); |
| Application::AcquireSolarMutex( nAcquireCount ); |
| } |
| |
| void VCLSession::callInteractionGranted( bool bInteractionGranted ) |
| { |
| std::list< Listener > aListeners; |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| // copy listener list since calling a listener may remove it. |
| for( std::list< Listener >::const_iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it ) |
| if( it->m_bInteractionRequested ) |
| aListeners.push_back( *it ); |
| |
| m_bInteractionGranted = bInteractionGranted; |
| |
| // answer the session manager even if no listeners available anymore |
| DBG_ASSERT( ! aListeners.empty(), "interactionGranted but no listeners !" ); |
| if( aListeners.empty() ) |
| { |
| if( m_pSession ) |
| m_pSession->interactionDone(); |
| return; |
| } |
| } |
| |
| sal_uLong nAcquireCount = Application::ReleaseSolarMutex(); |
| for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it ) |
| it->m_xListener->approveInteraction( bInteractionGranted ); |
| |
| Application::AcquireSolarMutex( nAcquireCount ); |
| } |
| |
| void VCLSession::callShutdownCancelled() |
| { |
| std::list< Listener > aListeners; |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| // copy listener list since calling a listener may remove it. |
| aListeners = m_aListeners; |
| // set back interaction state |
| m_bInteractionRequested = m_bInteractionDone = m_bInteractionGranted = false; |
| } |
| |
| sal_uLong nAcquireCount = Application::ReleaseSolarMutex(); |
| for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it ) |
| it->m_xListener->shutdownCanceled(); |
| Application::AcquireSolarMutex( nAcquireCount ); |
| } |
| |
| void VCLSession::callQuit() |
| { |
| std::list< Listener > aListeners; |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| // copy listener list since calling a listener may remove it. |
| aListeners = m_aListeners; |
| // set back interaction state |
| m_bInteractionRequested = m_bInteractionDone = m_bInteractionGranted = false; |
| } |
| |
| sal_uLong nAcquireCount = Application::ReleaseSolarMutex(); |
| for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it ) |
| { |
| css::uno::Reference< XSessionManagerListener2 > xListener2( it->m_xListener, UNO_QUERY ); |
| if( xListener2.is() ) |
| xListener2->doQuit(); |
| } |
| Application::AcquireSolarMutex( nAcquireCount ); |
| } |
| |
| void VCLSession::SalSessionEventProc( SalSessionEvent* pEvent ) |
| { |
| switch( pEvent->m_eType ) |
| { |
| case Interaction: |
| { |
| SalSessionInteractionEvent* pIEv = static_cast<SalSessionInteractionEvent*>(pEvent); |
| pOneInstance->callInteractionGranted( pIEv->m_bInteractionGranted ); |
| } |
| break; |
| case SaveRequest: |
| { |
| SalSessionSaveRequestEvent* pSEv = static_cast<SalSessionSaveRequestEvent*>(pEvent); |
| pOneInstance->callSaveRequested( pSEv->m_bShutdown, pSEv->m_bCancelable ); |
| } |
| break; |
| case ShutdownCancel: |
| pOneInstance->callShutdownCancelled(); |
| break; |
| case Quit: |
| pOneInstance->callQuit(); |
| break; |
| } |
| } |
| |
| void SAL_CALL VCLSession::addSessionManagerListener( const css::uno::Reference<XSessionManagerListener>& xListener ) throw( RuntimeException ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| m_aListeners.push_back( Listener( xListener ) ); |
| } |
| |
| void SAL_CALL VCLSession::removeSessionManagerListener( const css::uno::Reference<XSessionManagerListener>& xListener ) throw( RuntimeException ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| std::list< Listener >::iterator it = m_aListeners.begin(); |
| while( it != m_aListeners.end() ) |
| { |
| if( it->m_xListener == xListener ) |
| { |
| m_aListeners.erase( it ); |
| it = m_aListeners.begin(); |
| } |
| else |
| ++it; |
| } |
| } |
| |
| void SAL_CALL VCLSession::queryInteraction( const css::uno::Reference<XSessionManagerListener>& xListener ) throw( RuntimeException ) |
| { |
| if( m_bInteractionGranted ) |
| { |
| if( m_bInteractionDone ) |
| xListener->approveInteraction( false ); |
| else |
| xListener->approveInteraction( true ); |
| return; |
| } |
| |
| osl::MutexGuard aGuard( m_aMutex ); |
| if( ! m_bInteractionRequested ) |
| { |
| m_pSession->queryInteraction(); |
| m_bInteractionRequested = true; |
| } |
| for( std::list< Listener >::iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it ) |
| { |
| if( it->m_xListener == xListener ) |
| { |
| it->m_bInteractionRequested = true; |
| it->m_bInteractionDone = false; |
| } |
| } |
| } |
| |
| void SAL_CALL VCLSession::interactionDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| int nRequested = 0, nDone = 0; |
| for( std::list< Listener >::iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it ) |
| { |
| if( it->m_bInteractionRequested ) |
| { |
| nRequested++; |
| if( xListener == it->m_xListener ) |
| it->m_bInteractionDone = true; |
| } |
| if( it->m_bInteractionDone ) |
| nDone++; |
| } |
| if( nDone == nRequested && nDone > 0 ) |
| { |
| m_bInteractionDone = true; |
| if( m_pSession ) |
| m_pSession->interactionDone(); |
| } |
| } |
| |
| void SAL_CALL VCLSession::saveDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| |
| bool bSaveDone = true; |
| for( std::list< Listener >::iterator it = m_aListeners.begin(); |
| it != m_aListeners.end(); ++it ) |
| { |
| if( it->m_xListener == xListener ) |
| it->m_bSaveDone = true; |
| if( ! it->m_bSaveDone ) |
| bSaveDone = false; |
| } |
| if( bSaveDone ) |
| { |
| m_bSaveDone = true; |
| if( m_pSession ) |
| m_pSession->saveDone(); |
| } |
| } |
| |
| sal_Bool SAL_CALL VCLSession::cancelShutdown() throw( RuntimeException ) |
| { |
| return m_pSession ? (sal_Bool)m_pSession->cancelShutdown() : sal_False; |
| } |
| |
| // service implementation |
| |
| OUString SAL_CALL vcl_session_getImplementationName() |
| { |
| static OUString aImplementationName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.VCLSessionManagerClient" ) ); |
| return aImplementationName; |
| } |
| |
| Sequence< rtl::OUString > SAL_CALL vcl_session_getSupportedServiceNames() |
| { |
| Sequence< OUString > aRet(1); |
| aRet[0] = OUString::createFromAscii("com.sun.star.frame.SessionManagerClient"); |
| return aRet; |
| } |
| |
| css::uno::Reference< XInterface > SAL_CALL vcl_session_createInstance( const css::uno::Reference< XMultiServiceFactory > & /*xMultiServiceFactory*/ ) |
| { |
| ImplSVData* pSVData = ImplGetSVData(); |
| if( ! pSVData->xSMClient.is() ) |
| pSVData->xSMClient = new VCLSession(); |
| |
| return css::uno::Reference< XInterface >(pSVData->xSMClient, UNO_QUERY ); |
| } |