Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / winaccessibility / source / service / AccObjectWinManager.cxx
blobb56db56d4bab7f5572ec333d333e3b130dbb754b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cassert>
22 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
23 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
24 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
25 #include <com/sun/star/accessibility/AccessibleRole.hpp>
26 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <oleacc.h>
29 #include <AccObjectWinManager.hxx>
30 #include <AccEventListener.hxx>
31 #include <AccComponentEventListener.hxx>
32 #include <AccContainerEventListener.hxx>
33 #include <AccDialogEventListener.hxx>
34 #include <AccWindowEventListener.hxx>
35 #include <AccFrameEventListener.hxx>
36 #include <AccMenuEventListener.hxx>
37 #include <AccObjectContainerEventListener.hxx>
38 #include <AccParagraphEventListener.hxx>
39 #include <AccTextComponentEventListener.hxx>
40 #include <AccListEventListener.hxx>
41 #include <AccTreeEventListener.hxx>
42 #include <AccTableEventListener.hxx>
43 #include <AccObject.hxx>
44 #include <unomsaaevent.hxx>
47 using namespace std;
48 using namespace com::sun::star::accessibility;
49 using namespace com::sun::star::accessibility::AccessibleRole;
50 using namespace com::sun::star::accessibility::AccessibleStateType;
51 using namespace com::sun::star::uno;
53 /**
54 * constructor
55 * @param Agent The agent kept in all listeners,it's the sole interface by which
56 * listener communicate with windows manager.
57 * pEventAccObj The present event accobject.
58 * oldFocus Last focused object.
59 * isSelectionChanged flag that identifies if there is selection changed.
60 * selectionChildObj Selected object.
61 * dChildID Chile resource ID.
62 * hAcc TopWindowHWND
63 * @return
65 AccObjectWinManager::AccObjectWinManager( AccObjectManagerAgent* Agent ):
66 oldFocus( nullptr ),
67 pAgent( Agent )
71 /**
72 * Destructor,clear all resource.
73 * @param
74 * @return
76 AccObjectWinManager::~AccObjectWinManager()
78 XIdAccList.clear();
79 HwndXAcc.clear();
80 XResIdAccList.clear();
81 XHWNDDocList.clear();
82 #ifdef ACC_DEBUG
84 fclose( pFile );
85 #endif
89 /**
90 * Get valid com object interface when notifying some MSAA event
91 * @param pWND The top window handle that contains that event control.
92 * @param wParam Windows system interface.
93 * @return Com interface with event.
96 LRESULT
97 AccObjectWinManager::Get_ToATInterface(HWND hWnd, long lParam, WPARAM wParam)
99 IMAccessible* pRetIMAcc = nullptr;
101 if(lParam == OBJID_CLIENT )
103 AccObject* topWindowAccObj = GetTopWindowAccObj(hWnd);
104 if(topWindowAccObj)
106 pRetIMAcc = topWindowAccObj->GetIMAccessible();
107 if(pRetIMAcc)
108 pRetIMAcc->AddRef();//increase COM reference count
112 if ( pRetIMAcc && lParam == OBJID_CLIENT )
114 LRESULT result = LresultFromObject(IID_IAccessible, wParam, pRetIMAcc);
115 pRetIMAcc->Release();
116 return result;
118 return 0;
122 * Search AccObject by XAccessible pointer from our container.
123 * @param pXAcc XAccessible interface.
124 * @return Pointer of accObject that is found.
126 AccObject* AccObjectWinManager::GetAccObjByXAcc( XAccessible* pXAcc)
128 if( pXAcc == nullptr)
129 return nullptr;
131 XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
132 if ( pIndTemp == XIdAccList.end() )
133 return nullptr;
135 return &(pIndTemp->second);
139 * get acc object of top window by its handle
140 * @param hWnd, top window handle
141 * @return pointer to AccObject
143 AccObject* AccObjectWinManager::GetTopWindowAccObj(HWND hWnd)
145 XHWNDToXAccHash::iterator iterResult =HwndXAcc.find(hWnd);
146 if(iterResult == HwndXAcc.end())
147 return nullptr;
148 XAccessible* pXAcc = static_cast<XAccessible*>(iterResult->second);
149 return GetAccObjByXAcc(pXAcc);
153 * Simulate MSAA event via XAccessible interface and event type.
154 * @param pXAcc XAccessible interface.
155 * @param state Customize Interface
156 * @return The terminate result that identifies if the call is successful.
158 bool AccObjectWinManager::NotifyAccEvent(XAccessible* pXAcc,short state)
160 Reference< XAccessibleContext > pRContext;
162 if( pXAcc == nullptr)
163 return false;
166 pRContext = pXAcc->getAccessibleContext();
167 if( !pRContext.is() )
168 return false;
171 AccObject* selfAccObj= GetAccObjByXAcc(pXAcc);
173 if(selfAccObj==nullptr)
174 return false;
176 long dChildID = selfAccObj->GetResID();
177 HWND hAcc = selfAccObj->GetParentHWND();
179 switch(state)
181 case UM_EVENT_STATE_FOCUSED:
183 UpdateAccFocus(pXAcc);
184 selfAccObj->UpdateDefaultAction( );
185 UpdateValue(pXAcc);
186 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
187 break;
189 case UM_EVENT_STATE_BUSY:
190 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
191 break;
192 case UM_EVENT_STATE_CHECKED:
193 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
194 break;
195 case UM_EVENT_STATE_PRESSED:
196 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
197 break;
199 //Removed fire out selected event
200 //case UM_EVENT_STATE_SELECTED:
201 // NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
202 // break;
203 case UM_EVENT_STATE_ARMED:
204 UpdateAccFocus(pXAcc);
205 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
206 break;
207 case UM_EVENT_MENU_START:
208 NotifyWinEvent( EVENT_SYSTEM_MENUSTART,hAcc, OBJID_CLIENT,dChildID );
209 break;
210 case UM_EVENT_MENU_END:
211 NotifyWinEvent( EVENT_SYSTEM_MENUEND,hAcc, OBJID_CLIENT,dChildID );
212 break;
213 case UM_EVENT_MENUPOPUPSTART:
214 NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPSTART,hAcc, OBJID_CLIENT,dChildID );
215 break;
216 case UM_EVENT_MENUPOPUPEND:
217 NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPEND,hAcc, OBJID_CLIENT,dChildID );
218 break;
219 case UM_EVENT_SELECTION_CHANGED:
220 NotifyWinEvent( EVENT_OBJECT_SELECTION,hAcc, OBJID_CLIENT,dChildID );
221 break;
222 case UM_EVENT_SELECTION_CHANGED_ADD:
223 NotifyWinEvent( EVENT_OBJECT_SELECTIONADD,hAcc, OBJID_CLIENT,dChildID );
224 break;
225 case UM_EVENT_SELECTION_CHANGED_REMOVE:
226 NotifyWinEvent( EVENT_OBJECT_SELECTIONREMOVE,hAcc, OBJID_CLIENT,dChildID );
227 break;
228 case UM_EVENT_SELECTION_CHANGED_WITHIN:
229 NotifyWinEvent( EVENT_OBJECT_SELECTIONWITHIN,hAcc, OBJID_CLIENT,dChildID );
230 break;
231 case UM_EVENT_OBJECT_VALUECHANGE:
232 UpdateValue(pXAcc);
233 NotifyWinEvent( EVENT_OBJECT_VALUECHANGE,hAcc, OBJID_CLIENT,dChildID );
234 break;
235 case UM_EVENT_OBJECT_NAMECHANGE:
236 NotifyWinEvent( EVENT_OBJECT_NAMECHANGE,hAcc, OBJID_CLIENT,dChildID );
237 break;
238 case UM_EVENT_OBJECT_DESCRIPTIONCHANGE:
239 NotifyWinEvent( EVENT_OBJECT_DESCRIPTIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
240 break;
241 case UM_EVENT_OBJECT_DEFACTIONCHANGE:
242 NotifyWinEvent( IA2_EVENT_ACTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
243 break;
244 case UM_EVENT_OBJECT_CARETCHANGE:
245 NotifyWinEvent( IA2_EVENT_TEXT_CARET_MOVED,hAcc, OBJID_CLIENT,dChildID );
246 break;
247 case UM_EVENT_OBJECT_TEXTCHANGE:
248 NotifyWinEvent( IA2_EVENT_TEXT_CHANGED,hAcc, OBJID_CLIENT,dChildID );
249 break;
250 case UM_EVENT_ACTIVE_DESCENDANT_CHANGED:
251 UpdateAccFocus(pXAcc);
252 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
253 break;
254 case UM_EVENT_BOUNDRECT_CHANGED:
255 NotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
256 break;
257 case UM_EVENT_VISIBLE_DATA_CHANGED:
258 NotifyWinEvent( IA2_EVENT_VISIBLE_DATA_CHANGED,hAcc, OBJID_CLIENT,dChildID );
259 break;
260 case UM_EVENT_SHOW :
261 NotifyWinEvent( EVENT_OBJECT_SHOW,hAcc, OBJID_CLIENT,dChildID );
262 NotifyWinEvent( EVENT_SYSTEM_FOREGROUND,hAcc, OBJID_CLIENT,dChildID );
263 break;
264 case UM_EVENT_TABLE_CAPTION_CHANGED:
265 NotifyWinEvent( IA2_EVENT_TABLE_CAPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
266 break;
267 case UM_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED:
268 NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
269 break;
270 case UM_EVENT_TABLE_COLUMN_HEADER_CHANGED:
271 NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
272 break;
273 case UM_EVENT_TABLE_MODEL_CHANGED:
274 NotifyWinEvent( IA2_EVENT_TABLE_MODEL_CHANGED,hAcc, OBJID_CLIENT,dChildID );
275 break;
276 case UM_EVENT_TABLE_ROW_HEADER_CHANGED:
277 NotifyWinEvent( IA2_EVENT_TABLE_ROW_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
278 break;
279 case UM_EVENT_TABLE_SUMMARY_CHANGED:
280 NotifyWinEvent( IA2_EVENT_TABLE_SUMMARY_CHANGED,hAcc, OBJID_CLIENT,dChildID );
281 break;
282 case UM_EVENT_TABLE_ROW_DESCRIPTION_CHANGED:
283 NotifyWinEvent( IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
284 break;
285 case UM_EVENT_OBJECT_REORDER:
286 NotifyWinEvent( EVENT_OBJECT_REORDER,hAcc, OBJID_CLIENT,dChildID );
287 break;
288 case UM_EVENT_PAGE_CHANGED:
289 NotifyWinEvent( IA2_EVENT_PAGE_CHANGED,hAcc, OBJID_CLIENT,dChildID );
290 break;
291 case UM_EVENT_CHILD_REMOVED:
292 NotifyWinEvent( EVENT_OBJECT_DESTROY,hAcc, OBJID_CLIENT,dChildID );
293 break;
294 case UM_EVENT_CHILD_ADDED:
295 NotifyWinEvent( EVENT_OBJECT_CREATE ,hAcc, OBJID_CLIENT,dChildID );
296 break;
297 case UM_EVENT_OBJECT_PAGECHANGED:
298 NotifyWinEvent( IA2_EVENT_PAGE_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
299 break;
300 case UM_EVENT_TEXT_SELECTION_CHANGED:
301 NotifyWinEvent( IA2_EVENT_TEXT_SELECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
302 break;
303 case UM_EVENT_SECTION_CHANGED:
304 NotifyWinEvent( IA2_EVENT_SECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
305 break;
306 case UM_EVENT_COLUMN_CHANGED:
307 NotifyWinEvent( IA2_EVENT_TEXT_COLUMN_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
308 break;
309 default:
310 break;
313 return true;
317 * Get Parent XAccessible interface by XAccessible interface.
318 * @param pXAcc XAccessible interface.
319 * @return Parent XAccessible interface.
321 XAccessible* AccObjectWinManager::GetParentXAccessible( XAccessible* pXAcc )
323 AccObject* pObj= GetAccObjByXAcc(pXAcc);
324 if( pObj ==nullptr )
325 return nullptr;
326 if(pObj->GetParentObj())
328 pObj = pObj->GetParentObj();
329 return pObj->GetXAccessible().get();
331 return nullptr;
335 * Get Parent role by XAccessible interface.
336 * @param pXAcc XAccessible interface.
337 * @return Parent role.
339 short AccObjectWinManager::GetParentRole( XAccessible* pXAcc )
341 AccObject* pObj= GetAccObjByXAcc(pXAcc);
342 if( pObj ==nullptr )
343 return -1;
344 if(pObj->GetParentObj())
346 pObj = pObj->GetParentObj();
347 if(pObj->GetXAccessible().is())
349 Reference< XAccessibleContext > pRContext = pObj->GetXAccessible()->getAccessibleContext();
350 if(pRContext.is())
351 return pRContext->getAccessibleRole();
354 return -1;
358 * Update focus object by new focused XAccessible interface.
359 * @param newFocus New XAccessible interface that gets focus.
360 * @return
362 void AccObjectWinManager::UpdateAccFocus(XAccessible* newFocus)
364 AccObject* pAccObjNew = GetAccObjByXAcc(newFocus);
365 if(pAccObjNew)
367 AccObject* pAccObjOld = GetAccObjByXAcc(oldFocus);
368 oldFocus = newFocus;
369 pAccObjNew->setFocus();
370 //if old == new, the pAccObjNew will be without focused state
371 if (pAccObjOld && pAccObjOld != pAccObjNew)
372 pAccObjOld->unsetFocus();
377 * Update selected object by new focused XAccessible interface.
378 * @param pXAcc XAccessible interface that has selected child changed.
379 * @return Selected children count.
381 int AccObjectWinManager::UpdateAccSelection(XAccessible* pXAcc)
383 Reference< XAccessibleContext > pRContext;
385 if( pXAcc == nullptr)
386 return 0;
388 pRContext = pXAcc->getAccessibleContext();
389 if( !pRContext.is() )
390 return 0;
392 Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
393 if( !pRSelection.is() )
394 return 0;
396 AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
397 if(pAccObj==nullptr)
398 return 0;
400 Reference<XAccessible> pRChild;
401 AccObject* pAccChildObj = nullptr;
402 int selectNum= pRSelection->getSelectedAccessibleChildCount();
404 IAccSelectionList oldSelection = pAccObj->GetSelection();
406 if(selectNum > 4)//for selected.
407 return selectNum;
408 if(selectNum == 1 && oldSelection.size() == 0)
409 return 1;
411 for (int i=0;i<selectNum;i++)
413 pRChild = pRSelection->getSelectedAccessibleChild(i);
414 if(!pRChild.is())
416 continue;
418 Reference<XAccessibleContext> pRChildContext = pRChild->getAccessibleContext();
419 if(!pRChildContext.is())
421 continue;
423 long index = pRChildContext->getAccessibleIndexInParent();
424 IAccSelectionList::iterator temp = oldSelection.find(index);
425 if ( temp != oldSelection.end() )
427 oldSelection.erase(index);
428 continue;
431 pAccChildObj = GetAccObjByXAcc(pRChild.get());
432 if(!pAccChildObj)
434 InsertAccObj(pRChild.get(), pXAcc,pAccObj->GetParentHWND());
435 pAccChildObj = GetAccObjByXAcc(pRChild.get());
438 pAccObj->AddSelect(index, pAccChildObj);
440 if(pAccChildObj != nullptr)
441 NotifyWinEvent(EVENT_OBJECT_SELECTIONADD,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
444 for (const auto& rEntry : oldSelection)
446 pAccObj->GetSelection().erase(rEntry.first);
447 pAccChildObj = rEntry.second;
448 if(pAccChildObj != nullptr)
449 NotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
451 return 0;
456 * Delete child element from children list.
457 * @param pObj Child element that should be removed from parent child list.
458 * @return
460 void AccObjectWinManager::DeleteAccChildNode( AccObject* pObj )
462 AccObject *parentAccObj = pObj->GetParentObj();
463 if( parentAccObj )
464 parentAccObj->DeleteChild( pObj );
468 * Delete XAccessible items in top window handle hashtable
469 * @param pXAcc XAccessible interface.
470 * @return
472 void AccObjectWinManager::DeleteFromHwndXAcc(XAccessible const * pXAcc )
474 auto iter = std::find_if(HwndXAcc.begin(), HwndXAcc.end(),
475 [&pXAcc](XHWNDToXAccHash::value_type& rEntry) { return rEntry.second == pXAcc; });
476 if (iter != HwndXAcc.end())
477 HwndXAcc.erase(iter);
481 * Delete all children with the tree root of XAccessible pointer
482 * @param pXAcc Tree root XAccessible interface.
483 * @return
485 void AccObjectWinManager::DeleteChildrenAccObj(XAccessible* pXAcc)
487 AccObject* currentObj=nullptr;
488 AccObject* childObj=nullptr;
490 currentObj = GetAccObjByXAcc( pXAcc);
491 if(currentObj)
493 childObj = currentObj->NextChild();
494 while(childObj)
496 XAccessible *const pTmpXAcc = childObj->GetXAccessible().get();
497 if(pTmpXAcc)
499 DeleteChildrenAccObj(pTmpXAcc);
500 DeleteAccObj(pTmpXAcc);
502 childObj = currentObj->NextChild();
508 * Delete Acc object self.
509 * @param pXAcc The XAccessible interface.
510 * @return
512 void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
514 if( pXAcc == nullptr )
515 return;
516 XIdToAccObjHash::iterator temp = XIdAccList.find(pXAcc);
517 if( temp != XIdAccList.end() )
519 ResIdGen.SetSub( temp->second.GetResID() );
521 else
523 return;
526 AccObject& accObj = temp->second;
527 DeleteAccChildNode( &accObj );
528 DeleteAccListener( &accObj );
529 if( accObj.GetIMAccessible() )
531 accObj.GetIMAccessible()->Release();
533 size_t i = XResIdAccList.erase(accObj.GetResID());
534 assert(i != 0);
535 DeleteFromHwndXAcc(pXAcc);
536 if( accObj.GetRole() == DOCUMENT ||
537 accObj.GetRole() == DOCUMENT_PRESENTATION ||
538 accObj.GetRole() == DOCUMENT_SPREADSHEET ||
539 accObj.GetRole() == DOCUMENT_TEXT )
541 XHWNDDocList.erase(accObj.GetParentHWND());
543 XIdAccList.erase(pXAcc); // note: this invalidates accObj so do it last!
547 * Delete listener that inspects some XAccessible object
548 * @param pAccObj Accobject pointer.
549 * @return
551 void AccObjectWinManager::DeleteAccListener( AccObject* pAccObj )
553 AccEventListener* listener = pAccObj->getListener();
554 if( listener==nullptr )
555 return;
556 listener->RemoveMeFromBroadcaster();
557 pAccObj->SetListener(nullptr);
561 * Generate a child ID, which is used for AT
562 * @param
563 * @return New resource ID.
565 inline long AccObjectWinManager::ImpleGenerateResID()
567 return ResIdGen.GenerateNewResID();
571 * Insert all children of the current acc object
572 * @param pXAcc XAccessible interface
573 * @param pWnd Top Window handle
574 * @return The calling result.
576 bool AccObjectWinManager::InsertChildrenAccObj( css::accessibility::XAccessible* pXAcc,
577 HWND pWnd)
579 if(!IsContainer(pXAcc))
580 return false;
582 Reference< XAccessibleContext > pRContext;
584 if( pXAcc == nullptr)
585 return false;
586 pRContext = pXAcc->getAccessibleContext();
587 if( !pRContext.is() )
588 return false;
590 short role = pRContext->getAccessibleRole();
592 if(css::accessibility::AccessibleRole::DOCUMENT == role ||
593 css::accessibility::AccessibleRole::DOCUMENT_PRESENTATION == role ||
594 css::accessibility::AccessibleRole::DOCUMENT_SPREADSHEET == role ||
595 css::accessibility::AccessibleRole::DOCUMENT_TEXT == role)
597 if(IsStateManageDescendant(pXAcc))
599 return true;
603 int count = pRContext->getAccessibleChildCount();
604 for (int i=0;i<count;i++)
606 Reference<XAccessible> mxAccessible
607 = pRContext->getAccessibleChild(i);
608 XAccessible* mpAccessible = mxAccessible.get();
609 if(mpAccessible != nullptr)
611 InsertAccObj( mpAccessible,pXAcc,pWnd );
612 InsertChildrenAccObj(mpAccessible,pWnd);
616 return true;
620 * Insert child object.
621 * @param pCurObj The child object
622 * @param pParentObj The parent object
623 * @param pWnd Top window handle.
624 * @return
626 void AccObjectWinManager::InsertAccChildNode( AccObject* pCurObj, AccObject* pParentObj, HWND /* pWnd */ )
628 if(pCurObj)
630 if(pParentObj)
632 pParentObj->InsertChild(pCurObj);
634 else
636 pCurObj->UpdateValidWindow();
642 * Insert child object.
643 * @param pCurObj The child object
644 * @param pParentObj The parent object
645 * @param pWnd Top window handle.
646 * @return
648 bool AccObjectWinManager::InsertAccObj( XAccessible* pXAcc,XAccessible* pParentXAcc,HWND pWnd )
650 XIdToAccObjHash::iterator itXacc = XIdAccList.find( pXAcc );
651 if (itXacc != XIdAccList.end() )
653 short nCurRole =GetRole(pXAcc);
654 if (AccessibleRole::SHAPE == nCurRole)
656 AccObject &objXacc = itXacc->second;
657 AccObject *pObjParent = objXacc.GetParentObj();
658 if (pObjParent &&
659 pObjParent->GetXAccessible().is() &&
660 pObjParent->GetXAccessible().get() != pParentXAcc)
662 XIdToAccObjHash::iterator itXaccParent = XIdAccList.find( pParentXAcc );
663 if(itXaccParent != XIdAccList.end())
665 objXacc.SetParentObj(&(itXaccParent->second));
669 return false;
673 Reference< XAccessibleContext > pRContext;
675 if( pXAcc == nullptr)
676 return false;
678 pRContext = pXAcc->getAccessibleContext();
679 if( !pRContext.is() )
680 return false;
682 if( pWnd == nullptr )
684 if(pParentXAcc)
686 AccObject* pObj = GetAccObjByXAcc(pParentXAcc);
687 if(pObj)
688 pWnd = pObj->GetParentHWND();
690 if( pWnd == nullptr )
691 return false;
694 AccObject pObj( pXAcc,pAgent );
695 if( pObj.GetIMAccessible() == nullptr )
696 return false;
697 pObj.SetResID( this->ImpleGenerateResID());
698 pObj.SetParentHWND( pWnd );
700 //for file name support
701 if( pObj.GetRole() == DOCUMENT ||
702 pObj.GetRole() == DOCUMENT_PRESENTATION ||
703 pObj.GetRole() == DOCUMENT_SPREADSHEET ||
704 pObj.GetRole() == DOCUMENT_TEXT )
706 XHWNDToDocumentHash::iterator aIter = XHWNDDocList.find(pWnd);
707 if ( aIter != XHWNDDocList.end() )
709 XHWNDDocList.erase( aIter );
711 XHWNDDocList.emplace( pWnd, pXAcc );
713 //end of file name
715 ::rtl::Reference<AccEventListener> const pListener =
716 CreateAccEventListener(pXAcc);
717 if (!pListener.is())
718 return false;
719 Reference<XAccessibleComponent> xComponent(pRContext,UNO_QUERY);
720 Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
721 if (broadcaster.is())
723 Reference<XAccessibleEventListener> const xListener(pListener.get());
724 broadcaster->addAccessibleEventListener(xListener);
726 else
727 return false;
729 XIdAccList.emplace(pXAcc, pObj);
730 XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
731 XResIdAccList.emplace(pObj.GetResID(),&(pIndTemp->second));
733 AccObject* pCurObj = GetAccObjByXAcc(pXAcc);
734 if( pCurObj )
736 pCurObj->SetListener(pListener);
739 AccObject* pParentObj = GetAccObjByXAcc(pParentXAcc);
740 InsertAccChildNode(pCurObj,pParentObj,pWnd);
741 if( pCurObj )
742 pCurObj->UpdateAccessibleInfoFromUnoToMSAA();
743 return true;
748 * save the pair <topwindowhandle, XAccessible>
749 * @param hWnd, top window handle
750 * @param pXAcc XAccessible interface for top window
751 * @return void
753 void AccObjectWinManager::SaveTopWindowHandle(HWND hWnd, css::accessibility::XAccessible* pXAcc)
755 HwndXAcc.emplace(hWnd,pXAcc);
759 /** Create the corresponding listener.
760 * @param pXAcc XAccessible interface.
762 ::rtl::Reference<AccEventListener>
763 AccObjectWinManager::CreateAccEventListener(XAccessible* pXAcc)
765 ::rtl::Reference<AccEventListener> pRet;
766 Reference<XAccessibleContext> xContext = pXAcc->getAccessibleContext();
767 if(xContext.is())
769 switch( xContext->getAccessibleRole() )
771 case /*AccessibleRole::*/DIALOG:
772 pRet = new AccDialogEventListener(pXAcc,pAgent);
773 break;
774 case /*AccessibleRole::*/FRAME:
775 pRet = new AccFrameEventListener(pXAcc,pAgent);
776 break;
777 case /*AccessibleRole::*/WINDOW:
778 pRet = new AccWindowEventListener(pXAcc,pAgent);
779 break;
780 case /*AccessibleRole::*/ROOT_PANE:
781 pRet = new AccFrameEventListener(pXAcc,pAgent);
782 break;
783 //Container
784 case /*AccessibleRole::*/CANVAS:
785 case /*AccessibleRole::*/COMBO_BOX:
786 case /*AccessibleRole::*/DOCUMENT:
787 case /*AccessibleRole::*/DOCUMENT_PRESENTATION:
788 case /*AccessibleRole::*/DOCUMENT_SPREADSHEET:
789 case /*AccessibleRole::*/DOCUMENT_TEXT:
790 case /*AccessibleRole::*/END_NOTE:
791 case /*AccessibleRole::*/FILLER:
792 case /*AccessibleRole::*/FOOTNOTE:
793 case /*AccessibleRole::*/FOOTER:
794 case /*AccessibleRole::*/HEADER:
795 case /*AccessibleRole::*/LAYERED_PANE:
796 case /*AccessibleRole::*/MENU_BAR:
797 case /*AccessibleRole::*/POPUP_MENU:
798 case /*AccessibleRole::*/OPTION_PANE:
799 case /*AccessibleRole::*/PAGE_TAB:
800 case /*AccessibleRole::*/PAGE_TAB_LIST:
801 case /*AccessibleRole::*/PANEL:
802 case /*AccessibleRole::*/SCROLL_PANE:
803 case /*AccessibleRole::*/SPLIT_PANE:
804 case /*AccessibleRole::*/STATUS_BAR:
805 case /*AccessibleRole::*/TABLE_CELL:
806 case /*AccessibleRole::*/TOOL_BAR:
807 case /*AccessibleRole::*/VIEW_PORT:
808 pRet = new AccContainerEventListener(pXAcc,pAgent);
809 break;
810 case /*AccessibleRole::*/PARAGRAPH:
811 case /*AccessibleRole::*/HEADING:
812 pRet = new AccParagraphEventListener(pXAcc,pAgent);
813 break;
814 //Component
815 case /*AccessibleRole::*/CHECK_BOX:
816 case /*AccessibleRole::*/ICON:
817 case /*AccessibleRole::*/LABEL:
818 case /*AccessibleRole::*/STATIC:
819 case /*AccessibleRole::*/MENU_ITEM:
820 case /*AccessibleRole::*/CHECK_MENU_ITEM:
821 case /*AccessibleRole::*/RADIO_MENU_ITEM:
822 case /*AccessibleRole::*/PUSH_BUTTON:
823 case /*AccessibleRole::*/RADIO_BUTTON:
824 case /*AccessibleRole::*/SCROLL_BAR:
825 case /*AccessibleRole::*/SEPARATOR:
826 case /*AccessibleRole::*/TOGGLE_BUTTON:
827 case /*AccessibleRole::*/BUTTON_DROPDOWN:
828 case /*AccessibleRole::*/TOOL_TIP:
829 case /*AccessibleRole::*/SPIN_BOX:
830 case DATE_EDITOR:
831 pRet = new AccComponentEventListener(pXAcc,pAgent);
832 break;
833 //text component
834 case /*AccessibleRole::*/TEXT:
835 pRet = new AccTextComponentEventListener(pXAcc,pAgent);
836 break;
837 //menu
838 case /*AccessibleRole::*/MENU:
839 pRet = new AccMenuEventListener(pXAcc,pAgent);
840 break;
841 //object container
842 case /*AccessibleRole::*/SHAPE:
844 case /*AccessibleRole::*/EMBEDDED_OBJECT:
845 case /*AccessibleRole::*/GRAPHIC:
846 case /*AccessibleRole::*/TEXT_FRAME:
847 pRet = new AccObjectContainerEventListener(pXAcc,pAgent);
848 break;
849 //descendmanager
850 case /*AccessibleRole::*/LIST:
851 pRet = new AccListEventListener(pXAcc,pAgent);
852 break;
853 case /*AccessibleRole::*/TREE:
854 pRet = new AccTreeEventListener(pXAcc,pAgent);
855 break;
856 //special
857 case /*AccessibleRole::*/COLUMN_HEADER:
858 case /*AccessibleRole::*/TABLE:
859 pRet = new AccTableEventListener(pXAcc,pAgent);
860 break;
861 default:
862 pRet = new AccContainerEventListener(pXAcc,pAgent);
863 break;
866 return pRet;
870 * state is a combination integer, each bit of which represents a single state,
871 * such as focused,1 for the state on,0 for the state off. Here call COM interface
872 * to modify the state value, including DecreaseState.
873 * @param pXAcc XAccessible interface.
874 * @param pState Changed state.
875 * @return
877 void AccObjectWinManager::DecreaseState( XAccessible* pXAcc,unsigned short pState )
879 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
880 if( pAccObj )
881 pAccObj->DecreaseState( pState );
885 * state is a combination integer, each bit of which represents a single state,such as focused,1 for
886 * the state on,0 for the state off. Here call COM interface to modify the state value, including
887 * IncreaseState.
888 * @param pXAcc XAccessible interface.
889 * @param pState Changed state.
890 * @return
892 void AccObjectWinManager::IncreaseState( XAccessible* pXAcc,unsigned short pState )
894 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
895 if( pAccObj )
896 pAccObj->IncreaseState( pState );
899 void AccObjectWinManager::UpdateState( css::accessibility::XAccessible* pXAcc )
901 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
902 if( pAccObj )
903 pAccObj->UpdateState( );
907 * Set corresponding com object's accessible name via XAccessible interface and new
908 * name
909 * @param pXAcc XAccessible interface.
910 * @return
912 void AccObjectWinManager::UpdateAccName( XAccessible* pXAcc )
914 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
915 if( pAccObj )
916 pAccObj->UpdateName();
919 void AccObjectWinManager::UpdateAction( XAccessible* pXAcc )
921 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
922 if( pAccObj )
923 pAccObj->UpdateAction();
926 void AccObjectWinManager::UpdateDescription( XAccessible* pXAcc )
928 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
929 if ( pAccObj )
930 pAccObj->UpdateDescription();
934 * Set corresponding com object's accessible location via XAccessible interface and new
935 * location.
936 * @param pXAcc XAccessible interface.
937 * @return
939 void AccObjectWinManager::SetLocation( XAccessible* pXAcc, long /*top*/, long /*left*/, long /*width*/, long /*height*/ )
941 AccObject* pObj = GetAccObjByXAcc( pXAcc );
942 //get the location from XComponent.
943 Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext();
944 if( pObj )
945 pObj->UpdateLocation();
949 * Set corresponding com object's value via XAccessible interface and new value.
950 * @param pXAcc XAccessible interface.
951 * @param pAny new value.
952 * @return
954 void AccObjectWinManager::SetValue( XAccessible* pXAcc, Any pAny )
956 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
957 if( pAccObj )
958 pAccObj->SetValue( pAny );
962 * Set corresponding com object's value via XAccessible interface.
963 * @param pXAcc XAccessible interface.
964 * @return
966 void AccObjectWinManager::UpdateValue( XAccessible* pXAcc )
968 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
969 if( pAccObj )
970 pAccObj->UpdateValue();
974 * Set corresponding com object's name via XAccessible interface and new name.
975 * @param pXAcc XAccessible interface.
976 * @param newName new name
977 * @return
979 void AccObjectWinManager::SetAccName( XAccessible* pXAcc, Any newName)
981 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
982 if( pAccObj )
983 pAccObj->SetName( newName );
987 * Set corresponding com object's description via XAccessible interface and new description.
988 * @param pXAcc XAccessible interface.
989 * @param newDesc new description
990 * @return
992 void AccObjectWinManager::SetDescription( XAccessible* pXAcc, Any newDesc )
994 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
995 if( pAccObj )
996 pAccObj->SetDescription( newDesc );
1000 * Set corresponding com object's role via XAccessible interface and new role.
1001 * @param pXAcc XAccessible interface.
1002 * @param Role new role
1003 * @return
1005 void AccObjectWinManager::SetRole( XAccessible* pXAcc, long Role )
1007 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1008 if( pAccObj )
1009 pAccObj->SetRole( static_cast<short>(Role) );
1013 * Judge if a XAccessible object is a container object.
1014 * @param pAccessible XAccessible interface.
1015 * @return If XAccessible object is container.
1017 bool AccObjectWinManager::IsContainer(XAccessible* pAccessible)
1021 if(pAccessible)
1023 Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
1024 if(xContext.is())
1026 switch( xContext->getAccessibleRole() )
1028 case /*AccessibleRole::*/DIALOG:
1029 case /*AccessibleRole::*/FRAME:
1030 case /*AccessibleRole::*/WINDOW:
1031 case /*AccessibleRole::*/ROOT_PANE:
1032 case /*AccessibleRole::*/CANVAS:
1033 case /*AccessibleRole::*/COMBO_BOX:
1034 case /*AccessibleRole::*/DOCUMENT:
1035 case /*AccessibleRole::*/DOCUMENT_PRESENTATION:
1036 case /*AccessibleRole::*/DOCUMENT_SPREADSHEET:
1037 case /*AccessibleRole::*/DOCUMENT_TEXT:
1038 case /*AccessibleRole::*/EMBEDDED_OBJECT:
1039 case /*AccessibleRole::*/END_NOTE:
1040 case /*AccessibleRole::*/FILLER:
1041 case /*AccessibleRole::*/FOOTNOTE:
1042 case /*AccessibleRole::*/FOOTER:
1043 case /*AccessibleRole::*/GRAPHIC:
1044 case /*AccessibleRole::*/GROUP_BOX:
1045 case /*AccessibleRole::*/HEADER:
1046 case /*AccessibleRole::*/LAYERED_PANE:
1047 case /*AccessibleRole::*/MENU_BAR:
1048 case /*AccessibleRole::*/POPUP_MENU:
1049 case /*AccessibleRole::*/OPTION_PANE:
1050 case /*AccessibleRole::*/PAGE_TAB:
1051 case /*AccessibleRole::*/PAGE_TAB_LIST:
1052 case /*AccessibleRole::*/PANEL:
1053 case /*AccessibleRole::*/SCROLL_PANE:
1054 case /*AccessibleRole::*/SPLIT_PANE:
1055 case /*AccessibleRole::*/STATUS_BAR:
1056 case /*AccessibleRole::*/TABLE_CELL:
1057 case /*AccessibleRole::*/TEXT_FRAME:
1058 case /*AccessibleRole::*/TOOL_BAR:
1059 case /*AccessibleRole::*/VIEW_PORT:
1060 case /*AccessibleRole::*/SHAPE:
1061 return true;
1062 break;
1063 case /*AccessibleRole::*/COLUMN_HEADER:
1064 case /*AccessibleRole::*/TABLE:
1065 if(!IsStateManageDescendant(pAccessible))
1066 return true;
1067 break;
1068 case /*AccessibleRole::*/MENU:
1069 return true;
1070 break;
1071 default:
1072 return false;
1077 catch(...)
1079 return false;
1081 return false;
1085 * Judge if a XAccessible object has ManageDescendant event.
1086 * @param pAccessible XAccessible interface.
1087 * @return If XAccessible object is managedescendant.
1089 bool AccObjectWinManager::IsStateManageDescendant(XAccessible* pAccessible)
1091 if(pAccessible)
1093 Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
1094 if(xContext.is())
1096 Reference< XAccessibleStateSet > pRState = xContext->getAccessibleStateSet();
1097 if( !pRState.is() )
1098 return false;
1100 Sequence<short> pStates = pRState->getStates();
1101 int count = pStates.getLength();
1102 for( int iIndex = 0;iIndex < count;iIndex++ )
1104 if(pStates[iIndex] == /*AccessibleStateType::*/MANAGES_DESCENDANTS)
1105 return true;
1109 return false;
1113 * Query and get IAccessible interface by XAccessible interface from list.
1114 * @param pXAcc XAccessible interface.
1115 * @return Com accobject interface.
1117 IMAccessible* AccObjectWinManager::GetIMAccByXAcc(XAccessible* pXAcc)
1119 AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
1120 if(pAccObj)
1122 return pAccObj->GetIMAccessible();
1124 else
1126 return nullptr;
1131 * Query and get IAccessible interface by child id from list.
1132 * @param resID, childID.
1133 * @return Com accobject interface.
1135 IMAccessible * AccObjectWinManager::GetIAccessibleFromResID(long resID)
1137 XResIdToAccObjHash::iterator pIndTemp = XResIdAccList.find( resID );
1138 if ( pIndTemp == XResIdAccList.end() )
1139 return nullptr;
1141 AccObject* pObj = pIndTemp->second;
1143 if(pObj->GetIMAccessible())
1144 return pObj->GetIMAccessible();
1145 return nullptr;
1148 * Notify some object will be destroyed.
1149 * @param pXAcc XAccessible interface.
1150 * @return Com accobject interface.
1152 void AccObjectWinManager::NotifyDestroy(XAccessible* pXAcc)
1154 AccObject* accObj = GetAccObjByXAcc(pXAcc);
1155 if(accObj)
1157 accObj->NotifyDestroy(true);
1162 void AccObjectWinManager::UpdateChildState(css::accessibility::XAccessible* pAccSubMenu)
1164 Reference<css::accessibility::XAccessibleContext> xContext(pAccSubMenu,UNO_QUERY);
1165 if (!xContext.is())
1167 return;
1169 sal_Int32 nCount = xContext->getAccessibleChildCount();
1170 for (sal_Int32 i = 0 ; i < nCount ; ++i)
1172 Reference<css::accessibility::XAccessible> xChild = xContext->getAccessibleChild(i);
1173 if (xChild.is())
1175 AccObject *pObj = GetAccObjByXAcc(xChild.get());
1176 if (pObj)
1178 pObj->UpdateState();
1185 bool AccObjectWinManager::IsSpecialToolboItem(css::accessibility::XAccessible* pXAcc)
1187 if (pXAcc && oldFocus != pXAcc)
1189 if(GetParentRole(pXAcc) == TOOL_BAR)
1191 Reference< XAccessibleContext > pRContext(pXAcc->getAccessibleContext());
1192 if (pRContext.is())
1194 if(pRContext->getAccessibleRole() == TOGGLE_BUTTON)
1196 return true;
1201 return false;
1204 short AccObjectWinManager::GetRole(css::accessibility::XAccessible* pXAcc)
1206 assert(pXAcc != nullptr);
1207 Reference<css::accessibility::XAccessibleContext> xContext = pXAcc->getAccessibleContext();
1208 if(xContext.is())
1210 return xContext->getAccessibleRole();
1212 return -1;
1215 XAccessible* AccObjectWinManager::GetAccDocByHWND(HWND pWnd)
1217 XHWNDToDocumentHash::iterator aIter;
1218 aIter = XHWNDDocList.find( pWnd );
1219 if ( aIter != XHWNDDocList.end() )
1221 return aIter->second;
1224 return nullptr;
1227 XAccessible* AccObjectWinManager::GetAccDocByAccTopWin( XAccessible* pXAcc )
1229 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1230 HWND hWnd = pAccObj->GetParentHWND();
1231 return GetAccDocByHWND(hWnd);
1234 bool AccObjectWinManager::IsTopWinAcc( css::accessibility::XAccessible* pXAcc )
1236 bool bRet = false;
1237 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1238 if ( pAccObj )
1240 bRet = ( pAccObj->GetParentObj() == nullptr );
1242 return bRet;
1244 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */