diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /winaccessibility/source/service/AccObject.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'winaccessibility/source/service/AccObject.cxx')
-rw-r--r-- | winaccessibility/source/service/AccObject.cxx | 1128 |
1 files changed, 1128 insertions, 0 deletions
diff --git a/winaccessibility/source/service/AccObject.cxx b/winaccessibility/source/service/AccObject.cxx new file mode 100644 index 000000000..d2862577f --- /dev/null +++ b/winaccessibility/source/service/AccObject.cxx @@ -0,0 +1,1128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/XAccessibleValue.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleText.hpp> + +#include <o3tl/char16_t2wchar_t.hxx> +#include <o3tl/safeint.hxx> + +#include <stdlib.h> +#include <memory.h> +#include <stdio.h> +#include <algorithm> +#include <assert.h> + +#include <AccObject.hxx> +#include <AccEventListener.hxx> + +#if defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra-tokens" + // "#endif !_MIDL_USE_GUIDDEF_" in midl-generated code +#endif +#include <UAccCOM_i.c> +#if defined __clang__ +#pragma clang diagnostic pop +#endif + +using namespace com::sun::star::uno; +using namespace com::sun::star::accessibility; +using namespace com::sun::star::accessibility::AccessibleRole; +using namespace com::sun::star::accessibility::AccessibleStateType; + +//Role mapping table,left side is UNO role, right side is MSAA role +const short ROLE_TABLE[][2] = + { + {UNKNOWN, IA2_ROLE_UNKNOWN}, + {ALERT , ROLE_SYSTEM_DIALOG}, + {COLUMN_HEADER , ROLE_SYSTEM_COLUMNHEADER}, + //{CANVAS , ROLE_SYSTEM_CLIENT}, + {CANVAS , IA2_ROLE_CANVAS}, + {CHECK_BOX , ROLE_SYSTEM_CHECKBUTTON}, + {CHECK_MENU_ITEM , IA2_ROLE_CHECK_MENU_ITEM}, + {COLOR_CHOOSER, IA2_ROLE_COLOR_CHOOSER}, + {COMBO_BOX , ROLE_SYSTEM_COMBOBOX}, + {DATE_EDITOR , IA2_ROLE_DATE_EDITOR}, + {DESKTOP_ICON , IA2_ROLE_DESKTOP_ICON}, + {DESKTOP_PANE, IA2_ROLE_DESKTOP_PANE}, + {DIRECTORY_PANE, IA2_ROLE_DIRECTORY_PANE}, + {DIALOG, ROLE_SYSTEM_DIALOG}, + {DOCUMENT, ROLE_SYSTEM_DOCUMENT}, + {EMBEDDED_OBJECT , IA2_ROLE_EMBEDDED_OBJECT }, + {END_NOTE , IA2_ROLE_ENDNOTE }, + {FILE_CHOOSER , IA2_ROLE_FILE_CHOOSER }, + {FILLER, ROLE_SYSTEM_WHITESPACE}, + {FONT_CHOOSER, IA2_ROLE_FONT_CHOOSER}, + {FOOTER, IA2_ROLE_FOOTER}, + {FOOTNOTE, IA2_ROLE_FOOTNOTE}, + //{FRAME, IA2_ROLE_FRAME}, + {FRAME, ROLE_SYSTEM_DIALOG}, + {GLASS_PANE , IA2_ROLE_GLASS_PANE}, + {GRAPHIC , ROLE_SYSTEM_GRAPHIC}, + {GROUP_BOX, ROLE_SYSTEM_GROUPING}, + {HEADER , IA2_ROLE_HEADER}, + {HEADING , IA2_ROLE_HEADING}, + {HYPER_LINK , ROLE_SYSTEM_TEXT}, + {ICON , IA2_ROLE_ICON}, + {INTERNAL_FRAME, IA2_ROLE_INTERNAL_FRAME}, + {LABEL, ROLE_SYSTEM_STATICTEXT}, + {LAYERED_PANE , IA2_ROLE_LAYERED_PANE}, + {LIST , ROLE_SYSTEM_LIST}, + {LIST_ITEM , ROLE_SYSTEM_LISTITEM}, + //{MENU , ROLE_SYSTEM_MENUPOPUP}, + {MENU, ROLE_SYSTEM_MENUITEM}, + {MENU_BAR, ROLE_SYSTEM_MENUBAR}, + {MENU_ITEM, ROLE_SYSTEM_MENUITEM}, + {OPTION_PANE , IA2_ROLE_OPTION_PANE}, + {PAGE_TAB, ROLE_SYSTEM_PAGETAB}, + {PAGE_TAB_LIST, ROLE_SYSTEM_PAGETABLIST}, + {PANEL, IA2_ROLE_OPTION_PANE}, + {PARAGRAPH, IA2_ROLE_PARAGRAPH}, + {PASSWORD_TEXT, ROLE_SYSTEM_TEXT}, + {POPUP_MENU, ROLE_SYSTEM_MENUPOPUP}, + {PUSH_BUTTON, ROLE_SYSTEM_PUSHBUTTON}, + {PROGRESS_BAR, ROLE_SYSTEM_PROGRESSBAR}, + {RADIO_BUTTON, ROLE_SYSTEM_RADIOBUTTON}, + {RADIO_MENU_ITEM, IA2_ROLE_RADIO_MENU_ITEM}, + {ROW_HEADER , ROLE_SYSTEM_ROWHEADER}, + {ROOT_PANE, IA2_ROLE_ROOT_PANE}, + {SCROLL_BAR , ROLE_SYSTEM_SCROLLBAR}, + {SCROLL_PANE , IA2_ROLE_SCROLL_PANE}, + {SHAPE, IA2_ROLE_SHAPE}, + {SEPARATOR , ROLE_SYSTEM_SEPARATOR}, + {SLIDER , ROLE_SYSTEM_SLIDER}, + {SPIN_BOX , ROLE_SYSTEM_SPINBUTTON}, + {SPLIT_PANE, IA2_ROLE_SPLIT_PANE}, + {STATUS_BAR, ROLE_SYSTEM_STATUSBAR}, + {TABLE, ROLE_SYSTEM_TABLE}, + {TABLE_CELL , ROLE_SYSTEM_CELL}, + {TEXT, ROLE_SYSTEM_TEXT}, + {TEXT_FRAME , IA2_ROLE_TEXT_FRAME}, + //for change toggle button to push button for jaws + {TOGGLE_BUTTON, ROLE_SYSTEM_PUSHBUTTON}, + + {TOOL_BAR, ROLE_SYSTEM_TOOLBAR}, + {TOOL_TIP, ROLE_SYSTEM_TOOLTIP}, + {TREE , ROLE_SYSTEM_OUTLINE}, + {VIEW_PORT , IA2_ROLE_VIEW_PORT}, + {WINDOW, ROLE_SYSTEM_WINDOW}, + {BUTTON_DROPDOWN, ROLE_SYSTEM_BUTTONDROPDOWN}, + {BUTTON_MENU, ROLE_SYSTEM_BUTTONMENU}, + {CAPTION, IA2_ROLE_CAPTION}, + {CHART, IA2_ROLE_SHAPE}, + {EDIT_BAR, IA2_ROLE_EDITBAR}, + {FORM, IA2_ROLE_FORM}, + {IMAGE_MAP , IA2_ROLE_IMAGE_MAP}, + {NOTE, IA2_ROLE_NOTE}, + {PAGE, IA2_ROLE_PAGE}, + {RULER , IA2_ROLE_RULER}, + {SECTION, IA2_ROLE_SECTION}, + {TREE_ITEM , ROLE_SYSTEM_OUTLINEITEM}, + {TREE_TABLE, ROLE_SYSTEM_OUTLINE}, + {COMMENT, IA2_ROLE_TEXT_FRAME }, + {COMMENT_END, IA2_ROLE_TEXT_FRAME }, + {DOCUMENT_PRESENTATION, ROLE_SYSTEM_DOCUMENT }, + {DOCUMENT_SPREADSHEET, ROLE_SYSTEM_DOCUMENT }, + {DOCUMENT_TEXT, ROLE_SYSTEM_DOCUMENT }, + {STATIC, ROLE_SYSTEM_STATICTEXT } + }; + + +/** + * Constructor. + * @param pXAcc Uno XAccessible interface of control. + * @param Agent The agent kept in all listeners,it's the sole interface by which + * listener communicate with windows manager. + * @param listener listener that registers in UNO system. + * @return. + */ +AccObject::AccObject(XAccessible* pAcc, AccObjectManagerAgent* pAgent, + AccEventListener* pListener) : + m_resID (0), + m_pParantID (nullptr), + m_pIMAcc (nullptr), + m_pParentObj(nullptr), + m_pListener (pListener), + m_xAccRef( pAcc ) +{ + ImplInitializeCreateObj(); + + m_xAccContextRef = m_xAccRef->getAccessibleContext(); + m_xAccActionRef.set(m_xAccContextRef,UNO_QUERY); + m_accRole = m_xAccContextRef -> getAccessibleRole(); + if( m_pIMAcc ) + { + m_pIMAcc->SetXAccessible(reinterpret_cast<hyper>(m_xAccRef.get())); + m_pIMAcc->Put_XAccAgent(reinterpret_cast<hyper>(pAgent)); + m_pIMAcc->SetDefaultAction(reinterpret_cast<hyper>(m_xAccActionRef.get())); + } +} +/** + * Destructor. + * @param + * @return + */ +AccObject::~AccObject() +{ + m_pIMAcc = nullptr; + m_xAccRef = nullptr; + m_xAccActionRef = nullptr; + m_xAccContextRef = nullptr; +} + + +/** + * Insert a child element. + * @param pChild Child element that should be inserted into child list. + * @param pos Insert position. + * @return + */ +void AccObject::InsertChild( AccObject* pChild,short pos ) +{ + + std::vector<AccObject*>::iterator iter; + iter = std::find(m_childrenList.begin(),m_childrenList.end(),pChild); + if(iter!=m_childrenList.end()) + return; + if(LAST_CHILD==pos) + { + m_childrenList.push_back(pChild); + } + else + { + iter=m_childrenList.begin()+pos; + m_childrenList.insert(iter,pChild); + } + + pChild->SetParentObj(this); +} + +/** + * Delete a child element + * @param pChild Child element that should be inserted into child list. + * @param pos Insert position. + * @return + */ +void AccObject::DeleteChild( AccObject* pChild ) +{ + std::vector<AccObject*>::iterator iter; + iter = std::find(m_childrenList.begin(),m_childrenList.end(),pChild); + if(iter!=m_childrenList.end()) + { + m_childrenList.erase(iter); + if(m_pIMAcc) + pChild->SetParentObj(nullptr); + } +} + +/** + * In order to windows API WindowFromAccessibleObject, we sometimes to set a pure + * top window accessible object created by windows system as top ancestor. + * @param. + * @return + */ +void AccObject::UpdateValidWindow() +{ + if(m_pIMAcc) + m_pIMAcc->Put_XAccWindowHandle(m_pParantID); +} + +/** + * Translate all UNO basic information into MSAA com information. + * @param + * @return If the method is correctly processed. + */ +void AccObject::ImplInitializeCreateObj() +{ + m_pIMAcc = UAccCOMCreateInstance(); + + assert(m_pIMAcc); +} + +/** + * Update name property to com object. + * @param + * @return + */ +void AccObject::UpdateName( ) +{ + if (!m_pIMAcc) + { + return; + } + + if( ( TEXT_FRAME == m_accRole ) && ( m_pParentObj !=nullptr )&& ( SCROLL_PANE == m_pParentObj -> m_accRole ) ) + m_pIMAcc->Put_XAccName( o3tl::toW(m_pParentObj->m_xAccContextRef->getAccessibleName().getStr()) ); + //IAccessibility2 Implementation 2009----- + if ( PARAGRAPH == m_accRole) + { + m_pIMAcc->Put_XAccName(L""); + } + //-----IAccessibility2 Implementation 2009 + else + m_pIMAcc->Put_XAccName(o3tl::toW(m_xAccContextRef->getAccessibleName().getStr())); + + return ; +} + +/** + * Update default action property to com object. + * @param + * @return + */ +void AccObject::UpdateAction() +{ + m_xAccActionRef.set(m_xAccContextRef,UNO_QUERY); + + if( m_xAccActionRef.is() && m_pIMAcc ) + { + if( m_xAccActionRef->getAccessibleActionCount() > 0 ) + { + UpdateDefaultAction( ); + m_pIMAcc->SetDefaultAction( + reinterpret_cast<hyper>(m_xAccActionRef.get())); + } + } +} + +/** + * Update value property to com object. + * @param + * @return + */ +void AccObject::UpdateValue() +{ + if( nullptr == m_pIMAcc || !m_xAccContextRef.is() ) + { + assert(false); + return ; + } + + Reference< XAccessibleValue > pRValue(m_xAccContextRef,UNO_QUERY); + Any pAny; + if( pRValue.is() ) + { + pAny = pRValue->getCurrentValue(); + } + + SetValue( pAny ); +} + +/** + * Set special default action description string via UNO role. + * @param Role UNO role + * @return + */ +void AccObject::UpdateDefaultAction( ) +{ + if(!m_xAccActionRef.is()) + return ; + + switch(m_accRole) + { + case PUSH_BUTTON: + case TOGGLE_BUTTON: + case RADIO_BUTTON: + case MENU_ITEM: + case RADIO_MENU_ITEM: + case CHECK_MENU_ITEM: + case LIST_ITEM: + case CHECK_BOX: + case TREE_ITEM: + case BUTTON_DROPDOWN: + m_pIMAcc->Put_ActionDescription( o3tl::toW(m_xAccActionRef->getAccessibleActionDescription(sal_Int32(0)).getStr()) ); + return; + } +} + +/** + * Set value property via pAny. + * @param pAny New value. + * @return + */ +void AccObject::SetValue( Any pAny ) +{ + if( nullptr == m_pIMAcc || !m_xAccContextRef.is() ) + { + assert(false); + return ; + } + Reference< XAccessibleText > pRText(m_xAccContextRef,UNO_QUERY); + OUString val; + switch(m_accRole) + { + case SPIN_BOX: + // 3. date editor's msaa value should be the same as spinbox + case DATE_EDITOR: + case TEXT: + case PARAGRAPH: + case HEADING: + case TABLE_CELL: + + if(pRText) + { + val = pRText->getText(); + } + m_pIMAcc->Put_XAccValue( o3tl::toW(val.getStr()) ); + break; + case TREE_ITEM: + //case CHECK_BOX: //Commented by Li Xing to disable the value for general checkbox + case COMBO_BOX: + case NOTE: + case SCROLL_BAR: + m_pIMAcc->Put_XAccValue( o3tl::toW(GetMAccessibleValueFromAny(pAny).getStr()) ); + break ; + // Added by Li Xing, only the checkbox in tree should have the value. + case CHECK_BOX: + if( ( m_pParentObj !=nullptr ) && (TREE == m_pParentObj->m_accRole || TREE_ITEM == m_pParentObj->m_accRole )) + m_pIMAcc->Put_XAccValue( o3tl::toW(GetMAccessibleValueFromAny(pAny).getStr()) ); + break; + default: + break; + } + + return; +} + +OUString AccObject::GetMAccessibleValueFromAny(Any pAny) +{ + OUString strValue; + + if(nullptr == m_pIMAcc) + return strValue; + + if(pAny.getValueType() == cppu::UnoType<cppu::UnoUnsignedShortType>::get() ) + { + sal_uInt16 val; + if (pAny >>= val) + { + strValue=OUString::number(val); + + } + } + else if(pAny.getValueType() == cppu::UnoType<OUString>::get()) + { + + pAny >>= strValue ; + + } + else if(pAny.getValueType() == cppu::UnoType<Sequence< OUString >>::get()) + { + Sequence< OUString > val; + if (pAny >>= val) + { + for (const OUString& rElem : val) + strValue += rElem; + } + } + else if(pAny.getValueType() == cppu::UnoType<double>::get()) + { + double val; + if (pAny >>= val) + { + strValue=OUString::number(val); + } + } + else if(pAny.getValueType() == cppu::UnoType<sal_Int32>::get()) + { + sal_Int32 val; + if (pAny >>= val) + { + strValue=OUString::number(val); + } + } + else if (pAny.getValueType() == cppu::UnoType<css::accessibility::TextSegment>::get()) + { + css::accessibility::TextSegment val; + if (pAny >>= val) + { + OUString realVal(val.SegmentText); + strValue = realVal; + + } + } + + return strValue; +} +/** + * Set name property via pAny. + * @param pAny New accessible name. + * @return + */ +void AccObject::SetName( Any pAny) +{ + if( nullptr == m_pIMAcc ) + return ; + + m_pIMAcc->Put_XAccName( o3tl::toW(GetMAccessibleValueFromAny(pAny).getStr()) ); + +} + +/** +* Get role property via pAny +* @param +* @return accessible role +*/ +short AccObject::GetRole() const +{ + return m_accRole; +} + +/** + * Get MSAA state from UNO state + * @Role xState UNO state. + * @return + */ +DWORD AccObject::GetMSAAStateFromUNO(short xState) +{ + DWORD IState = UNO_MSAA_UNMAPPING; + + if( !m_xAccContextRef.is() ) + { + assert(false); + return IState; + } + short Role = m_accRole; + + switch( xState ) + { + case BUSY: + IState = STATE_SYSTEM_BUSY; + break; + case CHECKED: + if( Role == PUSH_BUTTON || Role == TOGGLE_BUTTON ) + { + IState = STATE_SYSTEM_PRESSED; + } + else + IState = STATE_SYSTEM_CHECKED; + break; + case DEFUNC: + IState = STATE_SYSTEM_UNAVAILABLE; + break; + case EXPANDED: + IState = STATE_SYSTEM_EXPANDED; + break; + case FOCUSABLE: + IState = STATE_SYSTEM_FOCUSABLE; + break; + case FOCUSED: + IState = STATE_SYSTEM_FOCUSED; + break; + case INDETERMINATE: + IState = STATE_SYSTEM_MIXED; + break; + case MULTI_SELECTABLE: + IState = STATE_SYSTEM_MULTISELECTABLE; + break; + case PRESSED: + IState = STATE_SYSTEM_PRESSED; + break; + case RESIZABLE: + IState = STATE_SYSTEM_SIZEABLE; + break; + case SELECTABLE: + if( m_accRole == MENU || m_accRole == MENU_ITEM) + { + IState = UNO_MSAA_UNMAPPING; + } + else + { + IState = STATE_SYSTEM_SELECTABLE; + } + break; + case SELECTED: + if( m_accRole == MENU || m_accRole == MENU_ITEM ) + { + IState = UNO_MSAA_UNMAPPING; + } + else + { + IState = STATE_SYSTEM_SELECTED; + } + break; + case ARMED: + IState = STATE_SYSTEM_FOCUSED; + break; + case EXPANDABLE: + { + sal_Bool isExpanded = true; + sal_Bool isExpandable = true; + if( Role == PUSH_BUTTON || Role == TOGGLE_BUTTON || BUTTON_DROPDOWN == Role ) + { + IState = STATE_SYSTEM_HASPOPUP; + } + else + { + GetExpandedState(&isExpandable,&isExpanded); + if(!isExpanded) + IState = STATE_SYSTEM_COLLAPSED; + } + } + break; + //Remove the SENSITIVE state mapping. There is no corresponding MSAA state. + //case SENSITIVE: + // IState = STATE_SYSTEM_PROTECTED; + case EDITABLE: + if( m_pIMAcc ) + { + m_pIMAcc->DecreaseState( STATE_SYSTEM_READONLY ); + } + break; + case OFFSCREEN: + IState = STATE_SYSTEM_OFFSCREEN; + break; + case MOVEABLE: + IState = STATE_SYSTEM_MOVEABLE; + break; + case COLLAPSE: + IState = STATE_SYSTEM_COLLAPSED; + break; + case DEFAULT: + IState = STATE_SYSTEM_DEFAULT; + break; + default: + break; + } + + return IState; +} + +/** + * Decrease state of com object + * @param xState The lost state. + * @return + */ +void AccObject::DecreaseState( short xState ) +{ + if( nullptr == m_pIMAcc ) + { + return; + } + + if( xState == FOCUSABLE) + { + short Role = m_accRole ; + if(Role == MENU_ITEM + || Role == RADIO_MENU_ITEM + || Role == CHECK_MENU_ITEM) + return; + else + { + if (Role == TOGGLE_BUTTON || Role == PUSH_BUTTON || BUTTON_DROPDOWN == Role) + { + if( ( m_pParentObj !=nullptr ) && (TOOL_BAR == m_pParentObj->m_accRole ) ) + return; + } + } + } + + else if( xState == AccessibleStateType::VISIBLE ) + { + m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE ); + } + else if( xState == AccessibleStateType::SHOWING ) + { + m_pIMAcc->IncreaseState( STATE_SYSTEM_OFFSCREEN ); + } + + DWORD msState = GetMSAAStateFromUNO(xState); + if(msState!=UNO_MSAA_UNMAPPING) + m_pIMAcc->DecreaseState(msState); +} + +/** + * Increase state of com object + * @param xState The new state. + * @return + */ +void AccObject::IncreaseState( short xState ) +{ + if( nullptr == m_pIMAcc ) + { + assert(false); + return; + } + + + if( xState == AccessibleStateType::VISIBLE ) + { + m_pIMAcc->DecreaseState( STATE_SYSTEM_INVISIBLE ); + } + else if( xState == AccessibleStateType::SHOWING ) + { + m_pIMAcc->DecreaseState( STATE_SYSTEM_OFFSCREEN ); + } + + + DWORD msState = GetMSAAStateFromUNO(xState); + if(msState!=UNO_MSAA_UNMAPPING) + m_pIMAcc->IncreaseState( msState ); +} + +/** + * Get next child element + * @param + * @return AccObject Object interface. + */ +AccObject* AccObject::NextChild() +{ + IAccChildList::iterator pInd = m_childrenList.begin(); + if( pInd != m_childrenList.end() ) + return *pInd; + return nullptr; +} +/** + * update action description desc + * @param + * @return + */ +void AccObject::UpdateActionDesc() +{ + if (!m_pIMAcc) + return; + + long Role = m_accRole; + + if( Role == PUSH_BUTTON || Role == RADIO_BUTTON || Role == MENU_ITEM || + Role == LIST_ITEM || Role == CHECK_BOX || Role == TREE_ITEM || + Role == CHECK_MENU_ITEM || Role == RADIO_MENU_ITEM ) + { + UpdateDefaultAction( ); + } + else + { + + if( m_xAccActionRef.is() ) + { + if( m_xAccActionRef->getAccessibleActionCount() > 0 ) + { + if (!(Role == SPIN_BOX || Role == COMBO_BOX || Role == DATE_EDITOR || + Role == EDIT_BAR || Role == PASSWORD_TEXT || Role == TEXT)) + { + const OUString sActionDesc = m_xAccActionRef->getAccessibleActionDescription(0); + // if string is non-empty, action is set. + if (!sActionDesc.isEmpty()) + m_pIMAcc->Put_ActionDescription(o3tl::toW(sActionDesc.getStr())); + } + } + } + } + +} +/** + * update role information from uno to com + * @param + * @return + */ +void AccObject::UpdateRole() +{ + if (!m_pIMAcc) + { + return; + } + + XAccessibleContext* pContext = m_xAccContextRef.get(); + m_pIMAcc->Put_XAccRole( ROLE_SYSTEM_WINDOW ); + sal_Int16 iRoleIndex = pContext->getAccessibleRole(); + if ((0 <= iRoleIndex) && (o3tl::make_unsigned(iRoleIndex) < SAL_N_ELEMENTS(ROLE_TABLE))) + { + short iIA2Role = ROLE_TABLE[iRoleIndex][1] ; + m_pIMAcc->Put_XAccRole( iIA2Role ); + } + +} +/** + * update state information from uno to com + * @param + * @return + */ +void AccObject::UpdateState() +{ + if (!m_pIMAcc) + { + return; + } + + XAccessibleContext* pContext = m_xAccContextRef.get(); + Reference< XAccessibleStateSet > pRState = pContext->getAccessibleStateSet(); + if( !pRState.is() ) + { + assert(false); + return ; + } + + m_pIMAcc->SetState(0); + + if ( m_accRole == POPUP_MENU ) + { + return; + } + + bool isEnable = false; + bool isShowing = false; + bool isEditable = false; + bool isVisible = false; + bool isFocusable = false; + + for (const sal_Int16 nState : pRState->getStates()) + { + if (nState == ENABLED) + isEnable = true; + else if (nState == SHOWING) + isShowing = true; + else if (nState == VISIBLE) + isVisible = true; + else if (nState == EDITABLE) + isEditable = true; + else if (nState == FOCUSABLE) + isFocusable = true; + IncreaseState(nState); + } + bool bIsMenuItem = m_accRole == MENU_ITEM || m_accRole == RADIO_MENU_ITEM || m_accRole == CHECK_MENU_ITEM; + + if(bIsMenuItem) + { + if(!(isShowing && isVisible) ) + { + m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE ); + m_pIMAcc->DecreaseState( STATE_SYSTEM_FOCUSABLE ); + } + } + else + { + if(!(isShowing || isVisible) ) + m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE ); + } + + short Role = m_accRole; + + switch(m_accRole) + { + case LABEL: + case STATIC: + m_pIMAcc->IncreaseState( STATE_SYSTEM_READONLY ); + break; + case TEXT: + // 2. editable combobox -> readonly ------ bridge + case EMBEDDED_OBJECT: + case END_NOTE: + case FOOTER: + case FOOTNOTE: + case GRAPHIC: + case HEADER: + case HEADING: + + //Image Map + case PARAGRAPH: + case PASSWORD_TEXT: + case SHAPE: + case SPIN_BOX: + case TABLE: + case TABLE_CELL: + case TEXT_FRAME: + case DATE_EDITOR: + case DOCUMENT: + case COLUMN_HEADER: + { + if(!isEditable) + m_pIMAcc->IncreaseState( STATE_SYSTEM_READONLY ); + } + break; + default: + break; + } + + if( isEnable ) + { + + if(!(Role == FILLER || Role == END_NOTE || Role == FOOTER || Role == FOOTNOTE || Role == GROUP_BOX || Role == RULER + || Role == HEADER || Role == ICON || Role == INTERNAL_FRAME || Role == LABEL || Role == LAYERED_PANE + || Role == SCROLL_BAR || Role == SCROLL_PANE || Role == SPLIT_PANE || Role == STATIC || Role == STATUS_BAR + || Role == TOOL_TIP)) + { + if( SEPARATOR == Role ) + { + if( ( m_pParentObj != nullptr ) && ( MENU == m_pParentObj->m_accRole || POPUP_MENU == m_pParentObj->m_accRole )) + IncreaseState( FOCUSABLE ); + } + + else if (TABLE_CELL == Role || TABLE == Role || PANEL == Role || OPTION_PANE == Role || + COLUMN_HEADER == Role) + { + if (isFocusable) + IncreaseState( FOCUSABLE ); + } + else + { + if(bIsMenuItem) + { + if ( isShowing && isVisible) + { + IncreaseState( FOCUSABLE ); + } + } + else + { + IncreaseState( FOCUSABLE ); + } + } + } + } + else + { + m_pIMAcc->IncreaseState( STATE_SYSTEM_UNAVAILABLE ); + if( !((Role == MENU_ITEM) || + (Role == RADIO_MENU_ITEM) || + (Role == CHECK_MENU_ITEM)) ) + { + if ( Role == TOGGLE_BUTTON || Role == PUSH_BUTTON || BUTTON_DROPDOWN == Role) + { + if(( m_pParentObj != nullptr )&& (TOOL_BAR == m_pParentObj->m_accRole ) ) + IncreaseState( FOCUSABLE ); + else + DecreaseState( FOCUSABLE ); + } + else + DecreaseState( FOCUSABLE ); + } + else if( isShowing || isVisible ) + { + IncreaseState( FOCUSABLE ); + } + } + + switch(m_accRole) + { + case POPUP_MENU: + case MENU: + if( pContext->getAccessibleChildCount() > 0 ) + m_pIMAcc->IncreaseState( STATE_SYSTEM_HASPOPUP ); + break; + case PASSWORD_TEXT: + m_pIMAcc->IncreaseState( STATE_SYSTEM_PROTECTED ); + break; + default: + break; + } +} + +/** + * update location information from uno to com + * @param + * @return + */ +void AccObject::UpdateLocation() +{ + if (!m_pIMAcc) + { + return; + } + XAccessibleContext* pContext = m_xAccContextRef.get(); + + Reference< XAccessibleComponent > pRComponent(pContext,UNO_QUERY); + if( pRComponent.is() ) + { + css::awt::Point pCPoint = pRComponent->getLocationOnScreen(); + css::awt::Size pCSize = pRComponent->getSize(); + Location tempLocation; + tempLocation.m_dLeft = pCPoint.X; + tempLocation.m_dTop = pCPoint.Y; + tempLocation.m_dWidth = pCSize.Width; + tempLocation.m_dHeight = pCSize.Height; + m_pIMAcc->Put_XAccLocation( tempLocation ); + } + +} + + +/** + * Public method to mapping information between MSAA and UNO. + * @param + * @return If the method is correctly processed. + */ +bool AccObject::UpdateAccessibleInfoFromUnoToMSAA() +{ + if( nullptr == m_pIMAcc || !m_xAccContextRef.is() ) + { + assert(false); + return false; + } + + UpdateName(); + + UpdateValue(); + + UpdateActionDesc(); + + UpdateRole(); + + UpdateLocation(); + + UpdateState(); + + return true; +} + +/* + * Add a child selected element. + * @param pAccObj Child object pointer. + * @return + */ +void AccObject::AddSelect( long index, AccObject* accObj) +{ + m_selectionList.emplace(index,accObj); +} + +IAccSelectionList& AccObject::GetSelection() +{ + return m_selectionList; +} + + +/** + * Set self to focus object in parent child list + * @param + * @return + */ +void AccObject::setFocus() +{ + if(m_pIMAcc) + { + IncreaseState(FOCUSED); + m_pIMAcc->Put_XAccFocus(CHILDID_SELF); + + UpdateRole(); + } +} + +/** + * Unset self from focus object in parent child list. + * @param + * @return + */ +void AccObject::unsetFocus() +{ + if(m_pIMAcc) + { + DecreaseState( FOCUSED ); + m_pIMAcc->Put_XAccFocus(UACC_NO_FOCUS); + } +} + +void AccObject::GetExpandedState( sal_Bool* isExpandable, sal_Bool* isExpanded) +{ + *isExpanded = false; + *isExpandable = false; + + if( !m_xAccContextRef.is() ) + { + return; + } + Reference< XAccessibleStateSet > pRState = m_xAccContextRef->getAccessibleStateSet(); + if( !pRState.is() ) + { + return; + } + + for (sal_Int16 nState : pRState->getStates()) + { + if (nState == EXPANDED) + *isExpanded = true; + else if (nState == EXPANDABLE) + *isExpandable = true; + } +} + +void AccObject::NotifyDestroy() +{ + if(m_pIMAcc) + m_pIMAcc->NotifyDestroy(); +} + +void AccObject::SetParentObj(AccObject* pParentAccObj) +{ + m_pParentObj = pParentAccObj; + + if(m_pIMAcc) + { + if(m_pParentObj) + { + m_pIMAcc->Put_XAccParent(m_pParentObj->GetIMAccessible()); + } + else + { + m_pIMAcc->Put_XAccParent(nullptr); + } + } +} +//ResID means ChildID in MSAA +void AccObject::SetResID(long id) +{ + m_resID = id; + if(m_pIMAcc) + m_pIMAcc->Put_XAccChildID(m_resID); +} +//return COM interface in acc object +IMAccessible* AccObject::GetIMAccessible() +{ + return m_pIMAcc; +} + +Reference<XAccessible> const& AccObject::GetXAccessible() +{ + return m_xAccRef; +} + +void AccObject::SetParentHWND(HWND hWnd) +{ + m_pParantID = hWnd; +} + +void AccObject::SetListener(rtl::Reference<AccEventListener> const& pListener) +{ + m_pListener = pListener; +} + +AccEventListener* AccObject::getListener() +{ + return m_pListener.get(); +} + +long AccObject::GetResID() +{ + return m_resID; +} + +HWND AccObject::GetParentHWND() +{ + return m_pParantID; +} + +AccObject* AccObject::GetParentObj() +{ + return m_pParentObj; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |