Accessibility for IconView

Change-Id: I65ca9d43f70a50e2e95aabfc3b8ba1b15f9ff8be
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135226
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Mike Kaganski 2022-06-01 11:18:26 +03:00
parent 2910ce0b43
commit 2a28ebeef5
16 changed files with 202 additions and 32 deletions

View file

@ -62,6 +62,7 @@ $(eval $(call gb_Library_add_exception_objects,acc,\
accessibility/source/extended/accessibleeditbrowseboxcell \
accessibility/source/extended/accessibleiconchoicectrl \
accessibility/source/extended/accessibleiconchoicectrlentry \
accessibility/source/extended/AccessibleIconView \
accessibility/source/extended/accessiblelistbox \
accessibility/source/extended/accessiblelistboxentry \
accessibility/source/extended/accessibletablistbox \

View file

@ -0,0 +1,30 @@
/* -*- 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/.
*/
#pragma once
#include <sal/config.h>
#include "accessiblelistbox.hxx"
namespace accessibility
{
class AccessibleIconView final : public AccessibleListBox
{
public:
AccessibleIconView(SvTreeListBox const& _rListBox,
const css::uno::Reference<css::accessibility::XAccessible>& _xParent);
protected:
// VCLXAccessibleComponent
virtual void ProcessWindowEvent(const VclWindowEvent& rVclWindowEvent) override;
};
} // namespace accessibility
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -37,7 +37,7 @@ namespace accessibility
/** the class OAccessibleListBoxEntry represents the base class for an accessible object of a listbox entry
*/
class AccessibleListBox final :
class AccessibleListBox :
public cppu::ImplHelper2<
css::accessibility::XAccessible,
css::accessibility::XAccessibleSelection>,
@ -45,18 +45,17 @@ namespace accessibility
{
css::uno::Reference< css::accessibility::XAccessible > m_xParent;
virtual ~AccessibleListBox() override;
// OComponentHelper overridables
/** this function is called upon disposing the component */
virtual void SAL_CALL disposing() override;
protected:
// VCLXAccessibleComponent
virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
virtual void ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent ) override;
virtual void FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) override;
private:
VclPtr< SvTreeListBox > getListBox() const;
void RemoveChildEntries(SvTreeListEntry*);
@ -73,6 +72,8 @@ namespace accessibility
AccessibleListBox( SvTreeListBox const & _rListBox,
const css::uno::Reference< css::accessibility::XAccessible >& _xParent );
virtual ~AccessibleListBox() override;
rtl::Reference<AccessibleListBoxEntry> implGetAccessible(SvTreeListEntry & rEntry);
// XTypeProvider

View file

@ -0,0 +1,53 @@
/* -*- 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/.
*/
#include <sal/config.h>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <toolkit/helper/convert.hxx>
#include <vcl/event.hxx>
#include <extended/AccessibleIconView.hxx>
namespace accessibility
{
AccessibleIconView::AccessibleIconView(
SvTreeListBox const& _rListBox,
const css::uno::Reference<css::accessibility::XAccessible>& _xParent)
: AccessibleListBox(_rListBox, _xParent)
{
}
void AccessibleIconView::ProcessWindowEvent(const VclWindowEvent& rVclWindowEvent)
{
if (!isAlive())
return;
switch (rVclWindowEvent.GetId())
{
case VclEventId::WindowMouseMove:
if (MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rVclWindowEvent.GetData()))
{
if (auto xChild = getAccessibleAtPoint(AWTPoint(pMouseEvt->GetPosPixel())))
{
// Allow announcing the element on mouse hover
css::uno::Any aNew(xChild);
NotifyAccessibleEvent(
css::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, {}, aNew);
}
}
break;
default:
AccessibleListBox::ProcessWindowEvent(rVclWindowEvent);
}
}
} // namespace accessibility
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -439,33 +439,12 @@ namespace accessibility
SolarMutexGuard aSolarGuard;
::osl::MutexGuard aGuard( m_aMutex );
SvTreeListEntry* pEntry = m_pTreeListBox->GetEntryFromPath( m_aEntryPath );
if( getAccessibleRole() == AccessibleRole::TREE_ITEM )
{
return OUString();
}
//want to count the real column number in the list box.
sal_uInt16 iRealItemCount = 0;
sal_uInt16 iCount = 0;
sal_uInt16 iTotleItemCount = pEntry->ItemCount();
while( iCount < iTotleItemCount )
{
const SvLBoxItem& rItem = pEntry->GetItem( iCount );
if ( rItem.GetType() == SvLBoxItemType::String &&
!static_cast<const SvLBoxString&>( rItem ).GetText().isEmpty() )
{
iRealItemCount++;
}
iCount++;
}
if(iRealItemCount<=1 )
{
return OUString();
}
else
{
return SvTreeListBox::SearchEntryTextWithHeadTitle( pEntry );
}
return m_pTreeListBox->GetEntryAccessibleDescription(
m_pTreeListBox->GetEntryFromPath(m_aEntryPath));
}
OUString SAL_CALL AccessibleListBoxEntry::getAccessibleName( )

