Bump version to 6.4.7.2.M8
[LibreOffice.git] / winaccessibility / source / UAccCOM / MAccessible.cxx
blob6a844f8d7ce6e0def438dcab84a45fd7a653033f
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 "stdafx.h"
21 #include "MAccessible.h"
23 #if defined __clang__
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
26 #endif
27 #include <UAccCOM.h>
28 #if defined __clang__
29 #pragma clang diagnostic pop
30 #endif
32 #include <algorithm>
33 #include <cstddef>
35 #include "AccAction.h"
36 #include "AccRelation.h"
37 #include "AccComponent.h"
38 #include "AccText.h"
39 #include "AccEditableText.h"
40 #include "AccImage.h"
41 #include "AccTable.h"
42 #include "AccValue.h"
43 #include "AccHypertext.h"
44 #include "AccHyperLink.h"
46 #include <rtl/ustrbuf.hxx>
47 #include <vcl/svapp.hxx>
48 #include <o3tl/char16_t2wchar_t.hxx>
49 #include <comphelper/AccessibleImplementationHelper.hxx>
51 #include <com/sun/star/accessibility/XAccessibleText.hpp>
52 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
53 #include <com/sun/star/accessibility/XAccessibleImage.hpp>
54 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
55 #include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
56 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
57 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
58 #include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
59 #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
60 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
61 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
62 #include <com/sun/star/accessibility/AccessibleRole.hpp>
63 #include <com/sun/star/accessibility/XAccessibleGroupPosition.hpp>
64 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
65 #include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
66 #include <com/sun/star/style/LineSpacing.hpp>
67 #include <com/sun/star/style/TabStop.hpp>
68 #include <com/sun/star/container/XIndexReplace.hpp>
71 using namespace com::sun::star::uno;
72 using namespace com::sun::star::accessibility;
73 using namespace com::sun::star::accessibility::AccessibleStateType;
75 enum XInterfaceIndex {
76 XI_COMPONENT = 0x01,
77 XI_TEXT = 0x02,
78 XI_TABLE = 0x03,
79 XI_EDITABLETEXT = 0x04,
80 XI_IMAGE = 0x05,
81 XI_SELECTION = 0x06,
82 XI_EXTENDEDCOMP = 0x07,
83 XI_VALUE = 0x08,
84 XI_KEYBINDING = 0x09,
85 XI_ACTION = 0x0A,
86 XI_HYPERTEXT = 0x0B,
87 XI_HYPERLINK = 0x0C,
88 XI_ATTRIBUTE = 0x0D,
89 XI_NULL = -1
92 // IA2 states mapping, and name
93 // maintenance the consistency, change one array, change the three all
94 long const IA2_STATES[] =
96 IA2_STATE_ACTIVE, // = 0x1;
97 IA2_STATE_ARMED, // = 0x2;
98 IA2_STATE_DEFUNCT, // = 0x4;
99 IA2_STATE_EDITABLE, // = 0x8;
100 IA2_STATE_HORIZONTAL, // = 0x10;
101 IA2_STATE_ICONIFIED, // = 0x20;
102 IA2_STATE_INVALID_ENTRY, // = 0x80;
103 IA2_STATE_MANAGES_DESCENDANTS, // = 0x100;
104 IA2_STATE_MODAL, // = 0x200;
105 IA2_STATE_MULTI_LINE, // = 0x400;
106 IA2_STATE_OPAQUE, // = 0x800;
107 IA2_STATE_REQUIRED, // = 0x2000;
108 IA2_STATE_SELECTABLE_TEXT, // = 0x3000;
109 IA2_STATE_SINGLE_LINE, // = 0x4000;
110 IA2_STATE_STALE, // = 0x8000;
111 IA2_STATE_SUPPORTS_AUTOCOMPLETION, // = 0x10000;
112 IA2_STATE_TRANSIENT, //= 0x20000;
113 IA2_STATE_VERTICAL // = 0x40000;
117 <=== map ===>
120 short const UNO_STATES[] =
122 ACTIVE, // = (sal_Int16)1;
123 ARMED, // = (sal_Int16)2;
124 DEFUNC, // = (sal_Int16)5;
125 EDITABLE, // = (sal_Int16)6;
126 HORIZONTAL, // = (sal_Int16)12;
127 ICONIFIED, // = (sal_Int16)13;
128 -1, //IA2_STATE_INVALID_ENTRY
129 MANAGES_DESCENDANTS, // = (sal_Int16)15;
130 MODAL, // = (sal_Int16)16;
131 MULTI_LINE, // = (sal_Int16)17;
132 OPAQUE, // = (sal_Int16)19;
133 -1, //IA2_STATE_REQUIRED
134 -1, //IA2_STATE_SELECTABLE_TEXT
135 SINGLE_LINE, // = (sal_Int16)26;
136 STALE, // = (sal_Int16)27;
137 -1, //IA2_STATE_SUPPORTS_AUTOCOMPLETION
138 TRANSIENT, //IA2_STATE_TRANSIENT
139 VERTICAL // = (sal_Int16)29;
142 using namespace com::sun::star::accessibility::AccessibleRole;
145 #define QUERYXINTERFACE(ainterface) \
147 if(pXAcc == nullptr) \
148 return FALSE; \
149 pRContext = pXAcc->getAccessibleContext(); \
150 if( !pRContext.is() ) \
152 return FALSE; \
154 Reference<X##ainterface> pRXI(pRContext,UNO_QUERY);\
155 if( !pRXI.is() ) \
157 return FALSE; \
159 *ppXI = pRXI.get(); \
160 return TRUE; \
163 #define ISDESTROY() \
164 if(m_isDestroy) \
165 return S_FALSE;
168 AccObjectManagerAgent* CMAccessible::g_pAgent = nullptr;
170 CMAccessible::CMAccessible():
171 m_pszName(nullptr),
172 m_pszValue(nullptr),
173 m_pszActionDescription(nullptr),
174 m_iRole(0x00),
175 m_dState(0x00),
176 m_pszDescription(nullptr),
177 m_pIParent(nullptr),
178 m_dChildID(0x00),
179 m_dFocusChildID(UACC_NO_FOCUS),
180 m_hwnd(nullptr),
181 m_isDestroy(FALSE),
182 m_bRequiresSave(FALSE)
184 m_sLocation.m_dLeft=0;
185 m_sLocation.m_dTop = 0;
186 m_sLocation.m_dWidth=0;
187 m_sLocation.m_dHeight=0;
188 CEnumVariant::Create(&m_pEnumVar);
189 m_containedObjects.clear();
192 CMAccessible::~CMAccessible()
194 SolarMutexGuard g;
196 if(m_pszName!=nullptr)
198 SAFE_SYSFREESTRING(m_pszName);
200 if(m_pszValue!=nullptr)
202 SAFE_SYSFREESTRING(m_pszValue);
204 if(m_pszDescription!=nullptr)
206 SAFE_SYSFREESTRING(m_pszDescription);
209 if(m_pszActionDescription!=nullptr)
211 SAFE_SYSFREESTRING(m_pszActionDescription);
214 if(m_pIParent)
216 m_pIParent->Release();
217 m_pIParent=nullptr;
219 m_pEnumVar->Release();
220 m_containedObjects.clear();
224 * Returns the Parent IAccessible interface pointer to AT.
225 * It should add reference, and the client should release the component.
226 * It should return E_FAIL when the parent point is null.
227 * @param ppdispParent [in,out] used to return the parent interface point.
228 * when the point is null, should return null.
229 * @return S_OK if successful and E_FAIL if the m_pIParent is NULL.
231 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accParent(IDispatch **ppdispParent)
233 SolarMutexGuard g;
235 ENTER_PROTECTED_BLOCK
236 ISDESTROY()
237 // #CHECK#
238 if(ppdispParent == nullptr)
240 return E_INVALIDARG;
243 if(m_pIParent)
245 *ppdispParent = m_pIParent;
246 (*ppdispParent)->AddRef();
247 return S_OK;
249 else if(m_hwnd)
251 HRESULT hr = AccessibleObjectFromWindow(m_hwnd, OBJID_WINDOW, IID_IAccessible, reinterpret_cast<void**>(ppdispParent));
252 if (!SUCCEEDED(hr) || !*ppdispParent)
254 return S_FALSE;
256 return S_OK;
258 return S_FALSE;
260 LEAVE_PROTECTED_BLOCK
264 * Returns child count of current COM object.
265 * @param pcountChildren [in,out] used to return the children count.
266 * @return S_OK if successful.
268 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accChildCount(long *pcountChildren)
270 SolarMutexGuard g;
272 ENTER_PROTECTED_BLOCK
273 ISDESTROY()
274 // #CHECK#
275 if(pcountChildren == nullptr)
277 return E_INVALIDARG;
280 if (!m_xAccessible.is())
281 return S_FALSE;
283 Reference<XAccessibleContext> const pRContext =
284 m_xAccessible->getAccessibleContext();
285 if( pRContext.is() )
287 *pcountChildren = pRContext->getAccessibleChildCount();
290 return S_OK;
292 LEAVE_PROTECTED_BLOCK
296 * Returns child interface pointer for AT according to input child ID.
297 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
298 * the child ID specify child index from 0 to children count, 0 stands for object self.
299 * @param ppdispChild, [in,out] use to return the child interface point.
300 * @return S_OK if successful and S_FALSE if failure.
302 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accChild(VARIANT varChild, IDispatch **ppdispChild)
304 SolarMutexGuard g;
306 ENTER_PROTECTED_BLOCK
307 ISDESTROY()
308 // #CHECK#
309 if(ppdispChild == nullptr)
311 return E_INVALIDARG;
313 if(varChild.vt==VT_I4)
315 //get child interface pointer due to child ID
316 if(varChild.lVal==CHILDID_SELF)
318 AddRef();
319 *ppdispChild = this;
320 return S_OK;
322 *ppdispChild = GetChildInterface(varChild.lVal);
323 if((*ppdispChild) == nullptr)
324 return E_FAIL;
325 (*ppdispChild)->AddRef();
326 return S_OK;
328 return S_FALSE;
330 LEAVE_PROTECTED_BLOCK
334 * Returns the accessible name of the current COM object self or its one child to AT.
335 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
336 * the child ID specify child index from 0 to children count, 0 stands for object self.
337 * @param pszName, [in,out] use to return the name of the proper object.
338 * @return S_OK if successful and S_FALSE if failure.
340 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accName(VARIANT varChild, BSTR *pszName)
342 SolarMutexGuard g;
344 ENTER_PROTECTED_BLOCK
345 ISDESTROY()
346 // #CHECK#
347 if(pszName == nullptr)
349 return E_INVALIDARG;
351 if(varChild.vt==VT_I4)
353 if(varChild.lVal==CHILDID_SELF)
355 SAFE_SYSFREESTRING(*pszName);
356 *pszName = SysAllocString(m_pszName);
357 return S_OK;
360 long lVal = varChild.lVal;
361 varChild.lVal = CHILDID_SELF;
362 IMAccessible *pChild = this->GetChildInterface(lVal);
363 if(!pChild)
364 return E_FAIL;
365 return pChild->get_accName(varChild,pszName);
367 return S_FALSE;
369 LEAVE_PROTECTED_BLOCK
373 * Returns the accessible value of the current COM object self or its one child to AT.
374 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
375 * the child ID specify child index from 0 to children count, 0 stands for object self.
376 * @param pszValue, [in,out] use to return the value of the proper object.
377 * @return S_OK if successful and S_FALSE if failure.
379 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accValue(VARIANT varChild, BSTR *pszValue)
381 SolarMutexGuard g;
383 ENTER_PROTECTED_BLOCK
384 ISDESTROY()
385 // #CHECK#
386 if( pszValue == nullptr )
388 return E_INVALIDARG;
390 if( varChild.vt==VT_I4 )
392 if(varChild.lVal==CHILDID_SELF)
394 if(m_dState & STATE_SYSTEM_PROTECTED)
395 return E_ACCESSDENIED;
397 if ( m_pszValue !=nullptr && wcslen(m_pszValue) == 0 )
398 return S_OK;
400 SAFE_SYSFREESTRING(*pszValue);
401 *pszValue = SysAllocString(m_pszValue);
402 return S_OK;
405 long lVal = varChild.lVal;
406 varChild.lVal = CHILDID_SELF;
407 IMAccessible *pChild = this->GetChildInterface(lVal);
408 if(!pChild)
409 return E_FAIL;
410 return pChild->get_accValue(varChild,pszValue);
412 return S_FALSE;
414 LEAVE_PROTECTED_BLOCK
418 * Returns the accessible description of the current COM object self or its one child to AT.
419 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
420 * the child ID specify child index from 0 to children count, 0 stands for object self.
421 * @param pszDescription, [in,out] use to return the description of the proper object.
422 * @return S_OK if successful and E_FAIL if failure.
424 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accDescription(VARIANT varChild, BSTR *pszDescription)
426 SolarMutexGuard g;
428 ENTER_PROTECTED_BLOCK
429 ISDESTROY()
430 // #CHECK#
431 if(pszDescription == nullptr)
433 return E_INVALIDARG;
435 if(varChild.vt==VT_I4)
437 if(varChild.lVal==CHILDID_SELF)
439 SAFE_SYSFREESTRING(*pszDescription);
440 *pszDescription = SysAllocString(m_pszDescription);
441 return S_OK;
444 long lVal = varChild.lVal;
445 varChild.lVal = CHILDID_SELF;
446 IMAccessible *pChild = this->GetChildInterface(lVal);
447 if(!pChild)
448 return E_FAIL;
449 return pChild->get_accDescription(varChild,pszDescription);
451 return S_FALSE;
453 LEAVE_PROTECTED_BLOCK
457 * Returns the accessible role of the current COM object self or its one child to AT.
458 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
459 * the child ID specify child index from 0 to children count, 0 stands for object self.
460 * @param pvarRole, [in,out] use to return the role of the proper object.
461 * @return S_OK if successful and S_FALSE if failure.
463 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accRole(VARIANT varChild, VARIANT *pvarRole)
465 SolarMutexGuard g;
467 ENTER_PROTECTED_BLOCK
468 ISDESTROY()
469 // #CHECK#
470 if(pvarRole == nullptr)
472 return E_INVALIDARG;
474 if(varChild.vt == VT_I4)
477 if(varChild.lVal == CHILDID_SELF)
479 if( m_iRole < IA2_ROLE_CAPTION )
481 VariantInit(pvarRole);
482 pvarRole->vt = VT_I4;
483 pvarRole->lVal = m_iRole;
485 else
487 VariantInit(pvarRole);
488 pvarRole->vt = VT_I4;
489 pvarRole->lVal = ROLE_SYSTEM_CLIENT;
491 return S_OK;
495 long lVal = varChild.lVal;
496 varChild.lVal = CHILDID_SELF;
497 IMAccessible *pChild = this->GetChildInterface(lVal);
498 if(!pChild)
499 return E_FAIL;
500 return pChild->get_accRole(varChild,pvarRole);
502 return S_FALSE;
504 LEAVE_PROTECTED_BLOCK
508 * Returns the accessible state of the current COM object self or its one child to AT.
509 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
510 * the child ID specify child index from 0 to children count, 0 stands for object self.
511 * @param pvarState, [in,out] use to return the state of the proper object.
512 * @return S_OK if successful and S_FALSE if failure.
514 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accState(VARIANT varChild, VARIANT *pvarState)
516 SolarMutexGuard g;
518 ENTER_PROTECTED_BLOCK
519 ISDESTROY()
520 // #CHECK#
521 if(pvarState == nullptr)
523 return E_INVALIDARG;
525 if(varChild.vt==VT_I4)
527 if(varChild.lVal == CHILDID_SELF)
529 if (m_xAccessible.is())
531 Reference<XAccessibleContext> const pContext =
532 m_xAccessible->getAccessibleContext();
533 if(pContext.is())
535 // add the STATE_SYSTEM_LINKED state
536 Reference< XAccessibleHypertext > pRHypertext(pContext,UNO_QUERY);
537 if(pRHypertext.is())
539 if( pRHypertext->getHyperLinkCount() > 0 )
540 m_dState |= STATE_SYSTEM_LINKED;
541 else
542 m_dState &= ~STATE_SYSTEM_LINKED;
544 else
545 m_dState &= ~STATE_SYSTEM_LINKED;
549 VariantInit(pvarState);
550 pvarState->vt = VT_I4;
551 pvarState->lVal = m_dState;
552 return S_OK;
555 long lVal = varChild.lVal;
556 varChild.lVal = CHILDID_SELF;
557 IMAccessible *pChild = this->GetChildInterface(lVal);
558 if(!pChild)
559 return E_FAIL;
560 return pChild->get_accState(varChild,pvarState);
562 return S_FALSE;
564 LEAVE_PROTECTED_BLOCK
568 * Returns the accessible helpString of the current COM object self or its one child to AT.
569 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
570 * the child ID specify child index from 0 to children count, 0 stands for object self.
571 * @param pszHelp, [in,out] use to return the helpString of the proper object.
572 * @return S_OK if successful and E_FAIL if failure.
574 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accHelp(VARIANT, BSTR *)
576 return E_NOTIMPL;
580 * Returns the accessible HelpTopic of the current COM object self or its one child to AT.
581 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
582 * the child ID specify child index from 0 to children count, 0 stands for object self.
583 * @param pszHelpFile, [in,out] use to return the HelpTopic of the proper object.
584 * @param pidTopic, use to return the HelpTopic ID of the proper object.
585 * @return S_OK if successful and E_FAIL if failure.
586 * Not implemented yet
588 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
590 return E_NOTIMPL;
593 static bool GetMnemonicChar( const OUString& aStr, sal_Unicode* wStr)
595 for (sal_Int32 i = 0;; i += 2) {
596 i = aStr.indexOf('~', i);
597 if (i == -1 || i == aStr.getLength() - 1) {
598 return false;
600 auto c = aStr[i + 1];
601 if (c != '~') {
602 *wStr = c;
603 return true;
609 * Returns the accessible keyboard shortcut of the current COM object self or its one child to AT.
610 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
611 * the child ID specify child index from 0 to children count, 0 stands for object self.
612 * @param pszKeyboardShortcut, [in,out] use to return the kbshortcut of the proper object.
613 * @return S_OK if successful and E_FAIL if failure.
615 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut)
617 SolarMutexGuard g;
619 ENTER_PROTECTED_BLOCK
621 ISDESTROY()
622 // #CHECK#
623 if(pszKeyboardShortcut == nullptr)
625 return E_INVALIDARG;
628 if(varChild.vt==VT_I4)
630 if(varChild.lVal == CHILDID_SELF)
632 if (m_xAccessible.is())
634 Reference<XAccessibleContext> const pRContext =
635 m_xAccessible->getAccessibleContext();
636 if( !pRContext.is() )
637 return S_FALSE;
639 Reference<XAccessibleAction> pRXI(pRContext,UNO_QUERY);
641 OUString wString;
643 if( pRXI.is() && pRXI->getAccessibleActionCount() >= 1)
645 Reference< XAccessibleKeyBinding > binding = pRXI->getAccessibleActionKeyBinding(0);
646 if( binding.is() )
648 long nCount = binding->getAccessibleKeyBindingCount();
649 if(nCount >= 1)
651 wString = comphelper::GetkeyBindingStrByXkeyBinding( binding->getAccessibleKeyBinding(0) );
655 if(wString.isEmpty())
657 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
658 if(!pRrelationSet.is())
660 return S_FALSE;
663 long nRelCount = pRrelationSet->getRelationCount();
665 // Modified by Steve Yin, for SODC_1552
666 if( /*nRelCount <= 0 &&*/ m_iRole == ROLE_SYSTEM_TEXT )
668 VARIANT varParentRole;
669 VariantInit( &varParentRole );
671 if (m_pIParent
672 && SUCCEEDED(m_pIParent->get_accRole(varChild, &varParentRole))
673 && varParentRole.lVal == ROLE_SYSTEM_COMBOBOX) // edit in comboBox
675 m_pIParent->get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
676 return S_OK;
680 AccessibleRelation *paccRelation = nullptr;
681 AccessibleRelation accRelation;
682 for(int i=0; i<nRelCount ; i++)
684 if( pRrelationSet->getRelation(i).RelationType == 6 )
686 accRelation = pRrelationSet->getRelation(i);
687 paccRelation = &accRelation;
691 if(paccRelation == nullptr)
692 return S_FALSE;
694 Sequence< Reference< XInterface > > xTargets = paccRelation->TargetSet;
695 Reference<XInterface> pRAcc = xTargets[0];
697 XAccessible* pXAcc = static_cast<XAccessible*>(pRAcc.get());
699 Reference<XAccessibleContext> pRLebelContext = pXAcc->getAccessibleContext();
700 if(!pRLebelContext.is())
701 return S_FALSE;
703 pRrelationSet = pRLebelContext->getAccessibleRelationSet();
704 nRelCount = pRrelationSet->getRelationCount();
706 paccRelation = nullptr;
707 for(int j=0; j<nRelCount ; j++)
709 if( pRrelationSet->getRelation(j).RelationType == 5 )
711 accRelation = pRrelationSet->getRelation(j);
712 paccRelation = &accRelation;
716 if(paccRelation)
718 xTargets = paccRelation->TargetSet;
719 pRAcc = xTargets[0];
720 if (m_xAccessible.get() != static_cast<XAccessible*>(pRAcc.get()))
721 return S_FALSE;
724 Reference<XAccessibleExtendedComponent> pRXIE(pRLebelContext,UNO_QUERY);
725 if(!pRXIE.is())
726 return S_FALSE;
728 OUString ouStr = pRXIE->getTitledBorderText();
729 sal_Unicode key;
730 if(GetMnemonicChar(ouStr, &key))
732 wString = "Alt+" + OUStringChar(key);
734 else
735 return S_FALSE;
738 SAFE_SYSFREESTRING(*pszKeyboardShortcut);
739 *pszKeyboardShortcut = SysAllocString(o3tl::toW(wString.getStr()));
741 return S_OK;
743 else
745 return S_FALSE;
749 long lVal = varChild.lVal;
750 varChild.lVal = CHILDID_SELF;
751 IMAccessible *pChild = this->GetChildInterface(lVal);
752 if(!pChild)
753 return E_FAIL;
755 return pChild->get_accKeyboardShortcut(varChild,pszKeyboardShortcut);
757 return S_FALSE;
759 LEAVE_PROTECTED_BLOCK
763 * Returns the current focused child to AT.
764 * @param pvarChild, [in,out] vt member of pvarChild must be VT_I4,and lVal member stores the child ID,
765 * the child ID specify child index from 0 to children count, 0 stands for object self.
766 * @return S_OK if successful and E_FAIL if failure.
768 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accFocus(VARIANT *pvarChild)
770 SolarMutexGuard g;
772 ENTER_PROTECTED_BLOCK
773 ISDESTROY()
774 // #CHECK#
775 if(pvarChild == nullptr)
777 return E_INVALIDARG;
779 if( m_dFocusChildID==UACC_NO_FOCUS )
781 pvarChild->vt = VT_EMPTY;//no focus on the object and its children
782 return S_OK;
784 //if the descendant of current object has focus indicated by m_dFocusChildID, return the IDispatch of this focused object
785 else
787 IMAccessible* pIMAcc = nullptr;
788 g_pAgent->GetIAccessibleFromResID(m_dFocusChildID,&pIMAcc);
789 if (pIMAcc == nullptr)
791 return E_FAIL;
793 pIMAcc->AddRef();
794 pvarChild->vt = VT_DISPATCH;
795 pvarChild->pdispVal = pIMAcc;
798 return S_OK;
800 LEAVE_PROTECTED_BLOCK
804 * Returns the selection of the current COM object to AT.
805 * @param pvarChildren,[in,out]
806 * if selection num is 0,return VT_EMPTY for vt,
807 * if selection num is 1,return VT_I4 for vt,and child index for lVal
808 * if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
809 * @return S_OK if successful and S_FALSE if failure.
811 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accSelection(VARIANT *pvarChildren)
813 SolarMutexGuard g;
815 ENTER_PROTECTED_BLOCK
816 ISDESTROY()
817 // #CHECK#
818 if(pvarChildren == nullptr)
820 return E_INVALIDARG;
822 switch(m_pEnumVar->GetCountOfElements())
824 case 0:
825 pvarChildren->vt = VT_EMPTY;
826 break;
827 case 1:
828 VARIANT varTmp[1];
829 ULONG count;
830 VariantInit(&varTmp[0]);
831 m_pEnumVar->Next(1,varTmp,&count);
832 if(count!=1)
833 return S_FALSE;
834 pvarChildren->vt = VT_I4;
835 pvarChildren->lVal = varTmp[0].lVal;
836 VariantClear(&varTmp[0]);
837 m_pEnumVar->Reset();
838 break;
839 default:
840 pvarChildren->vt = VT_UNKNOWN;
841 m_pEnumVar->AddRef();
842 pvarChildren->punkVal = m_pEnumVar;
843 break;
845 return S_OK;
847 LEAVE_PROTECTED_BLOCK
851 * Returns the location of the current COM object self or its one child to AT.
852 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
853 * the child ID specify child index from 0 to children count, 0 stands for object self.
854 * @param pxLeft, [in,out] use to return the x-coordination of the proper object.
855 * @param pyTop, [in,out] use to return the y-coordination of the proper object.
856 * @param pcxWidth, [in,out] use to return the x-coordination width of the proper object.
857 * @param pcyHeight, [in,out] use to return the y-coordination height of the proper object.
858 * @return S_OK if successful and S_FALSE if failure.
860 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild)
862 SolarMutexGuard g;
864 ENTER_PROTECTED_BLOCK
865 ISDESTROY()
866 // #CHECK#
867 if(pxLeft == nullptr || pyTop == nullptr || pcxWidth == nullptr || pcyHeight == nullptr)
869 return E_INVALIDARG;
872 if(varChild.vt==VT_I4)
874 if(varChild.lVal==CHILDID_SELF)
877 if (m_xAccessible.is())
879 Reference<XAccessibleContext> const pRContext =
880 m_xAccessible->getAccessibleContext();
881 if( !pRContext.is() )
882 return S_FALSE;
883 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
884 if( !pRComponent.is() )
885 return S_FALSE;
887 css::awt::Point pCPoint = pRComponent->getLocationOnScreen();
888 css::awt::Size pCSize = pRComponent->getSize();
889 *pxLeft = pCPoint.X;
890 *pyTop = pCPoint.Y;
891 *pcxWidth = pCSize.Width;
892 *pcyHeight = pCSize.Height;
893 return S_OK;
895 else
897 *pxLeft = m_sLocation.m_dLeft;
898 *pyTop = m_sLocation.m_dTop;
899 *pcxWidth = m_sLocation.m_dWidth;
900 *pcyHeight = m_sLocation.m_dHeight;
901 return S_OK;
906 return S_FALSE;
908 LEAVE_PROTECTED_BLOCK
912 * Returns the current focused child to AT.
913 * @param navDir, the direction flag of the navigation.
914 * @param varStart, the start child id of this navigation action.
915 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
916 * @return S_OK if successful and E_FAIL if failure.
918 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt)
920 SolarMutexGuard g;
922 ENTER_PROTECTED_BLOCK
923 ISDESTROY()
924 // #CHECK#
925 if(pvarEndUpAt == nullptr)
927 return E_INVALIDARG;
929 HRESULT ret = E_FAIL;
930 switch (navDir)
932 case NAVDIR_FIRSTCHILD:
933 ret = GetFirstChild(varStart,pvarEndUpAt);
934 break;
935 case NAVDIR_LASTCHILD:
936 ret = GetLastChild(varStart,pvarEndUpAt);
937 break;
938 case NAVDIR_NEXT:
939 ret = GetNextSibling(varStart,pvarEndUpAt);
940 break;
941 case NAVDIR_PREVIOUS:
942 ret = GetPreSibling(varStart,pvarEndUpAt);
943 break;
944 case NAVDIR_DOWN://do not implement temporarily
945 break;
946 case NAVDIR_UP://do not implement temporarily
947 break;
948 case NAVDIR_LEFT://do not implement temporarily
949 break;
950 case NAVDIR_RIGHT://do not implement temporarily
951 break;
952 default:
953 break;
955 return ret;
957 LEAVE_PROTECTED_BLOCK
960 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarChild)
962 SolarMutexGuard g;
964 ENTER_PROTECTED_BLOCK
965 ISDESTROY()
966 // #CHECK#
967 if(pvarChild == nullptr)
969 return E_INVALIDARG;
971 long x, y, w, h;
972 VARIANT varSelf;
973 VariantInit(&varSelf);
974 varSelf.vt = VT_I4;
975 varSelf.lVal = CHILDID_SELF;
976 accLocation(&x,&y,&w,&h,varSelf);
977 if( (x < xLeft && (x + w) >xLeft) && (y < yTop && (y + h) >yTop) )
979 int i, nCount;
980 pvarChild->vt = VT_EMPTY;
981 Reference< XAccessibleContext > pRContext = GetContextByXAcc(m_xAccessible.get());
982 nCount = pRContext->getAccessibleChildCount();
983 if(nCount > 256)
984 return E_FAIL;
985 IMAccessible* child = nullptr;
986 for( i = 0; i<nCount; i++)
989 child = GetChildInterface(i + 1);
990 if(child && child->accHitTest(xLeft,yTop,pvarChild) == S_OK)
991 break;
994 if(pvarChild->vt == VT_DISPATCH)
995 return S_OK;
997 if( i < nCount)
999 pvarChild->vt = VT_DISPATCH;
1000 pvarChild->pdispVal = child;
1001 child->AddRef();
1003 else
1005 pvarChild->vt = VT_I4;
1006 pvarChild->lVal = CHILDID_SELF;
1008 return S_OK;
1010 return S_FALSE;
1012 LEAVE_PROTECTED_BLOCK
1016 * Get The other Interface from CMAccessible.
1017 * @param guidService, must be IID_IAccessible here.
1018 * @param riid, the IID interface .
1019 * @return S_OK if successful and S_FALSE if failure.
1021 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::QueryService(REFGUID guidService, REFIID riid, void** ppvObject)
1023 if( InlineIsEqualGUID(guidService, IID_IAccessible) )
1024 return QueryInterface(riid, ppvObject);
1025 return S_FALSE;
1029 * Set the accessible name of the current COM object self or its one child from UNO.
1030 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1031 * the child ID specify child index from 0 to children count, 0 stands for object self.
1032 * @param szName, the name used to set the name of the proper object.
1033 * @return S_OK if successful and E_FAIL if failure.
1035 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::put_accName(VARIANT varChild, BSTR szName)
1037 SolarMutexGuard g;
1039 ENTER_PROTECTED_BLOCK
1040 ISDESTROY()
1041 if(varChild.vt==VT_I4)
1043 if(varChild.lVal==CHILDID_SELF)
1045 SAFE_SYSFREESTRING(m_pszName);
1046 m_pszName=SysAllocString(szName);
1047 return S_OK;
1050 long lVal = varChild.lVal;
1051 varChild.lVal = CHILDID_SELF;
1052 IMAccessible *pChild = this->GetChildInterface(lVal);
1053 if(!pChild)
1054 return E_FAIL;
1055 return pChild->put_accName(varChild,szName);
1057 return E_FAIL;
1059 LEAVE_PROTECTED_BLOCK
1063 * Set the accessible value of the current COM object self or its one child from UNO.
1064 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1065 * the child ID specify child index from 0 to children count, 0 stands for object self.
1066 * @param szValue, the value used to set the value of the proper object.
1067 * @return S_OK if successful and E_FAIL if failure.
1069 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::put_accValue(VARIANT varChild, BSTR szValue)
1071 SolarMutexGuard g;
1073 ENTER_PROTECTED_BLOCK
1074 ISDESTROY()
1075 if(varChild.vt==VT_I4)
1077 if(varChild.lVal==CHILDID_SELF)
1079 SAFE_SYSFREESTRING(m_pszValue);
1080 m_pszValue=SysAllocString(szValue);
1081 return S_OK;
1084 long lVal = varChild.lVal;
1085 varChild.lVal = CHILDID_SELF;
1086 IMAccessible *pChild = this->GetChildInterface(lVal);
1087 if(!pChild)
1088 return E_FAIL;
1089 return pChild->put_accValue(varChild,szValue);
1091 return E_FAIL;
1093 LEAVE_PROTECTED_BLOCK
1097 * Set the accessible name of the current COM object self from UNO.
1098 * @param pszName, the name value used to set the name of the current object.
1099 * @return S_OK if successful and E_FAIL if failure.
1101 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR *pszName)
1103 // internal IMAccessible - no mutex meeded
1105 ENTER_PROTECTED_BLOCK
1106 ISDESTROY()
1107 // #CHECK#
1108 if(pszName == nullptr)
1110 return E_INVALIDARG;
1113 SAFE_SYSFREESTRING(m_pszName);
1114 m_pszName = SysAllocString(pszName);
1115 if(m_pszName==nullptr)
1116 return E_FAIL;
1117 return S_OK;
1119 LEAVE_PROTECTED_BLOCK
1123 * Set the accessible role of the current COM object self from UNO.
1124 * @param pRole, the role value used to set the role of the current object.
1125 * @return S_OK if successful and E_FAIL if failure.
1127 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccRole(unsigned short pRole)
1129 // internal IMAccessible - no mutex meeded
1131 m_iRole = pRole;
1132 return S_OK;
1136 * Add one state into the current state set for the current COM object from UNO.
1137 * @param pXSate, the state used to set the name of the current object.
1138 * @return S_OK if successful and E_FAIL if failure.
1140 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::DecreaseState(DWORD pXSate)
1142 // internal IMAccessible - no mutex meeded
1144 m_dState &= (~pXSate);
1145 return S_OK;
1149 * Delete one state into the current state set for the current COM object from UNO.
1150 * @param pXSate, the state used to set the name of the current object.
1151 * @return S_OK if successful and E_FAIL if failure.
1153 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::IncreaseState(DWORD pXSate)
1155 // internal IMAccessible - no mutex meeded
1157 m_dState |= pXSate;
1158 return S_OK;
1162 * Set state into the current state set for the current COM object from UNO.
1163 * @param pXSate, the state used to set the name of the current object.
1164 * @return S_OK if successful and E_FAIL if failure.
1166 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::SetState(DWORD pXSate)
1168 // internal IMAccessible - no mutex meeded
1170 m_dState = pXSate;
1171 return S_OK;
1176 * Set the accessible description of the current COM object self from UNO.
1177 * @param pszDescription, the name used to set the description of the current object.
1178 * @return S_OK if successful and E_FAIL if failure.
1180 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccDescription(const OLECHAR __RPC_FAR *pszDescription)
1182 // internal IMAccessible - no mutex meeded
1184 ENTER_PROTECTED_BLOCK
1185 ISDESTROY()
1186 // #CHECK#
1187 if(pszDescription == nullptr)
1189 return E_INVALIDARG;
1192 SAFE_SYSFREESTRING(m_pszDescription);
1193 m_pszDescription = SysAllocString(pszDescription);
1195 if(m_pszDescription==nullptr)
1196 return E_FAIL;
1197 return S_OK;
1199 LEAVE_PROTECTED_BLOCK
1203 * Set the accessible value of the current COM object self from UNO.
1204 * @param pszAccValue, the name used to set the value of the current object.
1205 * @return S_OK if successful and E_FAIL if failure.
1207 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR *pszAccValue)
1209 // internal IMAccessible - no mutex meeded
1211 ENTER_PROTECTED_BLOCK
1212 ISDESTROY()
1213 // #CHECK#
1214 if(pszAccValue == nullptr)
1216 return E_INVALIDARG;
1218 SAFE_SYSFREESTRING(m_pszValue);
1219 m_pszValue = SysAllocString(pszAccValue);
1220 if(m_pszValue==nullptr)
1221 return E_FAIL;
1222 return S_OK;
1224 LEAVE_PROTECTED_BLOCK
1228 * Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
1229 * Object through the method AccessibleObjectFromWindow(...).
1230 * @param hwnd, the HWND used to set the value of the current object.
1231 * @return S_OK if successful and E_FAIL if failure.
1233 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccWindowHandle(HWND hwnd)
1235 // internal IMAccessible - no mutex meeded
1237 ENTER_PROTECTED_BLOCK
1238 ISDESTROY()
1239 m_hwnd = hwnd;
1240 return S_OK;
1242 LEAVE_PROTECTED_BLOCK
1246 * Set accessible focus by specifying child ID
1247 * @param dChildID, the child id identifies the focus child.
1248 * @return S_OK if successful and E_FAIL if failure.
1250 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccFocus(long dChildID)
1252 // internal IMAccessible - no mutex meeded
1254 ENTER_PROTECTED_BLOCK
1255 ISDESTROY()
1257 if(dChildID==CHILDID_SELF)
1259 if(m_pIParent)
1261 m_pIParent->Put_XAccFocus(m_dChildID);
1264 else
1266 m_dFocusChildID = dChildID;
1267 //traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
1268 //any of the ancestors, this id can be used to get the IAccessible of focused object.
1269 if(m_pIParent)
1271 m_pIParent->Put_XAccFocus(dChildID);
1274 return S_OK;
1276 LEAVE_PROTECTED_BLOCK
1280 *Set accessible object location for the current COM object
1281 * @param sLocation, the location of the current object.
1282 * @return S_OK if successful and E_FAIL if failure.
1284 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccLocation(const Location sLocation)
1286 // internal IMAccessible - no mutex meeded
1288 this->m_sLocation = sLocation;
1289 return S_OK;
1293 * Set accessible parent object for the current COM object if
1294 * the current object is a child of some COM object
1295 * @param pIParent, the parent of the current object.
1296 * @return S_OK if successful and E_FAIL if failure.
1298 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR *pIParent)
1300 // internal IMAccessible - no mutex meeded
1302 this->m_pIParent = pIParent;
1304 if(pIParent)
1305 m_pIParent->AddRef();
1307 return S_OK;
1311 * Set unique child id to COM
1312 * @param dChildID, the id of the current object.
1313 * @return S_OK if successful and E_FAIL if failure.
1315 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccChildID(long dChildID)
1317 // internal IMAccessible - no mutex meeded
1319 this->m_dChildID = dChildID;
1320 return S_OK;
1324 * Set AccObjectManagerAgent object pointer to COM
1325 * @param pAgent, the AccObjectManagerAgent point.
1326 * @return S_OK if successful and E_FAIL if failure.
1328 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccAgent(hyper pAgent)
1330 // internal IMAccessible - no mutex meeded
1332 g_pAgent = reinterpret_cast<AccObjectManagerAgent*>(pAgent);
1333 return S_OK;
1337 * When a UNO control disposing, it disposes its listeners,
1338 * then notify AccObject in bridge management, then notify
1339 * COM that the XAccessible is invalid,so set m_xAccessible as NULL
1340 * @param isDestroy, true is it needs to be destroyed.
1341 * @return S_OK if successful and E_FAIL if failure.
1343 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::NotifyDestroy(BOOL isDestroy)
1345 // internal IMAccessible - no mutex meeded
1347 m_isDestroy = isDestroy;
1348 m_xAccessible.clear();
1349 return S_OK;
1353 *private methods that help implement public functions
1357 * Return child interface pointer by child ID,note: need to call AddRef()
1358 * @param lChildID, specify child index,which AT(such as Inspect32) gives.
1359 * @return IMAccessible*, pointer to the corresponding child object.
1361 IMAccessible* CMAccessible::GetChildInterface(long dChildID)//for test
1363 if(dChildID<0)
1365 if(g_pAgent)
1367 IMAccessible* pIMAcc = nullptr;
1368 g_pAgent->GetIAccessibleFromResID(dChildID,&pIMAcc);
1369 return pIMAcc;
1371 return nullptr;
1373 else
1375 if (!m_xAccessible.is())
1376 return nullptr;
1378 Reference<XAccessibleContext> const pRContext =
1379 m_xAccessible->getAccessibleContext();
1380 if( !pRContext.is() )
1381 return nullptr;
1383 if(dChildID<1 || dChildID>pRContext->getAccessibleChildCount())
1384 return nullptr;
1386 IAccessible* pChild = nullptr;
1387 Reference< XAccessible > pXChild = pRContext->getAccessibleChild(dChildID-1);
1388 BOOL isGet = get_IAccessibleFromXAccessible(pXChild.get(), &pChild);
1390 if(!isGet)
1392 g_pAgent->InsertAccObj(pXChild.get(), m_xAccessible.get(),
1393 reinterpret_cast<sal_Int64>(m_hwnd));
1394 isGet = get_IAccessibleFromXAccessible(pXChild.get(), &pChild);
1397 if(isGet)
1399 IMAccessible* pIMAcc = static_cast<IMAccessible*>(pChild);
1400 return pIMAcc;
1404 return nullptr;
1408 * For List, tree and table,these roles belong to manage_descendant in UNO,
1409 * need to process specifically when navigate
1410 * @return BOOL, if it is descendantmanager, return true.
1412 BOOL CMAccessible::IsDescendantManage()
1415 return (m_iRole==ROLE_SYSTEM_LIST)||(m_iRole==ROLE_SYSTEM_OUTLINE)||(m_iRole==ROLE_SYSTEM_TABLE);
1419 * for descendantmanager circumstance,provide child interface when navigate
1420 * @param varCur, the current child.
1421 * @param flags, the navigation direction.
1422 * @return IMAccessible*, the child of the end up node.
1424 IMAccessible* CMAccessible::GetNavigateChildForDM(VARIANT varCur, short flags)
1427 XAccessibleContext* pXContext = GetContextByXAcc(m_xAccessible.get());
1428 if(pXContext==nullptr)
1430 return nullptr;
1433 int count = pXContext->getAccessibleChildCount();
1434 if(count<1)
1436 return nullptr;
1439 IMAccessible* pCurChild = nullptr;
1440 union {
1441 XAccessible* pChildXAcc;
1442 hyper nHyper = 0;
1444 Reference<XAccessible> pRChildXAcc;
1445 XAccessibleContext* pChildContext = nullptr;
1446 int index = 0,delta=0;
1447 switch(flags)
1449 case DM_FIRSTCHILD:
1450 pRChildXAcc = pXContext->getAccessibleChild(0);
1451 break;
1452 case DM_LASTCHILD:
1453 pRChildXAcc = pXContext->getAccessibleChild(count-1);
1454 break;
1455 case DM_NEXTCHILD:
1456 case DM_PREVCHILD:
1457 pCurChild = GetChildInterface(varCur.lVal);
1458 if(pCurChild==nullptr)
1460 return nullptr;
1462 pCurChild->GetUNOInterface(&nHyper);
1463 if(pChildXAcc==nullptr)
1465 return nullptr;
1467 pChildContext = GetContextByXAcc(pChildXAcc);
1468 if(pChildContext == nullptr)
1470 return nullptr;
1472 delta = (flags==DM_NEXTCHILD)?1:-1;
1473 //currently, getAccessibleIndexInParent is error in UNO for
1474 //some kind of List,such as ValueSet, the index will be less 1 than
1475 //what should be, need to fix UNO code
1476 index = pChildContext->getAccessibleIndexInParent()+delta;
1477 if((index>=0)&&(index<=count-1))
1479 pRChildXAcc = pXContext->getAccessibleChild(index);
1481 break;
1482 default:
1483 break;
1486 if(!pRChildXAcc.is())
1488 return nullptr;
1490 pChildXAcc = pRChildXAcc.get();
1491 g_pAgent->InsertAccObj(pChildXAcc, m_xAccessible.get());
1492 return g_pAgent->GetIMAccByXAcc(pChildXAcc);
1496 *the following 4 private methods are for accNavigate implementation
1500 * Return first child for parent container, process differently according
1501 * to whether it is descendant manage
1502 * @param varStart, the start child id of this navigation action.
1503 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1504 * @return S_OK if successful and E_FAIL if failure.
1506 HRESULT CMAccessible::GetFirstChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1509 ENTER_PROTECTED_BLOCK
1510 ISDESTROY()
1511 // #CHECK#
1512 if(pvarEndUpAt == nullptr)
1514 return E_INVALIDARG;
1516 if(varStart.vt != VT_I4)
1518 pvarEndUpAt->vt = VT_EMPTY;
1519 return E_INVALIDARG;
1522 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_FIRSTCHILD);
1523 if(pvarEndUpAt->pdispVal)
1525 pvarEndUpAt->pdispVal->AddRef();
1526 pvarEndUpAt->vt = VT_DISPATCH;
1527 return S_OK;
1530 pvarEndUpAt->vt = VT_EMPTY;
1531 return E_FAIL;
1533 LEAVE_PROTECTED_BLOCK
1537 * Return last child for parent container, process differently according
1538 * to whether it is descendant manage
1539 * @param varStart, the start child id of this navigation action.
1540 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1541 * @return S_OK if successful and E_FAIL if failure.
1543 HRESULT CMAccessible::GetLastChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1546 ENTER_PROTECTED_BLOCK
1547 ISDESTROY()
1548 // #CHECK#
1549 if(pvarEndUpAt == nullptr)
1551 return E_INVALIDARG;
1553 if(varStart.vt != VT_I4)
1555 pvarEndUpAt->vt = VT_EMPTY;
1556 return E_INVALIDARG;
1559 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_LASTCHILD);
1560 if(pvarEndUpAt->pdispVal)
1562 pvarEndUpAt->pdispVal->AddRef();
1563 pvarEndUpAt->vt = VT_DISPATCH;
1564 return S_OK;
1566 pvarEndUpAt->vt = VT_EMPTY;
1567 return E_FAIL;
1569 LEAVE_PROTECTED_BLOCK
1573 * The method GetNextSibling is general, whatever it is descendant manage or not
1574 * Get the next sibling object.
1575 * @param varStart, the start child id of this navigation action.
1576 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1577 * @return S_OK if successful and E_FAIL if failure.
1579 HRESULT CMAccessible::GetNextSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1582 ENTER_PROTECTED_BLOCK
1583 ISDESTROY()
1584 if(varStart.vt != VT_I4)
1586 pvarEndUpAt->vt = VT_EMPTY;
1587 return E_INVALIDARG;
1590 Reference<XAccessibleContext> const pRContext =
1591 GetContextByXAcc(m_xAccessible.get());
1592 if(pRContext.is())
1594 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent() + 2);
1595 if(m_pIParent)
1596 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1598 pvarEndUpAt->vt = VT_DISPATCH;
1599 return S_OK;
1602 pvarEndUpAt->vt = VT_EMPTY;
1603 return E_FAIL;
1605 LEAVE_PROTECTED_BLOCK
1609 *the method GetPreSibling is general, whatever it is descendant manage or not
1610 * @param varStart, the start child id of this navigation action.
1611 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1612 * @return S_OK if successful and E_FAIL if failure.
1614 HRESULT CMAccessible::GetPreSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1617 ENTER_PROTECTED_BLOCK
1618 ISDESTROY()
1619 // #CHECK#
1620 if(pvarEndUpAt == nullptr)
1622 return E_INVALIDARG;
1624 if(varStart.vt != VT_I4)
1626 pvarEndUpAt->vt = VT_EMPTY;
1627 return E_INVALIDARG;
1630 Reference<XAccessibleContext> const pRContext =
1631 GetContextByXAcc(m_xAccessible.get());
1632 if(pRContext.is())
1634 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent());
1635 if(m_pIParent && varStart.iVal > 0)
1636 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1638 pvarEndUpAt->vt = VT_DISPATCH;
1639 return S_OK;
1642 pvarEndUpAt->vt = VT_EMPTY;
1643 return E_FAIL;
1645 LEAVE_PROTECTED_BLOCK
1649 * For IAccessible2 implementation methods
1651 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_nRelations( long __RPC_FAR *nRelations)
1653 SolarMutexGuard g;
1655 ENTER_PROTECTED_BLOCK
1656 ISDESTROY()
1658 // #CHECK#
1659 if(nRelations == nullptr)
1661 return E_INVALIDARG;
1664 *nRelations = 0;
1666 if (!m_xContext.is())
1667 return E_FAIL;
1668 Reference<XAccessibleRelationSet> pRrelationSet =
1669 m_xContext.get()->getAccessibleRelationSet();
1670 if(!pRrelationSet.is())
1672 *nRelations = 0;
1673 return S_OK;
1676 *nRelations = pRrelationSet->getRelationCount();
1677 return S_OK;
1679 LEAVE_PROTECTED_BLOCK
1682 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_relation( long relationIndex, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation)
1684 SolarMutexGuard g;
1686 ENTER_PROTECTED_BLOCK
1687 ISDESTROY()
1688 // #CHECK#
1689 if(relation == nullptr)
1691 return E_INVALIDARG;
1694 if (!m_xContext.is())
1695 return E_FAIL;
1698 long nMax = 0;
1699 get_nRelations(&nMax);
1701 *relation = static_cast<IAccessibleRelation*>(::CoTaskMemAlloc(sizeof(IAccessibleRelation)));
1703 // #CHECK Memory Allocation#
1704 if(*relation == nullptr)
1706 return E_FAIL;
1709 if( relationIndex < nMax )
1711 Reference<XAccessibleRelationSet> const pRrelationSet =
1712 m_xContext.get()->getAccessibleRelationSet();
1713 if(!pRrelationSet.is())
1716 return E_FAIL;
1719 IAccessibleRelation* pRelation = nullptr;
1720 HRESULT hr = createInstance<CAccRelation>(IID_IAccessibleRelation,
1721 &pRelation);
1722 if(SUCCEEDED(hr))
1724 IUNOXWrapper* wrapper = nullptr;
1725 hr = pRelation->QueryInterface(IID_IUNOXWrapper, reinterpret_cast<void**>(&wrapper));
1726 if(SUCCEEDED(hr))
1728 AccessibleRelation accRelation = pRrelationSet->getRelation(relationIndex);
1729 wrapper->put_XSubInterface(
1730 reinterpret_cast<hyper>(&accRelation));
1731 wrapper->Release();
1732 *relation = pRelation;
1733 return S_OK;
1739 return E_FAIL;
1741 LEAVE_PROTECTED_BLOCK
1744 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation, long __RPC_FAR *nRelations)
1746 SolarMutexGuard g;
1748 ENTER_PROTECTED_BLOCK
1749 ISDESTROY()
1751 // #CHECK#
1752 if(relation == nullptr || nRelations == nullptr)
1754 return E_INVALIDARG;
1756 // #CHECK XInterface#
1758 if (!m_xContext.is())
1759 return E_FAIL;
1761 Reference<XAccessibleRelationSet> const pRrelationSet =
1762 m_xContext.get()->getAccessibleRelationSet();
1763 if(!pRrelationSet.is())
1765 *nRelations = 0;
1766 return S_OK;
1769 long nCount = pRrelationSet->getRelationCount();
1771 *relation = static_cast<IAccessibleRelation*>(::CoTaskMemAlloc(nCount*sizeof(IAccessibleRelation)));
1773 // #CHECK Memory Allocation#
1774 if(*relation == nullptr)
1776 return E_FAIL;
1779 for(int i=0; i<nCount ; i++)
1781 IAccessibleRelation* pRelation = nullptr;
1782 HRESULT hr = createInstance<CAccRelation>(IID_IAccessibleRelation,
1783 &pRelation);
1784 if(SUCCEEDED(hr))
1786 IUNOXWrapper* wrapper = nullptr;
1787 hr = pRelation->QueryInterface(IID_IUNOXWrapper, reinterpret_cast<void**>(&wrapper));
1788 if(SUCCEEDED(hr))
1790 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1791 wrapper->put_XSubInterface(
1792 reinterpret_cast<hyper>(&accRelation));
1793 wrapper->Release();
1795 relation[i] = pRelation;
1799 *nRelations = nCount;
1800 return S_OK;
1802 LEAVE_PROTECTED_BLOCK
1805 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::role(long __RPC_FAR *role)
1807 SolarMutexGuard g;
1809 ENTER_PROTECTED_BLOCK
1811 (*role) = m_iRole;
1813 return S_OK;
1815 LEAVE_PROTECTED_BLOCK
1819 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_nActions(long __RPC_FAR *nActions)
1821 SolarMutexGuard g;
1825 ISDESTROY()
1826 // #CHECK#
1827 if(nActions == nullptr)
1829 return E_INVALIDARG;
1831 *nActions = 0;
1832 IAccessibleAction* pAcc = nullptr;
1833 HRESULT hr = QueryInterface(IID_IAccessibleAction, reinterpret_cast<void**>(&pAcc));
1834 if( hr == S_OK )
1836 pAcc->nActions(nActions);
1837 pAcc->Release();
1840 return S_OK;
1842 catch(...)
1844 *nActions = 0;
1845 return S_OK;
1850 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: scrollToPoint(enum IA2CoordinateType, long, long)
1852 return E_NOTIMPL;
1855 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: scrollTo(enum IA2ScrollType)
1857 return E_NOTIMPL;
1860 static XAccessible* getTheParentOfMember(XAccessible* pXAcc)
1862 // #CHECK#
1863 if(pXAcc == nullptr)
1865 return nullptr;
1867 Reference<XAccessibleContext> pRContext = pXAcc->getAccessibleContext();
1868 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1869 sal_Int32 nRelations = pRrelationSet->getRelationCount();
1870 for(sal_Int32 i=0 ; i<nRelations ; i++)
1872 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1873 if(accRelation.RelationType == 7)
1875 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1876 return static_cast<XAccessible*>(xTargets[0].get());
1879 return nullptr;
1882 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_groupPosition(long __RPC_FAR *groupLevel,long __RPC_FAR *similarItemsInGroup,long __RPC_FAR *positionInGroup)
1884 SolarMutexGuard g;
1886 ENTER_PROTECTED_BLOCK
1887 ISDESTROY()
1888 // #CHECK#
1889 if(groupLevel == nullptr || similarItemsInGroup == nullptr || positionInGroup == nullptr)
1891 return E_INVALIDARG;
1894 if (!m_xAccessible.is())
1895 return E_FAIL;
1897 Reference<XAccessibleContext> const pRContext =
1898 m_xAccessible->getAccessibleContext();
1899 if(!pRContext.is())
1900 return E_FAIL;
1901 long Role = pRContext->getAccessibleRole();
1903 *groupLevel = 0;
1904 *similarItemsInGroup = 0;
1905 *positionInGroup = 0;
1907 if (Role != AccessibleRole::DOCUMENT && Role != AccessibleRole::DOCUMENT_PRESENTATION &&
1908 Role != AccessibleRole::DOCUMENT_SPREADSHEET && Role != AccessibleRole::DOCUMENT_TEXT)
1910 Reference< XAccessibleGroupPosition > xGroupPosition( pRContext, UNO_QUERY );
1911 if ( xGroupPosition.is() )
1913 Sequence< sal_Int32 > rSeq = xGroupPosition->getGroupPosition( makeAny( pRContext ) );
1914 if (rSeq.getLength() >= 3)
1916 *groupLevel = rSeq[0];
1917 *similarItemsInGroup = rSeq[1];
1918 *positionInGroup = rSeq[2];
1919 return S_OK;
1921 return S_OK;
1925 Reference< XAccessible> pParentAcc = pRContext->getAccessibleParent();
1926 if( !pParentAcc.is() )
1928 return S_OK;
1931 Reference<XAccessibleContext> pRParentContext = pParentAcc->getAccessibleContext();
1933 if( Role == RADIO_BUTTON )
1935 int index = 0;
1936 int number = 0;
1937 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1938 long nRel = pRrelationSet->getRelationCount();
1939 for(int i=0 ; i<nRel ; i++)
1941 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1942 if(accRelation.RelationType == 7)
1944 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1946 Reference<XInterface> pRAcc = xTargets[0];
1947 for(int j=0; j<pRParentContext->getAccessibleChildCount(); j++)
1949 if( getTheParentOfMember(pRParentContext->getAccessibleChild(j).get())
1950 == static_cast<XAccessible*>(pRAcc.get()) &&
1951 pRParentContext->getAccessibleChild(j)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON)
1952 number++;
1953 if (pRParentContext->getAccessibleChild(j).get() == m_xAccessible.get())
1954 index = number;
1958 *groupLevel = 1;
1959 *similarItemsInGroup = number;
1960 *positionInGroup = index;
1961 return S_OK;
1964 else if ( COMBO_BOX == Role )
1966 *groupLevel = 1;
1967 *similarItemsInGroup = 0;
1968 *positionInGroup = -1;
1970 long nCount = pRContext->getAccessibleChildCount();
1971 if( 2 != nCount)
1973 return S_OK;
1975 Reference<XAccessible> xList=pRContext->getAccessibleChild(1);
1976 if (!xList.is())
1978 return S_OK;
1980 Reference<XAccessibleContext> xListContext(xList,UNO_QUERY);
1981 if (!xListContext.is())
1983 return S_OK;
1985 Reference<XAccessibleSelection> xListSel(xList,UNO_QUERY);
1986 if (!xListSel.is())
1988 return S_OK;
1990 *similarItemsInGroup = xListContext->getAccessibleChildCount();
1991 if (*similarItemsInGroup > 0 )
1995 Reference<XAccessible> xChild = xListSel->getSelectedAccessibleChild(0);
1996 if (xChild.is())
1998 Reference<XAccessibleContext> xChildContext(xChild,UNO_QUERY);
1999 if (xChildContext.is())
2001 *positionInGroup=xChildContext->getAccessibleIndexInParent() + 1 ;
2002 return S_OK;
2006 catch(...)
2009 return S_OK;
2011 else if ( PAGE_TAB == Role )
2013 *groupLevel = 1;
2014 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2016 if (*similarItemsInGroup > 0 )
2018 *positionInGroup=pRContext->getAccessibleIndexInParent() + 1 ;
2020 else
2022 *positionInGroup = -1;
2024 return S_OK;
2027 int level = 0;
2028 BOOL isFound = FALSE;
2029 while( pParentAcc.is() && !isFound)
2031 level++;
2032 pRParentContext = pParentAcc->getAccessibleContext();
2033 Role = pRParentContext->getAccessibleRole();
2034 if( (Role == TREE) || (Role == LIST) )
2035 isFound = TRUE;
2036 pParentAcc = pRParentContext->getAccessibleParent();
2039 if( isFound )
2041 Reference< XAccessible> pTempAcc = pRContext->getAccessibleParent();
2042 pRParentContext = pTempAcc->getAccessibleContext();
2043 *groupLevel = level;
2044 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2045 *positionInGroup = pRContext->getAccessibleIndexInParent() + 1;
2047 else
2049 *groupLevel = 0;
2050 *similarItemsInGroup = 0;
2051 *positionInGroup = 0;
2053 return S_OK;
2055 LEAVE_PROTECTED_BLOCK
2058 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_extendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
2060 return E_NOTIMPL;
2064 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_uniqueID(long __RPC_FAR *uniqueID)
2066 SolarMutexGuard g;
2068 ENTER_PROTECTED_BLOCK
2069 ISDESTROY()
2070 // #CHECK#
2071 if(uniqueID == nullptr)
2073 return E_INVALIDARG;
2075 *uniqueID = m_dChildID;
2076 return S_OK;
2078 LEAVE_PROTECTED_BLOCK
2081 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_windowHandle(HWND __RPC_FAR *windowHandle)
2083 SolarMutexGuard g;
2085 ENTER_PROTECTED_BLOCK
2086 ISDESTROY()
2087 // #CHECK#
2088 if(windowHandle == nullptr)
2090 return E_INVALIDARG;
2093 HWND nHwnd = m_hwnd;
2094 IAccessible* pParent = m_pIParent;
2095 while((nHwnd==nullptr) && pParent)
2097 if (CMAccessible* pChild = dynamic_cast<CMAccessible*>(pParent))
2099 pParent = pChild->m_pIParent;
2100 nHwnd = pChild->m_hwnd;
2102 else
2103 pParent = nullptr;
2106 *windowHandle = nHwnd;
2107 return S_OK;
2109 LEAVE_PROTECTED_BLOCK
2113 * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
2114 * @param pXAcc, UNO XAccessible object point.
2115 * @return XAccessibleContext*, the context of the pXAcc.
2117 XAccessibleContext* CMAccessible::GetContextByXAcc( XAccessible* pXAcc )
2119 Reference< XAccessibleContext > pRContext;
2120 if( pXAcc == nullptr)
2121 return nullptr;
2123 pRContext = pXAcc->getAccessibleContext();
2124 if( !pRContext.is() )
2125 return nullptr;
2126 return pRContext.get();
2130 * Return the member variable m_pXAccessibleSelection, instead of
2131 * get XAccessibleSelection according to XAccessibleContext because if so,it will
2132 * depend on the UNO implementation code,so when COM is created, put XAccessibleSelection
2133 * by bridge management system
2134 * @return XAccessibleSelection*, the selection of the current object.
2136 Reference< XAccessibleSelection > CMAccessible::GetSelection()
2138 if (!m_xAccessible.is())
2139 return nullptr;
2140 Reference<XAccessibleContext> const pRContext =
2141 m_xAccessible->getAccessibleContext();
2142 if(pRContext.is())
2144 Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
2145 return pRSelection;
2147 return nullptr;
2151 * Select one XAccessible item, for accSelect implementation
2152 * @param pItem, the item should be selected.
2153 * @return S_OK if successful.
2155 HRESULT CMAccessible::SelectChild(XAccessible* pItem)
2158 ENTER_PROTECTED_BLOCK
2159 ISDESTROY()
2160 XAccessibleContext* pParentContext = GetContextByXAcc(m_xAccessible.get());
2161 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2162 if( pParentContext == nullptr || pContext == nullptr )
2163 return E_FAIL;
2165 Reference< XAccessibleSelection > pRSelection = GetSelection();
2166 if( !pRSelection.is() )
2167 return E_FAIL;
2168 long Index = pContext->getAccessibleIndexInParent();
2169 pRSelection->selectAccessibleChild( Index );
2170 return S_OK;
2172 LEAVE_PROTECTED_BLOCK
2176 * Deselect one XAccessible item, for accSelect implementation
2177 * @param pItem, the item should be deselected.
2178 * @return S_OK if successful.
2180 HRESULT CMAccessible::DeSelectChild(XAccessible* pItem)
2183 ENTER_PROTECTED_BLOCK
2184 ISDESTROY()
2185 XAccessibleContext* pParentContext = GetContextByXAcc(m_xAccessible.get());
2187 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2188 if( pParentContext == nullptr || pContext == nullptr )
2189 return E_INVALIDARG;
2191 Reference< XAccessibleSelection > pRSelection = GetSelection();
2192 if( !pRSelection.is() )
2193 return E_FAIL;
2194 long Index = pContext->getAccessibleIndexInParent();
2195 pRSelection->deselectAccessibleChild( Index );
2197 return S_OK;
2199 LEAVE_PROTECTED_BLOCK
2203 * Select multiple XAccessible items,for implementation of accSelect
2204 * @param pItem, the items should be selected.
2205 * @param size, the size of the items.
2206 * @return S_OK if successful.
2208 HRESULT CMAccessible::SelectMultipleChidren( XAccessible** pItem,int size )
2211 ENTER_PROTECTED_BLOCK
2212 ISDESTROY()
2213 // #CHECK#
2214 if(pItem == nullptr)
2216 return E_INVALIDARG;
2218 for(int index = 0;index < size;index++)
2220 SelectChild( pItem[index] );
2222 return S_OK;
2224 LEAVE_PROTECTED_BLOCK
2228 * Deselect multiple XAccessible items,for implementation of accSelect
2229 * @param pItem, the items should be selected.
2230 * @param size, the size of the items.
2231 * @return S_OK if successful.
2233 HRESULT CMAccessible::DeSelectMultipleChildren( XAccessible** pItem,int size )
2236 ENTER_PROTECTED_BLOCK
2237 ISDESTROY()
2238 // #CHECK#
2239 if(pItem == nullptr)
2241 return E_INVALIDARG;
2243 for(int index = 0;index < size;index++)
2245 DeSelectChild( pItem[index] );
2247 return S_OK;
2249 LEAVE_PROTECTED_BLOCK
2253 * When COM is created, UNO set XAccessible pointer to it
2254 * in order to COM can operate UNO information
2255 * @param pXAcc, the XAccessible object of current object.
2256 * @return S_OK if successful.
2258 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::SetXAccessible(hyper pXAcc)
2260 // internal IMAccessible - no mutex meeded
2262 m_xAccessible = reinterpret_cast<XAccessible*>(pXAcc);
2263 m_pEnumVar->PutSelection(/*XAccessibleSelection*/
2264 reinterpret_cast<hyper>(m_xAccessible.get()));
2266 m_xContext = m_xAccessible->getAccessibleContext();
2268 return S_OK;
2272 * accSelect method has many optional flags, needs to process comprehensively
2273 * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
2274 * The implementation of this flag is a little trouble-shooting,so we also
2275 * do not implement it now
2276 * @param flagsSelect, the selection flag of the select action.
2277 * @param varChild, the child object pointer of current action.
2278 * @return S_OK if successful.
2280 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accSelect(long flagsSelect, VARIANT varChild)
2282 SolarMutexGuard g;
2284 ENTER_PROTECTED_BLOCK
2285 ISDESTROY()
2286 if( (flagsSelect&SELFLAG_ADDSELECTION) &&
2287 (SELFLAG_REMOVESELECTION&flagsSelect) )
2288 return E_INVALIDARG;
2290 if ( (flagsSelect&SELFLAG_TAKESELECTION) &&
2292 (flagsSelect&SELFLAG_ADDSELECTION) ||
2293 (flagsSelect&SELFLAG_REMOVESELECTION) ||
2294 (flagsSelect&SELFLAG_EXTENDSELECTION )
2297 return E_INVALIDARG;
2299 if ( varChild.vt != VT_I4 )
2300 return E_INVALIDARG;
2302 IMAccessible* pSelectAcc;
2303 if( varChild.lVal == CHILDID_SELF )
2305 pSelectAcc = this;
2306 pSelectAcc->AddRef();
2308 else
2310 pSelectAcc = GetChildInterface(varChild.lVal);
2313 if( pSelectAcc == nullptr )
2314 return E_INVALIDARG;
2316 if( flagsSelect&SELFLAG_TAKEFOCUS )
2318 union {
2319 XAccessible* pTempUNO;
2320 hyper nHyper = 0;
2322 pSelectAcc->GetUNOInterface(&nHyper);
2324 if( pTempUNO == nullptr )
2325 return NULL;
2327 Reference<XAccessibleContext> pRContext = pTempUNO->getAccessibleContext();
2328 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
2329 Reference< XAccessible > pRParentXAcc = pRContext->getAccessibleParent();
2330 Reference< XAccessibleContext > pRParentContext = pRParentXAcc->getAccessibleContext();
2331 Reference< XAccessibleComponent > pRParentComponent(pRParentContext,UNO_QUERY);
2332 Reference< XAccessibleSelection > pRParentSelection(pRParentContext,UNO_QUERY);
2335 pRComponent->grabFocus();
2337 if( flagsSelect & SELFLAG_TAKESELECTION )
2339 pRParentSelection->clearAccessibleSelection();
2340 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2343 if( flagsSelect & SELFLAG_ADDSELECTION )
2345 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2348 if( flagsSelect & SELFLAG_REMOVESELECTION )
2350 pRParentSelection->deselectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2353 if( flagsSelect & SELFLAG_EXTENDSELECTION )
2355 long indexInParrent = pRContext->getAccessibleIndexInParent();
2357 if( pRParentSelection->isAccessibleChildSelected( indexInParrent + 1 ) ||
2358 pRParentSelection->isAccessibleChildSelected( indexInParrent - 1 ) )
2360 pRParentSelection->selectAccessibleChild( indexInParrent );
2366 pSelectAcc->Release();
2367 return S_OK;
2369 LEAVE_PROTECTED_BLOCK
2373 * Return XAccessible interface pointer when needed
2374 * @param pXAcc, [in, out] the Uno interface of the current object.
2375 * @return S_OK if successful.
2377 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::GetUNOInterface(hyper * pXAcc)
2379 // internal IMAccessible - no mutex meeded
2381 if(pXAcc == nullptr)
2382 return E_INVALIDARG;
2384 *pXAcc = reinterpret_cast<hyper>(m_xAccessible.get());
2385 return S_OK;
2389 * Helper method for Implementation of get_accDefaultAction
2390 * @param pAction, the default action point of the current object.
2391 * @return S_OK if successful.
2393 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::SetDefaultAction(hyper pAction)
2395 // internal IMAccessible - no mutex meeded
2397 m_xAction = reinterpret_cast<XAccessibleAction*>(pAction);
2398 return S_OK;
2402 * This method is called when AT open some UI elements initially
2403 * the UI element takes the default action defined here
2404 * @param varChild, the child id of the defaultaction.
2405 * @param pszDefaultAction,[in/out] the description of the current action.
2406 * @return S_OK if successful.
2408 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE CMAccessible::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction)
2410 SolarMutexGuard g;
2412 ENTER_PROTECTED_BLOCK
2413 ISDESTROY()
2414 // #CHECK#
2415 if(pszDefaultAction == nullptr)
2417 return E_INVALIDARG;
2419 if(varChild.vt==VT_I4)
2421 if(varChild.lVal==CHILDID_SELF)
2423 if (!m_xAction.is())
2424 return DISP_E_MEMBERNOTFOUND;
2425 SAFE_SYSFREESTRING(*pszDefaultAction);
2426 *pszDefaultAction = SysAllocString(m_pszActionDescription);
2427 return S_OK;
2430 long lVal = varChild.lVal;
2431 varChild.lVal = CHILDID_SELF;
2432 IMAccessible *pChild = this->GetChildInterface(lVal);
2433 if(!pChild)
2434 return E_FAIL;
2435 return pChild->get_accDefaultAction(varChild,pszDefaultAction);
2437 return S_FALSE;
2439 LEAVE_PROTECTED_BLOCK
2443 * AT call this method to operate application
2444 * @param varChild, the child id of the action object.
2445 * @return S_OK if successful.
2447 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE CMAccessible::accDoDefaultAction(VARIANT varChild)
2449 SolarMutexGuard g;
2451 ENTER_PROTECTED_BLOCK
2452 ISDESTROY()
2453 if( varChild.vt != VT_I4 )
2454 return E_INVALIDARG;
2455 if (!m_xAction.is())
2456 return E_FAIL;
2457 if (m_xAction->getAccessibleActionCount() == 0)
2458 return E_FAIL;
2460 if(varChild.lVal==CHILDID_SELF)
2462 if (m_xAction->getAccessibleActionCount() > 0)
2463 m_xAction->doAccessibleAction(0);
2464 return S_OK;
2467 long lVal = varChild.lVal;
2468 varChild.lVal = CHILDID_SELF;
2469 IMAccessible *pChild = this->GetChildInterface(lVal);
2470 if(!pChild)
2471 return E_FAIL;
2472 return pChild->accDoDefaultAction( varChild );
2474 LEAVE_PROTECTED_BLOCK
2478 * UNO set description information for action to COM.
2479 * @param szAction, the action description of the current object.
2480 * @return S_OK if successful.
2482 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_ActionDescription( const OLECHAR* szAction)
2484 // internal IMAccessible - no mutex meeded
2486 ENTER_PROTECTED_BLOCK
2487 ISDESTROY()
2488 // #CHECK#
2489 if(szAction == nullptr)
2491 return E_INVALIDARG;
2493 SAFE_SYSFREESTRING(m_pszActionDescription );
2494 m_pszActionDescription = SysAllocString( szAction );
2495 return S_OK;
2497 LEAVE_PROTECTED_BLOCK
2500 BOOL CMAccessible::GetXInterfaceFromXAccessible(XAccessible* pXAcc, XInterface** ppXI, int index)
2502 Reference< XAccessibleContext > pRContext;
2504 switch(index)
2506 case XI_COMPONENT:
2507 QUERYXINTERFACE(AccessibleComponent)
2508 break;
2509 case XI_TEXT:
2510 QUERYXINTERFACE(AccessibleText)
2511 break;
2512 case XI_EDITABLETEXT:
2513 QUERYXINTERFACE(AccessibleEditableText)
2514 break;
2515 case XI_TABLE:
2516 QUERYXINTERFACE(AccessibleTable)
2517 break;
2518 case XI_SELECTION:
2519 QUERYXINTERFACE(AccessibleSelection)
2520 break;
2521 case XI_EXTENDEDCOMP:
2522 QUERYXINTERFACE(AccessibleExtendedComponent)
2523 break;
2524 case XI_KEYBINDING:
2525 QUERYXINTERFACE(AccessibleKeyBinding)
2526 break;
2527 case XI_ACTION:
2528 QUERYXINTERFACE(AccessibleAction)
2529 break;
2530 case XI_VALUE:
2531 QUERYXINTERFACE(AccessibleValue)
2532 break;
2533 case XI_HYPERTEXT:
2534 QUERYXINTERFACE(AccessibleHypertext)
2535 break;
2536 case XI_HYPERLINK:
2537 QUERYXINTERFACE(AccessibleHyperlink)
2538 break;
2539 case XI_IMAGE:
2540 QUERYXINTERFACE(AccessibleImage)
2541 break;
2542 default:
2543 break;
2546 return FALSE;
2549 template<typename T> static HRESULT
2550 createAggInstance(CMAccessible &rOuter, void ** ppvObject)
2552 // Note: CComAggObject has special handling for IUnknown - must
2553 // query for that when creating it! Otherwise we get a T member of it
2554 // which will redirect QueryInterface back to CMAccessible infinitely.
2555 // (CComAggObject has its own ref-count too which is not a problem
2556 // since it is inserted in m_containedObjects.)
2557 return CComCreator< CComAggObject<T> >::CreateInstance(
2558 rOuter.GetControllingUnknown(), IID_IUnknown, ppvObject);
2561 typedef HRESULT (AggCreatorFunc)(CMAccessible &, void **);
2563 struct AggMapEntry
2565 const IID* piid;
2566 AggCreatorFunc* pfnCreateInstance;
2567 int XIFIndex;
2570 static AggMapEntry g_CMAccessible_AggMap[] = {
2571 { &IID_IAccessibleComponent, &createAggInstance<CAccComponent>, XI_COMPONENT },
2572 { &IID_IAccessibleText, &createAggInstance<CAccText>, XI_TEXT },
2573 { &IID_IAccessibleEditableText, &createAggInstance<CAccEditableText>, XI_EDITABLETEXT },
2574 { &IID_IAccessibleImage, &createAggInstance<CAccImage>, XI_IMAGE },
2575 { &IID_IAccessibleTable, &createAggInstance<CAccTable>, XI_TABLE },
2576 { &IID_IAccessibleAction, &createAggInstance<CAccAction>, XI_ACTION },
2577 { &IID_IAccessibleValue, &createAggInstance<CAccValue>, XI_VALUE },
2578 { &IID_IAccessibleHypertext, &createAggInstance<CAccHypertext>, XI_HYPERTEXT },
2579 { &IID_IAccessibleHyperlink, &createAggInstance<CAccHyperLink>, XI_HYPERLINK },
2580 { nullptr, nullptr, 0 },
2584 HRESULT WINAPI CMAccessible::SmartQI(void* /*pv*/, REFIID iid, void** ppvObject)
2586 ENTER_PROTECTED_BLOCK
2588 ISDESTROY()
2589 if (InlineIsEqualGUID(iid,IID_IAccIdentity) ||
2590 InlineIsEqualGUID(iid,IID_IStdMarshalInfo) ||
2591 InlineIsEqualGUID(iid,IID_IMarshal) ||
2592 InlineIsEqualGUID(iid,IID_IExternalConnection)||
2593 InlineIsEqualGUID(iid,IID_IOleWindow))
2595 return E_FAIL;
2598 AggMapEntry * pMap = &g_CMAccessible_AggMap[0];
2599 while(pMap && pMap->piid)
2601 if (InlineIsEqualGUID(iid, *pMap->piid))
2603 SolarMutexGuard g;
2605 XInterface* pXI = nullptr;
2606 BOOL bFound = GetXInterfaceFromXAccessible(m_xAccessible.get(),
2607 &pXI, pMap->XIFIndex);
2608 if(!bFound)
2610 return E_FAIL;
2613 XGUIDToComObjHash::iterator pIndTemp = m_containedObjects.find( iid );
2614 if ( pIndTemp != m_containedObjects.end() )
2616 return pIndTemp->second.p->QueryInterface( iid, ppvObject );
2618 else
2620 HRESULT hr = pMap->pfnCreateInstance(*this, ppvObject);
2621 assert(hr == S_OK);
2622 if(hr == S_OK)
2624 m_containedObjects.emplace(*pMap->piid, static_cast<IUnknown*>(*ppvObject));
2625 IUNOXWrapper* wrapper = nullptr;
2626 static_cast<IUnknown*>(*ppvObject)->QueryInterface(IID_IUNOXWrapper, reinterpret_cast<void**>(&wrapper));
2627 if(wrapper)
2629 wrapper->put_XInterface(
2630 reinterpret_cast<hyper>(m_xAccessible.get()));
2631 wrapper->Release();
2633 return S_OK;
2636 return E_FAIL;
2638 pMap++;
2640 return E_FAIL;
2642 LEAVE_PROTECTED_BLOCK
2645 BOOL
2646 CMAccessible::get_IAccessibleFromXAccessible(XAccessible * pXAcc, IAccessible **ppIA)
2652 // #CHECK#
2653 if(ppIA == nullptr)
2655 return FALSE;
2657 BOOL isGet = FALSE;
2658 if(g_pAgent)
2659 isGet = g_pAgent->GetIAccessibleFromXAccessible(pXAcc, ppIA);
2661 if(isGet)
2662 return TRUE;
2663 else
2664 return FALSE;
2667 catch(...)
2669 return FALSE;
2673 OUString CMAccessible::get_StringFromAny(Any const & pAny)
2675 switch(pAny.getValueTypeClass())
2677 case TypeClass_CHAR:
2679 sal_Int8 val;
2680 pAny >>= val;
2681 return OUString::number(val);
2683 case TypeClass_BOOLEAN:
2685 bool val;
2686 pAny >>= val;
2687 return OUString::number(int(val));
2689 case TypeClass_BYTE:
2691 sal_Int8 val;
2692 pAny >>= val;
2693 return OUString::number(val);
2695 case TypeClass_SHORT:
2697 sal_Int16 val;
2698 pAny >>= val;
2699 return OUString::number(val);
2701 case TypeClass_UNSIGNED_SHORT:
2703 sal_uInt16 val;
2704 pAny >>= val;
2705 return OUString::number(val);
2707 case TypeClass_LONG:
2709 sal_Int32 val;
2710 pAny >>= val;
2711 return OUString::number(val);
2713 case TypeClass_UNSIGNED_LONG:
2715 sal_uInt32 val;
2716 pAny >>= val;
2717 return OUString::number(val);
2719 case TypeClass_FLOAT:
2721 float val;
2722 pAny >>= val;
2723 return OUString::number(val);
2725 case TypeClass_DOUBLE:
2727 double val;
2728 pAny >>= val;
2729 return OUString::number(val);
2731 case TypeClass_STRING:
2733 OUString val;
2734 pAny >>= val;
2735 return val;
2737 case TypeClass_SEQUENCE:
2739 if(pAny.getValueType() == cppu::UnoType<Sequence< OUString >>::get())
2741 Sequence < OUString > val;
2742 pAny >>= val;
2744 OUStringBuffer pString;
2746 int count = val.getLength();
2748 for( int iIndex = 0;iIndex < count;iIndex++ )
2750 pString.append(val[iIndex]);
2752 return pString.makeStringAndClear();
2754 else if (pAny.getValueType() == cppu::UnoType<Sequence< css::style::TabStop >>::get())
2756 Sequence < css::style::TabStop > val;
2757 pAny >>= val;
2758 int count = val.getLength();
2760 OUStringBuffer buf;
2761 for( int iIndex = 0;iIndex < count;iIndex++ )
2763 css::style::TabStop sigleVal = val[iIndex];
2765 buf.append("Position=");
2766 buf.append(sigleVal.Position);
2767 buf.append(",TabAlign=");
2768 buf.append(sal_Int32(sigleVal.Alignment));
2769 buf.append(",");
2771 buf.append("DecimalChar=");
2772 if(sigleVal.DecimalChar==';' || sigleVal.DecimalChar == ':' || sigleVal.DecimalChar == ',' ||
2773 sigleVal.DecimalChar == '=' || sigleVal.DecimalChar == '\\')
2774 buf.append('\\');
2775 buf.append(sigleVal.DecimalChar);
2776 buf.append(",");
2778 buf.append("FillChar=");
2779 if(sigleVal.FillChar==';' || sigleVal.FillChar == ':' || sigleVal.FillChar == ',' ||
2780 sigleVal.FillChar == '=' || sigleVal.FillChar == '\\')
2781 buf.append('\\');
2782 buf.append(sigleVal.FillChar);
2783 buf.append(",");
2785 return buf.makeStringAndClear();
2787 break;
2789 case TypeClass_ENUM:
2791 if (pAny.getValueType() == cppu::UnoType<css::awt::FontSlant>::get())
2793 css::awt::FontSlant val;
2794 pAny >>= val;
2795 return OUString::number(sal_Int32(val));
2797 break;
2799 case TypeClass_STRUCT:
2801 if (pAny.getValueType() == cppu::UnoType<css::style::LineSpacing>::get())
2803 css::style::LineSpacing val;
2804 pAny >>= val;
2805 return "Mode=" + OUString::number(val.Mode) + ",Height="
2806 + OUString::number(val.Height) + ",";
2808 else if (pAny.getValueType() == cppu::UnoType<css::accessibility::TextSegment>::get())
2810 css::accessibility::TextSegment val;
2811 pAny >>= val;
2812 return val.SegmentText;
2814 break;
2816 case TypeClass_VOID:
2817 case TypeClass_HYPER:
2818 case TypeClass_UNSIGNED_HYPER:
2819 case TypeClass_TYPE:
2820 case TypeClass_ANY:
2821 case TypeClass_TYPEDEF:
2822 case TypeClass_EXCEPTION:
2823 case TypeClass_INTERFACE:
2824 case TypeClass_SERVICE:
2825 case TypeClass_MODULE:
2826 case TypeClass_INTERFACE_METHOD:
2827 case TypeClass_INTERFACE_ATTRIBUTE:
2828 case TypeClass_UNKNOWN:
2829 case TypeClass_PROPERTY:
2830 case TypeClass_CONSTANT:
2831 case TypeClass_CONSTANTS:
2832 case TypeClass_SINGLETON:
2833 break;
2834 default:
2835 break;
2837 return OUString();
2840 OUString CMAccessible::get_String4Numbering(const Any& pAny, sal_Int16 numberingLevel,const OUString& numberingPrefix)
2842 Reference< css::container::XIndexReplace > pXIndex;
2843 if((pAny>>=pXIndex) && (numberingLevel !=-1))//numbering level is -1,means invalid value
2845 Any aAny = pXIndex->getByIndex(numberingLevel);
2846 Sequence< css::beans::PropertyValue > aProps;
2847 aAny >>= aProps;
2848 const css::beans::PropertyValue* pPropArray = aProps.getConstArray();
2849 sal_Int32 nCount = aProps.getLength();
2850 OUStringBuffer buf("Numbering:NumberingLevel=");
2851 buf.append(sal_Int32(numberingLevel));
2852 buf.append(',');
2853 for( sal_Int32 i=0; i<nCount; i++ )
2855 css::beans::PropertyValue rProp = pPropArray[i];
2856 if( (rProp.Name == "BulletChar" ) ||
2857 (rProp.Name == "NumberingType" ))
2859 buf.append(rProp.Name);
2860 buf.append('=');
2861 auto const pTemp = CMAccessible::get_StringFromAny(rProp.Value);
2862 buf.append(pTemp);
2863 buf.append(',');
2865 if(rProp.Name == "NumberingType")
2867 if(numberingPrefix.getLength()!=0)
2869 buf.append("NumberingPrefix=");
2870 buf.append(numberingPrefix);
2875 return buf.makeStringAndClear();
2878 //Because now have three types numbering level:
2879 //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
2880 //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
2881 //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
2882 // IAText:numberinglevel base on 0, but TOC's level base on 1,
2883 // so NumberingLevel value will be decreased 1 in bridge code.
2884 else if(numberingLevel >0)
2886 return "Numbering:NumberingLevel=" + OUString::number(numberingLevel-1) + ",NumberingType=4,NumberingPrefix=,";
2888 else
2890 return "Numbering:";
2894 void CMAccessible::ConvertAnyToVariant(const css::uno::Any &rAnyVal, VARIANT *pvData)
2896 if(rAnyVal.hasValue())
2898 // Clear VARIANT variable.
2899 VariantClear(pvData);
2901 // Set value according to value type.
2902 switch(rAnyVal.getValueTypeClass())
2904 case TypeClass_CHAR:
2905 pvData->vt = VT_UI1;
2906 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Char));
2907 break;
2909 case TypeClass_BOOLEAN:
2911 bool bBoolean(false);
2912 rAnyVal >>= bBoolean;
2913 pvData->vt = VT_BOOL;
2914 pvData->boolVal = VARIANT_BOOL(bBoolean); // boolVal is a VARIANT_BOOL, a 16bit field
2915 break;
2917 case TypeClass_BYTE:
2918 pvData->vt = VT_UI1;
2919 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Int8));
2920 break;
2922 case TypeClass_SHORT:
2923 pvData->vt = VT_I2;
2924 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_Int16));
2925 break;
2927 case TypeClass_UNSIGNED_SHORT:
2928 pvData->vt = VT_I2;
2929 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_uInt16));
2930 break;
2932 case TypeClass_LONG:
2933 pvData->vt = VT_I4;
2934 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_Int32));
2935 break;
2937 case TypeClass_UNSIGNED_LONG:
2938 pvData->vt = VT_I4;
2939 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_uInt32));
2940 break;
2942 case TypeClass_FLOAT:
2943 pvData->vt = VT_R4;
2944 memcpy(&pvData->fltVal, rAnyVal.getValue(), sizeof(float));
2945 break;
2947 case TypeClass_DOUBLE:
2948 pvData->vt = VT_R8;
2949 memcpy(&pvData->dblVal, rAnyVal.getValue(), sizeof(double));
2950 break;
2952 case TypeClass_STRING:
2954 pvData->vt = VT_BSTR;
2955 OUString val;
2956 rAnyVal >>= val;
2957 pvData->bstrVal = SysAllocString(o3tl::toW(val.getStr()));
2958 break;
2961 case TypeClass_VOID:
2962 case TypeClass_HYPER:
2963 case TypeClass_UNSIGNED_HYPER:
2964 case TypeClass_TYPE:
2965 case TypeClass_ANY:
2966 case TypeClass_ENUM:
2967 case TypeClass_TYPEDEF:
2968 case TypeClass_STRUCT:
2969 case TypeClass_EXCEPTION:
2970 case TypeClass_SEQUENCE:
2971 case TypeClass_INTERFACE:
2973 Reference< XAccessible > pXAcc;
2974 if(rAnyVal >>= pXAcc)
2976 if(pXAcc.is())
2978 IAccessible* pIAcc = nullptr;
2979 get_IAccessibleFromXAccessible(pXAcc.get(), &pIAcc);
2980 if(pIAcc == nullptr)
2982 Reference< XAccessibleContext > pXAccContext = pXAcc->getAccessibleContext();
2983 g_pAgent->InsertAccObj(pXAcc.get(),pXAccContext->getAccessibleParent().get());
2984 get_IAccessibleFromXAccessible(pXAcc.get(), &pIAcc);
2986 if(pIAcc)
2988 pIAcc->AddRef();
2990 pvData->vt = VT_UNKNOWN;
2991 pvData->pdispVal = static_cast<IAccessible2*>(pIAcc);
2992 break;
2996 [[fallthrough]];
2998 case TypeClass_SERVICE:
2999 case TypeClass_MODULE:
3000 case TypeClass_INTERFACE_METHOD:
3001 case TypeClass_INTERFACE_ATTRIBUTE:
3002 case TypeClass_UNKNOWN:
3003 case TypeClass_PROPERTY:
3004 case TypeClass_CONSTANT:
3005 case TypeClass_CONSTANTS:
3006 case TypeClass_SINGLETON:
3007 case TypeClass::TypeClass_MAKE_FIXED_SIZE:
3008 // Output the type string, if there is other uno value type.
3009 pvData->vt = VT_BSTR;
3010 pvData->bstrVal = SysAllocString(o3tl::toW(rAnyVal.getValueTypeName().getStr()));
3011 break;
3013 default:
3014 break;
3017 else
3019 VariantClear(pvData);
3023 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Get_XAccChildID(long* childID)
3025 // internal IMAccessible - no mutex meeded
3027 if(childID == nullptr)
3029 return E_FAIL;
3031 *childID = m_dChildID;
3032 return S_OK;
3035 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_states(AccessibleStates __RPC_FAR *states )
3037 SolarMutexGuard g;
3039 ENTER_PROTECTED_BLOCK
3040 ISDESTROY()
3042 if (!m_xContext.is())
3043 return E_FAIL;
3045 Reference<XAccessibleStateSet> const pRStateSet =
3046 m_xContext.get()->getAccessibleStateSet();
3047 if(!pRStateSet.is())
3049 return S_OK;
3051 Sequence<short> pStates = pRStateSet->getStates();
3054 long count = pStates.getLength() ;
3055 *states = 0x0;
3056 for( int i = 0; i < count; i++ )
3058 for( std::size_t j = 0; j < SAL_N_ELEMENTS(UNO_STATES); j++ )
3060 if( pStates[i] == UNO_STATES[j] )
3062 *states |= IA2_STATES[j];
3063 break;
3067 return S_OK;
3070 LEAVE_PROTECTED_BLOCK
3073 // return the UNO roles
3074 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_extendedRole( BSTR __RPC_FAR * )
3076 return E_NOTIMPL;
3079 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_localizedExtendedRole( BSTR __RPC_FAR * )
3081 return E_NOTIMPL;
3084 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_nExtendedStates( long __RPC_FAR * )
3086 return E_NOTIMPL;
3090 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_localizedExtendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
3092 return E_NOTIMPL;
3096 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_indexInParent( long __RPC_FAR *accParentIndex)
3098 ENTER_PROTECTED_BLOCK
3099 ISDESTROY()
3100 // #CHECK#
3101 if(accParentIndex == nullptr)
3102 return E_INVALIDARG;
3104 if (!m_xContext.is())
3105 return E_FAIL;
3107 *accParentIndex = m_xContext.get()->getAccessibleIndexInParent();
3108 return S_OK;
3111 LEAVE_PROTECTED_BLOCK
3113 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_locale( IA2Locale __RPC_FAR *locale )
3115 ENTER_PROTECTED_BLOCK
3116 ISDESTROY()
3117 if(locale == nullptr)
3118 return E_INVALIDARG;
3120 if (!m_xContext.is())
3121 return E_FAIL;
3123 css::lang::Locale unoLoc = m_xContext.get()->getLocale();
3124 locale->language = SysAllocString(o3tl::toW(unoLoc.Language.getStr()));
3125 locale->country = SysAllocString(o3tl::toW(unoLoc.Country.getStr()));
3126 locale->variant = SysAllocString(o3tl::toW(unoLoc.Variant.getStr()));
3128 return S_OK;
3130 LEAVE_PROTECTED_BLOCK
3133 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_appName( BSTR __RPC_FAR *name)
3135 SolarMutexGuard g;
3137 ENTER_PROTECTED_BLOCK
3138 ISDESTROY()
3139 if(name == nullptr)
3140 return E_INVALIDARG;
3142 *name = SysAllocString(OLESTR("Hannover"));
3143 return S_OK;
3144 LEAVE_PROTECTED_BLOCK
3146 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_appVersion(BSTR __RPC_FAR *version)
3148 SolarMutexGuard g;
3150 ENTER_PROTECTED_BLOCK
3151 ISDESTROY()
3152 if(version == nullptr)
3153 return E_INVALIDARG;
3154 *version=SysAllocString(OLESTR("3.0"));
3155 return S_OK;
3156 LEAVE_PROTECTED_BLOCK
3158 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_toolkitName(BSTR __RPC_FAR *name)
3160 SolarMutexGuard g;
3162 ENTER_PROTECTED_BLOCK
3163 ISDESTROY()
3164 if(name == nullptr)
3165 return E_INVALIDARG;
3166 *name = SysAllocString(OLESTR(" "));
3167 return S_OK;
3168 LEAVE_PROTECTED_BLOCK
3170 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_toolkitVersion(BSTR __RPC_FAR *version)
3172 SolarMutexGuard g;
3174 ENTER_PROTECTED_BLOCK
3175 ISDESTROY()
3176 if(version == nullptr)
3177 return E_INVALIDARG;
3178 *version = SysAllocString(OLESTR(" "));
3179 return S_OK;
3180 LEAVE_PROTECTED_BLOCK
3184 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_attributes(/*[out]*/ BSTR *pAttr)
3186 SolarMutexGuard g;
3188 ENTER_PROTECTED_BLOCK
3189 ISDESTROY()
3191 if (!m_xAccessible.is())
3192 return E_FAIL;
3194 Reference<XAccessibleContext> pRContext = m_xAccessible->getAccessibleContext();
3195 if( !pRContext.is() )
3197 return E_FAIL;
3199 Reference<XAccessibleExtendedAttributes> pRXI(pRContext,UNO_QUERY);
3200 if( !pRXI.is() )
3201 return E_FAIL;
3202 else
3204 css::uno::Reference<css::accessibility::XAccessibleExtendedAttributes> pRXAttr;
3205 pRXAttr = pRXI.get();
3206 css::uno::Any anyVal = pRXAttr->getExtendedAttributes();
3208 OUString val;
3209 anyVal >>= val;
3211 if(*pAttr)
3212 SAFE_SYSFREESTRING(*pAttr);
3213 *pAttr = SysAllocString(o3tl::toW(val.getStr()));
3215 return S_OK;
3217 LEAVE_PROTECTED_BLOCK
3220 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */