Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : : #include <unotools/desktopterminationobserver.hxx>
21 : :
22 : : #include <com/sun/star/frame/XTerminateListener.hpp>
23 : : #include <com/sun/star/frame/XDesktop.hpp>
24 : : #include <cppuhelper/implbase1.hxx>
25 : : #include <comphelper/processfactory.hxx>
26 : :
27 : : #include <list>
28 : :
29 : : //........................................................................
30 : : namespace utl
31 : : {
32 : : //........................................................................
33 : :
34 : : using namespace ::com::sun::star::uno;
35 : : using namespace ::com::sun::star::lang;
36 : : using namespace ::com::sun::star::frame;
37 : :
38 : : namespace
39 : : {
40 : : //................................................................
41 : : typedef ::std::list< ITerminationListener* > Listeners;
42 : :
43 : 4 : struct ListenerAdminData
44 : : {
45 : : Listeners aListeners;
46 : : bool bAlreadyTerminated;
47 : : bool bCreatedAdapter;
48 : :
49 : 4 : ListenerAdminData() : bAlreadyTerminated( false ), bCreatedAdapter( false ) { }
50 : : };
51 : :
52 : : //................................................................
53 : 144 : ListenerAdminData& getListenerAdminData()
54 : : {
55 [ + + ][ + - ]: 144 : static ListenerAdminData s_aData;
[ + - ][ # # ]
56 : 144 : return s_aData;
57 : : }
58 : :
59 : : //================================================================
60 : : //= OObserverImpl
61 : : //================================================================
62 : : class OObserverImpl : public ::cppu::WeakImplHelper1< XTerminateListener >
63 : : {
64 : : public:
65 : : static void ensureObservation();
66 : :
67 : : protected:
68 : : OObserverImpl();
69 : : ~OObserverImpl();
70 : :
71 : : private:
72 : : // XTerminateListener
73 : : virtual void SAL_CALL queryTermination( const EventObject& Event ) throw (TerminationVetoException, RuntimeException);
74 : : virtual void SAL_CALL notifyTermination( const EventObject& Event ) throw (RuntimeException);
75 : :
76 : : // XEventListener
77 : : virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
78 : : };
79 : :
80 : : //--------------------------------------------------------------------
81 : 4 : OObserverImpl::OObserverImpl()
82 : : {
83 : 4 : }
84 : :
85 : : //--------------------------------------------------------------------
86 : 4 : OObserverImpl::~OObserverImpl()
87 : : {
88 [ - + ]: 8 : }
89 : :
90 : : //--------------------------------------------------------------------
91 : 30 : void OObserverImpl::ensureObservation()
92 : : {
93 : : {
94 [ + - ][ + + ]: 30 : if ( getListenerAdminData().bCreatedAdapter )
95 : : return;
96 [ + - ][ + - ]: 4 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
97 [ + - ][ - + ]: 4 : if ( getListenerAdminData().bCreatedAdapter )
98 : : return;
99 : :
100 [ + - ][ + - ]: 4 : getListenerAdminData().bCreatedAdapter = true;
[ + - ]
101 : : }
102 : :
103 : : try
104 : : {
105 : 4 : Reference< XDesktop > xDesktop;
106 [ + - ][ + - ]: 30 : xDesktop = xDesktop.query( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ) ) );
[ + - ][ + - ]
[ + - ][ + - ]
107 : : OSL_ENSURE( xDesktop.is(), "OObserverImpl::ensureObservation: could not ensureObservation the desktop!" );
108 [ + - ]: 4 : if ( xDesktop.is() )
109 [ + - ][ + - ]: 30 : xDesktop->addTerminateListener( new OObserverImpl );
[ + - ][ + - ]
[ + - ][ # # ]
110 : : }
111 : 0 : catch( const Exception& )
112 : : {
113 : : OSL_FAIL( "OObserverImpl::ensureObservation: caught an exception!" );
114 : : }
115 : : }
116 : :
117 : : //--------------------------------------------------------------------
118 : 4 : void SAL_CALL OObserverImpl::queryTermination( const EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException)
119 : : {
120 [ + - ]: 4 : Listeners aToNotify;
121 : : {
122 [ + - ][ + - ]: 4 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
123 [ + - ][ + - ]: 4 : aToNotify = getListenerAdminData().aListeners;
[ + - ]
124 : : }
125 : :
126 [ + + ]: 10 : for ( Listeners::const_iterator listener = aToNotify.begin();
127 : 5 : listener != aToNotify.end();
128 : : ++listener
129 : : )
130 : : {
131 [ + - ][ - + ]: 1 : if ( !(*listener)->queryTermination() )
132 [ # # ]: 0 : throw TerminationVetoException();
133 : 4 : }
134 : 4 : }
135 : :
136 : : //--------------------------------------------------------------------
137 : 4 : void SAL_CALL OObserverImpl::notifyTermination( const EventObject& /*Event*/ ) throw (RuntimeException)
138 : : {
139 : : // get the listeners
140 [ + - ]: 4 : Listeners aToNotify;
141 : : {
142 [ + - ][ + - ]: 4 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
143 : : OSL_ENSURE( !getListenerAdminData().bAlreadyTerminated, "OObserverImpl::notifyTermination: terminated twice?" );
144 [ + - ][ + - ]: 4 : aToNotify = getListenerAdminData().aListeners;
145 [ + - ][ + - ]: 4 : getListenerAdminData().bAlreadyTerminated = true;
146 : : }
147 : :
148 : : // notify the listeners
149 [ + + ]: 10 : for ( Listeners::const_iterator listener = aToNotify.begin();
150 : 5 : listener != aToNotify.end();
151 : : ++listener
152 : : )
153 : : {
154 [ + - ]: 1 : (*listener)->notifyTermination();
155 : : }
156 : :
157 : : // clear the listener container
158 : : {
159 [ + - ][ + - ]: 4 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
160 [ + - ][ + - ]: 4 : getListenerAdminData().aListeners.clear();
161 : 4 : }
162 : 4 : }
163 : :
164 : : //--------------------------------------------------------------------
165 : 4 : void SAL_CALL OObserverImpl::disposing( const EventObject& /*Event*/ ) throw (RuntimeException)
166 : : {
167 : : #if OSL_DEBUG_LEVEL > 0
168 : : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
169 : : OSL_ENSURE( getListenerAdminData().bAlreadyTerminated, "OObserverImpl::disposing: disposing without terminated?" );
170 : : #endif
171 : : // not interested in
172 : 4 : }
173 : : }
174 : :
175 : : //====================================================================
176 : : //= DesktopTerminationObserver
177 : : //====================================================================
178 : : //--------------------------------------------------------------------
179 : 30 : void DesktopTerminationObserver::registerTerminationListener( ITerminationListener* _pListener )
180 : : {
181 [ - + ]: 30 : if ( !_pListener )
182 : 0 : return;
183 : :
184 : : {
185 [ + - ][ + - ]: 30 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
186 [ + - ][ - + ]: 30 : if ( getListenerAdminData().bAlreadyTerminated )
187 : : {
188 [ # # ]: 0 : _pListener->notifyTermination();
189 : : return;
190 : : }
191 : :
192 [ + - ][ + - ]: 30 : getListenerAdminData().aListeners.push_back( _pListener );
[ + - ][ + - ]
193 : : }
194 : :
195 : 30 : OObserverImpl::ensureObservation();
196 : : }
197 : :
198 : : //--------------------------------------------------------------------
199 : 30 : void DesktopTerminationObserver::revokeTerminationListener( ITerminationListener* _pListener )
200 : : {
201 [ + - ][ + - ]: 30 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
202 [ + - ]: 30 : Listeners& rListeners = getListenerAdminData().aListeners;
203 [ + + ]: 60 : for ( Listeners::iterator lookup = rListeners.begin();
204 : 30 : lookup != rListeners.end();
205 : : ++lookup
206 : : )
207 : : {
208 [ + - ]: 29 : if ( *lookup == _pListener )
209 : : {
210 [ + - ]: 29 : rListeners.erase( lookup );
211 : 29 : break;
212 : : }
213 [ + - ]: 30 : }
214 : 30 : }
215 : :
216 : : //........................................................................
217 : : } // namespace utl
218 : : //........................................................................
219 : :
220 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|