winaccessibility/inc/AccDescendantManagerEventListener.hxx | 3 + winaccessibility/source/service/AccDescendantManagerEventListener.cxx | 20 ++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-)
New commits: commit 836a226205df9e76e77d26af80f402de7b876d61 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Thu Sep 16 07:11:47 2021 +0100 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Thu Sep 16 09:25:36 2021 +0200 tdf#100086 wina11y: Don't delete a11y object for removed cell right away When handling a SELECTION_CHANGED_REMOVE event, AccDescendantManagerEventListener previously emitted a corresponding EVENT_OBJECT_SELECTIONREMOVE MSAA event with the removed child's ID as a parameter, then deleted that child's accessibility object. This resulted in the accessibility object no longer being available if accessibility tools queried for the object just received in the EVENT_OBJECT_SELECTIONREMOVE event. As a consequence, no 'event_selectionRemove' would be triggered for any table cell object on NVDA side, so an updated selection would not be announced for that case. To keep child objects available for such cases, don't delete the corresponding object in the handler for the SELECTION_CHANGED_REMOVE handler, but remember it for deletion and only do the actual deletion once a subsequent different event is handled. With this in place, the announcement for multiple selected cells in Calc generally works with the NVDA screen reader and a pending NVDA pull request [1] by Leonard de Ruijter in place (s.a. discussion in NVDA issue [2] for more background and further information). (There are still cases where events in response to selection changes are missing, as described e.g. in tdf#118508 and tdf#118748, but those are not winaccessibility-specific and it's the same when using the gtk3 VCL plugin with the Orca screen reader on Linux.) [1] https://github.com/nvaccess/nvda/pull/12849 [2] https://github.com/nvaccess/nvda/issues/9310 Change-Id: I7a46060c501ba9b8288e7c127121a535c60ce2bc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122169 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/winaccessibility/inc/AccDescendantManagerEventListener.hxx b/winaccessibility/inc/AccDescendantManagerEventListener.hxx index 57ae373ce5f7..73cda0f4eb46 100644 --- a/winaccessibility/inc/AccDescendantManagerEventListener.hxx +++ b/winaccessibility/inc/AccDescendantManagerEventListener.hxx @@ -20,6 +20,7 @@ #pragma once #include <stdio.h> +#include <vector> #include "AccComponentEventListener.hxx" #include <com/sun/star/accessibility/XAccessibleEventListener.hpp> #include <com/sun/star/accessibility/XAccessible.hpp> @@ -32,6 +33,8 @@ */ class AccDescendantManagerEventListener: public AccComponentEventListener { +private: + std::vector<com::sun::star::accessibility::XAccessible*> m_aUnselectedChildrenForDeletion; public: AccDescendantManagerEventListener(css::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent); diff --git a/winaccessibility/source/service/AccDescendantManagerEventListener.cxx b/winaccessibility/source/service/AccDescendantManagerEventListener.cxx index c8fc771ae503..479f045cf6f3 100644 --- a/winaccessibility/source/service/AccDescendantManagerEventListener.cxx +++ b/winaccessibility/source/service/AccDescendantManagerEventListener.cxx @@ -183,10 +183,24 @@ bool AccDescendantManagerEventListener::NotifyChildEvent(short nWinEvent,const A XAccessible* pAcc = xChild.get(); pAgent->NotifyAccEvent(nWinEvent, pAcc); - if (pAgent->IsStateManageDescendant(m_xAccessible.get()) - && (nWinEvent == UM_EVENT_SELECTION_CHANGED_REMOVE)) + if (pAgent->IsStateManageDescendant(m_xAccessible.get())) { - pAgent->DeleteAccObj( pAcc ); + if (nWinEvent == UM_EVENT_SELECTION_CHANGED_REMOVE) + { + // The object has just been sent in a SELECTION_CHANGED_REMOVE event + // and accessibility tools may query for the object and call methods on + // it as a response to this. + // Therefore, don't delete the object yet, but remember it for deletion + // once the next event of a different type occurs. + m_aUnselectedChildrenForDeletion.push_back(pAcc); + } + else + { + // handle any pending deletions for objects previously removed from selection + for (XAccessible* pAcc : m_aUnselectedChildrenForDeletion) + pAgent->DeleteAccObj(pAcc); + m_aUnselectedChildrenForDeletion.clear(); + } } return true; }