Use the more concrete OAccessible instead of the abstract XAccessible UNO interface for that member. Drop now unnecessary querying for the XAccessibleContext UNO interface, as OAccessible implements that interface itself as well. Change-Id: I689af3c6b72f442967ab7fe4c39d438fc68b09fe Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211215 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
392 lines
9.7 KiB
C++
392 lines
9.7 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
/*
|
|
* 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 "AccessibleObject.hxx"
|
|
#include "AccessibleFocusManager.hxx"
|
|
|
|
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
|
|
#include <com/sun/star/accessibility/AccessibleRole.hpp>
|
|
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
|
|
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
|
|
|
|
|
|
AccessibleObject::AccessibleObject(
|
|
const sal_Int16 nRole,
|
|
const OUString& rName)
|
|
: msName(rName),
|
|
mnRole(nRole),
|
|
mnStateSet(0),
|
|
mbIsFocused(false)
|
|
{
|
|
}
|
|
|
|
void AccessibleObject::LateInitialization()
|
|
{
|
|
AccessibleFocusManager::Instance().AddFocusableObject(this);
|
|
}
|
|
|
|
void AccessibleObject::SetWindow (
|
|
const Reference<awt::XWindow>& rxContentWindow,
|
|
const Reference<awt::XWindow>& rxBorderWindow)
|
|
{
|
|
Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY);
|
|
|
|
if (mxContentWindow.get() == xContentWindow.get())
|
|
return;
|
|
|
|
if (mxContentWindow.is())
|
|
{
|
|
mxContentWindow->removeWindowListener(this);
|
|
}
|
|
|
|
mxContentWindow = std::move(xContentWindow);
|
|
mxBorderWindow.set(rxBorderWindow, UNO_QUERY);
|
|
|
|
if (mxContentWindow.is())
|
|
{
|
|
mxContentWindow->addWindowListener(this);
|
|
}
|
|
|
|
UpdateStateSet();
|
|
}
|
|
|
|
void AccessibleObject::SetAccessibleParent(
|
|
const rtl::Reference<comphelper::OAccessible>& rpAccessibleParent)
|
|
{
|
|
mpParentAccessible = rpAccessibleParent;
|
|
}
|
|
|
|
void SAL_CALL AccessibleObject::disposing()
|
|
{
|
|
OAccessible::disposing();
|
|
|
|
AccessibleFocusManager::Instance().RemoveFocusableObject(this);
|
|
SetWindow(nullptr, nullptr);
|
|
}
|
|
|
|
//----- XAccessibleContext ----------------------------------------------
|
|
|
|
sal_Int64 SAL_CALL AccessibleObject::getAccessibleChildCount()
|
|
{
|
|
ensureAlive();
|
|
|
|
return maChildren.size();
|
|
}
|
|
|
|
Reference<XAccessible> SAL_CALL
|
|
AccessibleObject::getAccessibleChild (sal_Int64 nIndex)
|
|
{
|
|
ensureAlive();
|
|
|
|
if (nIndex<0 || o3tl::make_unsigned(nIndex)>=maChildren.size())
|
|
throw lang::IndexOutOfBoundsException(u"invalid child index"_ustr, static_cast<uno::XWeak*>(this));
|
|
|
|
return maChildren[nIndex];
|
|
}
|
|
|
|
Reference<XAccessible> SAL_CALL
|
|
AccessibleObject::getAccessibleParent()
|
|
{
|
|
ensureAlive();
|
|
|
|
return mpParentAccessible;
|
|
}
|
|
|
|
sal_Int64 SAL_CALL
|
|
AccessibleObject::getAccessibleIndexInParent()
|
|
{
|
|
ensureAlive();
|
|
|
|
const Reference<XAccessible> xThis (this);
|
|
if (mpParentAccessible.is())
|
|
{
|
|
for (sal_Int64 nIndex = 0, nCount = mpParentAccessible->getAccessibleChildCount();
|
|
nIndex < nCount; ++nIndex)
|
|
{
|
|
if (mpParentAccessible->getAccessibleChild(nIndex) == xThis)
|
|
return nIndex;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
sal_Int16 SAL_CALL
|
|
AccessibleObject::getAccessibleRole()
|
|
{
|
|
ensureAlive();
|
|
|
|
return mnRole;
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
AccessibleObject::getAccessibleDescription()
|
|
{
|
|
ensureAlive();
|
|
|
|
return OUString();
|
|
}
|
|
|
|
OUString SAL_CALL
|
|
AccessibleObject::getAccessibleName()
|
|
{
|
|
ensureAlive();
|
|
|
|
return msName;
|
|
}
|
|
|
|
Reference<XAccessibleRelationSet> SAL_CALL
|
|
AccessibleObject::getAccessibleRelationSet()
|
|
{
|
|
ensureAlive();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
sal_Int64 SAL_CALL
|
|
AccessibleObject::getAccessibleStateSet()
|
|
{
|
|
ensureAlive();
|
|
|
|
return mnStateSet;
|
|
}
|
|
|
|
lang::Locale SAL_CALL
|
|
AccessibleObject::getLocale()
|
|
{
|
|
ensureAlive();
|
|
|
|
if (mpParentAccessible.is())
|
|
{
|
|
return mpParentAccessible->getLocale();
|
|
}
|
|
return css::lang::Locale();
|
|
}
|
|
|
|
//----- XAccessibleComponent ------------------------------------------------
|
|
|
|
Reference<XAccessible> SAL_CALL
|
|
AccessibleObject::getAccessibleAtPoint (const awt::Point&)
|
|
{
|
|
ensureAlive();
|
|
|
|
return Reference<XAccessible>();
|
|
}
|
|
|
|
awt::Rectangle AccessibleObject::implGetBounds()
|
|
{
|
|
const awt::Point aLocation (GetRelativeLocation());
|
|
const awt::Size aSize (GetSize());
|
|
|
|
return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height);
|
|
}
|
|
|
|
void SAL_CALL AccessibleObject::grabFocus()
|
|
{
|
|
ensureAlive();
|
|
if (mxBorderWindow.is())
|
|
mxBorderWindow->setFocus();
|
|
else if (mxContentWindow.is())
|
|
mxContentWindow->setFocus();
|
|
}
|
|
|
|
sal_Int32 SAL_CALL AccessibleObject::getForeground()
|
|
{
|
|
ensureAlive();
|
|
|
|
return 0x00ffffff;
|
|
}
|
|
|
|
sal_Int32 SAL_CALL AccessibleObject::getBackground()
|
|
{
|
|
ensureAlive();
|
|
|
|
return 0x00000000;
|
|
}
|
|
|
|
//----- XWindowListener ---------------------------------------------------
|
|
|
|
void SAL_CALL AccessibleObject::windowResized (
|
|
const css::awt::WindowEvent&)
|
|
{
|
|
FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
|
|
}
|
|
|
|
void SAL_CALL AccessibleObject::windowMoved (
|
|
const css::awt::WindowEvent&)
|
|
{
|
|
FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
|
|
}
|
|
|
|
void SAL_CALL AccessibleObject::windowShown (
|
|
const css::lang::EventObject&)
|
|
{
|
|
UpdateStateSet();
|
|
}
|
|
|
|
void SAL_CALL AccessibleObject::windowHidden (
|
|
const css::lang::EventObject&)
|
|
{
|
|
UpdateStateSet();
|
|
}
|
|
|
|
//----- XEventListener --------------------------------------------------------
|
|
|
|
void SAL_CALL AccessibleObject::disposing (const css::lang::EventObject& rEvent)
|
|
{
|
|
if (rEvent.Source == mxContentWindow)
|
|
{
|
|
mxContentWindow = nullptr;
|
|
mxBorderWindow = nullptr;
|
|
}
|
|
else
|
|
{
|
|
SetWindow(nullptr, nullptr);
|
|
}
|
|
}
|
|
|
|
//----- private ---------------------------------------------------------------
|
|
|
|
bool AccessibleObject::GetWindowState (const sal_Int64 nType) const
|
|
{
|
|
switch (nType)
|
|
{
|
|
case AccessibleStateType::ENABLED:
|
|
return mxContentWindow.is() && mxContentWindow->isEnabled();
|
|
|
|
case AccessibleStateType::FOCUSABLE:
|
|
return true;
|
|
|
|
case AccessibleStateType::FOCUSED:
|
|
return mbIsFocused;
|
|
|
|
case AccessibleStateType::SHOWING:
|
|
return mxContentWindow.is() && mxContentWindow->isVisible();
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void AccessibleObject::UpdateStateSet()
|
|
{
|
|
UpdateState(AccessibleStateType::FOCUSABLE, true);
|
|
UpdateState(AccessibleStateType::VISIBLE, true);
|
|
UpdateState(AccessibleStateType::ENABLED, true);
|
|
UpdateState(AccessibleStateType::MULTI_LINE, true);
|
|
UpdateState(AccessibleStateType::SENSITIVE, true);
|
|
|
|
UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED));
|
|
UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED));
|
|
UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING));
|
|
// UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE));
|
|
}
|
|
|
|
void AccessibleObject::UpdateState(
|
|
const sal_Int64 nState,
|
|
const bool bValue)
|
|
{
|
|
if (((mnStateSet & nState) != 0) == bValue)
|
|
return;
|
|
if (bValue)
|
|
{
|
|
mnStateSet |= nState;
|
|
FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState));
|
|
}
|
|
else
|
|
{
|
|
mnStateSet &= ~nState;
|
|
FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any());
|
|
}
|
|
}
|
|
|
|
void AccessibleObject::AddChild (
|
|
const ::rtl::Reference<AccessibleObject>& rpChild)
|
|
{
|
|
maChildren.push_back(rpChild);
|
|
rpChild->SetAccessibleParent(this);
|
|
FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
|
|
}
|
|
|
|
void AccessibleObject::RemoveChild (
|
|
const ::rtl::Reference<AccessibleObject>& rpChild)
|
|
{
|
|
rpChild->SetAccessibleParent({});
|
|
maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild));
|
|
FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
|
|
}
|
|
|
|
void AccessibleObject::SetIsFocused (const bool bIsFocused)
|
|
{
|
|
if (mbIsFocused != bIsFocused)
|
|
{
|
|
mbIsFocused = bIsFocused;
|
|
UpdateStateSet();
|
|
}
|
|
}
|
|
|
|
void AccessibleObject::SetAccessibleName (const OUString& rsName)
|
|
{
|
|
if (msName != rsName)
|
|
{
|
|
const OUString sOldName(msName);
|
|
msName = rsName;
|
|
FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName));
|
|
}
|
|
}
|
|
|
|
void AccessibleObject::FireAccessibleEvent (
|
|
const sal_Int16 nEventId,
|
|
const uno::Any& rOldValue,
|
|
const uno::Any& rNewValue )
|
|
{
|
|
NotifyAccessibleEvent(nEventId, rOldValue, rNewValue);
|
|
}
|
|
|
|
awt::Point AccessibleObject::GetRelativeLocation()
|
|
{
|
|
awt::Point aLocation;
|
|
if (mxContentWindow.is())
|
|
{
|
|
const awt::Rectangle aContentBox (mxContentWindow->getPosSize());
|
|
aLocation.X = aContentBox.X;
|
|
aLocation.Y = aContentBox.Y;
|
|
if (mxBorderWindow.is())
|
|
{
|
|
const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize());
|
|
aLocation.X += aBorderBox.X;
|
|
aLocation.Y += aBorderBox.Y;
|
|
}
|
|
}
|
|
return aLocation;
|
|
}
|
|
|
|
awt::Size AccessibleObject::GetSize()
|
|
{
|
|
if (mxContentWindow.is())
|
|
{
|
|
const awt::Rectangle aBox (mxContentWindow->getPosSize());
|
|
return awt::Size(aBox.Width, aBox.Height);
|
|
}
|
|
else
|
|
return awt::Size();
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|