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 #include <cassert>
23 
24 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
25 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
26 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 
29 #include <oleacc.h>
30 #ifndef _SV_AccObjectWinManager_HXX
31 #include "AccObjectWinManager.hxx"
32 #endif
33 #include "AccEventListener.hxx"
34 #include "AccComponentEventListener.hxx"
35 #include "AccContainerEventListener.hxx"
36 #include "AccDialogEventListener.hxx"
37 #include "AccWindowEventListener.hxx"
38 #include "AccFrameEventListener.hxx"
39 #include "AccMenuEventListener.hxx"
40 #include "AccObjectContainerEventListener.hxx"
41 #include "AccParagraphEventListener.hxx"
42 #include "AccTextComponentEventListener.hxx"
43 #include "AccListEventListener.hxx"
44 #include "AccTreeEventListener.hxx"
45 #include "AccTableEventListener.hxx"
46 #include "AccObject.hxx"
47 #include "unomsaaevent.hxx"
48 #include "checkmt.hxx"
49 
50 #define CHILDID_SELF             0
51 
52 
53 using namespace std;
54 using namespace com::sun::star::accessibility;
55 using namespace com::sun::star::uno;
56 
57 AccObjectWinManager* g_acc_manager = NULL;
58 AccObjectWinManager* AccObjectWinManager::me = NULL;
59 
60 /**
61    * Implementation of interface XMSAAService's method getAccObjectPtr() that return the
62    * corresponding com interface with the MS event.
63    *
64    * @param
65    * @return  Com interface.
66    */
GetMSComPtr(long hWnd,long lParam,long wParam)67 long GetMSComPtr(long hWnd, long lParam, long wParam)
68 {
69     if( g_acc_manager )
70         return (long)g_acc_manager->Get_ToATInterface(HWND((void*)hWnd),lParam,wParam );
71     return NULL;
72 }
73 
74 /**
75    * constructor
76    * @param   Agent The agent kept in all listeners,it's the sole interface by which
77    *                listener communicate with windows manager.
78    *          pEventAccObj The present event accobject.
79    *          oldFocus     Last focused object.
80    *          isSelectionChanged flag that identifies if there is selection changed.
81    *		  selectionChildObj  Selected object.
82    *          dChildID	Chile resource ID.
83    *          hAcc TopWindowHWND
84    * @return
85    */
AccObjectWinManager(AccObjectManagerAgent * Agent)86 AccObjectWinManager::AccObjectWinManager( AccObjectManagerAgent* Agent ):
87         pAgent( Agent ),
88         oldFocus( NULL )
89 {
90 }
91 
92 /**
93    * Public method to produce manager
94    * @param   Agent The agent kept in all listeners,it's the sole interface by which
95    *          listener communicate with windows manager.
96    * @return
97    */
CreateAccObjectWinManagerInstance(AccObjectManagerAgent * Agent)98 AccObjectWinManager* AccObjectWinManager::CreateAccObjectWinManagerInstance( AccObjectManagerAgent* Agent )
99 {
100     if( me == NULL )
101     {
102         me = new AccObjectWinManager( Agent );
103         g_acc_manager = me;
104         return me;
105     }
106 
107     return me;
108 }
109 
110 
111 /**
112    * Destructor,clear all resource.
113    * @param
114    * @return
115    */
~AccObjectWinManager()116 AccObjectWinManager::~AccObjectWinManager()
117 {
118     XIdAccList.clear();
119     HwndXAcc.clear();
120     XResIdAccList.clear();
121     XHWNDDocList.clear();
122 #ifdef ACC_DEBUG
123 
124     fclose( pFile );
125 #endif
126 }
127 
128 
129 /**
130    * Get valid com object interface when notifying some MSAA event
131    * @param pWND The top window handle that contains that event control.
132    * @param wParam Windows system interface.
133    * @return Com interface with event.
134    */
135 
Get_ToATInterface(HWND hWnd,long lParam,long wParam)136 long AccObjectWinManager::Get_ToATInterface( HWND hWnd, long lParam, long wParam)
137 {
138     vos::OGuard localGuard(maATInterfaceMutex);//
139 
140     IMAccessible* pRetIMAcc = NULL;
141 
142     if(lParam == OBJID_CLIENT )
143     {
144         AccObject* topWindowAccObj = GetTopWindowAccObj(hWnd);
145         if(topWindowAccObj)
146         {
147             pRetIMAcc = topWindowAccObj->GetIMAccessible();
148             if(pRetIMAcc)
149                 pRetIMAcc->AddRef();//increase COM reference count
150         }
151     }
152 
153     if ( pRetIMAcc && lParam == OBJID_CLIENT )
154     {
155         IAccessible* pTemp = dynamic_cast<IAccessible*>( pRetIMAcc );
156         HRESULT result = LresultFromObject(IID_IAccessible, wParam, pTemp);
157         pTemp->Release();
158         return result;
159     }
160     return 0;
161 }
162 
163 /**
164    * Search AccObject by XAccessible pointer from our container.
165    * @param pXAcc XAccessible interface.
166    * @return Pointer of accObject that is found.
167    */
GetAccObjByXAcc(XAccessible * pXAcc)168 AccObject* AccObjectWinManager::GetAccObjByXAcc( XAccessible* pXAcc)
169 {
170     if( pXAcc == NULL)
171         return NULL;
172 
173     XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( (void*)pXAcc );
174     if ( pIndTemp == XIdAccList.end() )
175         return NULL;
176 
177     return &(pIndTemp->second);
178 }
179 
180 /**
181    * Search XAccessible by AccObject pointer from our container.
182    * @param pAccObj AccObject pointer.
183    * @return Pointer of XAccessible Interface.
184    */
GetXAccByAccObj(AccObject * pAccObj)185 XAccessible* AccObjectWinManager::GetXAccByAccObj(AccObject* pAccObj)
186 {
187     XIdToAccObjHash::iterator iter = XIdAccList.begin();
188     while(iter!=XIdAccList.end())
189     {
190         AccObject* tmp = &(iter->second);
191         if(tmp== pAccObj)
192             return (XAccessible*)(iter->first);
193         iter++;
194     }
195     return NULL;
196 }
197 
198 /**
199    * get acc object of top window by its handle
200    * @param hWnd, top window handle
201    * @return pointer to AccObject
202    */
GetTopWindowAccObj(HWND hWnd)203 AccObject* AccObjectWinManager::GetTopWindowAccObj(HWND hWnd)
204 {
205     XHWNDToXAccHash::iterator iterResult =HwndXAcc.find(hWnd);
206     if(iterResult == HwndXAcc.end())
207         return NULL;
208     XAccessible* pXAcc = (XAccessible*)(iterResult->second);
209     return GetAccObjByXAcc(pXAcc);
210 }
211 
212 /**
213    * Simulate MSAA event via XAccessible interface and event type.
214    * @param pXAcc XAccessible interface.
215    * @param state Customize Interface
216    * @return The terminate result that identifies if the call is successful.
217    */
NotifyAccEvent(XAccessible * pXAcc,short state)218 sal_Bool AccObjectWinManager::NotifyAccEvent(XAccessible* pXAcc,short state)
219 {
220     vos::OGuard aGuard(aNotifyMutex);
221 
222     if (!IsInMainThread())
223     {
224         return sal_False;
225     }
226 
227     Reference< XAccessibleContext > pRContext;
228 
229     if( pXAcc == NULL)
230         return sal_False;
231 
232 
233     pRContext = pXAcc->getAccessibleContext();
234     if( !pRContext.is() )
235         return sal_False;
236 
237 
238     AccObject* selfAccObj= GetAccObjByXAcc(pXAcc);
239 
240     if(selfAccObj==NULL)
241         return sal_False;
242 
243     int selectNum =0;
244 
245     long dChildID = selfAccObj->GetResID();
246     HWND hAcc = selfAccObj->GetParentHWND();
247 
248     switch(state)
249     {
250     case UM_EVENT_STATE_FOCUSED:
251         {
252             UpdateAccFocus(pXAcc);
253             if( selfAccObj )
254                 selfAccObj->UpdateDefaultAction( );
255             UpdateValue(pXAcc);
256             NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID  );
257             break;
258         }
259     case UM_EVENT_STATE_BUSY:
260         NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
261         break;
262     case UM_EVENT_STATE_CHECKED:
263         NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
264         break;
265     case UM_EVENT_STATE_PRESSED:
266         NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
267         break;
268 
269     //Removed fire out selected event
270     //case UM_EVENT_STATE_SELECTED:
271     //	NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID  );
272     //	break;
273     case UM_EVENT_STATE_ARMED:
274         UpdateAccFocus(pXAcc);
275         NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID  );
276         break;
277     case UM_EVENT_MENU_START:
278         NotifyWinEvent( EVENT_SYSTEM_MENUSTART,hAcc, OBJID_CLIENT,dChildID  );
279         break;
280     case UM_EVENT_MENU_END:
281         NotifyWinEvent( EVENT_SYSTEM_MENUEND,hAcc, OBJID_CLIENT,dChildID  );
282         break;
283     case UM_EVENT_MENUPOPUPSTART:
284         NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPSTART,hAcc, OBJID_CLIENT,dChildID  );
285         break;
286     case UM_EVENT_MENUPOPUPEND:
287         NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPEND,hAcc, OBJID_CLIENT,dChildID  );
288         break;
289     case UM_EVENT_SELECTION_CHANGED:
290         NotifyWinEvent( EVENT_OBJECT_SELECTION,hAcc, OBJID_CLIENT,dChildID  );
291         break;
292     case UM_EVENT_SELECTION_CHANGED_ADD:
293        	NotifyWinEvent( EVENT_OBJECT_SELECTIONADD,hAcc, OBJID_CLIENT,dChildID  );
294        	break;
295     case UM_EVENT_SELECTION_CHANGED_REMOVE:
296        	NotifyWinEvent( EVENT_OBJECT_SELECTIONREMOVE,hAcc, OBJID_CLIENT,dChildID  );
297        	break;
298     case UM_EVENT_SELECTION_CHANGED_WITHIN:
299        	NotifyWinEvent( EVENT_OBJECT_SELECTIONWITHIN,hAcc, OBJID_CLIENT,dChildID  );
300        	break;
301     case UM_EVENT_OBJECT_VALUECHANGE:
302         UpdateValue(pXAcc);
303         NotifyWinEvent( EVENT_OBJECT_VALUECHANGE,hAcc, OBJID_CLIENT,dChildID  );
304         break;
305     case UM_EVENT_OBJECT_NAMECHANGE:
306         NotifyWinEvent( EVENT_OBJECT_NAMECHANGE,hAcc, OBJID_CLIENT,dChildID  );
307         break;
308     case UM_EVENT_OBJECT_DESCRIPTIONCHANGE:
309         NotifyWinEvent( EVENT_OBJECT_DESCRIPTIONCHANGE,hAcc, OBJID_CLIENT,dChildID  );
310         break;
311     case UM_EVENT_OBJECT_DEFACTIONCHANGE:
312         NotifyWinEvent( IA2_EVENT_ACTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
313         break;
314     case UM_EVENT_OBJECT_CARETCHANGE:
315         NotifyWinEvent( IA2_EVENT_TEXT_CARET_MOVED,hAcc, OBJID_CLIENT,dChildID  );
316         break;
317     case UM_EVENT_OBJECT_TEXTCHANGE:
318         NotifyWinEvent( IA2_EVENT_TEXT_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
319         break;
320     case UM_EVENT_ACTIVE_DESCENDANT_CHANGED:
321         UpdateAccFocus(pXAcc);
322         NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID  );
323         break;
324     case UM_EVENT_BOUNDRECT_CHANGED:
325         NotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE,hAcc, OBJID_CLIENT,dChildID  );
326         break;
327     case UM_EVENT_VISIBLE_DATA_CHANGED:
328         NotifyWinEvent( IA2_EVENT_VISIBLE_DATA_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
329         break;
330     case UM_EVENT_SHOW :
331         NotifyWinEvent( EVENT_OBJECT_SHOW,hAcc, OBJID_CLIENT,dChildID  );
332         NotifyWinEvent( EVENT_SYSTEM_FOREGROUND,hAcc, OBJID_CLIENT,dChildID  );
333 	break;
334     case UM_EVENT_TABLE_CAPTION_CHANGED:
335         NotifyWinEvent( IA2_EVENT_TABLE_CAPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
336         break;
337     case UM_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED:
338         NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
339         break;
340     case UM_EVENT_TABLE_COLUMN_HEADER_CHANGED:
341         NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
342         break;
343     case UM_EVENT_TABLE_MODEL_CHANGED:
344         NotifyWinEvent( IA2_EVENT_TABLE_MODEL_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
345         break;
346     case UM_EVENT_TABLE_ROW_HEADER_CHANGED:
347         NotifyWinEvent( IA2_EVENT_TABLE_ROW_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
348         break;
349     case UM_EVENT_TABLE_SUMMARY_CHANGED:
350         NotifyWinEvent( IA2_EVENT_TABLE_SUMMARY_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
351         break;
352     case UM_EVENT_TABLE_ROW_DESCRIPTION_CHANGED:
353         NotifyWinEvent( IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
354         break;
355     case UM_EVENT_OBJECT_REORDER:
356         NotifyWinEvent( EVENT_OBJECT_REORDER,hAcc, OBJID_CLIENT,dChildID  );
357         break;
358     case UM_EVENT_PAGE_CHANGED:
359         NotifyWinEvent( IA2_EVENT_PAGE_CHANGED,hAcc, OBJID_CLIENT,dChildID  );
360         break;
361     case UM_EVENT_CHILD_REMOVED:
362         NotifyWinEvent( EVENT_OBJECT_DESTROY,hAcc, OBJID_CLIENT,dChildID  );
363         break;
364     case UM_EVENT_CHILD_ADDED:
365         NotifyWinEvent( EVENT_OBJECT_CREATE ,hAcc, OBJID_CLIENT,dChildID  );
366         break;
367     case UM_EVENT_OBJECT_PAGECHANGED:
368         NotifyWinEvent( IA2_EVENT_PAGE_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
369         break;
370     case UM_EVENT_TEXT_SELECTION_CHANGED:
371         NotifyWinEvent( IA2_EVENT_TEXT_SELECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
372         break;
373     case UM_EVENT_SECTION_CHANGED:
374         NotifyWinEvent( IA2_EVENT_SECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
375         break;
376     case UM_EVENT_COLUMN_CHANGED:
377         NotifyWinEvent( IA2_EVENT_TEXT_COLUMN_CHANGED ,hAcc, OBJID_CLIENT,dChildID  );
378         break;
379     default:
380         break;
381     }
382 
383     return sal_True;
384 }
385 
386 /**
387    * Get Parent XAccessible interface by XAccessible interface.
388    * @param pXAcc XAccessible interface.
389    * @return Parent XAccessible interface.
390    */
GetParentXAccessible(XAccessible * pXAcc)391 XAccessible* AccObjectWinManager::GetParentXAccessible( XAccessible* pXAcc )
392 {
393     AccObject* pObj= GetAccObjByXAcc(pXAcc);
394     if( pObj ==NULL )
395         return NULL;
396     if(pObj->GetParentObj())
397     {
398         pObj = pObj->GetParentObj();
399         return pObj->GetXAccessible().get();
400     }
401     return NULL;
402 }
403 
404 /**
405    * Get Parent role by XAccessible interface.
406    * @param pXAcc XAccessible interface.
407    * @return Parent role.
408    */
GetParentRole(XAccessible * pXAcc)409 short AccObjectWinManager::GetParentRole( XAccessible* pXAcc )
410 {
411     AccObject* pObj= GetAccObjByXAcc(pXAcc);
412     if( pObj ==NULL )
413         return -1;
414     if(pObj->GetParentObj())
415     {
416         pObj = pObj->GetParentObj();
417         if(pObj->GetXAccessible().is())
418         {
419             XAccessible* pXAcc = pObj->GetXAccessible().get();
420             Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext();
421             if(pRContext.is())
422                 return pRContext->getAccessibleRole();
423         }
424     }
425     return -1;
426 }
427 
428 /**
429    * Update focus objcet by new focused XAccessible interface.
430    * @param newFocus New XAccessible interface that gets focus.
431    * @return
432    */
UpdateAccFocus(XAccessible * newFocus)433 void AccObjectWinManager::UpdateAccFocus(XAccessible* newFocus)
434 {
435     AccObject* pAccObjNew = GetAccObjByXAcc(newFocus);
436     if(pAccObjNew)
437     {
438         AccObject* pAccObjOld = GetAccObjByXAcc(oldFocus);
439         oldFocus = newFocus;
440         pAccObjNew->setFocus();
441         //if old == new, the pAccObjNew will be without focused state
442         if (pAccObjOld && pAccObjOld != pAccObjNew)
443             pAccObjOld->unsetFocus();
444     }
445 }
446 
447 /**
448    * Update selected objcet by new focused XAccessible interface.
449    * @param pXAcc XAccessible interface that has selected child changed.
450    * @return Selected children count.
451    */
UpdateAccSelection(XAccessible * pXAcc)452 int AccObjectWinManager::UpdateAccSelection(XAccessible* pXAcc)
453 {
454     XAccessibleSelection* pSelection = NULL;
455     Reference< XAccessibleContext > pRContext;
456 
457     if( pXAcc == NULL)
458         return sal_False;
459 
460     pRContext = pXAcc->getAccessibleContext();
461     if( !pRContext.is() )
462         return sal_False;
463 
464     Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
465     if( !pRSelection.is() )
466         return sal_False;
467 
468     AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
469     if(pAccObj==NULL)
470         return sal_False;
471 
472     Reference<XAccessible> pRChild = NULL;
473     AccObject* pAccChildObj = NULL;
474     int selectNum= pRSelection->getSelectedAccessibleChildCount();
475 
476     IAccSelectionList oldSelection = pAccObj->GetSelection();
477 
478     if(selectNum > 4)//for selected.
479         return selectNum;
480     if(selectNum == 1 && oldSelection.size() == 0)
481         return 1;
482 
483     for (int i=0;i<selectNum;i++)
484     {
485         pRChild = pRSelection->getSelectedAccessibleChild(i);
486         if(!pRChild.is())
487         {
488             continue;
489         }
490         Reference<XAccessibleContext> pRChildContext = pRChild->getAccessibleContext();
491         if(!pRChildContext.is())
492         {
493             continue;
494         }
495         long index = pRChildContext->getAccessibleIndexInParent();
496         IAccSelectionList::iterator temp = oldSelection.find(index);
497         if ( temp != oldSelection.end() )
498         {
499             oldSelection.erase(index);
500             continue;
501         }
502 
503         pAccChildObj = NULL;
504         pAccChildObj = GetAccObjByXAcc(pRChild.get());
505         if(!pAccChildObj)
506         {
507             InsertAccObj(pRChild.get(), pXAcc,pAccObj->GetParentHWND());
508             pAccChildObj = GetAccObjByXAcc(pRChild.get());
509         }
510 
511         pAccObj->AddSelect(index, pAccChildObj);
512 
513         if(pAccChildObj != NULL)
514             NotifyWinEvent(EVENT_OBJECT_SELECTIONADD,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
515     }
516 
517     IAccSelectionList::iterator iter = oldSelection.begin();
518     while(iter!=oldSelection.end())
519     {
520         pAccObj->GetSelection().erase(iter->first);
521         pAccChildObj = (AccObject*)(iter->second);
522         if(pAccChildObj != NULL)
523             NotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
524         iter++;
525     }
526     return 0;
527 
528 }
529 
530 /**
531    * Delete child element from children list.
532    * @param pObj Child element that should be removed from parant child list.
533    * @return
534    */
DeleteAccChildNode(AccObject * pObj)535 void AccObjectWinManager::DeleteAccChildNode( AccObject* pObj )
536 {
537     AccObject *parentAccObj = pObj->GetParentObj();
538     if( parentAccObj )
539         parentAccObj->DeleteChild( pObj );
540 }
541 
542 /**
543    * Delete XAccessible items in top window handle hashtable
544    * @param pXAcc XAccessible interface.
545    * @return
546    */
DeleteFromHwndXAcc(XAccessible * pXAcc)547 void AccObjectWinManager::DeleteFromHwndXAcc(XAccessible* pXAcc )
548 {
549     XHWNDToXAccHash::iterator iter = HwndXAcc.begin();
550     while(iter!=HwndXAcc.end())
551     {
552         if(iter->second == pXAcc )
553         {
554             HwndXAcc.erase(iter);
555             return;
556         }
557         iter++;
558     }
559 }
560 
561 /**
562    * Delete Delete all children with the tree root of XAccessible pointer
563    * @param pXAcc Tree root XAccessible interface.
564    * @return
565    */
DeleteChildrenAccObj(XAccessible * pXAcc)566 void AccObjectWinManager::DeleteChildrenAccObj(XAccessible* pXAcc)
567 {
568     vos::OGuard aGuard( aDeleteMutex );
569     AccObject* currentObj=NULL;
570     AccObject* childObj=NULL;
571     XAccessible* pTmpXAcc=NULL;
572 
573     currentObj =  GetAccObjByXAcc( pXAcc);
574     if(currentObj)
575     {
576         childObj = currentObj->NextChild();
577         while(childObj)
578         {
579             pTmpXAcc = GetXAccByAccObj(childObj);
580             if(pTmpXAcc)
581             {
582                 DeleteChildrenAccObj(pTmpXAcc);
583                 DeleteAccObj(pTmpXAcc);
584             }
585             childObj = currentObj->NextChild();
586         }
587     }
588 }
589 
590 /**
591    * Delete Delete Acc object self.
592    * @param pXAcc The XAccessible interface.
593    * @return
594    */
DeleteAccObj(XAccessible * pXAcc)595 void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
596 {
597     vos::OGuard aGuard( aDeleteMutex );
598     if( pXAcc == NULL )
599         return;
600     XIdToAccObjHash::iterator temp = XIdAccList.find(pXAcc);
601     if( temp != XIdAccList.end() )
602     {
603         ResIdGen.SetSub( temp->second.GetResID() );
604     }
605     else
606     {
607         return;
608     }
609 
610     AccObject& accObj = temp->second;
611     DeleteAccChildNode( &accObj );
612     DeleteAccListener( &accObj );
613     if( accObj.GetIMAccessible() )
614     {
615         accObj.GetIMAccessible()->Release();
616     }
617     XIdAccList.erase( pXAcc );
618     XResIdAccList.erase( accObj.GetResID() );
619     DeleteFromHwndXAcc(pXAcc);
620 }
621 
622 /**
623    * Delete listener that inspects some XAccessible object
624    * @param pAccObj Accobject pointer.
625    * @return
626    */
DeleteAccListener(AccObject * pAccObj)627 void AccObjectWinManager::DeleteAccListener( AccObject*  pAccObj )
628 {
629     AccEventListener* listener = pAccObj->getListener();
630     if( listener==NULL )
631         return;
632     listener->removeMeFromBroadcaster();
633     pAccObj->SetListener(NULL);
634 }
635 
636 /**
637    * Generate a child ID, which is used for AT
638    * @param
639    * @return New resource ID.
640    */
ImpleGenerateResID()641 inline long AccObjectWinManager::ImpleGenerateResID()
642 {
643     return ResIdGen.GenerateNewResID();
644 }
645 
646 /**
647    * Insert all children of the current acc object
648    * @param pXAcc XAccessible interface
649    * @param pWnd  Top Window handle
650    * @return The calling result.
651    */
InsertChildrenAccObj(com::sun::star::accessibility::XAccessible * pXAcc,HWND pWnd)652 sal_Bool AccObjectWinManager::InsertChildrenAccObj( com::sun::star::accessibility::XAccessible* pXAcc,
653         HWND pWnd)
654 {
655     if(!IsContainer(pXAcc))
656         return sal_False;
657 
658     Reference< XAccessibleContext > pRContext;
659 
660     if( pXAcc == NULL)
661         return sal_False;
662     pRContext = pXAcc->getAccessibleContext();
663     if( !pRContext.is() )
664         return sal_False;
665 
666     short role = pRContext->getAccessibleRole();
667 
668     if(com::sun::star::accessibility::AccessibleRole::DOCUMENT == role )
669     {
670         if(IsStateManageDescendant(pXAcc))
671         {
672             return sal_True;
673         }
674     }
675 
676     int count = pRContext->getAccessibleChildCount();
677     for (int i=0;i<count;i++)
678     {
679         Reference<XAccessible> mxAccessible
680         = pRContext->getAccessibleChild(i);
681         XAccessible* mpAccessible = mxAccessible.get();
682         if(mpAccessible != NULL)
683         {
684             InsertAccObj( mpAccessible,pXAcc,pWnd );
685             InsertChildrenAccObj(mpAccessible,pWnd);
686         }
687     }
688 
689     return sal_True;
690 }
691 
692 /**
693    * Insert child object.
694    * @param pCurObj The child object
695    * @param pParentObj The parant object
696    * @param pWnd Top window handle.
697    * @return
698    */
InsertAccChildNode(AccObject * pCurObj,AccObject * pParentObj,HWND)699 void AccObjectWinManager::InsertAccChildNode( AccObject* pCurObj, AccObject* pParentObj, HWND /* pWnd */ )
700 {
701     if(pCurObj)
702     {
703         if(pParentObj)
704         {
705             pParentObj->InsertChild(pCurObj);
706         }
707         else
708         {
709             pCurObj->UpdateValidWindow();
710         }
711     }
712 }
713 
714 /**
715    * Insert child object.
716    * @param pCurObj The child object
717    * @param pParentObj The parant object
718    * @param pWnd Top window handle.
719    * @return
720    */
InsertAccObj(XAccessible * pXAcc,XAccessible * pParentXAcc,HWND pWnd)721 sal_Bool AccObjectWinManager::InsertAccObj( XAccessible* pXAcc,XAccessible* pParentXAcc,HWND pWnd )
722 {
723     XIdToAccObjHash::iterator itXacc = XIdAccList.find( (void*)pXAcc );
724     if (itXacc != XIdAccList.end() )
725     {
726         short nCurRole =GetRole(pXAcc);
727         if (AccessibleRole::SHAPE == nCurRole)
728         {
729             AccObject &objXacc = itXacc->second;
730             AccObject *pObjParent = objXacc.GetParentObj();
731             if (pObjParent &&
732                     pObjParent->GetXAccessible().is() &&
733                     pObjParent->GetXAccessible().get() != pParentXAcc)
734             {
735                 XIdToAccObjHash::iterator itXaccParent  = XIdAccList.find( (void*)pParentXAcc );
736                 if(itXaccParent != XIdAccList.end())
737                 {
738                     objXacc.SetParentObj(&(itXaccParent->second));
739                 }
740             }
741         }
742         return sal_False;
743     }
744 
745 
746     Reference< XAccessibleContext > pRContext;
747 
748     if( pXAcc == NULL)
749         return sal_False;
750 
751     pRContext = pXAcc->getAccessibleContext();
752     if( !pRContext.is() )
753         return sal_False;
754 
755     if( pWnd == NULL )
756     {
757         if(pParentXAcc)
758         {
759             AccObject* pObj = GetAccObjByXAcc(pParentXAcc);
760             if(pObj)
761                 pWnd = pObj->GetParentHWND();
762         }
763         if( pWnd == NULL )
764             return sal_False;
765     }
766 
767     AccObject pObj( pXAcc,pAgent );
768     if( pObj.GetIMAccessible() == NULL )
769         return sal_False;
770     pObj.SetResID( this->ImpleGenerateResID());
771     pObj.SetParentHWND( pWnd );
772 
773     //for file name support
774     if ( pObj.GetRole() == DOCUMENT )
775     {
776         XHWNDToDocumentHash::iterator aIter = XHWNDDocList.find( (long)pWnd );
777         if ( aIter != XHWNDDocList.end() )
778         {
779             XHWNDDocList.erase( aIter );
780         }
781         XHWNDDocList.insert( XHWNDToDocumentHash::value_type( (long)pWnd, pXAcc ) );
782 
783     }
784     //end of file name
785 
786     AccEventListener* listener = createAccEventListener(pXAcc, pAgent);
787     if(listener==NULL)
788         return sal_False;
789     Reference<XAccessibleComponent> xComponent(pRContext,UNO_QUERY);
790     Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
791     if (broadcaster.is())
792     {
793         Reference <XAccessibleEventListener> pp (
794             static_cast< XAccessibleEventListener* >(listener),UNO_QUERY );
795         if(pp.is())
796         {
797             broadcaster->addEventListener(pp);
798         }
799         else
800         {
801             delete listener;
802             return sal_False;
803         }
804     }
805     else
806         return sal_False;
807 
808     XIdAccList.insert( XIdToAccObjHash::value_type( (void*)pXAcc, pObj ));
809     XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( (void*)pXAcc );
810     XResIdAccList.insert(XResIdToAccObjHash::value_type(pObj.GetResID(),&(pIndTemp->second)));
811 
812     AccObject* pCurObj = GetAccObjByXAcc(pXAcc);
813     if( pCurObj )
814     {
815         pCurObj->SetListener( listener );
816         if(listener != NULL)
817             listener->acquire();
818     }
819 
820     AccObject* pParentObj = GetAccObjByXAcc(pParentXAcc);
821     InsertAccChildNode(pCurObj,pParentObj,pWnd);
822     if( pCurObj )
823         pCurObj->UpdateAccessibleInfoFromUnoToMSAA();
824     return sal_True;
825 }
826 
827 
828 /**
829    * save the pair <topwindowhandle, XAccessible>
830    * @param hWnd, top window handle
831    * @param pXAcc XAccessible interface for top window
832    * @return void
833    */
SaveTopWindowHandle(HWND hWnd,com::sun::star::accessibility::XAccessible * pXAcc)834 void AccObjectWinManager::SaveTopWindowHandle(HWND hWnd, com::sun::star::accessibility::XAccessible* pXAcc)
835 {
836     HwndXAcc.insert( XHWNDToXAccHash::value_type( hWnd,(void*)pXAcc ) );
837 }
838 
839 
840 /**
841    * create the corresponding listener.
842    * @param pXAcc XAccessible interface.
843    * @param Agent The agent kept in all listeners,it's the sole interface by which
844    *        listener communicate with windows manager.
845    * @return
846    */
createAccEventListener(XAccessible * pXAcc,AccObjectManagerAgent *)847 AccEventListener* AccObjectWinManager::createAccEventListener(XAccessible* pXAcc, AccObjectManagerAgent* /* Agent */ )
848 {
849     AccEventListener* listener = NULL;
850     Reference<XAccessibleContext> xContext(pXAcc->getAccessibleContext(),UNO_QUERY);
851     if(xContext.is())
852     {
853         switch( xContext->getAccessibleRole() )
854         {
855         case /*AccessibleRole::*/DIALOG:
856             listener = new AccDialogEventListener(pXAcc,pAgent);
857             break;
858         case /*AccessibleRole::*/FRAME:
859             listener = new AccFrameEventListener(pXAcc,pAgent);
860             break;
861         case /*AccessibleRole::*/WINDOW:
862             listener = new AccWindowEventListener(pXAcc,pAgent);
863             break;
864         case /*AccessibleRole::*/ROOT_PANE:
865             listener = new AccFrameEventListener(pXAcc,pAgent);
866             break;
867             //Container
868         case /*AccessibleRole::*/CANVAS:
869         case /*AccessibleRole::*/COMBO_BOX:
870         case /*AccessibleRole::*/DOCUMENT:
871         case /*AccessibleRole::*/END_NOTE:
872         case /*AccessibleRole::*/FILLER:
873         case /*AccessibleRole::*/FOOTNOTE:
874         case /*AccessibleRole::*/FOOTER:
875         case /*AccessibleRole::*/HEADER:
876         case /*AccessibleRole::*/LAYERED_PANE:
877         case /*AccessibleRole::*/MENU_BAR:
878         case /*AccessibleRole::*/POPUP_MENU:
879         case /*AccessibleRole::*/OPTION_PANE:
880         case /*AccessibleRole::*/PAGE_TAB:
881         case /*AccessibleRole::*/PAGE_TAB_LIST:
882         case /*AccessibleRole::*/PANEL:
883         case /*AccessibleRole::*/SCROLL_PANE:
884         case /*AccessibleRole::*/SPLIT_PANE:
885         case /*AccessibleRole::*/STATUS_BAR:
886         case /*AccessibleRole::*/TABLE_CELL:
887         case /*AccessibleRole::*/TOOL_BAR:
888         case /*AccessibleRole::*/VIEW_PORT:
889             listener = new AccContainerEventListener(pXAcc,pAgent);
890             break;
891         case /*AccessibleRole::*/PARAGRAPH:
892         case /*AccessibleRole::*/HEADING:
893             listener = new AccParagraphEventListener(pXAcc,pAgent);
894             break;
895             //Component
896         case /*AccessibleRole::*/CHECK_BOX:
897         case /*AccessibleRole::*/ICON:
898         case /*AccessibleRole::*/LABEL:
899         case /*AccessibleRole::*/MENU_ITEM:
900         case /*AccessibleRole::*/CHECK_MENU_ITEM:
901         case /*AccessibleRole::*/RADIO_MENU_ITEM:
902         case /*AccessibleRole::*/PUSH_BUTTON:
903         case /*AccessibleRole::*/RADIO_BUTTON:
904         case /*AccessibleRole::*/SCROLL_BAR:
905         case /*AccessibleRole::*/SEPARATOR:
906         case /*AccessibleRole::*/TOGGLE_BUTTON:
907         case /*AccessibleRole::*/BUTTON_DROPDOWN:
908         case /*AccessibleRole::*/TOOL_TIP:
909         case /*AccessibleRole::*/SPIN_BOX:
910         case DATE_EDITOR:
911             listener = new AccComponentEventListener(pXAcc,pAgent);
912             break;
913             //text component
914         case /*AccessibleRole::*/TEXT:
915             listener = new AccTextComponentEventListener(pXAcc,pAgent);
916             break;
917             //menu
918         case /*AccessibleRole::*/MENU:
919             listener = new AccMenuEventListener(pXAcc,pAgent);
920             break;
921             //object container
922         case /*AccessibleRole::*/SHAPE:
923 
924         case /*AccessibleRole::*/EMBEDDED_OBJECT:
925         case /*AccessibleRole::*/GRAPHIC:
926         case /*AccessibleRole::*/TEXT_FRAME:
927             listener = new AccObjectContainerEventListener(pXAcc,pAgent);
928             break;
929             //descendmanager
930         case /*AccessibleRole::*/LIST:
931             listener = new AccListEventListener(pXAcc,pAgent);
932             break;
933         case /*AccessibleRole::*/TREE:
934             listener = new AccTreeEventListener(pXAcc,pAgent);
935             break;
936             //special
937         case /*AccessibleRole::*/COLUMN_HEADER:
938         case /*AccessibleRole::*/TABLE:
939             listener = new AccTableEventListener(pXAcc,pAgent);
940             break;
941         default:
942             listener = new AccContainerEventListener(pXAcc,pAgent);
943             break;
944         }
945     }
946 
947     return listener;
948 }
949 
950 /**
951    * state is a combination integer, each bit of which represents a single state,
952    * such as focused,1 for the state on,0 for the state off. Here call COM interface
953    * to modify the state value, including DecreaseState.
954    * @param pXAcc XAccessible interface.
955    * @param pState Changed state.
956    * @return
957    */
DecreaseState(XAccessible * pXAcc,unsigned short pState)958 void AccObjectWinManager::DecreaseState( XAccessible* pXAcc,unsigned short pState )
959 {
960     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
961     if( pAccObj )
962         pAccObj->DecreaseState( pState );
963 }
964 
965 /**
966    * state is a combination integer, each bit of which represents a single state,such as focused,1 for
967    * the state on,0 for the state off. Here call COM interface to modify the state value, including
968    * IncreaseState.
969    * @param pXAcc XAccessible interface.
970    * @param pState Changed state.
971    * @return
972    */
IncreaseState(XAccessible * pXAcc,unsigned short pState)973 void AccObjectWinManager::IncreaseState( XAccessible* pXAcc,unsigned short pState )
974 {
975     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
976     if( pAccObj )
977         pAccObj->IncreaseState( pState );
978 }
979 
UpdateState(com::sun::star::accessibility::XAccessible * pXAcc)980 void  AccObjectWinManager::UpdateState( com::sun::star::accessibility::XAccessible* pXAcc )
981 {
982     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
983     if( pAccObj )
984         pAccObj->UpdateState( );
985 }
986 
987 /**
988    * Set corresponding com object's accessible name via XAccessilbe interface and new
989    * name
990    * @param pXAcc XAccessible interface.
991    * @return
992    */
UpdateAccName(XAccessible * pXAcc)993 void  AccObjectWinManager::UpdateAccName( XAccessible* pXAcc )
994 {
995     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
996     if( pAccObj )
997         pAccObj->UpdateName();
998 }
999 
UpdateAction(XAccessible * pXAcc)1000 void  AccObjectWinManager::UpdateAction( XAccessible* pXAcc )
1001 {
1002     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1003     if( pAccObj )
1004         pAccObj->UpdateAction();
1005 }
1006 
UpdateDescription(XAccessible * pXAcc)1007 void AccObjectWinManager::UpdateDescription( XAccessible* pXAcc )
1008 {
1009     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1010     if ( pAccObj )
1011         pAccObj->UpdateDescription();
1012 }
1013 
1014 /**
1015    * Set corresponding com object's accessible location via XAccessilbe interface and new
1016    * location.
1017    * @param pXAcc XAccessible interface.
1018    * @return
1019    */
SetLocation(XAccessible * pXAcc,long,long,long,long)1020 void  AccObjectWinManager::SetLocation( XAccessible* pXAcc, long /*top*/, long /*left*/, long /*width*/, long /*height*/ )
1021 {
1022     AccObject* pObj = GetAccObjByXAcc( pXAcc );
1023     //get the location from XComponent.
1024     Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext();
1025     if( pObj )
1026         pObj->UpdateLocation();
1027 }
1028 
1029 /**
1030    * Set corresponding com object's value  via XAccessilbe interface and new value.
1031    * @param pXAcc XAccessible interface.
1032    * @param pAny new value.
1033    * @return
1034    */
SetValue(XAccessible * pXAcc,Any pAny)1035 void  AccObjectWinManager::SetValue( XAccessible* pXAcc, Any pAny )
1036 {
1037     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1038     if( pAccObj )
1039         pAccObj->SetValue( pAny );
1040 }
1041 
1042 /**
1043    * Set corresponding com object's value  via XAccessilbe interface.
1044    * @param pXAcc XAccessible interface.
1045    * @return
1046    */
UpdateValue(XAccessible * pXAcc)1047 void  AccObjectWinManager::UpdateValue( XAccessible* pXAcc )
1048 {
1049     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1050     if( pAccObj )
1051         pAccObj->UpdateValue();
1052 }
1053 
1054 /**
1055    * Set corresponding com object's name via XAccessilbe interface and new name.
1056    * @param pXAcc XAccessible interface.
1057    * @param newName new name
1058    * @return
1059    */
SetAccName(XAccessible * pXAcc,Any newName)1060 void  AccObjectWinManager::SetAccName( XAccessible* pXAcc, Any newName)
1061 {
1062     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1063     if( pAccObj )
1064         pAccObj->SetName( newName );
1065 }
1066 
1067 /**
1068    * Set corresponding com object's description via XAccessilbe interface and new description.
1069    * @param pXAcc XAccessible interface.
1070    * @param newDesc new description
1071    * @return
1072    */
SetDescription(XAccessible * pXAcc,Any newDesc)1073 void  AccObjectWinManager::SetDescription( XAccessible* pXAcc, Any newDesc )
1074 {
1075     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1076     if( pAccObj )
1077         pAccObj->SetDescription( newDesc );
1078 }
1079 
1080 /**
1081    * Set corresponding com object's role via XAccessilbe interface and new role.
1082    * @param pXAcc XAccessible interface.
1083    * @param Role new role
1084    * @return
1085    */
SetRole(XAccessible * pXAcc,long Role)1086 void  AccObjectWinManager::SetRole( XAccessible* pXAcc, long Role )
1087 {
1088     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1089     if( pAccObj )
1090         pAccObj->SetRole( (short)Role );
1091 }
1092 
1093 /**
1094    * Judge if a XAccessible object is a container object.
1095    * @param pAccessible XAccessible interface.
1096    * @return If XAccessible object is container.
1097    */
IsContainer(XAccessible * pAccessible)1098 sal_Bool AccObjectWinManager::IsContainer(XAccessible* pAccessible)
1099 {
1100     try
1101     {
1102         if(pAccessible)
1103         {
1104             Reference<XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
1105             if(xContext.is())
1106             {
1107                 switch( xContext->getAccessibleRole() )
1108                 {
1109                 case /*AccessibleRole::*/DIALOG:
1110                 case /*AccessibleRole::*/FRAME:
1111                 case /*AccessibleRole::*/WINDOW:
1112                 case /*AccessibleRole::*/ROOT_PANE:
1113                 case /*AccessibleRole::*/CANVAS:
1114                 case /*AccessibleRole::*/COMBO_BOX:
1115                 case /*AccessibleRole::*/DOCUMENT:
1116                 case /*AccessibleRole::*/EMBEDDED_OBJECT:
1117                 case /*AccessibleRole::*/END_NOTE:
1118                 case /*AccessibleRole::*/FILLER:
1119                 case /*AccessibleRole::*/FOOTNOTE:
1120                 case /*AccessibleRole::*/FOOTER:
1121                 case /*AccessibleRole::*/GRAPHIC:
1122                 case /*AccessibleRole::*/GROUP_BOX:
1123                 case /*AccessibleRole::*/HEADER:
1124                 case /*AccessibleRole::*/LAYERED_PANE:
1125                 case /*AccessibleRole::*/MENU_BAR:
1126                 case /*AccessibleRole::*/POPUP_MENU:
1127                 case /*AccessibleRole::*/OPTION_PANE:
1128                 case /*AccessibleRole::*/PAGE_TAB:
1129                 case /*AccessibleRole::*/PAGE_TAB_LIST:
1130                 case /*AccessibleRole::*/PANEL:
1131                 case /*AccessibleRole::*/SCROLL_PANE:
1132                 case /*AccessibleRole::*/SPLIT_PANE:
1133                 case /*AccessibleRole::*/STATUS_BAR:
1134                 case /*AccessibleRole::*/TABLE_CELL:
1135                 case /*AccessibleRole::*/TEXT_FRAME:
1136                 case /*AccessibleRole::*/TOOL_BAR:
1137                 case /*AccessibleRole::*/VIEW_PORT:
1138                 case /*AccessibleRole::*/SHAPE:
1139                     return sal_True;
1140                     break;
1141                 case /*AccessibleRole::*/COLUMN_HEADER:
1142                 case /*AccessibleRole::*/TABLE:
1143                     if(!IsStateManageDescendant(pAccessible))
1144                         return sal_True;
1145                     break;
1146                 case /*AccessibleRole::*/MENU:
1147                     return sal_True;
1148                     break;
1149                 default:
1150                     return sal_False;
1151                 }
1152             }
1153         }
1154     }
1155     catch(...)
1156     {
1157         return sal_False;
1158     }
1159     return sal_False;
1160 }
1161 
1162 /**
1163    * Judge if a XAccessible object has ManageDescendant event.
1164    * @param pAccessible XAccessible interface.
1165    * @return If XAccessible object is managedescendant.
1166    */
IsStateManageDescendant(XAccessible * pAccessible)1167 bool AccObjectWinManager::IsStateManageDescendant(XAccessible* pAccessible)
1168 {
1169     if(pAccessible)
1170     {
1171         Reference<XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
1172         if(xContext.is())
1173         {
1174             Reference< XAccessibleStateSet > pRState = xContext->getAccessibleStateSet();
1175             if( !pRState.is() )
1176                 return sal_False;
1177 
1178             Sequence<short> pStates = pRState->getStates();
1179             int count = pStates.getLength();
1180             for( int iIndex = 0;iIndex < count;iIndex++ )
1181             {
1182                 if(pStates[iIndex] == /*AccessibleStateType::*/MANAGES_DESCENDANTS)
1183                     return sal_True;
1184             }
1185         }
1186     }
1187     return sal_False;
1188 }
1189 
1190 /**
1191    * Query and get IAccessible interface by XAccessible interface from list.
1192    * @param pXAcc XAccessible interface.
1193    * @return Com accobject interface.
1194    */
GetIMAccByXAcc(XAccessible * pXAcc)1195 IMAccessible* AccObjectWinManager::GetIMAccByXAcc(XAccessible* pXAcc)
1196 {
1197     AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
1198     if(pAccObj)
1199     {
1200         return pAccObj->GetIMAccessible();
1201     }
1202     else
1203     {
1204         return NULL;
1205     }
1206 }
1207 
1208 /**
1209    * Query and get IAccessible interface by child id from list.
1210    * @param resID, childID.
1211    * @return Com accobject interface.
1212    */
GetIAccessibleFromResID(long resID)1213 IMAccessible * AccObjectWinManager::GetIAccessibleFromResID(long resID)
1214 {
1215     XResIdToAccObjHash::iterator pIndTemp = XResIdAccList.find( resID );
1216     if ( pIndTemp == XResIdAccList.end() )
1217         return NULL;
1218 
1219     AccObject* pObj = pIndTemp->second;
1220 
1221     if(pObj->GetIMAccessible())
1222         return pObj->GetIMAccessible();
1223     return NULL;
1224 }
1225 /**
1226    * Notify some object will be destroyed.
1227    * @param pXAcc XAccessible interface.
1228    * @return Com accobject interface.
1229    */
NotifyDestroy(XAccessible * pXAcc)1230 void AccObjectWinManager::NotifyDestroy(XAccessible* pXAcc)
1231 {
1232     AccObject* accObj = GetAccObjByXAcc(pXAcc);
1233     if(accObj)
1234     {
1235         accObj->NotifyDestroy(sal_True);
1236     }
1237 }
1238 
1239 
UpdateChildState(com::sun::star::accessibility::XAccessible * pAccSubMenu)1240 void AccObjectWinManager::UpdateChildState(com::sun::star::accessibility::XAccessible* pAccSubMenu)
1241 {
1242     Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccSubMenu,UNO_QUERY);
1243     if (!xContext.is())
1244     {
1245         return;
1246     }
1247     sal_Int32 nCount = xContext->getAccessibleChildCount();
1248     for (sal_Int32 i = 0 ; i < nCount ; ++i)
1249     {
1250         Reference<com::sun::star::accessibility::XAccessible> xChild = xContext->getAccessibleChild(i);
1251         if (xChild.is())
1252         {
1253             AccObject *pObj =  GetAccObjByXAcc(xChild.get());
1254             if (pObj)
1255             {
1256                 pObj->UpdateState();
1257             }
1258         }
1259     }
1260 }
1261 
1262 
IsSpecialToolboItem(com::sun::star::accessibility::XAccessible * pXAcc)1263 bool AccObjectWinManager::IsSpecialToolboItem(com::sun::star::accessibility::XAccessible* pXAcc)
1264 {
1265     if (pXAcc && oldFocus != pXAcc)
1266     {
1267         if(GetParentRole(pXAcc) == TOOL_BAR)
1268         {
1269             Reference< XAccessibleContext > pRContext(pXAcc->getAccessibleContext());
1270             if (pRContext.is())
1271             {
1272                 if(pRContext->getAccessibleRole() == TOGGLE_BUTTON)
1273                 {
1274                     return true;
1275                 }
1276             }
1277         }
1278     }
1279     return false;
1280 }
1281 
GetRole(com::sun::star::accessibility::XAccessible * pXAcc)1282 short AccObjectWinManager::GetRole(com::sun::star::accessibility::XAccessible* pXAcc)
1283 {
1284     assert(pXAcc != NULL);
1285     Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pXAcc->getAccessibleContext(),UNO_QUERY);
1286     if(xContext.is())
1287     {
1288         return xContext->getAccessibleRole();
1289     }
1290     return -1;
1291 }
1292 
GetAccDocByHWND(long pWnd)1293 XAccessible* AccObjectWinManager::GetAccDocByHWND( long pWnd )
1294 {
1295     XHWNDToDocumentHash::iterator aIter;
1296     aIter = XHWNDDocList.find( pWnd );
1297     if ( aIter != XHWNDDocList.end() )
1298     {
1299         return aIter->second;
1300     }
1301 
1302     return NULL;
1303 }
1304 
GetAccDocByAccTopWin(XAccessible * pXAcc)1305 XAccessible* AccObjectWinManager::GetAccDocByAccTopWin( XAccessible* pXAcc )
1306 {
1307     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1308     long pWnd = (long)( pAccObj->GetParentHWND() );
1309     return GetAccDocByHWND( pWnd );
1310 }
1311 
IsTopWinAcc(com::sun::star::accessibility::XAccessible * pXAcc)1312 bool AccObjectWinManager::IsTopWinAcc( com::sun::star::accessibility::XAccessible* pXAcc )
1313 {
1314     bool bRet = false;
1315     AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1316     if ( pAccObj )
1317     {
1318         bRet = ( pAccObj->GetParentObj() == NULL );
1319     }
1320     return bRet;
1321 }