summaryrefslogtreecommitdiffstats
path: root/winaccessibility/source/service
diff options
context:
space:
mode:
Diffstat (limited to 'winaccessibility/source/service')
-rw-r--r--winaccessibility/source/service/AccComponentEventListener.cxx325
-rw-r--r--winaccessibility/source/service/AccContainerEventListener.cxx552
-rw-r--r--winaccessibility/source/service/AccDescendantManagerEventListener.cxx237
-rw-r--r--winaccessibility/source/service/AccDialogEventListener.cxx133
-rw-r--r--winaccessibility/source/service/AccEventListener.cxx260
-rw-r--r--winaccessibility/source/service/AccFrameEventListener.cxx145
-rw-r--r--winaccessibility/source/service/AccListEventListener.cxx126
-rw-r--r--winaccessibility/source/service/AccMenuEventListener.cxx147
-rw-r--r--winaccessibility/source/service/AccObject.cxx1128
-rw-r--r--winaccessibility/source/service/AccObjectContainerEventListener.cxx68
-rw-r--r--winaccessibility/source/service/AccObjectManagerAgent.cxx384
-rw-r--r--winaccessibility/source/service/AccObjectWinManager.cxx1202
-rw-r--r--winaccessibility/source/service/AccParagraphEventListener.cxx131
-rw-r--r--winaccessibility/source/service/AccTableEventListener.cxx142
-rw-r--r--winaccessibility/source/service/AccTextComponentEventListener.cxx67
-rw-r--r--winaccessibility/source/service/AccTopWindowListener.cxx254
-rw-r--r--winaccessibility/source/service/AccTreeEventListener.cxx90
-rw-r--r--winaccessibility/source/service/AccWindowEventListener.cxx136
-rw-r--r--winaccessibility/source/service/ResIDGenerator.cxx46
-rw-r--r--winaccessibility/source/service/msaaservice_impl.cxx275
-rw-r--r--winaccessibility/source/service/winaccessibility.component25
21 files changed, 5873 insertions, 0 deletions
diff --git a/winaccessibility/source/service/AccComponentEventListener.cxx b/winaccessibility/source/service/AccComponentEventListener.cxx
new file mode 100644
index 000000000..f2a649a05
--- /dev/null
+++ b/winaccessibility/source/service/AccComponentEventListener.cxx
@@ -0,0 +1,325 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccComponentEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccComponentEventListener::AccComponentEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccEventListener(pAcc, Agent)
+{
+}
+
+AccComponentEventListener::~AccComponentEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ *
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccComponentEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::VALUE_CHANGED:
+ HandleValueChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::ACTION_CHANGED:
+ HandleActionChangedEvent();
+ break;
+ case AccessibleEventId::TEXT_CHANGED:
+ HandleTextChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::CARET_CHANGED:
+ HandleCaretChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::VISIBLE_DATA_CHANGED:
+ HandleVisibleDataChangedEvent();
+ break;
+ case AccessibleEventId::BOUNDRECT_CHANGED:
+ HandleBoundrectChangedEvent();
+ break;
+ case AccessibleEventId::SELECTION_CHANGED:
+ HandleSelectionChangedEventNoArgs();
+ break;
+ //to add TEXT_SELECTION_CHANGED event
+ case AccessibleEventId::TEXT_SELECTION_CHANGED:
+ HandleTextSelectionChangedEvent();
+ break;
+ //End
+ default:
+ AccEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the VALUE_CHANGED event
+ *
+ * @param oldValue the old value of the source of event
+ * @param newValue the new value of the source of event
+ */
+void AccComponentEventListener::HandleValueChangedEvent(Any, Any)
+{
+ pAgent->UpdateValue(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_VALUECHANGE, m_xAccessible.get());
+}
+
+/**
+ * handle the NAME_CHANGED event
+ */
+void AccComponentEventListener::HandleActionChangedEvent()
+{
+ pAgent->UpdateAction(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_DEFACTIONCHANGE, m_xAccessible.get());
+}
+
+/**
+ * handle the TEXT_CHANGED event
+ *
+ * @param oldValue the old value of the source of event
+ * @param newValue the new value of the source of event
+ */
+void AccComponentEventListener::HandleTextChangedEvent(Any, Any newValue)
+{
+ pAgent->UpdateValue(m_xAccessible.get(), newValue);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_VALUECHANGE, m_xAccessible.get());
+}
+
+/**
+ * handle the CARET_CHANGED event
+ *
+ * @param oldValue the old value of the source of event
+ * @param newValue the new value of the source of event
+ */
+void AccComponentEventListener::HandleCaretChangedEvent(Any, Any)
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_CARETCHANGE, m_xAccessible.get());
+}
+
+/**
+ * set the new state and fire the MSAA event
+ *
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccComponentEventListener::SetComponentState(short state, bool enable)
+{
+ // only the following state can be fired state event.
+ switch (state)
+ {
+ case AccessibleStateType::CHECKED:
+ case AccessibleStateType::PRESSED:
+ case AccessibleStateType::SELECTED:
+ case AccessibleStateType::ARMED:
+ case AccessibleStateType::INDETERMINATE:
+ case AccessibleStateType::SHOWING:
+ FireStatePropertyChange(state, enable);
+ break;
+ case AccessibleStateType::VISIBLE:
+ if (GetRole() == AccessibleRole::MENU_ITEM)
+ {
+ if(enable)
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSABLE);
+ }
+ else
+ {
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSABLE);
+ }
+ }
+ else
+ {
+ FireStatePropertyChange(state, enable);
+ }
+ break;
+ case AccessibleStateType::FOCUSED:
+ FireStateFocusedChange(enable);
+ break;
+ case AccessibleStateType::ENABLED:
+ if(enable)
+ {
+ pAgent->UpdateState(m_xAccessible.get());
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::DEFUNC);
+ // 8. label should have no FOCUSABLE state, Firefox has READONLY state, we can also have.
+ if ( GetRole() != AccessibleRole::LABEL
+ && GetRole() != AccessibleRole::STATIC
+ && GetRole() != AccessibleRole::SCROLL_BAR)
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSABLE);
+ }
+ }
+ else
+ {
+ pAgent->UpdateState(m_xAccessible.get());
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::DEFUNC);
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSABLE);
+ }
+ break;
+ case AccessibleStateType::ACTIVE:
+ // Only frames should be active
+ // no msaa state mapping
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * fire the MSAA state changed event
+ *
+ * @param state the state id
+ * @param set true if state is set, false if state is unset
+ */
+void AccComponentEventListener::FireStatePropertyChange(short state, bool set)
+{
+ if( set)
+ {
+ // new value
+ switch(state)
+ {
+ case AccessibleStateType::CHECKED:
+ case AccessibleStateType::INDETERMINATE:
+ pAgent->IncreaseState(m_xAccessible.get(), state);
+ pAgent->UpdateAction(m_xAccessible.get());
+
+ if (!pAgent->IsSpecialToolbarItem(m_xAccessible.get()))
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_CHECKED, m_xAccessible.get());
+ }
+ break;
+ case AccessibleStateType::PRESSED:
+ pAgent->IncreaseState(m_xAccessible.get(), state);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_PRESSED, m_xAccessible.get());
+ break;
+ case AccessibleStateType::SELECTED:
+ pAgent->IncreaseState(m_xAccessible.get(), state);
+ break;
+ case AccessibleStateType::ARMED:
+ pAgent->IncreaseState(m_xAccessible.get(), state);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_ARMED, m_xAccessible.get());
+ break;
+ case AccessibleStateType::SHOWING:
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::DEFUNC);
+ // UNO !SHOWING == MSAA OFFSCREEN
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::SHOWING );
+ break;
+ case AccessibleStateType::VISIBLE:
+ // UNO !VISIBLE == MSAA INVISIBLE
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE );
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // old value
+ switch(state)
+ {
+ case AccessibleStateType::CHECKED:
+ case AccessibleStateType::INDETERMINATE:
+ pAgent->DecreaseState(m_xAccessible.get(), state);
+ pAgent->UpdateAction(m_xAccessible.get());
+
+ if (!pAgent->IsSpecialToolbarItem(m_xAccessible.get()))
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_CHECKED, m_xAccessible.get());
+ }
+ break;
+ case AccessibleStateType::PRESSED:
+ pAgent->DecreaseState(m_xAccessible.get(), state);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_PRESSED, m_xAccessible.get());
+ break;
+ case AccessibleStateType::SELECTED:
+ pAgent->DecreaseState(m_xAccessible.get(), state);
+ //if the state is unset, no need to send MSAA SELECTION event
+ //pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_SELECTED, m_xAccessible.get());
+ break;
+ case AccessibleStateType::ARMED:
+ {
+ pAgent->DecreaseState(m_xAccessible.get(), state);
+ //if the state is unset, no need to send MSAA MENU event
+ //pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_ARMED, m_xAccessible.get());
+ }
+ break;
+ case AccessibleStateType::SHOWING:
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::DEFUNC);
+ // UNO !SHOWING == MSAA OFFSCREEN
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::SHOWING);
+ break;
+ case AccessibleStateType::VISIBLE:
+ // UNO !VISIBLE == MSAA INVISIBLE
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * handle the focused event
+ *
+ * @param enable true if get focus, false if lose focus
+ */
+void AccComponentEventListener::FireStateFocusedChange(bool enable)
+{
+ if(enable)
+ {
+ if (GetParentRole() != AccessibleRole::COMBO_BOX)
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_FOCUSED, m_xAccessible.get());
+ }
+ else
+ {
+ //if lose focus, no need to send MSAA FOCUS event
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSED);
+ }
+}
+
+void AccComponentEventListener::HandleSelectionChangedEventNoArgs()
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED, m_xAccessible.get());
+}
+
+//add TEXT_SELECTION_CHANGED event
+void AccComponentEventListener::HandleTextSelectionChangedEvent()
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TEXT_SELECTION_CHANGED, m_xAccessible.get());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccContainerEventListener.cxx b/winaccessibility/source/service/AccContainerEventListener.cxx
new file mode 100644
index 000000000..aa7a016e2
--- /dev/null
+++ b/winaccessibility/source/service/AccContainerEventListener.cxx
@@ -0,0 +1,552 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccContainerEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccContainerEventListener::AccContainerEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccEventListener(pAcc, Agent)
+{
+}
+
+AccContainerEventListener::~AccContainerEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ *
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccContainerEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::CHILD:
+ HandleChildChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED:
+ HandleSelectionChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::INVALIDATE_ALL_CHILDREN:
+ HandleAllChildrenChangedEvent();
+ break;
+ case AccessibleEventId::TEXT_CHANGED:
+ HandleTextChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ [[fallthrough]]; //TODO ???
+ case AccessibleEventId::VISIBLE_DATA_CHANGED:
+ HandleVisibleDataChangedEvent();
+ break;
+ case AccessibleEventId::BOUNDRECT_CHANGED:
+ HandleBoundrectChangedEvent();
+ break;
+ case AccessibleEventId::STATE_CHANGED:
+ HandleStateChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::VALUE_CHANGED:
+ HandleValueChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED_ADD:
+ HandleSelectionChangedAddEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED_REMOVE:
+ HandleSelectionChangedRemoveEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED_WITHIN:
+ HandleSelectionChangedWithinEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::PAGE_CHANGED:
+ HandlePageChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SECTION_CHANGED:
+ HandleSectionChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::COLUMN_CHANGED:
+ HandleColumnChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ default:
+ AccEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+void AccContainerEventListener::HandleStateChangedEvent(Any oldValue, Any newValue)
+{
+ short State;
+ if( newValue >>= State)
+ {
+ SetComponentState(State, true);
+ }
+ else if (oldValue >>= State)
+ {
+ SetComponentState(State, false);
+ }
+
+}
+
+/**
+ * handle the CHILD event
+ * @param oldValue the child to be deleted
+ * @param newValue the child to be added
+ */
+void AccContainerEventListener::HandleChildChangedEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+ if( newValue >>= xChild)
+ {
+ //create a new child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ //add this child
+
+ if (pAgent->InsertAccObj(pAcc, m_xAccessible.get()))
+ {
+ //add all oldValue's existing children
+ pAgent->InsertChildrenAccObj(pAcc);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_ADDED, pAcc);
+ }
+ }
+ }
+ else if (oldValue >>= xChild)
+ {
+ //delete an existing child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_REMOVED, pAcc);
+ //delete all oldValue's existing children
+ pAgent->DeleteChildrenAccObj( pAcc );
+ //delete this child
+ pAgent->DeleteAccObj( pAcc );
+
+ }
+ }
+
+}
+
+/**
+ * handle the SELECTION_CHANGED event
+ * @param oldValue the old value of the source of event
+ * @param newValue the new value of the source of event
+ */
+void AccContainerEventListener::HandleSelectionChangedEvent(const Any& /*oldValue*/, const Any& newValue)
+{
+ if (NotifyChildEvent(UnoMSAAEvent::SELECTION_CHANGED, newValue))
+ {
+ return ;
+ }
+
+ //menu bar does not process selection change event,just same as word behavior
+ if (GetRole()!=AccessibleRole::MENU_BAR)
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED, m_xAccessible.get());
+}
+
+/**
+ * handle the INVALIDATE_ALL_CHILDREN event
+ */
+void AccContainerEventListener::HandleAllChildrenChangedEvent()
+{
+ //TODO: update all the children
+ if (m_xAccessible.is())
+ {
+ //delete all oldValue's existing children
+ pAgent->DeleteChildrenAccObj(m_xAccessible.get());
+ //add all oldValue's existing children
+ pAgent->InsertChildrenAccObj(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_REORDER, m_xAccessible.get());
+ }
+}
+
+/**
+ * handle the TEXT_CHANGED event
+ */
+void AccContainerEventListener::HandleTextChangedEvent(Any, Any newValue)
+{
+ pAgent->UpdateValue(m_xAccessible.get(), newValue);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_TEXTCHANGE, m_xAccessible.get());
+}
+
+/**
+ * set the new state and fire the MSAA event
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccContainerEventListener::SetComponentState(short state, bool enable )
+{
+ // only the following state can be fired state event.
+
+ switch (state)
+ {
+ case AccessibleStateType::SELECTED:
+ case AccessibleStateType::BUSY:
+ case AccessibleStateType::INDETERMINATE:
+ case AccessibleStateType::OFFSCREEN:
+ case AccessibleStateType::FOCUSABLE:
+ case AccessibleStateType::SHOWING:
+ case AccessibleStateType::VISIBLE:
+ FireStatePropertyChange(state, enable);
+ break;
+ case AccessibleStateType::FOCUSED:
+ FireStateFocusedChange(enable);
+ break;
+ case AccessibleStateType::ENABLED:
+ if(enable)
+ {
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::DEFUNC);
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSABLE);
+ pAgent->UpdateState(m_xAccessible.get());
+
+ UpdateAllChildrenState(m_xAccessible.get());
+ }
+ else
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::DEFUNC);
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSABLE);
+ pAgent->UpdateState(m_xAccessible.get());
+
+ UpdateAllChildrenState(m_xAccessible.get());
+ }
+ break;
+ case AccessibleStateType::ACTIVE:
+ // Only frames should be active
+ // no msaa state mapping
+ //for PAGE_TAB_LIST, there will be ACTIVE state, then it should be converted to FOCUSED event.
+ if (GetRole() == AccessibleRole::PAGE_TAB_LIST)
+ {
+ if (!enable) /* get the active state */
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSED);
+ }
+
+ else /* lose the active state */
+ {
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSED);
+ }
+ }
+ break;
+
+ case AccessibleStateType::EXPANDED:
+ case AccessibleStateType::COLLAPSE:
+ case AccessibleStateType::CHECKED:
+ {
+ pAgent->UpdateState(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_BUSY, m_xAccessible.get());
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+/**
+ * fire the MSAA state changed event
+ * @param state the state id
+ * @param set true if state is set, false if state is unset
+ */
+void AccContainerEventListener::FireStatePropertyChange(short state, bool set)
+{
+ if( set )
+ {
+ // new value
+ switch(state)
+ {
+ case AccessibleStateType::SELECTED:
+ pAgent->IncreaseState(m_xAccessible.get(), state);
+ break;
+ case AccessibleStateType::INDETERMINATE:
+ case AccessibleStateType::BUSY:
+ case AccessibleStateType::FOCUSABLE:
+ case AccessibleStateType::OFFSCREEN:
+ pAgent->IncreaseState(m_xAccessible.get(), state);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_BUSY, m_xAccessible.get());
+ break;
+ case AccessibleStateType::SHOWING:
+ // UNO !SHOWING == MSAA OFFSCREEN
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::SHOWING);
+ break;
+ case AccessibleStateType::VISIBLE:
+ // UNO !VISIBLE == MSAA INVISIBLE
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // old value
+ switch(state)
+ {
+ case AccessibleStateType::SELECTED:
+ pAgent->DecreaseState(m_xAccessible.get(), state);
+ break;
+ case AccessibleStateType::BUSY:
+ case AccessibleStateType::INDETERMINATE:
+ case AccessibleStateType::FOCUSABLE:
+ case AccessibleStateType::OFFSCREEN:
+ pAgent->DecreaseState(m_xAccessible.get(), state);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_BUSY, m_xAccessible.get());
+ break;
+ case AccessibleStateType::SHOWING:
+ // UNO !SHOWING == MSAA OFFSCREEN
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::SHOWING);
+ break;
+ case AccessibleStateType::VISIBLE:
+ // UNO !VISIBLE == MSAA INVISIBLE
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * handle the focused event
+ * @param enable true if get focus, false if lose focus
+ */
+void AccContainerEventListener::FireStateFocusedChange(bool enable)
+{
+ if(enable)
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSED);
+ // if the acc role is MENU_BAR, UnoMSAAEvent::MENU_START event should be sent
+ // if the acc role is POPUP_MENU, UnoMSAAEvent::MENUPOPUPSTART event should be sent
+ short role = GetRole();
+ if(role == AccessibleRole::MENU_BAR)
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::MENU_START, m_xAccessible.get());
+ }
+ else if (role == AccessibleRole::POPUP_MENU)
+ pAgent->NotifyAccEvent(UnoMSAAEvent::MENUPOPUPSTART, m_xAccessible.get());
+ //Disable the focused event on option_pane and Panel.
+ //only disable option_pane for toolbar has panel to get focus
+ else if (role == AccessibleRole::PANEL || role == AccessibleRole::OPTION_PANE )
+ {
+ //don't send focused event on PANEL & OPTION_PANE if the parent is not toolbar
+ short parentRole = GetParentRole();
+ if (parentRole == AccessibleRole::TOOL_BAR
+ || parentRole == AccessibleRole::SCROLL_PANE // sidebar
+ || parentRole == AccessibleRole::PANEL) // sidebar
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_FOCUSED, m_xAccessible.get());
+ }
+ else if (role == AccessibleRole::COMBO_BOX )
+ {
+ //for editable combobox, send focus event on only edit control,
+ bool bSendFocusOnCombobox = true;
+ //send focused event to the first text child
+ Reference<XAccessibleContext> mxContext = m_xAccessible->getAccessibleContext();
+ if(mxContext.is())
+ {
+ Reference<XAccessible> mxChild = mxContext->getAccessibleChild(0);
+ if(mxChild.is())
+ {
+ Reference<XAccessibleContext> mxChildContext = mxChild->getAccessibleContext();
+ short childrole = mxChildContext->getAccessibleRole();
+ if (childrole == AccessibleRole::TEXT)
+ {
+ if (IsEditable(mxChildContext))
+ {
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSED);
+ pAgent->IncreaseState( mxChild.get(), AccessibleStateType::FOCUSED);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_FOCUSED, mxChild.get());
+ bSendFocusOnCombobox = false;
+ }
+ }
+ }
+ }
+ if (bSendFocusOnCombobox)
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_FOCUSED, m_xAccessible.get());
+ }
+ else
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_FOCUSED, m_xAccessible.get());
+ }
+ else
+ {
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSED);
+ // if the acc role is MENU_BAR, UnoMSAAEvent::MENU_END event should be sent
+ // if the acc role is POPUP_MENU, UnoMSAAEvent::MENUPOPUPEND event should be sent
+ if (GetRole() == AccessibleRole::MENU_BAR)
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::MENU_END, m_xAccessible.get());
+ }
+ else if (GetRole() == AccessibleRole::POPUP_MENU)
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::MENUPOPUPEND, m_xAccessible.get());
+ }
+ }
+}
+
+/**
+ * handle the VALUE_CHANGED event
+ *
+ * @param oldValue the old value of the source of event
+ * @param newValue the new value of the source of event
+ */
+void AccContainerEventListener::HandleValueChangedEvent(Any, Any)
+{
+ pAgent->UpdateValue(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_VALUECHANGE, m_xAccessible.get());
+}
+
+bool AccContainerEventListener::IsEditable(Reference<XAccessibleContext> const & xContext)
+{
+ Reference< XAccessibleStateSet > pRState = xContext->getAccessibleStateSet();
+ if( !pRState.is() )
+ return false;
+
+ Sequence<short> pStates = pRState->getStates();
+ int count = pStates.getLength();
+ for( int iIndex = 0;iIndex < count;iIndex++ )
+ {
+ if(pStates[iIndex] == AccessibleStateType::EDITABLE)
+ return true;
+ }
+ return false;
+}
+
+bool AccContainerEventListener::NotifyChildEvent(UnoMSAAEvent eWinEvent, const Any& Value)
+{
+ Reference< XAccessible > xChild;
+ if(Value >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->NotifyAccEvent(eWinEvent, pAcc);
+ return true;
+ }
+ }
+ return false;
+}
+
+void AccContainerEventListener::HandleSelectionChangedAddEvent(const Any& /*oldValue*/, const Any& newValue)
+{
+ if (NotifyChildEvent(UnoMSAAEvent::SELECTION_CHANGED_ADD, newValue))
+ {
+ return ;
+ }
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED_ADD, m_xAccessible.get());
+}
+
+void AccContainerEventListener::HandleSelectionChangedRemoveEvent(const Any& /*oldValue*/, const Any& newValue)
+{
+ if (NotifyChildEvent(UnoMSAAEvent::SELECTION_CHANGED_REMOVE, newValue))
+ {
+ return ;
+ }
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED_REMOVE, m_xAccessible.get());
+}
+
+void AccContainerEventListener::HandleSelectionChangedWithinEvent(const Any& /*oldValue*/, const Any& newValue)
+{
+ if (NotifyChildEvent(UnoMSAAEvent::SELECTION_CHANGED_WITHIN, newValue))
+ {
+ return ;
+ }
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED_WITHIN, m_xAccessible.get());
+}
+
+void AccContainerEventListener::UpdateAllChildrenState(XAccessible* pXAccessible)
+{
+ Reference<css::accessibility::XAccessibleContext> xContext = pXAccessible->getAccessibleContext();
+ if(!xContext.is())
+ {
+ return;
+ }
+ css::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
+ if(pAccessibleContext == nullptr)
+ {
+ return;
+ }
+
+ if (pAgent && pAgent->IsStateManageDescendant(pXAccessible))
+ {
+ return;
+ }
+
+ int count = pAccessibleContext->getAccessibleChildCount();
+ for (int i=0;i<count;i++)
+ {
+ Reference<css::accessibility::XAccessible> mxAccessible
+ = pAccessibleContext->getAccessibleChild(i);
+
+ css::accessibility::XAccessible* mpAccessible = mxAccessible.get();
+ if(mpAccessible != nullptr)
+ {
+ pAgent->UpdateState(mpAccessible);
+ UpdateAllChildrenState(mpAccessible);
+ }
+ }
+}
+
+void AccContainerEventListener::HandlePageChangedEvent(const Any& /*oldValue*/, const Any& /*newValue*/)
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_PAGECHANGED, m_xAccessible.get());
+}
+
+void AccContainerEventListener::HandleSectionChangedEvent(const Any& /*oldValue*/, const Any& /*newValue*/ )
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SECTION_CHANGED, m_xAccessible.get());
+}
+
+void AccContainerEventListener::HandleColumnChangedEvent(const Any& /*oldValue*/, const Any& /*newValue*/)
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::COLUMN_CHANGED, m_xAccessible.get());
+}
+
+void AccContainerEventListener::HandleNameChangedEvent( Any name )
+{
+ if (GetRole() == AccessibleRole::COMBO_BOX)
+ {
+ Reference<XAccessibleContext> mxContext(m_xAccessible->getAccessibleContext());
+ if(mxContext.is())
+ {
+ Reference<XAccessible> mxChild = mxContext->getAccessibleChild(0);
+ if(mxChild.is())
+ {
+ Reference<XAccessibleContext> mxChildContext = mxChild->getAccessibleContext();
+ short childrole = mxChildContext->getAccessibleRole();
+ if (childrole == AccessibleRole::TEXT)
+ {
+ pAgent->UpdateAccName(mxChild.get(), name);
+ }
+ }
+ }
+ }
+ AccEventListener::HandleNameChangedEvent(name);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccDescendantManagerEventListener.cxx b/winaccessibility/source/service/AccDescendantManagerEventListener.cxx
new file mode 100644
index 000000000..c38f19e32
--- /dev/null
+++ b/winaccessibility/source/service/AccDescendantManagerEventListener.cxx
@@ -0,0 +1,237 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccDescendantManagerEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccDescendantManagerEventListener::AccDescendantManagerEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ : AccComponentEventListener(pAcc, Agent)
+{
+}
+
+AccDescendantManagerEventListener::~AccDescendantManagerEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccDescendantManagerEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::SELECTION_CHANGED:
+ HandleSelectionChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::CHILD:
+ HandleChildChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS:
+ HandleChildChangedNoFocusEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED_ADD:
+ HandleSelectionChangedAddEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED_REMOVE:
+ HandleSelectionChangedRemoveEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED_WITHIN:
+ HandleSelectionChangedWithinEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ default:
+ AccComponentEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the CHILD event
+ * @param oldValue the child to be deleted
+ * @param newValue the child to be added
+ */
+void AccDescendantManagerEventListener::HandleChildChangedEvent(Any oldValue, Any newValue)
+{
+
+ Reference< XAccessible > xChild;
+ if( newValue >>= xChild)
+ {
+ //create a new child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ pAgent->InsertChildrenAccObj(pAcc);
+
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_ADDED, pAcc);
+
+ }
+ }
+
+ if (oldValue >>= xChild)
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_REMOVED, pAcc);
+ pAgent->DeleteChildrenAccObj( pAcc );
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+
+}
+
+/**
+ * handle the SELECTION_CHANGED event
+ */
+void AccDescendantManagerEventListener::HandleSelectionChangedEvent(Any oldValue, Any newValue)
+{
+ bool bSend =false;
+ Reference< XAccessible > xChild;
+ if(newValue >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ //if the Role is the SC cell ,don't add the selected state.
+ if (pAgent->GetRole(pAcc) != AccessibleRole::TABLE_CELL)
+ {
+ pAgent->IncreaseState( pAcc, AccessibleStateType::SELECTED);
+ }
+
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED, pAcc);
+ bSend=true;
+ }
+ }
+ if(oldValue >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->DecreaseState( pAcc, AccessibleStateType::SELECTED);
+ }
+ }
+ if (!bSend)
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED, m_xAccessible.get());
+ }
+}
+
+
+void AccDescendantManagerEventListener::HandleChildChangedNoFocusEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+ if(newValue >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ pAgent->InsertChildrenAccObj(pAcc);
+ }
+ }
+ if (oldValue >>= xChild)
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->DeleteChildrenAccObj( pAcc );
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+}
+
+bool AccDescendantManagerEventListener::NotifyChildEvent(UnoMSAAEvent eWinEvent, const Any& Value)
+{
+ Reference< XAccessible > xChild;
+ if(Value >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->NotifyAccEvent(eWinEvent, pAcc);
+
+ if (pAgent->IsStateManageDescendant(m_xAccessible.get()))
+ {
+ if (eWinEvent == UnoMSAAEvent::SELECTION_CHANGED_REMOVE)
+ {
+ // The object has just been sent in a SELECTION_CHANGED_REMOVE event
+ // and accessibility tools may query for the object and call methods on
+ // it as a response to this.
+ // Therefore, don't delete the object yet, but remember it for deletion
+ // once the next event of a different type occurs.
+ m_aUnselectedChildrenForDeletion.push_back(pAcc);
+ }
+ else
+ {
+ // handle any pending deletions for objects previously removed from selection
+ for (XAccessible* pAcc2 : m_aUnselectedChildrenForDeletion)
+ pAgent->DeleteAccObj(pAcc2);
+ m_aUnselectedChildrenForDeletion.clear();
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+void AccDescendantManagerEventListener::HandleSelectionChangedAddEvent(const Any& /*oldValue*/, const Any &newValue)
+{
+ if (NotifyChildEvent(UnoMSAAEvent::SELECTION_CHANGED_ADD, newValue))
+ {
+ return ;
+ }
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED_ADD, m_xAccessible.get());
+}
+
+void AccDescendantManagerEventListener::HandleSelectionChangedRemoveEvent(const Any& /*oldValue*/, const Any &newValue)
+{
+ if (NotifyChildEvent(UnoMSAAEvent::SELECTION_CHANGED_REMOVE, newValue))
+ {
+ return ;
+ }
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED_REMOVE, m_xAccessible.get());
+}
+
+void AccDescendantManagerEventListener::HandleSelectionChangedWithinEvent(const Any& /*oldValue*/, const Any &newValue)
+{
+ if (NotifyChildEvent(UnoMSAAEvent::SELECTION_CHANGED_WITHIN, newValue))
+ {
+ return ;
+ }
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED_WITHIN, m_xAccessible.get());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccDialogEventListener.cxx b/winaccessibility/source/service/AccDialogEventListener.cxx
new file mode 100644
index 000000000..865a039a7
--- /dev/null
+++ b/winaccessibility/source/service/AccDialogEventListener.cxx
@@ -0,0 +1,133 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccDialogEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccDialogEventListener::AccDialogEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccEventListener(pAcc, Agent)
+{}
+AccDialogEventListener::~AccDialogEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccDialogEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::CHILD:
+ HandleChildChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::VISIBLE_DATA_CHANGED:
+ HandleVisibleDataChangedEvent();
+ break;
+ case AccessibleEventId::BOUNDRECT_CHANGED:
+ HandleBoundrectChangedEvent();
+ break;
+ default:
+ AccEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the CHILD event
+ * @param oldValue the child to be deleted
+ * @param newValue the child to be added
+ */
+void AccDialogEventListener::HandleChildChangedEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+ if( newValue >>= xChild)
+ {
+ //create a new child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ //add this child
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ //add all oldValue's existing children
+ pAgent->InsertChildrenAccObj(pAcc);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_ADDED, pAcc);
+ }
+ }
+ else if (oldValue >>= xChild)
+ {
+ //delete an existing child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_REMOVED, pAcc);
+ //delete all oldValue's existing children
+ pAgent->DeleteChildrenAccObj( pAcc );
+ //delete this child
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+
+}
+
+/**
+ * set the new state and fire the MSAA event
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccDialogEventListener::SetComponentState(short state, bool enable)
+{
+ // only the following state can be fired state event.
+ switch (state)
+ {
+ case AccessibleStateType::ICONIFIED:
+ // no msaa state mapping
+ break;
+ case AccessibleStateType::VISIBLE:
+ // UNO !VISIBLE == MSAA INVISIBLE
+ if( enable )
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ else
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ break;
+ case AccessibleStateType::ACTIVE:
+ // Only frames should be active
+ // no msaa state mapping
+ break;
+ default:
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccEventListener.cxx b/winaccessibility/source/service/AccEventListener.cxx
new file mode 100644
index 000000000..fd8636099
--- /dev/null
+++ b/winaccessibility/source/service/AccEventListener.cxx
@@ -0,0 +1,260 @@
+/* -*- 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 <cppuhelper/bootstrap.hxx>
+#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+
+#include <stdio.h>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+using namespace cppu;
+
+AccEventListener::AccEventListener(css::accessibility::XAccessible* pAcc,
+ AccObjectManagerAgent* Agent)
+ : m_xAccessible(pAcc)
+ , pAgent(Agent)
+{
+}
+
+AccEventListener::~AccEventListener() {}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccEventListener::notifyEvent(const css::accessibility::AccessibleEventObject& aEvent)
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::NAME_CHANGED:
+ HandleNameChangedEvent(aEvent.NewValue);
+ break;
+ case AccessibleEventId::DESCRIPTION_CHANGED:
+ HandleDescriptionChangedEvent();
+ break;
+ case AccessibleEventId::STATE_CHANGED:
+ HandleStateChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * handle the NAME_CHANGED event
+ * @param name the new name with changed.
+ */
+void AccEventListener::HandleNameChangedEvent(Any name)
+{
+ if (pAgent->IsTopWinAcc(m_xAccessible.get()))
+ {
+ XAccessible* pAccDoc = pAgent->GetAccDocByAccTopWin(m_xAccessible.get());
+ if (pAccDoc)
+ {
+ pAgent->UpdateAccName(pAccDoc);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_NAMECHANGE, pAccDoc);
+ }
+ }
+
+ pAgent->UpdateAccName(m_xAccessible.get(), name);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_NAMECHANGE, m_xAccessible.get());
+}
+
+/**
+ * handle the DESCRIPTION_CHANGED event
+ */
+void AccEventListener::HandleDescriptionChangedEvent()
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_DESCRIPTIONCHANGE, m_xAccessible.get());
+}
+
+/**
+ * handle the BOUNDRECT_CHANGED event
+ */
+void AccEventListener::HandleBoundrectChangedEvent()
+{
+ AccObjectManagerAgent::UpdateLocation(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::BOUNDRECT_CHANGED, m_xAccessible.get());
+}
+
+/**
+ * handle the VISIBLE_DATA_CHANGED event
+ */
+void AccEventListener::HandleVisibleDataChangedEvent()
+{
+ pAgent->UpdateValue(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::VISIBLE_DATA_CHANGED, m_xAccessible.get());
+}
+
+/**
+ * handle the STATE_CHANGED event
+ * @param oldValue the old state of the source of event
+ * @param newValue the new state of the source of event
+ */
+void AccEventListener::HandleStateChangedEvent(Any oldValue, Any newValue)
+{
+ short newV, oldV;
+ if (newValue >>= newV)
+ {
+ SetComponentState(newV, true);
+ }
+ else if (oldValue >>= oldV)
+ {
+ SetComponentState(oldV, false);
+ }
+}
+
+/**
+ * set the new state and fire the MSAA event
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccEventListener::SetComponentState(short state, bool enable)
+{
+ switch (state)
+ {
+ case AccessibleStateType::FOCUSED:
+ FireStateFocusedChange(enable);
+ break;
+ default:
+ FireStatePropertyChange(state, enable);
+ break;
+ }
+}
+
+/**
+ * handle the focused event
+ * @param enable true if get focus, false if lose focus
+ */
+void AccEventListener::FireStateFocusedChange(bool enable)
+{
+ if (enable)
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::FOCUSED);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::STATE_FOCUSED, m_xAccessible.get());
+ }
+ else
+ {
+ // no focus lost event in MSAA
+ }
+}
+
+/**
+ * fire the MSAA state changed event
+ * @param state the state id
+ * @param set true if state is set, false if state is unset
+ */
+void AccEventListener::FireStatePropertyChange(short /*state*/, bool set)
+{
+ if (set)
+ {
+ //get new state
+ }
+ else
+ {
+ //lose old state
+ }
+}
+
+/**
+ * get the role of accessible object which is observed
+ */
+short AccEventListener::GetRole()
+{
+ css::uno::Reference<css::accessibility::XAccessibleContext> const xContext(
+ m_xAccessible->getAccessibleContext());
+ if (xContext.is())
+ {
+ return xContext->getAccessibleRole();
+ }
+ return -1;
+}
+
+/**
+ * get the role of accessible parent object which is observed
+ */
+short AccEventListener::GetParentRole()
+{
+ if (m_xAccessible.is())
+ {
+ return pAgent->GetParentRole(m_xAccessible.get());
+ }
+ return -1;
+}
+/**
+ * remove the listener from accessible object
+ */
+void AccEventListener::RemoveMeFromBroadcaster()
+{
+ try
+ {
+ if (!m_xAccessible.is())
+ {
+ return;
+ }
+ try
+ {
+ css::uno::Reference<XAccessibleEventBroadcaster> const xBroadcaster(
+ m_xAccessible->getAccessibleContext(), UNO_QUERY);
+ if (xBroadcaster.is())
+ {
+ //remove the lister from accessible object
+ xBroadcaster->removeAccessibleEventListener(this);
+ }
+ }
+ catch (Exception const&)
+ { // may throw if it's already disposed - ignore that
+ }
+ pAgent->NotifyDestroy(m_xAccessible.get());
+ m_xAccessible.clear(); // release cyclic reference
+ }
+ catch (...)
+ {
+ return;
+ }
+}
+
+/**
+ * this method is invoked before listener is disposed
+ */
+void AccEventListener::disposing(const css::lang::EventObject& /*Source*/)
+{
+ SolarMutexGuard g;
+
+ RemoveMeFromBroadcaster();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccFrameEventListener.cxx b/winaccessibility/source/service/AccFrameEventListener.cxx
new file mode 100644
index 000000000..bae97a1ca
--- /dev/null
+++ b/winaccessibility/source/service/AccFrameEventListener.cxx
@@ -0,0 +1,145 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccFrameEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+#include <vcl/window.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <vcl/sysdata.hxx>
+
+AccFrameEventListener::AccFrameEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccEventListener(pAcc, Agent)
+{
+}
+
+AccFrameEventListener::~AccFrameEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccFrameEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::CHILD:
+ HandleChildChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::VISIBLE_DATA_CHANGED:
+ HandleVisibleDataChangedEvent();
+ break;
+ case AccessibleEventId::BOUNDRECT_CHANGED:
+ HandleBoundrectChangedEvent();
+ break;
+ default:
+ AccEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the CHILD event
+ * @param oldValue the child to be deleted
+ * @param newValue the child to be added
+ */
+void AccFrameEventListener::HandleChildChangedEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+ if( newValue >>= xChild)
+ {
+ //create a new child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+
+ VCLXWindow* pvclwindow = dynamic_cast<VCLXWindow*>(m_xAccessible.get());
+ assert(pvclwindow);
+ const SystemEnvData* systemdata
+ = pvclwindow->GetWindow()->GetSystemData();
+
+ //add this child
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get(), systemdata->hWnd);
+ //add all oldValue's existing children
+ pAgent->InsertChildrenAccObj(pAcc);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_ADDED, pAcc);
+ }
+ }
+ else if (oldValue >>= xChild)
+ {
+ //delete an existing child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_REMOVED, pAcc);
+ //delete all oldValue's existing children
+ pAgent->DeleteChildrenAccObj( pAcc );
+ //delete this child
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+
+}
+
+/**
+ * set the new state and fire the MSAA event
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccFrameEventListener::SetComponentState(short state, bool enable )
+{
+ // only the following state can be fired state event.
+ switch (state)
+ {
+ case AccessibleStateType::ICONIFIED:
+ // no msaa state
+ break;
+ case AccessibleStateType::VISIBLE:
+ // UNO !VISIBLE == MSAA INVISIBLE
+ if( enable )
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ else
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ break;
+ case AccessibleStateType::ACTIVE:
+ // Only frames should be active
+ // no msaa state mapping
+ break;
+ default:
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccListEventListener.cxx b/winaccessibility/source/service/AccListEventListener.cxx
new file mode 100644
index 000000000..b4ecb9f77
--- /dev/null
+++ b/winaccessibility/source/service/AccListEventListener.cxx
@@ -0,0 +1,126 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccListEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccListEventListener::AccListEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccDescendantManagerEventListener(pAcc, Agent)
+{
+}
+
+AccListEventListener::~AccListEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccListEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
+ HandleActiveDescendantChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::INVALIDATE_ALL_CHILDREN:
+ // Since List items a transient a child events are mostly used
+ // to attach/detach listeners, it is safe to ignore it here
+ //TODO: investigate again
+ break;
+ case AccessibleEventId::VALUE_CHANGED:
+ HandleValueChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ default:
+ AccDescendantManagerEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the ACTIVE_DESCENDANT_CHANGED event
+ * @param oldValue the child to lose active
+ * @param newValue the child to get active
+ */
+void AccListEventListener::HandleActiveDescendantChangedEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+
+ if(newValue >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+
+ // Valueset has cache the child item xacc,Update state if no insert obj
+ bool bHasCache = pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ if (!bHasCache)
+ {
+ pAgent->UpdateState(pAcc);
+ }
+
+ pAgent->IncreaseState( pAcc, AccessibleStateType::FOCUSED);
+
+ pAgent->NotifyAccEvent(UnoMSAAEvent::ACTIVE_DESCENDANT_CHANGED, pAcc);
+ }
+ }
+ if (oldValue >>= xChild)
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+}
+
+/**
+ * handle the VALUE_CHANGED event
+ *
+ * @param oldValue the old value of the source of event
+ * @param newValue the new value of the source of event
+ */
+void AccListEventListener::HandleValueChangedEvent(Any, Any)
+{
+ //to enable value changed event
+ if (GetParentRole() == AccessibleRole::COMBO_BOX)
+ {
+ XAccessible* pParentAcc =
+ pAgent->GetParentXAccessible(m_xAccessible.get());
+ pAgent->UpdateValue(pParentAcc);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_VALUECHANGE, pParentAcc);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccMenuEventListener.cxx b/winaccessibility/source/service/AccMenuEventListener.cxx
new file mode 100644
index 000000000..05d78b9b0
--- /dev/null
+++ b/winaccessibility/source/service/AccMenuEventListener.cxx
@@ -0,0 +1,147 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccMenuEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccMenuEventListener::AccMenuEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccComponentEventListener(pAcc, Agent)
+{}
+AccMenuEventListener::~AccMenuEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccMenuEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::CHILD:
+ HandleChildChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::SELECTION_CHANGED:
+ //don't need to process anything,just same as word behavior
+ //handleSelectionChangedEvent();
+ break;
+ default:
+ AccComponentEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the CHILD event
+ * @param oldValue the child to be deleted
+ * @param newValue the child to be added
+ */
+void AccMenuEventListener::HandleChildChangedEvent(Any oldValue, Any newValue)
+{
+
+ Reference< XAccessible > xChild;
+ if( newValue >>= xChild)
+ {
+ //create a new child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ //add this child
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ //add all oldValue's existing children
+ pAgent->InsertChildrenAccObj(pAcc);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_ADDED, pAcc);
+ }
+ }
+ else if (oldValue >>= xChild)
+ {
+ //delete an existing child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_REMOVED, pAcc);
+ //delete all oldValue's existing children
+ pAgent->DeleteChildrenAccObj( pAcc );
+ //delete this child
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+
+}
+
+/**
+ * handle the SELECTION_CHANGED event
+ */
+void AccMenuEventListener::HandleSelectionChangedEventNoArgs()
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::SELECTION_CHANGED, m_xAccessible.get());
+}
+
+/**
+ * handle the Menu_popup event
+ */
+void AccMenuEventListener::FireStatePropertyChange(short state, bool set)
+{
+ if( set )
+ {
+ // new value
+ switch(state)
+ {
+ //for sub menu is popup, there is a menu selected event.
+ case AccessibleStateType::SELECTED:
+ pAgent->IncreaseState(m_xAccessible.get(), state);
+ pAgent->UpdateChildState(m_xAccessible.get());
+ break;
+ default:
+ AccComponentEventListener::FireStatePropertyChange(state, set);
+ break;
+ }
+ }
+ else
+ {
+ switch(state)
+ {
+ //for sub menu is popup, there is a menu selected event.
+ case AccessibleStateType::SELECTED:
+ pAgent->DecreaseState(m_xAccessible.get(), state);
+
+ break;
+ default:
+ AccComponentEventListener::FireStatePropertyChange(state, set);
+ break;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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: */
diff --git a/winaccessibility/source/service/AccObjectContainerEventListener.cxx b/winaccessibility/source/service/AccObjectContainerEventListener.cxx
new file mode 100644
index 000000000..429e99734
--- /dev/null
+++ b/winaccessibility/source/service/AccObjectContainerEventListener.cxx
@@ -0,0 +1,68 @@
+/* -*- 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 .
+ */
+
+// AccObjectContainerEventListener.cpp: implementation of the AccContainerEventListener class.
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <AccObjectContainerEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccObjectContainerEventListener::AccObjectContainerEventListener(
+ css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ : AccContainerEventListener(pAcc, Agent)
+{
+}
+AccObjectContainerEventListener::~AccObjectContainerEventListener() {}
+
+/**
+ * handle the STATE_CHANGED event
+ */
+void AccObjectContainerEventListener::HandleStateChangedEvent(Any oldValue, Any newValue)
+{
+ //set the accessible name before process for there is no NAME_CHANGED event when change
+ //the text in drawing objects.
+ short newV;
+ if (newValue >>= newV)
+ {
+ if (newV == AccessibleStateType::FOCUSED)
+ {
+ pAgent->UpdateAccName(m_xAccessible.get());
+ }
+ }
+ AccContainerEventListener::HandleStateChangedEvent(oldValue, newValue);
+}
+/**
+ * handle the VISIBLE_DATA_CHANGED event
+ * For SHAPES, the visible_data_changed event should be mapped to LOCATION_CHANGED event
+ */
+void AccObjectContainerEventListener::HandleVisibleDataChangedEvent()
+{
+ AccContainerEventListener::HandleBoundrectChangedEvent();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccObjectManagerAgent.cxx b/winaccessibility/source/service/AccObjectManagerAgent.cxx
new file mode 100644
index 000000000..b67a2294e
--- /dev/null
+++ b/winaccessibility/source/service/AccObjectManagerAgent.cxx
@@ -0,0 +1,384 @@
+/* -*- 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 <AccObjectManagerAgent.hxx>
+#include <AccObjectWinManager.hxx>
+
+#if defined __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
+#endif
+#include <UAccCOM.h>
+#if defined __clang__
+#pragma clang diagnostic pop
+#endif
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+/**
+ * Construction/Destruction.
+ * @param
+ * @return
+ */
+AccObjectManagerAgent::AccObjectManagerAgent()
+ : pWinManager(new AccObjectWinManager(this))
+{
+}
+
+AccObjectManagerAgent::~AccObjectManagerAgent()
+{
+}
+
+/**
+ * Interface of updating MSAA name when UNO name_changed event occurs.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return
+ */
+void AccObjectManagerAgent::UpdateAccName( XAccessible* pXAcc )
+{
+ if( pWinManager )
+ pWinManager->UpdateAccName( pXAcc );
+}
+
+/**
+ * Interface of updating MSAA name when UNO action changed event occurs.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return
+ */
+void AccObjectManagerAgent::UpdateAction( XAccessible* pXAcc )
+{
+ if( pWinManager )
+ pWinManager->UpdateAction( pXAcc );
+}
+
+/**
+ * Interface of updating MSAA value when UNO value_changed event occurs.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param pAny New value.
+ * @return
+ */
+void AccObjectManagerAgent::UpdateValue( XAccessible* pXAcc, Any pAny )
+{
+ if( pWinManager )
+ pWinManager->SetValue( pXAcc, pAny );
+}
+
+/**
+ * Interface of updating MSAA value when UNO value_changed event occurs. If we can not
+ * find new value, we'll get new value from pXAcc to update com value.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return
+ */
+void AccObjectManagerAgent::UpdateValue( XAccessible* pXAcc )
+{
+ if( pWinManager )
+ pWinManager->UpdateValue( pXAcc );
+}
+
+/**
+ * Interface of updating MSAA name when UNO name_changed event occurs.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param newName New UNO accessible name.
+ * @return
+ */
+void AccObjectManagerAgent::UpdateAccName( XAccessible* pXAcc, Any newName)
+{
+ if( pWinManager )
+ pWinManager->SetAccName( pXAcc, newName );
+}
+
+
+/**
+ * Interface of updating MSAA location when UNO location_changed event occurs.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param pXAcc Uno The top position of new location.
+ * @param pXAcc Uno The left position of new location.
+ * @param pXAcc Uno The width of new location.
+ * @param pXAcc Uno The width of new location.
+ * @return
+ */
+void AccObjectManagerAgent::UpdateLocation( XAccessible* /* pXAcc */, long /*top*/, long /*left*/, long /*width*/, long /*height*/ )
+{
+#ifdef _IMPL_WIN
+ if( pWinManager )
+ pWinManager->SetLocation( pXAcc, top, left, width, height );
+#endif
+}
+
+/**
+ * When a new UNO XAccessible object is found by listener, we create a corresponding
+ * com object and insert it to our manager list.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param pWnd The top window handle containing control.
+ * @return If the method is correctly processed.
+ */
+bool AccObjectManagerAgent::InsertAccObj(
+ XAccessible* pXAcc, XAccessible* pParentXAcc, HWND hWnd)
+{
+ if( pWinManager )
+ return pWinManager->InsertAccObj(pXAcc, pParentXAcc, hWnd);
+
+ return false;
+}
+
+/**
+ * save the pair <topwindowhandle, XAccessible>
+ * @param hWnd, top window handle
+ * @param pXAcc XAccessible interface for top window
+ * @return void
+ */
+void
+AccObjectManagerAgent::SaveTopWindowHandle(HWND hWnd, XAccessible* pXAcc)
+{
+ if( pWinManager )
+ pWinManager->SaveTopWindowHandle(hWnd, pXAcc);
+}
+
+
+/**
+ * When a UNO XAccessible object's new children are found by listener, we create
+ * corresponding com objects and insert them to our manager list.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param pWnd The top window handle containing control.
+ * @return If the method is correctly processed.
+ */
+bool
+AccObjectManagerAgent::InsertChildrenAccObj(XAccessible* pXAcc, HWND hWnd)
+{
+ if( pWinManager )
+ return pWinManager->InsertChildrenAccObj(pXAcc, hWnd);
+
+ return false;
+}
+
+/**
+ * When a new UNO XAccessible object is destroyed, we delete its corresponding
+ * com object and remove it from our manager list.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return
+ */
+void AccObjectManagerAgent::DeleteAccObj( XAccessible* pXAcc )
+{
+ if( pWinManager )
+ pWinManager->DeleteAccObj( pXAcc );
+}
+
+/**
+ * When new UNO children XAccessible objects are destroyed, we delete their
+ * corresponding com objects and remove them from our manager list.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return
+ */
+void AccObjectManagerAgent::DeleteChildrenAccObj( XAccessible* pXAcc )
+{
+ if( pWinManager )
+ pWinManager->DeleteChildrenAccObj( pXAcc );
+}
+
+/**
+ * Interface of decreasing MSAA state when some UNO state is decreased.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param pState The lost state of control.
+ * @return
+ */
+void AccObjectManagerAgent::DecreaseState( XAccessible* pXAcc,unsigned short pState )
+{
+ if(pWinManager)
+ {
+ pWinManager->DecreaseState( pXAcc, pState );
+ }
+}
+
+/**
+ * Interface of increasing MSAA name when some UNO state is increased.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param pState The new state of control.
+ * @return
+ */
+void AccObjectManagerAgent::IncreaseState( XAccessible* pXAcc,unsigned short pState )
+{
+ if(pWinManager)
+ {
+ pWinManager->IncreaseState( pXAcc, pState );
+ }
+}
+
+void AccObjectManagerAgent::UpdateState( css::accessibility::XAccessible* pXAcc )
+{
+ if(pWinManager)
+ pWinManager->UpdateState(pXAcc);
+}
+
+/**
+ * Interface of notify MSAA event when some UNO event occurred.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @param eEvent event type.
+ * @return If the method is correctly processed.
+ */
+bool AccObjectManagerAgent::NotifyAccEvent(UnoMSAAEvent eEvent, XAccessible* pXAcc)
+{
+ if(pWinManager)
+ return pWinManager->NotifyAccEvent(pXAcc, eEvent);
+
+ return false;
+}
+
+/**
+ * Judge whether a XAccessible object is a container object.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return If the method is correctly processed.
+ */
+bool AccObjectManagerAgent::IsContainer( XAccessible* pXAcc )
+{
+ if(pWinManager)
+ return AccObjectWinManager::IsContainer(pXAcc);
+
+ return false;
+}
+
+/**
+ * Return com object interface by querying XAccessible interface.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return Com interface.
+ */
+IMAccessible* AccObjectManagerAgent::GetIMAccByXAcc(XAccessible* pXAcc)
+{
+ if(pWinManager)
+ return pWinManager->GetIMAccByXAcc(pXAcc);
+
+ return nullptr;
+}
+
+/**
+ * Notify manager when a XAccessible object is destroying.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return.
+ */
+void AccObjectManagerAgent::NotifyDestroy(XAccessible* pXAcc)
+{
+ if(pWinManager)
+ pWinManager->NotifyDestroy(pXAcc);
+}
+
+/**
+ * Return com object interface by querying child id.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return Com interface.
+ */
+void AccObjectManagerAgent::GetIAccessibleFromResID(long childID,IMAccessible** pIMAcc)
+{
+ if(pWinManager)
+ *pIMAcc = pWinManager->GetIAccessibleFromResID(childID);
+}
+
+/**
+ * Return object interface by querying interface.
+ * @param pXAcc Uno XAccessible interface of control.
+ * @return Com interface.
+ */
+bool AccObjectManagerAgent::GetIAccessibleFromXAccessible(
+ XAccessible* pXAcc, IAccessible** ppXI)
+{
+ if(pWinManager)
+ {
+ *ppXI = pWinManager->GetIMAccByXAcc(pXAcc);
+ if(*ppXI)
+ return true;
+ }
+ return false;
+}
+
+XAccessible* AccObjectManagerAgent::GetParentXAccessible( XAccessible* pXAcc )
+{
+ if(pWinManager)
+ return pWinManager->GetParentXAccessible( pXAcc );
+
+ return nullptr;
+}
+
+short AccObjectManagerAgent::GetParentRole( XAccessible* pXAcc )
+{
+ if(pWinManager)
+ return pWinManager->GetParentRole( pXAcc );
+
+ return -1;
+}
+
+void AccObjectManagerAgent::UpdateChildState(XAccessible* pXAcc)
+{
+ if(pWinManager)
+ pWinManager->UpdateChildState( pXAcc );
+}
+
+
+bool AccObjectManagerAgent::IsSpecialToolbarItem(XAccessible* pXAcc)
+{
+ if(pWinManager)
+ return pWinManager->IsSpecialToolbarItem(pXAcc);
+
+ return false;
+}
+
+short AccObjectManagerAgent::GetRole(XAccessible* pXAcc)
+{
+ if(pWinManager)
+ return AccObjectWinManager::GetRole( pXAcc );
+
+ return -1;
+}
+
+XAccessible* AccObjectManagerAgent::GetAccDocByAccTopWin( XAccessible* pXAcc )
+{
+ if (pWinManager)
+ {
+ return pWinManager->GetAccDocByAccTopWin( pXAcc );
+ }
+ return nullptr;
+}
+bool AccObjectManagerAgent::IsTopWinAcc(XAccessible* pXAcc)
+{
+ if (pWinManager)
+ {
+ return pWinManager->IsTopWinAcc( pXAcc );
+ }
+ return false;
+}
+
+bool AccObjectManagerAgent::IsStateManageDescendant(XAccessible* pXAcc)
+{
+ if(pWinManager)
+ return AccObjectWinManager::IsStateManageDescendant( pXAcc );
+
+ return false;
+}
+
+/**
+ * Implementation of interface XMSAAService's method getAccObjectPtr()
+ * that returns the corresponding COM interface with the MS event.
+ * @return Com interface.
+ */
+sal_Int64 AccObjectManagerAgent::Get_ToATInterface(
+ sal_Int64 hWnd, sal_Int64 lParam, sal_Int64 wParam)
+{
+ return static_cast<sal_Int64>(pWinManager->Get_ToATInterface(
+ static_cast<HWND>(reinterpret_cast<void*>(hWnd)), lParam, wParam));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccObjectWinManager.cxx b/winaccessibility/source/service/AccObjectWinManager.cxx
new file mode 100644
index 000000000..bcde1ccf4
--- /dev/null
+++ b/winaccessibility/source/service/AccObjectWinManager.cxx
@@ -0,0 +1,1202 @@
+/* -*- 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 <cassert>
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+
+#include <oleacc.h>
+#include <AccObjectWinManager.hxx>
+#include <AccEventListener.hxx>
+#include <AccComponentEventListener.hxx>
+#include <AccContainerEventListener.hxx>
+#include <AccDialogEventListener.hxx>
+#include <AccWindowEventListener.hxx>
+#include <AccFrameEventListener.hxx>
+#include <AccMenuEventListener.hxx>
+#include <AccObjectContainerEventListener.hxx>
+#include <AccParagraphEventListener.hxx>
+#include <AccTextComponentEventListener.hxx>
+#include <AccListEventListener.hxx>
+#include <AccTreeEventListener.hxx>
+#include <AccTableEventListener.hxx>
+#include <AccObject.hxx>
+#include <unomsaaevent.hxx>
+
+
+using namespace com::sun::star::accessibility;
+using namespace com::sun::star::uno;
+
+/**
+ * constructor
+ * @param Agent The agent kept in all listeners,it's the sole interface by which
+ * listener communicate with windows manager.
+ * pEventAccObj The present event accobject.
+ * oldFocus Last focused object.
+ * isSelectionChanged flag that identifies if there is selection changed.
+ * selectionChildObj Selected object.
+ * dChildID Chile resource ID.
+ * hAcc TopWindowHWND
+ * @return
+ */
+AccObjectWinManager::AccObjectWinManager( AccObjectManagerAgent* Agent ):
+ oldFocus( nullptr ),
+ pAgent( Agent )
+{
+}
+
+/**
+ * Destructor,clear all resource.
+ * @param
+ * @return
+ */
+AccObjectWinManager::~AccObjectWinManager()
+{
+ XIdAccList.clear();
+ HwndXAcc.clear();
+ XResIdAccList.clear();
+ XHWNDDocList.clear();
+}
+
+
+/**
+ * Get valid com object interface when notifying some MSAA event
+ * @param pWND The top window handle that contains that event control.
+ * @param wParam Windows system interface.
+ * @return Com interface with event.
+ */
+
+LRESULT
+AccObjectWinManager::Get_ToATInterface(HWND hWnd, long lParam, WPARAM wParam)
+{
+ IMAccessible* pRetIMAcc = nullptr;
+
+ if(lParam == OBJID_CLIENT )
+ {
+ AccObject* topWindowAccObj = GetTopWindowAccObj(hWnd);
+ if(topWindowAccObj)
+ {
+ pRetIMAcc = topWindowAccObj->GetIMAccessible();
+ if(pRetIMAcc)
+ pRetIMAcc->AddRef();//increase COM reference count
+ }
+ }
+
+ if ( pRetIMAcc && lParam == OBJID_CLIENT )
+ {
+ LRESULT result = LresultFromObject(IID_IAccessible, wParam, pRetIMAcc);
+ pRetIMAcc->Release();
+ return result;
+ }
+ return 0;
+}
+
+/**
+ * Search AccObject by XAccessible pointer from our container.
+ * @param pXAcc XAccessible interface.
+ * @return Pointer of accObject that is found.
+ */
+AccObject* AccObjectWinManager::GetAccObjByXAcc( XAccessible* pXAcc)
+{
+ if( pXAcc == nullptr)
+ return nullptr;
+
+ XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
+ if ( pIndTemp == XIdAccList.end() )
+ return nullptr;
+
+ return &(pIndTemp->second);
+}
+
+/**
+ * get acc object of top window by its handle
+ * @param hWnd, top window handle
+ * @return pointer to AccObject
+ */
+AccObject* AccObjectWinManager::GetTopWindowAccObj(HWND hWnd)
+{
+ XHWNDToXAccHash::iterator iterResult =HwndXAcc.find(hWnd);
+ if(iterResult == HwndXAcc.end())
+ return nullptr;
+ XAccessible* pXAcc = iterResult->second;
+ return GetAccObjByXAcc(pXAcc);
+}
+
+/**
+ * Simulate MSAA event via XAccessible interface and event type.
+ * @param pXAcc XAccessible interface.
+ * @param eEvent event type
+ * @return The terminate result that identifies if the call is successful.
+ */
+bool AccObjectWinManager::NotifyAccEvent(XAccessible* pXAcc, UnoMSAAEvent eEvent)
+{
+ Reference< XAccessibleContext > pRContext;
+
+ if( pXAcc == nullptr)
+ return false;
+
+
+ pRContext = pXAcc->getAccessibleContext();
+ if( !pRContext.is() )
+ return false;
+
+
+ AccObject* selfAccObj= GetAccObjByXAcc(pXAcc);
+
+ if(selfAccObj==nullptr)
+ return false;
+
+ long dChildID = selfAccObj->GetResID();
+ HWND hAcc = selfAccObj->GetParentHWND();
+
+ switch(eEvent)
+ {
+ case UnoMSAAEvent::STATE_FOCUSED:
+ {
+ UpdateAccFocus(pXAcc);
+ selfAccObj->UpdateDefaultAction( );
+ UpdateValue(pXAcc);
+ NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ }
+ case UnoMSAAEvent::STATE_BUSY:
+ NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::STATE_CHECKED:
+ NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::STATE_PRESSED:
+ NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+
+ //Removed fire out selected event
+ //case UnoMSAAEvent::STATE_SELECTED:
+ // NotifyWinEvent( EVENT_OBJECT_STATECHANGE,hAcc, OBJID_CLIENT,dChildID );
+ // break;
+ case UnoMSAAEvent::STATE_ARMED:
+ UpdateAccFocus(pXAcc);
+ NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::MENU_START:
+ NotifyWinEvent( EVENT_SYSTEM_MENUSTART,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::MENU_END:
+ NotifyWinEvent( EVENT_SYSTEM_MENUEND,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::MENUPOPUPSTART:
+ NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPSTART,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::MENUPOPUPEND:
+ NotifyWinEvent( EVENT_SYSTEM_MENUPOPUPEND,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::SELECTION_CHANGED:
+ NotifyWinEvent( EVENT_OBJECT_SELECTION,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::SELECTION_CHANGED_ADD:
+ NotifyWinEvent( EVENT_OBJECT_SELECTIONADD,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::SELECTION_CHANGED_REMOVE:
+ NotifyWinEvent( EVENT_OBJECT_SELECTIONREMOVE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::SELECTION_CHANGED_WITHIN:
+ NotifyWinEvent( EVENT_OBJECT_SELECTIONWITHIN,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_VALUECHANGE:
+ UpdateValue(pXAcc);
+ NotifyWinEvent( EVENT_OBJECT_VALUECHANGE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_NAMECHANGE:
+ NotifyWinEvent( EVENT_OBJECT_NAMECHANGE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_DESCRIPTIONCHANGE:
+ NotifyWinEvent( EVENT_OBJECT_DESCRIPTIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_DEFACTIONCHANGE:
+ NotifyWinEvent( IA2_EVENT_ACTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_CARETCHANGE:
+ NotifyWinEvent( IA2_EVENT_TEXT_CARET_MOVED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_TEXTCHANGE:
+ NotifyWinEvent( IA2_EVENT_TEXT_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::ACTIVE_DESCENDANT_CHANGED:
+ UpdateAccFocus(pXAcc);
+ NotifyWinEvent( EVENT_OBJECT_FOCUS,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::BOUNDRECT_CHANGED:
+ NotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::VISIBLE_DATA_CHANGED:
+ NotifyWinEvent( IA2_EVENT_VISIBLE_DATA_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::SHOW :
+ NotifyWinEvent( EVENT_OBJECT_SHOW,hAcc, OBJID_CLIENT,dChildID );
+ NotifyWinEvent( EVENT_SYSTEM_FOREGROUND,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TABLE_CAPTION_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TABLE_CAPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TABLE_COLUMN_DESCRIPTION_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TABLE_COLUMN_HEADER_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TABLE_MODEL_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TABLE_MODEL_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TABLE_ROW_HEADER_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TABLE_ROW_HEADER_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TABLE_SUMMARY_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TABLE_SUMMARY_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TABLE_ROW_DESCRIPTION_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_REORDER:
+ NotifyWinEvent( EVENT_OBJECT_REORDER,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::PAGE_CHANGED:
+ NotifyWinEvent( IA2_EVENT_PAGE_CHANGED,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::CHILD_REMOVED:
+ NotifyWinEvent( EVENT_OBJECT_DESTROY,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::CHILD_ADDED:
+ NotifyWinEvent( EVENT_OBJECT_CREATE ,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::OBJECT_PAGECHANGED:
+ NotifyWinEvent( IA2_EVENT_PAGE_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::TEXT_SELECTION_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TEXT_SELECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::SECTION_CHANGED:
+ NotifyWinEvent( IA2_EVENT_SECTION_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ case UnoMSAAEvent::COLUMN_CHANGED:
+ NotifyWinEvent( IA2_EVENT_TEXT_COLUMN_CHANGED ,hAcc, OBJID_CLIENT,dChildID );
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+/**
+ * Get Parent XAccessible interface by XAccessible interface.
+ * @param pXAcc XAccessible interface.
+ * @return Parent XAccessible interface.
+ */
+XAccessible* AccObjectWinManager::GetParentXAccessible( XAccessible* pXAcc )
+{
+ AccObject* pObj= GetAccObjByXAcc(pXAcc);
+ if( pObj ==nullptr )
+ return nullptr;
+ if(pObj->GetParentObj())
+ {
+ pObj = pObj->GetParentObj();
+ return pObj->GetXAccessible().get();
+ }
+ return nullptr;
+}
+
+/**
+ * Get Parent role by XAccessible interface.
+ * @param pXAcc XAccessible interface.
+ * @return Parent role.
+ */
+short AccObjectWinManager::GetParentRole( XAccessible* pXAcc )
+{
+ AccObject* pObj= GetAccObjByXAcc(pXAcc);
+ if( pObj ==nullptr )
+ return -1;
+ if(pObj->GetParentObj())
+ {
+ pObj = pObj->GetParentObj();
+ if(pObj->GetXAccessible().is())
+ {
+ Reference< XAccessibleContext > pRContext = pObj->GetXAccessible()->getAccessibleContext();
+ if(pRContext.is())
+ return pRContext->getAccessibleRole();
+ }
+ }
+ return -1;
+}
+
+/**
+ * Update focus object by new focused XAccessible interface.
+ * @param newFocus New XAccessible interface that gets focus.
+ * @return
+ */
+void AccObjectWinManager::UpdateAccFocus(XAccessible* newFocus)
+{
+ AccObject* pAccObjNew = GetAccObjByXAcc(newFocus);
+ if(pAccObjNew)
+ {
+ AccObject* pAccObjOld = GetAccObjByXAcc(oldFocus);
+ oldFocus = newFocus;
+ pAccObjNew->setFocus();
+ //if old == new, the pAccObjNew will be without focused state
+ if (pAccObjOld && pAccObjOld != pAccObjNew)
+ pAccObjOld->unsetFocus();
+ }
+}
+
+/**
+ * Update selected object by new focused XAccessible interface.
+ * @param pXAcc XAccessible interface that has selected child changed.
+ * @return Selected children count.
+ */
+int AccObjectWinManager::UpdateAccSelection(XAccessible* pXAcc)
+{
+ Reference< XAccessibleContext > pRContext;
+
+ if( pXAcc == nullptr)
+ return 0;
+
+ pRContext = pXAcc->getAccessibleContext();
+ if( !pRContext.is() )
+ return 0;
+
+ Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
+ if( !pRSelection.is() )
+ return 0;
+
+ AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
+ if(pAccObj==nullptr)
+ return 0;
+
+ Reference<XAccessible> pRChild;
+ AccObject* pAccChildObj = nullptr;
+ int selectNum= pRSelection->getSelectedAccessibleChildCount();
+
+ IAccSelectionList oldSelection = pAccObj->GetSelection();
+
+ if(selectNum > 4)//for selected.
+ return selectNum;
+ if(selectNum == 1 && oldSelection.size() == 0)
+ return 1;
+
+ for (int i=0;i<selectNum;i++)
+ {
+ pRChild = pRSelection->getSelectedAccessibleChild(i);
+ if(!pRChild.is())
+ {
+ continue;
+ }
+ Reference<XAccessibleContext> pRChildContext = pRChild->getAccessibleContext();
+ if(!pRChildContext.is())
+ {
+ continue;
+ }
+ long index = pRChildContext->getAccessibleIndexInParent();
+ IAccSelectionList::iterator temp = oldSelection.find(index);
+ if ( temp != oldSelection.end() )
+ {
+ oldSelection.erase(index);
+ continue;
+ }
+
+ pAccChildObj = GetAccObjByXAcc(pRChild.get());
+ if(!pAccChildObj)
+ {
+ InsertAccObj(pRChild.get(), pXAcc,pAccObj->GetParentHWND());
+ pAccChildObj = GetAccObjByXAcc(pRChild.get());
+ }
+
+ pAccObj->AddSelect(index, pAccChildObj);
+
+ if(pAccChildObj != nullptr)
+ NotifyWinEvent(EVENT_OBJECT_SELECTIONADD,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
+ }
+
+ for (const auto& rEntry : oldSelection)
+ {
+ pAccObj->GetSelection().erase(rEntry.first);
+ pAccChildObj = rEntry.second;
+ if(pAccChildObj != nullptr)
+ NotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE,pAccObj->GetParentHWND(), OBJID_CLIENT,pAccChildObj->GetResID());
+ }
+ return 0;
+
+}
+
+/**
+ * Delete child element from children list.
+ * @param pObj Child element that should be removed from parent child list.
+ * @return
+ */
+void AccObjectWinManager::DeleteAccChildNode( AccObject* pObj )
+{
+ AccObject *parentAccObj = pObj->GetParentObj();
+ if( parentAccObj )
+ parentAccObj->DeleteChild( pObj );
+}
+
+/**
+ * Delete XAccessible items in top window handle hashtable
+ * @param pXAcc XAccessible interface.
+ * @return
+ */
+void AccObjectWinManager::DeleteFromHwndXAcc(XAccessible const * pXAcc )
+{
+ auto iter = std::find_if(HwndXAcc.begin(), HwndXAcc.end(),
+ [&pXAcc](XHWNDToXAccHash::value_type& rEntry) { return rEntry.second == pXAcc; });
+ if (iter != HwndXAcc.end())
+ HwndXAcc.erase(iter);
+}
+
+/**
+ * Delete all children with the tree root of XAccessible pointer
+ * @param pXAcc Tree root XAccessible interface.
+ * @return
+ */
+void AccObjectWinManager::DeleteChildrenAccObj(XAccessible* pXAcc)
+{
+ AccObject* currentObj=nullptr;
+ AccObject* childObj=nullptr;
+
+ currentObj = GetAccObjByXAcc( pXAcc);
+ if(currentObj)
+ {
+ childObj = currentObj->NextChild();
+ while(childObj)
+ {
+ XAccessible *const pTmpXAcc = childObj->GetXAccessible().get();
+ if(pTmpXAcc)
+ {
+ DeleteChildrenAccObj(pTmpXAcc);
+ DeleteAccObj(pTmpXAcc);
+ }
+ childObj = currentObj->NextChild();
+ }
+ }
+}
+
+/**
+ * Delete Acc object self.
+ * @param pXAcc The XAccessible interface.
+ * @return
+ */
+void AccObjectWinManager::DeleteAccObj( XAccessible* pXAcc )
+{
+ if( pXAcc == nullptr )
+ return;
+ XIdToAccObjHash::iterator temp = XIdAccList.find(pXAcc);
+ if( temp != XIdAccList.end() )
+ {
+ ResIdGen.SetSub( temp->second.GetResID() );
+ }
+ else
+ {
+ return;
+ }
+
+ AccObject& accObj = temp->second;
+ DeleteAccChildNode( &accObj );
+ DeleteAccListener( &accObj );
+ if( accObj.GetIMAccessible() )
+ {
+ accObj.GetIMAccessible()->Release();
+ }
+ size_t i = XResIdAccList.erase(accObj.GetResID());
+ assert(i != 0);
+ (void) i;
+ DeleteFromHwndXAcc(pXAcc);
+ if (accObj.GetRole() == AccessibleRole::DOCUMENT ||
+ accObj.GetRole() == AccessibleRole::DOCUMENT_PRESENTATION ||
+ accObj.GetRole() == AccessibleRole::DOCUMENT_SPREADSHEET ||
+ accObj.GetRole() == AccessibleRole::DOCUMENT_TEXT)
+ {
+ XHWNDDocList.erase(accObj.GetParentHWND());
+ }
+ XIdAccList.erase(pXAcc); // note: this invalidates accObj so do it last!
+}
+
+/**
+ * Delete listener that inspects some XAccessible object
+ * @param pAccObj Accobject pointer.
+ * @return
+ */
+void AccObjectWinManager::DeleteAccListener( AccObject* pAccObj )
+{
+ AccEventListener* listener = pAccObj->getListener();
+ if( listener==nullptr )
+ return;
+ listener->RemoveMeFromBroadcaster();
+ pAccObj->SetListener(nullptr);
+}
+
+/**
+ * Generate a child ID, which is used for AT
+ * @param
+ * @return New resource ID.
+ */
+inline long AccObjectWinManager::ImpleGenerateResID()
+{
+ return ResIdGen.GenerateNewResID();
+}
+
+/**
+ * Insert all children of the current acc object
+ * @param pXAcc XAccessible interface
+ * @param pWnd Top Window handle
+ * @return The calling result.
+ */
+bool AccObjectWinManager::InsertChildrenAccObj( css::accessibility::XAccessible* pXAcc,
+ HWND pWnd)
+{
+ if(!IsContainer(pXAcc))
+ return false;
+
+ Reference< XAccessibleContext > pRContext;
+
+ if( pXAcc == nullptr)
+ return false;
+ pRContext = pXAcc->getAccessibleContext();
+ if( !pRContext.is() )
+ return false;
+
+ short role = pRContext->getAccessibleRole();
+
+ if(css::accessibility::AccessibleRole::DOCUMENT == role ||
+ css::accessibility::AccessibleRole::DOCUMENT_PRESENTATION == role ||
+ css::accessibility::AccessibleRole::DOCUMENT_SPREADSHEET == role ||
+ css::accessibility::AccessibleRole::DOCUMENT_TEXT == role)
+ {
+ if(IsStateManageDescendant(pXAcc))
+ {
+ return true;
+ }
+ }
+
+ int count = pRContext->getAccessibleChildCount();
+ for (int i=0;i<count;i++)
+ {
+ Reference<XAccessible> mxAccessible
+ = pRContext->getAccessibleChild(i);
+ XAccessible* mpAccessible = mxAccessible.get();
+ if(mpAccessible != nullptr)
+ {
+ InsertAccObj( mpAccessible,pXAcc,pWnd );
+ InsertChildrenAccObj(mpAccessible,pWnd);
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Insert child object.
+ * @param pCurObj The child object
+ * @param pParentObj The parent object
+ * @param pWnd Top window handle.
+ * @return
+ */
+void AccObjectWinManager::InsertAccChildNode( AccObject* pCurObj, AccObject* pParentObj, HWND /* pWnd */ )
+{
+ if(pCurObj)
+ {
+ if(pParentObj)
+ {
+ pParentObj->InsertChild(pCurObj);
+ }
+ else
+ {
+ pCurObj->UpdateValidWindow();
+ }
+ }
+}
+
+/**
+ * Insert child object.
+ * @param pCurObj The child object
+ * @param pParentObj The parent object
+ * @param pWnd Top window handle.
+ * @return
+ */
+bool AccObjectWinManager::InsertAccObj( XAccessible* pXAcc,XAccessible* pParentXAcc,HWND pWnd )
+{
+ XIdToAccObjHash::iterator itXacc = XIdAccList.find( pXAcc );
+ if (itXacc != XIdAccList.end() )
+ {
+ short nCurRole =GetRole(pXAcc);
+ if (AccessibleRole::SHAPE == nCurRole)
+ {
+ AccObject &objXacc = itXacc->second;
+ AccObject *pObjParent = objXacc.GetParentObj();
+ if (pObjParent &&
+ pObjParent->GetXAccessible().is() &&
+ pObjParent->GetXAccessible().get() != pParentXAcc)
+ {
+ XIdToAccObjHash::iterator itXaccParent = XIdAccList.find( pParentXAcc );
+ if(itXaccParent != XIdAccList.end())
+ {
+ objXacc.SetParentObj(&(itXaccParent->second));
+ }
+ }
+ }
+ return false;
+ }
+
+
+ Reference< XAccessibleContext > pRContext;
+
+ if( pXAcc == nullptr)
+ return false;
+
+ pRContext = pXAcc->getAccessibleContext();
+ if( !pRContext.is() )
+ return false;
+
+ if( pWnd == nullptr )
+ {
+ if(pParentXAcc)
+ {
+ AccObject* pObj = GetAccObjByXAcc(pParentXAcc);
+ if(pObj)
+ pWnd = pObj->GetParentHWND();
+ }
+ if( pWnd == nullptr )
+ return false;
+ }
+
+ AccObject pObj( pXAcc,pAgent );
+ if( pObj.GetIMAccessible() == nullptr )
+ return false;
+ pObj.SetResID( this->ImpleGenerateResID());
+ pObj.SetParentHWND( pWnd );
+
+ //for file name support
+ if (pObj.GetRole() == AccessibleRole::DOCUMENT ||
+ pObj.GetRole() == AccessibleRole::DOCUMENT_PRESENTATION ||
+ pObj.GetRole() == AccessibleRole::DOCUMENT_SPREADSHEET ||
+ pObj.GetRole() == AccessibleRole::DOCUMENT_TEXT)
+ {
+ XHWNDToDocumentHash::iterator aIter = XHWNDDocList.find(pWnd);
+ if ( aIter != XHWNDDocList.end() )
+ {
+ XHWNDDocList.erase( aIter );
+ }
+ XHWNDDocList.emplace( pWnd, pXAcc );
+ }
+ //end of file name
+
+ ::rtl::Reference<AccEventListener> const pListener =
+ CreateAccEventListener(pXAcc);
+ if (!pListener.is())
+ return false;
+ Reference<XAccessibleComponent> xComponent(pRContext,UNO_QUERY);
+ Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
+ if (broadcaster.is())
+ {
+ Reference<XAccessibleEventListener> const xListener(pListener);
+ broadcaster->addAccessibleEventListener(xListener);
+ }
+ else
+ return false;
+
+ XIdAccList.emplace(pXAcc, pObj);
+ XIdToAccObjHash::iterator pIndTemp = XIdAccList.find( pXAcc );
+ XResIdAccList.emplace(pObj.GetResID(),&(pIndTemp->second));
+
+ AccObject* pCurObj = GetAccObjByXAcc(pXAcc);
+ if( pCurObj )
+ {
+ pCurObj->SetListener(pListener);
+ }
+
+ AccObject* pParentObj = GetAccObjByXAcc(pParentXAcc);
+ InsertAccChildNode(pCurObj,pParentObj,pWnd);
+ if( pCurObj )
+ pCurObj->UpdateAccessibleInfoFromUnoToMSAA();
+ return true;
+}
+
+
+/**
+ * save the pair <topwindowhandle, XAccessible>
+ * @param hWnd, top window handle
+ * @param pXAcc XAccessible interface for top window
+ * @return void
+ */
+void AccObjectWinManager::SaveTopWindowHandle(HWND hWnd, css::accessibility::XAccessible* pXAcc)
+{
+ HwndXAcc.emplace(hWnd,pXAcc);
+}
+
+
+/** Create the corresponding listener.
+ * @param pXAcc XAccessible interface.
+ */
+::rtl::Reference<AccEventListener>
+AccObjectWinManager::CreateAccEventListener(XAccessible* pXAcc)
+{
+ ::rtl::Reference<AccEventListener> pRet;
+ Reference<XAccessibleContext> xContext = pXAcc->getAccessibleContext();
+ if(xContext.is())
+ {
+ switch( xContext->getAccessibleRole() )
+ {
+ case AccessibleRole::DIALOG:
+ pRet = new AccDialogEventListener(pXAcc,pAgent);
+ break;
+ case AccessibleRole::FRAME:
+ pRet = new AccFrameEventListener(pXAcc,pAgent);
+ break;
+ case AccessibleRole::WINDOW:
+ pRet = new AccWindowEventListener(pXAcc,pAgent);
+ break;
+ case AccessibleRole::ROOT_PANE:
+ pRet = new AccFrameEventListener(pXAcc,pAgent);
+ break;
+ //Container
+ case AccessibleRole::CANVAS:
+ case AccessibleRole::COMBO_BOX:
+ case AccessibleRole::DOCUMENT:
+ case AccessibleRole::DOCUMENT_PRESENTATION:
+ case AccessibleRole::DOCUMENT_SPREADSHEET:
+ case AccessibleRole::DOCUMENT_TEXT:
+ case AccessibleRole::END_NOTE:
+ case AccessibleRole::FILLER:
+ case AccessibleRole::FOOTNOTE:
+ case AccessibleRole::FOOTER:
+ case AccessibleRole::HEADER:
+ case AccessibleRole::LAYERED_PANE:
+ case AccessibleRole::MENU_BAR:
+ case AccessibleRole::POPUP_MENU:
+ case AccessibleRole::OPTION_PANE:
+ case AccessibleRole::PAGE_TAB:
+ case AccessibleRole::PAGE_TAB_LIST:
+ case AccessibleRole::PANEL:
+ case AccessibleRole::SCROLL_PANE:
+ case AccessibleRole::SPLIT_PANE:
+ case AccessibleRole::STATUS_BAR:
+ case AccessibleRole::TABLE_CELL:
+ case AccessibleRole::TOOL_BAR:
+ case AccessibleRole::VIEW_PORT:
+ pRet = new AccContainerEventListener(pXAcc,pAgent);
+ break;
+ case AccessibleRole::PARAGRAPH:
+ case AccessibleRole::HEADING:
+ pRet = new AccParagraphEventListener(pXAcc,pAgent);
+ break;
+ //Component
+ case AccessibleRole::CHECK_BOX:
+ case AccessibleRole::ICON:
+ case AccessibleRole::LABEL:
+ case AccessibleRole::STATIC:
+ case AccessibleRole::MENU_ITEM:
+ case AccessibleRole::CHECK_MENU_ITEM:
+ case AccessibleRole::RADIO_MENU_ITEM:
+ case AccessibleRole::PUSH_BUTTON:
+ case AccessibleRole::RADIO_BUTTON:
+ case AccessibleRole::SCROLL_BAR:
+ case AccessibleRole::SEPARATOR:
+ case AccessibleRole::TOGGLE_BUTTON:
+ case AccessibleRole::BUTTON_DROPDOWN:
+ case AccessibleRole::TOOL_TIP:
+ case AccessibleRole::SPIN_BOX:
+ case AccessibleRole::DATE_EDITOR:
+ pRet = new AccComponentEventListener(pXAcc,pAgent);
+ break;
+ //text component
+ case AccessibleRole::TEXT:
+ pRet = new AccTextComponentEventListener(pXAcc,pAgent);
+ break;
+ //menu
+ case AccessibleRole::MENU:
+ pRet = new AccMenuEventListener(pXAcc,pAgent);
+ break;
+ //object container
+ case AccessibleRole::SHAPE:
+
+ case AccessibleRole::EMBEDDED_OBJECT:
+ case AccessibleRole::GRAPHIC:
+ case AccessibleRole::TEXT_FRAME:
+ pRet = new AccObjectContainerEventListener(pXAcc,pAgent);
+ break;
+ //descendmanager
+ case AccessibleRole::LIST:
+ pRet = new AccListEventListener(pXAcc,pAgent);
+ break;
+ case AccessibleRole::TREE:
+ pRet = new AccTreeEventListener(pXAcc,pAgent);
+ break;
+ //special
+ case AccessibleRole::COLUMN_HEADER:
+ case AccessibleRole::TABLE:
+ pRet = new AccTableEventListener(pXAcc,pAgent);
+ break;
+ default:
+ pRet = new AccContainerEventListener(pXAcc,pAgent);
+ break;
+ }
+ }
+ return pRet;
+}
+
+/**
+ * state is a combination integer, each bit of which represents a single state,
+ * such as focused,1 for the state on,0 for the state off. Here call COM interface
+ * to modify the state value, including DecreaseState.
+ * @param pXAcc XAccessible interface.
+ * @param pState Changed state.
+ * @return
+ */
+void AccObjectWinManager::DecreaseState( XAccessible* pXAcc,unsigned short pState )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->DecreaseState( pState );
+}
+
+/**
+ * state is a combination integer, each bit of which represents a single state,such as focused,1 for
+ * the state on,0 for the state off. Here call COM interface to modify the state value, including
+ * IncreaseState.
+ * @param pXAcc XAccessible interface.
+ * @param pState Changed state.
+ * @return
+ */
+void AccObjectWinManager::IncreaseState( XAccessible* pXAcc,unsigned short pState )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->IncreaseState( pState );
+}
+
+void AccObjectWinManager::UpdateState( css::accessibility::XAccessible* pXAcc )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->UpdateState( );
+}
+
+/**
+ * Set corresponding com object's accessible name via XAccessible interface and new
+ * name
+ * @param pXAcc XAccessible interface.
+ * @return
+ */
+void AccObjectWinManager::UpdateAccName( XAccessible* pXAcc )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->UpdateName();
+}
+
+void AccObjectWinManager::UpdateAction( XAccessible* pXAcc )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->UpdateAction();
+}
+
+/**
+ * Set corresponding com object's accessible location via XAccessible interface and new
+ * location.
+ * @param pXAcc XAccessible interface.
+ * @return
+ */
+void AccObjectWinManager::SetLocation( XAccessible* pXAcc, long /*top*/, long /*left*/, long /*width*/, long /*height*/ )
+{
+ AccObject* pObj = GetAccObjByXAcc( pXAcc );
+ //get the location from XComponent.
+ Reference< XAccessibleContext > pRContext = pXAcc->getAccessibleContext();
+ if( pObj )
+ pObj->UpdateLocation();
+}
+
+/**
+ * Set corresponding com object's value via XAccessible interface and new value.
+ * @param pXAcc XAccessible interface.
+ * @param pAny new value.
+ * @return
+ */
+void AccObjectWinManager::SetValue( XAccessible* pXAcc, Any pAny )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->SetValue( pAny );
+}
+
+/**
+ * Set corresponding com object's value via XAccessible interface.
+ * @param pXAcc XAccessible interface.
+ * @return
+ */
+void AccObjectWinManager::UpdateValue( XAccessible* pXAcc )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->UpdateValue();
+}
+
+/**
+ * Set corresponding com object's name via XAccessible interface and new name.
+ * @param pXAcc XAccessible interface.
+ * @param newName new name
+ * @return
+ */
+void AccObjectWinManager::SetAccName( XAccessible* pXAcc, Any newName)
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if( pAccObj )
+ pAccObj->SetName( newName );
+}
+
+/**
+ * Judge if a XAccessible object is a container object.
+ * @param pAccessible XAccessible interface.
+ * @return If XAccessible object is container.
+ */
+bool AccObjectWinManager::IsContainer(XAccessible* pAccessible)
+{
+ try
+ {
+ if(pAccessible)
+ {
+ Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
+ if(xContext.is())
+ {
+ switch( xContext->getAccessibleRole() )
+ {
+ case AccessibleRole::DIALOG:
+ case AccessibleRole::FRAME:
+ case AccessibleRole::WINDOW:
+ case AccessibleRole::ROOT_PANE:
+ case AccessibleRole::CANVAS:
+ case AccessibleRole::COMBO_BOX:
+ case AccessibleRole::DOCUMENT:
+ case AccessibleRole::DOCUMENT_PRESENTATION:
+ case AccessibleRole::DOCUMENT_SPREADSHEET:
+ case AccessibleRole::DOCUMENT_TEXT:
+ case AccessibleRole::EMBEDDED_OBJECT:
+ case AccessibleRole::END_NOTE:
+ case AccessibleRole::FILLER:
+ case AccessibleRole::FOOTNOTE:
+ case AccessibleRole::FOOTER:
+ case AccessibleRole::GRAPHIC:
+ case AccessibleRole::GROUP_BOX:
+ case AccessibleRole::HEADER:
+ case AccessibleRole::LAYERED_PANE:
+ case AccessibleRole::MENU_BAR:
+ case AccessibleRole::POPUP_MENU:
+ case AccessibleRole::OPTION_PANE:
+ case AccessibleRole::PAGE_TAB:
+ case AccessibleRole::PAGE_TAB_LIST:
+ case AccessibleRole::PANEL:
+ case AccessibleRole::SCROLL_PANE:
+ case AccessibleRole::SPLIT_PANE:
+ case AccessibleRole::STATUS_BAR:
+ case AccessibleRole::TABLE_CELL:
+ case AccessibleRole::TEXT_FRAME:
+ case AccessibleRole::TOOL_BAR:
+ case AccessibleRole::VIEW_PORT:
+ case AccessibleRole::SHAPE:
+ return true;
+ case AccessibleRole::COLUMN_HEADER:
+ case AccessibleRole::TABLE:
+ if(!IsStateManageDescendant(pAccessible))
+ return true;
+ break;
+ case AccessibleRole::MENU:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+ }
+ catch(...)
+ {
+ return false;
+ }
+ return false;
+}
+
+/**
+ * Judge if a XAccessible object has ManageDescendant event.
+ * @param pAccessible XAccessible interface.
+ * @return If XAccessible object is managedescendant.
+ */
+bool AccObjectWinManager::IsStateManageDescendant(XAccessible* pAccessible)
+{
+ if(pAccessible)
+ {
+ Reference<XAccessibleContext> xContext = pAccessible->getAccessibleContext();
+ if(xContext.is())
+ {
+ Reference< XAccessibleStateSet > pRState = xContext->getAccessibleStateSet();
+ if( !pRState.is() )
+ return false;
+
+ for (sal_Int16 nState : pRState->getStates())
+ {
+ if (nState == AccessibleStateType::MANAGES_DESCENDANTS)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
+ * Query and get IAccessible interface by XAccessible interface from list.
+ * @param pXAcc XAccessible interface.
+ * @return Com accobject interface.
+ */
+IMAccessible* AccObjectWinManager::GetIMAccByXAcc(XAccessible* pXAcc)
+{
+ AccObject* pAccObj = GetAccObjByXAcc(pXAcc);
+ if(pAccObj)
+ {
+ return pAccObj->GetIMAccessible();
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+/**
+ * Query and get IAccessible interface by child id from list.
+ * @param resID, childID.
+ * @return Com accobject interface.
+ */
+IMAccessible * AccObjectWinManager::GetIAccessibleFromResID(long resID)
+{
+ XResIdToAccObjHash::iterator pIndTemp = XResIdAccList.find( resID );
+ if ( pIndTemp == XResIdAccList.end() )
+ return nullptr;
+
+ AccObject* pObj = pIndTemp->second;
+
+ if(pObj->GetIMAccessible())
+ return pObj->GetIMAccessible();
+ return nullptr;
+}
+/**
+ * Notify some object will be destroyed.
+ * @param pXAcc XAccessible interface.
+ * @return Com accobject interface.
+ */
+void AccObjectWinManager::NotifyDestroy(XAccessible* pXAcc)
+{
+ AccObject* accObj = GetAccObjByXAcc(pXAcc);
+ if(accObj)
+ {
+ accObj->NotifyDestroy();
+ }
+}
+
+
+void AccObjectWinManager::UpdateChildState(css::accessibility::XAccessible* pAccSubMenu)
+{
+ Reference<css::accessibility::XAccessibleContext> xContext(pAccSubMenu,UNO_QUERY);
+ if (!xContext.is())
+ {
+ return;
+ }
+ sal_Int32 nCount = xContext->getAccessibleChildCount();
+ for (sal_Int32 i = 0 ; i < nCount ; ++i)
+ {
+ Reference<css::accessibility::XAccessible> xChild = xContext->getAccessibleChild(i);
+ if (xChild.is())
+ {
+ AccObject *pObj = GetAccObjByXAcc(xChild.get());
+ if (pObj)
+ {
+ pObj->UpdateState();
+ }
+ }
+ }
+}
+
+
+bool AccObjectWinManager::IsSpecialToolbarItem(css::accessibility::XAccessible* pXAcc)
+{
+ if (pXAcc && oldFocus != pXAcc)
+ {
+ if (GetParentRole(pXAcc) == AccessibleRole::TOOL_BAR)
+ {
+ Reference< XAccessibleContext > pRContext(pXAcc->getAccessibleContext());
+ if (pRContext.is())
+ {
+ if (pRContext->getAccessibleRole() == AccessibleRole::TOGGLE_BUTTON)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+short AccObjectWinManager::GetRole(css::accessibility::XAccessible* pXAcc)
+{
+ assert(pXAcc != nullptr);
+ Reference<css::accessibility::XAccessibleContext> xContext = pXAcc->getAccessibleContext();
+ if(xContext.is())
+ {
+ return xContext->getAccessibleRole();
+ }
+ return -1;
+}
+
+XAccessible* AccObjectWinManager::GetAccDocByHWND(HWND pWnd)
+{
+ XHWNDToDocumentHash::iterator aIter;
+ aIter = XHWNDDocList.find( pWnd );
+ if ( aIter != XHWNDDocList.end() )
+ {
+ return aIter->second;
+ }
+
+ return nullptr;
+}
+
+XAccessible* AccObjectWinManager::GetAccDocByAccTopWin( XAccessible* pXAcc )
+{
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ HWND hWnd = pAccObj->GetParentHWND();
+ return GetAccDocByHWND(hWnd);
+}
+
+bool AccObjectWinManager::IsTopWinAcc( css::accessibility::XAccessible* pXAcc )
+{
+ bool bRet = false;
+ AccObject* pAccObj = GetAccObjByXAcc( pXAcc );
+ if ( pAccObj )
+ {
+ bRet = ( pAccObj->GetParentObj() == nullptr );
+ }
+ return bRet;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccParagraphEventListener.cxx b/winaccessibility/source/service/AccParagraphEventListener.cxx
new file mode 100644
index 000000000..66783030c
--- /dev/null
+++ b/winaccessibility/source/service/AccParagraphEventListener.cxx
@@ -0,0 +1,131 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccParagraphEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccParagraphEventListener::AccParagraphEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccContainerEventListener(pAcc, Agent)
+{}
+AccParagraphEventListener::~AccParagraphEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccParagraphEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::CARET_CHANGED:
+ HandleCaretChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::VISIBLE_DATA_CHANGED:
+ HandleVisibleDataChangedEvent();
+ break;
+ case AccessibleEventId::BOUNDRECT_CHANGED:
+ HandleBoundrectChangedEvent();
+ break;
+ //Added for paragraph selected state.
+ case AccessibleEventId::STATE_CHANGED:
+ {
+ short State;
+ if( (aEvent.NewValue >>= State) && (State == AccessibleStateType::SELECTED) )
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), State);
+ break;
+ }
+ else if( (aEvent.OldValue >>= State) && (State == AccessibleStateType::SELECTED) )
+ {
+ pAgent->DecreaseState(m_xAccessible.get(), State);
+ break;
+ }
+
+ AccContainerEventListener::notifyEvent(aEvent);
+ break;
+ }
+
+ case AccessibleEventId::TEXT_SELECTION_CHANGED:
+ HandleTextSelectionChangedEvent();
+ break;
+
+ default:
+ AccContainerEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the CARET_CHANGED event
+ * @param oldValue in UNO, this parameter is always NULL
+ * @param newValue in UNO, this parameter is always NULL
+ */
+void AccParagraphEventListener::HandleCaretChangedEvent(Any, Any)
+{
+ AccObjectManagerAgent::UpdateLocation(m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::OBJECT_CARETCHANGE, m_xAccessible.get());
+}
+
+/**
+ * set the new state and fire the MSAA event
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccParagraphEventListener::SetComponentState(short state, bool enable )
+{
+ // only the following state can be fired state event.
+ switch (state)
+ {
+ case AccessibleStateType::EDITABLE:
+ // no msaa state
+ break;
+ case AccessibleStateType::MULTI_LINE:
+ // no msaa state mapping
+ break;
+ case AccessibleStateType::SINGLE_LINE:
+ // no msaa state mapping
+ break;
+ default:
+ AccContainerEventListener::SetComponentState(state, enable);
+ break;
+ }
+}
+
+void AccParagraphEventListener::HandleTextSelectionChangedEvent()
+{
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TEXT_SELECTION_CHANGED, m_xAccessible.get());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccTableEventListener.cxx b/winaccessibility/source/service/AccTableEventListener.cxx
new file mode 100644
index 000000000..96345cc86
--- /dev/null
+++ b/winaccessibility/source/service/AccTableEventListener.cxx
@@ -0,0 +1,142 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccTableEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccTableEventListener::AccTableEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccDescendantManagerEventListener(pAcc, Agent)
+{}
+AccTableEventListener::~AccTableEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccTableEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
+ HandleActiveDescendantChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+
+ case AccessibleEventId::TABLE_CAPTION_CHANGED:
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TABLE_CAPTION_CHANGED, m_xAccessible.get());
+ break;
+ }
+ case AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TABLE_COLUMN_DESCRIPTION_CHANGED, m_xAccessible.get());
+ break;
+ }
+ case AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TABLE_COLUMN_HEADER_CHANGED, m_xAccessible.get());
+ break;
+ }
+ case AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TABLE_ROW_HEADER_CHANGED, m_xAccessible.get());
+ break;
+ }
+ case AccessibleEventId::TABLE_MODEL_CHANGED:
+ {
+ HandleTableModelChangeEvent(aEvent.NewValue);
+ break;
+ }
+ case AccessibleEventId::TABLE_SUMMARY_CHANGED:
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TABLE_SUMMARY_CHANGED, m_xAccessible.get());
+ break;
+ }
+ case AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
+ {
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TABLE_ROW_DESCRIPTION_CHANGED, m_xAccessible.get());
+ break;
+ }
+ default:
+ AccDescendantManagerEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the ACTIVE_DESCENDANT_CHANGED event
+ * @param oldValue the child to lose active
+ * @param newValue the child to get active
+ */
+void AccTableEventListener::HandleActiveDescendantChangedEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+ if(newValue >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::ACTIVE_DESCENDANT_CHANGED, pAcc);
+ }
+ }
+ else if (oldValue >>= xChild)
+ {
+ //delete an existing child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+
+}
+void AccTableEventListener::HandleTableModelChangeEvent(Any newValue)
+{
+ AccessibleTableModelChange aModelChange;
+ if (newValue >>= aModelChange)
+ {
+ if (m_xAccessible.is())
+ {
+ //delete all oldValue's existing children
+ pAgent->DeleteChildrenAccObj(m_xAccessible.get());
+ //add all oldValue's existing children
+ pAgent->InsertChildrenAccObj(m_xAccessible.get());
+ }
+ pAgent->NotifyAccEvent(UnoMSAAEvent::TABLE_MODEL_CHANGED, m_xAccessible.get());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccTextComponentEventListener.cxx b/winaccessibility/source/service/AccTextComponentEventListener.cxx
new file mode 100644
index 000000000..1a185b0d8
--- /dev/null
+++ b/winaccessibility/source/service/AccTextComponentEventListener.cxx
@@ -0,0 +1,67 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccTextComponentEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccTextComponentEventListener::AccTextComponentEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccComponentEventListener(pAcc, Agent)
+{}
+AccTextComponentEventListener::~AccTextComponentEventListener()
+{
+}
+
+/**
+ * set the new state and fire the MSAA event
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccTextComponentEventListener::SetComponentState(short state, bool enable )
+{
+ // only the following state can be fired state event.
+ switch (state)
+ {
+ case AccessibleStateType::EDITABLE:
+ // no msaa state mapping
+ break;
+ case AccessibleStateType::MULTI_LINE:
+ // no msaa state mapping
+ break;
+ case AccessibleStateType::SINGLE_LINE:
+ // no msaa state mapping
+ break;
+ default:
+ AccComponentEventListener::SetComponentState(state, enable);
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccTopWindowListener.cxx b/winaccessibility/source/service/AccTopWindowListener.cxx
new file mode 100644
index 000000000..a828c36c0
--- /dev/null
+++ b/winaccessibility/source/service/AccTopWindowListener.cxx
@@ -0,0 +1,254 @@
+/* -*- 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 <sal/log.hxx>
+#include <vcl/window.hxx>
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+
+#include <vcl/sysdata.hxx>
+#include <vcl/svapp.hxx>
+
+#include <AccTopWindowListener.hxx>
+#include <unomsaaevent.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace com::sun::star::uno;
+
+/**
+ * For the new opened window, generate all the UNO accessible's object, COM object and add
+ * accessible listener to monitor all these objects.
+ * @param pAccessible the accessible of the new opened window
+ */
+void AccTopWindowListener::HandleWindowOpened( css::accessibility::XAccessible* pAccessible )
+{
+ //get SystemData from window
+ VclPtr<vcl::Window> window;
+ if (auto pvclwindow = dynamic_cast<VCLXWindow*>(pAccessible))
+ window = pvclwindow->GetWindow();
+ else if (auto pvclxcomponent = dynamic_cast<VCLXAccessibleComponent*>(pAccessible))
+ window = pvclxcomponent->GetWindow();
+ assert(window);
+ // The SalFrame of window may be destructed at this time
+ const SystemEnvData* systemdata = nullptr;
+ try
+ {
+ systemdata = window->GetSystemData();
+ }
+ catch(...)
+ {
+ systemdata = nullptr;
+ }
+ Reference<css::accessibility::XAccessibleContext> xContext = pAccessible->getAccessibleContext();
+ if(!xContext.is())
+ return;
+
+ css::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
+ //Only AccessibleContext exist, add all listeners
+ if(pAccessibleContext != nullptr && systemdata != nullptr)
+ {
+ accManagerAgent.SaveTopWindowHandle(systemdata->hWnd, pAccessible);
+
+ AddAllListeners(pAccessible,nullptr,systemdata->hWnd);
+
+ if( window->GetStyle() & WB_MOVEABLE )
+ accManagerAgent.IncreaseState( pAccessible, static_cast<unsigned short>(-1) /* U_MOVEBLE */ );
+
+ short role = pAccessibleContext->getAccessibleRole();
+
+ if (role == css::accessibility::AccessibleRole::POPUP_MENU ||
+ role == css::accessibility::AccessibleRole::MENU )
+ {
+ accManagerAgent.NotifyAccEvent(UnoMSAAEvent::MENUPOPUPSTART, pAccessible);
+ }
+
+ if (role == css::accessibility::AccessibleRole::FRAME ||
+ role == css::accessibility::AccessibleRole::DIALOG ||
+ role == css::accessibility::AccessibleRole::WINDOW ||
+ role == css::accessibility::AccessibleRole::ALERT)
+ {
+ accManagerAgent.NotifyAccEvent(UnoMSAAEvent::SHOW, pAccessible);
+ }
+ }
+}
+
+AccTopWindowListener::AccTopWindowListener()
+ : accManagerAgent()
+{
+}
+
+AccTopWindowListener::~AccTopWindowListener()
+{
+}
+
+/**
+ * It is invoked when a new window is opened, the source of this EventObject is the window
+ */
+void AccTopWindowListener::windowOpened( const css::lang::EventObject& e )
+{
+ SAL_INFO( "iacc2", "windowOpened triggered" );
+
+ if ( !e.Source.is())
+ return;
+
+ Reference< css::accessibility::XAccessible > xAccessible ( e.Source, UNO_QUERY );
+ css::accessibility::XAccessible* pAccessible = xAccessible.get();
+ if ( !pAccessible )
+ return;
+
+ SolarMutexGuard g;
+
+ HandleWindowOpened( pAccessible );
+}
+
+/**
+ * Add the accessible event listener to object and all its children objects.
+ * @param pAccessible the accessible object
+ * @param pParentXAcc the parent of current accessible object
+ * @param pWND the handle of top window which current object resides
+ */
+void AccTopWindowListener::AddAllListeners(css::accessibility::XAccessible* pAccessible, css::accessibility::XAccessible* pParentXAcc, HWND pWND)
+{
+ Reference<css::accessibility::XAccessibleContext> xContext = pAccessible->getAccessibleContext();
+ if(!xContext.is())
+ {
+ return;
+ }
+ css::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
+ if(pAccessibleContext == nullptr)
+ {
+ return;
+ }
+
+ accManagerAgent.InsertAccObj(pAccessible, pParentXAcc, pWND);
+
+ if (!accManagerAgent.IsContainer(pAccessible))
+ {
+ return;
+ }
+
+
+ short role = pAccessibleContext->getAccessibleRole();
+ if(css::accessibility::AccessibleRole::DOCUMENT == role ||
+ css::accessibility::AccessibleRole::DOCUMENT_PRESENTATION == role ||
+ css::accessibility::AccessibleRole::DOCUMENT_SPREADSHEET == role ||
+ css::accessibility::AccessibleRole::DOCUMENT_TEXT == role)
+ {
+ if(accManagerAgent.IsStateManageDescendant(pAccessible))
+ {
+ return ;
+ }
+ }
+
+
+ int count = pAccessibleContext->getAccessibleChildCount();
+ for (int i=0;i<count;i++)
+ {
+ Reference<css::accessibility::XAccessible> mxAccessible
+ = pAccessibleContext->getAccessibleChild(i);
+
+ css::accessibility::XAccessible* mpAccessible = mxAccessible.get();
+ if(mpAccessible != nullptr)
+ {
+ Reference<css::accessibility::XAccessibleContext> mxAccessibleContext
+ = mpAccessible->getAccessibleContext();
+ css::accessibility::XAccessibleContext* mpContext = mxAccessibleContext.get();
+ if(mpContext != nullptr)
+ AddAllListeners( mpAccessible, pAccessible, pWND);
+ }
+ }
+}
+
+void AccTopWindowListener::windowClosing( const css::lang::EventObject& )
+{
+ SAL_INFO( "iacc2", "windowClosing triggered" );
+}
+
+/**
+ * Invoke this method when the top window is closed, remove all the objects and its children
+ * from current manager's cache, and remove the COM object and the accessible event listener
+ * assigned to the accessible objects.
+ */
+void AccTopWindowListener::windowClosed( const css::lang::EventObject& e )
+{
+ SAL_INFO( "iacc2", "windowClosed triggered" );
+
+ if ( !e.Source.is())
+ return;
+
+ Reference< css::accessibility::XAccessible > xAccessible ( e.Source, UNO_QUERY );
+ css::accessibility::XAccessible* pAccessible = xAccessible.get();
+ if ( pAccessible == nullptr)
+ return;
+
+ Reference<css::accessibility::XAccessibleContext> xContext = pAccessible->getAccessibleContext();
+ if(!xContext.is())
+ {
+ return;
+ }
+ css::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
+
+ short role = -1;
+ if(pAccessibleContext != nullptr)
+ {
+ role = pAccessibleContext->getAccessibleRole();
+
+ if (role == css::accessibility::AccessibleRole::POPUP_MENU ||
+ role == css::accessibility::AccessibleRole::MENU)
+ {
+ accManagerAgent.NotifyAccEvent(UnoMSAAEvent::MENUPOPUPEND, pAccessible);
+ }
+ }
+
+
+ accManagerAgent.DeleteChildrenAccObj( pAccessible );
+ if( role != css::accessibility::AccessibleRole::POPUP_MENU )
+ accManagerAgent.DeleteAccObj( pAccessible );
+
+}
+
+void AccTopWindowListener::windowMinimized( const css::lang::EventObject& )
+{
+}
+
+void AccTopWindowListener::windowNormalized( const css::lang::EventObject& )
+{
+}
+
+void AccTopWindowListener::windowActivated( const css::lang::EventObject& )
+{
+}
+
+void AccTopWindowListener::windowDeactivated( const css::lang::EventObject& )
+{
+}
+
+void AccTopWindowListener::disposing( const css::lang::EventObject& )
+{
+}
+
+sal_Int64 AccTopWindowListener::GetMSComPtr(
+ sal_Int64 hWnd, sal_Int64 lParam, sal_Int64 wParam)
+{
+ return accManagerAgent.Get_ToATInterface(hWnd, lParam, wParam);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccTreeEventListener.cxx b/winaccessibility/source/service/AccTreeEventListener.cxx
new file mode 100644
index 000000000..ee3be70ac
--- /dev/null
+++ b/winaccessibility/source/service/AccTreeEventListener.cxx
@@ -0,0 +1,90 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccTreeEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccTreeEventListener::AccTreeEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccDescendantManagerEventListener(pAcc, Agent)
+{}
+AccTreeEventListener::~AccTreeEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject the event object which contains information about event
+ */
+void AccTreeEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
+ HandleActiveDescendantChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ default:
+ AccDescendantManagerEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the ACTIVE_DESCENDANT_CHANGED event
+ * @param oldValue the child to lose active
+ * @param newValue the child to get active
+ */
+void AccTreeEventListener::HandleActiveDescendantChangedEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+ if(newValue >>= xChild )
+ {
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ pAgent->NotifyAccEvent(UnoMSAAEvent::ACTIVE_DESCENDANT_CHANGED, pAcc);
+ }
+ }
+ if (oldValue >>= xChild)
+ {
+ //delete an existing child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/AccWindowEventListener.cxx b/winaccessibility/source/service/AccWindowEventListener.cxx
new file mode 100644
index 000000000..fbc719a81
--- /dev/null
+++ b/winaccessibility/source/service/AccWindowEventListener.cxx
@@ -0,0 +1,136 @@
+/* -*- 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/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <AccWindowEventListener.hxx>
+#include <AccObjectManagerAgent.hxx>
+#include <unomsaaevent.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::accessibility;
+
+AccWindowEventListener::AccWindowEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
+ :AccEventListener(pAcc, Agent)
+{}
+AccWindowEventListener::~AccWindowEventListener()
+{
+}
+
+/**
+ * Uno's event notifier when event is captured
+ * @param AccessibleEventObject: the event object which contains information about event
+ */
+void AccWindowEventListener::notifyEvent( const css::accessibility::AccessibleEventObject& aEvent )
+{
+ SolarMutexGuard g;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId::CHILD:
+ HandleChildChangedEvent(aEvent.OldValue, aEvent.NewValue);
+ break;
+ case AccessibleEventId::VISIBLE_DATA_CHANGED:
+ HandleVisibleDataChangedEvent();
+ break;
+ case AccessibleEventId::BOUNDRECT_CHANGED:
+ HandleBoundrectChangedEvent();
+ break;
+ default:
+ AccEventListener::notifyEvent(aEvent);
+ break;
+ }
+}
+
+/**
+ * handle the CHILD event
+ * @param oldValue the child to be deleted
+ * @param newValue the child to be added
+ */
+void AccWindowEventListener::HandleChildChangedEvent(Any oldValue, Any newValue)
+{
+ Reference< XAccessible > xChild;
+ if( newValue >>= xChild)
+ {
+ //create a new child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ //add this child
+ pAgent->InsertAccObj(pAcc, m_xAccessible.get());
+ //add all oldValue's existing children
+ pAgent->InsertChildrenAccObj(pAcc);
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_ADDED, pAcc);
+ }
+ }
+ else if (oldValue >>= xChild)
+ {
+ //delete an existing child
+ if(xChild.is())
+ {
+ XAccessible* pAcc = xChild.get();
+ pAgent->NotifyAccEvent(UnoMSAAEvent::CHILD_REMOVED, pAcc);
+ pAgent->DeleteChildrenAccObj( pAcc );
+ //delete this child
+ pAgent->DeleteAccObj( pAcc );
+ }
+ }
+}
+
+/**
+ * set the new state and fire the MSAA event
+ * @param state new state id
+ * @param enable true if state is set, false if state is unset
+ */
+void AccWindowEventListener::SetComponentState(short state, bool enable )
+{
+ // only the following state can be fired state event.
+ switch (state)
+ {
+ case AccessibleStateType::ICONIFIED:
+ // no msaa state
+ break;
+ case AccessibleStateType::VISIBLE:
+ // UNO !VISIBLE == MSAA INVISIBLE
+ if( enable )
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ else
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::VISIBLE);
+ break;
+ case AccessibleStateType::SHOWING:
+ // UNO !SHOWING == MSAA OFFSCREEN
+ if( enable )
+ {
+ pAgent->IncreaseState(m_xAccessible.get(), AccessibleStateType::SHOWING);
+ }
+ else
+ pAgent->DecreaseState(m_xAccessible.get(), AccessibleStateType::SHOWING);
+ break;
+ default:
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/ResIDGenerator.cxx b/winaccessibility/source/service/ResIDGenerator.cxx
new file mode 100644
index 000000000..749838030
--- /dev/null
+++ b/winaccessibility/source/service/ResIDGenerator.cxx
@@ -0,0 +1,46 @@
+/* -*- 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 <ResIDGenerator.hxx>
+
+#include <cassert>
+
+ResIDGenerator::~ResIDGenerator() {}
+
+/**
+ * SubList stores those IDs that were ever generated and deleted, the method
+ * return the ID from subList first if subList is not empty, else return m_nMin--.
+ * Add the obsolete IDs by calling SetSub method
+ *
+ * @param
+ * @return new resource ID.
+ */
+long ResIDGenerator::GenerateNewResID()
+{
+ if (!subList.empty())
+ {
+ long nRes = *(subList.begin());
+ subList.pop_front();
+ return nRes;
+ }
+ assert(m_nMin > LONG_MIN);
+ return m_nMin--;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/msaaservice_impl.cxx b/winaccessibility/source/service/msaaservice_impl.cxx
new file mode 100644
index 000000000..13f10a6d7
--- /dev/null
+++ b/winaccessibility/source/service/msaaservice_impl.cxx
@@ -0,0 +1,275 @@
+/* -*- 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 <rtl/ref.hxx>
+#include <sal/log.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/accessibility/XMSAAService.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+#include <com/sun/star/awt/XExtendedToolkit.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+
+#include <prewin.h>
+#include <postwin.h>
+
+using namespace ::com::sun::star; // for odk interfaces
+using namespace ::com::sun::star::uno; // for basic types
+using namespace ::com::sun::star::accessibility;
+
+using namespace ::com::sun::star::awt;
+
+#include <AccTopWindowListener.hxx>
+
+namespace my_sc_impl
+{
+
+namespace {
+
+class MSAAServiceImpl : public ::cppu::WeakImplHelper<
+ XMSAAService, lang::XServiceInfo >
+{
+private:
+ rtl::Reference<AccTopWindowListener> m_pTopWindowListener;
+
+public:
+ MSAAServiceImpl ();
+
+ // XComponent - as used by VCL to lifecycle manage this bridge.
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& ) override
+ { /* dummy */ }
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& ) override
+ { /* dummy */ }
+
+ // XMSAAService
+ virtual sal_Int64 SAL_CALL getAccObjectPtr(
+ sal_Int64 hWnd, sal_Int64 lParam, sal_Int64 wParam) override;
+ virtual void SAL_CALL handleWindowOpened(sal_Int64) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+}
+
+/**
+ * Implementation of getAccObjectPtr.
+ * @param
+ * @return Com interface.
+ */
+sal_Int64 MSAAServiceImpl::getAccObjectPtr(
+ sal_Int64 hWnd, sal_Int64 lParam, sal_Int64 wParam)
+{
+ SolarMutexGuard g;
+
+ if (!m_pTopWindowListener.is())
+ {
+ return 0;
+ }
+ return m_pTopWindowListener->GetMSComPtr(hWnd, lParam, wParam);
+}
+
+/**
+ * Implementation of handleWindowOpened, the method will be invoked when a
+ * top window is opened and AT starts up.
+ * @param
+ * @return
+ */
+void MSAAServiceImpl::handleWindowOpened(sal_Int64 nAcc)
+{
+ SolarMutexGuard g;
+
+ SAL_INFO( "iacc2", "Window opened " << nAcc );
+
+ if (m_pTopWindowListener.is() && nAcc)
+ {
+ m_pTopWindowListener->HandleWindowOpened(
+ static_cast<css::accessibility::XAccessible*>(
+ reinterpret_cast<void*>(nAcc)));
+ }
+}
+
+OUString MSAAServiceImpl::getImplementationName()
+{
+ return "com.sun.star.accessibility.my_sc_implementation.MSAAService";
+}
+
+/**
+ * Implementation of XServiceInfo, return support service name.
+ * @param Service name.
+ * @return If the service name is supported.
+ */
+sal_Bool MSAAServiceImpl::supportsService( OUString const & serviceName )
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+/**
+ * Implementation of XServiceInfo, return all service names.
+ * @param.
+ * @return service name sequence.
+ */
+Sequence< OUString > MSAAServiceImpl::getSupportedServiceNames()
+{
+ return { "com.sun.star.accessibility.MSAAService" };
+}
+
+static void AccessBridgeHandleExistingWindow(const Reference< XMSAAService > &xAccMgr,
+ vcl::Window *pWindow, bool bShow)
+{
+ if ( pWindow )
+ {
+ css::uno::Reference< css::accessibility::XAccessible > xAccessible;
+
+ SAL_INFO( "iacc2", "Decide whether to register existing window with IAccessible2" );
+
+ // Test for combo box - drop down floating windows first
+ vcl::Window * pParentWindow = pWindow->GetParent();
+
+ if ( pParentWindow )
+ {
+ try
+ {
+ // The parent window of a combo box floating window should have the role COMBO_BOX
+ css::uno::Reference< css::accessibility::XAccessible > xParentAccessible(pParentWindow->GetAccessible());
+ if ( xParentAccessible.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext > xParentAC( xParentAccessible->getAccessibleContext() );
+ if ( xParentAC.is() && (css::accessibility::AccessibleRole::COMBO_BOX == xParentAC->getAccessibleRole()) )
+ {
+ // O.k. - this is a combo box floating window corresponding to the child of role LIST of the parent.
+ // Let's not rely on a specific child order, just search for the child with the role LIST
+ sal_Int32 nCount = xParentAC->getAccessibleChildCount();
+ for ( sal_Int32 n = 0; (n < nCount) && !xAccessible.is(); n++)
+ {
+ css::uno::Reference< css::accessibility::XAccessible > xChild = xParentAC->getAccessibleChild(n);
+ if ( xChild.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext > xChildAC = xChild->getAccessibleContext();
+ if ( xChildAC.is() && (css::accessibility::AccessibleRole::LIST == xChildAC->getAccessibleRole()) )
+ {
+ xAccessible = xChild;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (css::uno::RuntimeException const&)
+ {
+ // Ignore show events that throw DisposedExceptions in getAccessibleContext(),
+ // but keep revoking these windows in hide(s).
+ if (bShow)
+ return;
+ }
+ }
+
+ // We have to rely on the fact that Window::GetAccessible()->getAccessibleContext() returns a valid XAccessibleContext
+ // also for other menus than menubar or toplevel popup window. Otherwise we had to traverse the hierarchy to find the
+ // context object to this menu floater. This makes the call to Window->IsMenuFloatingWindow() obsolete.
+ if ( ! xAccessible.is() )
+ xAccessible = pWindow->GetAccessible();
+
+ assert( xAccMgr.is() );
+ if ( xAccessible.is() )
+ {
+ xAccMgr->handleWindowOpened(
+ reinterpret_cast<sal_Int64>(xAccessible.get()));
+ SAL_INFO( "iacc2", "Decide whether to register existing window with IAccessible2" );
+ }
+ }
+}
+
+/*
+ * Setup and notify the OS of Accessible peers for all existing windows.
+ */
+static void AccessBridgeUpdateOldTopWindows( const Reference< XMSAAService > &xAccMgr )
+{
+ sal_uInt16 nTopWindowCount = static_cast<sal_uInt16>(Application::GetTopWindowCount());
+
+ for ( sal_uInt16 i = 0; i < nTopWindowCount; i++ )
+ {
+ vcl::Window* pTopWindow = Application::GetTopWindow( i );
+ css::uno::Reference< css::accessibility::XAccessible > xAccessible = pTopWindow->GetAccessible();
+ if ( xAccessible.is() )
+ {
+ css::uno::Reference< css::accessibility::XAccessibleContext > xAC( xAccessible->getAccessibleContext() );
+ if ( xAC.is())
+ {
+ if ( !xAC->getAccessibleName().isEmpty() )
+ AccessBridgeHandleExistingWindow( xAccMgr, pTopWindow, true );
+ }
+ }
+ }
+}
+
+MSAAServiceImpl::MSAAServiceImpl()
+{
+ Reference< XExtendedToolkit > xToolkit(Application::GetVCLToolkit(), UNO_QUERY);
+
+ if( xToolkit.is() )
+ {
+ m_pTopWindowListener.set(new AccTopWindowListener());
+ Reference<XTopWindowListener> const xRef(m_pTopWindowListener);
+ xToolkit->addTopWindowListener( xRef );
+ SAL_INFO( "iacc2", "successfully connected to the toolkit event hose" );
+ }
+ else
+ SAL_WARN( "iacc2", "No VCL toolkit interface to listen to for events");
+}
+
+void MSAAServiceImpl::dispose()
+{
+ SolarMutexGuard g;
+
+ // As all folders and streams contain references to their parents,
+ // we must remove these references so that they will be deleted when
+ // the hash_map of the root folder is cleared, releasing all subfolders
+ // and substreams which in turn release theirs, etc. When xRootFolder is
+ // released when this destructor completes, the folder tree should be
+ // deleted fully (and automagically).
+ m_pTopWindowListener.clear();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+winaccessibility_MSAAServiceImpl_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
+{
+ Reference< XMSAAService > xAccMgr( new MSAAServiceImpl() );
+
+ AccessBridgeUpdateOldTopWindows( xAccMgr );
+
+ SAL_INFO("iacc2", "Created new IAccessible2 service impl.");
+
+ xAccMgr->acquire();
+ return xAccMgr.get();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/winaccessibility/source/service/winaccessibility.component b/winaccessibility/source/service/winaccessibility.component
new file mode 100644
index 000000000..fe26e40e2
--- /dev/null
+++ b/winaccessibility/source/service/winaccessibility.component
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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 .
+ -->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.accessibility.my_sc_implementation.MSAAService"
+ constructor="winaccessibility_MSAAServiceImpl_get_implementation">
+ <service name="com.sun.star.accessibility.MSAAService"/>
+ </implementation>
+</component>