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"
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
29 #pragma clang diagnostic pop
35 #include "AccAction.h"
36 #include "AccRelation.h"
37 #include "AccComponent.h"
39 #include "AccEditableText.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
{
79 XI_EDITABLETEXT
= 0x04,
82 XI_EXTENDEDCOMP
= 0x07,
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;
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) \
149 pRContext = pXAcc->getAccessibleContext(); \
150 if( !pRContext.is() ) \
154 Reference<X##ainterface> pRXI(pRContext,UNO_QUERY);\
159 *ppXI = pRXI.get(); \
163 #define ISDESTROY() \
168 AccObjectManagerAgent
* CMAccessible::g_pAgent
= nullptr;
170 CMAccessible::CMAccessible():
173 m_pszActionDescription(nullptr),
176 m_pszDescription(nullptr),
179 m_dFocusChildID(UACC_NO_FOCUS
),
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()
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
);
216 m_pIParent
->Release();
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
)
235 ENTER_PROTECTED_BLOCK
238 if(ppdispParent
== nullptr)
245 *ppdispParent
= m_pIParent
;
246 (*ppdispParent
)->AddRef();
251 HRESULT hr
= AccessibleObjectFromWindow(m_hwnd
, OBJID_WINDOW
, IID_IAccessible
, reinterpret_cast<void**>(ppdispParent
));
252 if (!SUCCEEDED(hr
) || !*ppdispParent
)
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
)
272 ENTER_PROTECTED_BLOCK
275 if(pcountChildren
== nullptr)
280 if (!m_xAccessible
.is())
283 Reference
<XAccessibleContext
> const pRContext
=
284 m_xAccessible
->getAccessibleContext();
287 *pcountChildren
= pRContext
->getAccessibleChildCount();
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
)
306 ENTER_PROTECTED_BLOCK
309 if(ppdispChild
== nullptr)
313 if(varChild
.vt
==VT_I4
)
315 //get child interface pointer due to child ID
316 if(varChild
.lVal
==CHILDID_SELF
)
322 *ppdispChild
= GetChildInterface(varChild
.lVal
);
323 if((*ppdispChild
) == nullptr)
325 (*ppdispChild
)->AddRef();
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
)
344 ENTER_PROTECTED_BLOCK
347 if(pszName
== nullptr)
351 if(varChild
.vt
==VT_I4
)
353 if(varChild
.lVal
==CHILDID_SELF
)
355 SAFE_SYSFREESTRING(*pszName
);
356 *pszName
= SysAllocString(m_pszName
);
360 long lVal
= varChild
.lVal
;
361 varChild
.lVal
= CHILDID_SELF
;
362 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
365 return pChild
->get_accName(varChild
,pszName
);
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
)
383 ENTER_PROTECTED_BLOCK
386 if( pszValue
== nullptr )
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 )
400 SAFE_SYSFREESTRING(*pszValue
);
401 *pszValue
= SysAllocString(m_pszValue
);
405 long lVal
= varChild
.lVal
;
406 varChild
.lVal
= CHILDID_SELF
;
407 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
410 return pChild
->get_accValue(varChild
,pszValue
);
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
)
428 ENTER_PROTECTED_BLOCK
431 if(pszDescription
== nullptr)
435 if(varChild
.vt
==VT_I4
)
437 if(varChild
.lVal
==CHILDID_SELF
)
439 SAFE_SYSFREESTRING(*pszDescription
);
440 *pszDescription
= SysAllocString(m_pszDescription
);
444 long lVal
= varChild
.lVal
;
445 varChild
.lVal
= CHILDID_SELF
;
446 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
449 return pChild
->get_accDescription(varChild
,pszDescription
);
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
)
467 ENTER_PROTECTED_BLOCK
470 if(pvarRole
== nullptr)
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
;
487 VariantInit(pvarRole
);
488 pvarRole
->vt
= VT_I4
;
489 pvarRole
->lVal
= ROLE_SYSTEM_CLIENT
;
495 long lVal
= varChild
.lVal
;
496 varChild
.lVal
= CHILDID_SELF
;
497 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
500 return pChild
->get_accRole(varChild
,pvarRole
);
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
)
518 ENTER_PROTECTED_BLOCK
521 if(pvarState
== nullptr)
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();
535 // add the STATE_SYSTEM_LINKED state
536 Reference
< XAccessibleHypertext
> pRHypertext(pContext
,UNO_QUERY
);
539 if( pRHypertext
->getHyperLinkCount() > 0 )
540 m_dState
|= STATE_SYSTEM_LINKED
;
542 m_dState
&= ~STATE_SYSTEM_LINKED
;
545 m_dState
&= ~STATE_SYSTEM_LINKED
;
549 VariantInit(pvarState
);
550 pvarState
->vt
= VT_I4
;
551 pvarState
->lVal
= m_dState
;
555 long lVal
= varChild
.lVal
;
556 varChild
.lVal
= CHILDID_SELF
;
557 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
560 return pChild
->get_accState(varChild
,pvarState
);
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
*)
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 *)
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) {
600 auto c
= aStr
[i
+ 1];
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
)
619 ENTER_PROTECTED_BLOCK
623 if(pszKeyboardShortcut
== nullptr)
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() )
639 Reference
<XAccessibleAction
> pRXI(pRContext
,UNO_QUERY
);
643 if( pRXI
.is() && pRXI
->getAccessibleActionCount() >= 1)
645 Reference
< XAccessibleKeyBinding
> binding
= pRXI
->getAccessibleActionKeyBinding(0);
648 long nCount
= binding
->getAccessibleKeyBindingCount();
651 wString
= comphelper::GetkeyBindingStrByXkeyBinding( binding
->getAccessibleKeyBinding(0) );
655 if(wString
.isEmpty())
657 Reference
<XAccessibleRelationSet
> pRrelationSet
= pRContext
->getAccessibleRelationSet();
658 if(!pRrelationSet
.is())
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
);
672 && SUCCEEDED(m_pIParent
->get_accRole(varChild
, &varParentRole
))
673 && varParentRole
.lVal
== ROLE_SYSTEM_COMBOBOX
) // edit in comboBox
675 m_pIParent
->get_accKeyboardShortcut(varChild
, pszKeyboardShortcut
);
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)
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())
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
;
718 xTargets
= paccRelation
->TargetSet
;
720 if (m_xAccessible
.get() != static_cast<XAccessible
*>(pRAcc
.get()))
724 Reference
<XAccessibleExtendedComponent
> pRXIE(pRLebelContext
,UNO_QUERY
);
728 OUString ouStr
= pRXIE
->getTitledBorderText();
730 if(GetMnemonicChar(ouStr
, &key
))
732 wString
= "Alt+" + OUStringChar(key
);
738 SAFE_SYSFREESTRING(*pszKeyboardShortcut
);
739 *pszKeyboardShortcut
= SysAllocString(o3tl::toW(wString
.getStr()));
749 long lVal
= varChild
.lVal
;
750 varChild
.lVal
= CHILDID_SELF
;
751 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
755 return pChild
->get_accKeyboardShortcut(varChild
,pszKeyboardShortcut
);
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
)
772 ENTER_PROTECTED_BLOCK
775 if(pvarChild
== nullptr)
779 if( m_dFocusChildID
==UACC_NO_FOCUS
)
781 pvarChild
->vt
= VT_EMPTY
;//no focus on the object and its children
784 //if the descendant of current object has focus indicated by m_dFocusChildID, return the IDispatch of this focused object
787 IMAccessible
* pIMAcc
= nullptr;
788 g_pAgent
->GetIAccessibleFromResID(m_dFocusChildID
,&pIMAcc
);
789 if (pIMAcc
== nullptr)
794 pvarChild
->vt
= VT_DISPATCH
;
795 pvarChild
->pdispVal
= pIMAcc
;
800 LEAVE_PROTECTED_BLOCK
804 * Returns the selection of the current COM object to AT.
805 * @param pvarChildren,[in,out]
806 * if selection num is 0,return VT_EMPTY for vt,
807 * if selection num is 1,return VT_I4 for vt,and child index for lVal
808 * if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
809 * @return S_OK if successful and S_FALSE if failure.
811 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_accSelection(VARIANT
*pvarChildren
)
815 ENTER_PROTECTED_BLOCK
818 if(pvarChildren
== nullptr)
822 switch(m_pEnumVar
->GetCountOfElements())
825 pvarChildren
->vt
= VT_EMPTY
;
830 VariantInit(&varTmp
[0]);
831 m_pEnumVar
->Next(1,varTmp
,&count
);
834 pvarChildren
->vt
= VT_I4
;
835 pvarChildren
->lVal
= varTmp
[0].lVal
;
836 VariantClear(&varTmp
[0]);
840 pvarChildren
->vt
= VT_UNKNOWN
;
841 m_pEnumVar
->AddRef();
842 pvarChildren
->punkVal
= m_pEnumVar
;
847 LEAVE_PROTECTED_BLOCK
851 * Returns the location of the current COM object self or its one child to AT.
852 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
853 * the child ID specify child index from 0 to children count, 0 stands for object self.
854 * @param pxLeft, [in,out] use to return the x-coordination of the proper object.
855 * @param pyTop, [in,out] use to return the y-coordination of the proper object.
856 * @param pcxWidth, [in,out] use to return the x-coordination width of the proper object.
857 * @param pcyHeight, [in,out] use to return the y-coordination height of the proper object.
858 * @return S_OK if successful and S_FALSE if failure.
860 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accLocation(long *pxLeft
, long *pyTop
, long *pcxWidth
, long *pcyHeight
, VARIANT varChild
)
864 ENTER_PROTECTED_BLOCK
867 if(pxLeft
== nullptr || pyTop
== nullptr || pcxWidth
== nullptr || pcyHeight
== nullptr)
872 if(varChild
.vt
==VT_I4
)
874 if(varChild
.lVal
==CHILDID_SELF
)
877 if (m_xAccessible
.is())
879 Reference
<XAccessibleContext
> const pRContext
=
880 m_xAccessible
->getAccessibleContext();
881 if( !pRContext
.is() )
883 Reference
< XAccessibleComponent
> pRComponent(pRContext
,UNO_QUERY
);
884 if( !pRComponent
.is() )
887 css::awt::Point pCPoint
= pRComponent
->getLocationOnScreen();
888 css::awt::Size pCSize
= pRComponent
->getSize();
891 *pcxWidth
= pCSize
.Width
;
892 *pcyHeight
= pCSize
.Height
;
897 *pxLeft
= m_sLocation
.m_dLeft
;
898 *pyTop
= m_sLocation
.m_dTop
;
899 *pcxWidth
= m_sLocation
.m_dWidth
;
900 *pcyHeight
= m_sLocation
.m_dHeight
;
908 LEAVE_PROTECTED_BLOCK
912 * Returns the current focused child to AT.
913 * @param navDir, the direction flag of the navigation.
914 * @param varStart, the start child id of this navigation action.
915 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
916 * @return S_OK if successful and E_FAIL if failure.
918 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accNavigate(long navDir
, VARIANT varStart
, VARIANT
*pvarEndUpAt
)
922 ENTER_PROTECTED_BLOCK
925 if(pvarEndUpAt
== nullptr)
929 HRESULT ret
= E_FAIL
;
932 case NAVDIR_FIRSTCHILD
:
933 ret
= GetFirstChild(varStart
,pvarEndUpAt
);
935 case NAVDIR_LASTCHILD
:
936 ret
= GetLastChild(varStart
,pvarEndUpAt
);
939 ret
= GetNextSibling(varStart
,pvarEndUpAt
);
941 case NAVDIR_PREVIOUS
:
942 ret
= GetPreSibling(varStart
,pvarEndUpAt
);
944 case NAVDIR_DOWN
://do not implement temporarily
946 case NAVDIR_UP
://do not implement temporarily
948 case NAVDIR_LEFT
://do not implement temporarily
950 case NAVDIR_RIGHT
://do not implement temporarily
957 LEAVE_PROTECTED_BLOCK
960 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accHitTest(long xLeft
, long yTop
, VARIANT
*pvarChild
)
964 ENTER_PROTECTED_BLOCK
967 if(pvarChild
== nullptr)
973 VariantInit(&varSelf
);
975 varSelf
.lVal
= CHILDID_SELF
;
976 accLocation(&x
,&y
,&w
,&h
,varSelf
);
977 if( (x
< xLeft
&& (x
+ w
) >xLeft
) && (y
< yTop
&& (y
+ h
) >yTop
) )
980 pvarChild
->vt
= VT_EMPTY
;
981 Reference
< XAccessibleContext
> pRContext
= GetContextByXAcc(m_xAccessible
.get());
982 nCount
= pRContext
->getAccessibleChildCount();
985 IMAccessible
* child
= nullptr;
986 for( i
= 0; i
<nCount
; i
++)
989 child
= GetChildInterface(i
+ 1);
990 if(child
&& child
->accHitTest(xLeft
,yTop
,pvarChild
) == S_OK
)
994 if(pvarChild
->vt
== VT_DISPATCH
)
999 pvarChild
->vt
= VT_DISPATCH
;
1000 pvarChild
->pdispVal
= child
;
1005 pvarChild
->vt
= VT_I4
;
1006 pvarChild
->lVal
= CHILDID_SELF
;
1012 LEAVE_PROTECTED_BLOCK
1016 * Get The other Interface from CMAccessible.
1017 * @param guidService, must be IID_IAccessible here.
1018 * @param riid, the IID interface .
1019 * @return S_OK if successful and S_FALSE if failure.
1021 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::QueryService(REFGUID guidService
, REFIID riid
, void** ppvObject
)
1023 if( InlineIsEqualGUID(guidService
, IID_IAccessible
) )
1024 return QueryInterface(riid
, ppvObject
);
1029 * Set the accessible name of the current COM object self or its one child from UNO.
1030 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1031 * the child ID specify child index from 0 to children count, 0 stands for object self.
1032 * @param szName, the name used to set the name of the proper object.
1033 * @return S_OK if successful and E_FAIL if failure.
1035 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::put_accName(VARIANT varChild
, BSTR szName
)
1039 ENTER_PROTECTED_BLOCK
1041 if(varChild
.vt
==VT_I4
)
1043 if(varChild
.lVal
==CHILDID_SELF
)
1045 SAFE_SYSFREESTRING(m_pszName
);
1046 m_pszName
=SysAllocString(szName
);
1050 long lVal
= varChild
.lVal
;
1051 varChild
.lVal
= CHILDID_SELF
;
1052 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
1055 return pChild
->put_accName(varChild
,szName
);
1059 LEAVE_PROTECTED_BLOCK
1063 * Set the accessible value of the current COM object self or its one child from UNO.
1064 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1065 * the child ID specify child index from 0 to children count, 0 stands for object self.
1066 * @param szValue, the value used to set the value of the proper object.
1067 * @return S_OK if successful and E_FAIL if failure.
1069 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::put_accValue(VARIANT varChild
, BSTR szValue
)
1073 ENTER_PROTECTED_BLOCK
1075 if(varChild
.vt
==VT_I4
)
1077 if(varChild
.lVal
==CHILDID_SELF
)
1079 SAFE_SYSFREESTRING(m_pszValue
);
1080 m_pszValue
=SysAllocString(szValue
);
1084 long lVal
= varChild
.lVal
;
1085 varChild
.lVal
= CHILDID_SELF
;
1086 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
1089 return pChild
->put_accValue(varChild
,szValue
);
1093 LEAVE_PROTECTED_BLOCK
1097 * Set the accessible name of the current COM object self from UNO.
1098 * @param pszName, the name value used to set the name of the current object.
1099 * @return S_OK if successful and E_FAIL if failure.
1101 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR
*pszName
)
1103 // internal IMAccessible - no mutex meeded
1105 ENTER_PROTECTED_BLOCK
1108 if(pszName
== nullptr)
1110 return E_INVALIDARG
;
1113 SAFE_SYSFREESTRING(m_pszName
);
1114 m_pszName
= SysAllocString(pszName
);
1115 if(m_pszName
==nullptr)
1119 LEAVE_PROTECTED_BLOCK
1123 * Set the accessible role of the current COM object self from UNO.
1124 * @param pRole, the role value used to set the role of the current object.
1125 * @return S_OK if successful and E_FAIL if failure.
1127 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccRole(unsigned short pRole
)
1129 // internal IMAccessible - no mutex meeded
1136 * Add one state into the current state set for the current COM object from UNO.
1137 * @param pXSate, the state used to set the name of the current object.
1138 * @return S_OK if successful and E_FAIL if failure.
1140 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::DecreaseState(DWORD pXSate
)
1142 // internal IMAccessible - no mutex meeded
1144 m_dState
&= (~pXSate
);
1149 * Delete one state into the current state set for the current COM object from UNO.
1150 * @param pXSate, the state used to set the name of the current object.
1151 * @return S_OK if successful and E_FAIL if failure.
1153 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::IncreaseState(DWORD pXSate
)
1155 // internal IMAccessible - no mutex meeded
1162 * Set state into the current state set for the current COM object from UNO.
1163 * @param pXSate, the state used to set the name of the current object.
1164 * @return S_OK if successful and E_FAIL if failure.
1166 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::SetState(DWORD pXSate
)
1168 // internal IMAccessible - no mutex meeded
1176 * Set the accessible description of the current COM object self from UNO.
1177 * @param pszDescription, the name used to set the description of the current object.
1178 * @return S_OK if successful and E_FAIL if failure.
1180 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccDescription(const OLECHAR __RPC_FAR
*pszDescription
)
1182 // internal IMAccessible - no mutex meeded
1184 ENTER_PROTECTED_BLOCK
1187 if(pszDescription
== nullptr)
1189 return E_INVALIDARG
;
1192 SAFE_SYSFREESTRING(m_pszDescription
);
1193 m_pszDescription
= SysAllocString(pszDescription
);
1195 if(m_pszDescription
==nullptr)
1199 LEAVE_PROTECTED_BLOCK
1203 * Set the accessible value of the current COM object self from UNO.
1204 * @param pszAccValue, the name used to set the value of the current object.
1205 * @return S_OK if successful and E_FAIL if failure.
1207 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR
*pszAccValue
)
1209 // internal IMAccessible - no mutex meeded
1211 ENTER_PROTECTED_BLOCK
1214 if(pszAccValue
== nullptr)
1216 return E_INVALIDARG
;
1218 SAFE_SYSFREESTRING(m_pszValue
);
1219 m_pszValue
= SysAllocString(pszAccValue
);
1220 if(m_pszValue
==nullptr)
1224 LEAVE_PROTECTED_BLOCK
1228 * Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
1229 * Object through the method AccessibleObjectFromWindow(...).
1230 * @param hwnd, the HWND used to set the value of the current object.
1231 * @return S_OK if successful and E_FAIL if failure.
1233 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccWindowHandle(HWND hwnd
)
1235 // internal IMAccessible - no mutex meeded
1237 ENTER_PROTECTED_BLOCK
1242 LEAVE_PROTECTED_BLOCK
1246 * Set accessible focus by specifying child ID
1247 * @param dChildID, the child id identifies the focus child.
1248 * @return S_OK if successful and E_FAIL if failure.
1250 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccFocus(long dChildID
)
1252 // internal IMAccessible - no mutex meeded
1254 ENTER_PROTECTED_BLOCK
1257 if(dChildID
==CHILDID_SELF
)
1261 m_pIParent
->Put_XAccFocus(m_dChildID
);
1266 m_dFocusChildID
= dChildID
;
1267 //traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
1268 //any of the ancestors, this id can be used to get the IAccessible of focused object.
1271 m_pIParent
->Put_XAccFocus(dChildID
);
1276 LEAVE_PROTECTED_BLOCK
1280 *Set accessible object location for the current COM object
1281 * @param sLocation, the location of the current object.
1282 * @return S_OK if successful and E_FAIL if failure.
1284 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccLocation(const Location sLocation
)
1286 // internal IMAccessible - no mutex meeded
1288 this->m_sLocation
= sLocation
;
1293 * Set accessible parent object for the current COM object if
1294 * the current object is a child of some COM object
1295 * @param pIParent, the parent of the current object.
1296 * @return S_OK if successful and E_FAIL if failure.
1298 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR
*pIParent
)
1300 // internal IMAccessible - no mutex meeded
1302 this->m_pIParent
= pIParent
;
1305 m_pIParent
->AddRef();
1311 * Set unique child id to COM
1312 * @param dChildID, the id of the current object.
1313 * @return S_OK if successful and E_FAIL if failure.
1315 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccChildID(long dChildID
)
1317 // internal IMAccessible - no mutex meeded
1319 this->m_dChildID
= dChildID
;
1324 * Set AccObjectManagerAgent object pointer to COM
1325 * @param pAgent, the AccObjectManagerAgent point.
1326 * @return S_OK if successful and E_FAIL if failure.
1328 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_XAccAgent(hyper pAgent
)
1330 // internal IMAccessible - no mutex meeded
1332 g_pAgent
= reinterpret_cast<AccObjectManagerAgent
*>(pAgent
);
1337 * When a UNO control disposing, it disposes its listeners,
1338 * then notify AccObject in bridge management, then notify
1339 * COM that the XAccessible is invalid,so set m_xAccessible as NULL
1340 * @param isDestroy, true is it needs to be destroyed.
1341 * @return S_OK if successful and E_FAIL if failure.
1343 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::NotifyDestroy(BOOL isDestroy
)
1345 // internal IMAccessible - no mutex meeded
1347 m_isDestroy
= isDestroy
;
1348 m_xAccessible
.clear();
1353 *private methods that help implement public functions
1357 * Return child interface pointer by child ID,note: need to call AddRef()
1358 * @param lChildID, specify child index,which AT(such as Inspect32) gives.
1359 * @return IMAccessible*, pointer to the corresponding child object.
1361 IMAccessible
* CMAccessible::GetChildInterface(long dChildID
)//for test
1367 IMAccessible
* pIMAcc
= nullptr;
1368 g_pAgent
->GetIAccessibleFromResID(dChildID
,&pIMAcc
);
1375 if (!m_xAccessible
.is())
1378 Reference
<XAccessibleContext
> const pRContext
=
1379 m_xAccessible
->getAccessibleContext();
1380 if( !pRContext
.is() )
1383 if(dChildID
<1 || dChildID
>pRContext
->getAccessibleChildCount())
1386 IAccessible
* pChild
= nullptr;
1387 Reference
< XAccessible
> pXChild
= pRContext
->getAccessibleChild(dChildID
-1);
1388 BOOL isGet
= get_IAccessibleFromXAccessible(pXChild
.get(), &pChild
);
1392 g_pAgent
->InsertAccObj(pXChild
.get(), m_xAccessible
.get(),
1393 reinterpret_cast<sal_Int64
>(m_hwnd
));
1394 isGet
= get_IAccessibleFromXAccessible(pXChild
.get(), &pChild
);
1399 IMAccessible
* pIMAcc
= static_cast<IMAccessible
*>(pChild
);
1408 * For List, tree and table,these roles belong to manage_descendant in UNO,
1409 * need to process specifically when navigate
1410 * @return BOOL, if it is descendantmanager, return true.
1412 BOOL
CMAccessible::IsDescendantManage()
1415 return (m_iRole
==ROLE_SYSTEM_LIST
)||(m_iRole
==ROLE_SYSTEM_OUTLINE
)||(m_iRole
==ROLE_SYSTEM_TABLE
);
1419 * for descendantmanager circumstance,provide child interface when navigate
1420 * @param varCur, the current child.
1421 * @param flags, the navigation direction.
1422 * @return IMAccessible*, the child of the end up node.
1424 IMAccessible
* CMAccessible::GetNavigateChildForDM(VARIANT varCur
, short flags
)
1427 XAccessibleContext
* pXContext
= GetContextByXAcc(m_xAccessible
.get());
1428 if(pXContext
==nullptr)
1433 int count
= pXContext
->getAccessibleChildCount();
1439 IMAccessible
* pCurChild
= nullptr;
1441 XAccessible
* pChildXAcc
;
1444 Reference
<XAccessible
> pRChildXAcc
;
1445 XAccessibleContext
* pChildContext
= nullptr;
1446 int index
= 0,delta
=0;
1450 pRChildXAcc
= pXContext
->getAccessibleChild(0);
1453 pRChildXAcc
= pXContext
->getAccessibleChild(count
-1);
1457 pCurChild
= GetChildInterface(varCur
.lVal
);
1458 if(pCurChild
==nullptr)
1462 pCurChild
->GetUNOInterface(&nHyper
);
1463 if(pChildXAcc
==nullptr)
1467 pChildContext
= GetContextByXAcc(pChildXAcc
);
1468 if(pChildContext
== nullptr)
1472 delta
= (flags
==DM_NEXTCHILD
)?1:-1;
1473 //currently, getAccessibleIndexInParent is error in UNO for
1474 //some kind of List,such as ValueSet, the index will be less 1 than
1475 //what should be, need to fix UNO code
1476 index
= pChildContext
->getAccessibleIndexInParent()+delta
;
1477 if((index
>=0)&&(index
<=count
-1))
1479 pRChildXAcc
= pXContext
->getAccessibleChild(index
);
1486 if(!pRChildXAcc
.is())
1490 pChildXAcc
= pRChildXAcc
.get();
1491 g_pAgent
->InsertAccObj(pChildXAcc
, m_xAccessible
.get());
1492 return g_pAgent
->GetIMAccByXAcc(pChildXAcc
);
1496 *the following 4 private methods are for accNavigate implementation
1500 * Return first child for parent container, process differently according
1501 * to whether it is descendant manage
1502 * @param varStart, the start child id of this navigation action.
1503 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1504 * @return S_OK if successful and E_FAIL if failure.
1506 HRESULT
CMAccessible::GetFirstChild(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1509 ENTER_PROTECTED_BLOCK
1512 if(pvarEndUpAt
== nullptr)
1514 return E_INVALIDARG
;
1516 if(varStart
.vt
!= VT_I4
)
1518 pvarEndUpAt
->vt
= VT_EMPTY
;
1519 return E_INVALIDARG
;
1522 pvarEndUpAt
->pdispVal
= GetNavigateChildForDM(varStart
, DM_FIRSTCHILD
);
1523 if(pvarEndUpAt
->pdispVal
)
1525 pvarEndUpAt
->pdispVal
->AddRef();
1526 pvarEndUpAt
->vt
= VT_DISPATCH
;
1530 pvarEndUpAt
->vt
= VT_EMPTY
;
1533 LEAVE_PROTECTED_BLOCK
1537 * Return last child for parent container, process differently according
1538 * to whether it is descendant manage
1539 * @param varStart, the start child id of this navigation action.
1540 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1541 * @return S_OK if successful and E_FAIL if failure.
1543 HRESULT
CMAccessible::GetLastChild(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1546 ENTER_PROTECTED_BLOCK
1549 if(pvarEndUpAt
== nullptr)
1551 return E_INVALIDARG
;
1553 if(varStart
.vt
!= VT_I4
)
1555 pvarEndUpAt
->vt
= VT_EMPTY
;
1556 return E_INVALIDARG
;
1559 pvarEndUpAt
->pdispVal
= GetNavigateChildForDM(varStart
, DM_LASTCHILD
);
1560 if(pvarEndUpAt
->pdispVal
)
1562 pvarEndUpAt
->pdispVal
->AddRef();
1563 pvarEndUpAt
->vt
= VT_DISPATCH
;
1566 pvarEndUpAt
->vt
= VT_EMPTY
;
1569 LEAVE_PROTECTED_BLOCK
1573 * The method GetNextSibling is general, whatever it is descendant manage or not
1574 * Get the next sibling object.
1575 * @param varStart, the start child id of this navigation action.
1576 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1577 * @return S_OK if successful and E_FAIL if failure.
1579 HRESULT
CMAccessible::GetNextSibling(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1582 ENTER_PROTECTED_BLOCK
1584 if(varStart
.vt
!= VT_I4
)
1586 pvarEndUpAt
->vt
= VT_EMPTY
;
1587 return E_INVALIDARG
;
1590 Reference
<XAccessibleContext
> const pRContext
=
1591 GetContextByXAcc(m_xAccessible
.get());
1594 varStart
.iVal
= sal_Int16(pRContext
->getAccessibleIndexInParent() + 2);
1596 if( m_pIParent
->get_accChild(varStart
,&pvarEndUpAt
->pdispVal
) == S_OK
)
1598 pvarEndUpAt
->vt
= VT_DISPATCH
;
1602 pvarEndUpAt
->vt
= VT_EMPTY
;
1605 LEAVE_PROTECTED_BLOCK
1609 *the method GetPreSibling is general, whatever it is descendant manage or not
1610 * @param varStart, the start child id of this navigation action.
1611 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1612 * @return S_OK if successful and E_FAIL if failure.
1614 HRESULT
CMAccessible::GetPreSibling(VARIANT varStart
,VARIANT
* pvarEndUpAt
)
1617 ENTER_PROTECTED_BLOCK
1620 if(pvarEndUpAt
== nullptr)
1622 return E_INVALIDARG
;
1624 if(varStart
.vt
!= VT_I4
)
1626 pvarEndUpAt
->vt
= VT_EMPTY
;
1627 return E_INVALIDARG
;
1630 Reference
<XAccessibleContext
> const pRContext
=
1631 GetContextByXAcc(m_xAccessible
.get());
1634 varStart
.iVal
= sal_Int16(pRContext
->getAccessibleIndexInParent());
1635 if(m_pIParent
&& varStart
.iVal
> 0)
1636 if( m_pIParent
->get_accChild(varStart
,&pvarEndUpAt
->pdispVal
) == S_OK
)
1638 pvarEndUpAt
->vt
= VT_DISPATCH
;
1642 pvarEndUpAt
->vt
= VT_EMPTY
;
1645 LEAVE_PROTECTED_BLOCK
1649 * For IAccessible2 implementation methods
1651 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_nRelations( long __RPC_FAR
*nRelations
)
1655 ENTER_PROTECTED_BLOCK
1659 if(nRelations
== nullptr)
1661 return E_INVALIDARG
;
1666 if (!m_xContext
.is())
1668 Reference
<XAccessibleRelationSet
> pRrelationSet
=
1669 m_xContext
.get()->getAccessibleRelationSet();
1670 if(!pRrelationSet
.is())
1676 *nRelations
= pRrelationSet
->getRelationCount();
1679 LEAVE_PROTECTED_BLOCK
1682 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_relation( long relationIndex
, IAccessibleRelation __RPC_FAR
*__RPC_FAR
*relation
)
1686 ENTER_PROTECTED_BLOCK
1689 if(relation
== nullptr)
1691 return E_INVALIDARG
;
1694 if (!m_xContext
.is())
1699 get_nRelations(&nMax
);
1701 *relation
= static_cast<IAccessibleRelation
*>(::CoTaskMemAlloc(sizeof(IAccessibleRelation
)));
1703 // #CHECK Memory Allocation#
1704 if(*relation
== nullptr)
1709 if( relationIndex
< nMax
)
1711 Reference
<XAccessibleRelationSet
> const pRrelationSet
=
1712 m_xContext
.get()->getAccessibleRelationSet();
1713 if(!pRrelationSet
.is())
1719 IAccessibleRelation
* pRelation
= nullptr;
1720 HRESULT hr
= createInstance
<CAccRelation
>(IID_IAccessibleRelation
,
1724 IUNOXWrapper
* wrapper
= nullptr;
1725 hr
= pRelation
->QueryInterface(IID_IUNOXWrapper
, reinterpret_cast<void**>(&wrapper
));
1728 AccessibleRelation accRelation
= pRrelationSet
->getRelation(relationIndex
);
1729 wrapper
->put_XSubInterface(
1730 reinterpret_cast<hyper
>(&accRelation
));
1732 *relation
= pRelation
;
1741 LEAVE_PROTECTED_BLOCK
1744 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR
*__RPC_FAR
*relation
, long __RPC_FAR
*nRelations
)
1748 ENTER_PROTECTED_BLOCK
1752 if(relation
== nullptr || nRelations
== nullptr)
1754 return E_INVALIDARG
;
1756 // #CHECK XInterface#
1758 if (!m_xContext
.is())
1761 Reference
<XAccessibleRelationSet
> const pRrelationSet
=
1762 m_xContext
.get()->getAccessibleRelationSet();
1763 if(!pRrelationSet
.is())
1769 long nCount
= pRrelationSet
->getRelationCount();
1771 *relation
= static_cast<IAccessibleRelation
*>(::CoTaskMemAlloc(nCount
*sizeof(IAccessibleRelation
)));
1773 // #CHECK Memory Allocation#
1774 if(*relation
== nullptr)
1779 for(int i
=0; i
<nCount
; i
++)
1781 IAccessibleRelation
* pRelation
= nullptr;
1782 HRESULT hr
= createInstance
<CAccRelation
>(IID_IAccessibleRelation
,
1786 IUNOXWrapper
* wrapper
= nullptr;
1787 hr
= pRelation
->QueryInterface(IID_IUNOXWrapper
, reinterpret_cast<void**>(&wrapper
));
1790 AccessibleRelation accRelation
= pRrelationSet
->getRelation(i
);
1791 wrapper
->put_XSubInterface(
1792 reinterpret_cast<hyper
>(&accRelation
));
1795 relation
[i
] = pRelation
;
1799 *nRelations
= nCount
;
1802 LEAVE_PROTECTED_BLOCK
1805 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::role(long __RPC_FAR
*role
)
1809 ENTER_PROTECTED_BLOCK
1815 LEAVE_PROTECTED_BLOCK
1819 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_nActions(long __RPC_FAR
*nActions
)
1827 if(nActions
== nullptr)
1829 return E_INVALIDARG
;
1832 IAccessibleAction
* pAcc
= nullptr;
1833 HRESULT hr
= QueryInterface(IID_IAccessibleAction
, reinterpret_cast<void**>(&pAcc
));
1836 pAcc
->nActions(nActions
);
1850 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: scrollToPoint(enum IA2CoordinateType
, long, long)
1855 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: scrollTo(enum IA2ScrollType
)
1860 static XAccessible
* getTheParentOfMember(XAccessible
* pXAcc
)
1863 if(pXAcc
== nullptr)
1867 Reference
<XAccessibleContext
> pRContext
= pXAcc
->getAccessibleContext();
1868 Reference
<XAccessibleRelationSet
> pRrelationSet
= pRContext
->getAccessibleRelationSet();
1869 sal_Int32 nRelations
= pRrelationSet
->getRelationCount();
1870 for(sal_Int32 i
=0 ; i
<nRelations
; i
++)
1872 AccessibleRelation accRelation
= pRrelationSet
->getRelation(i
);
1873 if(accRelation
.RelationType
== 7)
1875 Sequence
< Reference
< XInterface
> > xTargets
= accRelation
.TargetSet
;
1876 return static_cast<XAccessible
*>(xTargets
[0].get());
1882 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_groupPosition(long __RPC_FAR
*groupLevel
,long __RPC_FAR
*similarItemsInGroup
,long __RPC_FAR
*positionInGroup
)
1886 ENTER_PROTECTED_BLOCK
1889 if(groupLevel
== nullptr || similarItemsInGroup
== nullptr || positionInGroup
== nullptr)
1891 return E_INVALIDARG
;
1894 if (!m_xAccessible
.is())
1897 Reference
<XAccessibleContext
> const pRContext
=
1898 m_xAccessible
->getAccessibleContext();
1901 long Role
= pRContext
->getAccessibleRole();
1904 *similarItemsInGroup
= 0;
1905 *positionInGroup
= 0;
1907 if (Role
!= AccessibleRole::DOCUMENT
&& Role
!= AccessibleRole::DOCUMENT_PRESENTATION
&&
1908 Role
!= AccessibleRole::DOCUMENT_SPREADSHEET
&& Role
!= AccessibleRole::DOCUMENT_TEXT
)
1910 Reference
< XAccessibleGroupPosition
> xGroupPosition( pRContext
, UNO_QUERY
);
1911 if ( xGroupPosition
.is() )
1913 Sequence
< sal_Int32
> rSeq
= xGroupPosition
->getGroupPosition( makeAny( pRContext
) );
1914 if (rSeq
.getLength() >= 3)
1916 *groupLevel
= rSeq
[0];
1917 *similarItemsInGroup
= rSeq
[1];
1918 *positionInGroup
= rSeq
[2];
1925 Reference
< XAccessible
> pParentAcc
= pRContext
->getAccessibleParent();
1926 if( !pParentAcc
.is() )
1931 Reference
<XAccessibleContext
> pRParentContext
= pParentAcc
->getAccessibleContext();
1933 if( Role
== RADIO_BUTTON
)
1937 Reference
<XAccessibleRelationSet
> pRrelationSet
= pRContext
->getAccessibleRelationSet();
1938 long nRel
= pRrelationSet
->getRelationCount();
1939 for(int i
=0 ; i
<nRel
; i
++)
1941 AccessibleRelation accRelation
= pRrelationSet
->getRelation(i
);
1942 if(accRelation
.RelationType
== 7)
1944 Sequence
< Reference
< XInterface
> > xTargets
= accRelation
.TargetSet
;
1946 Reference
<XInterface
> pRAcc
= xTargets
[0];
1947 for(int j
=0; j
<pRParentContext
->getAccessibleChildCount(); j
++)
1949 if( getTheParentOfMember(pRParentContext
->getAccessibleChild(j
).get())
1950 == static_cast<XAccessible
*>(pRAcc
.get()) &&
1951 pRParentContext
->getAccessibleChild(j
)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON
)
1953 if (pRParentContext
->getAccessibleChild(j
).get() == m_xAccessible
.get())
1959 *similarItemsInGroup
= number
;
1960 *positionInGroup
= index
;
1964 else if ( COMBO_BOX
== Role
)
1967 *similarItemsInGroup
= 0;
1968 *positionInGroup
= -1;
1970 long nCount
= pRContext
->getAccessibleChildCount();
1975 Reference
<XAccessible
> xList
=pRContext
->getAccessibleChild(1);
1980 Reference
<XAccessibleContext
> xListContext(xList
,UNO_QUERY
);
1981 if (!xListContext
.is())
1985 Reference
<XAccessibleSelection
> xListSel(xList
,UNO_QUERY
);
1990 *similarItemsInGroup
= xListContext
->getAccessibleChildCount();
1991 if (*similarItemsInGroup
> 0 )
1995 Reference
<XAccessible
> xChild
= xListSel
->getSelectedAccessibleChild(0);
1998 Reference
<XAccessibleContext
> xChildContext(xChild
,UNO_QUERY
);
1999 if (xChildContext
.is())
2001 *positionInGroup
=xChildContext
->getAccessibleIndexInParent() + 1 ;
2011 else if ( PAGE_TAB
== Role
)
2014 *similarItemsInGroup
= pRParentContext
->getAccessibleChildCount();
2016 if (*similarItemsInGroup
> 0 )
2018 *positionInGroup
=pRContext
->getAccessibleIndexInParent() + 1 ;
2022 *positionInGroup
= -1;
2028 BOOL isFound
= FALSE
;
2029 while( pParentAcc
.is() && !isFound
)
2032 pRParentContext
= pParentAcc
->getAccessibleContext();
2033 Role
= pRParentContext
->getAccessibleRole();
2034 if( (Role
== TREE
) || (Role
== LIST
) )
2036 pParentAcc
= pRParentContext
->getAccessibleParent();
2041 Reference
< XAccessible
> pTempAcc
= pRContext
->getAccessibleParent();
2042 pRParentContext
= pTempAcc
->getAccessibleContext();
2043 *groupLevel
= level
;
2044 *similarItemsInGroup
= pRParentContext
->getAccessibleChildCount();
2045 *positionInGroup
= pRContext
->getAccessibleIndexInParent() + 1;
2050 *similarItemsInGroup
= 0;
2051 *positionInGroup
= 0;
2055 LEAVE_PROTECTED_BLOCK
2058 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_extendedStates( long, BSTR __RPC_FAR
*__RPC_FAR
*, long __RPC_FAR
*)
2064 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_uniqueID(long __RPC_FAR
*uniqueID
)
2068 ENTER_PROTECTED_BLOCK
2071 if(uniqueID
== nullptr)
2073 return E_INVALIDARG
;
2075 *uniqueID
= m_dChildID
;
2078 LEAVE_PROTECTED_BLOCK
2081 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_windowHandle(HWND __RPC_FAR
*windowHandle
)
2085 ENTER_PROTECTED_BLOCK
2088 if(windowHandle
== nullptr)
2090 return E_INVALIDARG
;
2093 HWND nHwnd
= m_hwnd
;
2094 IAccessible
* pParent
= m_pIParent
;
2095 while((nHwnd
==nullptr) && pParent
)
2097 if (CMAccessible
* pChild
= dynamic_cast<CMAccessible
*>(pParent
))
2099 pParent
= pChild
->m_pIParent
;
2100 nHwnd
= pChild
->m_hwnd
;
2106 *windowHandle
= nHwnd
;
2109 LEAVE_PROTECTED_BLOCK
2113 * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
2114 * @param pXAcc, UNO XAccessible object point.
2115 * @return XAccessibleContext*, the context of the pXAcc.
2117 XAccessibleContext
* CMAccessible::GetContextByXAcc( XAccessible
* pXAcc
)
2119 Reference
< XAccessibleContext
> pRContext
;
2120 if( pXAcc
== nullptr)
2123 pRContext
= pXAcc
->getAccessibleContext();
2124 if( !pRContext
.is() )
2126 return pRContext
.get();
2130 * Return the member variable m_pXAccessibleSelection, instead of
2131 * get XAccessibleSelection according to XAccessibleContext because if so,it will
2132 * depend on the UNO implementation code,so when COM is created, put XAccessibleSelection
2133 * by bridge management system
2134 * @return XAccessibleSelection*, the selection of the current object.
2136 Reference
< XAccessibleSelection
> CMAccessible::GetSelection()
2138 if (!m_xAccessible
.is())
2140 Reference
<XAccessibleContext
> const pRContext
=
2141 m_xAccessible
->getAccessibleContext();
2144 Reference
< XAccessibleSelection
> pRSelection(pRContext
,UNO_QUERY
);
2151 * Select one XAccessible item, for accSelect implementation
2152 * @param pItem, the item should be selected.
2153 * @return S_OK if successful.
2155 HRESULT
CMAccessible::SelectChild(XAccessible
* pItem
)
2158 ENTER_PROTECTED_BLOCK
2160 XAccessibleContext
* pParentContext
= GetContextByXAcc(m_xAccessible
.get());
2161 XAccessibleContext
* pContext
= GetContextByXAcc( pItem
);
2162 if( pParentContext
== nullptr || pContext
== nullptr )
2165 Reference
< XAccessibleSelection
> pRSelection
= GetSelection();
2166 if( !pRSelection
.is() )
2168 long Index
= pContext
->getAccessibleIndexInParent();
2169 pRSelection
->selectAccessibleChild( Index
);
2172 LEAVE_PROTECTED_BLOCK
2176 * Deselect one XAccessible item, for accSelect implementation
2177 * @param pItem, the item should be deselected.
2178 * @return S_OK if successful.
2180 HRESULT
CMAccessible::DeSelectChild(XAccessible
* pItem
)
2183 ENTER_PROTECTED_BLOCK
2185 XAccessibleContext
* pParentContext
= GetContextByXAcc(m_xAccessible
.get());
2187 XAccessibleContext
* pContext
= GetContextByXAcc( pItem
);
2188 if( pParentContext
== nullptr || pContext
== nullptr )
2189 return E_INVALIDARG
;
2191 Reference
< XAccessibleSelection
> pRSelection
= GetSelection();
2192 if( !pRSelection
.is() )
2194 long Index
= pContext
->getAccessibleIndexInParent();
2195 pRSelection
->deselectAccessibleChild( Index
);
2199 LEAVE_PROTECTED_BLOCK
2203 * Select multiple XAccessible items,for implementation of accSelect
2204 * @param pItem, the items should be selected.
2205 * @param size, the size of the items.
2206 * @return S_OK if successful.
2208 HRESULT
CMAccessible::SelectMultipleChidren( XAccessible
** pItem
,int size
)
2211 ENTER_PROTECTED_BLOCK
2214 if(pItem
== nullptr)
2216 return E_INVALIDARG
;
2218 for(int index
= 0;index
< size
;index
++)
2220 SelectChild( pItem
[index
] );
2224 LEAVE_PROTECTED_BLOCK
2228 * Deselect multiple XAccessible items,for implementation of accSelect
2229 * @param pItem, the items should be selected.
2230 * @param size, the size of the items.
2231 * @return S_OK if successful.
2233 HRESULT
CMAccessible::DeSelectMultipleChildren( XAccessible
** pItem
,int size
)
2236 ENTER_PROTECTED_BLOCK
2239 if(pItem
== nullptr)
2241 return E_INVALIDARG
;
2243 for(int index
= 0;index
< size
;index
++)
2245 DeSelectChild( pItem
[index
] );
2249 LEAVE_PROTECTED_BLOCK
2253 * When COM is created, UNO set XAccessible pointer to it
2254 * in order to COM can operate UNO information
2255 * @param pXAcc, the XAccessible object of current object.
2256 * @return S_OK if successful.
2258 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::SetXAccessible(hyper pXAcc
)
2260 // internal IMAccessible - no mutex meeded
2262 m_xAccessible
= reinterpret_cast<XAccessible
*>(pXAcc
);
2263 m_pEnumVar
->PutSelection(/*XAccessibleSelection*/
2264 reinterpret_cast<hyper
>(m_xAccessible
.get()));
2266 m_xContext
= m_xAccessible
->getAccessibleContext();
2272 * accSelect method has many optional flags, needs to process comprehensively
2273 * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
2274 * The implementation of this flag is a little trouble-shooting,so we also
2275 * do not implement it now
2276 * @param flagsSelect, the selection flag of the select action.
2277 * @param varChild, the child object pointer of current action.
2278 * @return S_OK if successful.
2280 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::accSelect(long flagsSelect
, VARIANT varChild
)
2284 ENTER_PROTECTED_BLOCK
2286 if( (flagsSelect
&SELFLAG_ADDSELECTION
) &&
2287 (SELFLAG_REMOVESELECTION
&flagsSelect
) )
2288 return E_INVALIDARG
;
2290 if ( (flagsSelect
&SELFLAG_TAKESELECTION
) &&
2292 (flagsSelect
&SELFLAG_ADDSELECTION
) ||
2293 (flagsSelect
&SELFLAG_REMOVESELECTION
) ||
2294 (flagsSelect
&SELFLAG_EXTENDSELECTION
)
2297 return E_INVALIDARG
;
2299 if ( varChild
.vt
!= VT_I4
)
2300 return E_INVALIDARG
;
2302 IMAccessible
* pSelectAcc
;
2303 if( varChild
.lVal
== CHILDID_SELF
)
2306 pSelectAcc
->AddRef();
2310 pSelectAcc
= GetChildInterface(varChild
.lVal
);
2313 if( pSelectAcc
== nullptr )
2314 return E_INVALIDARG
;
2316 if( flagsSelect
&SELFLAG_TAKEFOCUS
)
2319 XAccessible
* pTempUNO
;
2322 pSelectAcc
->GetUNOInterface(&nHyper
);
2324 if( pTempUNO
== nullptr )
2327 Reference
<XAccessibleContext
> pRContext
= pTempUNO
->getAccessibleContext();
2328 Reference
< XAccessibleComponent
> pRComponent(pRContext
,UNO_QUERY
);
2329 Reference
< XAccessible
> pRParentXAcc
= pRContext
->getAccessibleParent();
2330 Reference
< XAccessibleContext
> pRParentContext
= pRParentXAcc
->getAccessibleContext();
2331 Reference
< XAccessibleComponent
> pRParentComponent(pRParentContext
,UNO_QUERY
);
2332 Reference
< XAccessibleSelection
> pRParentSelection(pRParentContext
,UNO_QUERY
);
2335 pRComponent
->grabFocus();
2337 if( flagsSelect
& SELFLAG_TAKESELECTION
)
2339 pRParentSelection
->clearAccessibleSelection();
2340 pRParentSelection
->selectAccessibleChild( pRContext
->getAccessibleIndexInParent() );
2343 if( flagsSelect
& SELFLAG_ADDSELECTION
)
2345 pRParentSelection
->selectAccessibleChild( pRContext
->getAccessibleIndexInParent() );
2348 if( flagsSelect
& SELFLAG_REMOVESELECTION
)
2350 pRParentSelection
->deselectAccessibleChild( pRContext
->getAccessibleIndexInParent() );
2353 if( flagsSelect
& SELFLAG_EXTENDSELECTION
)
2355 long indexInParrent
= pRContext
->getAccessibleIndexInParent();
2357 if( pRParentSelection
->isAccessibleChildSelected( indexInParrent
+ 1 ) ||
2358 pRParentSelection
->isAccessibleChildSelected( indexInParrent
- 1 ) )
2360 pRParentSelection
->selectAccessibleChild( indexInParrent
);
2366 pSelectAcc
->Release();
2369 LEAVE_PROTECTED_BLOCK
2373 * Return XAccessible interface pointer when needed
2374 * @param pXAcc, [in, out] the Uno interface of the current object.
2375 * @return S_OK if successful.
2377 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::GetUNOInterface(hyper
* pXAcc
)
2379 // internal IMAccessible - no mutex meeded
2381 if(pXAcc
== nullptr)
2382 return E_INVALIDARG
;
2384 *pXAcc
= reinterpret_cast<hyper
>(m_xAccessible
.get());
2389 * Helper method for Implementation of get_accDefaultAction
2390 * @param pAction, the default action point of the current object.
2391 * @return S_OK if successful.
2393 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::SetDefaultAction(hyper pAction
)
2395 // internal IMAccessible - no mutex meeded
2397 m_xAction
= reinterpret_cast<XAccessibleAction
*>(pAction
);
2402 * This method is called when AT open some UI elements initially
2403 * the UI element takes the default action defined here
2404 * @param varChild, the child id of the defaultaction.
2405 * @param pszDefaultAction,[in/out] the description of the current action.
2406 * @return S_OK if successful.
2408 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CMAccessible::get_accDefaultAction(VARIANT varChild
, BSTR
*pszDefaultAction
)
2412 ENTER_PROTECTED_BLOCK
2415 if(pszDefaultAction
== nullptr)
2417 return E_INVALIDARG
;
2419 if(varChild
.vt
==VT_I4
)
2421 if(varChild
.lVal
==CHILDID_SELF
)
2423 if (!m_xAction
.is())
2424 return DISP_E_MEMBERNOTFOUND
;
2425 SAFE_SYSFREESTRING(*pszDefaultAction
);
2426 *pszDefaultAction
= SysAllocString(m_pszActionDescription
);
2430 long lVal
= varChild
.lVal
;
2431 varChild
.lVal
= CHILDID_SELF
;
2432 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
2435 return pChild
->get_accDefaultAction(varChild
,pszDefaultAction
);
2439 LEAVE_PROTECTED_BLOCK
2443 * AT call this method to operate application
2444 * @param varChild, the child id of the action object.
2445 * @return S_OK if successful.
2447 COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE
CMAccessible::accDoDefaultAction(VARIANT varChild
)
2451 ENTER_PROTECTED_BLOCK
2453 if( varChild
.vt
!= VT_I4
)
2454 return E_INVALIDARG
;
2455 if (!m_xAction
.is())
2457 if (m_xAction
->getAccessibleActionCount() == 0)
2460 if(varChild
.lVal
==CHILDID_SELF
)
2462 if (m_xAction
->getAccessibleActionCount() > 0)
2463 m_xAction
->doAccessibleAction(0);
2467 long lVal
= varChild
.lVal
;
2468 varChild
.lVal
= CHILDID_SELF
;
2469 IMAccessible
*pChild
= this->GetChildInterface(lVal
);
2472 return pChild
->accDoDefaultAction( varChild
);
2474 LEAVE_PROTECTED_BLOCK
2478 * UNO set description information for action to COM.
2479 * @param szAction, the action description of the current object.
2480 * @return S_OK if successful.
2482 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Put_ActionDescription( const OLECHAR
* szAction
)
2484 // internal IMAccessible - no mutex meeded
2486 ENTER_PROTECTED_BLOCK
2489 if(szAction
== nullptr)
2491 return E_INVALIDARG
;
2493 SAFE_SYSFREESTRING(m_pszActionDescription
);
2494 m_pszActionDescription
= SysAllocString( szAction
);
2497 LEAVE_PROTECTED_BLOCK
2500 BOOL
CMAccessible::GetXInterfaceFromXAccessible(XAccessible
* pXAcc
, XInterface
** ppXI
, int index
)
2502 Reference
< XAccessibleContext
> pRContext
;
2507 QUERYXINTERFACE(AccessibleComponent
)
2510 QUERYXINTERFACE(AccessibleText
)
2512 case XI_EDITABLETEXT
:
2513 QUERYXINTERFACE(AccessibleEditableText
)
2516 QUERYXINTERFACE(AccessibleTable
)
2519 QUERYXINTERFACE(AccessibleSelection
)
2521 case XI_EXTENDEDCOMP
:
2522 QUERYXINTERFACE(AccessibleExtendedComponent
)
2525 QUERYXINTERFACE(AccessibleKeyBinding
)
2528 QUERYXINTERFACE(AccessibleAction
)
2531 QUERYXINTERFACE(AccessibleValue
)
2534 QUERYXINTERFACE(AccessibleHypertext
)
2537 QUERYXINTERFACE(AccessibleHyperlink
)
2540 QUERYXINTERFACE(AccessibleImage
)
2549 template<typename T
> static HRESULT
2550 createAggInstance(CMAccessible
&rOuter
, void ** ppvObject
)
2552 // Note: CComAggObject has special handling for IUnknown - must
2553 // query for that when creating it! Otherwise we get a T member of it
2554 // which will redirect QueryInterface back to CMAccessible infinitely.
2555 // (CComAggObject has its own ref-count too which is not a problem
2556 // since it is inserted in m_containedObjects.)
2557 return CComCreator
< CComAggObject
<T
> >::CreateInstance(
2558 rOuter
.GetControllingUnknown(), IID_IUnknown
, ppvObject
);
2561 typedef HRESULT (AggCreatorFunc
)(CMAccessible
&, void **);
2566 AggCreatorFunc
* pfnCreateInstance
;
2570 static AggMapEntry g_CMAccessible_AggMap
[] = {
2571 { &IID_IAccessibleComponent
, &createAggInstance
<CAccComponent
>, XI_COMPONENT
},
2572 { &IID_IAccessibleText
, &createAggInstance
<CAccText
>, XI_TEXT
},
2573 { &IID_IAccessibleEditableText
, &createAggInstance
<CAccEditableText
>, XI_EDITABLETEXT
},
2574 { &IID_IAccessibleImage
, &createAggInstance
<CAccImage
>, XI_IMAGE
},
2575 { &IID_IAccessibleTable
, &createAggInstance
<CAccTable
>, XI_TABLE
},
2576 { &IID_IAccessibleAction
, &createAggInstance
<CAccAction
>, XI_ACTION
},
2577 { &IID_IAccessibleValue
, &createAggInstance
<CAccValue
>, XI_VALUE
},
2578 { &IID_IAccessibleHypertext
, &createAggInstance
<CAccHypertext
>, XI_HYPERTEXT
},
2579 { &IID_IAccessibleHyperlink
, &createAggInstance
<CAccHyperLink
>, XI_HYPERLINK
},
2580 { nullptr, nullptr, 0 },
2584 HRESULT WINAPI
CMAccessible::SmartQI(void* /*pv*/, REFIID iid
, void** ppvObject
)
2586 ENTER_PROTECTED_BLOCK
2589 if (InlineIsEqualGUID(iid
,IID_IAccIdentity
) ||
2590 InlineIsEqualGUID(iid
,IID_IStdMarshalInfo
) ||
2591 InlineIsEqualGUID(iid
,IID_IMarshal
) ||
2592 InlineIsEqualGUID(iid
,IID_IExternalConnection
)||
2593 InlineIsEqualGUID(iid
,IID_IOleWindow
))
2598 AggMapEntry
* pMap
= &g_CMAccessible_AggMap
[0];
2599 while(pMap
&& pMap
->piid
)
2601 if (InlineIsEqualGUID(iid
, *pMap
->piid
))
2605 XInterface
* pXI
= nullptr;
2606 BOOL bFound
= GetXInterfaceFromXAccessible(m_xAccessible
.get(),
2607 &pXI
, pMap
->XIFIndex
);
2613 XGUIDToComObjHash::iterator pIndTemp
= m_containedObjects
.find( iid
);
2614 if ( pIndTemp
!= m_containedObjects
.end() )
2616 return pIndTemp
->second
.p
->QueryInterface( iid
, ppvObject
);
2620 HRESULT hr
= pMap
->pfnCreateInstance(*this, ppvObject
);
2624 m_containedObjects
.emplace(*pMap
->piid
, static_cast<IUnknown
*>(*ppvObject
));
2625 IUNOXWrapper
* wrapper
= nullptr;
2626 static_cast<IUnknown
*>(*ppvObject
)->QueryInterface(IID_IUNOXWrapper
, reinterpret_cast<void**>(&wrapper
));
2629 wrapper
->put_XInterface(
2630 reinterpret_cast<hyper
>(m_xAccessible
.get()));
2642 LEAVE_PROTECTED_BLOCK
2646 CMAccessible::get_IAccessibleFromXAccessible(XAccessible
* pXAcc
, IAccessible
**ppIA
)
2659 isGet
= g_pAgent
->GetIAccessibleFromXAccessible(pXAcc
, ppIA
);
2673 OUString
CMAccessible::get_StringFromAny(Any
const & pAny
)
2675 switch(pAny
.getValueTypeClass())
2677 case TypeClass_CHAR
:
2681 return OUString::number(val
);
2683 case TypeClass_BOOLEAN
:
2687 return OUString::number(int(val
));
2689 case TypeClass_BYTE
:
2693 return OUString::number(val
);
2695 case TypeClass_SHORT
:
2699 return OUString::number(val
);
2701 case TypeClass_UNSIGNED_SHORT
:
2705 return OUString::number(val
);
2707 case TypeClass_LONG
:
2711 return OUString::number(val
);
2713 case TypeClass_UNSIGNED_LONG
:
2717 return OUString::number(val
);
2719 case TypeClass_FLOAT
:
2723 return OUString::number(val
);
2725 case TypeClass_DOUBLE
:
2729 return OUString::number(val
);
2731 case TypeClass_STRING
:
2737 case TypeClass_SEQUENCE
:
2739 if(pAny
.getValueType() == cppu::UnoType
<Sequence
< OUString
>>::get())
2741 Sequence
< OUString
> val
;
2744 OUStringBuffer pString
;
2746 int count
= val
.getLength();
2748 for( int iIndex
= 0;iIndex
< count
;iIndex
++ )
2750 pString
.append(val
[iIndex
]);
2752 return pString
.makeStringAndClear();
2754 else if (pAny
.getValueType() == cppu::UnoType
<Sequence
< css::style::TabStop
>>::get())
2756 Sequence
< css::style::TabStop
> val
;
2758 int count
= val
.getLength();
2761 for( int iIndex
= 0;iIndex
< count
;iIndex
++ )
2763 css::style::TabStop sigleVal
= val
[iIndex
];
2765 buf
.append("Position=");
2766 buf
.append(sigleVal
.Position
);
2767 buf
.append(",TabAlign=");
2768 buf
.append(sal_Int32(sigleVal
.Alignment
));
2771 buf
.append("DecimalChar=");
2772 if(sigleVal
.DecimalChar
==';' || sigleVal
.DecimalChar
== ':' || sigleVal
.DecimalChar
== ',' ||
2773 sigleVal
.DecimalChar
== '=' || sigleVal
.DecimalChar
== '\\')
2775 buf
.append(sigleVal
.DecimalChar
);
2778 buf
.append("FillChar=");
2779 if(sigleVal
.FillChar
==';' || sigleVal
.FillChar
== ':' || sigleVal
.FillChar
== ',' ||
2780 sigleVal
.FillChar
== '=' || sigleVal
.FillChar
== '\\')
2782 buf
.append(sigleVal
.FillChar
);
2785 return buf
.makeStringAndClear();
2789 case TypeClass_ENUM
:
2791 if (pAny
.getValueType() == cppu::UnoType
<css::awt::FontSlant
>::get())
2793 css::awt::FontSlant val
;
2795 return OUString::number(sal_Int32(val
));
2799 case TypeClass_STRUCT
:
2801 if (pAny
.getValueType() == cppu::UnoType
<css::style::LineSpacing
>::get())
2803 css::style::LineSpacing val
;
2805 return "Mode=" + OUString::number(val
.Mode
) + ",Height="
2806 + OUString::number(val
.Height
) + ",";
2808 else if (pAny
.getValueType() == cppu::UnoType
<css::accessibility::TextSegment
>::get())
2810 css::accessibility::TextSegment val
;
2812 return val
.SegmentText
;
2816 case TypeClass_VOID
:
2817 case TypeClass_HYPER
:
2818 case TypeClass_UNSIGNED_HYPER
:
2819 case TypeClass_TYPE
:
2821 case TypeClass_TYPEDEF
:
2822 case TypeClass_EXCEPTION
:
2823 case TypeClass_INTERFACE
:
2824 case TypeClass_SERVICE
:
2825 case TypeClass_MODULE
:
2826 case TypeClass_INTERFACE_METHOD
:
2827 case TypeClass_INTERFACE_ATTRIBUTE
:
2828 case TypeClass_UNKNOWN
:
2829 case TypeClass_PROPERTY
:
2830 case TypeClass_CONSTANT
:
2831 case TypeClass_CONSTANTS
:
2832 case TypeClass_SINGLETON
:
2840 OUString
CMAccessible::get_String4Numbering(const Any
& pAny
, sal_Int16 numberingLevel
,const OUString
& numberingPrefix
)
2842 Reference
< css::container::XIndexReplace
> pXIndex
;
2843 if((pAny
>>=pXIndex
) && (numberingLevel
!=-1))//numbering level is -1,means invalid value
2845 Any aAny
= pXIndex
->getByIndex(numberingLevel
);
2846 Sequence
< css::beans::PropertyValue
> aProps
;
2848 const css::beans::PropertyValue
* pPropArray
= aProps
.getConstArray();
2849 sal_Int32 nCount
= aProps
.getLength();
2850 OUStringBuffer
buf("Numbering:NumberingLevel=");
2851 buf
.append(sal_Int32(numberingLevel
));
2853 for( sal_Int32 i
=0; i
<nCount
; i
++ )
2855 css::beans::PropertyValue rProp
= pPropArray
[i
];
2856 if( (rProp
.Name
== "BulletChar" ) ||
2857 (rProp
.Name
== "NumberingType" ))
2859 buf
.append(rProp
.Name
);
2861 auto const pTemp
= CMAccessible::get_StringFromAny(rProp
.Value
);
2865 if(rProp
.Name
== "NumberingType")
2867 if(numberingPrefix
.getLength()!=0)
2869 buf
.append("NumberingPrefix=");
2870 buf
.append(numberingPrefix
);
2875 return buf
.makeStringAndClear();
2878 //Because now have three types numbering level:
2879 //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
2880 //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
2881 //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
2882 // IAText:numberinglevel base on 0, but TOC's level base on 1,
2883 // so NumberingLevel value will be decreased 1 in bridge code.
2884 else if(numberingLevel
>0)
2886 return "Numbering:NumberingLevel=" + OUString::number(numberingLevel
-1) + ",NumberingType=4,NumberingPrefix=,";
2890 return "Numbering:";
2894 void CMAccessible::ConvertAnyToVariant(const css::uno::Any
&rAnyVal
, VARIANT
*pvData
)
2896 if(rAnyVal
.hasValue())
2898 // Clear VARIANT variable.
2899 VariantClear(pvData
);
2901 // Set value according to value type.
2902 switch(rAnyVal
.getValueTypeClass())
2904 case TypeClass_CHAR
:
2905 pvData
->vt
= VT_UI1
;
2906 memcpy(&pvData
->bVal
, rAnyVal
.getValue(), sizeof(sal_Char
));
2909 case TypeClass_BOOLEAN
:
2911 bool bBoolean(false);
2912 rAnyVal
>>= bBoolean
;
2913 pvData
->vt
= VT_BOOL
;
2914 pvData
->boolVal
= VARIANT_BOOL(bBoolean
); // boolVal is a VARIANT_BOOL, a 16bit field
2917 case TypeClass_BYTE
:
2918 pvData
->vt
= VT_UI1
;
2919 memcpy(&pvData
->bVal
, rAnyVal
.getValue(), sizeof(sal_Int8
));
2922 case TypeClass_SHORT
:
2924 memcpy(&pvData
->iVal
, rAnyVal
.getValue(), sizeof(sal_Int16
));
2927 case TypeClass_UNSIGNED_SHORT
:
2929 memcpy(&pvData
->iVal
, rAnyVal
.getValue(), sizeof(sal_uInt16
));
2932 case TypeClass_LONG
:
2934 memcpy(&pvData
->lVal
, rAnyVal
.getValue(), sizeof(sal_Int32
));
2937 case TypeClass_UNSIGNED_LONG
:
2939 memcpy(&pvData
->lVal
, rAnyVal
.getValue(), sizeof(sal_uInt32
));
2942 case TypeClass_FLOAT
:
2944 memcpy(&pvData
->fltVal
, rAnyVal
.getValue(), sizeof(float));
2947 case TypeClass_DOUBLE
:
2949 memcpy(&pvData
->dblVal
, rAnyVal
.getValue(), sizeof(double));
2952 case TypeClass_STRING
:
2954 pvData
->vt
= VT_BSTR
;
2957 pvData
->bstrVal
= SysAllocString(o3tl::toW(val
.getStr()));
2961 case TypeClass_VOID
:
2962 case TypeClass_HYPER
:
2963 case TypeClass_UNSIGNED_HYPER
:
2964 case TypeClass_TYPE
:
2966 case TypeClass_ENUM
:
2967 case TypeClass_TYPEDEF
:
2968 case TypeClass_STRUCT
:
2969 case TypeClass_EXCEPTION
:
2970 case TypeClass_SEQUENCE
:
2971 case TypeClass_INTERFACE
:
2973 Reference
< XAccessible
> pXAcc
;
2974 if(rAnyVal
>>= pXAcc
)
2978 IAccessible
* pIAcc
= nullptr;
2979 get_IAccessibleFromXAccessible(pXAcc
.get(), &pIAcc
);
2980 if(pIAcc
== nullptr)
2982 Reference
< XAccessibleContext
> pXAccContext
= pXAcc
->getAccessibleContext();
2983 g_pAgent
->InsertAccObj(pXAcc
.get(),pXAccContext
->getAccessibleParent().get());
2984 get_IAccessibleFromXAccessible(pXAcc
.get(), &pIAcc
);
2990 pvData
->vt
= VT_UNKNOWN
;
2991 pvData
->pdispVal
= static_cast<IAccessible2
*>(pIAcc
);
2998 case TypeClass_SERVICE
:
2999 case TypeClass_MODULE
:
3000 case TypeClass_INTERFACE_METHOD
:
3001 case TypeClass_INTERFACE_ATTRIBUTE
:
3002 case TypeClass_UNKNOWN
:
3003 case TypeClass_PROPERTY
:
3004 case TypeClass_CONSTANT
:
3005 case TypeClass_CONSTANTS
:
3006 case TypeClass_SINGLETON
:
3007 case TypeClass::TypeClass_MAKE_FIXED_SIZE
:
3008 // Output the type string, if there is other uno value type.
3009 pvData
->vt
= VT_BSTR
;
3010 pvData
->bstrVal
= SysAllocString(o3tl::toW(rAnyVal
.getValueTypeName().getStr()));
3019 VariantClear(pvData
);
3023 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::Get_XAccChildID(long* childID
)
3025 // internal IMAccessible - no mutex meeded
3027 if(childID
== nullptr)
3031 *childID
= m_dChildID
;
3035 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_states(AccessibleStates __RPC_FAR
*states
)
3039 ENTER_PROTECTED_BLOCK
3042 if (!m_xContext
.is())
3045 Reference
<XAccessibleStateSet
> const pRStateSet
=
3046 m_xContext
.get()->getAccessibleStateSet();
3047 if(!pRStateSet
.is())
3051 Sequence
<short> pStates
= pRStateSet
->getStates();
3054 long count
= pStates
.getLength() ;
3056 for( int i
= 0; i
< count
; i
++ )
3058 for( std::size_t j
= 0; j
< SAL_N_ELEMENTS(UNO_STATES
); j
++ )
3060 if( pStates
[i
] == UNO_STATES
[j
] )
3062 *states
|= IA2_STATES
[j
];
3070 LEAVE_PROTECTED_BLOCK
3073 // return the UNO roles
3074 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_extendedRole( BSTR __RPC_FAR
* )
3079 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_localizedExtendedRole( BSTR __RPC_FAR
* )
3084 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_nExtendedStates( long __RPC_FAR
* )
3090 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_localizedExtendedStates( long, BSTR __RPC_FAR
*__RPC_FAR
*, long __RPC_FAR
*)
3096 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_indexInParent( long __RPC_FAR
*accParentIndex
)
3098 ENTER_PROTECTED_BLOCK
3101 if(accParentIndex
== nullptr)
3102 return E_INVALIDARG
;
3104 if (!m_xContext
.is())
3107 *accParentIndex
= m_xContext
.get()->getAccessibleIndexInParent();
3111 LEAVE_PROTECTED_BLOCK
3113 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_locale( IA2Locale __RPC_FAR
*locale
)
3115 ENTER_PROTECTED_BLOCK
3117 if(locale
== nullptr)
3118 return E_INVALIDARG
;
3120 if (!m_xContext
.is())
3123 css::lang::Locale unoLoc
= m_xContext
.get()->getLocale();
3124 locale
->language
= SysAllocString(o3tl::toW(unoLoc
.Language
.getStr()));
3125 locale
->country
= SysAllocString(o3tl::toW(unoLoc
.Country
.getStr()));
3126 locale
->variant
= SysAllocString(o3tl::toW(unoLoc
.Variant
.getStr()));
3130 LEAVE_PROTECTED_BLOCK
3133 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_appName( BSTR __RPC_FAR
*name
)
3137 ENTER_PROTECTED_BLOCK
3140 return E_INVALIDARG
;
3142 *name
= SysAllocString(OLESTR("Hannover"));
3144 LEAVE_PROTECTED_BLOCK
3146 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_appVersion(BSTR __RPC_FAR
*version
)
3150 ENTER_PROTECTED_BLOCK
3152 if(version
== nullptr)
3153 return E_INVALIDARG
;
3154 *version
=SysAllocString(OLESTR("3.0"));
3156 LEAVE_PROTECTED_BLOCK
3158 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_toolkitName(BSTR __RPC_FAR
*name
)
3162 ENTER_PROTECTED_BLOCK
3165 return E_INVALIDARG
;
3166 *name
= SysAllocString(OLESTR(" "));
3168 LEAVE_PROTECTED_BLOCK
3170 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible:: get_toolkitVersion(BSTR __RPC_FAR
*version
)
3174 ENTER_PROTECTED_BLOCK
3176 if(version
== nullptr)
3177 return E_INVALIDARG
;
3178 *version
= SysAllocString(OLESTR(" "));
3180 LEAVE_PROTECTED_BLOCK
3184 COM_DECLSPEC_NOTHROW STDMETHODIMP
CMAccessible::get_attributes(/*[out]*/ BSTR
*pAttr
)
3188 ENTER_PROTECTED_BLOCK
3191 if (!m_xAccessible
.is())
3194 Reference
<XAccessibleContext
> pRContext
= m_xAccessible
->getAccessibleContext();
3195 if( !pRContext
.is() )
3199 Reference
<XAccessibleExtendedAttributes
> pRXI(pRContext
,UNO_QUERY
);
3204 css::uno::Reference
<css::accessibility::XAccessibleExtendedAttributes
> pRXAttr
;
3205 pRXAttr
= pRXI
.get();
3206 css::uno::Any anyVal
= pRXAttr
->getExtendedAttributes();
3212 SAFE_SYSFREESTRING(*pAttr
);
3213 *pAttr
= SysAllocString(o3tl::toW(val
.getStr()));
3217 LEAVE_PROTECTED_BLOCK
3220 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */