1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include "MAccessible.h"
26 #include "AccAction.h"
27 #include "AccRelation.h"
28 #include "AccComponent.h"
30 #include "AccEditableText.h"
33 #include "AccTableCell.h"
35 #include "AccHypertext.h"
36 #include "AccHyperLink.h"
38 #include <rtl/ustrbuf.hxx>
39 #include <sal/log.hxx>
40 #include <unotools/configmgr.hxx>
41 #include <vcl/svapp.hxx>
42 #include <o3tl/char16_t2wchar_t.hxx>
43 #include <comphelper/AccessibleImplementationHelper.hxx>
45 #include <com/sun/star/accessibility/XAccessibleText.hpp>
46 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
47 #include <com/sun/star/accessibility/XAccessibleImage.hpp>
48 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
49 #include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
50 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
51 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
52 #include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
53 #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
54 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
55 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
56 #include <com/sun/star/accessibility/AccessibleRole.hpp>
57 #include <com/sun/star/accessibility/XAccessibleGroupPosition.hpp>
58 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
59 #include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
60 #include <com/sun/star/style/LineSpacing.hpp>
61 #include <com/sun/star/style/TabStop.hpp>
62 #include <com/sun/star/container/XIndexReplace.hpp>
65 using namespace com::sun::star::uno
;
66 using namespace com::sun::star::accessibility
;
67 using namespace com::sun::star::accessibility::AccessibleStateType
;
71 enum class XInterfaceType
{
88 template <class Interface
>
89 bool queryXInterface(XAccessible
* pXAcc
, XInterface
** ppXI
)
94 Reference
<XAccessibleContext
> pRContext
= pXAcc
->getAccessibleContext();
98 Reference
<Interface
> pRXI(pRContext
, UNO_QUERY
);
106 // Since there's no specific XInterface for table cells, this
107 // method checks that the accessible's parent is a table
108 // (implements XAccessibleTable) and pXAcc's context implements
109 // XAccessibleComponent.
110 bool queryTableCell(XAccessible
* pXAcc
, XInterface
** ppXI
)
112 XInterface
* pXInterface
= nullptr;
114 const bool bSupportsInterface
= queryXInterface
<XAccessibleComponent
>(pXAcc
, &pXInterface
);
115 if (!bSupportsInterface
)
118 // check whether parent is a table (its accessible context implements XAccessibleTable)
119 XInterface
* pParentXInterface
= nullptr;
120 Reference
<XAccessible
> xParentAcc
= pXAcc
->getAccessibleContext()->getAccessibleParent();
121 const bool bParentIsTable
= queryXInterface
<XAccessibleTable
>(xParentAcc
.get(), &pParentXInterface
);
132 // IA2 states mapping, and name
133 // maintenance the consistency, change one array, change the three all
134 long const IA2_STATES
[] =
136 IA2_STATE_ACTIVE
, // = 0x1;
137 IA2_STATE_ARMED
, // = 0x2;
138 IA2_STATE_DEFUNCT
, // = 0x4;
139 IA2_STATE_EDITABLE
, // = 0x8;
140 IA2_STATE_HORIZONTAL
, // = 0x10;
141 IA2_STATE_ICONIFIED
, // = 0x20;
142 IA2_STATE_INVALID_ENTRY
, // = 0x80;
143 IA2_STATE_MANAGES_DESCENDANTS
, // = 0x100;
144 IA2_STATE_MODAL
, // = 0x200;
145 IA2_STATE_MULTI_LINE
, // = 0x400;
146 IA2_STATE_OPAQUE
, // = 0x800;
147 IA2_STATE_REQUIRED
, // = 0x2000;
148 IA2_STATE_SELECTABLE_TEXT
, // = 0x3000;
149 IA2_STATE_SINGLE_LINE
, // = 0x4000;
150 IA2_STATE_STALE
, // = 0x8000;
151 IA2_STATE_SUPPORTS_AUTOCOMPLETION
, // = 0x10000;
152 IA2_STATE_TRANSIENT
, //= 0x20000;
153 IA2_STATE_VERTICAL
// = 0x40000;
156 sal_Int64
const UNO_STATES
[] =
164 -1, //IA2_STATE_INVALID_ENTRY
169 -1, //IA2_STATE_REQUIRED
170 -1, //IA2_STATE_SELECTABLE_TEXT
173 -1, //IA2_STATE_SUPPORTS_AUTOCOMPLETION
174 TRANSIENT
, //IA2_STATE_TRANSIENT
178 using namespace com::sun::star::accessibility::AccessibleRole
;
181 AccObjectManagerAgent
* CMAccessible::g_pAgent
= nullptr;
183 CMAccessible::CMAccessible():
186 m_pszActionDescription(nullptr),
191 m_dFocusChildID(UACC_NO_FOCUS
),
195 CEnumVariant::Create(&m_pEnumVar
);
196 m_containedObjects
.clear();
199 CMAccessible::~CMAccessible()
203 if(m_pszName
!=nullptr)
205 SysFreeString(std::exchange(m_pszName
, nullptr));
207 if(m_pszValue
!=nullptr)
209 SysFreeString(std::exchange(m_pszValue
, nullptr));
212 if(m_pszActionDescription
!=nullptr)
214 SysFreeString(std::exchange(m_pszActionDescription
, nullptr));
219 m_pIParent
->Release();
222 m_pEnumVar
->Release();
223 m_containedObjects
.clear();
227 * Returns the Parent IAccessible interface pointer to AT.
228 * It should add reference, and the client should release the component.
229 * It should return E_FAIL when the parent point is null.
230 * @param ppdispParent [in,out] used to return the parent interface point.
231 * when the point is null, should return null.
232 * @return S_OK if successful and E_FAIL if the m_pIParent is NULL.
234 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accParent(IDispatch
**ppdispParent
)
239 if (m_isDestroy
) return S_FALSE
;
241 if(ppdispParent
== nullptr)
248 *ppdispParent
= m_pIParent
;
249 (*ppdispParent
)->AddRef();
254 HRESULT hr
= AccessibleObjectFromWindow(m_hwnd
, OBJID_WINDOW
, IID_IAccessible
, reinterpret_cast<void**>(ppdispParent
));
255 if (!SUCCEEDED(hr
) || !*ppdispParent
)
263 } catch(...) { return E_FAIL
; }
267 * Returns child count of current COM object.
268 * @param pcountChildren [in,out] used to return the children count.
269 * @return S_OK if successful.
271 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accChildCount(long *pcountChildren
)
276 if (m_isDestroy
) return S_FALSE
;
278 if(pcountChildren
== nullptr)
283 if (!m_xAccessible
.is())
286 Reference
<XAccessibleContext
> const pRContext
=
287 m_xAccessible
->getAccessibleContext();
290 sal_Int64 nChildCount
= pRContext
->getAccessibleChildCount();
291 if (nChildCount
> std::numeric_limits
<long>::max())
293 SAL_WARN("iacc2", "CMAccessible::get_accChildCount: Child count exceeds maximum long value, "
294 "returning max long.");
295 nChildCount
= std::numeric_limits
<long>::max();
298 *pcountChildren
= nChildCount
;
303 } catch(...) { return E_FAIL
; }
307 * Returns child interface pointer for AT according to input child ID.
308 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
309 * the child ID specify child index from 0 to children count, 0 stands for object self.
310 * @param ppdispChild, [in,out] use to return the child interface point.
311 * @return S_OK if successful and S_FALSE if failure.
313 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accChild(VARIANT varChild
, IDispatch
**ppdispChild
)
318 if (m_isDestroy
) return S_FALSE
;
320 if(ppdispChild
== nullptr)
324 if(varChild
.vt
==VT_I4
)
326 //get child interface pointer due to child ID
327 if(varChild
.lVal
==CHILDID_SELF
)
333 *ppdispChild
= GetChildInterface(varChild
.lVal
);
334 if((*ppdispChild
) == nullptr)
336 (*ppdispChild
)->AddRef();
341 } catch(...) { return E_FAIL
; }
345 * Returns the accessible name of the current COM object self or its one child to AT.
346 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
347 * the child ID specify child index from 0 to children count, 0 stands for object self.
348 * @param pszName, [in,out] use to return the name of the proper object.
349 * @return S_OK if successful and S_FALSE if failure.
351 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accName(VARIANT varChild
, BSTR
*pszName
)
356 if (m_isDestroy
) return S_FALSE
;
358 if(pszName
== nullptr)
362 if(varChild
.vt
==VT_I4
)
364 if(varChild
.lVal
==CHILDID_SELF
)
366 SysFreeString(*pszName
);
367 *pszName
= SysAllocString(m_pszName
);
371 long lVal
= varChild
.lVal
;
372 varChild
.lVal
= CHILDID_SELF
;
373 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
376 return pChild
->get_accName(varChild
,pszName
);
380 } catch(...) { return E_FAIL
; }
384 * Returns the accessible value of the current COM object self or its one child to AT.
385 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
386 * the child ID specify child index from 0 to children count, 0 stands for object self.
387 * @param pszValue, [in,out] use to return the value of the proper object.
388 * @return S_OK if successful and S_FALSE if failure.
390 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accValue(VARIANT varChild
, BSTR
*pszValue
)
395 if (m_isDestroy
) return S_FALSE
;
397 if( pszValue
== nullptr )
401 if( varChild
.vt
==VT_I4
)
403 if(varChild
.lVal
==CHILDID_SELF
)
405 if(m_dState
& STATE_SYSTEM_PROTECTED
)
406 return E_ACCESSDENIED
;
408 if ( m_pszValue
!=nullptr && wcslen(m_pszValue
) == 0 )
411 SysFreeString(*pszValue
);
412 *pszValue
= SysAllocString(m_pszValue
);
416 long lVal
= varChild
.lVal
;
417 varChild
.lVal
= CHILDID_SELF
;
418 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
421 return pChild
->get_accValue(varChild
,pszValue
);
425 } catch(...) { return E_FAIL
; }
429 * Returns the accessible description of the current COM object self or its one child to AT.
430 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
431 * the child ID specify child index from 0 to children count, 0 stands for object self.
432 * @param pszDescription, [in,out] use to return the description of the proper object.
433 * @return S_OK if successful and E_FAIL if failure.
435 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accDescription(VARIANT varChild
, BSTR
*pszDescription
)
440 if (m_isDestroy
) return S_FALSE
;
442 if(pszDescription
== nullptr)
446 if(varChild
.vt
==VT_I4
)
448 if(varChild
.lVal
==CHILDID_SELF
)
450 if (!m_xAccessible
.is())
453 Reference
<XAccessibleContext
> xContext
= m_xAccessible
->getAccessibleContext();
457 const OUString sDescription
= xContext
->getAccessibleDescription();
458 SysFreeString(*pszDescription
);
459 *pszDescription
= SysAllocString(o3tl::toW(sDescription
.getStr()));
463 long lVal
= varChild
.lVal
;
464 varChild
.lVal
= CHILDID_SELF
;
465 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
468 return pChild
->get_accDescription(varChild
,pszDescription
);
472 } catch(...) { return E_FAIL
; }
476 * Returns the accessible role of the current COM object self or its one child to AT.
477 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
478 * the child ID specify child index from 0 to children count, 0 stands for object self.
479 * @param pvarRole, [in,out] use to return the role of the proper object.
480 * @return S_OK if successful and S_FALSE if failure.
482 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accRole(VARIANT varChild
, VARIANT
*pvarRole
)
487 if (m_isDestroy
) return S_FALSE
;
489 if(pvarRole
== nullptr)
493 if(varChild
.vt
== VT_I4
)
496 if(varChild
.lVal
== CHILDID_SELF
)
498 VariantInit(pvarRole
);
499 pvarRole
->vt
= VT_I4
;
501 if (m_iRole
< IA2_ROLE_CAPTION
)
502 pvarRole
->lVal
= m_iRole
;
504 pvarRole
->lVal
= ROLE_SYSTEM_CLIENT
;
510 long lVal
= varChild
.lVal
;
511 varChild
.lVal
= CHILDID_SELF
;
512 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
515 return pChild
->get_accRole(varChild
,pvarRole
);
519 } catch(...) { return E_FAIL
; }
523 * Returns the accessible state of the current COM object self or its one child to AT.
524 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
525 * the child ID specify child index from 0 to children count, 0 stands for object self.
526 * @param pvarState, [in,out] use to return the state of the proper object.
527 * @return S_OK if successful and S_FALSE if failure.
529 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accState(VARIANT varChild
, VARIANT
*pvarState
)
534 if (m_isDestroy
) return S_FALSE
;
536 if(pvarState
== nullptr)
540 if(varChild
.vt
==VT_I4
)
542 if(varChild
.lVal
== CHILDID_SELF
)
544 if (m_xAccessible
.is())
546 Reference
<XAccessibleContext
> const pContext
=
547 m_xAccessible
->getAccessibleContext();
550 // add the STATE_SYSTEM_LINKED state
551 Reference
< XAccessibleHypertext
> pRHypertext(pContext
,UNO_QUERY
);
554 if( pRHypertext
->getHyperLinkCount() > 0 )
555 m_dState
|= STATE_SYSTEM_LINKED
;
557 m_dState
&= ~STATE_SYSTEM_LINKED
;
560 m_dState
&= ~STATE_SYSTEM_LINKED
;
564 VariantInit(pvarState
);
565 pvarState
->vt
= VT_I4
;
566 pvarState
->lVal
= m_dState
;
570 long lVal
= varChild
.lVal
;
571 varChild
.lVal
= CHILDID_SELF
;
572 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
575 return pChild
->get_accState(varChild
,pvarState
);
579 } catch(...) { return E_FAIL
; }
583 * Returns the accessible helpString of the current COM object self or its one child to AT.
584 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
585 * the child ID specify child index from 0 to children count, 0 stands for object self.
586 * @param pszHelp, [in,out] use to return the helpString of the proper object.
587 * @return S_OK if successful and E_FAIL if failure.
589 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accHelp(VARIANT
, BSTR
*)
595 * Returns the accessible HelpTopic of the current COM object self or its one child to AT.
596 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
597 * the child ID specify child index from 0 to children count, 0 stands for object self.
598 * @param pszHelpFile, [in,out] use to return the HelpTopic of the proper object.
599 * @param pidTopic, use to return the HelpTopic ID of the proper object.
600 * @return S_OK if successful and E_FAIL if failure.
601 * Not implemented yet
603 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accHelpTopic(BSTR
*, VARIANT
, long *)
608 static bool GetMnemonicChar( const OUString
& aStr
, sal_Unicode
* wStr
)
610 for (sal_Int32 i
= 0;; i
+= 2) {
611 i
= aStr
.indexOf('~', i
);
612 if (i
== -1 || i
== aStr
.getLength() - 1) {
615 auto c
= aStr
[i
+ 1];
624 * Returns the accessible keyboard shortcut of the current COM object self or its one child to AT.
625 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
626 * the child ID specify child index from 0 to children count, 0 stands for object self.
627 * @param pszKeyboardShortcut, [in,out] use to return the kbshortcut of the proper object.
628 * @return S_OK if successful and E_FAIL if failure.
630 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accKeyboardShortcut(VARIANT varChild
, BSTR
*pszKeyboardShortcut
)
636 if (m_isDestroy
) return S_FALSE
;
638 if(pszKeyboardShortcut
== nullptr)
643 if(varChild
.vt
==VT_I4
)
645 if(varChild
.lVal
== CHILDID_SELF
)
647 if (m_xAccessible
.is())
649 Reference
<XAccessibleContext
> const pRContext
=
650 m_xAccessible
->getAccessibleContext();
651 if( !pRContext
.is() )
654 Reference
<XAccessibleAction
> pRXI(pRContext
,UNO_QUERY
);
658 if( pRXI
.is() && pRXI
->getAccessibleActionCount() >= 1)
660 Reference
< XAccessibleKeyBinding
> binding
= pRXI
->getAccessibleActionKeyBinding(0);
663 long nCount
= binding
->getAccessibleKeyBindingCount();
666 wString
= comphelper::GetkeyBindingStrByXkeyBinding( binding
->getAccessibleKeyBinding(0) );
670 if(wString
.isEmpty())
672 Reference
<XAccessibleRelationSet
> pRrelationSet
= pRContext
->getAccessibleRelationSet();
673 if(!pRrelationSet
.is())
678 long nRelCount
= pRrelationSet
->getRelationCount();
680 // Modified by Steve Yin, for SODC_1552
681 if( /*nRelCount <= 0 &&*/ m_iRole
== ROLE_SYSTEM_TEXT
)
683 VARIANT varParentRole
;
684 VariantInit( &varParentRole
);
687 && SUCCEEDED(m_pIParent
->get_accRole(varChild
, &varParentRole
))
688 && varParentRole
.lVal
== ROLE_SYSTEM_COMBOBOX
) // edit in comboBox
690 m_pIParent
->get_accKeyboardShortcut(varChild
, pszKeyboardShortcut
);
695 AccessibleRelation
*paccRelation
= nullptr;
696 AccessibleRelation accRelation
;
697 for(int i
=0; i
<nRelCount
; i
++)
699 if( pRrelationSet
->getRelation(i
).RelationType
== 6 )
701 accRelation
= pRrelationSet
->getRelation(i
);
702 paccRelation
= &accRelation
;
706 if(paccRelation
== nullptr)
709 Sequence
< Reference
< XInterface
> > xTargets
= paccRelation
->TargetSet
;
710 Reference
<XInterface
> pRAcc
= xTargets
[0];
712 XAccessible
* pXAcc
= static_cast<XAccessible
*>(pRAcc
.get());
714 Reference
<XAccessibleContext
> pRLebelContext
= pXAcc
->getAccessibleContext();
715 if(!pRLebelContext
.is())
718 pRrelationSet
= pRLebelContext
->getAccessibleRelationSet();
719 nRelCount
= pRrelationSet
->getRelationCount();
721 paccRelation
= nullptr;
722 for(int j
=0; j
<nRelCount
; j
++)
724 if( pRrelationSet
->getRelation(j
).RelationType
== 5 )
726 accRelation
= pRrelationSet
->getRelation(j
);
727 paccRelation
= &accRelation
;
733 xTargets
= paccRelation
->TargetSet
;
735 if (m_xAccessible
.get() != static_cast<XAccessible
*>(pRAcc
.get()))
739 Reference
<XAccessibleExtendedComponent
> pRXIE(pRLebelContext
,UNO_QUERY
);
743 OUString ouStr
= pRXIE
->getTitledBorderText();
745 if(GetMnemonicChar(ouStr
, &key
))
747 wString
= "Alt+" + OUStringChar(key
);
753 SysFreeString(*pszKeyboardShortcut
);
754 *pszKeyboardShortcut
= SysAllocString(o3tl::toW(wString
.getStr()));
764 long lVal
= varChild
.lVal
;
765 varChild
.lVal
= CHILDID_SELF
;
766 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
770 return pChild
->get_accKeyboardShortcut(varChild
,pszKeyboardShortcut
);
774 } catch(...) { return E_FAIL
; }
778 * Returns the current focused child to AT.
779 * @param pvarChild, [in,out] vt member of pvarChild must be VT_I4,and lVal member stores the child ID,
780 * the child ID specify child index from 0 to children count, 0 stands for object self.
781 * @return S_OK if successful and E_FAIL if failure.
783 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accFocus(VARIANT
*pvarChild
)
788 if (m_isDestroy
) return S_FALSE
;
790 if(pvarChild
== nullptr)
794 if( m_dFocusChildID
==UACC_NO_FOCUS
)
796 pvarChild
->vt
= VT_EMPTY
;//no focus on the object and its children
799 //if the descendant of current object has focus indicated by m_dFocusChildID, return the IDispatch of this focused object
802 IMAccessible
* pIMAcc
= nullptr;
803 g_pAgent
->GetIAccessibleFromResID(m_dFocusChildID
,&pIMAcc
);
804 if (pIMAcc
== nullptr)
809 pvarChild
->vt
= VT_DISPATCH
;
810 pvarChild
->pdispVal
= pIMAcc
;
815 } catch(...) { return E_FAIL
; }
819 * Returns the selection of the current COM object to AT.
820 * @param pvarChildren,[in,out]
821 * if selection num is 0,return VT_EMPTY for vt,
822 * if selection num is 1,return VT_I4 for vt,and child index for lVal
823 * if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
824 * @return S_OK if successful and S_FALSE if failure.
826 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accSelection(VARIANT
*pvarChildren
)
831 if (m_isDestroy
) return S_FALSE
;
833 if(pvarChildren
== nullptr)
837 switch(m_pEnumVar
->GetCountOfElements())
840 pvarChildren
->vt
= VT_EMPTY
;
845 VariantInit(&varTmp
[0]);
846 m_pEnumVar
->Next(1,varTmp
,&count
);
849 pvarChildren
->vt
= VT_DISPATCH
;
850 pvarChildren
->pdispVal
= varTmp
[0].pdispVal
;
851 pvarChildren
->pdispVal
->AddRef();
852 VariantClear(&varTmp
[0]);
856 pvarChildren
->vt
= VT_UNKNOWN
;
857 IEnumVARIANT
* pClone
;
858 m_pEnumVar
->Clone(&pClone
);
860 pvarChildren
->punkVal
= pClone
;
865 } catch(...) { return E_FAIL
; }
869 * Returns the location of the current COM object self or its one child to AT.
870 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
871 * the child ID specify child index from 0 to children count, 0 stands for object self.
872 * @param pxLeft, [in,out] use to return the x-coordination of the proper object.
873 * @param pyTop, [in,out] use to return the y-coordination of the proper object.
874 * @param pcxWidth, [in,out] use to return the x-coordination width of the proper object.
875 * @param pcyHeight, [in,out] use to return the y-coordination height of the proper object.
876 * @return S_OK if successful and S_FALSE if failure.
878 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accLocation(long *pxLeft
, long *pyTop
, long *pcxWidth
, long *pcyHeight
, VARIANT varChild
)
883 if (m_isDestroy
) return S_FALSE
;
885 if(pxLeft
== nullptr || pyTop
== nullptr || pcxWidth
== nullptr || pcyHeight
== nullptr)
890 if(varChild
.vt
==VT_I4
)
892 if(varChild
.lVal
==CHILDID_SELF
)
894 if (!m_xAccessible
.is())
897 Reference
<XAccessibleContext
> const pRContext
=
898 m_xAccessible
->getAccessibleContext();
899 if( !pRContext
.is() )
901 Reference
< XAccessibleComponent
> pRComponent(pRContext
,UNO_QUERY
);
902 if( !pRComponent
.is() )
905 css::awt::Point pCPoint
= pRComponent
->getLocationOnScreen();
906 css::awt::Size pCSize
= pRComponent
->getSize();
909 *pcxWidth
= pCSize
.Width
;
910 *pcyHeight
= pCSize
.Height
;
916 } catch(...) { return E_FAIL
; }
920 * Returns the current focused child to AT.
921 * @param navDir, the direction flag of the navigation.
922 * @param varStart, the start child id of this navigation action.
923 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
924 * @return S_OK if successful and E_FAIL if failure.
926 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accNavigate(long navDir
, VARIANT varStart
, VARIANT
*pvarEndUpAt
)
931 if (m_isDestroy
) return S_FALSE
;
933 if(pvarEndUpAt
== nullptr)
937 HRESULT ret
= E_FAIL
;
940 case NAVDIR_FIRSTCHILD
:
941 ret
= GetFirstChild(varStart
,pvarEndUpAt
);
943 case NAVDIR_LASTCHILD
:
944 ret
= GetLastChild(varStart
,pvarEndUpAt
);
947 ret
= GetNextSibling(varStart
,pvarEndUpAt
);
949 case NAVDIR_PREVIOUS
:
950 ret
= GetPreSibling(varStart
,pvarEndUpAt
);
952 case NAVDIR_DOWN
://do not implement temporarily
954 case NAVDIR_UP
://do not implement temporarily
956 case NAVDIR_LEFT
://do not implement temporarily
958 case NAVDIR_RIGHT
://do not implement temporarily
965 } catch(...) { return E_FAIL
; }
968 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accHitTest(long xLeft
, long yTop
, VARIANT
*pvarChild
)
973 if (m_isDestroy
) return S_FALSE
;
975 if(pvarChild
== nullptr)
981 VariantInit(&varSelf
);
983 varSelf
.lVal
= CHILDID_SELF
;
984 accLocation(&x
,&y
,&w
,&h
,varSelf
);
985 if( (x
< xLeft
&& (x
+ w
) >xLeft
) && (y
< yTop
&& (y
+ h
) >yTop
) )
988 pvarChild
->vt
= VT_EMPTY
;
989 Reference
< XAccessibleContext
> pRContext
= GetContextByXAcc(m_xAccessible
.get());
990 nCount
= pRContext
->getAccessibleChildCount();
993 IMAccessible
* child
= nullptr;
994 for( i
= 0; i
<nCount
; i
++)
997 child
= GetChildInterface(i
+ 1);
998 if(child
&& child
->accHitTest(xLeft
,yTop
,pvarChild
) == S_OK
)
1002 if(pvarChild
->vt
== VT_DISPATCH
)
1007 pvarChild
->vt
= VT_DISPATCH
;
1008 pvarChild
->pdispVal
= child
;
1013 pvarChild
->vt
= VT_I4
;
1014 pvarChild
->lVal
= CHILDID_SELF
;
1020 } catch(...) { return E_FAIL
; }
1024 * Get The other Interface from CMAccessible.
1025 * @param guidService, must be IID_IAccessible here.
1026 * @param riid, the IID interface .
1027 * @return S_OK if successful and S_FALSE if failure.
1029 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::QueryService(REFGUID guidService
, REFIID riid
, void** ppvObject
)
1031 if( InlineIsEqualGUID(guidService
, IID_IAccessible
) )
1032 return QueryInterface(riid
, ppvObject
);
1037 * No longer supported according to IAccessible doc.
1038 * Servers should return E_NOTIMPL
1040 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::put_accName(VARIANT
, BSTR
)
1046 * Set the accessible value of the current COM object self or its one child from UNO.
1047 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1048 * the child ID specify child index from 0 to children count, 0 stands for object self.
1049 * @param szValue, the value used to set the value of the proper object.
1050 * @return S_OK if successful and E_FAIL if failure.
1052 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::put_accValue(VARIANT varChild
, BSTR szValue
)
1057 if (m_isDestroy
) return S_FALSE
;
1058 if(varChild
.vt
==VT_I4
)
1060 if(varChild
.lVal
==CHILDID_SELF
)
1062 SysFreeString(m_pszValue
);
1063 m_pszValue
=SysAllocString(szValue
);
1067 long lVal
= varChild
.lVal
;
1068 varChild
.lVal
= CHILDID_SELF
;
1069 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
1072 return pChild
->put_accValue(varChild
,szValue
);
1076 } catch(...) { return E_FAIL
; }
1080 * Set the accessible name of the current COM object self from UNO.
1081 * @param pszName, the name value used to set the name of the current object.
1082 * @return S_OK if successful and E_FAIL if failure.
1084 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR
*pszName
)
1086 // internal IMAccessible - no mutex meeded
1089 if (m_isDestroy
) return S_FALSE
;
1091 if(pszName
== nullptr)
1093 return E_INVALIDARG
;
1096 SysFreeString(m_pszName
);
1097 m_pszName
= SysAllocString(pszName
);
1098 if(m_pszName
==nullptr)
1102 } catch(...) { return E_FAIL
; }
1106 * Set the accessible role of the current COM object self from UNO.
1107 * @param pRole, the role value used to set the role of the current object.
1108 * @return S_OK if successful and E_FAIL if failure.
1110 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccRole(unsigned short pRole
)
1112 // internal IMAccessible - no mutex meeded
1119 * Add one state into the current state set for the current COM object from UNO.
1120 * @param pXSate, the state used to set the name of the current object.
1121 * @return S_OK if successful and E_FAIL if failure.
1123 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::DecreaseState(DWORD pXSate
)
1125 // internal IMAccessible - no mutex meeded
1127 m_dState
&= (~pXSate
);
1132 * Delete 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::IncreaseState(DWORD pXSate
)
1138 // internal IMAccessible - no mutex meeded
1145 * Set 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::SetState(DWORD pXSate
)
1151 // internal IMAccessible - no mutex meeded
1158 * Set the accessible value of the current COM object self from UNO.
1159 * @param pszAccValue, the name used to set the value of the current object.
1160 * @return S_OK if successful and E_FAIL if failure.
1162 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR
*pszAccValue
)
1164 // internal IMAccessible - no mutex meeded
1167 if (m_isDestroy
) return S_FALSE
;
1169 if(pszAccValue
== nullptr)
1171 return E_INVALIDARG
;
1173 SysFreeString(m_pszValue
);
1174 m_pszValue
= SysAllocString(pszAccValue
);
1175 if(m_pszValue
==nullptr)
1179 } catch(...) { return E_FAIL
; }
1183 * Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
1184 * Object through the method AccessibleObjectFromWindow(...).
1185 * @param hwnd, the HWND used to set the value of the current object.
1186 * @return S_OK if successful and E_FAIL if failure.
1188 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccWindowHandle(HWND hwnd
)
1190 // internal IMAccessible - no mutex meeded
1193 if (m_isDestroy
) return S_FALSE
;
1197 } catch(...) { return E_FAIL
; }
1201 * Set accessible focus by specifying child ID
1202 * @param dChildID, the child id identifies the focus child.
1203 * @return S_OK if successful and E_FAIL if failure.
1205 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccFocus(long dChildID
)
1207 // internal IMAccessible - no mutex meeded
1210 if (m_isDestroy
) return S_FALSE
;
1212 if(dChildID
==CHILDID_SELF
)
1216 m_pIParent
->Put_XAccFocus(m_dChildID
);
1221 m_dFocusChildID
= dChildID
;
1222 //traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
1223 //any of the ancestors, this id can be used to get the IAccessible of focused object.
1226 m_pIParent
->Put_XAccFocus(dChildID
);
1231 } catch(...) { return E_FAIL
; }
1235 * Set accessible parent object for the current COM object if
1236 * the current object is a child of some COM object
1237 * @param pIParent, the parent of the current object.
1238 * @return S_OK if successful and E_FAIL if failure.
1240 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR
*pIParent
)
1242 // internal IMAccessible - no mutex meeded
1244 this->m_pIParent
= pIParent
;
1247 m_pIParent
->AddRef();
1253 * Set unique child id to COM
1254 * @param dChildID, the id of the current object.
1255 * @return S_OK if successful and E_FAIL if failure.
1257 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccChildID(long dChildID
)
1259 // internal IMAccessible - no mutex meeded
1261 this->m_dChildID
= dChildID
;
1266 * Set AccObjectManagerAgent object pointer to COM
1267 * @param pAgent, the AccObjectManagerAgent point.
1268 * @return S_OK if successful and E_FAIL if failure.
1270 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccAgent(hyper pAgent
)
1272 // internal IMAccessible - no mutex meeded
1274 g_pAgent
= reinterpret_cast<AccObjectManagerAgent
*>(pAgent
);
1279 * When a UNO control disposing, it disposes its listeners,
1280 * then notify AccObject in bridge management, then notify
1281 * COM that the XAccessible is invalid, so set m_xAccessible as NULL
1282 * @return S_OK if successful and E_FAIL if failure.
1284 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::NotifyDestroy()
1286 // internal IMAccessible - no mutex meeded
1289 m_xAccessible
.clear();
1294 *private methods that help implement public functions
1298 * Return child interface pointer by child ID,note: need to call AddRef()
1299 * @param lChildID, specify child index,which AT(such as Inspect32) gives.
1300 * @return IMAccessible*, pointer to the corresponding child object.
1302 IMAccessible
* CMAccessible::GetChildInterface(long dChildID
)//for test
1308 IMAccessible
* pIMAcc
= nullptr;
1309 g_pAgent
->GetIAccessibleFromResID(dChildID
,&pIMAcc
);
1316 if (!m_xAccessible
.is())
1319 Reference
<XAccessibleContext
> const pRContext
=
1320 m_xAccessible
->getAccessibleContext();
1321 if( !pRContext
.is() )
1324 if(dChildID
<1 || dChildID
>pRContext
->getAccessibleChildCount())
1327 IAccessible
* pChild
= nullptr;
1328 Reference
< XAccessible
> pXChild
= pRContext
->getAccessibleChild(dChildID
-1);
1329 bool isGet
= get_IAccessibleFromXAccessible(pXChild
.get(), &pChild
);
1333 g_pAgent
->InsertAccObj(pXChild
.get(), m_xAccessible
.get(), m_hwnd
);
1334 isGet
= get_IAccessibleFromXAccessible(pXChild
.get(), &pChild
);
1339 IMAccessible
* pIMAcc
= static_cast<IMAccessible
*>(pChild
);
1348 * for descendantmanager circumstance,provide child interface when navigate
1349 * @param varCur, the current child.
1350 * @param flags, the navigation direction.
1351 * @return IMAccessible*, the child of the end up node.
1353 IMAccessible
* CMAccessible::GetNavigateChildForDM(VARIANT varCur
, short flags
)
1356 XAccessibleContext
* pXContext
= GetContextByXAcc(m_xAccessible
.get());
1357 if(pXContext
==nullptr)
1362 sal_Int64 count
= pXContext
->getAccessibleChildCount();
1368 IMAccessible
* pCurChild
= nullptr;
1370 XAccessible
* pChildXAcc
;
1373 Reference
<XAccessible
> pRChildXAcc
;
1374 XAccessibleContext
* pChildContext
= nullptr;
1375 sal_Int64 index
= 0, delta
= 0;
1379 pRChildXAcc
= pXContext
->getAccessibleChild(0);
1382 pRChildXAcc
= pXContext
->getAccessibleChild(count
-1);
1386 pCurChild
= GetChildInterface(varCur
.lVal
);
1387 if(pCurChild
==nullptr)
1391 pCurChild
->GetUNOInterface(&nHyper
);
1392 if(pChildXAcc
==nullptr)
1396 pChildContext
= GetContextByXAcc(pChildXAcc
);
1397 if(pChildContext
== nullptr)
1401 delta
= (flags
==DM_NEXTCHILD
)?1:-1;
1402 //currently, getAccessibleIndexInParent is error in UNO for
1403 //some kind of List,such as ValueSet, the index will be less 1 than
1404 //what should be, need to fix UNO code
1405 index
= pChildContext
->getAccessibleIndexInParent()+delta
;
1406 if((index
>=0)&&(index
<=count
-1))
1408 pRChildXAcc
= pXContext
->getAccessibleChild(index
);
1415 if(!pRChildXAcc
.is())
1419 pChildXAcc
= pRChildXAcc
.get();
1420 g_pAgent
->InsertAccObj(pChildXAcc
, m_xAccessible
.get());
1421 return g_pAgent
->GetIMAccByXAcc(pChildXAcc
);
1425 *the following 4 private methods are for accNavigate implementation
1429 * Return first child for parent container, process differently according
1430 * to whether it is descendant manage
1431 * @param varStart, the start child id of this navigation action.
1432 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1433 * @return S_OK if successful and E_FAIL if failure.
1435 HRESULT
CMAccessible::GetFirstChild(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1439 if (m_isDestroy
) return S_FALSE
;
1441 if(pvarEndUpAt
== nullptr)
1443 return E_INVALIDARG
;
1445 if(varStart
.vt
!= VT_I4
)
1447 pvarEndUpAt
->vt
= VT_EMPTY
;
1448 return E_INVALIDARG
;
1451 pvarEndUpAt
->pdispVal
= GetNavigateChildForDM(varStart
, DM_FIRSTCHILD
);
1452 if(pvarEndUpAt
->pdispVal
)
1454 pvarEndUpAt
->pdispVal
->AddRef();
1455 pvarEndUpAt
->vt
= VT_DISPATCH
;
1459 pvarEndUpAt
->vt
= VT_EMPTY
;
1462 } catch(...) { return E_FAIL
; }
1466 * Return last child for parent container, process differently according
1467 * to whether it is descendant manage
1468 * @param varStart, the start child id of this navigation action.
1469 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1470 * @return S_OK if successful and E_FAIL if failure.
1472 HRESULT
CMAccessible::GetLastChild(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1476 if (m_isDestroy
) return S_FALSE
;
1478 if(pvarEndUpAt
== nullptr)
1480 return E_INVALIDARG
;
1482 if(varStart
.vt
!= VT_I4
)
1484 pvarEndUpAt
->vt
= VT_EMPTY
;
1485 return E_INVALIDARG
;
1488 pvarEndUpAt
->pdispVal
= GetNavigateChildForDM(varStart
, DM_LASTCHILD
);
1489 if(pvarEndUpAt
->pdispVal
)
1491 pvarEndUpAt
->pdispVal
->AddRef();
1492 pvarEndUpAt
->vt
= VT_DISPATCH
;
1495 pvarEndUpAt
->vt
= VT_EMPTY
;
1498 } catch(...) { return E_FAIL
; }
1502 * The method GetNextSibling is general, whatever it is descendant manage or not
1503 * Get the next sibling object.
1504 * @param varStart, the start child id of this navigation action.
1505 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1506 * @return S_OK if successful and E_FAIL if failure.
1508 HRESULT
CMAccessible::GetNextSibling(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1512 if (m_isDestroy
) return S_FALSE
;
1513 if(varStart
.vt
!= VT_I4
)
1515 pvarEndUpAt
->vt
= VT_EMPTY
;
1516 return E_INVALIDARG
;
1519 Reference
<XAccessibleContext
> const pRContext
=
1520 GetContextByXAcc(m_xAccessible
.get());
1523 varStart
.iVal
= sal_Int16(pRContext
->getAccessibleIndexInParent() + 2);
1525 if( m_pIParent
->get_accChild(varStart
,&pvarEndUpAt
->pdispVal
) == S_OK
)
1527 pvarEndUpAt
->vt
= VT_DISPATCH
;
1531 pvarEndUpAt
->vt
= VT_EMPTY
;
1534 } catch(...) { return E_FAIL
; }
1538 *the method GetPreSibling is general, whatever it is descendant manage or not
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::GetPreSibling(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1547 if (m_isDestroy
) return S_FALSE
;
1549 if(pvarEndUpAt
== nullptr)
1551 return E_INVALIDARG
;
1553 if(varStart
.vt
!= VT_I4
)
1555 pvarEndUpAt
->vt
= VT_EMPTY
;
1556 return E_INVALIDARG
;
1559 Reference
<XAccessibleContext
> const pRContext
=
1560 GetContextByXAcc(m_xAccessible
.get());
1563 varStart
.iVal
= sal_Int16(pRContext
->getAccessibleIndexInParent());
1564 if(m_pIParent
&& varStart
.iVal
> 0)
1565 if( m_pIParent
->get_accChild(varStart
,&pvarEndUpAt
->pdispVal
) == S_OK
)
1567 pvarEndUpAt
->vt
= VT_DISPATCH
;
1571 pvarEndUpAt
->vt
= VT_EMPTY
;
1574 } catch(...) { return E_FAIL
; }
1578 * For IAccessible2 implementation methods
1580 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_nRelations( long __RPC_FAR
*nRelations
)
1585 if (m_isDestroy
) return S_FALSE
;
1588 if(nRelations
== nullptr)
1590 return E_INVALIDARG
;
1595 if (!m_xContext
.is())
1597 Reference
<XAccessibleRelationSet
> pRrelationSet
=
1598 m_xContext
->getAccessibleRelationSet();
1599 if(!pRrelationSet
.is())
1605 *nRelations
= pRrelationSet
->getRelationCount();
1608 } catch(...) { return E_FAIL
; }
1611 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_relation( long relationIndex
, IAccessibleRelation __RPC_FAR
*__RPC_FAR
*relation
)
1616 if (m_isDestroy
) return S_FALSE
;
1618 if(relation
== nullptr)
1620 return E_INVALIDARG
;
1623 if (!m_xContext
.is())
1628 get_nRelations(&nMax
);
1630 *relation
= static_cast<IAccessibleRelation
*>(::CoTaskMemAlloc(sizeof(IAccessibleRelation
)));
1632 // #CHECK Memory Allocation#
1633 if(*relation
== nullptr)
1638 if( relationIndex
< nMax
)
1640 Reference
<XAccessibleRelationSet
> const pRrelationSet
=
1641 m_xContext
->getAccessibleRelationSet();
1642 if(!pRrelationSet
.is())
1648 IAccessibleRelation
* pRelation
= nullptr;
1649 HRESULT hr
= createInstance
<CAccRelation
>(IID_IAccessibleRelation
,
1653 IUNOXWrapper
* wrapper
= nullptr;
1654 hr
= pRelation
->QueryInterface(IID_IUNOXWrapper
, reinterpret_cast<void**>(&wrapper
));
1657 AccessibleRelation accRelation
= pRrelationSet
->getRelation(relationIndex
);
1658 wrapper
->put_XSubInterface(
1659 reinterpret_cast<hyper
>(&accRelation
));
1661 *relation
= pRelation
;
1670 } catch(...) { return E_FAIL
; }
1673 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR
*__RPC_FAR
*relation
, long __RPC_FAR
*nRelations
)
1678 if (m_isDestroy
) return S_FALSE
;
1681 if(relation
== nullptr || nRelations
== nullptr)
1683 return E_INVALIDARG
;
1685 // #CHECK XInterface#
1687 if (!m_xContext
.is())
1690 Reference
<XAccessibleRelationSet
> const pRrelationSet
=
1691 m_xContext
->getAccessibleRelationSet();
1692 if(!pRrelationSet
.is())
1698 long nCount
= pRrelationSet
->getRelationCount();
1700 *relation
= static_cast<IAccessibleRelation
*>(::CoTaskMemAlloc(nCount
*sizeof(IAccessibleRelation
)));
1702 // #CHECK Memory Allocation#
1703 if(*relation
== nullptr)
1708 for(int i
=0; i
<nCount
; i
++)
1710 IAccessibleRelation
* pRelation
= nullptr;
1711 HRESULT hr
= createInstance
<CAccRelation
>(IID_IAccessibleRelation
,
1715 IUNOXWrapper
* wrapper
= nullptr;
1716 hr
= pRelation
->QueryInterface(IID_IUNOXWrapper
, reinterpret_cast<void**>(&wrapper
));
1719 AccessibleRelation accRelation
= pRrelationSet
->getRelation(i
);
1720 wrapper
->put_XSubInterface(
1721 reinterpret_cast<hyper
>(&accRelation
));
1724 relation
[i
] = pRelation
;
1728 *nRelations
= nCount
;
1731 } catch(...) { return E_FAIL
; }
1734 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::role(long __RPC_FAR
*role
)
1744 } catch(...) { return E_FAIL
; }
1748 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_nActions(long __RPC_FAR
*nActions
)
1754 if (m_isDestroy
) return S_FALSE
;
1756 if(nActions
== nullptr)
1758 return E_INVALIDARG
;
1761 IAccessibleAction
* pAcc
= nullptr;
1762 HRESULT hr
= QueryInterface(IID_IAccessibleAction
, reinterpret_cast<void**>(&pAcc
));
1765 pAcc
->nActions(nActions
);
1779 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::scrollToPoint(enum IA2CoordinateType
, long, long)
1784 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::scrollTo(enum IA2ScrollType
)
1789 static XAccessible
* getTheParentOfMember(XAccessible
* pXAcc
)
1792 if(pXAcc
== nullptr)
1796 Reference
<XAccessibleContext
> pRContext
= pXAcc
->getAccessibleContext();
1797 Reference
<XAccessibleRelationSet
> pRrelationSet
= pRContext
->getAccessibleRelationSet();
1798 sal_Int32 nRelations
= pRrelationSet
->getRelationCount();
1799 for(sal_Int32 i
=0 ; i
<nRelations
; i
++)
1801 AccessibleRelation accRelation
= pRrelationSet
->getRelation(i
);
1802 if(accRelation
.RelationType
== 7)
1804 Sequence
< Reference
< XInterface
> > xTargets
= accRelation
.TargetSet
;
1805 return static_cast<XAccessible
*>(xTargets
[0].get());
1811 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_groupPosition(long __RPC_FAR
*groupLevel
,long __RPC_FAR
*similarItemsInGroup
,long __RPC_FAR
*positionInGroup
)
1816 if (m_isDestroy
) return S_FALSE
;
1818 if(groupLevel
== nullptr || similarItemsInGroup
== nullptr || positionInGroup
== nullptr)
1820 return E_INVALIDARG
;
1823 if (!m_xAccessible
.is())
1826 Reference
<XAccessibleContext
> const pRContext
=
1827 m_xAccessible
->getAccessibleContext();
1830 long Role
= pRContext
->getAccessibleRole();
1833 *similarItemsInGroup
= 0;
1834 *positionInGroup
= 0;
1836 if (Role
!= AccessibleRole::DOCUMENT
&& Role
!= AccessibleRole::DOCUMENT_PRESENTATION
&&
1837 Role
!= AccessibleRole::DOCUMENT_SPREADSHEET
&& Role
!= AccessibleRole::DOCUMENT_TEXT
)
1839 Reference
< XAccessibleGroupPosition
> xGroupPosition( pRContext
, UNO_QUERY
);
1840 if ( xGroupPosition
.is() )
1842 Sequence
< sal_Int32
> rSeq
= xGroupPosition
->getGroupPosition( Any( pRContext
) );
1843 if (rSeq
.getLength() >= 3)
1845 *groupLevel
= rSeq
[0];
1846 *similarItemsInGroup
= rSeq
[1];
1847 *positionInGroup
= rSeq
[2];
1854 Reference
< XAccessible
> pParentAcc
= pRContext
->getAccessibleParent();
1855 if( !pParentAcc
.is() )
1860 Reference
<XAccessibleContext
> pRParentContext
= pParentAcc
->getAccessibleContext();
1862 if( Role
== RADIO_BUTTON
)
1866 Reference
<XAccessibleRelationSet
> pRrelationSet
= pRContext
->getAccessibleRelationSet();
1867 long nRel
= pRrelationSet
->getRelationCount();
1868 for(int i
=0 ; i
<nRel
; i
++)
1870 AccessibleRelation accRelation
= pRrelationSet
->getRelation(i
);
1871 if(accRelation
.RelationType
== 7)
1873 Sequence
< Reference
< XInterface
> > xTargets
= accRelation
.TargetSet
;
1875 Reference
<XInterface
> pRAcc
= xTargets
[0];
1876 sal_Int64 nChildCount
= pRParentContext
->getAccessibleChildCount();
1877 assert(nChildCount
< std::numeric_limits
<long>::max());
1878 for (sal_Int64 j
= 0; j
< nChildCount
; j
++)
1880 if( getTheParentOfMember(pRParentContext
->getAccessibleChild(j
).get())
1881 == static_cast<XAccessible
*>(pRAcc
.get()) &&
1882 pRParentContext
->getAccessibleChild(j
)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON
)
1884 if (pRParentContext
->getAccessibleChild(j
).get() == m_xAccessible
.get())
1890 *similarItemsInGroup
= number
;
1891 *positionInGroup
= index
;
1895 else if ( COMBO_BOX
== Role
)
1898 *similarItemsInGroup
= 0;
1899 *positionInGroup
= -1;
1901 if (pRContext
->getAccessibleChildCount() != 2)
1905 Reference
<XAccessible
> xList
=pRContext
->getAccessibleChild(1);
1910 Reference
<XAccessibleContext
> xListContext(xList
,UNO_QUERY
);
1911 if (!xListContext
.is())
1915 Reference
<XAccessibleSelection
> xListSel(xList
,UNO_QUERY
);
1920 sal_Int64 nChildCount
= xListContext
->getAccessibleChildCount();
1921 assert(nChildCount
< std::numeric_limits
<long>::max());
1922 *similarItemsInGroup
= nChildCount
;
1923 if (*similarItemsInGroup
> 0 )
1927 Reference
<XAccessible
> xChild
= xListSel
->getSelectedAccessibleChild(0);
1930 Reference
<XAccessibleContext
> xChildContext(xChild
,UNO_QUERY
);
1931 if (xChildContext
.is())
1933 *positionInGroup
=xChildContext
->getAccessibleIndexInParent() + 1 ;
1943 else if ( PAGE_TAB
== Role
)
1946 sal_Int64 nChildCount
= pRParentContext
->getAccessibleChildCount();
1947 assert(nChildCount
< std::numeric_limits
<long>::max());
1948 *similarItemsInGroup
= nChildCount
;
1949 if (*similarItemsInGroup
> 0 )
1951 *positionInGroup
=pRContext
->getAccessibleIndexInParent() + 1 ;
1955 *positionInGroup
= -1;
1961 bool isFound
= false;
1962 while( pParentAcc
.is() && !isFound
)
1965 pRParentContext
= pParentAcc
->getAccessibleContext();
1966 Role
= pRParentContext
->getAccessibleRole();
1967 if( (Role
== TREE
) || (Role
== LIST
) )
1969 pParentAcc
= pRParentContext
->getAccessibleParent();
1974 Reference
< XAccessible
> pTempAcc
= pRContext
->getAccessibleParent();
1975 pRParentContext
= pTempAcc
->getAccessibleContext();
1976 *groupLevel
= level
;
1977 sal_Int64 nChildCount
= pRParentContext
->getAccessibleChildCount();
1978 assert(nChildCount
< std::numeric_limits
<long>::max());
1979 *similarItemsInGroup
= nChildCount
;
1980 *positionInGroup
= pRContext
->getAccessibleIndexInParent() + 1;
1985 *similarItemsInGroup
= 0;
1986 *positionInGroup
= 0;
1990 } catch(...) { return E_FAIL
; }
1993 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_extendedStates(long, BSTR __RPC_FAR
*__RPC_FAR
*, long __RPC_FAR
*)
1999 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_uniqueID(long __RPC_FAR
*uniqueID
)
2004 if (m_isDestroy
) return S_FALSE
;
2006 if(uniqueID
== nullptr)
2008 return E_INVALIDARG
;
2010 *uniqueID
= m_dChildID
;
2013 } catch(...) { return E_FAIL
; }
2016 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_windowHandle(HWND __RPC_FAR
*windowHandle
)
2021 if (m_isDestroy
) return S_FALSE
;
2023 if(windowHandle
== nullptr)
2025 return E_INVALIDARG
;
2028 HWND nHwnd
= m_hwnd
;
2029 IAccessible
* pParent
= m_pIParent
;
2030 while((nHwnd
==nullptr) && pParent
)
2032 if (CMAccessible
* pChild
= dynamic_cast<CMAccessible
*>(pParent
))
2034 pParent
= pChild
->m_pIParent
;
2035 nHwnd
= pChild
->m_hwnd
;
2041 *windowHandle
= nHwnd
;
2044 } catch(...) { return E_FAIL
; }
2048 * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
2049 * @param pXAcc, UNO XAccessible object point.
2050 * @return XAccessibleContext*, the context of the pXAcc.
2052 XAccessibleContext
* CMAccessible::GetContextByXAcc( XAccessible
* pXAcc
)
2054 Reference
< XAccessibleContext
> pRContext
;
2055 if( pXAcc
== nullptr)
2058 pRContext
= pXAcc
->getAccessibleContext();
2059 if( !pRContext
.is() )
2061 return pRContext
.get();
2065 * When COM is created, UNO set XAccessible pointer to it
2066 * in order to COM can operate UNO information
2067 * @param pXAcc, the XAccessible object of current object.
2068 * @return S_OK if successful.
2070 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::SetXAccessible(hyper pXAcc
)
2072 // internal IMAccessible - no mutex meeded
2074 m_xAccessible
= reinterpret_cast<XAccessible
*>(pXAcc
);
2075 m_pEnumVar
->PutSelection(/*XAccessibleSelection*/
2076 reinterpret_cast<hyper
>(m_xAccessible
.get()));
2078 m_xContext
= m_xAccessible
->getAccessibleContext();
2084 * accSelect method has many optional flags, needs to process comprehensively
2085 * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
2086 * The implementation of this flag is a little trouble-shooting,so we also
2087 * do not implement it now
2088 * @param flagsSelect, the selection flag of the select action.
2089 * @param varChild, the child object pointer of current action.
2090 * @return S_OK if successful.
2092 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accSelect(long flagsSelect
, VARIANT varChild
)
2097 if (m_isDestroy
) return S_FALSE
;
2098 if( (flagsSelect
&SELFLAG_ADDSELECTION
) &&
2099 (SELFLAG_REMOVESELECTION
&flagsSelect
) )
2100 return E_INVALIDARG
;
2102 if ( (flagsSelect
&SELFLAG_TAKESELECTION
) &&
2104 (flagsSelect
&SELFLAG_ADDSELECTION
) ||
2105 (flagsSelect
&SELFLAG_REMOVESELECTION
) ||
2106 (flagsSelect
&SELFLAG_EXTENDSELECTION
)
2109 return E_INVALIDARG
;
2111 if ( varChild
.vt
!= VT_I4
)
2112 return E_INVALIDARG
;
2114 IMAccessible
* pSelectAcc
;
2115 if( varChild
.lVal
== CHILDID_SELF
)
2118 pSelectAcc
->AddRef();
2122 pSelectAcc
= GetChildInterface(varChild
.lVal
);
2125 if( pSelectAcc
== nullptr )
2126 return E_INVALIDARG
;
2128 if( flagsSelect
&SELFLAG_TAKEFOCUS
)
2131 XAccessible
* pTempUNO
;
2134 pSelectAcc
->GetUNOInterface(&nHyper
);
2136 if( pTempUNO
== nullptr )
2139 Reference
<XAccessibleContext
> pRContext
= pTempUNO
->getAccessibleContext();
2140 Reference
< XAccessibleComponent
> pRComponent(pRContext
,UNO_QUERY
);
2141 Reference
< XAccessible
> pRParentXAcc
= pRContext
->getAccessibleParent();
2142 Reference
< XAccessibleContext
> pRParentContext
= pRParentXAcc
->getAccessibleContext();
2143 Reference
< XAccessibleComponent
> pRParentComponent(pRParentContext
,UNO_QUERY
);
2144 Reference
< XAccessibleSelection
> pRParentSelection(pRParentContext
,UNO_QUERY
);
2147 pRComponent
->grabFocus();
2149 if( flagsSelect
& SELFLAG_TAKESELECTION
)
2151 pRParentSelection
->clearAccessibleSelection();
2152 pRParentSelection
->selectAccessibleChild( pRContext
->getAccessibleIndexInParent() );
2155 if( flagsSelect
& SELFLAG_ADDSELECTION
)
2157 pRParentSelection
->selectAccessibleChild( pRContext
->getAccessibleIndexInParent() );
2160 if( flagsSelect
& SELFLAG_REMOVESELECTION
)
2162 pRParentSelection
->deselectAccessibleChild( pRContext
->getAccessibleIndexInParent() );
2165 if( flagsSelect
& SELFLAG_EXTENDSELECTION
)
2167 sal_Int64 indexInParrent
= pRContext
->getAccessibleIndexInParent();
2169 if( pRParentSelection
->isAccessibleChildSelected( indexInParrent
+ 1 ) ||
2170 pRParentSelection
->isAccessibleChildSelected( indexInParrent
- 1 ) )
2172 pRParentSelection
->selectAccessibleChild( indexInParrent
);
2178 pSelectAcc
->Release();
2181 } catch(...) { return E_FAIL
; }
2185 * Return XAccessible interface pointer when needed
2186 * @param pXAcc, [in, out] the Uno interface of the current object.
2187 * @return S_OK if successful.
2189 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::GetUNOInterface(hyper
* pXAcc
)
2191 // internal IMAccessible - no mutex meeded
2193 if(pXAcc
== nullptr)
2194 return E_INVALIDARG
;
2196 *pXAcc
= reinterpret_cast<hyper
>(m_xAccessible
.get());
2201 * Helper method for Implementation of get_accDefaultAction
2202 * @param pAction, the default action point of the current object.
2203 * @return S_OK if successful.
2205 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::SetDefaultAction(hyper pAction
)
2207 // internal IMAccessible - no mutex meeded
2209 m_xAction
= reinterpret_cast<XAccessibleAction
*>(pAction
);
2214 * This method is called when AT open some UI elements initially
2215 * the UI element takes the default action defined here
2216 * @param varChild, the child id of the defaultaction.
2217 * @param pszDefaultAction,[in/out] the description of the current action.
2218 * @return S_OK if successful.
2220 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CMAccessible::get_accDefaultAction(VARIANT varChild
, BSTR
*pszDefaultAction
)
2225 if (m_isDestroy
) return S_FALSE
;
2227 if(pszDefaultAction
== nullptr)
2229 return E_INVALIDARG
;
2231 if(varChild
.vt
==VT_I4
)
2233 if(varChild
.lVal
==CHILDID_SELF
)
2235 if (!m_xAction
.is())
2236 return DISP_E_MEMBERNOTFOUND
;
2237 SysFreeString(*pszDefaultAction
);
2238 *pszDefaultAction
= SysAllocString(m_pszActionDescription
);
2242 long lVal
= varChild
.lVal
;
2243 varChild
.lVal
= CHILDID_SELF
;
2244 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
2247 return pChild
->get_accDefaultAction(varChild
,pszDefaultAction
);
2251 } catch(...) { return E_FAIL
; }
2255 * AT call this method to operate application
2256 * @param varChild, the child id of the action object.
2257 * @return S_OK if successful.
2259 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CMAccessible::accDoDefaultAction(VARIANT varChild
)
2264 if (m_isDestroy
) return S_FALSE
;
2265 if( varChild
.vt
!= VT_I4
)
2266 return E_INVALIDARG
;
2267 if (!m_xAction
.is())
2269 if (m_xAction
->getAccessibleActionCount() == 0)
2272 if(varChild
.lVal
==CHILDID_SELF
)
2274 if (m_xAction
->getAccessibleActionCount() > 0)
2275 m_xAction
->doAccessibleAction(0);
2279 long lVal
= varChild
.lVal
;
2280 varChild
.lVal
= CHILDID_SELF
;
2281 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
2284 return pChild
->accDoDefaultAction( varChild
);
2286 } catch(...) { return E_FAIL
; }
2290 * UNO set description information for action to COM.
2291 * @param szAction, the action description of the current object.
2292 * @return S_OK if successful.
2294 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_ActionDescription( const OLECHAR
* szAction
)
2296 // internal IMAccessible - no mutex meeded
2299 if (m_isDestroy
) return S_FALSE
;
2301 if(szAction
== nullptr)
2303 return E_INVALIDARG
;
2305 SysFreeString(m_pszActionDescription
);
2306 m_pszActionDescription
= SysAllocString( szAction
);
2309 } catch(...) { return E_FAIL
; }
2312 bool CMAccessible::GetXInterfaceFromXAccessible(XAccessible
* pXAcc
, XInterface
** ppXI
, XInterfaceType eType
)
2316 case XInterfaceType::XI_COMPONENT
:
2317 return queryXInterface
<XAccessibleComponent
>(pXAcc
, ppXI
);
2318 case XInterfaceType::XI_TEXT
:
2319 return queryXInterface
<XAccessibleText
>(pXAcc
, ppXI
);
2320 case XInterfaceType::XI_EDITABLETEXT
:
2321 return queryXInterface
<XAccessibleEditableText
>(pXAcc
, ppXI
);
2322 case XInterfaceType::XI_TABLE
:
2323 return queryXInterface
<XAccessibleTable
>(pXAcc
, ppXI
);
2324 case XInterfaceType::XI_TABLECELL
:
2325 // needs specific handling, since there's no XInterface for table cells
2326 return queryTableCell(pXAcc
, ppXI
);
2327 case XInterfaceType::XI_SELECTION
:
2328 return queryXInterface
<XAccessibleSelection
>(pXAcc
, ppXI
);
2329 case XInterfaceType::XI_EXTENDEDCOMP
:
2330 return queryXInterface
<XAccessibleExtendedComponent
>(pXAcc
, ppXI
);
2331 case XInterfaceType::XI_KEYBINDING
:
2332 return queryXInterface
<XAccessibleKeyBinding
>(pXAcc
, ppXI
);
2333 case XInterfaceType::XI_ACTION
:
2334 return queryXInterface
<XAccessibleAction
>(pXAcc
, ppXI
);
2335 case XInterfaceType::XI_VALUE
:
2336 return queryXInterface
<XAccessibleValue
>(pXAcc
, ppXI
);
2337 case XInterfaceType::XI_HYPERTEXT
:
2338 return queryXInterface
<XAccessibleHypertext
>(pXAcc
, ppXI
);
2339 case XInterfaceType::XI_HYPERLINK
:
2340 return queryXInterface
<XAccessibleHyperlink
>(pXAcc
, ppXI
);
2341 case XInterfaceType::XI_IMAGE
:
2342 return queryXInterface
<XAccessibleImage
>(pXAcc
, ppXI
);
2348 template<typename T
> static HRESULT
2349 createAggInstance(CMAccessible
&rOuter
, void ** ppvObject
)
2351 // Note: CComAggObject has special handling for IUnknown - must
2352 // query for that when creating it! Otherwise we get a T member of it
2353 // which will redirect QueryInterface back to CMAccessible infinitely.
2354 // (CComAggObject has its own ref-count too which is not a problem
2355 // since it is inserted in m_containedObjects.)
2356 return CComCreator
< CComAggObject
<T
> >::CreateInstance(
2357 rOuter
.GetControllingUnknown(), IID_IUnknown
, ppvObject
);
2360 typedef HRESULT (AggCreatorFunc
)(CMAccessible
&, void **);
2367 AggCreatorFunc
* pfnCreateInstance
;
2368 const XInterfaceType eXInterfaceType
;
2373 static AggMapEntry g_CMAccessible_AggMap
[] = {
2374 { &IID_IAccessibleComponent
, &createAggInstance
<CAccComponent
>, XInterfaceType::XI_COMPONENT
},
2375 { &IID_IAccessibleText
, &createAggInstance
<CAccText
>, XInterfaceType::XI_TEXT
},
2376 { &IID_IAccessibleEditableText
, &createAggInstance
<CAccEditableText
>, XInterfaceType::XI_EDITABLETEXT
},
2377 { &IID_IAccessibleImage
, &createAggInstance
<CAccImage
>, XInterfaceType::XI_IMAGE
},
2378 { &IID_IAccessibleTable
, &createAggInstance
<CAccTable
>, XInterfaceType::XI_TABLE
},
2379 { &IID_IAccessibleTable2
, &createAggInstance
<CAccTable
>, XInterfaceType::XI_TABLE
},
2380 { &IID_IAccessibleTableCell
, &createAggInstance
<CAccTableCell
>, XInterfaceType::XI_TABLECELL
},
2381 { &IID_IAccessibleAction
, &createAggInstance
<CAccAction
>, XInterfaceType::XI_ACTION
},
2382 { &IID_IAccessibleValue
, &createAggInstance
<CAccValue
>, XInterfaceType::XI_VALUE
},
2383 { &IID_IAccessibleHypertext
, &createAggInstance
<CAccHypertext
>, XInterfaceType::XI_HYPERTEXT
},
2384 { &IID_IAccessibleHyperlink
, &createAggInstance
<CAccHyperLink
>, XInterfaceType::XI_HYPERLINK
}
2388 HRESULT WINAPI
CMAccessible::SmartQI(void* /*pv*/, REFIID iid
, void** ppvObject
)
2392 if (m_isDestroy
) return S_FALSE
;
2393 if (InlineIsEqualGUID(iid
,IID_IAccIdentity
) ||
2394 InlineIsEqualGUID(iid
,IID_IStdMarshalInfo
) ||
2395 InlineIsEqualGUID(iid
,IID_IMarshal
) ||
2396 InlineIsEqualGUID(iid
,IID_IExternalConnection
)||
2397 InlineIsEqualGUID(iid
,IID_IOleWindow
))
2402 for (const AggMapEntry
& rEntry
: g_CMAccessible_AggMap
)
2404 if (InlineIsEqualGUID(iid
, *rEntry
.piid
))
2408 XInterface
* pXI
= nullptr;
2409 bool bFound
= GetXInterfaceFromXAccessible(m_xAccessible
.get(),
2410 &pXI
, rEntry
.eXInterfaceType
);
2416 XGUIDToComObjHash::iterator pIndTemp
= m_containedObjects
.find( iid
);
2417 if ( pIndTemp
!= m_containedObjects
.end() )
2419 return pIndTemp
->second
.p
->QueryInterface( iid
, ppvObject
);
2423 HRESULT hr
= rEntry
.pfnCreateInstance(*this, ppvObject
);
2427 m_containedObjects
.emplace(*rEntry
.piid
, static_cast<IUnknown
*>(*ppvObject
));
2428 IUNOXWrapper
* wrapper
= nullptr;
2429 static_cast<IUnknown
*>(*ppvObject
)->QueryInterface(IID_IUNOXWrapper
, reinterpret_cast<void**>(&wrapper
));
2432 wrapper
->put_XInterface(
2433 reinterpret_cast<hyper
>(m_xAccessible
.get()));
2444 } catch(...) { return E_FAIL
; }
2447 bool CMAccessible::get_IAccessibleFromXAccessible(XAccessible
* pXAcc
, IAccessible
** ppIA
)
2458 isGet
= g_pAgent
->GetIAccessibleFromXAccessible(pXAcc
, ppIA
);
2468 OUString
CMAccessible::get_StringFromAny(Any
const & pAny
)
2470 switch(pAny
.getValueTypeClass())
2472 case TypeClass_CHAR
:
2476 return OUString::number(val
);
2478 case TypeClass_BOOLEAN
:
2482 return OUString::number(int(val
));
2484 case TypeClass_BYTE
:
2488 return OUString::number(val
);
2490 case TypeClass_SHORT
:
2494 return OUString::number(val
);
2496 case TypeClass_UNSIGNED_SHORT
:
2500 return OUString::number(val
);
2502 case TypeClass_LONG
:
2506 return OUString::number(val
);
2508 case TypeClass_UNSIGNED_LONG
:
2512 return OUString::number(val
);
2514 case TypeClass_FLOAT
:
2518 return OUString::number(val
);
2520 case TypeClass_DOUBLE
:
2524 return OUString::number(val
);
2526 case TypeClass_STRING
:
2532 case TypeClass_SEQUENCE
:
2534 if(pAny
.getValueType() == cppu::UnoType
<Sequence
< OUString
>>::get())
2536 Sequence
< OUString
> val
;
2539 OUStringBuffer pString
;
2541 for (const OUString
& rElem
: val
)
2542 pString
.append(rElem
);
2544 return pString
.makeStringAndClear();
2546 else if (pAny
.getValueType() == cppu::UnoType
<Sequence
< css::style::TabStop
>>::get())
2548 Sequence
< css::style::TabStop
> val
;
2552 for (const css::style::TabStop
& rSingleVal
: val
)
2555 "Position=" + OUString::number(rSingleVal
.Position
) + ",TabAlign="
2556 + OUString::number(sal_Int32(rSingleVal
.Alignment
)) + ",DecimalChar=");
2557 if (rSingleVal
.DecimalChar
==';' || rSingleVal
.DecimalChar
== ':' || rSingleVal
.DecimalChar
== ',' ||
2558 rSingleVal
.DecimalChar
== '=' || rSingleVal
.DecimalChar
== '\\')
2560 buf
.append(OUStringChar(rSingleVal
.DecimalChar
) + ",FillChar=");
2561 if (rSingleVal
.FillChar
==';' || rSingleVal
.FillChar
== ':' || rSingleVal
.FillChar
== ',' ||
2562 rSingleVal
.FillChar
== '=' || rSingleVal
.FillChar
== '\\')
2564 buf
.append(OUStringChar(rSingleVal
.FillChar
) + ",");
2566 return buf
.makeStringAndClear();
2570 case TypeClass_ENUM
:
2572 if (pAny
.getValueType() == cppu::UnoType
<css::awt::FontSlant
>::get())
2574 css::awt::FontSlant val
;
2576 return OUString::number(sal_Int32(val
));
2580 case TypeClass_STRUCT
:
2582 if (pAny
.getValueType() == cppu::UnoType
<css::style::LineSpacing
>::get())
2584 css::style::LineSpacing val
;
2586 return "Mode=" + OUString::number(val
.Mode
) + ",Height="
2587 + OUString::number(val
.Height
) + ",";
2589 else if (pAny
.getValueType() == cppu::UnoType
<css::accessibility::TextSegment
>::get())
2591 css::accessibility::TextSegment val
;
2593 return val
.SegmentText
;
2597 case TypeClass_VOID
:
2598 case TypeClass_HYPER
:
2599 case TypeClass_UNSIGNED_HYPER
:
2600 case TypeClass_TYPE
:
2602 case TypeClass_TYPEDEF
:
2603 case TypeClass_EXCEPTION
:
2604 case TypeClass_INTERFACE
:
2605 case TypeClass_SERVICE
:
2606 case TypeClass_MODULE
:
2607 case TypeClass_INTERFACE_METHOD
:
2608 case TypeClass_INTERFACE_ATTRIBUTE
:
2609 case TypeClass_UNKNOWN
:
2610 case TypeClass_PROPERTY
:
2611 case TypeClass_CONSTANT
:
2612 case TypeClass_CONSTANTS
:
2613 case TypeClass_SINGLETON
:
2621 OUString
CMAccessible::get_String4Numbering(const Any
& pAny
, sal_Int16 numberingLevel
,std::u16string_view numberingPrefix
)
2623 Reference
< css::container::XIndexReplace
> pXIndex
;
2624 if((pAny
>>=pXIndex
) && (numberingLevel
!=-1))//numbering level is -1,means invalid value
2626 Any aAny
= pXIndex
->getByIndex(numberingLevel
);
2627 Sequence
< css::beans::PropertyValue
> aProps
;
2629 OUStringBuffer
buf("Numbering:NumberingLevel=" + OUString::number(numberingLevel
) + ",");
2630 for (const css::beans::PropertyValue
& rProp
: aProps
)
2632 if( (rProp
.Name
== "BulletChar" ) ||
2633 (rProp
.Name
== "NumberingType" ))
2635 buf
.append(rProp
.Name
+ "=");
2636 auto const pTemp
= CMAccessible::get_StringFromAny(rProp
.Value
);
2637 buf
.append(pTemp
+ ",");
2639 if (rProp
.Name
== "NumberingType" && !numberingPrefix
.empty())
2641 buf
.append(OUString::Concat("NumberingPrefix=") + numberingPrefix
);
2645 return buf
.makeStringAndClear();
2648 //Because now have three types numbering level:
2649 //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
2650 //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
2651 //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
2652 // IAText:numberinglevel base on 0, but TOC's level base on 1,
2653 // so NumberingLevel value will be decreased 1 in bridge code.
2654 else if(numberingLevel
>0)
2656 return "Numbering:NumberingLevel=" + OUString::number(numberingLevel
-1) + ",NumberingType=4,NumberingPrefix=,";
2660 return "Numbering:";
2664 void CMAccessible::ConvertAnyToVariant(const css::uno::Any
&rAnyVal
, VARIANT
*pvData
)
2666 if(rAnyVal
.hasValue())
2668 // Clear VARIANT variable.
2669 VariantClear(pvData
);
2671 // Set value according to value type.
2672 switch(rAnyVal
.getValueTypeClass())
2674 case TypeClass_CHAR
:
2675 pvData
->vt
= VT_UI1
;
2676 memcpy(&pvData
->bVal
, rAnyVal
.getValue(), sizeof(char));
2679 case TypeClass_BOOLEAN
:
2681 bool bBoolean(false);
2682 rAnyVal
>>= bBoolean
;
2683 pvData
->vt
= VT_BOOL
;
2684 pvData
->boolVal
= VARIANT_BOOL(bBoolean
); // boolVal is a VARIANT_BOOL, a 16bit field
2687 case TypeClass_BYTE
:
2688 pvData
->vt
= VT_UI1
;
2689 memcpy(&pvData
->bVal
, rAnyVal
.getValue(), sizeof(sal_Int8
));
2692 case TypeClass_SHORT
:
2694 memcpy(&pvData
->iVal
, rAnyVal
.getValue(), sizeof(sal_Int16
));
2697 case TypeClass_UNSIGNED_SHORT
:
2699 memcpy(&pvData
->iVal
, rAnyVal
.getValue(), sizeof(sal_uInt16
));
2702 case TypeClass_LONG
:
2704 memcpy(&pvData
->lVal
, rAnyVal
.getValue(), sizeof(sal_Int32
));
2707 case TypeClass_UNSIGNED_LONG
:
2709 memcpy(&pvData
->lVal
, rAnyVal
.getValue(), sizeof(sal_uInt32
));
2712 case TypeClass_FLOAT
:
2714 memcpy(&pvData
->fltVal
, rAnyVal
.getValue(), sizeof(float));
2717 case TypeClass_DOUBLE
:
2719 memcpy(&pvData
->dblVal
, rAnyVal
.getValue(), sizeof(double));
2722 case TypeClass_STRING
:
2724 pvData
->vt
= VT_BSTR
;
2727 pvData
->bstrVal
= SysAllocString(o3tl::toW(val
.getStr()));
2731 case TypeClass_VOID
:
2732 case TypeClass_HYPER
:
2733 case TypeClass_UNSIGNED_HYPER
:
2734 case TypeClass_TYPE
:
2736 case TypeClass_ENUM
:
2737 case TypeClass_TYPEDEF
:
2738 case TypeClass_STRUCT
:
2739 case TypeClass_EXCEPTION
:
2740 case TypeClass_SEQUENCE
:
2741 case TypeClass_INTERFACE
:
2743 Reference
< XAccessible
> pXAcc
;
2744 if(rAnyVal
>>= pXAcc
)
2748 IAccessible
* pIAcc
= nullptr;
2749 get_IAccessibleFromXAccessible(pXAcc
.get(), &pIAcc
);
2750 if(pIAcc
== nullptr)
2752 Reference
< XAccessibleContext
> pXAccContext
= pXAcc
->getAccessibleContext();
2753 g_pAgent
->InsertAccObj(pXAcc
.get(),pXAccContext
->getAccessibleParent().get());
2754 get_IAccessibleFromXAccessible(pXAcc
.get(), &pIAcc
);
2760 pvData
->vt
= VT_UNKNOWN
;
2761 pvData
->pdispVal
= pIAcc
;
2768 case TypeClass_SERVICE
:
2769 case TypeClass_MODULE
:
2770 case TypeClass_INTERFACE_METHOD
:
2771 case TypeClass_INTERFACE_ATTRIBUTE
:
2772 case TypeClass_UNKNOWN
:
2773 case TypeClass_PROPERTY
:
2774 case TypeClass_CONSTANT
:
2775 case TypeClass_CONSTANTS
:
2776 case TypeClass_SINGLETON
:
2777 case TypeClass::TypeClass_MAKE_FIXED_SIZE
:
2778 // Output the type string, if there is other uno value type.
2779 pvData
->vt
= VT_BSTR
;
2780 pvData
->bstrVal
= SysAllocString(o3tl::toW(rAnyVal
.getValueTypeName().getStr()));
2789 VariantClear(pvData
);
2793 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_states(AccessibleStates __RPC_FAR
*states
)
2798 if (m_isDestroy
) return S_FALSE
;
2800 if (!m_xContext
.is())
2803 sal_Int64
const nRStateSet
=
2804 m_xContext
->getAccessibleStateSet();
2807 for( std::size_t j
= 0; j
< SAL_N_ELEMENTS(UNO_STATES
); j
++ )
2809 if( (UNO_STATES
[j
] != -1) && (nRStateSet
& UNO_STATES
[j
]) )
2811 *states
|= IA2_STATES
[j
];
2817 } catch(...) { return E_FAIL
; }
2820 // return the UNO roles
2821 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_extendedRole(BSTR __RPC_FAR
*)
2826 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_localizedExtendedRole(BSTR __RPC_FAR
*)
2831 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_nExtendedStates(long __RPC_FAR
*)
2837 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_localizedExtendedStates(long, BSTR __RPC_FAR
*__RPC_FAR
*, long __RPC_FAR
*)
2843 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_indexInParent(long __RPC_FAR
*accParentIndex
)
2846 if (m_isDestroy
) return S_FALSE
;
2848 if(accParentIndex
== nullptr)
2849 return E_INVALIDARG
;
2851 if (!m_xContext
.is())
2854 sal_Int64 nIndex
= m_xContext
->getAccessibleIndexInParent();
2855 if (nIndex
> std::numeric_limits
<long>::max())
2857 SAL_WARN("iacc2", "CMAccessible::get_indexInParent: Child index exceeds maximum long value, "
2858 "returning max long.");
2859 nIndex
= std::numeric_limits
<long>::max();
2861 *accParentIndex
= nIndex
;
2865 } catch(...) { return E_FAIL
; }
2867 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_locale( IA2Locale __RPC_FAR
*locale
)
2870 if (m_isDestroy
) return S_FALSE
;
2871 if(locale
== nullptr)
2872 return E_INVALIDARG
;
2874 if (!m_xContext
.is())
2877 css::lang::Locale unoLoc
= m_xContext
->getLocale();
2878 locale
->language
= SysAllocString(o3tl::toW(unoLoc
.Language
.getStr()));
2879 locale
->country
= SysAllocString(o3tl::toW(unoLoc
.Country
.getStr()));
2880 locale
->variant
= SysAllocString(o3tl::toW(unoLoc
.Variant
.getStr()));
2884 } catch(...) { return E_FAIL
; }
2887 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_appName(BSTR __RPC_FAR
*name
)
2892 if (m_isDestroy
) return S_FALSE
;
2894 return E_INVALIDARG
;
2896 static const OUString sAppName
= utl::ConfigManager::getProductName();
2897 *name
= SysAllocString(o3tl::toW(sAppName
.getStr()));
2899 } catch(...) { return E_FAIL
; }
2901 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_appVersion(BSTR __RPC_FAR
*version
)
2906 if (m_isDestroy
) return S_FALSE
;
2907 if(version
== nullptr)
2908 return E_INVALIDARG
;
2909 static const OUString sVersion
= utl::ConfigManager::getProductVersion();
2910 *version
=SysAllocString(o3tl::toW(sVersion
.getStr()));
2912 } catch(...) { return E_FAIL
; }
2914 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_toolkitName(BSTR __RPC_FAR
*name
)
2919 if (m_isDestroy
) return S_FALSE
;
2921 return E_INVALIDARG
;
2922 *name
= SysAllocString(OLESTR("VCL"));
2924 } catch(...) { return E_FAIL
; }
2926 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_toolkitVersion(BSTR __RPC_FAR
*version
)
2928 return get_appVersion(version
);
2932 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_attributes(/*[out]*/ BSTR
*pAttr
)
2937 if (m_isDestroy
) return S_FALSE
;
2939 if (!m_xAccessible
.is())
2942 Reference
<XAccessibleContext
> pRContext
= m_xAccessible
->getAccessibleContext();
2943 if( !pRContext
.is() )
2947 Reference
<XAccessibleExtendedAttributes
> pRXI(pRContext
,UNO_QUERY
);
2952 css::uno::Reference
<css::accessibility::XAccessibleExtendedAttributes
> pRXAttr
;
2953 pRXAttr
= pRXI
.get();
2954 css::uno::Any anyVal
= pRXAttr
->getExtendedAttributes();
2960 SysFreeString(*pAttr
);
2961 *pAttr
= SysAllocString(o3tl::toW(val
.getStr()));
2965 } catch(...) { return E_FAIL
; }
2968 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */