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