xref: /AOO41X/main/comphelper/source/misc/accessiblewrapper.cxx (revision dde7d3faf6dcd9cbeb7b48ba6d0cea5ffcc883d0)
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