/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include #include #include #include #ifndef _SV_SYSDATA_HXX #if defined( WIN ) || defined( WNT ) || defined( OS2 ) typedef sal_Int32 HWND; #endif #endif #include "AccEventListener.hxx" #include "AccObjectManagerAgent.hxx" #include "unomsaaevent.hxx" #include #include #include #include #include #include #include using namespace com::sun::star::uno; using namespace com::sun::star::accessibility; using namespace rtl; using namespace cppu; AccEventListener::AccEventListener(com::sun::star::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent) :pAccessible(pAcc), pAgent(Agent), m_isDisposed(false), m_refcount(0) {} AccEventListener::~AccEventListener() { } /** * Uno's event notifier when event is captured * @param AccessibleEventObject the event object which contains information about event */ void AccEventListener::notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException) { switch (aEvent.EventId) { case AccessibleEventId::NAME_CHANGED: handleNameChangedEvent(aEvent.NewValue); break; case AccessibleEventId::DESCRIPTION_CHANGED: handleDescriptionChangedEvent(aEvent.NewValue); break; case AccessibleEventId::STATE_CHANGED: handleStateChangedEvent(aEvent.OldValue, aEvent.NewValue); break; default: break; } } /** * handle the NAME_CHANGED event * @param name the new name with changed. */ void AccEventListener::handleNameChangedEvent(Any name) { if ( pAgent->IsTopWinAcc( pAccessible ) ) { XAccessible* pAccDoc = pAgent->GetAccDocByAccTopWin( pAccessible ); if ( pAccDoc ) { pAgent->UpdateAccName(pAccDoc); pAgent->NotifyAccEvent(UM_EVENT_OBJECT_NAMECHANGE, pAccDoc); } } pAgent->UpdateAccName(pAccessible, name); pAgent->NotifyAccEvent(UM_EVENT_OBJECT_NAMECHANGE, pAccessible); } /** * handle the DESCRIPTION_CHANGED event * @param desc the new description */ void AccEventListener::handleDescriptionChangedEvent(Any desc) { pAgent->UpdateDescription(pAccessible, desc); pAgent->NotifyAccEvent(UM_EVENT_OBJECT_DESCRIPTIONCHANGE, pAccessible); } /** * handle the BOUNDRECT_CHANGED event */ void AccEventListener::handleBoundrectChangedEvent() { pAgent->UpdateLocation(pAccessible); pAgent->NotifyAccEvent(UM_EVENT_BOUNDRECT_CHANGED, pAccessible); } /** * handle the VISIBLE_DATA_CHANGED event */ void AccEventListener::handleVisibleDataChangedEvent() { pAgent->UpdateValue(pAccessible); pAgent->NotifyAccEvent(UM_EVENT_VISIBLE_DATA_CHANGED, pAccessible); } /** * handle the STATE_CHANGED event * @param oldValue the old state of the source of event * @param newValue the new state of the source of event */ void AccEventListener::handleStateChangedEvent(Any oldValue, Any newValue) { short newV, oldV; if( newValue >>= newV) { setComponentState(newV, true); } else if (oldValue >>= oldV) { setComponentState(oldV, false); } } /** * set the new state and fire the MSAA event * @param state new state id * @param enable true if state is set, false if state is unset */ void AccEventListener::setComponentState(short state, bool enable ) { switch (state) { case AccessibleStateType::FOCUSED: fireStateFocusdChange(enable); break; default: fireStatePropertyChange(state, enable); break; } } /** * handle the focused event * @param enable true if get focus, false if lose focus */ void AccEventListener::fireStateFocusdChange(bool enable) { if(enable) { pAgent->IncreaseState( pAccessible, AccessibleStateType::FOCUSED); pAgent->NotifyAccEvent(UM_EVENT_STATE_FOCUSED, pAccessible); } else { // no focus lost event in MSAA } } /** * fire the MSAA state changed event * @param state the state id * @param set true if state is set, false if state is unset */ void AccEventListener::fireStatePropertyChange(short state, bool set ) { if( set ) { //get new state } else { //lose old state } } /** * get the role of accessible object which is observed */ short AccEventListener::getRole() { Reference xContext(pAccessible->getAccessibleContext(),UNO_QUERY); if(xContext.is()) { return xContext->getAccessibleRole(); } return -1; } /** * get the role of accessible parent object which is observed */ short AccEventListener::getParentRole() { if(pAccessible) { return pAgent->GetParentRole(pAccessible); } return -1; } /** * remove the listener from accessible object */ void AccEventListener::removeMeFromBroadcaster() { try { vos::OGuard aGuard(aRemoveMutex); if(m_isDisposed) return; //get accessible context Reference< XAccessibleContext > pRContext; XAccessibleContext* pContext =NULL; if( pAccessible == NULL) { return; } pRContext = pAccessible->getAccessibleContext(); if( !pRContext.is() ) { return; } //get broadcaster from accessible component Reference xComponent(pRContext,UNO_QUERY); if(!xComponent.is()) { return; } Reference broadcaster(xComponent,UNO_QUERY); XAccessibleEventBroadcaster* pBroadcaster = broadcaster.get(); if (pBroadcaster != NULL) { //remove the lister from accessible object pBroadcaster->removeEventListener(this); m_isDisposed = true; pAgent->NotifyDestroy(pAccessible); } } catch(...) { return; } } /** * this method is invoked before listener is disposed */ void AccEventListener::disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException) { removeMeFromBroadcaster(); } //need to investigate further ::com::sun::star::uno::Any SAL_CALL AccEventListener::queryInterface( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException) { if(aType.equals(::getCppuType( (Reference< com::sun::star::accessibility::XAccessibleEventListener> const *)0 ) )) { Reference< com::sun::star::accessibility::XAccessibleEventListener> xEventListener( static_cast< com::sun::star::accessibility::XAccessibleEventListener* >(this)); return makeAny(xEventListener); } return Any(); } void AccEventListener::acquire( ) throw () { ::osl_incrementInterlockedCount( &m_refcount ); } void AccEventListener::release() throw () { // thread-safe decrementation of reference count if (0 == ::osl_decrementInterlockedCount( &m_refcount )) { delete this; // shutdown this object } }