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