xref: /trunk/main/vcl/source/app/session.cxx (revision 9f62ea84)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <cppuhelper/compbase1.hxx>
28 
29 #include <tools/debug.hxx>
30 
31 #include <vcl/svapp.hxx>
32 
33 #include <svdata.hxx>
34 #include <salinst.hxx>
35 #include <salsession.hxx>
36 
37 #include <com/sun/star/frame/XSessionManagerClient.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/frame/XSessionManagerListener2.hpp>
40 
41 #include <list>
42 
43 namespace {
44 
45 namespace css = com::sun::star;
46 
47 }
48 
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::frame;
52 using namespace rtl;
53 
~SalSession()54 SalSession::~SalSession()
55 {
56 }
57 
58 class VCLSession : public cppu::WeakComponentImplHelper1 < XSessionManagerClient >
59 {
60     struct Listener
61     {
62         css::uno::Reference< XSessionManagerListener >		m_xListener;
63         bool										m_bInteractionRequested;
64         bool										m_bInteractionDone;
65         bool										m_bSaveDone;
66 
ListenerVCLSession::Listener67         Listener( const css::uno::Reference< XSessionManagerListener >& xListener )
68                 : m_xListener( xListener ),
69                   m_bInteractionRequested( false ),
70                   m_bInteractionDone( false ),
71                   m_bSaveDone( false )
72         {}
73     };
74 
75     std::list< Listener >							m_aListeners;
76     SalSession*										m_pSession;
77     osl::Mutex										m_aMutex;
78     bool											m_bInteractionRequested;
79     bool											m_bInteractionGranted;
80     bool											m_bInteractionDone;
81     bool											m_bSaveDone;
82 
83     static void SalSessionEventProc( SalSessionEvent* pEvent );
84     static VCLSession* pOneInstance;
85 
86     void callSaveRequested( bool bShutdown, bool bCancelable );
87     void callShutdownCancelled();
88     void callInteractionGranted( bool bGranted );
89     void callQuit();
90 public:
91     VCLSession();
92     virtual ~VCLSession();
93 
94     virtual void SAL_CALL addSessionManagerListener( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException );
95     virtual void SAL_CALL removeSessionManagerListener( const css::uno::Reference< XSessionManagerListener>& xListener ) throw( RuntimeException );
96     virtual void SAL_CALL queryInteraction( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException );
97     virtual void SAL_CALL interactionDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException );
98     virtual void SAL_CALL saveDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException );
99     virtual sal_Bool SAL_CALL cancelShutdown() throw( RuntimeException );
100 };
101 
102 VCLSession* VCLSession::pOneInstance = NULL;
103 
VCLSession()104 VCLSession::VCLSession()
105         : cppu::WeakComponentImplHelper1< XSessionManagerClient >( m_aMutex ),
106           m_bInteractionRequested( false ),
107           m_bInteractionGranted( false ),
108           m_bInteractionDone( false ),
109           m_bSaveDone( false )
110 {
111     DBG_ASSERT( pOneInstance == 0, "One instance  of VCLSession only !" );
112     pOneInstance = this;
113     m_pSession = ImplGetSVData()->mpDefInst->CreateSalSession();
114     if( m_pSession )
115         m_pSession->SetCallback( SalSessionEventProc );
116 }
117 
~VCLSession()118 VCLSession::~VCLSession()
119 {
120     DBG_ASSERT( pOneInstance == this, "Another instance of VCLSession in destructor !" );
121     pOneInstance = NULL;
122     delete m_pSession;
123 }
124 
callSaveRequested(bool bShutdown,bool bCancelable)125 void VCLSession::callSaveRequested( bool bShutdown, bool bCancelable )
126 {
127     std::list< Listener > aListeners;
128     {
129         osl::MutexGuard aGuard( m_aMutex );
130         // reset listener states
131         for( std::list< Listener >::iterator it = m_aListeners.begin();
132              it != m_aListeners.end(); ++it )
133         {
134             it->m_bSaveDone = it->m_bInteractionRequested = it->m_bInteractionDone = false;
135         }
136 
137         // copy listener list since calling a listener may remove it.
138         aListeners = m_aListeners;
139         // set back interaction state
140         m_bSaveDone = false;
141         m_bInteractionDone = false;
142         // without session we assume UI is always possible,
143         // so it was reqeusted and granted
144         m_bInteractionRequested = m_bInteractionGranted = m_pSession ? false : true;
145 
146         // answer the session manager even if no listeners available anymore
147         DBG_ASSERT( ! aListeners.empty(), "saveRequested but no listeners !" );
148         if( aListeners.empty() )
149         {
150             if( m_pSession )
151                 m_pSession->saveDone();
152             return;
153         }
154     }
155 
156     sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
157     for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it )
158         it->m_xListener->doSave( bShutdown, bCancelable );
159     Application::AcquireSolarMutex( nAcquireCount );
160 }
161 
callInteractionGranted(bool bInteractionGranted)162 void VCLSession::callInteractionGranted( bool bInteractionGranted )
163 {
164     std::list< Listener > aListeners;
165     {
166         osl::MutexGuard aGuard( m_aMutex );
167         // copy listener list since calling a listener may remove it.
168         for( std::list< Listener >::const_iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it )
169             if( it->m_bInteractionRequested )
170                 aListeners.push_back( *it );
171 
172         m_bInteractionGranted = bInteractionGranted;
173 
174         // answer the session manager even if no listeners available anymore
175         DBG_ASSERT( ! aListeners.empty(), "interactionGranted but no listeners !" );
176         if( aListeners.empty() )
177         {
178             if( m_pSession )
179                 m_pSession->interactionDone();
180             return;
181         }
182     }
183 
184     sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
185     for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it )
186         it->m_xListener->approveInteraction( bInteractionGranted );
187 
188     Application::AcquireSolarMutex( nAcquireCount );
189 }
190 
callShutdownCancelled()191 void VCLSession::callShutdownCancelled()
192 {
193     std::list< Listener > aListeners;
194     {
195         osl::MutexGuard aGuard( m_aMutex );
196         // copy listener list since calling a listener may remove it.
197         aListeners = m_aListeners;
198         // set back interaction state
199         m_bInteractionRequested = m_bInteractionDone = m_bInteractionGranted = false;
200     }
201 
202     sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
203     for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it )
204         it->m_xListener->shutdownCanceled();
205     Application::AcquireSolarMutex( nAcquireCount );
206 }
207 
callQuit()208 void VCLSession::callQuit()
209 {
210     std::list< Listener > aListeners;
211     {
212         osl::MutexGuard aGuard( m_aMutex );
213         // copy listener list since calling a listener may remove it.
214         aListeners = m_aListeners;
215         // set back interaction state
216         m_bInteractionRequested = m_bInteractionDone = m_bInteractionGranted = false;
217     }
218 
219     sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
220     for( std::list< Listener >::const_iterator it = aListeners.begin(); it != aListeners.end(); ++it )
221     {
222         css::uno::Reference< XSessionManagerListener2 > xListener2( it->m_xListener, UNO_QUERY );
223         if( xListener2.is() )
224             xListener2->doQuit();
225     }
226     Application::AcquireSolarMutex( nAcquireCount );
227 }
228 
SalSessionEventProc(SalSessionEvent * pEvent)229 void VCLSession::SalSessionEventProc( SalSessionEvent* pEvent )
230 {
231     switch( pEvent->m_eType )
232     {
233         case Interaction:
234         {
235             SalSessionInteractionEvent* pIEv = static_cast<SalSessionInteractionEvent*>(pEvent);
236             pOneInstance->callInteractionGranted( pIEv->m_bInteractionGranted );
237         }
238         break;
239         case SaveRequest:
240         {
241             SalSessionSaveRequestEvent* pSEv = static_cast<SalSessionSaveRequestEvent*>(pEvent);
242             pOneInstance->callSaveRequested( pSEv->m_bShutdown, pSEv->m_bCancelable );
243         }
244         break;
245         case ShutdownCancel:
246             pOneInstance->callShutdownCancelled();
247             break;
248         case Quit:
249             pOneInstance->callQuit();
250             break;
251     }
252 }
253 
addSessionManagerListener(const css::uno::Reference<XSessionManagerListener> & xListener)254 void SAL_CALL VCLSession::addSessionManagerListener( const css::uno::Reference<XSessionManagerListener>& xListener ) throw( RuntimeException )
255 {
256     osl::MutexGuard aGuard( m_aMutex );
257 
258     m_aListeners.push_back( Listener( xListener ) );
259 }
260 
removeSessionManagerListener(const css::uno::Reference<XSessionManagerListener> & xListener)261 void SAL_CALL VCLSession::removeSessionManagerListener( const css::uno::Reference<XSessionManagerListener>& xListener ) throw( RuntimeException )
262 {
263     osl::MutexGuard aGuard( m_aMutex );
264 
265     std::list< Listener >::iterator it = m_aListeners.begin();
266     while( it != m_aListeners.end() )
267     {
268         if( it->m_xListener == xListener )
269         {
270             m_aListeners.erase( it );
271             it = m_aListeners.begin();
272         }
273         else
274             ++it;
275     }
276 }
277 
queryInteraction(const css::uno::Reference<XSessionManagerListener> & xListener)278 void SAL_CALL VCLSession::queryInteraction( const css::uno::Reference<XSessionManagerListener>& xListener ) throw( RuntimeException )
279 {
280     if( m_bInteractionGranted )
281     {
282         if( m_bInteractionDone )
283             xListener->approveInteraction( false );
284         else
285             xListener->approveInteraction( true );
286         return;
287     }
288 
289     osl::MutexGuard aGuard( m_aMutex );
290     if( ! m_bInteractionRequested )
291     {
292         m_pSession->queryInteraction();
293         m_bInteractionRequested = true;
294     }
295     for( std::list< Listener >::iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it )
296     {
297         if( it->m_xListener == xListener )
298         {
299             it->m_bInteractionRequested	= true;
300             it->m_bInteractionDone		= false;
301         }
302     }
303 }
304 
interactionDone(const css::uno::Reference<XSessionManagerListener> & xListener)305 void SAL_CALL VCLSession::interactionDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException )
306 {
307     osl::MutexGuard aGuard( m_aMutex );
308     int nRequested = 0, nDone = 0;
309     for( std::list< Listener >::iterator it = m_aListeners.begin(); it != m_aListeners.end(); ++it )
310     {
311         if( it->m_bInteractionRequested )
312         {
313             nRequested++;
314             if( xListener == it->m_xListener )
315                 it->m_bInteractionDone = true;
316         }
317         if( it->m_bInteractionDone )
318             nDone++;
319     }
320     if( nDone == nRequested && nDone > 0 )
321     {
322         m_bInteractionDone = true;
323         if( m_pSession )
324             m_pSession->interactionDone();
325     }
326 }
327 
saveDone(const css::uno::Reference<XSessionManagerListener> & xListener)328 void SAL_CALL VCLSession::saveDone( const css::uno::Reference< XSessionManagerListener >& xListener ) throw( RuntimeException )
329 {
330     osl::MutexGuard aGuard( m_aMutex );
331 
332     bool bSaveDone = true;
333     for( std::list< Listener >::iterator it = m_aListeners.begin();
334          it != m_aListeners.end(); ++it )
335     {
336         if( it->m_xListener == xListener )
337             it->m_bSaveDone = true;
338         if( ! it->m_bSaveDone )
339             bSaveDone = false;
340     }
341     if( bSaveDone )
342     {
343         m_bSaveDone = true;
344         if( m_pSession )
345             m_pSession->saveDone();
346     }
347 }
348 
cancelShutdown()349 sal_Bool SAL_CALL VCLSession::cancelShutdown() throw( RuntimeException )
350 {
351     return m_pSession ? (sal_Bool)m_pSession->cancelShutdown() : sal_False;
352 }
353 
354 // service implementation
355 
vcl_session_getImplementationName()356 OUString SAL_CALL vcl_session_getImplementationName()
357 {
358 	static OUString aImplementationName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.VCLSessionManagerClient" ) );
359 	return aImplementationName;
360 }
361 
vcl_session_getSupportedServiceNames()362 Sequence< rtl::OUString > SAL_CALL vcl_session_getSupportedServiceNames()
363 {
364 	Sequence< OUString > aRet(1);
365 	aRet[0] = OUString::createFromAscii("com.sun.star.frame.SessionManagerClient");
366 	return aRet;
367 }
368 
vcl_session_createInstance(const css::uno::Reference<XMultiServiceFactory> &)369 css::uno::Reference< XInterface > SAL_CALL vcl_session_createInstance( const css::uno::Reference< XMultiServiceFactory > & /*xMultiServiceFactory*/ )
370 {
371     ImplSVData* pSVData = ImplGetSVData();
372     if( ! pSVData->xSMClient.is() )
373         pSVData->xSMClient = new VCLSession();
374 
375 	return css::uno::Reference< XInterface >(pSVData->xSMClient, UNO_QUERY );
376 }
377