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_comphelper.hxx"
26 #include "comphelper/accessiblewrapper.hxx"
27 #include <com/sun/star/reflection/XProxyFactory.hpp>
28 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
29 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
30 
31 #include <algorithm>
32 
33 using namespace	::comphelper;
34 using namespace	::com::sun::star::accessibility;
35 using namespace	::com::sun::star::uno;
36 using namespace	::com::sun::star::lang;
37 
38 //.............................................................................
39 namespace comphelper
40 {
41 //.............................................................................
42 
43 	//=========================================================================
44 	//= OWrappedAccessibleChildrenManager
45 	//=========================================================================
46 	//--------------------------------------------------------------------
47 	struct RemoveEventListener
48 			: public ::std::unary_function< AccessibleMap::value_type, void >
49 	{
50 	private:
51 		Reference< XEventListener >	m_xListener;
52 
53 	public:
RemoveEventListenercomphelper::RemoveEventListener54 		RemoveEventListener( const Reference< XEventListener >& _rxListener )
55 			:m_xListener( _rxListener  )
56 		{
57 		}
58 
operator ()comphelper::RemoveEventListener59 		void operator()( const AccessibleMap::value_type& _rMapEntry ) const
60 		{
61 			Reference< XComponent > xComp( _rMapEntry.first, UNO_QUERY );
62 			if ( xComp.is() )
63 				xComp->removeEventListener( m_xListener );
64 		}
65 	};
66 
67 	//--------------------------------------------------------------------
68 	struct DisposeMappedChild
69 			: public ::std::unary_function< AccessibleMap::value_type, void >
70 	{
operator ()comphelper::DisposeMappedChild71 		void operator()( const AccessibleMap::value_type& _rMapEntry ) const
72 		{
73             Reference< XComponent > xContextComponent;
74             if ( _rMapEntry.second.is() )
75                 xContextComponent = xContextComponent.query( _rMapEntry.second->getAccessibleContext() );
76 			if ( xContextComponent.is() )
77 				xContextComponent->dispose();
78 		}
79 	};
80 
81 	//-------------------------------------------------------------------------
OWrappedAccessibleChildrenManager(const Reference<XMultiServiceFactory> & _rxORB)82 	OWrappedAccessibleChildrenManager::OWrappedAccessibleChildrenManager( const Reference< XMultiServiceFactory >& _rxORB )
83 		:m_xORB( _rxORB )
84 		,m_bTransientChildren( sal_True )
85 	{
86 	}
87 
88 	//-------------------------------------------------------------------------
~OWrappedAccessibleChildrenManager()89 	OWrappedAccessibleChildrenManager::~OWrappedAccessibleChildrenManager( )
90 	{
91 	}
92 
93 	//-------------------------------------------------------------------------
setTransientChildren(sal_Bool _bSet)94 	void OWrappedAccessibleChildrenManager::setTransientChildren( sal_Bool _bSet )
95 	{
96 		m_bTransientChildren = _bSet;
97 	}
98 
99 	//-------------------------------------------------------------------------
setOwningAccessible(const Reference<XAccessible> & _rxAcc)100 	void OWrappedAccessibleChildrenManager::setOwningAccessible( const Reference< XAccessible >& _rxAcc )
101 	{
102 		OSL_ENSURE( !m_aOwningAccessible.get().is(), "OWrappedAccessibleChildrenManager::setOwningAccessible: to be called only once!" );
103 		m_aOwningAccessible = WeakReference< XAccessible >( _rxAcc );
104 	}
105 
106 	//-------------------------------------------------------------------------
removeFromCache(const Reference<XAccessible> & _rxKey)107 	void OWrappedAccessibleChildrenManager::removeFromCache( const Reference< XAccessible >& _rxKey )
108 	{
109 		AccessibleMap::iterator aRemovedPos = m_aChildrenMap.find( _rxKey );
110 		if ( m_aChildrenMap.end() != aRemovedPos )
111 		{	// it was cached
112 			// remove ourself as event listener
113 			RemoveEventListener aOperator( this );
114 			aOperator( *aRemovedPos );
115 			// and remove the entry from the map
116 			m_aChildrenMap.erase( aRemovedPos );
117 		}
118 	}
119 
120 	//-------------------------------------------------------------------------
invalidateAll()121 	void OWrappedAccessibleChildrenManager::invalidateAll( )
122 	{
123 		// remove as event listener from the map elements
124 		::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), RemoveEventListener( this ) );
125 		// clear the map
126 		AccessibleMap aMap;
127 		m_aChildrenMap.swap( aMap );
128 	}
129 
130 	//-------------------------------------------------------------------------
getAccessibleWrapperFor(const Reference<XAccessible> & _rxKey,sal_Bool _bCreate)131 	Reference< XAccessible > OWrappedAccessibleChildrenManager::getAccessibleWrapperFor(
132 		const Reference< XAccessible >& _rxKey,	sal_Bool _bCreate )
133 	{
134 		Reference< XAccessible > xValue;
135 
136 		if( !_rxKey.is() )
137 		{
138 			// fprintf( stderr, "It was this path that was crashing stuff\n" );
139 			return xValue;
140 		}
141 
142 		// do we have this child in the cahce?
143 		AccessibleMap::const_iterator aPos = m_aChildrenMap.find( _rxKey );
144 		if ( m_aChildrenMap.end() != aPos )
145 		{
146 			xValue = aPos->second;
147 		}
148 		else if ( _bCreate )
149 		{	// not found in the cache, and allowed to create
150 			// -> new wrapper
151 			xValue = new OAccessibleWrapper( m_xORB, _rxKey, (Reference< XAccessible >)m_aOwningAccessible );
152 
153 			// see if we do cache children
154 			if ( !m_bTransientChildren )
155 			{
156 				if (!m_aChildrenMap.insert(
157                         AccessibleMap::value_type( _rxKey, xValue ) ).second)
158                 {
159                     OSL_ENSURE(
160                         false,
161                         "OWrappedAccessibleChildrenManager::"
162                             "getAccessibleWrapperFor: element was already"
163                             " inserted!" );
164                 }
165 
166 				// listen for disposals of inner children - this may happen when the inner context
167 				// is the owner for the inner children (it will dispose these children, and of course
168 				// not our wrapper for these children)
169 				Reference< XComponent > xComp( _rxKey, UNO_QUERY );
170 				if ( xComp.is() )
171 					xComp->addEventListener( this );
172 			}
173 		}
174 
175 		return xValue;
176 	}
177 
178 	//-------------------------------------------------------------------------
dispose()179 	void OWrappedAccessibleChildrenManager::dispose()
180 	{
181 		// dispose our children
182 		::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), RemoveEventListener( this ) );
183 		::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), DisposeMappedChild( ) );
184 		// clear our children
185 		AccessibleMap aMap;
186 		m_aChildrenMap.swap( aMap );
187 	}
188 
189 	//--------------------------------------------------------------------
implTranslateChildEventValue(const Any & _rInValue,Any & _rOutValue)190 	void OWrappedAccessibleChildrenManager::implTranslateChildEventValue( const Any& _rInValue, Any& _rOutValue )
191 	{
192 		_rOutValue.clear();
193 		Reference< XAccessible > xChild;
194 		if ( _rInValue >>= xChild )
195 			_rOutValue <<= getAccessibleWrapperFor( xChild, sal_True );
196 	}
197 
198 	//-------------------------------------------------------------------------
translateAccessibleEvent(const AccessibleEventObject & _rEvent,AccessibleEventObject & _rTranslatedEvent)199 	void OWrappedAccessibleChildrenManager::translateAccessibleEvent( const AccessibleEventObject& _rEvent, AccessibleEventObject& _rTranslatedEvent )
200 	{
201 		// just in case we can't translate some of the values:
202 		_rTranslatedEvent.NewValue = _rEvent.NewValue;
203 		_rTranslatedEvent.OldValue = _rEvent.OldValue;
204 
205 		switch ( _rEvent.EventId )
206 		{
207 			case AccessibleEventId::CHILD:
208 			case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
209 			case AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED:
210 			case AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED:
211 			case AccessibleEventId::LABEL_FOR_RELATION_CHANGED:
212 			case AccessibleEventId::LABELED_BY_RELATION_CHANGED:
213 			case AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED:
214 			case AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED:
215 				// these are events where both the old and the new value contain child references
216 				implTranslateChildEventValue( _rEvent.OldValue, _rTranslatedEvent.OldValue );
217 				implTranslateChildEventValue( _rEvent.NewValue, _rTranslatedEvent.NewValue );
218 				break;
219 
220             case AccessibleEventId::NAME_CHANGED:
221             case AccessibleEventId::DESCRIPTION_CHANGED:
222             case AccessibleEventId::ACTION_CHANGED:
223             case AccessibleEventId::STATE_CHANGED:
224             case AccessibleEventId::BOUNDRECT_CHANGED:
225             case AccessibleEventId::INVALIDATE_ALL_CHILDREN:
226             case AccessibleEventId::SELECTION_CHANGED:
227             case AccessibleEventId::VISIBLE_DATA_CHANGED:
228             case AccessibleEventId::VALUE_CHANGED:
229             case AccessibleEventId::MEMBER_OF_RELATION_CHANGED:
230             case AccessibleEventId::CARET_CHANGED:
231             case AccessibleEventId::TEXT_CHANGED:
232             case AccessibleEventId::HYPERTEXT_CHANGED:
233             case AccessibleEventId::TABLE_CAPTION_CHANGED:
234 			case AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
235 			case AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
236 			case AccessibleEventId::TABLE_MODEL_CHANGED:
237 			case AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
238 			case AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
239 			case AccessibleEventId::TABLE_SUMMARY_CHANGED:
240             // --> PB 2006-03-21 #130798# EventId TEXT_SELECTION_CHANGED was missed
241             // these Ids are also missed: SUB_WINDOW_OF_RELATION_CHANGED & TEXT_ATTRIBUTE_CHANGED
242             case AccessibleEventId::TEXT_SELECTION_CHANGED:
243             // <--
244                 // nothing to translate
245 				break;
246 
247 			default:
248 				OSL_ENSURE( sal_False, "OWrappedAccessibleChildrenManager::translateAccessibleEvent: unknown (or unexpected) event id!" );
249 				break;
250 		}
251 	}
252 
253 	//-------------------------------------------------------------------------
handleChildNotification(const AccessibleEventObject & _rEvent)254 	void OWrappedAccessibleChildrenManager::handleChildNotification( const AccessibleEventObject& _rEvent )
255 	{
256 		if ( AccessibleEventId::INVALIDATE_ALL_CHILDREN == _rEvent.EventId )
257 		{	// clear our child map
258 			invalidateAll( );
259 		}
260 		else if ( AccessibleEventId::CHILD == _rEvent.EventId )
261 		{
262 			// check if the removed or replaced element is cached
263 			Reference< XAccessible > xRemoved;
264 			if ( _rEvent.OldValue >>= xRemoved )
265 				removeFromCache( xRemoved );
266 		}
267 	}
268 
269 	//--------------------------------------------------------------------
disposing(const EventObject & _rSource)270 	void SAL_CALL OWrappedAccessibleChildrenManager::disposing( const EventObject& _rSource ) throw (RuntimeException)
271 	{
272 		// this should come from one of the inner XAccessible's of our children
273 		Reference< XAccessible > xSource( _rSource.Source, UNO_QUERY );
274 		AccessibleMap::iterator aDisposedPos = m_aChildrenMap.find( xSource );
275 #if OSL_DEBUG_LEVEL > 0
276         if ( m_aChildrenMap.end() == aDisposedPos )
277         {
278        		OSL_ENSURE( sal_False,
279 	    		"OWrappedAccessibleChildrenManager::disposing: where did this come from?" );
280             // helper for dignostics
281             Reference< XAccessible > xOwningAccessible( m_aOwningAccessible );
282             Reference< XAccessibleContext > xContext;
283             try
284             {
285                 if ( xOwningAccessible.is() )
286                     xContext = xOwningAccessible->getAccessibleContext();
287                 if ( xContext.is() )
288                 {
289                     ::rtl::OUString sName = xContext->getAccessibleName();
290                     ::rtl::OUString sDescription = xContext->getAccessibleDescription();
291 //                  sal_Int32 nPlaceYourBreakpointHere = 0;
292                 }
293             }
294             catch( const Exception& /*e*/ )
295             {
296                 // silent this, it's only diagnostics which failed
297             }
298         }
299 #endif
300 		if ( m_aChildrenMap.end() != aDisposedPos )
301 		{
302 			m_aChildrenMap.erase( aDisposedPos );
303 		}
304 	}
305 
306 	//=========================================================================
307 	//= OAccessibleWrapper (implementation)
308 	//=========================================================================
309 	//-------------------------------------------------------------------------
OAccessibleWrapper(const Reference<XMultiServiceFactory> & _rxORB,const Reference<XAccessible> & _rxInnerAccessible,const Reference<XAccessible> & _rxParentAccessible)310 	OAccessibleWrapper::OAccessibleWrapper( const Reference< XMultiServiceFactory >& _rxORB,
311 			const Reference< XAccessible >& _rxInnerAccessible, const Reference< XAccessible >& _rxParentAccessible )
312 		:OAccessibleWrapper_Base( )
313 		,OComponentProxyAggregation( _rxORB, Reference< XComponent >( _rxInnerAccessible, UNO_QUERY ) )
314 		,m_xParentAccessible( _rxParentAccessible )
315 		,m_xInnerAccessible( _rxInnerAccessible )
316 	{
317 	}
318 
319 	//--------------------------------------------------------------------
~OAccessibleWrapper()320 	OAccessibleWrapper::~OAccessibleWrapper( )
321 	{
322 		if ( !m_rBHelper.bDisposed )
323 		{
324 			acquire();	// to prevent duplicate dtor calls
325 			dispose();
326 		}
327 	}
328 
329 	//--------------------------------------------------------------------
IMPLEMENT_FORWARD_XTYPEPROVIDER2(OAccessibleWrapper,OComponentProxyAggregation,OAccessibleWrapper_Base)330 	IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleWrapper, OComponentProxyAggregation, OAccessibleWrapper_Base )
331     IMPLEMENT_FORWARD_REFCOUNT( OAccessibleWrapper, OComponentProxyAggregation )
332 
333 	//--------------------------------------------------------------------
334 	Any OAccessibleWrapper::queryInterface( const Type& _rType ) throw (RuntimeException)
335 	{
336         // #111089# instead of the inner XAccessible the proxy XAccessible must be returned
337 		Any aReturn = OAccessibleWrapper_Base::queryInterface( _rType );
338 		if ( !aReturn.hasValue() )
339 			aReturn = OComponentProxyAggregation::queryInterface( _rType );
340 
341 		return aReturn;
342 	}
343 
344 	//--------------------------------------------------------------------
getContextNoCreate() const345 	Reference< XAccessibleContext > OAccessibleWrapper::getContextNoCreate( ) const
346 	{
347 		return (Reference< XAccessibleContext >)m_aContext;
348 	}
349 
350 	//--------------------------------------------------------------------
createAccessibleContext(const Reference<XAccessibleContext> & _rxInnerContext)351 	OAccessibleContextWrapper* OAccessibleWrapper::createAccessibleContext( const Reference< XAccessibleContext >& _rxInnerContext )
352 	{
353 		return new OAccessibleContextWrapper( getORB(), _rxInnerContext, this, m_xParentAccessible );
354 	}
355 
356 	//--------------------------------------------------------------------
getAccessibleContext()357 	Reference< XAccessibleContext > SAL_CALL OAccessibleWrapper::getAccessibleContext(  ) throw (RuntimeException)
358 	{
359 		// see if the context is still alive (we cache it)
360 		Reference< XAccessibleContext > xContext = (Reference< XAccessibleContext >)m_aContext;
361 		if ( !xContext.is() )
362 		{
363 			// create a new context
364 			Reference< XAccessibleContext > xInnerContext = m_xInnerAccessible->getAccessibleContext( );
365 			if ( xInnerContext.is() )
366 			{
367 				xContext = createAccessibleContext( xInnerContext );
368 				// cache it
369 				m_aContext = WeakReference< XAccessibleContext >( xContext );
370 			}
371 		}
372 
373 		return xContext;
374 	}
375 
376 	//=========================================================================
377 	//= OAccessibleWrapper (implementation)
378 	//=========================================================================
379 	//-------------------------------------------------------------------------
OAccessibleContextWrapperHelper(const Reference<XMultiServiceFactory> & _rxORB,::cppu::OBroadcastHelper & _rBHelper,const Reference<XAccessibleContext> & _rxInnerAccessibleContext,const Reference<XAccessible> & _rxOwningAccessible,const Reference<XAccessible> & _rxParentAccessible)380 	OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper(
381 				const Reference< XMultiServiceFactory >& _rxORB,
382 				::cppu::OBroadcastHelper& _rBHelper,
383 				const Reference< XAccessibleContext >& _rxInnerAccessibleContext,
384 				const Reference< XAccessible >& _rxOwningAccessible,
385 				const Reference< XAccessible >& _rxParentAccessible )
386 		:OComponentProxyAggregationHelper( _rxORB, _rBHelper )
387 		,m_xInnerContext( _rxInnerAccessibleContext )
388 		,m_xOwningAccessible( _rxOwningAccessible )
389 		,m_xParentAccessible( _rxParentAccessible )
390 		,m_pChildMapper( NULL )
391 	{
392 		// initialize the mapper for our children
393 		m_pChildMapper = new OWrappedAccessibleChildrenManager( getORB() );
394 		m_pChildMapper->acquire();
395 
396 		// determine if we're allowed to cache children
397 		Reference< XAccessibleStateSet > xStates( m_xInnerContext->getAccessibleStateSet( ) );
398 		OSL_ENSURE( xStates.is(), "OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper: no inner state set!" );
399 		m_pChildMapper->setTransientChildren( !xStates.is() || xStates->contains( AccessibleStateType::MANAGES_DESCENDANTS) );
400 
401 		m_pChildMapper->setOwningAccessible( m_xOwningAccessible );
402 	}
403 
404 	//--------------------------------------------------------------------
aggregateProxy(oslInterlockedCount & _rRefCount,::cppu::OWeakObject & _rDelegator)405 	void OAccessibleContextWrapperHelper::aggregateProxy( oslInterlockedCount& _rRefCount, ::cppu::OWeakObject& _rDelegator )
406 	{
407 		Reference< XComponent > xInnerComponent( m_xInnerContext, UNO_QUERY );
408 		OSL_ENSURE( xInnerComponent.is(), "OComponentProxyAggregation::aggregateProxy: accessible is no XComponent!" );
409         if ( xInnerComponent.is() )
410 		    componentAggregateProxyFor( xInnerComponent, _rRefCount, _rDelegator );
411 
412 		// add as event listener to the inner context, because we want to multiplex the AccessibleEvents
413 		osl_incrementInterlockedCount( &_rRefCount );
414 		{
415 			Reference< XAccessibleEventBroadcaster > xBroadcaster( m_xInner, UNO_QUERY );
416 			if ( xBroadcaster.is() )
417 				xBroadcaster->addEventListener( this );
418 		}
419 		osl_decrementInterlockedCount( &_rRefCount );
420 	}
421 
422 	//--------------------------------------------------------------------
~OAccessibleContextWrapperHelper()423 	OAccessibleContextWrapperHelper::~OAccessibleContextWrapperHelper( )
424 	{
425 		OSL_ENSURE( m_rBHelper.bDisposed, "OAccessibleContextWrapperHelper::~OAccessibleContextWrapperHelper: you should ensure (in your dtor) that the object is disposed!" );
426 
427 		m_pChildMapper->release();
428 		m_pChildMapper = NULL;
429 	}
430 
431 	//--------------------------------------------------------------------
queryInterface(const Type & _rType)432 	Any SAL_CALL OAccessibleContextWrapperHelper::queryInterface( const Type& _rType ) throw (RuntimeException)
433 	{
434 		Any aReturn = OComponentProxyAggregationHelper::queryInterface( _rType );
435 		if ( !aReturn.hasValue() )
436 			aReturn = OAccessibleContextWrapperHelper_Base::queryInterface( _rType );
437 		return aReturn;
438 	}
439 
440 	//--------------------------------------------------------------------
IMPLEMENT_FORWARD_XTYPEPROVIDER2(OAccessibleContextWrapperHelper,OComponentProxyAggregationHelper,OAccessibleContextWrapperHelper_Base)441 	IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapperHelper, OComponentProxyAggregationHelper, OAccessibleContextWrapperHelper_Base )
442 
443 	//--------------------------------------------------------------------
444 	sal_Int32 SAL_CALL OAccessibleContextWrapperHelper::getAccessibleChildCount(  ) throw (RuntimeException)
445 	{
446 		return m_xInnerContext->getAccessibleChildCount();
447 	}
448 
449 	//--------------------------------------------------------------------
getAccessibleChild(sal_Int32 i)450 	Reference< XAccessible > SAL_CALL OAccessibleContextWrapperHelper::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
451 	{
452 		// get the child of the wrapped component
453 		Reference< XAccessible > xInnerChild = m_xInnerContext->getAccessibleChild( i );
454 		return m_pChildMapper->getAccessibleWrapperFor( xInnerChild );
455 	}
456 
457 	//--------------------------------------------------------------------
getAccessibleRelationSet()458 	Reference< XAccessibleRelationSet > SAL_CALL OAccessibleContextWrapperHelper::getAccessibleRelationSet(  ) throw (RuntimeException)
459 	{
460 		return m_xInnerContext->getAccessibleRelationSet();
461 			// TODO: if this relation set would contain relations to siblings, we would normally need
462 			// to wrap them, too ....
463 	}
464 
465 	//--------------------------------------------------------------------
notifyEvent(const AccessibleEventObject & _rEvent)466 	void SAL_CALL OAccessibleContextWrapperHelper::notifyEvent( const AccessibleEventObject& _rEvent ) throw (RuntimeException)
467 	{
468 #if OSL_DEBUG_LEVEL > 0
469 		if ( AccessibleEventId::STATE_CHANGED == _rEvent.EventId )
470 		{
471 			sal_Bool bChildTransienceChanged = sal_False;
472 			sal_Int16 nChangeState = 0;
473 			if ( _rEvent.OldValue >>= nChangeState )
474 				bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState;
475 			if ( _rEvent.NewValue >>= nChangeState )
476 				bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState;
477 			OSL_ENSURE( !bChildTransienceChanged, "OAccessibleContextWrapperHelper::notifyEvent: MANAGES_DESCENDANTS is not expected to change during runtime!" );
478 				// if this asserts, then we would need to update our m_bTransientChildren flag here,
479 				// as well as (potentially) our child cache
480 		}
481 #endif
482 		AccessibleEventObject aTranslatedEvent( _rEvent );
483 
484 		{
485 			::osl::MutexGuard aGuard( m_rBHelper.rMutex );
486 
487             // translate the event
488 			queryInterface( ::getCppuType( static_cast< Reference< XInterface >* >( NULL ) ) ) >>= aTranslatedEvent.Source;
489 			m_pChildMapper->translateAccessibleEvent( _rEvent, aTranslatedEvent );
490 
491             // see if any of these notifications affect our child manager
492 			m_pChildMapper->handleChildNotification( _rEvent );
493 
494             if ( aTranslatedEvent.NewValue == m_xInner )
495 				aTranslatedEvent.NewValue = makeAny(aTranslatedEvent.Source);
496 			if ( aTranslatedEvent.OldValue == m_xInner )
497 				aTranslatedEvent.OldValue = makeAny(aTranslatedEvent.Source);
498 		}
499 
500 		notifyTranslatedEvent( aTranslatedEvent );
501 	}
502 
503 	//--------------------------------------------------------------------
dispose()504 	void SAL_CALL OAccessibleContextWrapperHelper::dispose() throw( RuntimeException )
505 	{
506 		::osl::MutexGuard aGuard( m_rBHelper.rMutex );
507 
508 		// stop multiplexing events
509 		Reference< XAccessibleEventBroadcaster > xBroadcaster( m_xInner, UNO_QUERY );
510 		OSL_ENSURE( xBroadcaster.is(), "OAccessibleContextWrapperHelper::disposing(): inner context is no broadcaster!" );
511 		if ( xBroadcaster.is() )
512 			xBroadcaster->removeEventListener( this );
513 
514 		// dispose the child cache/map
515 		m_pChildMapper->dispose();
516 
517 		// let the base class dispose the inner component
518 		OComponentProxyAggregationHelper::dispose();
519 	}
520 
521 	//--------------------------------------------------------------------
disposing(const EventObject & _rEvent)522 	void SAL_CALL OAccessibleContextWrapperHelper::disposing( const EventObject& _rEvent )  throw (RuntimeException)
523 	{
524 		// simply disambiguate this
525 		OComponentProxyAggregationHelper::disposing( _rEvent );
526 	}
527 
528 	//====================================================================
529 	//= OAccessibleContextWrapper
530 	//====================================================================
531 	//--------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2(OAccessibleContextWrapper,OAccessibleContextWrapper_CBase,OAccessibleContextWrapperHelper)532 	IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleContextWrapper, OAccessibleContextWrapper_CBase, OAccessibleContextWrapperHelper )
533 
534 	//--------------------------------------------------------------------
535 	IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapper, OAccessibleContextWrapper_CBase, OAccessibleContextWrapperHelper )
536 
537 	//--------------------------------------------------------------------
538 	OAccessibleContextWrapper::OAccessibleContextWrapper( const Reference< XMultiServiceFactory >& _rxORB,
539 			const Reference< XAccessibleContext >& _rxInnerAccessibleContext, const Reference< XAccessible >& _rxOwningAccessible,
540 			const Reference< XAccessible >& _rxParentAccessible )
541 		:OAccessibleContextWrapper_CBase( m_aMutex )
542 		,OAccessibleContextWrapperHelper( _rxORB, rBHelper, _rxInnerAccessibleContext, _rxOwningAccessible, _rxParentAccessible )
543 		,m_nNotifierClient( 0 )
544 	{
545 		aggregateProxy( m_refCount, *this );
546 	}
547 
548 	//--------------------------------------------------------------------
~OAccessibleContextWrapper()549 	OAccessibleContextWrapper::~OAccessibleContextWrapper()
550 	{
551 	}
552 
553 	//--------------------------------------------------------------------
getAccessibleChildCount()554 	sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleChildCount(  ) throw (RuntimeException)
555 	{
556 		return OAccessibleContextWrapperHelper::getAccessibleChildCount();
557 	}
558 
559 	//--------------------------------------------------------------------
getAccessibleChild(sal_Int32 i)560 	Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
561 	{
562 		return OAccessibleContextWrapperHelper::getAccessibleChild( i );
563 	}
564 
565 	//--------------------------------------------------------------------
getAccessibleParent()566 	Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleParent(  ) throw (RuntimeException)
567 	{
568 		return m_xParentAccessible;
569 	}
570 
571 	//--------------------------------------------------------------------
getAccessibleIndexInParent()572 	sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent(  ) throw (RuntimeException)
573 	{
574 		return m_xInnerContext->getAccessibleIndexInParent();
575 	}
576 
577 	//--------------------------------------------------------------------
getAccessibleRole()578 	sal_Int16 SAL_CALL OAccessibleContextWrapper::getAccessibleRole(  ) throw (RuntimeException)
579 	{
580 		return m_xInnerContext->getAccessibleRole();
581 	}
582 
583 	//--------------------------------------------------------------------
getAccessibleDescription()584 	::rtl::OUString SAL_CALL OAccessibleContextWrapper::getAccessibleDescription(  ) throw (RuntimeException)
585 	{
586 		return m_xInnerContext->getAccessibleDescription();
587 	}
588 
589 	//--------------------------------------------------------------------
getAccessibleName()590 	::rtl::OUString SAL_CALL OAccessibleContextWrapper::getAccessibleName(  ) throw (RuntimeException)
591 	{
592 		return m_xInnerContext->getAccessibleName();
593 	}
594 
595 	//--------------------------------------------------------------------
getAccessibleRelationSet()596 	Reference< XAccessibleRelationSet > SAL_CALL OAccessibleContextWrapper::getAccessibleRelationSet(  ) throw (RuntimeException)
597 	{
598 		return OAccessibleContextWrapperHelper::getAccessibleRelationSet();
599 	}
600 
601 	//--------------------------------------------------------------------
getAccessibleStateSet()602 	Reference< XAccessibleStateSet > SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet(  ) throw (RuntimeException)
603 	{
604 		return m_xInnerContext->getAccessibleStateSet();
605 	}
606 
607 	//--------------------------------------------------------------------
getLocale()608 	Locale SAL_CALL OAccessibleContextWrapper::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
609 	{
610 		return m_xInnerContext->getLocale();
611 	}
612 
613 	//--------------------------------------------------------------------
notifyTranslatedEvent(const AccessibleEventObject & _rEvent)614 	void OAccessibleContextWrapper::notifyTranslatedEvent( const AccessibleEventObject& _rEvent ) throw (RuntimeException)
615 	{
616 		if ( m_nNotifierClient )
617 			AccessibleEventNotifier::addEvent( m_nNotifierClient, _rEvent );
618 	}
619 
620 	//--------------------------------------------------------------------
addEventListener(const Reference<XAccessibleEventListener> & _rxListener)621 	void SAL_CALL OAccessibleContextWrapper::addEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException)
622 	{
623 		::osl::MutexGuard aGuard( m_aMutex );
624 		if ( !m_nNotifierClient )
625 			m_nNotifierClient = AccessibleEventNotifier::registerClient( );
626 		AccessibleEventNotifier::addEventListener( m_nNotifierClient, _rxListener );
627 	}
628 
629 	//--------------------------------------------------------------------
removeEventListener(const Reference<XAccessibleEventListener> & _rxListener)630 	void SAL_CALL OAccessibleContextWrapper::removeEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException)
631 	{
632 		::osl::MutexGuard aGuard( m_aMutex );
633 		if ( m_nNotifierClient )
634 		{
635 			if ( 0 == AccessibleEventNotifier::removeEventListener( m_nNotifierClient, _rxListener ) )
636 			{
637 				AccessibleEventNotifier::TClientId nId( m_nNotifierClient );
638 				m_nNotifierClient = 0;
639 				AccessibleEventNotifier::revokeClient( nId );
640 			}
641 		}
642 	}
643 
644 	//--------------------------------------------------------------------
disposing()645 	void SAL_CALL OAccessibleContextWrapper::disposing()  throw (RuntimeException)
646 	{
647 		AccessibleEventNotifier::TClientId nClientId( 0 );
648 
649 		// --- <mutex lock> -----------------------------------------
650 		{
651 			::osl::MutexGuard aGuard( m_aMutex );
652 
653 			// prepare notifying our AccessibleListeners
654 			if ( m_nNotifierClient )
655 			{
656 				nClientId = m_nNotifierClient;
657 				m_nNotifierClient = 0;
658 			}
659 		}
660 		// --- </mutex lock> -----------------------------------------
661 
662 		// let the base class do
663 		OAccessibleContextWrapperHelper::dispose();
664 
665 		// notify the disposal
666 		if ( nClientId )
667 			AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
668 	}
669 
670 	//--------------------------------------------------------------------
dispose()671 	void SAL_CALL OAccessibleContextWrapper::dispose() throw( RuntimeException )
672 	{
673 		// simply disambiguate
674 		OComponentProxyAggregation_CBase::dispose();
675 	}
676 
677 //.............................................................................
678 }	// namespace accessibility
679 //.............................................................................
680