/* -*- 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 #include #include #include #include #include #include #include #include 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: */