Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / winaccessibility / source / UAccCOM / MAccessible.cxx
blobd681c38a793ca31409bfe4592558fa64c8450cf6
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 pIMAcc->AddRef();
790 pvarChild->vt = VT_DISPATCH;
791 pvarChild->pdispVal = pIMAcc;
794 return S_OK;
796 LEAVE_PROTECTED_BLOCK
800 * Returns the selection of the current COM object to AT.
801 * @param pvarChildren,[in,out]
802 * if selection num is 0,return VT_EMPTY for vt,
803 * if selection num is 1,return VT_I4 for vt,and child index for lVal
804 * if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
805 * @return S_OK if successful and S_FALSE if failure.
807 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_accSelection(VARIANT *pvarChildren)
809 SolarMutexGuard g;
811 ENTER_PROTECTED_BLOCK
812 ISDESTROY()
813 // #CHECK#
814 if(pvarChildren == nullptr)
816 return E_INVALIDARG;
818 switch(m_pEnumVar->GetCountOfElements())
820 case 0:
821 pvarChildren->vt = VT_EMPTY;
822 break;
823 case 1:
824 VARIANT varTmp[1];
825 ULONG count;
826 VariantInit(&varTmp[0]);
827 m_pEnumVar->Next(1,varTmp,&count);
828 if(count!=1)
829 return S_FALSE;
830 pvarChildren->vt = VT_I4;
831 pvarChildren->lVal = varTmp[0].lVal;
832 VariantClear(&varTmp[0]);
833 m_pEnumVar->Reset();
834 break;
835 default:
836 pvarChildren->vt = VT_UNKNOWN;
837 m_pEnumVar->AddRef();
838 pvarChildren->punkVal = m_pEnumVar;
839 break;
841 return S_OK;
843 LEAVE_PROTECTED_BLOCK
847 * Returns the location of the current COM object self or its one child to AT.
848 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
849 * the child ID specify child index from 0 to children count, 0 stands for object self.
850 * @param pxLeft, [in,out] use to return the x-coordination of the proper object.
851 * @param pyTop, [in,out] use to return the y-coordination of the proper object.
852 * @param pcxWidth, [in,out] use to return the x-coordination width of the proper object.
853 * @param pcyHeight, [in,out] use to return the y-coordination height of the proper object.
854 * @return S_OK if successful and S_FALSE if failure.
856 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild)
858 SolarMutexGuard g;
860 ENTER_PROTECTED_BLOCK
861 ISDESTROY()
862 // #CHECK#
863 if(pxLeft == nullptr || pyTop == nullptr || pcxWidth == nullptr || pcyHeight == nullptr)
865 return E_INVALIDARG;
868 if(varChild.vt==VT_I4)
870 if(varChild.lVal==CHILDID_SELF)
873 if (m_xAccessible.is())
875 Reference<XAccessibleContext> const pRContext =
876 m_xAccessible->getAccessibleContext();
877 if( !pRContext.is() )
878 return S_FALSE;
879 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
880 if( !pRComponent.is() )
881 return S_FALSE;
883 css::awt::Point pCPoint = pRComponent->getLocationOnScreen();
884 css::awt::Size pCSize = pRComponent->getSize();
885 *pxLeft = pCPoint.X;
886 *pyTop = pCPoint.Y;
887 *pcxWidth = pCSize.Width;
888 *pcyHeight = pCSize.Height;
889 return S_OK;
891 else
893 *pxLeft = m_sLocation.m_dLeft;
894 *pyTop = m_sLocation.m_dTop;
895 *pcxWidth = m_sLocation.m_dWidth;
896 *pcyHeight = m_sLocation.m_dHeight;
897 return S_OK;
902 return S_FALSE;
904 LEAVE_PROTECTED_BLOCK
908 * Returns the current focused child to AT.
909 * @param navDir, the direction flag of the navigation.
910 * @param varStart, the start child id of this navigation action.
911 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
912 * @return S_OK if successful and E_FAIL if failure.
914 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt)
916 SolarMutexGuard g;
918 ENTER_PROTECTED_BLOCK
919 ISDESTROY()
920 // #CHECK#
921 if(pvarEndUpAt == nullptr)
923 return E_INVALIDARG;
925 HRESULT ret = E_FAIL;
926 switch (navDir)
928 case NAVDIR_FIRSTCHILD:
929 ret = GetFirstChild(varStart,pvarEndUpAt);
930 break;
931 case NAVDIR_LASTCHILD:
932 ret = GetLastChild(varStart,pvarEndUpAt);
933 break;
934 case NAVDIR_NEXT:
935 ret = GetNextSibling(varStart,pvarEndUpAt);
936 break;
937 case NAVDIR_PREVIOUS:
938 ret = GetPreSibling(varStart,pvarEndUpAt);
939 break;
940 case NAVDIR_DOWN://do not implement temporarily
941 break;
942 case NAVDIR_UP://do not implement temporarily
943 break;
944 case NAVDIR_LEFT://do not implement temporarily
945 break;
946 case NAVDIR_RIGHT://do not implement temporarily
947 break;
948 default:
949 break;
951 return ret;
953 LEAVE_PROTECTED_BLOCK
956 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarChild)
958 SolarMutexGuard g;
960 ENTER_PROTECTED_BLOCK
961 ISDESTROY()
962 // #CHECK#
963 if(pvarChild == nullptr)
965 return E_INVALIDARG;
967 long x, y, w, h;
968 VARIANT varSelf;
969 VariantInit(&varSelf);
970 varSelf.vt = VT_I4;
971 varSelf.lVal = CHILDID_SELF;
972 accLocation(&x,&y,&w,&h,varSelf);
973 if( (x < xLeft && (x + w) >xLeft) && (y < yTop && (y + h) >yTop) )
975 int i, nCount;
976 pvarChild->vt = VT_EMPTY;
977 Reference< XAccessibleContext > pRContext = GetContextByXAcc(m_xAccessible.get());
978 nCount = pRContext->getAccessibleChildCount();
979 if(nCount > 256)
980 return E_FAIL;
981 IMAccessible* child = nullptr;
982 for( i = 0; i<nCount; i++)
985 child = GetChildInterface(i + 1);
986 if(child && child->accHitTest(xLeft,yTop,pvarChild) == S_OK)
987 break;
990 if(pvarChild->vt == VT_DISPATCH)
991 return S_OK;
993 if( i < nCount)
995 pvarChild->vt = VT_DISPATCH;
996 pvarChild->pdispVal = child;
997 child->AddRef();
999 else
1001 pvarChild->vt = VT_I4;
1002 pvarChild->lVal = CHILDID_SELF;
1004 return S_OK;
1006 return S_FALSE;
1008 LEAVE_PROTECTED_BLOCK
1012 * Get The other Interface from CMAccessible.
1013 * @param guidService, must be IID_IAccessible here.
1014 * @param riid, the IID interface .
1015 * @return S_OK if successful and S_FALSE if failure.
1017 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::QueryService(REFGUID guidService, REFIID riid, void** ppvObject)
1019 if( InlineIsEqualGUID(guidService, IID_IAccessible) )
1020 return QueryInterface(riid, ppvObject);
1021 return S_FALSE;
1025 * Set the accessible name of the current COM object self or its one child from UNO.
1026 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1027 * the child ID specify child index from 0 to children count, 0 stands for object self.
1028 * @param szName, the name used to set the name of the proper object.
1029 * @return S_OK if successful and E_FAIL if failure.
1031 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::put_accName(VARIANT varChild, BSTR szName)
1033 SolarMutexGuard g;
1035 ENTER_PROTECTED_BLOCK
1036 ISDESTROY()
1037 if(varChild.vt==VT_I4)
1039 if(varChild.lVal==CHILDID_SELF)
1041 SAFE_SYSFREESTRING(m_pszName);
1042 m_pszName=SysAllocString(szName);
1043 return S_OK;
1046 long lVal = varChild.lVal;
1047 varChild.lVal = CHILDID_SELF;
1048 IMAccessible *pChild = this->GetChildInterface(lVal);
1049 if(!pChild)
1050 return E_FAIL;
1051 return pChild->put_accName(varChild,szName);
1053 return E_FAIL;
1055 LEAVE_PROTECTED_BLOCK
1059 * Set the accessible value of the current COM object self or its one child from UNO.
1060 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1061 * the child ID specify child index from 0 to children count, 0 stands for object self.
1062 * @param szValue, the value used to set the value of the proper object.
1063 * @return S_OK if successful and E_FAIL if failure.
1065 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::put_accValue(VARIANT varChild, BSTR szValue)
1067 SolarMutexGuard g;
1069 ENTER_PROTECTED_BLOCK
1070 ISDESTROY()
1071 if(varChild.vt==VT_I4)
1073 if(varChild.lVal==CHILDID_SELF)
1075 SAFE_SYSFREESTRING(m_pszValue);
1076 m_pszValue=SysAllocString(szValue);
1077 return S_OK;
1080 long lVal = varChild.lVal;
1081 varChild.lVal = CHILDID_SELF;
1082 IMAccessible *pChild = this->GetChildInterface(lVal);
1083 if(!pChild)
1084 return E_FAIL;
1085 return pChild->put_accValue(varChild,szValue);
1087 return E_FAIL;
1089 LEAVE_PROTECTED_BLOCK
1093 * Set the accessible name of the current COM object self from UNO.
1094 * @param pszName, the name value used to set the name of the current object.
1095 * @return S_OK if successful and E_FAIL if failure.
1097 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR *pszName)
1099 // internal IMAccessible - no mutex meeded
1101 ENTER_PROTECTED_BLOCK
1102 ISDESTROY()
1103 // #CHECK#
1104 if(pszName == nullptr)
1106 return E_INVALIDARG;
1109 SAFE_SYSFREESTRING(m_pszName);
1110 m_pszName = SysAllocString(pszName);
1111 if(m_pszName==nullptr)
1112 return E_FAIL;
1113 return S_OK;
1115 LEAVE_PROTECTED_BLOCK
1119 * Set the accessible role of the current COM object self from UNO.
1120 * @param pRole, the role value used to set the role of the current object.
1121 * @return S_OK if successful and E_FAIL if failure.
1123 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccRole(unsigned short pRole)
1125 // internal IMAccessible - no mutex meeded
1127 m_iRole = pRole;
1128 return S_OK;
1132 * Add one state into the current state set for the current COM object from UNO.
1133 * @param pXSate, the state used to set the name of the current object.
1134 * @return S_OK if successful and E_FAIL if failure.
1136 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::DecreaseState(DWORD pXSate)
1138 // internal IMAccessible - no mutex meeded
1140 m_dState &= (~pXSate);
1141 return S_OK;
1145 * Delete one state into the current state set for the current COM object from UNO.
1146 * @param pXSate, the state used to set the name of the current object.
1147 * @return S_OK if successful and E_FAIL if failure.
1149 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::IncreaseState(DWORD pXSate)
1151 // internal IMAccessible - no mutex meeded
1153 m_dState |= pXSate;
1154 return S_OK;
1158 * Set state into the current state set for the current COM object from UNO.
1159 * @param pXSate, the state used to set the name of the current object.
1160 * @return S_OK if successful and E_FAIL if failure.
1162 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::SetState(DWORD pXSate)
1164 // internal IMAccessible - no mutex meeded
1166 m_dState = pXSate;
1167 return S_OK;
1172 * Set the accessible description of the current COM object self from UNO.
1173 * @param pszDescription, the name used to set the description of the current object.
1174 * @return S_OK if successful and E_FAIL if failure.
1176 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccDescription(const OLECHAR __RPC_FAR *pszDescription)
1178 // internal IMAccessible - no mutex meeded
1180 ENTER_PROTECTED_BLOCK
1181 ISDESTROY()
1182 // #CHECK#
1183 if(pszDescription == nullptr)
1185 return E_INVALIDARG;
1188 SAFE_SYSFREESTRING(m_pszDescription);
1189 m_pszDescription = SysAllocString(pszDescription);
1191 if(m_pszDescription==nullptr)
1192 return E_FAIL;
1193 return S_OK;
1195 LEAVE_PROTECTED_BLOCK
1199 * Set the accessible value of the current COM object self from UNO.
1200 * @param pszAccValue, the name used to set the value of the current object.
1201 * @return S_OK if successful and E_FAIL if failure.
1203 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR *pszAccValue)
1205 // internal IMAccessible - no mutex meeded
1207 ENTER_PROTECTED_BLOCK
1208 ISDESTROY()
1209 // #CHECK#
1210 if(pszAccValue == nullptr)
1212 return E_INVALIDARG;
1214 SAFE_SYSFREESTRING(m_pszValue);
1215 m_pszValue = SysAllocString(pszAccValue);
1216 if(m_pszValue==nullptr)
1217 return E_FAIL;
1218 return S_OK;
1220 LEAVE_PROTECTED_BLOCK
1224 * Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
1225 * Object through the method AccessibleObjectFromWindow(...).
1226 * @param hwnd, the HWND used to set the value of the current object.
1227 * @return S_OK if successful and E_FAIL if failure.
1229 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccWindowHandle(HWND hwnd)
1231 // internal IMAccessible - no mutex meeded
1233 ENTER_PROTECTED_BLOCK
1234 ISDESTROY()
1235 m_hwnd = hwnd;
1236 return S_OK;
1238 LEAVE_PROTECTED_BLOCK
1242 * Set accessible focus by specifying child ID
1243 * @param dChildID, the child id identifies the focus child.
1244 * @return S_OK if successful and E_FAIL if failure.
1246 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccFocus(long dChildID)
1248 // internal IMAccessible - no mutex meeded
1250 ENTER_PROTECTED_BLOCK
1251 ISDESTROY()
1253 if(dChildID==CHILDID_SELF)
1255 if(m_pIParent)
1257 m_pIParent->Put_XAccFocus(m_dChildID);
1260 else
1262 m_dFocusChildID = dChildID;
1263 //traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
1264 //any of the ancestors, this id can be used to get the IAccessible of focused object.
1265 if(m_pIParent)
1267 m_pIParent->Put_XAccFocus(dChildID);
1270 return S_OK;
1272 LEAVE_PROTECTED_BLOCK
1276 *Set accessible object location for the current COM object
1277 * @param sLocation, the location of the current object.
1278 * @return S_OK if successful and E_FAIL if failure.
1280 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccLocation(const Location sLocation)
1282 // internal IMAccessible - no mutex meeded
1284 this->m_sLocation = sLocation;
1285 return S_OK;
1289 * Set accessible parent object for the current COM object if
1290 * the current object is a child of some COM object
1291 * @param pIParent, the parent of the current object.
1292 * @return S_OK if successful and E_FAIL if failure.
1294 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR *pIParent)
1296 // internal IMAccessible - no mutex meeded
1298 this->m_pIParent = pIParent;
1300 if(pIParent)
1301 m_pIParent->AddRef();
1303 return S_OK;
1307 * Set unique child id to COM
1308 * @param dChildID, the id of the current object.
1309 * @return S_OK if successful and E_FAIL if failure.
1311 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccChildID(long dChildID)
1313 // internal IMAccessible - no mutex meeded
1315 this->m_dChildID = dChildID;
1316 return S_OK;
1320 * Set AccObjectManagerAgent object pointer to COM
1321 * @param pAgent, the AccObjectManagerAgent point.
1322 * @return S_OK if successful and E_FAIL if failure.
1324 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_XAccAgent(hyper pAgent)
1326 // internal IMAccessible - no mutex meeded
1328 g_pAgent = reinterpret_cast<AccObjectManagerAgent*>(pAgent);
1329 return S_OK;
1333 * When a UNO control disposing, it disposes its listeners,
1334 * then notify AccObject in bridge management, then notify
1335 * COM that the XAccessible is invalid,so set m_xAccessible as NULL
1336 * @param isDestroy, true is it needs to be destroyed.
1337 * @return S_OK if successful and E_FAIL if failure.
1339 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::NotifyDestroy(BOOL isDestroy)
1341 // internal IMAccessible - no mutex meeded
1343 m_isDestroy = isDestroy;
1344 m_xAccessible.clear();
1345 return S_OK;
1349 *private methods that help implement public functions
1353 * Return child interface pointer by child ID,note: need to call AddRef()
1354 * @param lChildID, specify child index,which AT(such as Inspect32) gives.
1355 * @return IMAccessible*, pointer to the corresponding child object.
1357 IMAccessible* CMAccessible::GetChildInterface(long dChildID)//for test
1359 if(dChildID<0)
1361 if(g_pAgent)
1363 IMAccessible* pIMAcc = nullptr;
1364 g_pAgent->GetIAccessibleFromResID(dChildID,&pIMAcc);
1365 return pIMAcc;
1367 return nullptr;
1369 else
1371 if (!m_xAccessible.is())
1372 return nullptr;
1374 Reference<XAccessibleContext> const pRContext =
1375 m_xAccessible->getAccessibleContext();
1376 if( !pRContext.is() )
1377 return nullptr;
1379 if(dChildID<1 || dChildID>pRContext->getAccessibleChildCount())
1380 return nullptr;
1382 IAccessible* pChild = nullptr;
1383 Reference< XAccessible > pXChild = pRContext->getAccessibleChild(dChildID-1);
1384 BOOL isGet = get_IAccessibleFromXAccessible(pXChild.get(), &pChild);
1386 if(!isGet)
1388 g_pAgent->InsertAccObj(pXChild.get(), m_xAccessible.get(),
1389 reinterpret_cast<sal_Int64>(m_hwnd));
1390 isGet = get_IAccessibleFromXAccessible(pXChild.get(), &pChild);
1393 if(isGet)
1395 IMAccessible* pIMAcc = static_cast<IMAccessible*>(pChild);
1396 return pIMAcc;
1400 return nullptr;
1404 * For List, tree and table,these roles belong to manage_descendant in UNO,
1405 * need to process specifically when navigate
1406 * @return BOOL, if it is descendantmanager, return true.
1408 BOOL CMAccessible::IsDescendantManage()
1411 return (m_iRole==ROLE_SYSTEM_LIST)||(m_iRole==ROLE_SYSTEM_OUTLINE)||(m_iRole==ROLE_SYSTEM_TABLE);
1415 * for descendantmanager circumstance,provide child interface when navigate
1416 * @param varCur, the current child.
1417 * @param flags, the navigation direction.
1418 * @return IMAccessible*, the child of the end up node.
1420 IMAccessible* CMAccessible::GetNavigateChildForDM(VARIANT varCur, short flags)
1423 XAccessibleContext* pXContext = GetContextByXAcc(m_xAccessible.get());
1424 if(pXContext==nullptr)
1426 return nullptr;
1429 int count = pXContext->getAccessibleChildCount();
1430 if(count<1)
1432 return nullptr;
1435 IMAccessible* pCurChild = nullptr;
1436 union {
1437 XAccessible* pChildXAcc;
1438 hyper nHyper = 0;
1440 Reference<XAccessible> pRChildXAcc;
1441 XAccessibleContext* pChildContext = nullptr;
1442 int index = 0,delta=0;
1443 switch(flags)
1445 case DM_FIRSTCHILD:
1446 pRChildXAcc = pXContext->getAccessibleChild(0);
1447 break;
1448 case DM_LASTCHILD:
1449 pRChildXAcc = pXContext->getAccessibleChild(count-1);
1450 break;
1451 case DM_NEXTCHILD:
1452 case DM_PREVCHILD:
1453 pCurChild = GetChildInterface(varCur.lVal);
1454 if(pCurChild==nullptr)
1456 return nullptr;
1458 pCurChild->GetUNOInterface(&nHyper);
1459 if(pChildXAcc==nullptr)
1461 return nullptr;
1463 pChildContext = GetContextByXAcc(pChildXAcc);
1464 if(pChildContext == nullptr)
1466 return nullptr;
1468 delta = (flags==DM_NEXTCHILD)?1:-1;
1469 //currently, getAccessibleIndexInParent is error in UNO for
1470 //some kind of List,such as ValueSet, the index will be less 1 than
1471 //what should be, need to fix UNO code
1472 index = pChildContext->getAccessibleIndexInParent()+delta;
1473 if((index>=0)&&(index<=count-1))
1475 pRChildXAcc = pXContext->getAccessibleChild(index);
1477 break;
1478 default:
1479 break;
1482 if(!pRChildXAcc.is())
1484 return nullptr;
1486 pChildXAcc = pRChildXAcc.get();
1487 g_pAgent->InsertAccObj(pChildXAcc, m_xAccessible.get());
1488 return g_pAgent->GetIMAccByXAcc(pChildXAcc);
1492 *the following 4 private methods are for accNavigate implementation
1496 * Return first child for parent container, process differently according
1497 * to whether it is descendant manage
1498 * @param varStart, the start child id of this navigation action.
1499 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1500 * @return S_OK if successful and E_FAIL if failure.
1502 HRESULT CMAccessible::GetFirstChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1505 ENTER_PROTECTED_BLOCK
1506 ISDESTROY()
1507 // #CHECK#
1508 if(pvarEndUpAt == nullptr)
1510 return E_INVALIDARG;
1512 if(varStart.vt != VT_I4)
1514 pvarEndUpAt->vt = VT_EMPTY;
1515 return E_INVALIDARG;
1518 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_FIRSTCHILD);
1519 if(pvarEndUpAt->pdispVal)
1521 pvarEndUpAt->pdispVal->AddRef();
1522 pvarEndUpAt->vt = VT_DISPATCH;
1523 return S_OK;
1526 pvarEndUpAt->vt = VT_EMPTY;
1527 return E_FAIL;
1529 LEAVE_PROTECTED_BLOCK
1533 * Return last child for parent container, process differently according
1534 * to whether it is descendant manage
1535 * @param varStart, the start child id of this navigation action.
1536 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1537 * @return S_OK if successful and E_FAIL if failure.
1539 HRESULT CMAccessible::GetLastChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1542 ENTER_PROTECTED_BLOCK
1543 ISDESTROY()
1544 // #CHECK#
1545 if(pvarEndUpAt == nullptr)
1547 return E_INVALIDARG;
1549 if(varStart.vt != VT_I4)
1551 pvarEndUpAt->vt = VT_EMPTY;
1552 return E_INVALIDARG;
1555 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_LASTCHILD);
1556 if(pvarEndUpAt->pdispVal)
1558 pvarEndUpAt->pdispVal->AddRef();
1559 pvarEndUpAt->vt = VT_DISPATCH;
1560 return S_OK;
1562 pvarEndUpAt->vt = VT_EMPTY;
1563 return E_FAIL;
1565 LEAVE_PROTECTED_BLOCK
1569 * The method GetNextSibling is general, whatever it is descendant manage or not
1570 * Get the next sibling object.
1571 * @param varStart, the start child id of this navigation action.
1572 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1573 * @return S_OK if successful and E_FAIL if failure.
1575 HRESULT CMAccessible::GetNextSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1578 ENTER_PROTECTED_BLOCK
1579 ISDESTROY()
1580 if(varStart.vt != VT_I4)
1582 pvarEndUpAt->vt = VT_EMPTY;
1583 return E_INVALIDARG;
1586 Reference<XAccessibleContext> const pRContext =
1587 GetContextByXAcc(m_xAccessible.get());
1588 if(pRContext.is())
1590 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent() + 2);
1591 if(m_pIParent)
1592 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1594 pvarEndUpAt->vt = VT_DISPATCH;
1595 return S_OK;
1598 pvarEndUpAt->vt = VT_EMPTY;
1599 return E_FAIL;
1601 LEAVE_PROTECTED_BLOCK
1605 *the method GetPreSibling is general, whatever it is descendant manage or not
1606 * @param varStart, the start child id of this navigation action.
1607 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1608 * @return S_OK if successful and E_FAIL if failure.
1610 HRESULT CMAccessible::GetPreSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1613 ENTER_PROTECTED_BLOCK
1614 ISDESTROY()
1615 // #CHECK#
1616 if(pvarEndUpAt == nullptr)
1618 return E_INVALIDARG;
1620 if(varStart.vt != VT_I4)
1622 pvarEndUpAt->vt = VT_EMPTY;
1623 return E_INVALIDARG;
1626 Reference<XAccessibleContext> const pRContext =
1627 GetContextByXAcc(m_xAccessible.get());
1628 if(pRContext.is())
1630 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent());
1631 if(m_pIParent && varStart.iVal > 0)
1632 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1634 pvarEndUpAt->vt = VT_DISPATCH;
1635 return S_OK;
1638 pvarEndUpAt->vt = VT_EMPTY;
1639 return E_FAIL;
1641 LEAVE_PROTECTED_BLOCK
1645 * For IAccessible2 implementation methods
1647 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_nRelations( long __RPC_FAR *nRelations)
1649 SolarMutexGuard g;
1651 ENTER_PROTECTED_BLOCK
1652 ISDESTROY()
1654 // #CHECK#
1655 if(nRelations == nullptr)
1657 return E_INVALIDARG;
1660 *nRelations = 0;
1662 if (!m_xContext.is())
1663 return E_FAIL;
1664 Reference<XAccessibleRelationSet> pRrelationSet =
1665 m_xContext.get()->getAccessibleRelationSet();
1666 if(!pRrelationSet.is())
1668 *nRelations = 0;
1669 return S_OK;
1672 *nRelations = pRrelationSet->getRelationCount();
1673 return S_OK;
1675 LEAVE_PROTECTED_BLOCK
1678 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_relation( long relationIndex, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation)
1680 SolarMutexGuard g;
1682 ENTER_PROTECTED_BLOCK
1683 ISDESTROY()
1684 // #CHECK#
1685 if(relation == nullptr)
1687 return E_INVALIDARG;
1690 if (!m_xContext.is())
1691 return E_FAIL;
1694 long nMax = 0;
1695 get_nRelations(&nMax);
1697 *relation = static_cast<IAccessibleRelation*>(::CoTaskMemAlloc(sizeof(IAccessibleRelation)));
1699 // #CHECK Memory Allocation#
1700 if(*relation == nullptr)
1702 return E_FAIL;
1705 if( relationIndex < nMax )
1707 Reference<XAccessibleRelationSet> const pRrelationSet =
1708 m_xContext.get()->getAccessibleRelationSet();
1709 if(!pRrelationSet.is())
1712 return E_FAIL;
1715 IAccessibleRelation* pRelation = nullptr;
1716 HRESULT hr = createInstance<CAccRelation>(IID_IAccessibleRelation,
1717 &pRelation);
1718 if(SUCCEEDED(hr))
1720 IUNOXWrapper* wrapper = nullptr;
1721 hr = pRelation->QueryInterface(IID_IUNOXWrapper, reinterpret_cast<void**>(&wrapper));
1722 if(SUCCEEDED(hr))
1724 AccessibleRelation accRelation = pRrelationSet->getRelation(relationIndex);
1725 wrapper->put_XSubInterface(
1726 reinterpret_cast<hyper>(&accRelation));
1727 wrapper->Release();
1728 *relation = pRelation;
1729 return S_OK;
1735 return E_FAIL;
1737 LEAVE_PROTECTED_BLOCK
1740 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation, long __RPC_FAR *nRelations)
1742 SolarMutexGuard g;
1744 ENTER_PROTECTED_BLOCK
1745 ISDESTROY()
1747 // #CHECK#
1748 if(relation == nullptr || nRelations == nullptr)
1750 return E_INVALIDARG;
1752 // #CHECK XInterface#
1754 if (!m_xContext.is())
1755 return E_FAIL;
1757 Reference<XAccessibleRelationSet> const pRrelationSet =
1758 m_xContext.get()->getAccessibleRelationSet();
1759 if(!pRrelationSet.is())
1761 *nRelations = 0;
1762 return S_OK;
1765 long nCount = pRrelationSet->getRelationCount();
1767 *relation = static_cast<IAccessibleRelation*>(::CoTaskMemAlloc(nCount*sizeof(IAccessibleRelation)));
1769 // #CHECK Memory Allocation#
1770 if(*relation == nullptr)
1772 return E_FAIL;
1775 for(int i=0; i<nCount ; i++)
1777 IAccessibleRelation* pRelation = nullptr;
1778 HRESULT hr = createInstance<CAccRelation>(IID_IAccessibleRelation,
1779 &pRelation);
1780 if(SUCCEEDED(hr))
1782 IUNOXWrapper* wrapper = nullptr;
1783 hr = pRelation->QueryInterface(IID_IUNOXWrapper, reinterpret_cast<void**>(&wrapper));
1784 if(SUCCEEDED(hr))
1786 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1787 wrapper->put_XSubInterface(
1788 reinterpret_cast<hyper>(&accRelation));
1789 wrapper->Release();
1791 relation[i] = pRelation;
1795 *nRelations = nCount;
1796 return S_OK;
1798 LEAVE_PROTECTED_BLOCK
1801 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::role(long __RPC_FAR *role)
1803 SolarMutexGuard g;
1805 ENTER_PROTECTED_BLOCK
1807 (*role) = m_iRole;
1809 return S_OK;
1811 LEAVE_PROTECTED_BLOCK
1815 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_nActions(long __RPC_FAR *nActions)
1817 SolarMutexGuard g;
1821 ISDESTROY()
1822 // #CHECK#
1823 if(nActions == nullptr)
1825 return E_INVALIDARG;
1827 *nActions = 0;
1828 IAccessibleAction* pAcc = nullptr;
1829 HRESULT hr = QueryInterface(IID_IAccessibleAction, reinterpret_cast<void**>(&pAcc));
1830 if( hr == S_OK )
1832 pAcc->nActions(nActions);
1833 pAcc->Release();
1836 return S_OK;
1838 catch(...)
1840 *nActions = 0;
1841 return S_OK;
1846 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: scrollToPoint(enum IA2CoordinateType, long, long)
1848 return E_NOTIMPL;
1851 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: scrollTo(enum IA2ScrollType)
1853 return E_NOTIMPL;
1856 static XAccessible* getTheParentOfMember(XAccessible* pXAcc)
1858 // #CHECK#
1859 if(pXAcc == nullptr)
1861 return nullptr;
1863 Reference<XAccessibleContext> pRContext = pXAcc->getAccessibleContext();
1864 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1865 sal_Int32 nRelations = pRrelationSet->getRelationCount();
1866 for(sal_Int32 i=0 ; i<nRelations ; i++)
1868 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1869 if(accRelation.RelationType == 7)
1871 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1872 return static_cast<XAccessible*>(xTargets[0].get());
1875 return nullptr;
1878 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_groupPosition(long __RPC_FAR *groupLevel,long __RPC_FAR *similarItemsInGroup,long __RPC_FAR *positionInGroup)
1880 SolarMutexGuard g;
1882 ENTER_PROTECTED_BLOCK
1883 ISDESTROY()
1884 // #CHECK#
1885 if(groupLevel == nullptr || similarItemsInGroup == nullptr || positionInGroup == nullptr)
1887 return E_INVALIDARG;
1890 if (!m_xAccessible.is())
1891 return E_FAIL;
1893 Reference<XAccessibleContext> const pRContext =
1894 m_xAccessible->getAccessibleContext();
1895 if(!pRContext.is())
1896 return E_FAIL;
1897 long Role = pRContext->getAccessibleRole();
1899 *groupLevel = 0;
1900 *similarItemsInGroup = 0;
1901 *positionInGroup = 0;
1903 if (Role != AccessibleRole::DOCUMENT && Role != AccessibleRole::DOCUMENT_PRESENTATION &&
1904 Role != AccessibleRole::DOCUMENT_SPREADSHEET && Role != AccessibleRole::DOCUMENT_TEXT)
1906 Reference< XAccessibleGroupPosition > xGroupPosition( pRContext, UNO_QUERY );
1907 if ( xGroupPosition.is() )
1909 Sequence< sal_Int32 > rSeq = xGroupPosition->getGroupPosition( makeAny( pRContext ) );
1910 if (rSeq.getLength() >= 3)
1912 *groupLevel = rSeq[0];
1913 *similarItemsInGroup = rSeq[1];
1914 *positionInGroup = rSeq[2];
1915 return S_OK;
1917 return S_OK;
1921 Reference< XAccessible> pParentAcc = pRContext->getAccessibleParent();
1922 if( !pParentAcc.is() )
1924 return S_OK;
1927 Reference<XAccessibleContext> pRParentContext = pParentAcc->getAccessibleContext();
1929 if( Role == RADIO_BUTTON )
1931 int index = 0;
1932 int number = 0;
1933 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1934 long nRel = pRrelationSet->getRelationCount();
1935 for(int i=0 ; i<nRel ; i++)
1937 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1938 if(accRelation.RelationType == 7)
1940 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1942 Reference<XInterface> pRAcc = xTargets[0];
1943 for(int j=0; j<pRParentContext->getAccessibleChildCount(); j++)
1945 if( getTheParentOfMember(pRParentContext->getAccessibleChild(j).get())
1946 == static_cast<XAccessible*>(pRAcc.get()) &&
1947 pRParentContext->getAccessibleChild(j)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON)
1948 number++;
1949 if (pRParentContext->getAccessibleChild(j).get() == m_xAccessible.get())
1950 index = number;
1954 *groupLevel = 1;
1955 *similarItemsInGroup = number;
1956 *positionInGroup = index;
1957 return S_OK;
1960 else if ( COMBO_BOX == Role )
1962 *groupLevel = 1;
1963 *similarItemsInGroup = 0;
1964 *positionInGroup = -1;
1966 long nCount = pRContext->getAccessibleChildCount();
1967 if( 2 != nCount)
1969 return S_OK;
1971 Reference<XAccessible> xList=pRContext->getAccessibleChild(1);
1972 if (!xList.is())
1974 return S_OK;
1976 Reference<XAccessibleContext> xListContext(xList,UNO_QUERY);
1977 if (!xListContext.is())
1979 return S_OK;
1981 Reference<XAccessibleSelection> xListSel(xList,UNO_QUERY);
1982 if (!xListSel.is())
1984 return S_OK;
1986 *similarItemsInGroup = xListContext->getAccessibleChildCount();
1987 if (*similarItemsInGroup > 0 )
1991 Reference<XAccessible> xChild = xListSel->getSelectedAccessibleChild(0);
1992 if (xChild.is())
1994 Reference<XAccessibleContext> xChildContext(xChild,UNO_QUERY);
1995 if (xChildContext.is())
1997 *positionInGroup=xChildContext->getAccessibleIndexInParent() + 1 ;
1998 return S_OK;
2002 catch(...)
2005 return S_OK;
2007 else if ( PAGE_TAB == Role )
2009 *groupLevel = 1;
2010 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2012 if (*similarItemsInGroup > 0 )
2014 *positionInGroup=pRContext->getAccessibleIndexInParent() + 1 ;
2016 else
2018 *positionInGroup = -1;
2020 return S_OK;
2023 int level = 0;
2024 BOOL isFound = FALSE;
2025 while( pParentAcc.is() && !isFound)
2027 level++;
2028 pRParentContext = pParentAcc->getAccessibleContext();
2029 Role = pRParentContext->getAccessibleRole();
2030 if( (Role == TREE) || (Role == LIST) )
2031 isFound = TRUE;
2032 pParentAcc = pRParentContext->getAccessibleParent();
2035 if( isFound )
2037 Reference< XAccessible> pTempAcc = pRContext->getAccessibleParent();
2038 pRParentContext = pTempAcc->getAccessibleContext();
2039 *groupLevel = level;
2040 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2041 *positionInGroup = pRContext->getAccessibleIndexInParent() + 1;
2043 else
2045 *groupLevel = 0;
2046 *similarItemsInGroup = 0;
2047 *positionInGroup = 0;
2049 return S_OK;
2051 LEAVE_PROTECTED_BLOCK
2054 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_extendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
2056 return E_NOTIMPL;
2060 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_uniqueID(long __RPC_FAR *uniqueID)
2062 SolarMutexGuard g;
2064 ENTER_PROTECTED_BLOCK
2065 ISDESTROY()
2066 // #CHECK#
2067 if(uniqueID == nullptr)
2069 return E_INVALIDARG;
2071 *uniqueID = m_dChildID;
2072 return S_OK;
2074 LEAVE_PROTECTED_BLOCK
2077 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_windowHandle(HWND __RPC_FAR *windowHandle)
2079 SolarMutexGuard g;
2081 ENTER_PROTECTED_BLOCK
2082 ISDESTROY()
2083 // #CHECK#
2084 if(windowHandle == nullptr)
2086 return E_INVALIDARG;
2089 HWND nHwnd = m_hwnd;
2090 IAccessible* pParent = m_pIParent;
2091 while((nHwnd==nullptr) && pParent)
2093 if (CMAccessible* pChild = dynamic_cast<CMAccessible*>(pParent))
2095 pParent = pChild->m_pIParent;
2096 nHwnd = pChild->m_hwnd;
2098 else
2099 pParent = nullptr;
2102 *windowHandle = nHwnd;
2103 return S_OK;
2105 LEAVE_PROTECTED_BLOCK
2109 * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
2110 * @param pXAcc, UNO XAccessible object point.
2111 * @return XAccessibleContext*, the context of the pXAcc.
2113 XAccessibleContext* CMAccessible::GetContextByXAcc( XAccessible* pXAcc )
2115 Reference< XAccessibleContext > pRContext;
2116 if( pXAcc == nullptr)
2117 return nullptr;
2119 pRContext = pXAcc->getAccessibleContext();
2120 if( !pRContext.is() )
2121 return nullptr;
2122 return pRContext.get();
2126 * Return the member variable m_pXAccessibleSelection, instead of
2127 * get XAccessibleSelection according to XAccessibleContext because if so,it will
2128 * depend on the UNO implementation code,so when COM is created, put XAccessibleSelection
2129 * by bridge management system
2130 * @return XAccessibleSelection*, the selection of the current object.
2132 Reference< XAccessibleSelection > CMAccessible::GetSelection()
2134 if (!m_xAccessible.is())
2135 return nullptr;
2136 Reference<XAccessibleContext> const pRContext =
2137 m_xAccessible->getAccessibleContext();
2138 if(pRContext.is())
2140 Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
2141 return pRSelection;
2143 return nullptr;
2147 * Select one XAccessible item, for accSelect implementation
2148 * @param pItem, the item should be selected.
2149 * @return S_OK if successful.
2151 HRESULT CMAccessible::SelectChild(XAccessible* pItem)
2154 ENTER_PROTECTED_BLOCK
2155 ISDESTROY()
2156 XAccessibleContext* pParentContext = GetContextByXAcc(m_xAccessible.get());
2157 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2158 if( pParentContext == nullptr || pContext == nullptr )
2159 return E_FAIL;
2161 Reference< XAccessibleSelection > pRSelection = GetSelection();
2162 if( !pRSelection.is() )
2163 return E_FAIL;
2164 long Index = pContext->getAccessibleIndexInParent();
2165 pRSelection->selectAccessibleChild( Index );
2166 return S_OK;
2168 LEAVE_PROTECTED_BLOCK
2172 * Deselect one XAccessible item, for accSelect implementation
2173 * @param pItem, the item should be deselected.
2174 * @return S_OK if successful.
2176 HRESULT CMAccessible::DeSelectChild(XAccessible* pItem)
2179 ENTER_PROTECTED_BLOCK
2180 ISDESTROY()
2181 XAccessibleContext* pParentContext = GetContextByXAcc(m_xAccessible.get());
2183 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2184 if( pParentContext == nullptr || pContext == nullptr )
2185 return E_INVALIDARG;
2187 Reference< XAccessibleSelection > pRSelection = GetSelection();
2188 if( !pRSelection.is() )
2189 return E_FAIL;
2190 long Index = pContext->getAccessibleIndexInParent();
2191 pRSelection->deselectAccessibleChild( Index );
2193 return S_OK;
2195 LEAVE_PROTECTED_BLOCK
2199 * Select multiple XAccessible items,for implementation of accSelect
2200 * @param pItem, the items should be selected.
2201 * @param size, the size of the items.
2202 * @return S_OK if successful.
2204 HRESULT CMAccessible::SelectMultipleChidren( XAccessible** pItem,int size )
2207 ENTER_PROTECTED_BLOCK
2208 ISDESTROY()
2209 // #CHECK#
2210 if(pItem == nullptr)
2212 return E_INVALIDARG;
2214 for(int index = 0;index < size;index++)
2216 SelectChild( pItem[index] );
2218 return S_OK;
2220 LEAVE_PROTECTED_BLOCK
2224 * Deselect multiple XAccessible items,for implementation of accSelect
2225 * @param pItem, the items should be selected.
2226 * @param size, the size of the items.
2227 * @return S_OK if successful.
2229 HRESULT CMAccessible::DeSelectMultipleChildren( XAccessible** pItem,int size )
2232 ENTER_PROTECTED_BLOCK
2233 ISDESTROY()
2234 // #CHECK#
2235 if(pItem == nullptr)
2237 return E_INVALIDARG;
2239 for(int index = 0;index < size;index++)
2241 DeSelectChild( pItem[index] );
2243 return S_OK;
2245 LEAVE_PROTECTED_BLOCK
2249 * When COM is created, UNO set XAccessible pointer to it
2250 * in order to COM can operate UNO information
2251 * @param pXAcc, the XAccessible object of current object.
2252 * @return S_OK if successful.
2254 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::SetXAccessible(hyper pXAcc)
2256 // internal IMAccessible - no mutex meeded
2258 m_xAccessible = reinterpret_cast<XAccessible*>(pXAcc);
2259 m_pEnumVar->PutSelection(/*XAccessibleSelection*/
2260 reinterpret_cast<hyper>(m_xAccessible.get()));
2262 m_xContext = m_xAccessible->getAccessibleContext();
2264 return S_OK;
2268 * accSelect method has many optional flags, needs to process comprehensively
2269 * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
2270 * The implementation of this flag is a little trouble-shooting,so we also
2271 * do not implement it now
2272 * @param flagsSelect, the selection flag of the select action.
2273 * @param varChild, the child object pointer of current action.
2274 * @return S_OK if successful.
2276 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::accSelect(long flagsSelect, VARIANT varChild)
2278 SolarMutexGuard g;
2280 ENTER_PROTECTED_BLOCK
2281 ISDESTROY()
2282 if( (flagsSelect&SELFLAG_ADDSELECTION) &&
2283 (SELFLAG_REMOVESELECTION&flagsSelect) )
2284 return E_INVALIDARG;
2286 if ( (flagsSelect&SELFLAG_TAKESELECTION) &&
2288 (flagsSelect&SELFLAG_ADDSELECTION) ||
2289 (flagsSelect&SELFLAG_REMOVESELECTION) ||
2290 (flagsSelect&SELFLAG_EXTENDSELECTION )
2293 return E_INVALIDARG;
2295 if ( varChild.vt != VT_I4 )
2296 return E_INVALIDARG;
2298 IMAccessible* pSelectAcc;
2299 if( varChild.lVal == CHILDID_SELF )
2301 pSelectAcc = this;
2302 pSelectAcc->AddRef();
2304 else
2306 pSelectAcc = GetChildInterface(varChild.lVal);
2309 if( pSelectAcc == nullptr )
2310 return E_INVALIDARG;
2312 if( flagsSelect&SELFLAG_TAKEFOCUS )
2314 union {
2315 XAccessible* pTempUNO;
2316 hyper nHyper = 0;
2318 pSelectAcc->GetUNOInterface(&nHyper);
2320 if( pTempUNO == nullptr )
2321 return NULL;
2323 Reference<XAccessibleContext> pRContext = pTempUNO->getAccessibleContext();
2324 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
2325 Reference< XAccessible > pRParentXAcc = pRContext->getAccessibleParent();
2326 Reference< XAccessibleContext > pRParentContext = pRParentXAcc->getAccessibleContext();
2327 Reference< XAccessibleComponent > pRParentComponent(pRParentContext,UNO_QUERY);
2328 Reference< XAccessibleSelection > pRParentSelection(pRParentContext,UNO_QUERY);
2331 pRComponent->grabFocus();
2333 if( flagsSelect & SELFLAG_TAKESELECTION )
2335 pRParentSelection->clearAccessibleSelection();
2336 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2339 if( flagsSelect & SELFLAG_ADDSELECTION )
2341 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2344 if( flagsSelect & SELFLAG_REMOVESELECTION )
2346 pRParentSelection->deselectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2349 if( flagsSelect & SELFLAG_EXTENDSELECTION )
2351 long indexInParrent = pRContext->getAccessibleIndexInParent();
2353 if( pRParentSelection->isAccessibleChildSelected( indexInParrent + 1 ) ||
2354 pRParentSelection->isAccessibleChildSelected( indexInParrent - 1 ) )
2356 pRParentSelection->selectAccessibleChild( indexInParrent );
2362 pSelectAcc->Release();
2363 return S_OK;
2365 LEAVE_PROTECTED_BLOCK
2369 * Return XAccessible interface pointer when needed
2370 * @param pXAcc, [in, out] the Uno interface of the current object.
2371 * @return S_OK if successful.
2373 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::GetUNOInterface(hyper * pXAcc)
2375 // internal IMAccessible - no mutex meeded
2377 if(pXAcc == nullptr)
2378 return E_INVALIDARG;
2380 *pXAcc = reinterpret_cast<hyper>(m_xAccessible.get());
2381 return S_OK;
2385 * Helper method for Implementation of get_accDefaultAction
2386 * @param pAction, the default action point of the current object.
2387 * @return S_OK if successful.
2389 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::SetDefaultAction(hyper pAction)
2391 // internal IMAccessible - no mutex meeded
2393 m_xAction = reinterpret_cast<XAccessibleAction*>(pAction);
2394 return S_OK;
2398 * This method is called when AT open some UI elements initially
2399 * the UI element takes the default action defined here
2400 * @param varChild, the child id of the defaultaction.
2401 * @param pszDefaultAction,[in/out] the description of the current action.
2402 * @return S_OK if successful.
2404 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE CMAccessible::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction)
2406 SolarMutexGuard g;
2408 ENTER_PROTECTED_BLOCK
2409 ISDESTROY()
2410 // #CHECK#
2411 if(pszDefaultAction == nullptr)
2413 return E_INVALIDARG;
2415 if(varChild.vt==VT_I4)
2417 if(varChild.lVal==CHILDID_SELF)
2419 if (!m_xAction.is())
2420 return DISP_E_MEMBERNOTFOUND;
2421 SAFE_SYSFREESTRING(*pszDefaultAction);
2422 *pszDefaultAction = SysAllocString(m_pszActionDescription);
2423 return S_OK;
2426 long lVal = varChild.lVal;
2427 varChild.lVal = CHILDID_SELF;
2428 IMAccessible *pChild = this->GetChildInterface(lVal);
2429 if(!pChild)
2430 return E_FAIL;
2431 return pChild->get_accDefaultAction(varChild,pszDefaultAction);
2433 return S_FALSE;
2435 LEAVE_PROTECTED_BLOCK
2439 * AT call this method to operate application
2440 * @param varChild, the child id of the action object.
2441 * @return S_OK if successful.
2443 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE CMAccessible::accDoDefaultAction(VARIANT varChild)
2445 SolarMutexGuard g;
2447 ENTER_PROTECTED_BLOCK
2448 ISDESTROY()
2449 if( varChild.vt != VT_I4 )
2450 return E_INVALIDARG;
2451 if (!m_xAction.is())
2452 return E_FAIL;
2453 if (m_xAction->getAccessibleActionCount() == 0)
2454 return E_FAIL;
2456 if(varChild.lVal==CHILDID_SELF)
2458 if (m_xAction->getAccessibleActionCount() > 0)
2459 m_xAction->doAccessibleAction(0);
2460 return S_OK;
2463 long lVal = varChild.lVal;
2464 varChild.lVal = CHILDID_SELF;
2465 IMAccessible *pChild = this->GetChildInterface(lVal);
2466 if(!pChild)
2467 return E_FAIL;
2468 return pChild->accDoDefaultAction( varChild );
2470 LEAVE_PROTECTED_BLOCK
2474 * UNO set description information for action to COM.
2475 * @param szAction, the action description of the current object.
2476 * @return S_OK if successful.
2478 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Put_ActionDescription( const OLECHAR* szAction)
2480 // internal IMAccessible - no mutex meeded
2482 ENTER_PROTECTED_BLOCK
2483 ISDESTROY()
2484 // #CHECK#
2485 if(szAction == nullptr)
2487 return E_INVALIDARG;
2489 SAFE_SYSFREESTRING(m_pszActionDescription );
2490 m_pszActionDescription = SysAllocString( szAction );
2491 return S_OK;
2493 LEAVE_PROTECTED_BLOCK
2496 BOOL CMAccessible::GetXInterfaceFromXAccessible(XAccessible* pXAcc, XInterface** ppXI, int index)
2498 Reference< XAccessibleContext > pRContext;
2500 switch(index)
2502 case XI_COMPONENT:
2503 QUERYXINTERFACE(AccessibleComponent)
2504 break;
2505 case XI_TEXT:
2506 QUERYXINTERFACE(AccessibleText)
2507 break;
2508 case XI_EDITABLETEXT:
2509 QUERYXINTERFACE(AccessibleEditableText)
2510 break;
2511 case XI_TABLE:
2512 QUERYXINTERFACE(AccessibleTable)
2513 break;
2514 case XI_SELECTION:
2515 QUERYXINTERFACE(AccessibleSelection)
2516 break;
2517 case XI_EXTENDEDCOMP:
2518 QUERYXINTERFACE(AccessibleExtendedComponent)
2519 break;
2520 case XI_KEYBINDING:
2521 QUERYXINTERFACE(AccessibleKeyBinding)
2522 break;
2523 case XI_ACTION:
2524 QUERYXINTERFACE(AccessibleAction)
2525 break;
2526 case XI_VALUE:
2527 QUERYXINTERFACE(AccessibleValue)
2528 break;
2529 case XI_HYPERTEXT:
2530 QUERYXINTERFACE(AccessibleHypertext)
2531 break;
2532 case XI_HYPERLINK:
2533 QUERYXINTERFACE(AccessibleHyperlink)
2534 break;
2535 case XI_IMAGE:
2536 QUERYXINTERFACE(AccessibleImage)
2537 break;
2538 default:
2539 break;
2542 return FALSE;
2545 template<typename T> static HRESULT
2546 createAggInstance(CMAccessible &rOuter, void ** ppvObject)
2548 // Note: CComAggObject has special handling for IUnknown - must
2549 // query for that when creating it! Otherwise we get a T member of it
2550 // which will redirect QueryInterface back to CMAccessible infinitely.
2551 // (CComAggObject has its own ref-count too which is not a problem
2552 // since it is inserted in m_containedObjects.)
2553 return CComCreator< CComAggObject<T> >::CreateInstance(
2554 rOuter.GetControllingUnknown(), IID_IUnknown, ppvObject);
2557 typedef HRESULT (AggCreatorFunc)(CMAccessible &, void **);
2559 struct AggMapEntry
2561 const IID* piid;
2562 AggCreatorFunc* pfnCreateInstance;
2563 int XIFIndex;
2566 static AggMapEntry g_CMAccessible_AggMap[] = {
2567 { &IID_IAccessibleComponent, &createAggInstance<CAccComponent>, XI_COMPONENT },
2568 { &IID_IAccessibleText, &createAggInstance<CAccText>, XI_TEXT },
2569 { &IID_IAccessibleEditableText, &createAggInstance<CAccEditableText>, XI_EDITABLETEXT },
2570 { &IID_IAccessibleImage, &createAggInstance<CAccImage>, XI_IMAGE },
2571 { &IID_IAccessibleTable, &createAggInstance<CAccTable>, XI_TABLE },
2572 { &IID_IAccessibleAction, &createAggInstance<CAccAction>, XI_ACTION },
2573 { &IID_IAccessibleValue, &createAggInstance<CAccValue>, XI_VALUE },
2574 { &IID_IAccessibleHypertext, &createAggInstance<CAccHypertext>, XI_HYPERTEXT },
2575 { &IID_IAccessibleHyperlink, &createAggInstance<CAccHyperLink>, XI_HYPERLINK },
2576 { nullptr, nullptr, 0 },
2580 HRESULT WINAPI CMAccessible::SmartQI(void* /*pv*/, REFIID iid, void** ppvObject)
2582 ENTER_PROTECTED_BLOCK
2584 ISDESTROY()
2585 if (InlineIsEqualGUID(iid,IID_IAccIdentity) ||
2586 InlineIsEqualGUID(iid,IID_IStdMarshalInfo) ||
2587 InlineIsEqualGUID(iid,IID_IMarshal) ||
2588 InlineIsEqualGUID(iid,IID_IExternalConnection)||
2589 InlineIsEqualGUID(iid,IID_IOleWindow))
2591 return E_FAIL;
2594 AggMapEntry * pMap = &g_CMAccessible_AggMap[0];
2595 while(pMap && pMap->piid)
2597 if (InlineIsEqualGUID(iid, *pMap->piid))
2599 SolarMutexGuard g;
2601 XInterface* pXI = nullptr;
2602 BOOL bFound = GetXInterfaceFromXAccessible(m_xAccessible.get(),
2603 &pXI, pMap->XIFIndex);
2604 if(!bFound)
2606 return E_FAIL;
2609 XGUIDToComObjHash::iterator pIndTemp = m_containedObjects.find( iid );
2610 if ( pIndTemp != m_containedObjects.end() )
2612 return pIndTemp->second.p->QueryInterface( iid, ppvObject );
2614 else
2616 HRESULT hr = pMap->pfnCreateInstance(*this, ppvObject);
2617 assert(hr == S_OK);
2618 if(hr == S_OK)
2620 m_containedObjects.emplace(*pMap->piid, static_cast<IUnknown*>(*ppvObject));
2621 IUNOXWrapper* wrapper = nullptr;
2622 static_cast<IUnknown*>(*ppvObject)->QueryInterface(IID_IUNOXWrapper, reinterpret_cast<void**>(&wrapper));
2623 if(wrapper)
2625 wrapper->put_XInterface(
2626 reinterpret_cast<hyper>(m_xAccessible.get()));
2627 wrapper->Release();
2629 return S_OK;
2632 return E_FAIL;
2634 pMap++;
2636 return E_FAIL;
2638 LEAVE_PROTECTED_BLOCK
2641 BOOL
2642 CMAccessible::get_IAccessibleFromXAccessible(XAccessible * pXAcc, IAccessible **ppIA)
2648 // #CHECK#
2649 if(ppIA == nullptr)
2651 return FALSE;
2653 BOOL isGet = FALSE;
2654 if(g_pAgent)
2655 isGet = g_pAgent->GetIAccessibleFromXAccessible(pXAcc, ppIA);
2657 if(isGet)
2658 return TRUE;
2659 else
2660 return FALSE;
2663 catch(...)
2665 return FALSE;
2669 OUString CMAccessible::get_StringFromAny(Any const & pAny)
2671 switch(pAny.getValueTypeClass())
2673 case TypeClass_CHAR:
2675 sal_Int8 val;
2676 pAny >>= val;
2677 return OUString::number(val);
2679 case TypeClass_BOOLEAN:
2681 bool val;
2682 pAny >>= val;
2683 return OUString::number(int(val));
2685 case TypeClass_BYTE:
2687 sal_Int8 val;
2688 pAny >>= val;
2689 return OUString::number(val);
2691 case TypeClass_SHORT:
2693 sal_Int16 val;
2694 pAny >>= val;
2695 return OUString::number(val);
2697 case TypeClass_UNSIGNED_SHORT:
2699 sal_uInt16 val;
2700 pAny >>= val;
2701 return OUString::number(val);
2703 case TypeClass_LONG:
2705 sal_Int32 val;
2706 pAny >>= val;
2707 return OUString::number(val);
2709 case TypeClass_UNSIGNED_LONG:
2711 sal_uInt32 val;
2712 pAny >>= val;
2713 return OUString::number(val);
2715 case TypeClass_FLOAT:
2717 float val;
2718 pAny >>= val;
2719 return OUString::number(val);
2721 case TypeClass_DOUBLE:
2723 double val;
2724 pAny >>= val;
2725 return OUString::number(val);
2727 case TypeClass_STRING:
2729 OUString val;
2730 pAny >>= val;
2731 return val;
2733 case TypeClass_SEQUENCE:
2735 if(pAny.getValueType() == cppu::UnoType<Sequence< OUString >>::get())
2737 Sequence < OUString > val;
2738 pAny >>= val;
2740 OUStringBuffer pString;
2742 int count = val.getLength();
2744 for( int iIndex = 0;iIndex < count;iIndex++ )
2746 pString.append(val[iIndex]);
2748 return pString.makeStringAndClear();
2750 else if (pAny.getValueType() == cppu::UnoType<Sequence< css::style::TabStop >>::get())
2752 Sequence < css::style::TabStop > val;
2753 pAny >>= val;
2754 int count = val.getLength();
2756 OUStringBuffer buf;
2757 for( int iIndex = 0;iIndex < count;iIndex++ )
2759 css::style::TabStop sigleVal = val[iIndex];
2761 buf.append("Position=");
2762 buf.append(sigleVal.Position);
2763 buf.append(",TabAlign=");
2764 buf.append(sal_Int32(sigleVal.Alignment));
2765 buf.append(",");
2767 buf.append("DecimalChar=");
2768 if(sigleVal.DecimalChar==';' || sigleVal.DecimalChar == ':' || sigleVal.DecimalChar == ',' ||
2769 sigleVal.DecimalChar == '=' || sigleVal.DecimalChar == '\\')
2770 buf.append('\\');
2771 buf.append(sigleVal.DecimalChar);
2772 buf.append(",");
2774 buf.append("FillChar=");
2775 if(sigleVal.FillChar==';' || sigleVal.FillChar == ':' || sigleVal.FillChar == ',' ||
2776 sigleVal.FillChar == '=' || sigleVal.FillChar == '\\')
2777 buf.append('\\');
2778 buf.append(sigleVal.FillChar);
2779 buf.append(",");
2781 return buf.makeStringAndClear();
2783 break;
2785 case TypeClass_ENUM:
2787 if (pAny.getValueType() == cppu::UnoType<css::awt::FontSlant>::get())
2789 css::awt::FontSlant val;
2790 pAny >>= val;
2791 return OUString::number(sal_Int32(val));
2793 break;
2795 case TypeClass_STRUCT:
2797 if (pAny.getValueType() == cppu::UnoType<css::style::LineSpacing>::get())
2799 css::style::LineSpacing val;
2800 pAny >>= val;
2801 return "Mode=" + OUString::number(val.Mode) + ",Height="
2802 + OUString::number(val.Height) + ",";
2804 else if (pAny.getValueType() == cppu::UnoType<css::accessibility::TextSegment>::get())
2806 css::accessibility::TextSegment val;
2807 pAny >>= val;
2808 return val.SegmentText;
2810 break;
2812 case TypeClass_VOID:
2813 case TypeClass_HYPER:
2814 case TypeClass_UNSIGNED_HYPER:
2815 case TypeClass_TYPE:
2816 case TypeClass_ANY:
2817 case TypeClass_TYPEDEF:
2818 case TypeClass_EXCEPTION:
2819 case TypeClass_INTERFACE:
2820 case TypeClass_SERVICE:
2821 case TypeClass_MODULE:
2822 case TypeClass_INTERFACE_METHOD:
2823 case TypeClass_INTERFACE_ATTRIBUTE:
2824 case TypeClass_UNKNOWN:
2825 case TypeClass_PROPERTY:
2826 case TypeClass_CONSTANT:
2827 case TypeClass_CONSTANTS:
2828 case TypeClass_SINGLETON:
2829 break;
2830 default:
2831 break;
2833 return OUString();
2836 OUString CMAccessible::get_String4Numbering(const Any& pAny, sal_Int16 numberingLevel,const OUString& numberingPrefix)
2838 Reference< css::container::XIndexReplace > pXIndex;
2839 if((pAny>>=pXIndex) && (numberingLevel !=-1))//numbering level is -1,means invalid value
2841 Any aAny = pXIndex->getByIndex(numberingLevel);
2842 Sequence< css::beans::PropertyValue > aProps;
2843 aAny >>= aProps;
2844 const css::beans::PropertyValue* pPropArray = aProps.getConstArray();
2845 sal_Int32 nCount = aProps.getLength();
2846 OUStringBuffer buf("Numbering:NumberingLevel=");
2847 buf.append(sal_Int32(numberingLevel));
2848 buf.append(',');
2849 for( sal_Int32 i=0; i<nCount; i++ )
2851 css::beans::PropertyValue rProp = pPropArray[i];
2852 if( (rProp.Name == "BulletChar" ) ||
2853 (rProp.Name == "NumberingType" ))
2855 buf.append(rProp.Name);
2856 buf.append('=');
2857 auto const pTemp = CMAccessible::get_StringFromAny(rProp.Value);
2858 buf.append(pTemp);
2859 buf.append(',');
2861 if(rProp.Name == "NumberingType")
2863 if(numberingPrefix.getLength()!=0)
2865 buf.append("NumberingPrefix=");
2866 buf.append(numberingPrefix);
2871 return buf.makeStringAndClear();
2874 //Because now have three types numbering level:
2875 //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
2876 //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
2877 //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
2878 // IAText:numberinglevel base on 0, but TOC's level base on 1,
2879 // so NumberingLevel value will be decreased 1 in bridge code.
2880 else if(numberingLevel >0)
2882 return "Numbering:NumberingLevel=" + OUString::number(numberingLevel-1) + ",NumberingType=4,NumberingPrefix=,";
2884 else
2886 return "Numbering:";
2890 void CMAccessible::ConvertAnyToVariant(const css::uno::Any &rAnyVal, VARIANT *pvData)
2892 if(rAnyVal.hasValue())
2894 // Clear VARIANT variable.
2895 VariantClear(pvData);
2897 // Set value according to value type.
2898 switch(rAnyVal.getValueTypeClass())
2900 case TypeClass_CHAR:
2901 pvData->vt = VT_UI1;
2902 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Char));
2903 break;
2905 case TypeClass_BOOLEAN:
2907 bool bBoolean(false);
2908 rAnyVal >>= bBoolean;
2909 pvData->vt = VT_BOOL;
2910 pvData->boolVal = VARIANT_BOOL(bBoolean); // boolVal is a VARIANT_BOOL, a 16bit field
2911 break;
2913 case TypeClass_BYTE:
2914 pvData->vt = VT_UI1;
2915 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Int8));
2916 break;
2918 case TypeClass_SHORT:
2919 pvData->vt = VT_I2;
2920 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_Int16));
2921 break;
2923 case TypeClass_UNSIGNED_SHORT:
2924 pvData->vt = VT_I2;
2925 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_uInt16));
2926 break;
2928 case TypeClass_LONG:
2929 pvData->vt = VT_I4;
2930 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_Int32));
2931 break;
2933 case TypeClass_UNSIGNED_LONG:
2934 pvData->vt = VT_I4;
2935 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_uInt32));
2936 break;
2938 case TypeClass_FLOAT:
2939 pvData->vt = VT_R4;
2940 memcpy(&pvData->fltVal, rAnyVal.getValue(), sizeof(float));
2941 break;
2943 case TypeClass_DOUBLE:
2944 pvData->vt = VT_R8;
2945 memcpy(&pvData->dblVal, rAnyVal.getValue(), sizeof(double));
2946 break;
2948 case TypeClass_STRING:
2950 pvData->vt = VT_BSTR;
2951 OUString val;
2952 rAnyVal >>= val;
2953 pvData->bstrVal = SysAllocString(o3tl::toW(val.getStr()));
2954 break;
2957 case TypeClass_VOID:
2958 case TypeClass_HYPER:
2959 case TypeClass_UNSIGNED_HYPER:
2960 case TypeClass_TYPE:
2961 case TypeClass_ANY:
2962 case TypeClass_ENUM:
2963 case TypeClass_TYPEDEF:
2964 case TypeClass_STRUCT:
2965 case TypeClass_EXCEPTION:
2966 case TypeClass_SEQUENCE:
2967 case TypeClass_INTERFACE:
2969 Reference< XAccessible > pXAcc;
2970 if(rAnyVal >>= pXAcc)
2972 if(pXAcc.is())
2974 IAccessible* pIAcc = nullptr;
2975 get_IAccessibleFromXAccessible(pXAcc.get(), &pIAcc);
2976 if(pIAcc == nullptr)
2978 Reference< XAccessibleContext > pXAccContext = pXAcc->getAccessibleContext();
2979 g_pAgent->InsertAccObj(pXAcc.get(),pXAccContext->getAccessibleParent().get());
2980 get_IAccessibleFromXAccessible(pXAcc.get(), &pIAcc);
2982 if(pIAcc)
2984 pIAcc->AddRef();
2986 pvData->vt = VT_UNKNOWN;
2987 pvData->pdispVal = static_cast<IAccessible2*>(pIAcc);
2988 break;
2992 [[fallthrough]];
2994 case TypeClass_SERVICE:
2995 case TypeClass_MODULE:
2996 case TypeClass_INTERFACE_METHOD:
2997 case TypeClass_INTERFACE_ATTRIBUTE:
2998 case TypeClass_UNKNOWN:
2999 case TypeClass_PROPERTY:
3000 case TypeClass_CONSTANT:
3001 case TypeClass_CONSTANTS:
3002 case TypeClass_SINGLETON:
3003 case TypeClass::TypeClass_MAKE_FIXED_SIZE:
3004 // Output the type string, if there is other uno value type.
3005 pvData->vt = VT_BSTR;
3006 pvData->bstrVal = SysAllocString(o3tl::toW(rAnyVal.getValueTypeName().getStr()));
3007 break;
3009 default:
3010 break;
3013 else
3015 VariantClear(pvData);
3019 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::Get_XAccChildID(long* childID)
3021 // internal IMAccessible - no mutex meeded
3023 if(childID == nullptr)
3025 return E_FAIL;
3027 *childID = m_dChildID;
3028 return S_OK;
3031 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_states(AccessibleStates __RPC_FAR *states )
3033 SolarMutexGuard g;
3035 ENTER_PROTECTED_BLOCK
3036 ISDESTROY()
3038 if (!m_xContext.is())
3039 return E_FAIL;
3041 Reference<XAccessibleStateSet> const pRStateSet =
3042 m_xContext.get()->getAccessibleStateSet();
3043 if(!pRStateSet.is())
3045 return S_OK;
3047 Sequence<short> pStates = pRStateSet->getStates();
3050 long count = pStates.getLength() ;
3051 *states = 0x0;
3052 for( int i = 0; i < count; i++ )
3054 for( std::size_t j = 0; j < SAL_N_ELEMENTS(UNO_STATES); j++ )
3056 if( pStates[i] == UNO_STATES[j] )
3058 *states |= IA2_STATES[j];
3059 break;
3063 return S_OK;
3066 LEAVE_PROTECTED_BLOCK
3069 // return the UNO roles
3070 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_extendedRole( BSTR __RPC_FAR * )
3072 return E_NOTIMPL;
3075 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_localizedExtendedRole( BSTR __RPC_FAR * )
3077 return E_NOTIMPL;
3080 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_nExtendedStates( long __RPC_FAR * )
3082 return E_NOTIMPL;
3086 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_localizedExtendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
3088 return E_NOTIMPL;
3092 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_indexInParent( long __RPC_FAR *accParentIndex)
3094 ENTER_PROTECTED_BLOCK
3095 ISDESTROY()
3096 // #CHECK#
3097 if(accParentIndex == nullptr)
3098 return E_INVALIDARG;
3100 if (!m_xContext.is())
3101 return E_FAIL;
3103 *accParentIndex = m_xContext.get()->getAccessibleIndexInParent();
3104 return S_OK;
3107 LEAVE_PROTECTED_BLOCK
3109 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_locale( IA2Locale __RPC_FAR *locale )
3111 ENTER_PROTECTED_BLOCK
3112 ISDESTROY()
3113 if(locale == nullptr)
3114 return E_INVALIDARG;
3116 if (!m_xContext.is())
3117 return E_FAIL;
3119 css::lang::Locale unoLoc = m_xContext.get()->getLocale();
3120 locale->language = SysAllocString(o3tl::toW(unoLoc.Language.getStr()));
3121 locale->country = SysAllocString(o3tl::toW(unoLoc.Country.getStr()));
3122 locale->variant = SysAllocString(o3tl::toW(unoLoc.Variant.getStr()));
3124 return S_OK;
3126 LEAVE_PROTECTED_BLOCK
3129 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_appName( BSTR __RPC_FAR *name)
3131 SolarMutexGuard g;
3133 ENTER_PROTECTED_BLOCK
3134 ISDESTROY()
3135 if(name == nullptr)
3136 return E_INVALIDARG;
3138 *name = SysAllocString(OLESTR("Hannover"));
3139 return S_OK;
3140 LEAVE_PROTECTED_BLOCK
3142 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_appVersion(BSTR __RPC_FAR *version)
3144 SolarMutexGuard g;
3146 ENTER_PROTECTED_BLOCK
3147 ISDESTROY()
3148 if(version == nullptr)
3149 return E_INVALIDARG;
3150 *version=SysAllocString(OLESTR("3.0"));
3151 return S_OK;
3152 LEAVE_PROTECTED_BLOCK
3154 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_toolkitName(BSTR __RPC_FAR *name)
3156 SolarMutexGuard g;
3158 ENTER_PROTECTED_BLOCK
3159 ISDESTROY()
3160 if(name == nullptr)
3161 return E_INVALIDARG;
3162 *name = SysAllocString(OLESTR(" "));
3163 return S_OK;
3164 LEAVE_PROTECTED_BLOCK
3166 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible:: get_toolkitVersion(BSTR __RPC_FAR *version)
3168 SolarMutexGuard g;
3170 ENTER_PROTECTED_BLOCK
3171 ISDESTROY()
3172 if(version == nullptr)
3173 return E_INVALIDARG;
3174 *version = SysAllocString(OLESTR(" "));
3175 return S_OK;
3176 LEAVE_PROTECTED_BLOCK
3180 COM_DECLSPEC_NOTHROW STDMETHODIMP CMAccessible::get_attributes(/*[out]*/ BSTR *pAttr)
3182 SolarMutexGuard g;
3184 ENTER_PROTECTED_BLOCK
3185 ISDESTROY()
3187 if (!m_xAccessible.is())
3188 return E_FAIL;
3190 Reference<XAccessibleContext> pRContext = m_xAccessible->getAccessibleContext();
3191 if( !pRContext.is() )
3193 return E_FAIL;
3195 Reference<XAccessibleExtendedAttributes> pRXI(pRContext,UNO_QUERY);
3196 if( !pRXI.is() )
3197 return E_FAIL;
3198 else
3200 css::uno::Reference<css::accessibility::XAccessibleExtendedAttributes> pRXAttr;
3201 pRXAttr = pRXI.get();
3202 css::uno::Any anyVal = pRXAttr->getExtendedAttributes();
3204 OUString val;
3205 anyVal >>= val;
3207 if(*pAttr)
3208 SAFE_SYSFREESTRING(*pAttr);
3209 *pAttr = SysAllocString(o3tl::toW(val.getStr()));
3211 return S_OK;
3213 LEAVE_PROTECTED_BLOCK
3216 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */