1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <sal/config.h>
22 #include <sal/log.hxx>
24 #include <cppuhelper/basemutex.hxx>
25 #include <cppuhelper/compbase.hxx>
26 #include <cppuhelper/supportsservice.hxx>
28 #include <comphelper/diagnose_ex.hxx>
30 #include <vcl/svapp.hxx>
32 #include <factory.hxx>
34 #include <salinst.hxx>
35 #include <salsession.hxx>
37 #include <com/sun/star/frame/XSessionManagerClient.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/lang/XServiceInfo.hpp>
40 #include <com/sun/star/frame/XSessionManagerListener2.hpp>
44 using namespace com::sun::star::uno
;
45 using namespace com::sun::star::lang
;
46 using namespace com::sun::star::frame
;
48 SalSession::~SalSession()
55 private cppu::BaseMutex
,
56 public cppu::WeakComponentImplHelper
< XSessionManagerClient
, css::lang::XServiceInfo
>
60 css::uno::Reference
< XSessionManagerListener
> m_xListener
;
61 bool m_bInteractionRequested
;
62 bool m_bInteractionDone
;
65 explicit Listener( css::uno::Reference
< XSessionManagerListener
> xListener
)
66 : m_xListener(std::move( xListener
)),
67 m_bInteractionRequested( false ),
68 m_bInteractionDone( false ),
73 std::vector
< Listener
> m_aListeners
;
74 std::unique_ptr
< SalSession
> m_xSession
;
75 bool m_bInteractionRequested
;
76 bool m_bInteractionGranted
;
77 bool m_bInteractionDone
;
80 static void SalSessionEventProc( void* pData
, SalSessionEvent
* pEvent
);
82 virtual ~VCLSession() override
{}
84 virtual void SAL_CALL
addSessionManagerListener( const css::uno::Reference
< XSessionManagerListener
>& xListener
) override
;
85 virtual void SAL_CALL
removeSessionManagerListener( const css::uno::Reference
< XSessionManagerListener
>& xListener
) override
;
86 virtual void SAL_CALL
queryInteraction( const css::uno::Reference
< XSessionManagerListener
>& xListener
) override
;
87 virtual void SAL_CALL
interactionDone( const css::uno::Reference
< XSessionManagerListener
>& xListener
) override
;
88 virtual void SAL_CALL
saveDone( const css::uno::Reference
< XSessionManagerListener
>& xListener
) override
;
89 virtual sal_Bool SAL_CALL
cancelShutdown() override
;
91 OUString SAL_CALL
getImplementationName() override
{
92 return "com.sun.star.frame.VCLSessionManagerClient";
95 sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
{
96 return cppu::supportsService(this, ServiceName
);
99 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
{
100 return {"com.sun.star.frame.SessionManagerClient"};
103 void SAL_CALL
disposing() override
;
105 void callSaveRequested( bool bShutdown
);
106 void callShutdownCancelled();
107 void callInteractionGranted( bool bGranted
);
116 VCLSession::VCLSession()
117 : WeakComponentImplHelper( m_aMutex
),
118 m_xSession( ImplGetSVData()->mpDefInst
->CreateSalSession() ),
119 m_bInteractionRequested( false ),
120 m_bInteractionGranted( false ),
121 m_bInteractionDone( false ),
124 SAL_INFO("vcl.se", "VCLSession::VCLSession" );
127 m_xSession
->SetCallback( SalSessionEventProc
, this );
130 void VCLSession::callSaveRequested( bool bShutdown
)
132 SAL_INFO("vcl.se", "VCLSession::callSaveRequested" );
134 std::vector
< Listener
> aListeners
;
136 osl::MutexGuard
aGuard( m_aMutex
);
137 // reset listener states
138 for (auto & listener
: m_aListeners
) {
139 listener
.m_bSaveDone
= listener
.m_bInteractionRequested
= listener
.m_bInteractionDone
= false;
142 // copy listener vector since calling a listener may remove it.
143 aListeners
= m_aListeners
;
144 // set back interaction state
146 m_bInteractionDone
= false;
147 // without session we assume UI is always possible,
148 // so it was requested and granted
149 m_bInteractionRequested
= m_bInteractionGranted
= !m_xSession
;
151 // answer the session manager even if no listeners available anymore
152 SAL_WARN_IF( aListeners
.empty(), "vcl.se", "saveRequested but no listeners !" );
154 SAL_INFO("vcl.se.debug", " aListeners.empty() = " << (aListeners
.empty() ? "true" : "false") <<
155 ", bShutdown = " << (bShutdown
? "true" : "false"));
156 if( aListeners
.empty() )
159 m_xSession
->saveDone();
164 SolarMutexReleaser aReleaser
;
165 for (auto const & listener
: aListeners
)
166 listener
.m_xListener
->doSave( bShutdown
, false/*bCancelable*/ );
169 void VCLSession::callInteractionGranted( bool bInteractionGranted
)
171 SAL_INFO("vcl.se", "VCLSession::callInteractionGranted" );
173 std::vector
< Listener
> aListeners
;
175 osl::MutexGuard
aGuard( m_aMutex
);
176 // copy listener vector since calling a listener may remove it.
177 for (auto const & listener
: m_aListeners
)
178 if( listener
.m_bInteractionRequested
)
179 aListeners
.push_back( listener
);
181 m_bInteractionGranted
= bInteractionGranted
;
183 // answer the session manager even if no listeners available anymore
184 SAL_WARN_IF( aListeners
.empty(), "vcl.se", "interactionGranted but no listeners !" );
186 SAL_INFO("vcl.se.debug", " aListeners.empty() = " << (aListeners
.empty() ? "true" : "false") <<
187 ", bInteractionGranted = " << (bInteractionGranted
? "true" : "false"));
188 if( aListeners
.empty() )
191 m_xSession
->interactionDone();
196 SolarMutexReleaser aReleaser
;
197 for (auto const & listener
: aListeners
)
198 listener
.m_xListener
->approveInteraction( bInteractionGranted
);
201 void VCLSession::callShutdownCancelled()
203 SAL_INFO("vcl.se", "VCLSession::callShutdownCancelled");
205 std::vector
< Listener
> aListeners
;
207 osl::MutexGuard
aGuard( m_aMutex
);
208 // copy listener vector since calling a listener may remove it.
209 aListeners
= m_aListeners
;
210 // set back interaction state
211 m_bInteractionRequested
= m_bInteractionDone
= m_bInteractionGranted
= false;
214 SolarMutexReleaser aReleaser
;
215 for (auto const & listener
: aListeners
)
216 listener
.m_xListener
->shutdownCanceled();
219 void VCLSession::callQuit()
221 SAL_INFO("vcl.se", "VCLSession::callQuit");
223 std::vector
< Listener
> aListeners
;
225 osl::MutexGuard
aGuard( m_aMutex
);
226 // copy listener vector since calling a listener may remove it.
227 aListeners
= m_aListeners
;
228 // set back interaction state
229 m_bInteractionRequested
= m_bInteractionDone
= m_bInteractionGranted
= false;
232 SolarMutexReleaser aReleaser
;
233 for (auto const & listener
: aListeners
)
235 css::uno::Reference
< XSessionManagerListener2
> xListener2( listener
.m_xListener
, UNO_QUERY
);
236 if( xListener2
.is() )
237 xListener2
->doQuit();
241 void VCLSession::SalSessionEventProc( void* pData
, SalSessionEvent
* pEvent
)
243 SAL_INFO("vcl.se", "VCLSession::SalSessionEventProc");
245 VCLSession
* pThis
= static_cast< VCLSession
* >( pData
);
246 switch( pEvent
->m_eType
)
250 SAL_INFO("vcl.se.debug", " EventProcType = Interaction");
251 SalSessionInteractionEvent
* pIEv
= static_cast<SalSessionInteractionEvent
*>(pEvent
);
252 pThis
->callInteractionGranted( pIEv
->m_bInteractionGranted
);
257 SAL_INFO("vcl.se.debug", " EventProcType = SaveRequest");
258 SalSessionSaveRequestEvent
* pSEv
= static_cast<SalSessionSaveRequestEvent
*>(pEvent
);
259 pThis
->callSaveRequested( pSEv
->m_bShutdown
);
263 SAL_INFO("vcl.se.debug", " EventProcType = ShutdownCancel");
264 pThis
->callShutdownCancelled();
267 SAL_INFO("vcl.se.debug", " EventProcType = Quit");
273 void SAL_CALL
VCLSession::addSessionManagerListener( const css::uno::Reference
<XSessionManagerListener
>& xListener
)
275 SAL_INFO("vcl.se", "VCLSession::addSessionManagerListener" );
277 osl::MutexGuard
aGuard( m_aMutex
);
279 SAL_INFO("vcl.se.debug", " m_aListeners.size() = " << m_aListeners
.size() );
280 m_aListeners
.emplace_back( xListener
);
283 void SAL_CALL
VCLSession::removeSessionManagerListener( const css::uno::Reference
<XSessionManagerListener
>& xListener
)
285 SAL_INFO("vcl.se", "VCLSession::removeSessionManagerListener" );
287 osl::MutexGuard
aGuard( m_aMutex
);
289 SAL_INFO("vcl.se.debug", " m_aListeners.size() = " << m_aListeners
.size() );
291 m_aListeners
.erase(std::remove_if(m_aListeners
.begin(), m_aListeners
.end(), [&](Listener
& listener
) {return xListener
== listener
.m_xListener
;}), m_aListeners
.end());
294 void SAL_CALL
VCLSession::queryInteraction( const css::uno::Reference
<XSessionManagerListener
>& xListener
)
296 SAL_INFO("vcl.se", "VCLSession::queryInteraction");
298 SAL_INFO("vcl.se.debug", " m_bInteractionGranted = " << (m_bInteractionGranted
? "true" : "false") <<
299 ", m_bInteractionRequested = "<< (m_bInteractionRequested
? "true" : "false"));
300 if( m_bInteractionGranted
)
302 if( m_bInteractionDone
)
303 xListener
->approveInteraction( false );
305 xListener
->approveInteraction( true );
309 osl::MutexGuard
aGuard( m_aMutex
);
310 if( ! m_bInteractionRequested
)
312 m_xSession
->queryInteraction();
313 m_bInteractionRequested
= true;
315 for (auto & listener
: m_aListeners
)
317 if( listener
.m_xListener
== xListener
)
319 SAL_INFO("vcl.se.debug", " listener.m_xListener == xListener");
320 listener
.m_bInteractionRequested
= true;
321 listener
.m_bInteractionDone
= false;
326 void SAL_CALL
VCLSession::interactionDone( const css::uno::Reference
< XSessionManagerListener
>& xListener
)
328 SAL_INFO("vcl.se", "VCLSession::interactionDone");
330 osl::MutexGuard
aGuard( m_aMutex
);
331 int nRequested
= 0, nDone
= 0;
332 for (auto & listener
: m_aListeners
)
334 if( listener
.m_bInteractionRequested
)
337 if( xListener
== listener
.m_xListener
)
338 listener
.m_bInteractionDone
= true;
340 if( listener
.m_bInteractionDone
)
344 SAL_INFO("vcl.se.debug", " nDone = " << nDone
<<
345 ", nRequested =" << nRequested
);
346 if( nDone
== nRequested
&& nDone
> 0 )
348 m_bInteractionDone
= true;
350 m_xSession
->interactionDone();
354 void SAL_CALL
VCLSession::saveDone( const css::uno::Reference
< XSessionManagerListener
>& xListener
)
356 SAL_INFO("vcl.se", "VCLSession::saveDone");
358 osl::MutexGuard
aGuard( m_aMutex
);
360 bool bSaveDone
= true;
361 for (auto & listener
: m_aListeners
)
363 if( listener
.m_xListener
== xListener
)
364 listener
.m_bSaveDone
= true;
365 if( ! listener
.m_bSaveDone
)
369 SAL_INFO("vcl.se.debug", " bSaveDone = " << (bSaveDone
? "true" : "false"));
371 if( bSaveDone
&& !m_bSaveDone
)
375 m_xSession
->saveDone();
379 sal_Bool SAL_CALL
VCLSession::cancelShutdown()
381 SAL_INFO("vcl.se", "VCLSession::cancelShutdown");
383 return m_xSession
&& m_xSession
->cancelShutdown();
386 void VCLSession::disposing() {
387 SAL_INFO("vcl.se", "VCLSession::disposing");
389 std::vector
<Listener
> vector
;
391 osl::MutexGuard
g(m_aMutex
);
392 vector
.swap(m_aListeners
);
394 css::lang::EventObject
src(getXWeak());
395 for (auto const & listener
: vector
) {
397 listener
.m_xListener
->disposing(src
);
398 SAL_INFO("vcl.se.debug", " call Listener disposing");
399 } catch (css::uno::RuntimeException
&) {
400 TOOLS_WARN_EXCEPTION("vcl.se", "ignoring");
405 // service implementation
407 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
408 com_sun_star_frame_VCLSessionManagerClient_get_implementation(
409 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
411 return cppu::acquire(new VCLSession
);
414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */