Fix GNU C++ version check
[LibreOffice.git] / winaccessibility / source / service / AccObjectWinManager.cxx
blobc6edbb0b03923bfa0d00aa672d77820bc273b7f0
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 AccObjectWinManager::AccObjectWinManager():
52 oldFocus(nullptr)
56 /**
57 * Destructor,clear all resource.
58 * @param
59 * @return
61 AccObjectWinManager::~AccObjectWinManager()
64 std::scoped_lock l(m_Mutex);
66 XIdAccList.clear();
67 HwndXAcc.clear();
69 XResIdAccList.clear();
70 XHWNDDocList.clear();
74 /**
75 * Get valid com object interface when notifying some MSAA event
76 * @param pWND The top window handle that contains that event control.
77 * @param wParam Windows system interface.
78 * @return Com interface with event.
81 sal_Int64
82 AccObjectWinManager::Get_ToATInterface(sal_Int64 nHWnd, long lParam, WPARAM wParam)
84 IMAccessible* pRetIMAcc = nullptr;
86 if(lParam == OBJID_CLIENT )
88 HWND hWnd = reinterpret_cast<HWND>(nHWnd);
89 pRetIMAcc = GetTopWindowIMAccessible(hWnd);
92 if ( pRetIMAcc && lParam == OBJID_CLIENT )
94 LRESULT result = LresultFromObject(IID_IAccessible, wParam, pRetIMAcc);
95 pRetIMAcc->Release();
96 return static_cast<sal_Int64>(result);
98 return 0;
102 * Search AccObject by XAccessible pointer from our container.
103 * @param pXAcc XAccessible interface.
104 * @return Pointer of accObject that is found.
106 AccObject* AccObjectWinManager::GetAccObjByXAcc( XAccessible* pXAcc)
108 if( pXAcc == nullptr)
109 return nullptr;
111 std::scoped_lock l(m_Mutex);
113 XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
114 if ( pIndTemp == XIdAccList.end() )
115 return nullptr;
117 return &(pIndTemp->second);
121 * get acc object of top window by its handle
122 * @param hWnd, top window handle
123 * @return pointer to AccObject
125 IMAccessible * AccObjectWinManager::GetTopWindowIMAccessible(HWND hWnd)
127 std::scoped_lock l(m_Mutex); // tdf#155794 for HwndXAcc and XIdAccList
129 XHWNDToXAccHash::iterator iterResult =HwndXAcc.find(hWnd);
130 if(iterResult == HwndXAcc.end())
131 return nullptr;
132 XAccessible* pXAcc = iterResult->second;
133 AccObject *const pAccObject(GetAccObjByXAcc(pXAcc));
134 if (!pAccObject)
136 return nullptr;
138 IMAccessible *const pRet(pAccObject->GetIMAccessible());
139 if (!pRet)
141 return nullptr;
143 pRet->AddRef();
144 return pRet;
148 * Simulate MSAA event via XAccessible interface and event type.
149 * @param pXAcc XAccessible interface.
150 * @param eEvent event type
151 * @return The terminate result that identifies if the call is successful.
153 bool AccObjectWinManager::NotifyAccEvent(XAccessible* pXAcc, UnoMSAAEvent eEvent)
155 Reference< XAccessibleContext > pRContext;
157 if( pXAcc == nullptr)
158 return false;
161 pRContext = pXAcc->getAccessibleContext();
162 if( !pRContext.is() )
163 return false;
166 AccObject* selfAccObj= GetAccObjByXAcc(pXAcc);
168 if(selfAccObj==nullptr)
169 return false;
171 long dChildID = selfAccObj->GetResID();
172 HWND hAcc = selfAccObj->GetParentHWND();
174 switch(eEvent)
176 case UnoMSAAEvent::STATE_FOCUSED:
178 UpdateAccFocus(pXAcc);
179 UpdateValue(pXAcc);
180 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
181 break;
183 case UnoMSAAEvent::STATE_BUSY:
184 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
185 break;
186 case UnoMSAAEvent::STATE_CHECKED:
187 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
188 break;
189 case UnoMSAAEvent::STATE_PRESSED:
190 NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
191 break;
193 //Removed fire out selected event
194 //case UnoMSAAEvent::STATE_SELECTED:
195 // NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
196 // break;
197 case UnoMSAAEvent::STATE_ARMED:
198 UpdateAccFocus(pXAcc);
199 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
200 break;
201 case UnoMSAAEvent::STATE_SHOWING:
202 // send EVENT_SYSTEM_ALERT when notification gets shown
203 if (pRContext->getAccessibleRole() == AccessibleRole::NOTIFICATION)
204 NotifyWinEvent(EVENT_SYSTEM_ALERT, hAcc, OBJID_CLIENT, dChildID);
205 break;
206 case UnoMSAAEvent::MENU_START:
207 NotifyWinEvent( EVENT_SYSTEM_MENUSTART,hAcc, OBJID_CLIENT,dChildID );
208 break;
209 case UnoMSAAEvent::MENU_END:
210 NotifyWinEvent( EVENT_SYSTEM_MENUEND,hAcc, OBJID_CLIENT,dChildID );
211 break;
212 case UnoMSAAEvent::MENUPOPUPSTART:
213 NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPSTART,hAcc, OBJID_CLIENT,dChildID );
214 break;
215 case UnoMSAAEvent::MENUPOPUPEND:
216 NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPEND,hAcc, OBJID_CLIENT,dChildID );
217 break;
218 case UnoMSAAEvent::SELECTION_CHANGED:
219 NotifyWinEvent( EVENT_OBJECT_SELECTION,hAcc, OBJID_CLIENT,dChildID );
220 break;
221 case UnoMSAAEvent::SELECTION_CHANGED_ADD:
222 NotifyWinEvent( EVENT_OBJECT_SELECTIONADD,hAcc, OBJID_CLIENT,dChildID );
223 break;
224 case UnoMSAAEvent::SELECTION_CHANGED_REMOVE:
225 NotifyWinEvent( EVENT_OBJECT_SELECTIONREMOVE,hAcc, OBJID_CLIENT,dChildID );
226 break;
227 case UnoMSAAEvent::SELECTION_CHANGED_WITHIN:
228 NotifyWinEvent( EVENT_OBJECT_SELECTIONWITHIN,hAcc, OBJID_CLIENT,dChildID );
229 break;
230 case UnoMSAAEvent::OBJECT_VALUECHANGE:
231 UpdateValue(pXAcc);
232 NotifyWinEvent( EVENT_OBJECT_VALUECHANGE,hAcc, OBJID_CLIENT,dChildID );
233 break;
234 case UnoMSAAEvent::OBJECT_NAMECHANGE:
235 NotifyWinEvent( EVENT_OBJECT_NAMECHANGE,hAcc, OBJID_CLIENT,dChildID );
236 break;
237 case UnoMSAAEvent::OBJECT_DESCRIPTIONCHANGE:
238 NotifyWinEvent( EVENT_OBJECT_DESCRIPTIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
239 break;
240 case UnoMSAAEvent::OBJECT_DEFACTIONCHANGE:
241 NotifyWinEvent( IA2_EVENT_ACTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
242 break;
243 case UnoMSAAEvent::OBJECT_CARETCHANGE:
244 NotifyWinEvent( IA2_EVENT_TEXT_CARET_MOVED,hAcc, OBJID_CLIENT,dChildID );
245 break;
246 case UnoMSAAEvent::OBJECT_TEXTCHANGE:
247 NotifyWinEvent(IA2_EVENT_TEXT_UPDATED, hAcc, OBJID_CLIENT, dChildID);
248 break;
249 case UnoMSAAEvent::ACTIVE_DESCENDANT_CHANGED:
250 UpdateAccFocus(pXAcc);
251 NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
252 break;
253 case UnoMSAAEvent::BOUNDRECT_CHANGED:
254 NotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
255 break;
256 case UnoMSAAEvent::VISIBLE_DATA_CHANGED:
257 NotifyWinEvent( IA2_EVENT_VISIBLE_DATA_CHANGED,hAcc, OBJID_CLIENT,dChildID );
258 break;
259 case UnoMSAAEvent::SHOW :
260 NotifyWinEvent( EVENT_OBJECT_SHOW,hAcc, OBJID_CLIENT,dChildID );
261 NotifyWinEvent( EVENT_SYSTEM_FOREGROUND,hAcc, OBJID_CLIENT,dChildID );
262 break;
263 case UnoMSAAEvent::TABLE_CAPTION_CHANGED:
264 NotifyWinEvent( IA2_EVENT_TABLE_CAPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
265 break;
266 case UnoMSAAEvent::TABLE_COLUMN_DESCRIPTION_CHANGED:
267 NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
268 break;
269 case UnoMSAAEvent::TABLE_COLUMN_HEADER_CHANGED:
270 NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
271 break;
272 case UnoMSAAEvent::TABLE_MODEL_CHANGED:
273 NotifyWinEvent( IA2_EVENT_TABLE_MODEL_CHANGED,hAcc, OBJID_CLIENT,dChildID );
274 break;
275 case UnoMSAAEvent::TABLE_ROW_HEADER_CHANGED:
276 NotifyWinEvent( IA2_EVENT_TABLE_ROW_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
277 break;
278 case UnoMSAAEvent::TABLE_SUMMARY_CHANGED:
279 NotifyWinEvent( IA2_EVENT_TABLE_SUMMARY_CHANGED,hAcc, OBJID_CLIENT,dChildID );
280 break;
281 case UnoMSAAEvent::TABLE_ROW_DESCRIPTION_CHANGED:
282 NotifyWinEvent( IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
283 break;
284 case UnoMSAAEvent::OBJECT_REORDER:
285 NotifyWinEvent( EVENT_OBJECT_REORDER,hAcc, OBJID_CLIENT,dChildID );
286 break;
287 case UnoMSAAEvent::PAGE_CHANGED:
288 NotifyWinEvent( IA2_EVENT_PAGE_CHANGED,hAcc, OBJID_CLIENT,dChildID );
289 break;
290 case UnoMSAAEvent::CHILD_REMOVED:
291 NotifyWinEvent( EVENT_OBJECT_DESTROY,hAcc, OBJID_CLIENT,dChildID );
292 break;
293 case UnoMSAAEvent::CHILD_ADDED:
294 NotifyWinEvent( EVENT_OBJECT_CREATE ,hAcc, OBJID_CLIENT,dChildID );
295 break;
296 case UnoMSAAEvent::OBJECT_PAGECHANGED:
297 NotifyWinEvent( IA2_EVENT_PAGE_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
298 break;
299 case UnoMSAAEvent::TEXT_SELECTION_CHANGED:
300 NotifyWinEvent( IA2_EVENT_TEXT_SELECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
301 break;
302 case UnoMSAAEvent::SECTION_CHANGED:
303 NotifyWinEvent( IA2_EVENT_SECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
304 break;
305 case UnoMSAAEvent::COLUMN_CHANGED:
306 NotifyWinEvent( IA2_EVENT_TEXT_COLUMN_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
307 break;
308 default:
309 break;
312 return true;
316 * Get Parent XAccessible interface by XAccessible interface.
317 * @param pXAcc XAccessible interface.
318 * @return Parent XAccessible interface.
320 XAccessible* AccObjectWinManager::GetParentXAccessible( XAccessible* pXAcc )
322 AccObject* pObj= GetAccObjByXAcc(pXAcc);
323 if( pObj ==nullptr )
324 return nullptr;
325 if(pObj->GetParentObj())
327 pObj = pObj->GetParentObj();
328 return pObj->GetXAccessible().get();
330 return nullptr;
334 * Get Parent role by XAccessible interface.
335 * @param pXAcc XAccessible interface.
336 * @return Parent role.
338 short AccObjectWinManager::GetParentRole( XAccessible* pXAcc )
340 AccObject* pObj= GetAccObjByXAcc(pXAcc);
341 if( pObj ==nullptr )
342 return -1;
343 if(pObj->GetParentObj())
345 pObj = pObj->GetParentObj();
346 if(pObj->GetXAccessible().is())
348 Reference< XAccessibleContext > pRContext = pObj->GetXAccessible()->getAccessibleContext();
349 if(pRContext.is())
350 return pRContext->getAccessibleRole();
353 return -1;
357 * Update focus object by new focused XAccessible interface.
358 * @param newFocus New XAccessible interface that gets focus.
359 * @return
361 void AccObjectWinManager::UpdateAccFocus(XAccessible* newFocus)
363 AccObject* pAccObjNew = GetAccObjByXAcc(newFocus);
364 if(pAccObjNew)
366 AccObject* pAccObjOld = GetAccObjByXAcc(oldFocus);
367 oldFocus = newFocus;
368 pAccObjNew->setFocus();
369 //if old == new, the pAccObjNew will be without focused state
370 if (pAccObjOld && pAccObjOld != pAccObjNew)
371 pAccObjOld->unsetFocus();
376 * Delete child element from children list.
377 * @param pObj Child element that should be removed from parent child list.
378 * @return
380 void AccObjectWinManager::DeleteAccChildNode( AccObject* pObj )
382 AccObject *parentAccObj = pObj->GetParentObj();
383 if( parentAccObj )
384 parentAccObj->DeleteChild( pObj );
388 * Delete XAccessible items in top window handle hashtable
389 * @param pXAcc XAccessible interface.
390 * @return
392 void AccObjectWinManager::DeleteFromHwndXAcc(XAccessible const * pXAcc )
394 std::scoped_lock l(m_Mutex);
396 auto iter = std::find_if(HwndXAcc.begin(), HwndXAcc.end(),
397 [&pXAcc](XHWNDToXAccHash::value_type& rEntry) { return rEntry.second == pXAcc; });
398 if (iter != HwndXAcc.end())
399 HwndXAcc.erase(iter);
403 * Delete all children with the tree root of XAccessible pointer
404 * @param pXAcc Tree root XAccessible interface.
405 * @return
407 void AccObjectWinManager::DeleteChildrenAccObj(XAccessible* pXAcc)
409 AccObject* currentObj=nullptr;
410 AccObject* childObj=nullptr;
412 currentObj = GetAccObjByXAcc( pXAcc);
413 if(currentObj)
415 childObj = currentObj->NextChild();
416 while(childObj)
418 XAccessible *const pTmpXAcc = childObj->GetXAccessible().get();
419 if(pTmpXAcc)
421 DeleteChildrenAccObj(pTmpXAcc);
422 DeleteAccObj(pTmpXAcc);
424 childObj = currentObj->NextChild();
430 * Delete Acc object self.
431 * @param pXAcc The XAccessible interface.
432 * @return
434 void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
436 if( pXAcc == nullptr )
437 return;
439 rtl::Reference<AccEventListener> pListener;
442 std::scoped_lock l(m_Mutex);
444 XIdToAccObjHash::iterator temp = XIdAccList.find(pXAcc);
445 if( temp != XIdAccList.end() )
447 ResIdGen.SetSub( temp->second.GetResID() );
449 else
451 return;
454 AccObject& accObj = temp->second;
455 DeleteAccChildNode( &accObj );
456 pListener = DeleteAccListener(&accObj);
457 accObj.NotifyDestroy();
458 if( accObj.GetIMAccessible() )
460 accObj.GetIMAccessible()->Release();
462 size_t i = XResIdAccList.erase(accObj.GetResID());
463 assert(i != 0);
464 (void) i;
465 DeleteFromHwndXAcc(pXAcc);
466 if (accObj.GetRole() == AccessibleRole::DOCUMENT ||
467 accObj.GetRole() == AccessibleRole::DOCUMENT_PRESENTATION ||
468 accObj.GetRole() == AccessibleRole::DOCUMENT_SPREADSHEET ||
469 accObj.GetRole() == AccessibleRole::DOCUMENT_TEXT)
471 XHWNDDocList.erase(accObj.GetParentHWND());
473 XIdAccList.erase(pXAcc); // note: this invalidates accObj so do it last!
475 if (pListener)
477 pListener->RemoveMeFromBroadcaster(false);
482 * Delete listener that inspects some XAccessible object
483 * @param pAccObj Accobject pointer.
484 * @return
486 rtl::Reference<AccEventListener> AccObjectWinManager::DeleteAccListener( AccObject* pAccObj )
488 return pAccObj->SetListener(nullptr);
492 * Generate a child ID, which is used for AT
493 * @param
494 * @return New resource ID.
496 inline long AccObjectWinManager::ImpleGenerateResID()
498 return ResIdGen.GenerateNewResID();
502 * Insert all children of the current acc object
503 * @param pXAcc XAccessible interface
504 * @param pWnd Top Window handle
505 * @return The calling result.
507 bool AccObjectWinManager::InsertChildrenAccObj( css::accessibility::XAccessible* pXAcc,
508 HWND pWnd)
510 if(!IsContainer(pXAcc))
511 return false;
513 if( pXAcc == nullptr)
514 return false;
516 Reference<XAccessibleContext> xContext = pXAcc->getAccessibleContext();
517 if (!xContext.is())
518 return false;
520 short role = xContext->getAccessibleRole();
522 if(css::accessibility::AccessibleRole::DOCUMENT == role ||
523 css::accessibility::AccessibleRole::DOCUMENT_PRESENTATION == role ||
524 css::accessibility::AccessibleRole::DOCUMENT_SPREADSHEET == role ||
525 css::accessibility::AccessibleRole::DOCUMENT_TEXT == role)
527 if(IsStateManageDescendant(pXAcc))
529 return true;
533 const sal_Int64 nCount = xContext->getAccessibleChildCount();
534 for (sal_Int64 i = 0; i < nCount; i++)
536 Reference<XAccessible> mxAccessible = xContext->getAccessibleChild(i);
537 XAccessible* mpAccessible = mxAccessible.get();
538 if(mpAccessible != nullptr)
540 InsertAccObj( mpAccessible,pXAcc,pWnd );
541 InsertChildrenAccObj(mpAccessible,pWnd);
545 return true;
549 * Insert child object.
550 * @param pCurObj The child object
551 * @param pParentObj The parent object
552 * @param pWnd Top window handle.
553 * @return
555 void AccObjectWinManager::InsertAccChildNode( AccObject* pCurObj, AccObject* pParentObj, HWND /* pWnd */ )
557 if(pCurObj)
559 if(pParentObj)
561 pParentObj->InsertChild(pCurObj);
563 else
565 pCurObj->UpdateValidWindow();
571 * Insert child object.
572 * @param pCurObj The child object
573 * @param pParentObj The parent object
574 * @param pWnd Top window handle.
575 * @return
577 bool AccObjectWinManager::InsertAccObj( XAccessible* pXAcc,XAccessible* pParentXAcc,HWND pWnd )
579 if( pXAcc == nullptr)
580 return false;
582 Reference<XAccessibleContext> xContext = pXAcc->getAccessibleContext();
583 if (!xContext.is())
584 return false;
587 short nCurRole = xContext->getAccessibleRole();
589 std::scoped_lock l(m_Mutex);
591 XIdToAccObjHash::iterator itXacc = XIdAccList.find( pXAcc );
592 if (itXacc != XIdAccList.end() )
594 if (AccessibleRole::SHAPE == nCurRole)
596 AccObject &objXacc = itXacc->second;
597 AccObject *pObjParent = objXacc.GetParentObj();
598 if (pObjParent &&
599 pObjParent->GetXAccessible().is() &&
600 pObjParent->GetXAccessible().get() != pParentXAcc)
602 XIdToAccObjHash::iterator itXaccParent = XIdAccList.find( pParentXAcc );
603 if(itXaccParent != XIdAccList.end())
605 objXacc.SetParentObj(&(itXaccParent->second));
609 return false;
613 if( pWnd == nullptr )
615 if(pParentXAcc)
617 AccObject* pObj = GetAccObjByXAcc(pParentXAcc);
619 // insert parent if necessary
620 if (!pObj)
622 Reference<XAccessibleContext> xParentContext = pParentXAcc->getAccessibleContext();
623 assert(xParentContext.is() && "parent accessible has no context");
624 InsertAccObj(pParentXAcc, xParentContext->getAccessibleParent().get());
625 pObj = GetAccObjByXAcc(pParentXAcc);
628 if(pObj)
629 pWnd = pObj->GetParentHWND();
631 if( pWnd == nullptr )
632 return false;
635 AccObject pObj(pXAcc, this);
636 pObj.SetResID( this->ImpleGenerateResID());
637 pObj.SetParentHWND( pWnd );
639 //for file name support
640 if (pObj.GetRole() == AccessibleRole::DOCUMENT ||
641 pObj.GetRole() == AccessibleRole::DOCUMENT_PRESENTATION ||
642 pObj.GetRole() == AccessibleRole::DOCUMENT_SPREADSHEET ||
643 pObj.GetRole() == AccessibleRole::DOCUMENT_TEXT)
645 XHWNDToDocumentHash::iterator aIter = XHWNDDocList.find(pWnd);
646 if ( aIter != XHWNDDocList.end() )
648 XHWNDDocList.erase( aIter );
650 XHWNDDocList.emplace( pWnd, pXAcc );
652 //end of file name
654 ::rtl::Reference<AccEventListener> const pListener =
655 CreateAccEventListener(pXAcc);
656 if (!pListener.is())
657 return false;
658 Reference<XAccessibleComponent> xComponent(xContext, UNO_QUERY);
659 Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
660 if (broadcaster.is())
662 Reference<XAccessibleEventListener> const xListener(pListener);
663 broadcaster->addAccessibleEventListener(xListener);
665 else
666 return false;
669 std::scoped_lock l(m_Mutex);
671 XIdAccList.emplace(pXAcc, pObj);
672 XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
673 XResIdAccList.emplace(pObj.GetResID(),&(pIndTemp->second));
676 AccObject* pCurObj = GetAccObjByXAcc(pXAcc);
677 if( pCurObj )
679 pCurObj->SetListener(pListener);
682 AccObject* pParentObj = GetAccObjByXAcc(pParentXAcc);
683 InsertAccChildNode(pCurObj,pParentObj,pWnd);
684 if( pCurObj )
685 pCurObj->UpdateAccessibleInfoFromUnoToMSAA();
686 return true;
691 * save the pair <topwindowhandle, XAccessible>
692 * @param hWnd, top window handle
693 * @param pXAcc XAccessible interface for top window
694 * @return void
696 void AccObjectWinManager::SaveTopWindowHandle(HWND hWnd, css::accessibility::XAccessible* pXAcc)
698 std::scoped_lock l(m_Mutex);
700 HwndXAcc.emplace(hWnd,pXAcc);
704 /** Create the corresponding listener.
705 * @param pXAcc XAccessible interface.
707 ::rtl::Reference<AccEventListener>
708 AccObjectWinManager::CreateAccEventListener(XAccessible* pXAcc)
710 ::rtl::Reference<AccEventListener> pRet;
711 Reference<XAccessibleContext> xContext = pXAcc->getAccessibleContext();
712 if(xContext.is())
714 switch( xContext->getAccessibleRole() )
716 case AccessibleRole::DIALOG:
717 pRet = new AccDialogEventListener(pXAcc, *this);
718 break;
719 case AccessibleRole::FRAME:
720 pRet = new AccFrameEventListener(pXAcc, *this);
721 break;
722 case AccessibleRole::WINDOW:
723 pRet = new AccWindowEventListener(pXAcc, *this);
724 break;
725 case AccessibleRole::ROOT_PANE:
726 pRet = new AccFrameEventListener(pXAcc, *this);
727 break;
728 //Container
729 case AccessibleRole::CANVAS:
730 case AccessibleRole::COMBO_BOX:
731 case AccessibleRole::DOCUMENT:
732 case AccessibleRole::DOCUMENT_PRESENTATION:
733 case AccessibleRole::DOCUMENT_SPREADSHEET:
734 case AccessibleRole::DOCUMENT_TEXT:
735 case AccessibleRole::END_NOTE:
736 case AccessibleRole::FILLER:
737 case AccessibleRole::FOOTNOTE:
738 case AccessibleRole::FOOTER:
739 case AccessibleRole::HEADER:
740 case AccessibleRole::LAYERED_PANE:
741 case AccessibleRole::MENU_BAR:
742 case AccessibleRole::POPUP_MENU:
743 case AccessibleRole::OPTION_PANE:
744 case AccessibleRole::PAGE_TAB:
745 case AccessibleRole::PAGE_TAB_LIST:
746 case AccessibleRole::PANEL:
747 case AccessibleRole::SCROLL_PANE:
748 case AccessibleRole::SPLIT_PANE:
749 case AccessibleRole::STATUS_BAR:
750 case AccessibleRole::TABLE_CELL:
751 case AccessibleRole::TOOL_BAR:
752 case AccessibleRole::VIEW_PORT:
753 pRet = new AccContainerEventListener(pXAcc, *this);
754 break;
755 case AccessibleRole::BLOCK_QUOTE:
756 case AccessibleRole::PARAGRAPH:
757 case AccessibleRole::HEADING:
758 pRet = new AccParagraphEventListener(pXAcc, *this);
759 break;
760 //Component
761 case AccessibleRole::CHECK_BOX:
762 case AccessibleRole::ICON:
763 case AccessibleRole::LABEL:
764 case AccessibleRole::STATIC:
765 case AccessibleRole::NOTIFICATION:
766 case AccessibleRole::MENU_ITEM:
767 case AccessibleRole::CHECK_MENU_ITEM:
768 case AccessibleRole::RADIO_MENU_ITEM:
769 case AccessibleRole::PUSH_BUTTON:
770 case AccessibleRole::RADIO_BUTTON:
771 case AccessibleRole::SCROLL_BAR:
772 case AccessibleRole::SEPARATOR:
773 case AccessibleRole::TOGGLE_BUTTON:
774 case AccessibleRole::BUTTON_DROPDOWN:
775 case AccessibleRole::TOOL_TIP:
776 case AccessibleRole::SPIN_BOX:
777 case AccessibleRole::DATE_EDITOR:
778 pRet = new AccComponentEventListener(pXAcc, *this);
779 break;
780 //text component
781 case AccessibleRole::TEXT:
782 pRet = new AccTextComponentEventListener(pXAcc, *this);
783 break;
784 //menu
785 case AccessibleRole::MENU:
786 pRet = new AccMenuEventListener(pXAcc, *this);
787 break;
788 //object container
789 case AccessibleRole::SHAPE:
791 case AccessibleRole::EMBEDDED_OBJECT:
792 case AccessibleRole::GRAPHIC:
793 case AccessibleRole::TEXT_FRAME:
794 pRet = new AccObjectContainerEventListener(pXAcc, *this);
795 break;
796 //descendmanager
797 case AccessibleRole::LIST:
798 pRet = new AccListEventListener(pXAcc, *this);
799 break;
800 case AccessibleRole::TREE:
801 pRet = new AccTreeEventListener(pXAcc, *this);
802 break;
803 //special
804 case AccessibleRole::COLUMN_HEADER:
805 case AccessibleRole::TABLE:
806 pRet = new AccTableEventListener(pXAcc, *this);
807 break;
808 default:
809 pRet = new AccContainerEventListener(pXAcc, *this);
810 break;
813 return pRet;
817 * state is a combination integer, each bit of which represents a single state,
818 * such as focused,1 for the state on,0 for the state off. Here call COM interface
819 * to modify the state value, including DecreaseState.
820 * @param pXAcc XAccessible interface.
821 * @param pState Changed state.
822 * @return
824 void AccObjectWinManager::DecreaseState(XAccessible* pXAcc, sal_Int64 nState)
826 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
827 if( pAccObj )
828 pAccObj->DecreaseState(nState);
832 * state is a combination integer, each bit of which represents a single state,such as focused,1 for
833 * the state on,0 for the state off. Here call COM interface to modify the state value, including
834 * IncreaseState.
835 * @param pXAcc XAccessible interface.
836 * @param pState Changed state.
837 * @return
839 void AccObjectWinManager::IncreaseState(XAccessible* pXAcc, sal_Int64 nState)
841 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
842 if( pAccObj )
843 pAccObj->IncreaseState(nState);
846 void AccObjectWinManager::UpdateState( css::accessibility::XAccessible* pXAcc )
848 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
849 if( pAccObj )
850 pAccObj->UpdateState( );
854 * Set corresponding com object's value via XAccessible interface and new value.
855 * @param pXAcc XAccessible interface.
856 * @param pAny new value.
857 * @return
859 void AccObjectWinManager::SetValue( XAccessible* pXAcc, Any pAny )
861 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
862 if( pAccObj )
863 pAccObj->SetValue( pAny );
867 * Set corresponding com object's value via XAccessible interface.
868 * @param pXAcc XAccessible interface.
869 * @return
871 void AccObjectWinManager::UpdateValue( XAccessible* pXAcc )
873 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
874 if( pAccObj )
875 pAccObj->UpdateValue();
879 * Judge if a XAccessible object is a container object.
880 * @param pAccessible XAccessible interface.
881 * @return If XAccessible object is container.
883 bool AccObjectWinManager::IsContainer(XAccessible* pAccessible)
887 if(pAccessible)
889 Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
890 if(xContext.is())
892 switch( xContext->getAccessibleRole() )
894 case AccessibleRole::DIALOG:
895 case AccessibleRole::FRAME:
896 case AccessibleRole::WINDOW:
897 case AccessibleRole::ROOT_PANE:
898 case AccessibleRole::CANVAS:
899 case AccessibleRole::COMBO_BOX:
900 case AccessibleRole::DOCUMENT:
901 case AccessibleRole::DOCUMENT_PRESENTATION:
902 case AccessibleRole::DOCUMENT_SPREADSHEET:
903 case AccessibleRole::DOCUMENT_TEXT:
904 case AccessibleRole::EMBEDDED_OBJECT:
905 case AccessibleRole::END_NOTE:
906 case AccessibleRole::FILLER:
907 case AccessibleRole::FOOTNOTE:
908 case AccessibleRole::FOOTER:
909 case AccessibleRole::GRAPHIC:
910 case AccessibleRole::GROUP_BOX:
911 case AccessibleRole::HEADER:
912 case AccessibleRole::LAYERED_PANE:
913 case AccessibleRole::MENU_BAR:
914 case AccessibleRole::POPUP_MENU:
915 case AccessibleRole::OPTION_PANE:
916 case AccessibleRole::PAGE_TAB:
917 case AccessibleRole::PAGE_TAB_LIST:
918 case AccessibleRole::PANEL:
919 case AccessibleRole::SCROLL_PANE:
920 case AccessibleRole::SPLIT_PANE:
921 case AccessibleRole::STATUS_BAR:
922 case AccessibleRole::TABLE_CELL:
923 case AccessibleRole::TEXT_FRAME:
924 case AccessibleRole::TOOL_BAR:
925 case AccessibleRole::VIEW_PORT:
926 case AccessibleRole::SHAPE:
927 return true;
928 case AccessibleRole::COLUMN_HEADER:
929 case AccessibleRole::TABLE:
930 if(!IsStateManageDescendant(pAccessible))
931 return true;
932 break;
933 case AccessibleRole::MENU:
934 return true;
935 default:
936 return false;
941 catch(...)
943 return false;
945 return false;
949 * Judge if a XAccessible object has ManageDescendant event.
950 * @param pAccessible XAccessible interface.
951 * @return If XAccessible object is managedescendant.
953 bool AccObjectWinManager::IsStateManageDescendant(XAccessible* pAccessible)
955 if(pAccessible)
957 Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
958 if(xContext.is())
960 sal_Int64 nRState = xContext->getAccessibleStateSet();
961 return nRState & AccessibleStateType::MANAGES_DESCENDANTS;
964 return false;
968 * Query and get IAccessible interface by XAccessible interface from list.
969 * @param pXAcc XAccessible interface.
970 * @return Com accobject interface.
972 IMAccessible* AccObjectWinManager::GetIAccessibleFromXAccessible(XAccessible* pXAcc)
974 AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
975 if (pAccObj)
976 return pAccObj->GetIMAccessible();
978 return nullptr;
982 * Query and get IAccessible interface by child id from list.
983 * @param resID, childID.
984 * @return Com accobject interface.
986 IMAccessible * AccObjectWinManager::GetIAccessibleFromResID(long resID)
988 XResIdToAccObjHash::iterator pIndTemp = XResIdAccList.find( resID );
989 if ( pIndTemp == XResIdAccList.end() )
990 return nullptr;
992 AccObject* pObj = pIndTemp->second;
994 if(pObj->GetIMAccessible())
995 return pObj->GetIMAccessible();
996 return nullptr;
999 * Notify some object will be destroyed.
1000 * @param pXAcc XAccessible interface.
1001 * @return Com accobject interface.
1003 void AccObjectWinManager::NotifyDestroy(XAccessible* pXAcc)
1005 AccObject* accObj = GetAccObjByXAcc(pXAcc);
1006 if(accObj)
1008 accObj->NotifyDestroy();
1013 void AccObjectWinManager::UpdateChildState(css::accessibility::XAccessible* pAccSubMenu)
1015 Reference<css::accessibility::XAccessibleContext> xContext(pAccSubMenu,UNO_QUERY);
1016 if (!xContext.is())
1018 return;
1020 const sal_Int64 nCount = xContext->getAccessibleChildCount();
1021 for (sal_Int64 i = 0 ; i < nCount; ++i)
1023 Reference<css::accessibility::XAccessible> xChild = xContext->getAccessibleChild(i);
1024 if (xChild.is())
1026 AccObject *pObj = GetAccObjByXAcc(xChild.get());
1027 if (pObj)
1029 pObj->UpdateState();
1035 XAccessible* AccObjectWinManager::GetAccDocByHWND(HWND pWnd)
1037 XHWNDToDocumentHash::iterator aIter;
1038 aIter = XHWNDDocList.find( pWnd );
1039 if ( aIter != XHWNDDocList.end() )
1041 return aIter->second;
1044 return nullptr;
1047 XAccessible* AccObjectWinManager::GetAccDocByAccTopWin( XAccessible* pXAcc )
1049 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1050 HWND hWnd = pAccObj->GetParentHWND();
1051 return GetAccDocByHWND(hWnd);
1054 bool AccObjectWinManager::IsTopWinAcc( css::accessibility::XAccessible* pXAcc )
1056 bool bRet = false;
1057 AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
1058 if ( pAccObj )
1060 bRet = ( pAccObj->GetParentObj() == nullptr );
1062 return bRet;
1064 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */