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