1*dde7d3faSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*dde7d3faSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*dde7d3faSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*dde7d3faSAndrew Rist * distributed with this work for additional information 6*dde7d3faSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*dde7d3faSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*dde7d3faSAndrew Rist * "License"); you may not use this file except in compliance 9*dde7d3faSAndrew Rist * with the License. You may obtain a copy of the License at 10*dde7d3faSAndrew Rist * 11*dde7d3faSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*dde7d3faSAndrew Rist * 13*dde7d3faSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*dde7d3faSAndrew Rist * software distributed under the License is distributed on an 15*dde7d3faSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*dde7d3faSAndrew Rist * KIND, either express or implied. See the License for the 17*dde7d3faSAndrew Rist * specific language governing permissions and limitations 18*dde7d3faSAndrew Rist * under the License. 19*dde7d3faSAndrew Rist * 20*dde7d3faSAndrew Rist *************************************************************/ 21*dde7d3faSAndrew Rist 22*dde7d3faSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_comphelper.hxx" 26cdf0e10cSrcweir #include <comphelper/accessiblecontexthelper.hxx> 27cdf0e10cSrcweir #include <comphelper/accessibleeventbuffer.hxx> 28cdf0e10cSrcweir #include <osl/diagnose.h> 29cdf0e10cSrcweir #include <cppuhelper/weakref.hxx> 30cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleEventId.hpp> 31cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleStateType.hpp> 32cdf0e10cSrcweir #include <comphelper/accessibleeventnotifier.hxx> 33cdf0e10cSrcweir 34cdf0e10cSrcweir //......................................................................... 35cdf0e10cSrcweir namespace comphelper 36cdf0e10cSrcweir { 37cdf0e10cSrcweir //......................................................................... 38cdf0e10cSrcweir 39cdf0e10cSrcweir using namespace ::com::sun::star::uno; 40cdf0e10cSrcweir using namespace ::com::sun::star::lang; 41cdf0e10cSrcweir using namespace ::com::sun::star::accessibility; 42cdf0e10cSrcweir 43cdf0e10cSrcweir //===================================================================== 44cdf0e10cSrcweir //= OContextHelper_Impl 45cdf0e10cSrcweir //===================================================================== 46cdf0e10cSrcweir /** implementation class for OAccessibleContextHelper. No own thread safety! 47cdf0e10cSrcweir */ 48cdf0e10cSrcweir class OContextHelper_Impl 49cdf0e10cSrcweir { 50cdf0e10cSrcweir private: 51cdf0e10cSrcweir OAccessibleContextHelper* m_pAntiImpl; // the owning instance 52cdf0e10cSrcweir IMutex* m_pExternalLock; // the optional additional external lock 53cdf0e10cSrcweir 54cdf0e10cSrcweir ::cppu::OInterfaceContainerHelper* m_pEventListeners; 55cdf0e10cSrcweir WeakReference< XAccessible > m_aCreator; // the XAccessible which created our XAccessibleContext 56cdf0e10cSrcweir 57cdf0e10cSrcweir AccessibleEventNotifier::TClientId m_nClientId; 58cdf0e10cSrcweir 59cdf0e10cSrcweir public: getCreator() const60cdf0e10cSrcweir inline Reference< XAccessible > getCreator( ) const { return m_aCreator; } 61cdf0e10cSrcweir inline void setCreator( const Reference< XAccessible >& _rAcc ); 62cdf0e10cSrcweir getExternalLock()63cdf0e10cSrcweir inline IMutex* getExternalLock( ) { return m_pExternalLock; } setExternalLock(IMutex * _pLock)64cdf0e10cSrcweir inline void setExternalLock( IMutex* _pLock ) { m_pExternalLock = _pLock; } 65cdf0e10cSrcweir 66cdf0e10cSrcweir inline AccessibleEventNotifier::TClientId getClientId() const67cdf0e10cSrcweir getClientId() const { return m_nClientId; } setClientId(const AccessibleEventNotifier::TClientId _nId)68cdf0e10cSrcweir inline void setClientId( const AccessibleEventNotifier::TClientId _nId ) 69cdf0e10cSrcweir { m_nClientId = _nId; } 70cdf0e10cSrcweir 71cdf0e10cSrcweir public: OContextHelper_Impl(OAccessibleContextHelper * _pAntiImpl)72cdf0e10cSrcweir OContextHelper_Impl( OAccessibleContextHelper* _pAntiImpl ) 73cdf0e10cSrcweir :m_pAntiImpl( _pAntiImpl ) 74cdf0e10cSrcweir ,m_pExternalLock( NULL ) 75cdf0e10cSrcweir ,m_pEventListeners( NULL ) 76cdf0e10cSrcweir ,m_nClientId( 0 ) 77cdf0e10cSrcweir { 78cdf0e10cSrcweir } 79cdf0e10cSrcweir }; 80cdf0e10cSrcweir 81cdf0e10cSrcweir //--------------------------------------------------------------------- setCreator(const Reference<XAccessible> & _rAcc)82cdf0e10cSrcweir inline void OContextHelper_Impl::setCreator( const Reference< XAccessible >& _rAcc ) 83cdf0e10cSrcweir { 84cdf0e10cSrcweir m_aCreator = _rAcc; 85cdf0e10cSrcweir } 86cdf0e10cSrcweir 87cdf0e10cSrcweir //===================================================================== 88cdf0e10cSrcweir //= OAccessibleContextHelper 89cdf0e10cSrcweir //===================================================================== 90cdf0e10cSrcweir //--------------------------------------------------------------------- OAccessibleContextHelper()91cdf0e10cSrcweir OAccessibleContextHelper::OAccessibleContextHelper( ) 92cdf0e10cSrcweir :OAccessibleContextHelper_Base( GetMutex() ) 93cdf0e10cSrcweir ,m_pImpl( NULL ) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir m_pImpl = new OContextHelper_Impl( this ); 96cdf0e10cSrcweir } 97cdf0e10cSrcweir 98cdf0e10cSrcweir //--------------------------------------------------------------------- OAccessibleContextHelper(IMutex * _pExternalLock)99cdf0e10cSrcweir OAccessibleContextHelper::OAccessibleContextHelper( IMutex* _pExternalLock ) 100cdf0e10cSrcweir :OAccessibleContextHelper_Base( GetMutex() ) 101cdf0e10cSrcweir ,m_pImpl( NULL ) 102cdf0e10cSrcweir { 103cdf0e10cSrcweir m_pImpl = new OContextHelper_Impl( this ); 104cdf0e10cSrcweir m_pImpl->setExternalLock( _pExternalLock ); 105cdf0e10cSrcweir } 106cdf0e10cSrcweir 107cdf0e10cSrcweir //--------------------------------------------------------------------- forgetExternalLock()108cdf0e10cSrcweir void OAccessibleContextHelper::forgetExternalLock() 109cdf0e10cSrcweir { 110cdf0e10cSrcweir m_pImpl->setExternalLock( NULL ); 111cdf0e10cSrcweir } 112cdf0e10cSrcweir 113cdf0e10cSrcweir //--------------------------------------------------------------------- ~OAccessibleContextHelper()114cdf0e10cSrcweir OAccessibleContextHelper::~OAccessibleContextHelper( ) 115cdf0e10cSrcweir { 116cdf0e10cSrcweir forgetExternalLock(); 117cdf0e10cSrcweir // this ensures that the lock, which may be already destroyed as part of the derivee, 118cdf0e10cSrcweir // is not used anymore 119cdf0e10cSrcweir 120cdf0e10cSrcweir ensureDisposed(); 121cdf0e10cSrcweir 122cdf0e10cSrcweir delete m_pImpl; 123cdf0e10cSrcweir m_pImpl = NULL; 124cdf0e10cSrcweir } 125cdf0e10cSrcweir 126cdf0e10cSrcweir //--------------------------------------------------------------------- getExternalLock()127cdf0e10cSrcweir IMutex* OAccessibleContextHelper::getExternalLock( ) 128cdf0e10cSrcweir { 129cdf0e10cSrcweir return m_pImpl->getExternalLock(); 130cdf0e10cSrcweir } 131cdf0e10cSrcweir 132cdf0e10cSrcweir //--------------------------------------------------------------------- disposing()133cdf0e10cSrcweir void SAL_CALL OAccessibleContextHelper::disposing() 134cdf0e10cSrcweir { 135cdf0e10cSrcweir ::osl::ClearableMutexGuard aGuard( GetMutex() ); 136cdf0e10cSrcweir 137cdf0e10cSrcweir if ( m_pImpl->getClientId( ) ) 138cdf0e10cSrcweir { 139cdf0e10cSrcweir AccessibleEventNotifier::revokeClientNotifyDisposing( m_pImpl->getClientId( ), *this ); 140cdf0e10cSrcweir m_pImpl->setClientId( 0 ); 141cdf0e10cSrcweir } 142cdf0e10cSrcweir } 143cdf0e10cSrcweir 144cdf0e10cSrcweir //--------------------------------------------------------------------- addEventListener(const Reference<XAccessibleEventListener> & _rxListener)145cdf0e10cSrcweir void SAL_CALL OAccessibleContextHelper::addEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir OMutexGuard aGuard( getExternalLock() ); 148cdf0e10cSrcweir // don't use the OContextEntryGuard - it will throw an exception if we're not alive 149cdf0e10cSrcweir // anymore, while the most recent specification for XComponent states that we should 150cdf0e10cSrcweir // silently ignore the call in such a situation 151cdf0e10cSrcweir if ( !isAlive() ) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir if ( _rxListener.is() ) 154cdf0e10cSrcweir _rxListener->disposing( EventObject( *this ) ); 155cdf0e10cSrcweir return; 156cdf0e10cSrcweir } 157cdf0e10cSrcweir 158cdf0e10cSrcweir if ( _rxListener.is() ) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir if ( !m_pImpl->getClientId( ) ) 161cdf0e10cSrcweir m_pImpl->setClientId( AccessibleEventNotifier::registerClient( ) ); 162cdf0e10cSrcweir 163cdf0e10cSrcweir AccessibleEventNotifier::addEventListener( m_pImpl->getClientId( ), _rxListener ); 164cdf0e10cSrcweir } 165cdf0e10cSrcweir } 166cdf0e10cSrcweir 167cdf0e10cSrcweir //--------------------------------------------------------------------- removeEventListener(const Reference<XAccessibleEventListener> & _rxListener)168cdf0e10cSrcweir void SAL_CALL OAccessibleContextHelper::removeEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException) 169cdf0e10cSrcweir { 170cdf0e10cSrcweir OMutexGuard aGuard( getExternalLock() ); 171cdf0e10cSrcweir // don't use the OContextEntryGuard - it will throw an exception if we're not alive 172cdf0e10cSrcweir // anymore, while the most recent specification for XComponent states that we should 173cdf0e10cSrcweir // silently ignore the call in such a situation 174cdf0e10cSrcweir if ( !isAlive() ) 175cdf0e10cSrcweir return; 176cdf0e10cSrcweir 177cdf0e10cSrcweir if ( _rxListener.is() ) 178cdf0e10cSrcweir { 179cdf0e10cSrcweir sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( m_pImpl->getClientId( ), _rxListener ); 180cdf0e10cSrcweir if ( !nListenerCount ) 181cdf0e10cSrcweir { 182cdf0e10cSrcweir // no listeners anymore 183cdf0e10cSrcweir // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), 184cdf0e10cSrcweir // and at least to us not firing any events anymore, in case somebody calls 185cdf0e10cSrcweir // NotifyAccessibleEvent, again 186cdf0e10cSrcweir AccessibleEventNotifier::revokeClient( m_pImpl->getClientId( ) ); 187cdf0e10cSrcweir m_pImpl->setClientId( 0 ); 188cdf0e10cSrcweir } 189cdf0e10cSrcweir } 190cdf0e10cSrcweir } 191cdf0e10cSrcweir 192cdf0e10cSrcweir //--------------------------------------------------------------------- NotifyAccessibleEvent(const sal_Int16 _nEventId,const Any & _rOldValue,const Any & _rNewValue)193cdf0e10cSrcweir void SAL_CALL OAccessibleContextHelper::NotifyAccessibleEvent( const sal_Int16 _nEventId, 194cdf0e10cSrcweir const Any& _rOldValue, const Any& _rNewValue ) 195cdf0e10cSrcweir { 196cdf0e10cSrcweir if ( !m_pImpl->getClientId( ) ) 197cdf0e10cSrcweir // if we don't have a client id for the notifier, then we don't have listeners, then 198cdf0e10cSrcweir // we don't need to notify anything 199cdf0e10cSrcweir return; 200cdf0e10cSrcweir 201cdf0e10cSrcweir // build an event object 202cdf0e10cSrcweir AccessibleEventObject aEvent; 203cdf0e10cSrcweir aEvent.Source = *this; 204cdf0e10cSrcweir aEvent.EventId = _nEventId; 205cdf0e10cSrcweir aEvent.OldValue = _rOldValue; 206cdf0e10cSrcweir aEvent.NewValue = _rNewValue; 207cdf0e10cSrcweir 208cdf0e10cSrcweir // let the notifier handle this event 209cdf0e10cSrcweir AccessibleEventNotifier::addEvent( m_pImpl->getClientId( ), aEvent ); 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir //--------------------------------------------------------------------- BufferAccessibleEvent(const sal_Int16 _nEventId,const Any & _rOldValue,const Any & _rNewValue,AccessibleEventBuffer & _rBuffer)213cdf0e10cSrcweir void SAL_CALL OAccessibleContextHelper::BufferAccessibleEvent( const sal_Int16 _nEventId, 214cdf0e10cSrcweir const Any& _rOldValue, const Any& _rNewValue, 215cdf0e10cSrcweir AccessibleEventBuffer & _rBuffer ) 216cdf0e10cSrcweir { 217cdf0e10cSrcweir // TODO: this whole method (as well as the class AccessibleEventBuffer) should be removed 218cdf0e10cSrcweir // The reasons why they have been introduces id that we needed to collect a set of events 219cdf0e10cSrcweir // before notifying them alltogether (after releasing our mutex). With the other 220cdf0e10cSrcweir // NotifyAccessibleEvent being asynchronous now, this should not be necessary anymore 221cdf0e10cSrcweir // - clients could use the other version now. 222cdf0e10cSrcweir 223cdf0e10cSrcweir // copy our current listeners 224cdf0e10cSrcweir Sequence< Reference< XInterface > > aListeners; 225cdf0e10cSrcweir if ( m_pImpl->getClientId( ) ) 226cdf0e10cSrcweir aListeners = AccessibleEventNotifier::getEventListeners( m_pImpl->getClientId( ) ); 227cdf0e10cSrcweir 228cdf0e10cSrcweir if ( aListeners.getLength() ) 229cdf0e10cSrcweir { 230cdf0e10cSrcweir AccessibleEventObject aEvent; 231cdf0e10cSrcweir aEvent.Source = *this; 232cdf0e10cSrcweir OSL_ENSURE( aEvent.Source.is(), "OAccessibleContextHelper::BufferAccessibleEvent: invalid creator!" ); 233cdf0e10cSrcweir aEvent.EventId = _nEventId; 234cdf0e10cSrcweir aEvent.OldValue = _rOldValue; 235cdf0e10cSrcweir aEvent.NewValue = _rNewValue; 236cdf0e10cSrcweir 237cdf0e10cSrcweir _rBuffer.addEvent( aEvent, aListeners ); 238cdf0e10cSrcweir } 239cdf0e10cSrcweir } 240cdf0e10cSrcweir 241cdf0e10cSrcweir //--------------------------------------------------------------------- isAlive() const242cdf0e10cSrcweir sal_Bool OAccessibleContextHelper::isAlive() const 243cdf0e10cSrcweir { 244cdf0e10cSrcweir return !GetBroadcastHelper().bDisposed && !GetBroadcastHelper().bInDispose; 245cdf0e10cSrcweir } 246cdf0e10cSrcweir 247cdf0e10cSrcweir //--------------------------------------------------------------------- ensureAlive() const248cdf0e10cSrcweir void OAccessibleContextHelper::ensureAlive() const SAL_THROW( ( DisposedException ) ) 249cdf0e10cSrcweir { 250cdf0e10cSrcweir if( !isAlive() ) 251cdf0e10cSrcweir throw DisposedException(); 252cdf0e10cSrcweir } 253cdf0e10cSrcweir 254cdf0e10cSrcweir //--------------------------------------------------------------------- ensureDisposed()255cdf0e10cSrcweir void OAccessibleContextHelper::ensureDisposed( ) 256cdf0e10cSrcweir { 257cdf0e10cSrcweir if ( !GetBroadcastHelper().bDisposed ) 258cdf0e10cSrcweir { 259cdf0e10cSrcweir OSL_ENSURE( 0 == m_refCount, "OAccessibleContextHelper::ensureDisposed: this method _has_ to be called from without your dtor only!" ); 260cdf0e10cSrcweir acquire(); 261cdf0e10cSrcweir dispose(); 262cdf0e10cSrcweir } 263cdf0e10cSrcweir } 264cdf0e10cSrcweir 265cdf0e10cSrcweir //--------------------------------------------------------------------- lateInit(const Reference<XAccessible> & _rxAccessible)266cdf0e10cSrcweir void OAccessibleContextHelper::lateInit( const Reference< XAccessible >& _rxAccessible ) 267cdf0e10cSrcweir { 268cdf0e10cSrcweir m_pImpl->setCreator( _rxAccessible ); 269cdf0e10cSrcweir } 270cdf0e10cSrcweir 271cdf0e10cSrcweir //--------------------------------------------------------------------- getAccessibleCreator() const272cdf0e10cSrcweir Reference< XAccessible > OAccessibleContextHelper::getAccessibleCreator( ) const 273cdf0e10cSrcweir { 274cdf0e10cSrcweir return m_pImpl->getCreator(); 275cdf0e10cSrcweir } 276cdf0e10cSrcweir 277cdf0e10cSrcweir //--------------------------------------------------------------------- getAccessibleIndexInParent()278cdf0e10cSrcweir sal_Int32 SAL_CALL OAccessibleContextHelper::getAccessibleIndexInParent( ) throw (RuntimeException) 279cdf0e10cSrcweir { 280cdf0e10cSrcweir OExternalLockGuard aGuard( this ); 281cdf0e10cSrcweir 282cdf0e10cSrcweir // -1 for child not found/no parent (according to specification) 283cdf0e10cSrcweir sal_Int32 nRet = -1; 284cdf0e10cSrcweir 285cdf0e10cSrcweir try 286cdf0e10cSrcweir { 287cdf0e10cSrcweir 288cdf0e10cSrcweir Reference< XAccessibleContext > xParentContext( implGetParentContext() ); 289cdf0e10cSrcweir 290cdf0e10cSrcweir // iterate over parent's children and search for this object 291cdf0e10cSrcweir if ( xParentContext.is() ) 292cdf0e10cSrcweir { 293cdf0e10cSrcweir // our own XAccessible for comparing with the children of our parent 294cdf0e10cSrcweir Reference< XAccessible > xCreator( m_pImpl->getCreator() ); 295cdf0e10cSrcweir 296cdf0e10cSrcweir OSL_ENSURE( xCreator.is(), "OAccessibleContextHelper::getAccessibleIndexInParent: invalid creator!" ); 297cdf0e10cSrcweir // two ideas why this could be NULL: 298cdf0e10cSrcweir // * nobody called our late ctor (init), so we never had a creator at all -> bad 299cdf0e10cSrcweir // * the creator is already dead. In this case, we should have been disposed, and 300cdf0e10cSrcweir // never survived the above OContextEntryGuard. 301cdf0e10cSrcweir // in all other situations the creator should be non-NULL 302cdf0e10cSrcweir 303cdf0e10cSrcweir if ( xCreator.is() ) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); 306cdf0e10cSrcweir for ( sal_Int32 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild ) 307cdf0e10cSrcweir { 308cdf0e10cSrcweir Reference< XAccessible > xChild( xParentContext->getAccessibleChild( nChild ) ); 309cdf0e10cSrcweir if ( xChild.get() == xCreator.get() ) 310cdf0e10cSrcweir nRet = nChild; 311cdf0e10cSrcweir } 312cdf0e10cSrcweir } 313cdf0e10cSrcweir } 314cdf0e10cSrcweir } 315cdf0e10cSrcweir catch( const Exception& ) 316cdf0e10cSrcweir { 317cdf0e10cSrcweir OSL_ENSURE( sal_False, "OAccessibleContextHelper::getAccessibleIndexInParent: caught an exception!" ); 318cdf0e10cSrcweir } 319cdf0e10cSrcweir 320cdf0e10cSrcweir return nRet; 321cdf0e10cSrcweir } 322cdf0e10cSrcweir 323cdf0e10cSrcweir //--------------------------------------------------------------------- getLocale()324cdf0e10cSrcweir Locale SAL_CALL OAccessibleContextHelper::getLocale( ) throw (IllegalAccessibleComponentStateException, RuntimeException) 325cdf0e10cSrcweir { 326cdf0e10cSrcweir // simply ask the parent 327cdf0e10cSrcweir Reference< XAccessible > xParent = getAccessibleParent(); 328cdf0e10cSrcweir Reference< XAccessibleContext > xParentContext; 329cdf0e10cSrcweir if ( xParent.is() ) 330cdf0e10cSrcweir xParentContext = xParent->getAccessibleContext(); 331cdf0e10cSrcweir 332cdf0e10cSrcweir if ( !xParentContext.is() ) 333cdf0e10cSrcweir throw IllegalAccessibleComponentStateException( ::rtl::OUString(), *this ); 334cdf0e10cSrcweir 335cdf0e10cSrcweir return xParentContext->getLocale(); 336cdf0e10cSrcweir } 337cdf0e10cSrcweir 338cdf0e10cSrcweir //--------------------------------------------------------------------- implGetParentContext()339cdf0e10cSrcweir Reference< XAccessibleContext > OAccessibleContextHelper::implGetParentContext() SAL_THROW( ( RuntimeException ) ) 340cdf0e10cSrcweir { 341cdf0e10cSrcweir Reference< XAccessible > xParent = getAccessibleParent(); 342cdf0e10cSrcweir Reference< XAccessibleContext > xParentContext; 343cdf0e10cSrcweir if ( xParent.is() ) 344cdf0e10cSrcweir xParentContext = xParent->getAccessibleContext(); 345cdf0e10cSrcweir return xParentContext; 346cdf0e10cSrcweir } 347cdf0e10cSrcweir 348cdf0e10cSrcweir //......................................................................... 349cdf0e10cSrcweir } // namespace comphelper 350cdf0e10cSrcweir //......................................................................... 351cdf0e10cSrcweir 352cdf0e10cSrcweir 353