/************************************************************** * * 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 #include #include #ifndef _SV_AccObjectWinManager_HXX #include "AccObjectWinManager.hxx" #endif #include "AccEventListener.hxx" #include "AccComponentEventListener.hxx" #include "AccContainerEventListener.hxx" #include "AccDialogEventListener.hxx" #include "AccWindowEventListener.hxx" #include "AccFrameEventListener.hxx" #include "AccMenuEventListener.hxx" #include "AccObjectContainerEventListener.hxx" #include "AccParagraphEventListener.hxx" #include "AccTextComponentEventListener.hxx" #include "AccListEventListener.hxx" #include "AccTreeEventListener.hxx" #include "AccTableEventListener.hxx" #include "AccObject.hxx" #include "unomsaaevent.hxx" #include "checkmt.hxx" #define CHILDID_SELF 0 using namespace std; using namespace com::sun::star::accessibility; using namespace com::sun::star::uno; AccObjectWinManager* g_acc_manager = NULL; AccObjectWinManager* AccObjectWinManager::me = NULL; /** * Implementation of interface XMSAAService's method getAccObjectPtr() that return the * corresponding com interface with the MS event. * * @param * @return Com interface. */ long GetMSComPtr(long hWnd, long lParam, long wParam) { if( g_acc_manager ) return (long)g_acc_manager->Get_ToATInterface(HWND((void*)hWnd),lParam,wParam ); return NULL; } /** * constructor * @param Agent The agent kept in all listeners,it's the sole interface by which * listener communicate with windows manager. * pEventAccObj The present event accobject. * oldFocus Last focused object. * isSelectionChanged flag that identifies if there is selection changed. * selectionChildObj Selected object. * dChildID Chile resource ID. * hAcc TopWindowHWND * @return */ AccObjectWinManager::AccObjectWinManager( AccObjectManagerAgent* Agent ): pAgent( Agent ), oldFocus( NULL ) { } /** * Public method to produce manager * @param Agent The agent kept in all listeners,it's the sole interface by which * listener communicate with windows manager. * @return */ AccObjectWinManager* AccObjectWinManager::CreateAccObjectWinManagerInstance( AccObjectManagerAgent* Agent ) { if( me == NULL ) { me = new AccObjectWinManager( Agent ); g_acc_manager = me; return me; } return me; } /** * Destructor,clear all resource. * @param * @return */ AccObjectWinManager::~AccObjectWinManager() { XIdAccList.clear(); HwndXAcc.clear(); XResIdAccList.clear(); XHWNDDocList.clear(); #ifdef ACC_DEBUG fclose( pFile ); #endif } /** * Get valid com object interface when notifying some MSAA event * @param pWND The top window handle that contains that event control. * @param wParam Windows system interface. * @return Com interface with event. */ long AccObjectWinManager::Get_ToATInterface( HWND hWnd, long lParam, long wParam) { vos::OGuard localGuard(maATInterfaceMutex);// IMAccessible* pRetIMAcc = NULL; if(lParam == OBJID_CLIENT ) { AccObject* topWindowAccObj = GetTopWindowAccObj(hWnd); if(topWindowAccObj) { pRetIMAcc = topWindowAccObj->GetIMAccessible(); if(pRetIMAcc) pRetIMAcc->AddRef();//increase COM reference count } } if ( pRetIMAcc && lParam == OBJID_CLIENT ) { IAccessible* pTemp = dynamic_cast( pRetIMAcc ); HRESULT result = LresultFromObject(IID_IAccessible, wParam, pTemp); pTemp->Release(); return result; } return 0; } /** * Search AccObject by XAccessible pointer from our container. * @param pXAcc XAccessible interface. * @return Pointer of accObject that is found. */ AccObject* AccObjectWinManager::GetAccObjByXAcc( XAccessible* pXAcc) { if( pXAcc == NULL) return NULL; XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( (void*)pXAcc ); if ( pIndTemp == XIdAccList.end() ) return NULL; return &(pIndTemp->second); } /** * Search XAccessible by AccObject pointer from our container. * @param pAccObj AccObject pointer. * @return Pointer of XAccessible Interface. */ XAccessible* AccObjectWinManager::GetXAccByAccObj(AccObject* pAccObj) { XIdToAccObjHash::iterator iter = XIdAccList.begin(); while(iter!=XIdAccList.end()) { AccObject* tmp = &(iter->second); if(tmp== pAccObj) return (XAccessible*)(iter->first); iter++; } return NULL; } /** * get acc object of top window by its handle * @param hWnd, top window handle * @return pointer to AccObject */ AccObject* AccObjectWinManager::GetTopWindowAccObj(HWND hWnd) { XHWNDToXAccHash::iterator iterResult =HwndXAcc.find(hWnd); if(iterResult == HwndXAcc.end()) return NULL; XAccessible* pXAcc = (XAccessible*)(iterResult->second); return GetAccObjByXAcc(pXAcc); } /** * Simulate MSAA event via XAccessible interface and event type. * @param pXAcc XAccessible interface. * @param state Customize Interface * @return The terminate result that identifies if the call is successful. */ sal_Bool AccObjectWinManager::NotifyAccEvent(XAccessible* pXAcc,short state) { vos::OGuard aGuard(aNotifyMutex); if (!IsInMainThread()) { return sal_False; } Reference< XAccessibleContext > pRContext; if( pXAcc == NULL) return sal_False; pRContext = pXAcc->getAccessibleContext(); if( !pRContext.is() ) return sal_False; AccObject* selfAccObj= GetAccObjByXAcc(pXAcc); if(selfAccObj==NULL) return sal_False; int selectNum =0; long dChildID = selfAccObj->GetResID(); HWND hAcc = selfAccObj->GetParentHWND(); switch(state) { case UM_EVENT_STATE_FOCUSED: { UpdateAccFocus(pXAcc); if( selfAccObj ) selfAccObj->UpdateDefaultAction( ); UpdateValue(pXAcc); NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID ); break; } case UM_EVENT_STATE_BUSY: NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_STATE_CHECKED: NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_STATE_PRESSED: NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID ); break; //Removed fire out selected event //case UM_EVENT_STATE_SELECTED: // NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID ); // break; case UM_EVENT_STATE_ARMED: UpdateAccFocus(pXAcc); NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_MENU_START: NotifyWinEvent( EVENT_SYSTEM_MENUSTART,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_MENU_END: NotifyWinEvent( EVENT_SYSTEM_MENUEND,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_MENUPOPUPSTART: NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPSTART,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_MENUPOPUPEND: NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPEND,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_SELECTION_CHANGED: NotifyWinEvent( EVENT_OBJECT_SELECTION,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_SELECTION_CHANGED_ADD: NotifyWinEvent( EVENT_OBJECT_SELECTIONADD,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_SELECTION_CHANGED_REMOVE: NotifyWinEvent( EVENT_OBJECT_SELECTIONREMOVE,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_SELECTION_CHANGED_WITHIN: NotifyWinEvent( EVENT_OBJECT_SELECTIONWITHIN,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_VALUECHANGE: UpdateValue(pXAcc); NotifyWinEvent( EVENT_OBJECT_VALUECHANGE,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_NAMECHANGE: NotifyWinEvent( EVENT_OBJECT_NAMECHANGE,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_DESCRIPTIONCHANGE: NotifyWinEvent( EVENT_OBJECT_DESCRIPTIONCHANGE,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_DEFACTIONCHANGE: NotifyWinEvent( IA2_EVENT_ACTION_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_CARETCHANGE: NotifyWinEvent( IA2_EVENT_TEXT_CARET_MOVED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_TEXTCHANGE: NotifyWinEvent( IA2_EVENT_TEXT_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_ACTIVE_DESCENDANT_CHANGED: UpdateAccFocus(pXAcc); NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_BOUNDRECT_CHANGED: NotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_VISIBLE_DATA_CHANGED: NotifyWinEvent( IA2_EVENT_VISIBLE_DATA_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_SHOW : NotifyWinEvent( EVENT_OBJECT_SHOW,hAcc, OBJID_CLIENT,dChildID ); NotifyWinEvent( EVENT_SYSTEM_FOREGROUND,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TABLE_CAPTION_CHANGED: NotifyWinEvent( IA2_EVENT_TABLE_CAPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED: NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TABLE_COLUMN_HEADER_CHANGED: NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TABLE_MODEL_CHANGED: NotifyWinEvent( IA2_EVENT_TABLE_MODEL_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TABLE_ROW_HEADER_CHANGED: NotifyWinEvent( IA2_EVENT_TABLE_ROW_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TABLE_SUMMARY_CHANGED: NotifyWinEvent( IA2_EVENT_TABLE_SUMMARY_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TABLE_ROW_DESCRIPTION_CHANGED: NotifyWinEvent( IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_REORDER: NotifyWinEvent( EVENT_OBJECT_REORDER,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_PAGE_CHANGED: NotifyWinEvent( IA2_EVENT_PAGE_CHANGED,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_CHILD_REMOVED: NotifyWinEvent( EVENT_OBJECT_DESTROY,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_CHILD_ADDED: NotifyWinEvent( EVENT_OBJECT_CREATE ,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_OBJECT_PAGECHANGED: NotifyWinEvent( IA2_EVENT_PAGE_CHANGED ,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_TEXT_SELECTION_CHANGED: NotifyWinEvent( IA2_EVENT_TEXT_SELECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_SECTION_CHANGED: NotifyWinEvent( IA2_EVENT_SECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID ); break; case UM_EVENT_COLUMN_CHANGED: NotifyWinEvent( IA2_EVENT_TEXT_COLUMN_CHANGED ,hAcc, OBJID_CLIENT,dChildID ); break; default: break; } return sal_True; } /** * Get Parent XAccessible interface by XAccessible interface. * @param pXAcc XAccessible interface. * @return Parent XAccessible interface. */ XAccessible* AccObjectWinManager::GetParentXAccessible( XAccessible* pXAcc ) { AccObject* pObj= GetAccObjByXAcc(pXAcc); if( pObj ==NULL ) return NULL; if(pObj->GetParentObj()) { pObj = pObj->GetParentObj(); return pObj->GetXAccessible().get(); } return NULL; } /** * Get Parent role by XAccessible interface. * @param pXAcc XAccessible interface. * @return Parent role. */ short AccObjectWinManager::GetParentRole( XAccessible* pXAcc ) { AccObject* pObj= GetAccObjByXAcc(pXAcc); if( pObj ==NULL ) return -1; if(pObj->GetParentObj()) { pObj = pObj->GetParentObj(); if(pObj->GetXAccessible().is()) { XAccessible* pXAcc = pObj->GetXAccessible().get(); Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext(); if(pRContext.is()) return pRContext->getAccessibleRole(); } } return -1; } /** * Update focus objcet by new focused XAccessible interface. * @param newFocus New XAccessible interface that gets focus. * @return */ void AccObjectWinManager::UpdateAccFocus(XAccessible* newFocus) { AccObject* pAccObjNew = GetAccObjByXAcc(newFocus); if(pAccObjNew) { AccObject* pAccObjOld = GetAccObjByXAcc(oldFocus); oldFocus = newFocus; pAccObjNew->setFocus(); //if old == new, the pAccObjNew will be without focused state if (pAccObjOld && pAccObjOld != pAccObjNew) pAccObjOld->unsetFocus(); } } /** * Update selected objcet by new focused XAccessible interface. * @param pXAcc XAccessible interface that has selected child changed. * @return Selected children count. */ int AccObjectWinManager::UpdateAccSelection(XAccessible* pXAcc) { XAccessibleSelection* pSelection = NULL; Reference< XAccessibleContext > pRContext; if( pXAcc == NULL) return sal_False; pRContext = pXAcc->getAccessibleContext(); if( !pRContext.is() ) return sal_False; Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY); if( !pRSelection.is() ) return sal_False; AccObject* pAccObj = GetAccObjByXAcc(pXAcc); if(pAccObj==NULL) return sal_False; Reference pRChild = NULL; AccObject* pAccChildObj = NULL; int selectNum= pRSelection->getSelectedAccessibleChildCount(); IAccSelectionList oldSelection = pAccObj->GetSelection(); if(selectNum > 4)//for selected. return selectNum; if(selectNum == 1 && oldSelection.size() == 0) return 1; for (int i=0;igetSelectedAccessibleChild(i); if(!pRChild.is()) { continue; } Reference pRChildContext = pRChild->getAccessibleContext(); if(!pRChildContext.is()) { continue; } long index = pRChildContext->getAccessibleIndexInParent(); IAccSelectionList::iterator temp = oldSelection.find(index); if ( temp != oldSelection.end() ) { oldSelection.erase(index); continue; } pAccChildObj = NULL; pAccChildObj = GetAccObjByXAcc(pRChild.get()); if(!pAccChildObj) { InsertAccObj(pRChild.get(), pXAcc,pAccObj->GetParentHWND()); pAccChildObj = GetAccObjByXAcc(pRChild.get()); } pAccObj->AddSelect(index, pAccChildObj); if(pAccChildObj != NULL) NotifyWinEvent(EVENT_OBJECT_SELECTIONADD,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID()); } IAccSelectionList::iterator iter = oldSelection.begin(); while(iter!=oldSelection.end()) { pAccObj->GetSelection().erase(iter->first); pAccChildObj = (AccObject*)(iter->second); if(pAccChildObj != NULL) NotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID()); iter++; } return 0; } /** * Delete child element from children list. * @param pObj Child element that should be removed from parant child list. * @return */ void AccObjectWinManager::DeleteAccChildNode( AccObject* pObj ) { AccObject *parentAccObj = pObj->GetParentObj(); if( parentAccObj ) parentAccObj->DeleteChild( pObj ); } /** * Delete XAccessible items in top window handle hashtable * @param pXAcc XAccessible interface. * @return */ void AccObjectWinManager::DeleteFromHwndXAcc(XAccessible* pXAcc ) { XHWNDToXAccHash::iterator iter = HwndXAcc.begin(); while(iter!=HwndXAcc.end()) { if(iter->second == pXAcc ) { HwndXAcc.erase(iter); return; } iter++; } } /** * Delete Delete all children with the tree root of XAccessible pointer * @param pXAcc Tree root XAccessible interface. * @return */ void AccObjectWinManager::DeleteChildrenAccObj(XAccessible* pXAcc) { vos::OGuard aGuard( aDeleteMutex ); AccObject* currentObj=NULL; AccObject* childObj=NULL; XAccessible* pTmpXAcc=NULL; currentObj = GetAccObjByXAcc( pXAcc); if(currentObj) { childObj = currentObj->NextChild(); while(childObj) { pTmpXAcc = GetXAccByAccObj(childObj); if(pTmpXAcc) { DeleteChildrenAccObj(pTmpXAcc); DeleteAccObj(pTmpXAcc); } childObj = currentObj->NextChild(); } } } /** * Delete Delete Acc object self. * @param pXAcc The XAccessible interface. * @return */ void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc ) { vos::OGuard aGuard( aDeleteMutex ); if( pXAcc == NULL ) return; XIdToAccObjHash::iterator temp = XIdAccList.find(pXAcc); if( temp != XIdAccList.end() ) { ResIdGen.SetSub( temp->second.GetResID() ); } else { return; } AccObject& accObj = temp->second; DeleteAccChildNode( &accObj ); DeleteAccListener( &accObj ); if( accObj.GetIMAccessible() ) { accObj.GetIMAccessible()->Release(); } XIdAccList.erase( pXAcc ); XResIdAccList.erase( accObj.GetResID() ); DeleteFromHwndXAcc(pXAcc); } /** * Delete listener that inspects some XAccessible object * @param pAccObj Accobject pointer. * @return */ void AccObjectWinManager::DeleteAccListener( AccObject* pAccObj ) { AccEventListener* listener = pAccObj->getListener(); if( listener==NULL ) return; listener->removeMeFromBroadcaster(); pAccObj->SetListener(NULL); } /** * Generate a child ID, which is used for AT * @param * @return New resource ID. */ inline long AccObjectWinManager::ImpleGenerateResID() { return ResIdGen.GenerateNewResID(); } /** * Insert all children of the current acc object * @param pXAcc XAccessible interface * @param pWnd Top Window handle * @return The calling result. */ sal_Bool AccObjectWinManager::InsertChildrenAccObj( com::sun::star::accessibility::XAccessible* pXAcc, HWND pWnd) { if(!IsContainer(pXAcc)) return sal_False; Reference< XAccessibleContext > pRContext; if( pXAcc == NULL) return sal_False; pRContext = pXAcc->getAccessibleContext(); if( !pRContext.is() ) return sal_False; short role = pRContext->getAccessibleRole(); if(com::sun::star::accessibility::AccessibleRole::DOCUMENT == role ) { if(IsStateManageDescendant(pXAcc)) { return sal_True; } } int count = pRContext->getAccessibleChildCount(); for (int i=0;i mxAccessible = pRContext->getAccessibleChild(i); XAccessible* mpAccessible = mxAccessible.get(); if(mpAccessible != NULL) { InsertAccObj( mpAccessible,pXAcc,pWnd ); InsertChildrenAccObj(mpAccessible,pWnd); } } return sal_True; } /** * Insert child object. * @param pCurObj The child object * @param pParentObj The parant object * @param pWnd Top window handle. * @return */ void AccObjectWinManager::InsertAccChildNode( AccObject* pCurObj, AccObject* pParentObj, HWND /* pWnd */ ) { if(pCurObj) { if(pParentObj) { pParentObj->InsertChild(pCurObj); } else { pCurObj->UpdateValidWindow(); } } } /** * Insert child object. * @param pCurObj The child object * @param pParentObj The parant object * @param pWnd Top window handle. * @return */ sal_Bool AccObjectWinManager::InsertAccObj( XAccessible* pXAcc,XAccessible* pParentXAcc,HWND pWnd ) { XIdToAccObjHash::iterator itXacc = XIdAccList.find( (void*)pXAcc ); if (itXacc != XIdAccList.end() ) { short nCurRole =GetRole(pXAcc); if (AccessibleRole::SHAPE == nCurRole) { AccObject &objXacc = itXacc->second; AccObject *pObjParent = objXacc.GetParentObj(); if (pObjParent && pObjParent->GetXAccessible().is() && pObjParent->GetXAccessible().get() != pParentXAcc) { XIdToAccObjHash::iterator itXaccParent = XIdAccList.find( (void*)pParentXAcc ); if(itXaccParent != XIdAccList.end()) { objXacc.SetParentObj(&(itXaccParent->second)); } } } return sal_False; } Reference< XAccessibleContext > pRContext; if( pXAcc == NULL) return sal_False; pRContext = pXAcc->getAccessibleContext(); if( !pRContext.is() ) return sal_False; if( pWnd == NULL ) { if(pParentXAcc) { AccObject* pObj = GetAccObjByXAcc(pParentXAcc); if(pObj) pWnd = pObj->GetParentHWND(); } if( pWnd == NULL ) return sal_False; } AccObject pObj( pXAcc,pAgent ); if( pObj.GetIMAccessible() == NULL ) return sal_False; pObj.SetResID( this->ImpleGenerateResID()); pObj.SetParentHWND( pWnd ); //for file name support if ( pObj.GetRole() == DOCUMENT ) { XHWNDToDocumentHash::iterator aIter = XHWNDDocList.find( (long)pWnd ); if ( aIter != XHWNDDocList.end() ) { XHWNDDocList.erase( aIter ); } XHWNDDocList.insert( XHWNDToDocumentHash::value_type( (long)pWnd, pXAcc ) ); } //end of file name AccEventListener* listener = createAccEventListener(pXAcc, pAgent); if(listener==NULL) return sal_False; Reference xComponent(pRContext,UNO_QUERY); Reference broadcaster(xComponent,UNO_QUERY); if (broadcaster.is()) { Reference pp ( static_cast< XAccessibleEventListener* >(listener),UNO_QUERY ); if(pp.is()) { broadcaster->addEventListener(pp); } else { delete listener; return sal_False; } } else return sal_False; XIdAccList.insert( XIdToAccObjHash::value_type( (void*)pXAcc, pObj )); XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( (void*)pXAcc ); XResIdAccList.insert(XResIdToAccObjHash::value_type(pObj.GetResID(),&(pIndTemp->second))); AccObject* pCurObj = GetAccObjByXAcc(pXAcc); if( pCurObj ) { pCurObj->SetListener( listener ); if(listener != NULL) listener->acquire(); } AccObject* pParentObj = GetAccObjByXAcc(pParentXAcc); InsertAccChildNode(pCurObj,pParentObj,pWnd); if( pCurObj ) pCurObj->UpdateAccessibleInfoFromUnoToMSAA(); return sal_True; } /** * save the pair * @param hWnd, top window handle * @param pXAcc XAccessible interface for top window * @return void */ void AccObjectWinManager::SaveTopWindowHandle(HWND hWnd, com::sun::star::accessibility::XAccessible* pXAcc) { HwndXAcc.insert( XHWNDToXAccHash::value_type( hWnd,(void*)pXAcc ) ); } /** * create the corresponding listener. * @param pXAcc XAccessible interface. * @param Agent The agent kept in all listeners,it's the sole interface by which * listener communicate with windows manager. * @return */ AccEventListener* AccObjectWinManager::createAccEventListener(XAccessible* pXAcc, AccObjectManagerAgent* /* Agent */ ) { AccEventListener* listener = NULL; Reference xContext(pXAcc->getAccessibleContext(),UNO_QUERY); if(xContext.is()) { switch( xContext->getAccessibleRole() ) { case /*AccessibleRole::*/DIALOG: listener = new AccDialogEventListener(pXAcc,pAgent); break; case /*AccessibleRole::*/FRAME: listener = new AccFrameEventListener(pXAcc,pAgent); break; case /*AccessibleRole::*/WINDOW: listener = new AccWindowEventListener(pXAcc,pAgent); break; case /*AccessibleRole::*/ROOT_PANE: listener = new AccFrameEventListener(pXAcc,pAgent); break; //Container case /*AccessibleRole::*/CANVAS: case /*AccessibleRole::*/COMBO_BOX: case /*AccessibleRole::*/DOCUMENT: case /*AccessibleRole::*/END_NOTE: case /*AccessibleRole::*/FILLER: case /*AccessibleRole::*/FOOTNOTE: case /*AccessibleRole::*/FOOTER: case /*AccessibleRole::*/HEADER: case /*AccessibleRole::*/LAYERED_PANE: case /*AccessibleRole::*/MENU_BAR: case /*AccessibleRole::*/POPUP_MENU: case /*AccessibleRole::*/OPTION_PANE: case /*AccessibleRole::*/PAGE_TAB: case /*AccessibleRole::*/PAGE_TAB_LIST: case /*AccessibleRole::*/PANEL: case /*AccessibleRole::*/SCROLL_PANE: case /*AccessibleRole::*/SPLIT_PANE: case /*AccessibleRole::*/STATUS_BAR: case /*AccessibleRole::*/TABLE_CELL: case /*AccessibleRole::*/TOOL_BAR: case /*AccessibleRole::*/VIEW_PORT: listener = new AccContainerEventListener(pXAcc,pAgent); break; case /*AccessibleRole::*/PARAGRAPH: case /*AccessibleRole::*/HEADING: listener = new AccParagraphEventListener(pXAcc,pAgent); break; //Component case /*AccessibleRole::*/CHECK_BOX: case /*AccessibleRole::*/ICON: case /*AccessibleRole::*/LABEL: case /*AccessibleRole::*/MENU_ITEM: case /*AccessibleRole::*/CHECK_MENU_ITEM: case /*AccessibleRole::*/RADIO_MENU_ITEM: case /*AccessibleRole::*/PUSH_BUTTON: case /*AccessibleRole::*/RADIO_BUTTON: case /*AccessibleRole::*/SCROLL_BAR: case /*AccessibleRole::*/SEPARATOR: case /*AccessibleRole::*/TOGGLE_BUTTON: case /*AccessibleRole::*/BUTTON_DROPDOWN: case /*AccessibleRole::*/TOOL_TIP: case /*AccessibleRole::*/SPIN_BOX: case DATE_EDITOR: listener = new AccComponentEventListener(pXAcc,pAgent); break; //text component case /*AccessibleRole::*/TEXT: listener = new AccTextComponentEventListener(pXAcc,pAgent); break; //menu case /*AccessibleRole::*/MENU: listener = new AccMenuEventListener(pXAcc,pAgent); break; //object container case /*AccessibleRole::*/SHAPE: case /*AccessibleRole::*/EMBEDDED_OBJECT: case /*AccessibleRole::*/GRAPHIC: case /*AccessibleRole::*/TEXT_FRAME: listener = new AccObjectContainerEventListener(pXAcc,pAgent); break; //descendmanager case /*AccessibleRole::*/LIST: listener = new AccListEventListener(pXAcc,pAgent); break; case /*AccessibleRole::*/TREE: listener = new AccTreeEventListener(pXAcc,pAgent); break; //special case /*AccessibleRole::*/COLUMN_HEADER: case /*AccessibleRole::*/TABLE: listener = new AccTableEventListener(pXAcc,pAgent); break; default: listener = new AccContainerEventListener(pXAcc,pAgent); break; } } return listener; } /** * state is a combination integer, each bit of which represents a single state, * such as focused,1 for the state on,0 for the state off. Here call COM interface * to modify the state value, including DecreaseState. * @param pXAcc XAccessible interface. * @param pState Changed state. * @return */ void AccObjectWinManager::DecreaseState( XAccessible* pXAcc,unsigned short pState ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->DecreaseState( pState ); } /** * state is a combination integer, each bit of which represents a single state,such as focused,1 for * the state on,0 for the state off. Here call COM interface to modify the state value, including * IncreaseState. * @param pXAcc XAccessible interface. * @param pState Changed state. * @return */ void AccObjectWinManager::IncreaseState( XAccessible* pXAcc,unsigned short pState ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->IncreaseState( pState ); } void AccObjectWinManager::UpdateState( com::sun::star::accessibility::XAccessible* pXAcc ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->UpdateState( ); } /** * Set corresponding com object's accessible name via XAccessilbe interface and new * name * @param pXAcc XAccessible interface. * @return */ void AccObjectWinManager::UpdateAccName( XAccessible* pXAcc ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->UpdateName(); } void AccObjectWinManager::UpdateAction( XAccessible* pXAcc ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->UpdateAction(); } void AccObjectWinManager::UpdateDescription( XAccessible* pXAcc ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if ( pAccObj ) pAccObj->UpdateDescription(); } /** * Set corresponding com object's accessible location via XAccessilbe interface and new * location. * @param pXAcc XAccessible interface. * @return */ void AccObjectWinManager::SetLocation( XAccessible* pXAcc, long /*top*/, long /*left*/, long /*width*/, long /*height*/ ) { AccObject* pObj = GetAccObjByXAcc( pXAcc ); //get the location from XComponent. Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext(); if( pObj ) pObj->UpdateLocation(); } /** * Set corresponding com object's value via XAccessilbe interface and new value. * @param pXAcc XAccessible interface. * @param pAny new value. * @return */ void AccObjectWinManager::SetValue( XAccessible* pXAcc, Any pAny ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->SetValue( pAny ); } /** * Set corresponding com object's value via XAccessilbe interface. * @param pXAcc XAccessible interface. * @return */ void AccObjectWinManager::UpdateValue( XAccessible* pXAcc ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->UpdateValue(); } /** * Set corresponding com object's name via XAccessilbe interface and new name. * @param pXAcc XAccessible interface. * @param newName new name * @return */ void AccObjectWinManager::SetAccName( XAccessible* pXAcc, Any newName) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->SetName( newName ); } /** * Set corresponding com object's description via XAccessilbe interface and new description. * @param pXAcc XAccessible interface. * @param newDesc new description * @return */ void AccObjectWinManager::SetDescription( XAccessible* pXAcc, Any newDesc ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->SetDescription( newDesc ); } /** * Set corresponding com object's role via XAccessilbe interface and new role. * @param pXAcc XAccessible interface. * @param Role new role * @return */ void AccObjectWinManager::SetRole( XAccessible* pXAcc, long Role ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if( pAccObj ) pAccObj->SetRole( (short)Role ); } /** * Judge if a XAccessible object is a container object. * @param pAccessible XAccessible interface. * @return If XAccessible object is container. */ sal_Bool AccObjectWinManager::IsContainer(XAccessible* pAccessible) { try { if(pAccessible) { Reference xContext(pAccessible->getAccessibleContext(),UNO_QUERY); if(xContext.is()) { switch( xContext->getAccessibleRole() ) { case /*AccessibleRole::*/DIALOG: case /*AccessibleRole::*/FRAME: case /*AccessibleRole::*/WINDOW: case /*AccessibleRole::*/ROOT_PANE: case /*AccessibleRole::*/CANVAS: case /*AccessibleRole::*/COMBO_BOX: case /*AccessibleRole::*/DOCUMENT: case /*AccessibleRole::*/EMBEDDED_OBJECT: case /*AccessibleRole::*/END_NOTE: case /*AccessibleRole::*/FILLER: case /*AccessibleRole::*/FOOTNOTE: case /*AccessibleRole::*/FOOTER: case /*AccessibleRole::*/GRAPHIC: case /*AccessibleRole::*/GROUP_BOX: case /*AccessibleRole::*/HEADER: case /*AccessibleRole::*/LAYERED_PANE: case /*AccessibleRole::*/MENU_BAR: case /*AccessibleRole::*/POPUP_MENU: case /*AccessibleRole::*/OPTION_PANE: case /*AccessibleRole::*/PAGE_TAB: case /*AccessibleRole::*/PAGE_TAB_LIST: case /*AccessibleRole::*/PANEL: case /*AccessibleRole::*/SCROLL_PANE: case /*AccessibleRole::*/SPLIT_PANE: case /*AccessibleRole::*/STATUS_BAR: case /*AccessibleRole::*/TABLE_CELL: case /*AccessibleRole::*/TEXT_FRAME: case /*AccessibleRole::*/TOOL_BAR: case /*AccessibleRole::*/VIEW_PORT: case /*AccessibleRole::*/SHAPE: return sal_True; break; case /*AccessibleRole::*/COLUMN_HEADER: case /*AccessibleRole::*/TABLE: if(!IsStateManageDescendant(pAccessible)) return sal_True; break; case /*AccessibleRole::*/MENU: return sal_True; break; default: return sal_False; } } } } catch(...) { return sal_False; } return sal_False; } /** * Judge if a XAccessible object has ManageDescendant event. * @param pAccessible XAccessible interface. * @return If XAccessible object is managedescendant. */ bool AccObjectWinManager::IsStateManageDescendant(XAccessible* pAccessible) { if(pAccessible) { Reference xContext(pAccessible->getAccessibleContext(),UNO_QUERY); if(xContext.is()) { Reference< XAccessibleStateSet > pRState = xContext->getAccessibleStateSet(); if( !pRState.is() ) return sal_False; Sequence pStates = pRState->getStates(); int count = pStates.getLength(); for( int iIndex = 0;iIndex < count;iIndex++ ) { if(pStates[iIndex] == /*AccessibleStateType::*/MANAGES_DESCENDANTS) return sal_True; } } } return sal_False; } /** * Query and get IAccessible interface by XAccessible interface from list. * @param pXAcc XAccessible interface. * @return Com accobject interface. */ IMAccessible* AccObjectWinManager::GetIMAccByXAcc(XAccessible* pXAcc) { AccObject* pAccObj = GetAccObjByXAcc(pXAcc); if(pAccObj) { return pAccObj->GetIMAccessible(); } else { return NULL; } } /** * Query and get IAccessible interface by child id from list. * @param resID, childID. * @return Com accobject interface. */ IMAccessible * AccObjectWinManager::GetIAccessibleFromResID(long resID) { XResIdToAccObjHash::iterator pIndTemp = XResIdAccList.find( resID ); if ( pIndTemp == XResIdAccList.end() ) return NULL; AccObject* pObj = pIndTemp->second; if(pObj->GetIMAccessible()) return pObj->GetIMAccessible(); return NULL; } /** * Notify some object will be destroyed. * @param pXAcc XAccessible interface. * @return Com accobject interface. */ void AccObjectWinManager::NotifyDestroy(XAccessible* pXAcc) { AccObject* accObj = GetAccObjByXAcc(pXAcc); if(accObj) { accObj->NotifyDestroy(sal_True); } } void AccObjectWinManager::UpdateChildState(com::sun::star::accessibility::XAccessible* pAccSubMenu) { Reference xContext(pAccSubMenu,UNO_QUERY); if (!xContext.is()) { return; } sal_Int32 nCount = xContext->getAccessibleChildCount(); for (sal_Int32 i = 0 ; i < nCount ; ++i) { Reference xChild = xContext->getAccessibleChild(i); if (xChild.is()) { AccObject *pObj = GetAccObjByXAcc(xChild.get()); if (pObj) { pObj->UpdateState(); } } } } bool AccObjectWinManager::IsSpecialToolboItem(com::sun::star::accessibility::XAccessible* pXAcc) { if (pXAcc && oldFocus != pXAcc) { if(GetParentRole(pXAcc) == TOOL_BAR) { Reference< XAccessibleContext > pRContext(pXAcc->getAccessibleContext()); if (pRContext.is()) { if(pRContext->getAccessibleRole() == TOGGLE_BUTTON) { return true; } } } } return false; } short AccObjectWinManager::GetRole(com::sun::star::accessibility::XAccessible* pXAcc) { assert(pXAcc != NULL); Reference xContext(pXAcc->getAccessibleContext(),UNO_QUERY); if(xContext.is()) { return xContext->getAccessibleRole(); } return -1; } XAccessible* AccObjectWinManager::GetAccDocByHWND( long pWnd ) { XHWNDToDocumentHash::iterator aIter; aIter = XHWNDDocList.find( pWnd ); if ( aIter != XHWNDDocList.end() ) { return aIter->second; } return NULL; } XAccessible* AccObjectWinManager::GetAccDocByAccTopWin( XAccessible* pXAcc ) { AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); long pWnd = (long)( pAccObj->GetParentHWND() ); return GetAccDocByHWND( pWnd ); } bool AccObjectWinManager::IsTopWinAcc( com::sun::star::accessibility::XAccessible* pXAcc ) { bool bRet = false; AccObject* pAccObj = GetAccObjByXAcc( pXAcc ); if ( pAccObj ) { bRet = ( pAccObj->GetParentObj() == NULL ); } return bRet; }