vcl/inc/accessibility/vclxaccessiblelistitem.hxx | 38 +----- vcl/source/accessibility/vclxaccessiblelistitem.cxx | 122 ++------------------ 2 files changed, 24 insertions(+), 136 deletions(-)
New commits: commit 95aaa121a5705a029f147a92d5818469c161ce92 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Tue Feb 11 15:32:59 2025 +0100 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Wed Feb 12 08:07:25 2025 +0100 list item a11y: Use comphelper::OAccessibleComponentHelper Let VCLXAccessibleListItem subclass comphelper::OAccessibleComponentHelper which already implements the logic for event handling and most of the location/bounds handling, instead of duplicating the logic here. The existing VCLXAccessibleListItem::implGetBounds basically already implements the logic needed to override the purely virtual comphelper::OAccessibleComponentHelper::implGetBounds, only the required conversion from tools::Rectangle to awt::Rectangle is still added in this commit. Tested as described in more detail in previous commit Change-Id: I53c686276537713fec604eb22d19be2331ce1f56 Author: Michael Weghorn <m.wegh...@posteo.de> Date: Tue Feb 11 15:13:41 2025 +0100 list item a11y: Fix parent-relative position with no change in behavior noticed (now that the issues detected previously have been addressed in previous commits already in preparation for this commit). Change-Id: I74e53e3297948977bed1b8608468dc8378859426 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181433 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/vcl/inc/accessibility/vclxaccessiblelistitem.hxx b/vcl/inc/accessibility/vclxaccessiblelistitem.hxx index 5345de57ffe9..e3d3b87abc35 100644 --- a/vcl/inc/accessibility/vclxaccessiblelistitem.hxx +++ b/vcl/inc/accessibility/vclxaccessiblelistitem.hxx @@ -21,10 +21,7 @@ #include <com/sun/star/accessibility/AccessibleScrollType.hpp> #include <com/sun/star/accessibility/XAccessible.hpp> -#include <com/sun/star/accessibility/XAccessibleComponent.hpp> -#include <com/sun/star/accessibility/XAccessibleContext.hpp> #include <com/sun/star/accessibility/XAccessibleText.hpp> -#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <comphelper/compbase.hxx> #include <comphelper/accessibletexthelper.hxx> @@ -42,18 +39,13 @@ namespace com::sun::star::awt { // class VCLXAccessibleListItem ------------------------------------------ -typedef ::comphelper::WeakComponentImplHelper< css::accessibility::XAccessible - , css::accessibility::XAccessibleContext - , css::accessibility::XAccessibleComponent - , css::accessibility::XAccessibleEventBroadcaster - , css::accessibility::XAccessibleText - , css::lang::XServiceInfo > VCLXAccessibleListItem_BASE; - /** the class OAccessibleListBoxEntry represents the base class for an accessible object of a listbox entry */ -class VCLXAccessibleListItem final : - public ::comphelper::OCommonAccessibleText, - public VCLXAccessibleListItem_BASE +class VCLXAccessibleListItem final + : public cppu::ImplInheritanceHelper< + comphelper::OAccessibleComponentHelper, css::accessibility::XAccessible, + css::accessibility::XAccessibleText, css::lang::XServiceInfo>, + public comphelper::OCommonAccessibleText { private: OUString m_sEntryText; @@ -61,22 +53,19 @@ private: bool m_bSelected; bool m_bVisible; - /// client id in the AccessibleEventNotifier queue - sal_uInt32 m_nClientId; - rtl::Reference< VCLXAccessibleList > m_xParent; virtual ~VCLXAccessibleListItem() override = default; - /** this function is called upon disposing the component - */ - virtual void disposing(std::unique_lock<std::mutex>& rGuard) override; + + virtual void SAL_CALL disposing() override; // OCommonAccessibleText virtual OUString implGetText() override; virtual css::lang::Locale implGetLocale() override; virtual void implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ) override; - tools::Rectangle implGetBounds(); + // OCommonAccessibleComponent + virtual css::awt::Rectangle implGetBounds() override; OUString getTextRangeImpl(sal_Int32 nStartIndex, sal_Int32 nEndIndex); @@ -120,12 +109,7 @@ public: virtual css::lang::Locale SAL_CALL getLocale( ) override; // XAccessibleComponent - virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override; virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override; - virtual css::awt::Rectangle SAL_CALL getBounds( ) override; - virtual css::awt::Point SAL_CALL getLocation( ) override; - virtual css::awt::Point SAL_CALL getLocationOnScreen( ) override; - virtual css::awt::Size SAL_CALL getSize( ) override; virtual void SAL_CALL grabFocus( ) override; virtual sal_Int32 SAL_CALL getForeground() override; virtual sal_Int32 SAL_CALL getBackground() override; @@ -149,10 +133,6 @@ public: virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) override; virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override; virtual sal_Bool SAL_CALL scrollSubstringTo( sal_Int32 nStartIndex, sal_Int32 nEndIndex, css::accessibility::AccessibleScrollType aScrollType) override; - - // XAccessibleEventBroadcaster - virtual void SAL_CALL addAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override; - virtual void SAL_CALL removeAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override; }; diff --git a/vcl/source/accessibility/vclxaccessiblelistitem.cxx b/vcl/source/accessibility/vclxaccessiblelistitem.cxx index cfde41faa73e..54bb44ddd281 100644 --- a/vcl/source/accessibility/vclxaccessiblelistitem.cxx +++ b/vcl/source/accessibility/vclxaccessiblelistitem.cxx @@ -59,11 +59,11 @@ using namespace ::com::sun::star; // Ctor() and Dtor() -VCLXAccessibleListItem::VCLXAccessibleListItem(sal_Int32 _nIndexInParent, rtl::Reference< VCLXAccessibleList > _xParent) +VCLXAccessibleListItem::VCLXAccessibleListItem(sal_Int32 _nIndexInParent, + rtl::Reference<VCLXAccessibleList> _xParent) : m_nIndexInParent(_nIndexInParent) , m_bSelected(false) , m_bVisible(false) - , m_nClientId(0) , m_xParent(std::move(_xParent)) { assert(m_xParent.is()); @@ -104,14 +104,8 @@ void VCLXAccessibleListItem::NotifyAccessibleEvent( sal_Int16 _nEventId, const css::uno::Any& _aOldValue, const css::uno::Any& _aNewValue ) { - AccessibleEventObject aEvt; - aEvt.Source = *this; - aEvt.EventId = _nEventId; - aEvt.OldValue = _aOldValue; - aEvt.NewValue = _aNewValue; - - if (m_nClientId) - comphelper::AccessibleEventNotifier::addEvent( m_nClientId, aEvt ); + comphelper::OAccessibleComponentHelper::NotifyAccessibleEvent(_nEventId, _aOldValue, + _aNewValue); } // OCommonAccessibleText @@ -132,7 +126,7 @@ void VCLXAccessibleListItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32 nEndIndex = 0; } -tools::Rectangle VCLXAccessibleListItem::implGetBounds() +awt::Rectangle VCLXAccessibleListItem::implGetBounds() { tools::Rectangle aRect; IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr; @@ -144,7 +138,7 @@ tools::Rectangle VCLXAccessibleListItem::implGetBounds() aRect -= vcl::unohelper::ConvertToVCLPoint(m_xParent->getLocation()); } - return aRect; + return vcl::unohelper::ConvertToAWTRect(aRect); } // XTypeProvider @@ -156,24 +150,12 @@ Sequence< sal_Int8 > VCLXAccessibleListItem::getImplementationId() // XComponent -void VCLXAccessibleListItem::disposing(std::unique_lock<std::mutex>& rGuard) +void SAL_CALL VCLXAccessibleListItem::disposing() { - VCLXAccessibleListItem_BASE::disposing(rGuard); - m_sEntryText.clear(); - m_xParent = nullptr; - comphelper::AccessibleEventNotifier::TClientId nId = m_nClientId; - m_nClientId = 0; - Reference< XInterface > xEventSource; - if ( nId ) - { - xEventSource = *this; + m_xParent = nullptr; - // Send a disposing to all listeners. - rGuard.unlock(); - comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this ); - rGuard.lock(); - } + OAccessibleComponentHelper::disposing(); } // XServiceInfo @@ -257,7 +239,7 @@ sal_Int64 SAL_CALL VCLXAccessibleListItem::getAccessibleStateSet( ) sal_Int64 nStateSet = 0; - if ( !m_bDisposed ) + if (isAlive()) { nStateSet |= AccessibleStateType::TRANSIENT; @@ -292,55 +274,11 @@ Locale SAL_CALL VCLXAccessibleListItem::getLocale( ) // XAccessibleComponent -sal_Bool SAL_CALL VCLXAccessibleListItem::containsPoint( const awt::Point& _aPoint ) -{ - SolarMutexGuard aSolarGuard; - - tools::Rectangle aRect = implGetBounds(); - aRect.SetPos(Point(0, 0)); - const bool bInside = aRect.Contains(vcl::unohelper::ConvertToVCLPoint(_aPoint)); - return bInside; -} - Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleAtPoint( const awt::Point& ) { return Reference< XAccessible >(); } -awt::Rectangle SAL_CALL VCLXAccessibleListItem::getBounds( ) -{ - SolarMutexGuard aSolarGuard; - - return vcl::unohelper::ConvertToAWTRect(implGetBounds()); -} - -awt::Point SAL_CALL VCLXAccessibleListItem::getLocation( ) -{ - SolarMutexGuard aSolarGuard; - - const Point aPoint = implGetBounds().TopLeft(); - return vcl::unohelper::ConvertToAWTPoint(aPoint); -} - -awt::Point SAL_CALL VCLXAccessibleListItem::getLocationOnScreen( ) -{ - SolarMutexGuard aSolarGuard; - - Point aPoint = implGetBounds().TopLeft(); - if (m_xParent.is()) - aPoint += vcl::unohelper::ConvertToVCLPoint(m_xParent->getLocationOnScreen()); - - return vcl::unohelper::ConvertToAWTPoint(aPoint); -} - -awt::Size SAL_CALL VCLXAccessibleListItem::getSize( ) -{ - SolarMutexGuard aSolarGuard; - - Size aSize = implGetBounds().GetSize(); - return vcl::unohelper::ConvertToAWTSize(aSize); -} - void SAL_CALL VCLXAccessibleListItem::grabFocus( ) { // no focus for each item @@ -526,40 +464,6 @@ sal_Bool VCLXAccessibleListItem::scrollSubstringTo( sal_Int32, sal_Int32, Access return false; } -// XAccessibleEventBroadcaster - -void SAL_CALL VCLXAccessibleListItem::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener ) -{ - if (xListener.is()) - { - if (!m_nClientId) - m_nClientId = comphelper::AccessibleEventNotifier::registerClient( ); - comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener ); - } -} - -void SAL_CALL VCLXAccessibleListItem::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener ) -{ - if ( !(xListener.is() && m_nClientId) ) - return; - - sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener ); - if ( nListenerCount ) - return; - - // no listeners anymore - // -> 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 - if ( m_nClientId ) - { - comphelper::AccessibleEventNotifier::TClientId nId( m_nClientId ); - m_nClientId = 0; - comphelper::AccessibleEventNotifier::revokeClient( nId ); - } -} - - // AF (Oct. 29 2002): Return black as constant foreground color. This is an // initial implementation and has to be substituted by code that determines // the color that is actually used. commit f315c44bbf1cf8002302f1f760befbb0aa031b22 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Tue Feb 11 15:13:41 2025 +0100 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Wed Feb 12 08:07:20 2025 +0100 list item a11y: Fix parent-relative position XAccessibleComponent::getLocation etc. are supposed to return the objects position relative to its direct accessible parent. However, IComboListBoxHelper::GetBoundingRectangle used by the VCLXAccessibleListItem::implGetBounds helper method returns the position relative to the ComboBox or ListBox for which the a11y implementation is , which is a VCLXAccessibleBox subclass, and that is actually the VCLXAccessibleListItem's accessible "grandparent" (parent's parent), as the direct parent is a VCLXAccessibleList. Therefore, the parent-relative position was incorrect. Fix that by subtracting the parent's relative position within the ListBox/ComboBox. VCLXAccessibleListItem::getLocationOnScreen, which returns the absolute screen position, was correct, because it added the combobox/listbox position to the "parent-relative" position (which was actually the position relative to the combobox/listbox). Now that VCLXAccessibleListItem::implGetBounds returns the position relative to the actual parent, also adjust VCLXAccessibleListItem::getLocationOnScreen to add the actual parent's location on screen. The issue about incorrect parent-relative positions was noticed with an (upcoming) change that refactors VCLXAccessibleListItem to subclass comphelper::OAccessibleComponentHelper where the parent-relative position gets used. Issue could also be reproduced like this: 1) apply only the VCLXAccessibleListItem::getLocationOnScreen part of this change 2) run Python script attachment 199141 from tdf#161087 on X11/XWayland which highlights the area of the currently focused object: GDK_BACKEND=x11 python3 ./highlight-focused-object.py 3) start LO with the qt6 VCL plugin on X11/XWayland: QT_QPA_PLATFORM=xcb SAL_USE_VCLPLUGIN=qt6 ./instdir/program/soffice.bin --writer 4) Navigate to the "Styles" combobox in the formatting toolbar 5) Press Alt+Down to expand, then arrow keys to navigate through the combobox entries (Note: Running Orca in addition can help to trigger creation of the the required a11y objects and events.) Without this change in place, the wrong area was highlighted when moving between entries. Now, the correct area of the currently focused combobox entry is highlighted. Change-Id: I53c686276537713fec604eb22d19be2331ce1f56 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181432 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/vcl/source/accessibility/vclxaccessiblelistitem.cxx b/vcl/source/accessibility/vclxaccessiblelistitem.cxx index 5437f0f58627..cfde41faa73e 100644 --- a/vcl/source/accessibility/vclxaccessiblelistitem.cxx +++ b/vcl/source/accessibility/vclxaccessiblelistitem.cxx @@ -137,7 +137,12 @@ tools::Rectangle VCLXAccessibleListItem::implGetBounds() tools::Rectangle aRect; IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr; if (pListBoxHelper) + { aRect = pListBoxHelper->GetBoundingRectangle(static_cast<sal_uInt16>(m_nIndexInParent)); + // convert position relative to the combobox/listbox (parent's parent) to position relative + // to direct parent by subtracting parent's relative position in the combobox/listbox + aRect -= vcl::unohelper::ConvertToVCLPoint(m_xParent->getLocation()); + } return aRect; } @@ -322,9 +327,8 @@ awt::Point SAL_CALL VCLXAccessibleListItem::getLocationOnScreen( ) SolarMutexGuard aSolarGuard; Point aPoint = implGetBounds().TopLeft(); - IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr; - if (pListBoxHelper) - aPoint += Point(pListBoxHelper->GetWindowExtentsAbsolute().TopLeft()); + if (m_xParent.is()) + aPoint += vcl::unohelper::ConvertToVCLPoint(m_xParent->getLocationOnScreen()); return vcl::unohelper::ConvertToAWTPoint(aPoint); }