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