View file

@ -46,6 +46,7 @@
#include <extended/accessibletablistbox.hxx>
#include <extended/AccessibleBrowseBox.hxx>
#include <extended/accessibleiconchoicectrl.hxx>
#include <extended/AccessibleIconView.hxx>
#include <extended/accessibletabbar.hxx>
#include <extended/accessiblelistbox.hxx>
#include <extended/AccessibleBrowseBoxHeaderBar.hxx>
@ -155,6 +156,12 @@ public:
const css::uno::Reference< css::accessibility::XAccessible >& _xParent
) const override;
virtual css::uno::Reference< css::accessibility::XAccessible >
createAccessibleIconView(
SvTreeListBox& _rListBox,
const css::uno::Reference< css::accessibility::XAccessible >& _xParent
) const override;
virtual css::uno::Reference< css::accessibility::XAccessible >
createAccessibleBrowseBoxHeaderBar(
const css::uno::Reference< css::accessibility::XAccessible >& rxParent,
@ -407,6 +414,12 @@ Reference< XAccessible > AccessibleFactory::createAccessibleTreeListBox(
return new AccessibleListBox( _rListBox, _xParent );
}
Reference< XAccessible > AccessibleFactory::createAccessibleIconView(
SvTreeListBox& _rListBox, const Reference< XAccessible >& _xParent ) const
{
return new AccessibleIconView( _rListBox, _xParent );
}
Reference< XAccessible > AccessibleFactory::createAccessibleBrowseBoxHeaderBar(
const Reference< XAccessible >& rxParent, vcl::IAccessibleTableProvider& _rOwningTable,
AccessibleBrowseBoxObjType _eObjType ) const

View file

@ -82,6 +82,11 @@ namespace vcl
SvTreeListBox& _rListBox,
const css::uno::Reference< css::accessibility::XAccessible >& _xParent
) const = 0;
virtual css::uno::Reference< css::accessibility::XAccessible >
createAccessibleIconView(
SvTreeListBox& _rListBox,
const css::uno::Reference< css::accessibility::XAccessible >& _xParent
) const = 0;
virtual vcl::IAccessibleBrowseBox*
createAccessibleBrowseBox(
const css::uno::Reference< css::accessibility::XAccessible >& _rxParent,

View file

@ -456,6 +456,8 @@ public:
/** Fills the StateSet of one entry. */
void FillAccessibleEntryStateSet( SvTreeListEntry* pEntry, ::utl::AccessibleStateSetHelper& rStateSet ) const;
virtual OUString GetEntryAccessibleDescription(SvTreeListEntry* pEntry) const;
/** Calculate and return the bounding rectangle of an entry.
@param pEntry
The entry.

View file

@ -1348,7 +1348,10 @@ protected:
void signal_selection_changed() { m_aSelectionChangeHdl.Call(*this); }
bool signal_item_activated() { return m_aItemActivatedHdl.Call(*this); }
OUString signal_query_tooltip(const TreeIter& rIter) { return m_aQueryTooltipHdl.Call(rIter); }
OUString signal_query_tooltip(const TreeIter& rIter) const
{
return m_aQueryTooltipHdl.Call(rIter);
}
public:
virtual int get_item_width() const = 0;

View file

@ -84,8 +84,7 @@ void SmGraphicAccessible::ClearWin()
if ( nClientId )
{
comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
nClientId = 0;
comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( std::exchange(nClientId, 0), *this );
}
}
@ -391,8 +390,7 @@ void SAL_CALL SmGraphicAccessible::removeAccessibleEventListener(
// -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
// and at least to us not firing any events anymore, in case somebody calls
// NotifyAccessibleEvent, again
comphelper::AccessibleEventNotifier::revokeClient( nClientId );
nClientId = 0;
comphelper::AccessibleEventNotifier::revokeClient( std::exchange(nClientId, 0) );
}
}

View file

@ -36,11 +36,22 @@ public:
void PaintEntry(SvTreeListEntry&, tools::Long nX, tools::Long nY,
vcl::RenderContext& rRenderContext);
virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() override;
virtual OUString GetEntryAccessibleDescription(SvTreeListEntry* pEntry) const override;
void SetEntryAccessibleDescriptionHdl(const Link<SvTreeListEntry*, OUString>& rLink)
{
maEntryAccessibleDescriptionHdl = rLink;
}
virtual FactoryFunction GetUITestFactory() const override;
virtual void DumpAsPropertyTree(tools::JsonWriter& rJsonWriter) override;
protected:
virtual void CalcEntryHeight(SvTreeListEntry const* pEntry) override;
private:
Link<SvTreeListEntry*, OUString> maEntryAccessibleDescriptionHdl;
};
#endif

View file

@ -1759,6 +1759,7 @@ private:
DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
DECL_LINK(CommandHdl, const CommandEvent&, bool);
DECL_LINK(TooltipHdl, const HelpEvent&, bool);
DECL_LINK(EntryAccessibleDescriptionHdl, SvTreeListEntry*, OUString);
public:
SalInstanceIconView(::IconView* pIconView, SalInstanceBuilder* pBuilder, bool bTakeOwnership);

View file

@ -5317,6 +5317,10 @@ SalInstanceIconView::SalInstanceIconView(::IconView* pIconView, SalInstanceBuild
m_xIconView->SetDeselectHdl(LINK(this, SalInstanceIconView, DeSelectHdl));
m_xIconView->SetDoubleClickHdl(LINK(this, SalInstanceIconView, DoubleClickHdl));
m_xIconView->SetPopupMenuHdl(LINK(this, SalInstanceIconView, CommandHdl));
m_xIconView->SetEntryAccessibleDescriptionHdl(
LINK(this, SalInstanceIconView, EntryAccessibleDescriptionHdl));
m_xIconView->SetAccessible(m_xIconView->CreateAccessible());
}
int SalInstanceIconView::get_item_width() const { return m_xIconView->GetEntryWidth(); }
@ -5457,6 +5461,14 @@ IMPL_LINK(SalInstanceIconView, TooltipHdl, const HelpEvent&, rHEvt, bool)
return true;
}
IMPL_LINK(SalInstanceIconView, EntryAccessibleDescriptionHdl, SvTreeListEntry*, pEntry, OUString)
{
OUString s = SvTreeListBox::SearchEntryTextWithHeadTitle(pEntry);
if (s.isEmpty())
s = signal_query_tooltip(SalInstanceTreeIter(pEntry));
return s;
}
void SalInstanceIconView::connect_query_tooltip(const Link<const weld::TreeIter&, OUString>& rLink)
{
weld::IconView::connect_query_tooltip(rLink);

View file

@ -82,6 +82,15 @@ namespace vcl
return nullptr;
}
virtual css::uno::Reference< css::accessibility::XAccessible >
createAccessibleIconView(
SvTreeListBox& /*_rListBox*/,
const css::uno::Reference< css::accessibility::XAccessible >& /*_xParent*/
) const override
{
return nullptr;
}
virtual vcl::IAccessibleBrowseBox*
createAccessibleBrowseBox(
const css::uno::Reference< css::accessibility::XAccessible >& /*_rxParent*/,

View file

@ -21,6 +21,7 @@
#include <vcl/toolkit/viewdataentry.hxx>
#include <iconview.hxx>
#include "iconviewimpl.hxx"
#include <vcl/accessiblefactory.hxx>
#include <vcl/uitest/uiobject.hxx>
#include <tools/json_writer.hxx>
#include <vcl/toolkit/svlbitm.hxx>
@ -231,6 +232,30 @@ void IconView::PaintEntry(SvTreeListEntry& rEntry, tools::Long nX, tools::Long n
}
}
css::uno::Reference<css::accessibility::XAccessible> IconView::CreateAccessible()
{
if (vcl::Window* pParent = GetAccessibleParentWindow())
{
if (auto xAccParent = pParent->GetAccessible())
{
// need to be done here to get the vclxwindow later on in the accessible
css::uno::Reference<css::awt::XWindowPeer> xHoldAlive(GetComponentInterface());
return pImpl->m_aFactoryAccess.getFactory().createAccessibleIconView(*this, xAccParent);
}
}
return {};
}
OUString IconView::GetEntryAccessibleDescription(SvTreeListEntry* pEntry) const
{
assert(pEntry);
if (maEntryAccessibleDescriptionHdl.IsSet())
return maEntryAccessibleDescriptionHdl.Call(pEntry);
return SvTreeListBox::GetEntryAccessibleDescription(pEntry);
}
FactoryFunction IconView::GetUITestFactory() const { return IconViewUIObject::create; }
static OUString extractPngString(const SvLBoxContextBmp* pBmpItem)

View file

@ -3513,6 +3513,33 @@ void SvTreeListBox::FillAccessibleEntryStateSet( SvTreeListEntry* pEntry, ::utl:
}
}
OUString SvTreeListBox::GetEntryAccessibleDescription(SvTreeListEntry* pEntry) const
{
assert(pEntry);
//want to count the real column number in the list box.
sal_uInt16 iRealItemCount = 0;
for (size_t i = 0; i < pEntry->ItemCount(); ++i)
{
const SvLBoxItem& rItem = pEntry->GetItem(i);
if (rItem.GetType() == SvLBoxItemType::String &&
!static_cast<const SvLBoxString&>(rItem).GetText().isEmpty())
{
iRealItemCount++;
}
}
// No idea why <= 1; that was in AccessibleListBoxEntry::getAccessibleDescription
// since the "Integrate branch of IAccessible2" commit
if (iRealItemCount <= 1)
{
return {};
}
else
{
return SearchEntryTextWithHeadTitle(pEntry);
}
}
tools::Rectangle SvTreeListBox::GetBoundingRect(const SvTreeListEntry* pEntry)
{
Point aPos = GetEntryPosition( pEntry );