Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / winaccessibility / source / service / AccObjectWinManager.cxx
blobc8e5c7ac936b94ea27959dadc9fdf3d540691ecc
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/XAccessible.hpp>
23 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
24 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
25 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
26 #include <com/sun/star/accessibility/AccessibleRole.hpp>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
29 #include <oleacc.h>
30 #include <AccObjectWinManager.hxx>
31 #include <AccEventListener.hxx>
32 #include <AccComponentEventListener.hxx>
33 #include <AccContainerEventListener.hxx>
34 #include <AccDialogEventListener.hxx>
35 #include <AccWindowEventListener.hxx>
36 #include <AccFrameEventListener.hxx>
37 #include <AccMenuEventListener.hxx>
38 #include <AccObjectContainerEventListener.hxx>
39 #include <AccParagraphEventListener.hxx>
40 #include <AccTextComponentEventListener.hxx>
41 #include <AccListEventListener.hxx>
42 #include <AccTreeEventListener.hxx>
43 #include <AccTableEventListener.hxx>
44 #include <AccObject.hxx>
45 #include <unomsaaevent.hxx>
48 using namespace com::sun::star::accessibility;
49 using namespace com::sun::star::uno;
51 /**
52 * constructor
53 * @param Agent The agent kept in all listeners,it's the sole interface by which
54 * listener communicate with windows manager.
55 * pEventAccObj The present event accobject.
56 * oldFocus Last focused object.
57 * isSelectionChanged flag that identifies if there is selection changed.
58 * selectionChildObj Selected object.
59 * dChildID Chile resource ID.
60 * hAcc TopWindowHWND
61 * @return
63 AccObjectWinManager::AccObjectWinManager( AccObjectManagerAgent* Agent ):
64 oldFocus( nullptr ),
65 pAgent( Agent )
69 /**
70 * Destructor,clear all resource.
71 * @param
72 * @return
74 AccObjectWinManager::~AccObjectWinManager()
77 std::scoped_lock l(m_Mutex);
79 XIdAccList.clear();
80 HwndXAcc.clear();
82 XResIdAccList.clear();
83 XHWNDDocList.clear();
87 /**
88 * Get valid com object interface when notifying some MSAA event
89 * @param pWND The top window handle that contains that event control.
90 * @param wParam Windows system interface.
91 * @return Com interface with event.
94 LRESULT
95 AccObjectWinManager::Get_ToATInterface(HWND hWnd, long lParam, WPARAM wParam)
97 IMAccessible* pRetIMAcc = nullptr;
99 if(lParam == OBJID_CLIENT )
101 pRetIMAcc = GetTopWindowIMAccessible(hWnd);
104 if ( pRetIMAcc && lParam == OBJID_CLIENT )
106 LRESULT result = LresultFromObject(IID_IAccessible, wParam, pRetIMAcc);
107 pRetIMAcc->Release();
108 return result;
110 return 0;
114 * Search AccObject by XAccessible pointer from our container.
115 * @param pXAcc XAccessible interface.
116 * @return Pointer of accObject that is found.
118 AccObject* AccObjectWinManager::GetAccObjByXAcc( XAccessible* pXAcc)
120 if( pXAcc == nullptr)
121 return nullptr;
123 std::scoped_lock l(m_Mutex);
125 XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
126 if ( pIndTemp == XIdAccList.end() )
127 return nullptr;
129 return &(pIndTemp->second);
133 * get acc object of top window by its handle
134 * @param hWnd, top window handle
135 * @return pointer to AccObject
137 IMAccessible * AccObjectWinManager::GetTopWindowIMAccessible(HWND hWnd)
139 std::scoped_lock l(m_Mutex); // tdf#155794 for HwndXAcc and XIdAccList
141 XHWNDToXAccHash::iterator iterResult =HwndXAcc.find(hWnd);
142 if(iterResult == HwndXAcc.end())
143 return nullptr;
144 XAccessible* pXAcc = iterResult->second;
145 AccObject *const pAccObject(GetAccObjByXAcc(pXAcc));
146 if (!pAccObject)
148 return nullptr;
150 IMAccessible *const pRet(pAccObject->GetIMAccessible());
151 if (!pRet)
153 return nullptr;
155 pRet->AddRef();
156 return pRet;
160 * Simulate MSAA event via XAccessible interface and event type.
161 * @param pXAcc XAccessible interface.
162 * @param eEvent event type
163 * @return The terminate result that identifies if the call is successful.
165 bool AccObjectWinManager::NotifyAccEvent(XAccessible* pXAcc, UnoMSAAEvent eEvent)
167 Reference< XAccessibleContext > pRContext;
169 if( pXAcc == nullptr)
170 return false;
173 pRContext = pXAcc->getAccessibleContext();
174 if( !pRContext.is() )
175 return false;
178 AccObject* selfAccObj= GetAccObjByXAcc(pXAcc);
180 if(selfAccObj==nullptr)
181 return false;
183 long dChildID = selfAccObj->GetResID();
184 HWND hAcc = selfAccObj->GetParentHWND();
186 switch(eEvent)
188 case UnoMSAAEvent::STATE_FOCUSED:
190 UpdateAccFocus(pXAcc);
191 selfAccObj->UpdateDefaultAction( );
192 UpdateValue(pXAcc);
193 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
194 break;
196 case UnoMSAAEvent::STATE_BUSY:
197 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
198 break;
199 case UnoMSAAEvent::STATE_CHECKED:
200 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
201 break;
202 case UnoMSAAEvent::STATE_PRESSED:
203 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
204 break;
206 //Removed fire out selected event
207 //case UnoMSAAEvent::STATE_SELECTED:
208 // NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
209 // break;
210 case UnoMSAAEvent::STATE_ARMED:
211 UpdateAccFocus(pXAcc);
212 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
213 break;
214 case UnoMSAAEvent::STATE_SHOWING:
215 // send EVENT_SYSTEM_ALERT when notification gets shown
216 if (pRContext->getAccessibleRole() == AccessibleRole::NOTIFICATION)
217 NotifyWinEvent(EVENT_SYSTEM_ALERT, hAcc, OBJID_CLIENT, dChildID);
218 break;
219 case UnoMSAAEvent::MENU_START:
220 NotifyWinEvent( EVENT_SYSTEM_MENUSTART,hAcc, OBJID_CLIENT,dChildID );
221 break;
222 case UnoMSAAEvent::MENU_END:
223 NotifyWinEvent( EVENT_SYSTEM_MENUEND,hAcc, OBJID_CLIENT,dChildID );
224 break;
225 case UnoMSAAEvent::MENUPOPUPSTART:
226 NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPSTART,hAcc, OBJID_CLIENT,dChildID );
227 break;
228 case UnoMSAAEvent::MENUPOPUPEND:
229 NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPEND,hAcc, OBJID_CLIENT,dChildID );
230 break;
231 case UnoMSAAEvent::SELECTION_CHANGED:
232 NotifyWinEvent( EVENT_OBJECT_SELECTION,hAcc, OBJID_CLIENT,dChildID );
233 break;
234 case UnoMSAAEvent::SELECTION_CHANGED_ADD:
235 NotifyWinEvent( EVENT_OBJECT_SELECTIONADD,hAcc, OBJID_CLIENT,dChildID );
236 break;
237 case UnoMSAAEvent::SELECTION_CHANGED_REMOVE:
238 NotifyWinEvent( EVENT_OBJECT_SELECTIONREMOVE,hAcc, OBJID_CLIENT,dChildID );
239 break;
240 case UnoMSAAEvent::SELECTION_CHANGED_WITHIN:
241 NotifyWinEvent( EVENT_OBJECT_SELECTIONWITHIN,hAcc, OBJID_CLIENT,dChildID );
242 break;
243 case UnoMSAAEvent::OBJECT_VALUECHANGE:
244 UpdateValue(pXAcc);
245 NotifyWinEvent( EVENT_OBJECT_VALUECHANGE,hAcc, OBJID_CLIENT,dChildID );
246 break;
247 case UnoMSAAEvent::OBJECT_NAMECHANGE:
248 NotifyWinEvent( EVENT_OBJECT_NAMECHANGE,hAcc, OBJID_CLIENT,dChildID );
249 break;
250 case UnoMSAAEvent::OBJECT_DESCRIPTIONCHANGE:
251 NotifyWinEvent( EVENT_OBJECT_DESCRIPTIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
252 break;
253 case UnoMSAAEvent::OBJECT_DEFACTIONCHANGE:
254 NotifyWinEvent( IA2_EVENT_ACTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
255 break;
256 case UnoMSAAEvent::OBJECT_CARETCHANGE:
257 NotifyWinEvent( IA2_EVENT_TEXT_CARET_MOVED,hAcc, OBJID_CLIENT,dChildID );
258 break;
259 case UnoMSAAEvent::OBJECT_TEXTCHANGE:
260 NotifyWinEvent( IA2_EVENT_TEXT_CHANGED,hAcc, OBJID_CLIENT,dChildID );
261 break;
262 case UnoMSAAEvent::ACTIVE_DESCENDANT_CHANGED:
263 UpdateAccFocus(pXAcc);
264 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
265 break;
266 case UnoMSAAEvent::BOUNDRECT_CHANGED:
267 NotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
268 break;
269 case UnoMSAAEvent::VISIBLE_DATA_CHANGED:
270 NotifyWinEvent( IA2_EVENT_VISIBLE_DATA_CHANGED,hAcc, OBJID_CLIENT,dChildID );
271 break;
272 case UnoMSAAEvent::SHOW :
273 NotifyWinEvent( EVENT_OBJECT_SHOW,hAcc, OBJID_CLIENT,dChildID );
274 NotifyWinEvent( EVENT_SYSTEM_FOREGROUND,hAcc, OBJID_CLIENT,dChildID );
275 break;
276 case UnoMSAAEvent::TABLE_CAPTION_CHANGED:
277 NotifyWinEvent( IA2_EVENT_TABLE_CAPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
278 break;
279 case UnoMSAAEvent::TABLE_COLUMN_DESCRIPTION_CHANGED:
280 NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
281 break;
282 case UnoMSAAEvent::TABLE_COLUMN_HEADER_CHANGED:
283 NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
284 break;
285 case UnoMSAAEvent::TABLE_MODEL_CHANGED:
286 NotifyWinEvent( IA2_EVENT_TABLE_MODEL_CHANGED,hAcc, OBJID_CLIENT,dChildID );
287 break;
288 case UnoMSAAEvent::TABLE_ROW_HEADER_CHANGED:
289 NotifyWinEvent( IA2_EVENT_TABLE_ROW_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
290 break;
291 case UnoMSAAEvent::TABLE_SUMMARY_CHANGED:
292 NotifyWinEvent( IA2_EVENT_TABLE_SUMMARY_CHANGED,hAcc, OBJID_CLIENT,dChildID );
293 break;
294 case UnoMSAAEvent::TABLE_ROW_DESCRIPTION_CHANGED:
295 NotifyWinEvent( IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
296 break;
297 case UnoMSAAEvent::OBJECT_REORDER:
298 NotifyWinEvent( EVENT_OBJECT_REORDER,hAcc, OBJID_CLIENT,dChildID );
299 break;
300 case UnoMSAAEvent::PAGE_CHANGED:
301 NotifyWinEvent( IA2_EVENT_PAGE_CHANGED,hAcc, OBJID_CLIENT,dChildID );
302 break;
303 case UnoMSAAEvent::CHILD_REMOVED:
304 NotifyWinEvent( EVENT_OBJECT_DESTROY,hAcc, OBJID_CLIENT,dChildID );
305 break;
306 case UnoMSAAEvent::CHILD_ADDED:
307 NotifyWinEvent( EVENT_OBJECT_CREATE ,hAcc, OBJID_CLIENT,dChildID );
308 break;
309 case UnoMSAAEvent::OBJECT_PAGECHANGED:
310 NotifyWinEvent( IA2_EVENT_PAGE_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
311 break;
312 case UnoMSAAEvent::TEXT_SELECTION_CHANGED:
313 NotifyWinEvent( IA2_EVENT_TEXT_SELECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
314 break;
315 case UnoMSAAEvent::SECTION_CHANGED:
316 NotifyWinEvent( IA2_EVENT_SECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
317 break;
318 case UnoMSAAEvent::COLUMN_CHANGED:
319 NotifyWinEvent( IA2_EVENT_TEXT_COLUMN_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
320 break;
321 default:
322 break;
325 return true;
329 * Get Parent XAccessible interface by XAccessible interface.
330 * @param pXAcc XAccessible interface.
331 * @return Parent XAccessible interface.
333 XAccessible* AccObjectWinManager::GetParentXAccessible( XAccessible* pXAcc )
335 AccObject* pObj= GetAccObjByXAcc(pXAcc);
336 if( pObj ==nullptr )
337 return nullptr;
338 if(pObj->GetParentObj())
340 pObj = pObj->GetParentObj();
341 return pObj->GetXAccessible().get();
343 return nullptr;
347 * Get Parent role by XAccessible interface.
348 * @param pXAcc XAccessible interface.
349 * @return Parent role.
351 short AccObjectWinManager::GetParentRole( XAccessible* pXAcc )
353 AccObject* pObj= GetAccObjByXAcc(pXAcc);
354 if( pObj ==nullptr )
355 return -1;
356 if(pObj->GetParentObj())
358 pObj = pObj->GetParentObj();
359 if(pObj->GetXAccessible().is())
361 Reference< XAccessibleContext > pRContext = pObj->GetXAccessible()->getAccessibleContext();
362 if(pRContext.is())
363 return pRContext->getAccessibleRole();
366 return -1;
370 * Update focus object by new focused XAccessible interface.
371 * @param newFocus New XAccessible interface that gets focus.
372 * @return
374 void AccObjectWinManager::UpdateAccFocus(XAccessible* newFocus)
376 AccObject* pAccObjNew = GetAccObjByXAcc(newFocus);
377 if(pAccObjNew)
379 AccObject* pAccObjOld = GetAccObjByXAcc(oldFocus);
380 oldFocus = newFocus;
381 pAccObjNew->setFocus();
382 //if old == new, the pAccObjNew will be without focused state
383 if (pAccObjOld && pAccObjOld != pAccObjNew)
384 pAccObjOld->unsetFocus();
389 * Delete child element from children list.
390 * @param pObj Child element that should be removed from parent child list.
391 * @return
393 void AccObjectWinManager::DeleteAccChildNode( AccObject* pObj )
395 AccObject *parentAccObj = pObj->GetParentObj();
396 if( parentAccObj )
397 parentAccObj->DeleteChild( pObj );
401 * Delete XAccessible items in top window handle hashtable
402 * @param pXAcc XAccessible interface.
403 * @return
405 void AccObjectWinManager::DeleteFromHwndXAcc(XAccessible const * pXAcc )
407 std::scoped_lock l(m_Mutex);
409 auto iter = std::find_if(HwndXAcc.begin(), HwndXAcc.end(),
410 [&pXAcc](XHWNDToXAccHash::value_type& rEntry) { return rEntry.second == pXAcc; });
411 if (iter != HwndXAcc.end())
412 HwndXAcc.erase(iter);
416 * Delete all children with the tree root of XAccessible pointer
417 * @param pXAcc Tree root XAccessible interface.
418 * @return
420 void AccObjectWinManager::DeleteChildrenAccObj(XAccessible* pXAcc)
422 AccObject* currentObj=nullptr;
423 AccObject* childObj=nullptr;
425 currentObj = GetAccObjByXAcc( pXAcc);
426 if(currentObj)
428 childObj = currentObj->NextChild();
429 while(childObj)
431 XAccessible *const pTmpXAcc = childObj->GetXAccessible().get();
432 if(pTmpXAcc)
434 DeleteChildrenAccObj(pTmpXAcc);
435 DeleteAccObj(pTmpXAcc);
437 childObj = currentObj->NextChild();
443 * Delete Acc object self.
444 * @param pXAcc The XAccessible interface.
445 * @return
447 void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
449 if( pXAcc == nullptr )
450 return;
452 rtl::Reference<AccEventListener> pListener;
455 std::scoped_lock l(m_Mutex);
457 XIdToAccObjHash::iterator temp = XIdAccList.find(pXAcc);
458 if( temp != XIdAccList.end() )
460 ResIdGen.SetSub( temp->second.GetResID() );
462 else
464 return;
467 AccObject& accObj = temp->second;
468 DeleteAccChildNode( &accObj );
469 pListener = DeleteAccListener(&accObj);
470 accObj.NotifyDestroy();
471 if( accObj.GetIMAccessible() )
473 accObj.GetIMAccessible()->Release();
475 size_t i = XResIdAccList.erase(accObj.GetResID());
476 assert(i != 0);
477 (void) i;
478 DeleteFromHwndXAcc(pXAcc);
479 if (accObj.GetRole() == AccessibleRole::DOCUMENT ||
480 accObj.GetRole() == AccessibleRole::DOCUMENT_PRESENTATION ||
481 accObj.GetRole() == AccessibleRole::DOCUMENT_SPREADSHEET ||
482 accObj.GetRole() == AccessibleRole::DOCUMENT_TEXT)
484 XHWNDDocList.erase(accObj.GetParentHWND());
486 XIdAccList.erase(pXAcc); // note: this invalidates accObj so do it last!
488 if (pListener)
490 pListener->RemoveMeFromBroadcaster(false);
495 * Delete listener that inspects some XAccessible object
496 * @param pAccObj Accobject pointer.
497 * @return
499 rtl::Reference<AccEventListener> AccObjectWinManager::DeleteAccListener( AccObject* pAccObj )
501 return pAccObj->SetListener(nullptr);
505 * Generate a child ID, which is used for AT
506 * @param
507 * @return New resource ID.
509 inline long AccObjectWinManager::ImpleGenerateResID()
511 return ResIdGen.GenerateNewResID();
515 * Insert all children of the current acc object
516 * @param pXAcc XAccessible interface
517 * @param pWnd Top Window handle
518 * @return The calling result.
520 bool AccObjectWinManager::InsertChildrenAccObj( css::accessibility::XAccessible* pXAcc,
521 HWND pWnd)
523 if(!IsContainer(pXAcc))
524 return false;
526 Reference< XAccessibleContext > pRContext;
528 if( pXAcc == nullptr)
529 return false;
530 pRContext = pXAcc->getAccessibleContext();
531 if( !pRContext.is() )
532 return false;
534 short role = pRContext->getAccessibleRole();
536 if(css::accessibility::AccessibleRole::DOCUMENT == role ||
537 css::accessibility::AccessibleRole::DOCUMENT_PRESENTATION == role ||
538 css::accessibility::AccessibleRole::DOCUMENT_SPREADSHEET == role ||
539 css::accessibility::AccessibleRole::DOCUMENT_TEXT == role)
541 if(IsStateManageDescendant(pXAcc))
543 return true;
547 const sal_Int64 nCount = pRContext->getAccessibleChildCount();
548 for (sal_Int64 i = 0; i < nCount; i++)
550 Reference<XAccessible> mxAccessible
551 = pRContext->getAccessibleChild(i);
552 XAccessible* mpAccessible = mxAccessible.get();
553 if(mpAccessible != nullptr)
555 InsertAccObj( mpAccessible,pXAcc,pWnd );
556 InsertChildrenAccObj(mpAccessible,pWnd);
560 return true;
564 * Insert child object.
565 * @param pCurObj The child object
566 * @param pParentObj The parent object
567 * @param pWnd Top window handle.
568 * @return
570 void AccObjectWinManager::InsertAccChildNode( AccObject* pCurObj, AccObject* pParentObj, HWND /* pWnd */ )
572 if(pCurObj)
574 if(pParentObj)
576 pParentObj->InsertChild(pCurObj);
578 else
580 pCurObj->UpdateValidWindow();
586 * Insert child object.
587 * @param pCurObj The child object
588 * @param pParentObj The parent object
589 * @param pWnd Top window handle.
590 * @return
592 bool AccObjectWinManager::InsertAccObj( XAccessible* pXAcc,XAccessible* pParentXAcc,HWND pWnd )
594 Reference< XAccessibleContext > pRContext;
596 if( pXAcc == nullptr)
597 return false;
599 pRContext = pXAcc->getAccessibleContext();
600 if( !pRContext.is() )
601 return false;
604 short nCurRole = GetRole(pXAcc);
606 std::scoped_lock l(m_Mutex);
608 XIdToAccObjHash::iterator itXacc = XIdAccList.find( pXAcc );
609 if (itXacc != XIdAccList.end() )
611 if (AccessibleRole::SHAPE == nCurRole)
613 AccObject &objXacc = itXacc->second;
614 AccObject *pObjParent = objXacc.GetParentObj();
615 if (pObjParent &&
616 pObjParent->GetXAccessible().is() &&
617 pObjParent->GetXAccessible().get() != pParentXAcc)
619 XIdToAccObjHash::iterator itXaccParent = XIdAccList.find( pParentXAcc );
620 if(itXaccParent != XIdAccList.end())
622 objXacc.SetParentObj(&(itXaccParent->second));
626 return false;
630 if( pWnd == nullptr )
632 if(pParentXAcc)
634 AccObject* pObj = GetAccObjByXAcc(pParentXAcc);
635 if(pObj)
636 pWnd = pObj->GetParentHWND();
638 if( pWnd == nullptr )
639 return false;
642 AccObject pObj( pXAcc,pAgent );
643 if( pObj.GetIMAccessible() == nullptr )
644 return false;
645 pObj.SetResID( this->ImpleGenerateResID());
646 pObj.SetParentHWND( pWnd );
648 //for file name support
649 if (pObj.GetRole() == AccessibleRole::DOCUMENT ||
650 pObj.GetRole() == AccessibleRole::DOCUMENT_PRESENTATION ||
651 pObj.GetRole() == AccessibleRole::DOCUMENT_SPREADSHEET ||
652 pObj.GetRole() == AccessibleRole::DOCUMENT_TEXT)
654 XHWNDToDocumentHash::iterator aIter = XHWNDDocList.find(pWnd);
655 if ( aIter != XHWNDDocList.end() )
657 XHWNDDocList.erase( aIter );
659 XHWNDDocList.emplace( pWnd, pXAcc );
661 //end of file name
663 ::rtl::Reference<AccEventListener> const pListener =
664 CreateAccEventListener(pXAcc);
665 if (!pListener.is())
666 return false;
667 Reference<XAccessibleComponent> xComponent(pRContext,UNO_QUERY);
668 Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
669 if (broadcaster.is())
671 Reference<XAccessibleEventListener> const xListener(pListener);
672 broadcaster->addAccessibleEventListener(xListener);
674 else
675 return false;
678 std::scoped_lock l(m_Mutex);
680 XIdAccList.emplace(pXAcc, pObj);
681 XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
682 XResIdAccList.emplace(pObj.GetResID(),&(pIndTemp->second));
685 AccObject* pCurObj = GetAccObjByXAcc(pXAcc);
686 if( pCurObj )
688 pCurObj->SetListener(pListener);
691 AccObject* pParentObj = GetAccObjByXAcc(pParentXAcc);
692 InsertAccChildNode(pCurObj,pParentObj,pWnd);
693 if( pCurObj )
694 pCurObj->UpdateAccessibleInfoFromUnoToMSAA();
695 return true;
700 * save the pair <topwindowhandle, XAccessible>
701 * @param hWnd, top window handle
702 * @param pXAcc XAccessible interface for top window
703 * @return void
705 void AccObjectWinManager::SaveTopWindowHandle(HWND hWnd, css::accessibility::XAccessible* pXAcc)
707 std::scoped_lock l(m_Mutex);
709 HwndXAcc.emplace(hWnd,pXAcc);
713 /** Create the corresponding listener.
714 * @param pXAcc XAccessible interface.
716 ::rtl::Reference<AccEventListener>
717 AccObjectWinManager::CreateAccEventListener(XAccessible* pXAcc)
719 ::rtl::Reference<AccEventListener> pRet;
720 Reference<XAccessibleContext> xContext = pXAcc->getAccessibleContext();
721 if(xContext.is())
723 switch( xContext->getAccessibleRole() )
725 case AccessibleRole::DIALOG:
726 pRet = new AccDialogEventListener(pXAcc,pAgent);
727 break;
728 case AccessibleRole::FRAME:
729 pRet = new AccFrameEventListener(pXAcc,pAgent);
730 break;
731 case AccessibleRole::WINDOW:
732 pRet = new AccWindowEventListener(pXAcc,pAgent);
733 break;
734 case AccessibleRole::ROOT_PANE:
735 pRet = new AccFrameEventListener(pXAcc,pAgent);
736 break;
737 //Container
738 case AccessibleRole::CANVAS:
739 case AccessibleRole::COMBO_BOX:
740 case AccessibleRole::DOCUMENT:
741 case AccessibleRole::DOCUMENT_PRESENTATION:
742 case AccessibleRole::DOCUMENT_SPREADSHEET:
743 case AccessibleRole::DOCUMENT_TEXT:
744 case AccessibleRole::END_NOTE:
745 case AccessibleRole::FILLER:
746 case AccessibleRole::FOOTNOTE:
747 case AccessibleRole::FOOTER:
748 case AccessibleRole::HEADER:
749 case AccessibleRole::LAYERED_PANE:
750 case AccessibleRole::MENU_BAR:
751 case AccessibleRole::POPUP_MENU:
752 case AccessibleRole::OPTION_PANE:
753 case AccessibleRole::PAGE_TAB:
754 case AccessibleRole::PAGE_TAB_LIST:
755 case AccessibleRole::PANEL:
756 case AccessibleRole::SCROLL_PANE:
757 case AccessibleRole::SPLIT_PANE:
758 case AccessibleRole::STATUS_BAR:
759 case AccessibleRole::TABLE_CELL:
760 case AccessibleRole::TOOL_BAR:
761 case AccessibleRole::VIEW_PORT:
762 pRet = new AccContainerEventListener(pXAcc,pAgent);
763 break;
764 case AccessibleRole::PARAGRAPH:
765 case AccessibleRole::HEADING:
766 pRet = new AccParagraphEventListener(pXAcc,pAgent);
767 break;
768 //Component
769 case AccessibleRole::CHECK_BOX:
770 case AccessibleRole::ICON:
771 case AccessibleRole::LABEL:
772 case AccessibleRole::STATIC:
773 case AccessibleRole::NOTIFICATION:
774 case AccessibleRole::MENU_ITEM:
775 case AccessibleRole::CHECK_MENU_ITEM:
776 case AccessibleRole::RADIO_MENU_ITEM:
777 case AccessibleRole::PUSH_BUTTON:
778 case AccessibleRole::RADIO_BUTTON:
779 case AccessibleRole::SCROLL_BAR:
780 case AccessibleRole::SEPARATOR:
781 case AccessibleRole::TOGGLE_BUTTON:
782 case AccessibleRole::BUTTON_DROPDOWN:
783 case AccessibleRole::TOOL_TIP:
784 case AccessibleRole::SPIN_BOX:
785 case AccessibleRole::DATE_EDITOR:
786 pRet = new AccComponentEventListener(pXAcc,pAgent);
787 break;
788 //text component
789 case AccessibleRole::TEXT:
790 pRet = new AccTextComponentEventListener(pXAcc,pAgent);
791 break;
792 //menu
793 case AccessibleRole::MENU:
794 pRet = new AccMenuEventListener(pXAcc,pAgent);
795 break;
796 //object container
797 case AccessibleRole::SHAPE:
799 case AccessibleRole::EMBEDDED_OBJECT:
800 case AccessibleRole::GRAPHIC:
801 case AccessibleRole::TEXT_FRAME:
802 pRet = new AccObjectContainerEventListener(pXAcc,pAgent);
803 break;
804 //descendmanager
805 case AccessibleRole::LIST:
806 pRet = new AccListEventListener(pXAcc,pAgent);
807 break;
808 case AccessibleRole::TREE:
809 pRet = new AccTreeEventListener(pXAcc,pAgent);
810 break;
811 //special
812 case AccessibleRole::COLUMN_HEADER:
813 case AccessibleRole::TABLE:
814 pRet = new AccTableEventListener(pXAcc,pAgent);
815 break;
816 default:
817 pRet = new AccContainerEventListener(pXAcc,pAgent);
818 break;
821 return pRet;
825 * state is a combination integer, each bit of which represents a single state,
826 * such as focused,1 for the state on,0 for the state off. Here call COM interface
827 * to modify the state value, including DecreaseState.
828 * @param pXAcc XAccessible interface.
829 * @param pState Changed state.
830 * @return
832 void AccObjectWinManager::DecreaseState(XAccessible* pXAcc, sal_Int64 nState)
834 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
835 if( pAccObj )
836 pAccObj->DecreaseState(nState);
840 * state is a combination integer, each bit of which represents a single state,such as focused,1 for
841 * the state on,0 for the state off. Here call COM interface to modify the state value, including
842 * IncreaseState.
843 * @param pXAcc XAccessible interface.
844 * @param pState Changed state.
845 * @return
847 void AccObjectWinManager::IncreaseState(XAccessible* pXAcc, sal_Int64 nState)
849 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
850 if( pAccObj )
851 pAccObj->IncreaseState(nState);
854 void AccObjectWinManager::UpdateState( css::accessibility::XAccessible* pXAcc )
856 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
857 if( pAccObj )
858 pAccObj->UpdateState( );
862 * Set corresponding com object's accessible name via XAccessible interface and new
863 * name
864 * @param pXAcc XAccessible interface.
865 * @return
867 void AccObjectWinManager::UpdateAccName( XAccessible* pXAcc )
869 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
870 if( pAccObj )
871 pAccObj->UpdateName();
874 void AccObjectWinManager::UpdateAction( XAccessible* pXAcc )
876 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
877 if( pAccObj )
878 pAccObj->UpdateAction();
882 * Set corresponding com object's value via XAccessible interface and new value.
883 * @param pXAcc XAccessible interface.
884 * @param pAny new value.
885 * @return
887 void AccObjectWinManager::SetValue( XAccessible* pXAcc, Any pAny )
889 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
890 if( pAccObj )
891 pAccObj->SetValue( pAny );
895 * Set corresponding com object's value via XAccessible interface.
896 * @param pXAcc XAccessible interface.
897 * @return
899 void AccObjectWinManager::UpdateValue( XAccessible* pXAcc )
901 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
902 if( pAccObj )
903 pAccObj->UpdateValue();
907 * Set corresponding com object's name via XAccessible interface and new name.
908 * @param pXAcc XAccessible interface.
909 * @param newName new name
910 * @return
912 void AccObjectWinManager::SetAccName( XAccessible* pXAcc, Any newName)
914 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
915 if( pAccObj )
916 pAccObj->SetName( newName );
920 * Judge if a XAccessible object is a container object.
921 * @param pAccessible XAccessible interface.
922 * @return If XAccessible object is container.
924 bool AccObjectWinManager::IsContainer(XAccessible* pAccessible)
928 if(pAccessible)
930 Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
931 if(xContext.is())
933 switch( xContext->getAccessibleRole() )
935 case AccessibleRole::DIALOG:
936 case AccessibleRole::FRAME:
937 case AccessibleRole::WINDOW:
938 case AccessibleRole::ROOT_PANE:
939 case AccessibleRole::CANVAS:
940 case AccessibleRole::COMBO_BOX:
941 case AccessibleRole::DOCUMENT:
942 case AccessibleRole::DOCUMENT_PRESENTATION:
943 case AccessibleRole::DOCUMENT_SPREADSHEET:
944 case AccessibleRole::DOCUMENT_TEXT:
945 case AccessibleRole::EMBEDDED_OBJECT:
946 case AccessibleRole::END_NOTE:
947 case AccessibleRole::FILLER:
948 case AccessibleRole::FOOTNOTE:
949 case AccessibleRole::FOOTER:
950 case AccessibleRole::GRAPHIC:
951 case AccessibleRole::GROUP_BOX:
952 case AccessibleRole::HEADER:
953 case AccessibleRole::LAYERED_PANE:
954 case AccessibleRole::MENU_BAR:
955 case AccessibleRole::POPUP_MENU:
956 case AccessibleRole::OPTION_PANE:
957 case AccessibleRole::PAGE_TAB:
958 case AccessibleRole::PAGE_TAB_LIST:
959 case AccessibleRole::PANEL:
960 case AccessibleRole::SCROLL_PANE:
961 case AccessibleRole::SPLIT_PANE:
962 case AccessibleRole::STATUS_BAR:
963 case AccessibleRole::TABLE_CELL:
964 case AccessibleRole::TEXT_FRAME:
965 case AccessibleRole::TOOL_BAR:
966 case AccessibleRole::VIEW_PORT:
967 case AccessibleRole::SHAPE:
968 return true;
969 case AccessibleRole::COLUMN_HEADER:
970 case AccessibleRole::TABLE:
971 if(!IsStateManageDescendant(pAccessible))
972 return true;
973 break;
974 case AccessibleRole::MENU:
975 return true;
976 default:
977 return false;
982 catch(...)
984 return false;
986 return false;
990 * Judge if a XAccessible object has ManageDescendant event.
991 * @param pAccessible XAccessible interface.
992 * @return If XAccessible object is managedescendant.
994 bool AccObjectWinManager::IsStateManageDescendant(XAccessible* pAccessible)
996 if(pAccessible)
998 Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
999 if(xContext.is())
1001 sal_Int64 nRState = xContext->getAccessibleStateSet();
1002 return nRState & AccessibleStateType::MANAGES_DESCENDANTS;
1005 return false;
1009 * Query and get IAccessible interface by XAccessible interface from list.
1010 * @param pXAcc XAccessible interface.
1011 * @return Com accobject interface.
1013 IMAccessible* AccObjectWinManager::GetIMAccByXAcc(XAccessible* pXAcc)
1015 AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
1016 if(pAccObj)
1018 return pAccObj->GetIMAccessible();
1020 else
1022 return nullptr;
1027 * Query and get IAccessible interface by child id from list.
1028 * @param resID, childID.
1029 * @return Com accobject interface.
1031 IMAccessible * AccObjectWinManager::GetIAccessibleFromResID(long resID)
1033 XResIdToAccObjHash::iterator pIndTemp = XResIdAccList.find( resID );
1034 if ( pIndTemp == XResIdAccList.end() )
1035 return nullptr;
1037 AccObject* pObj = pIndTemp->second;
1039 if(pObj->GetIMAccessible())
1040 return pObj->GetIMAccessible();
1041 return nullptr;
1044 * Notify some object will be destroyed.
1045 * @param pXAcc XAccessible interface.
1046 * @return Com accobject interface.
1048 void AccObjectWinManager::NotifyDestroy(XAccessible* pXAcc)
1050 AccObject* accObj = GetAccObjByXAcc(pXAcc);
1051 if(accObj)
1053 accObj->NotifyDestroy();
1058 void AccObjectWinManager::UpdateChildState(css::accessibility::XAccessible* pAccSubMenu)
1060 Reference<css::accessibility::XAccessibleContext> xContext(pAccSubMenu,UNO_QUERY);
1061 if (!xContext.is())
1063 return;
1065 const sal_Int64 nCount = xContext->getAccessibleChildCount();
1066 for (sal_Int64 i = 0 ; i < nCount; ++i)
1068 Reference<css::accessibility::XAccessible> xChild = xContext->getAccessibleChild(i);
1069 if (xChild.is())
1071 AccObject *pObj = GetAccObjByXAcc(xChild.get());
1072 if (pObj)
1074 pObj->UpdateState();
1081 bool AccObjectWinManager::IsSpecialToolbarItem(css::accessibility::XAccessible* pXAcc)
1083 if (pXAcc && oldFocus != pXAcc)
1085 if (GetParentRole(pXAcc) == AccessibleRole::TOOL_BAR)
1087 Reference< XAccessibleContext > pRContext(pXAcc->getAccessibleContext());
1088 if (pRContext.is())
1090 if (pRContext->getAccessibleRole() == AccessibleRole::TOGGLE_BUTTON)
1092 return true;
1097 return false;
1100 short AccObjectWinManager::GetRole(css::accessibility::XAccessible* pXAcc)
1102 assert(pXAcc != nullptr);
1103 Reference<css::accessibility::XAccessibleContext> xContext = pXAcc->getAccessibleContext();
1104 if(xContext.is())
1106 return xContext->getAccessibleRole();
1108 return -1;
1111 XAccessible* AccObjectWinManager::GetAccDocByHWND(HWND pWnd)
1113 XHWNDToDocumentHash::iterator aIter;
1114 aIter = XHWNDDocList.find( pWnd );
1115 if ( aIter != XHWNDDocList.end() )
1117 return aIter->second;
1120 return nullptr;
1123 XAccessible* AccObjectWinManager::GetAccDocByAccTopWin( XAccessible* pXAcc )
1125 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1126 HWND hWnd = pAccObj->GetParentHWND();
1127 return GetAccDocByHWND(hWnd);
1130 bool AccObjectWinManager::IsTopWinAcc( css::accessibility::XAccessible* pXAcc )
1132 bool bRet = false;
1133 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1134 if ( pAccObj )
1136 bRet = ( pAccObj->GetParentObj() == nullptr );
1138 return bRet;
1140 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */