Files
Michael Weghorn 6b81401b71 sd a11y: Switch AccessibleObject::mxParentAccessible to OAccessible
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>
2026-09-20 22:20:48 +02:00

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