tdf#157092 a11y Let only drawing area dispose its ValueSet acc
Don't dispose the a11y object in the `ValueSet` dtor, because it
doesn't own its a11y object, but it is owned by the `weld::DrawingArea`
of the `CustomWeld` that the `ValueSet` (as a sub-class of
`CustomWidgetController`) belongs to.
The `CustomWeld` ctor passes the a11y ref retrieved by
`CustomWidgetController::createAccessible` to `weld_drawing_area`,
which takes ownership and disposes the object.
(For Gtk, see `GtkInstanceDrawingArea::~GtkInstanceDrawingArea`.
For non-Gtk, see how the `SalInstanceDrawingArea` ctor
passes the reference to `VclInstanceDrawingArea::SetAccessible`/
`vcl::Window::SetAccessible`, so it gets disposed when that
`VclInstanceDrawingArea` gets disposed, s. `vcl::Window::dispose`.)
Other classes derived from `CustomWidgetController`
also don't dispose the a11y object themselves.
Still reset the `ValueSet` pointer in `ValueSetAcc` to
nullptr when the `ValueSet` gets destroyed and turn the
check for a valid pointer from just an `OSL_ASSERT`
to a real assert and throwing a `RuntimeException`.
But still allow getting the a11y context when only
the ValueSet has been deleted but the object has not
been disposed yet.
Fixes a crash due to a `com::sun::star::lang::DisposedException`
being thrown when using the new search feature in the "Tools" ->
"Options" dialog (or when just switching to the "LibreOfficeDev
Writer/Web" -> "Background" page with the qt6 VCL plugin or
on Windows when the NVDA screen reader is running.
This happens when the drawing area is hidden and the a11y layer
is meant to be notified about this (so the a11y object can be
removed).
It still seems a bit odd that the `ValueSet` gets destroyed
(in `SvxColorTabPage::~SvxColorTabPage`, frame 20 in below backtrace)
before the corresponding `vcl::Window` gets hidden (in the base
class dtor, `SfxTabPage::~SfxTabPage`, s. frame 19 in the backtrace).
Backtrace for how the exception gets thrown:
1 com::sun::star::lang::DisposedException::DisposedException DisposedException.hpp 40 0x7fa385fd9ca9
2 ValueSetAcc::ThrowIfDisposed valueacc.cxx 956 0x7fa385fd9342
3 ValueSetAcc::getAccessibleContext valueacc.cxx 473 0x7fa385fd69fa
4 VCLXAccessibleComponent::ProcessWindowChildEvent vclxaccessiblecomponent.cxx 186 0x7fa3853dc905
5 VCLXAccessibleComponent::WindowChildEventListener vclxaccessiblecomponent.cxx 124 0x7fa3853dc51d
6 VCLXAccessibleComponent::LinkStubWindowChildEventListener vclxaccessiblecomponent.cxx 114 0x7fa3853dc43f
7 Link<VclWindowEvent&, void>::Call link.hxx 111 0x7fa382c56ccf
8 vcl::Window::CallEventListeners event.cxx 296 0x7fa382c53e5b
9 vcl::Window::ImplResetReallyVisible stacking.cxx 719 0x7fa382b51a49
10 vcl::Window::ImplResetReallyVisible stacking.cxx 735 0x7fa382b51b0e
11 vcl::Window::ImplResetReallyVisible stacking.cxx 735 0x7fa382b51b0e
12 vcl::Window::ImplResetReallyVisible stacking.cxx 735 0x7fa382b51b0e
13 vcl::Window::ImplResetReallyVisible stacking.cxx 735 0x7fa382b51b0e
14 vcl::Window::ImplResetReallyVisible stacking.cxx 735 0x7fa382b51b0e
15 vcl::Window::ImplResetReallyVisible stacking.cxx 735 0x7fa382b51b0e
16 vcl::Window::Show window.cxx 2234 0x7fa382d94f7c
17 vcl::Window::Hide window.hxx 880 0x7fa382b23600
18 SalInstanceContainer::move salvtables.cxx 1352 0x7fa3834789f3
19 SfxTabPage::~SfxTabPage tabdlg.cxx 157 0x7fa38928ab47
20 SvxColorTabPage::~SvxColorTabPage tpcolor.cxx 166 0x7fa350950d3e
21 SvxColorTabPage::~SvxColorTabPage tpcolor.cxx 166 0x7fa350950d5a
22 std::default_delete<SfxTabPage>::operator() unique_ptr.h 99 0x7fa350538fdc
23 std::__uniq_ptr_impl<SfxTabPage, std::default_delete<SfxTabPage>>::reset unique_ptr.h 211 0x7fa35080dcbe
24 std::unique_ptr<SfxTabPage, std::default_delete<SfxTabPage>>::reset unique_ptr.h 509 0x7fa350808555
25 SvxAreaTabPage::SetOptimalSize tparea.cxx 155 0x7fa35093db3e
26 SvxBkgTabPage::Create backgrnd.cxx 230 0x7fa350864dbc
27 SwModule::CreateTabPage appopt.cxx 509 0x7fa339e10973
28 OfaTreeOptionsDialog::SelectHdl_Impl treeopt.cxx 1335 0x7fa3507f947a
29 OfaTreeOptionsDialog::ShowPageHdl_Impl treeopt.cxx 625 0x7fa3507f4782
30 OfaTreeOptionsDialog::LinkStubShowPageHdl_Impl treeopt.cxx 623 0x7fa3507f4763
31 Link<weld::TreeView&, void>::Call link.hxx 111 0x7fa3834b18f1
32 weld::TreeView::signal_changed weld.hxx 953 0x7fa3834aa10d
33 SalInstanceTreeView::SelectHdl salvtables.cxx 5276 0x7fa38349363e
34 SalInstanceTreeView::LinkStubSelectHdl salvtables.cxx 5272 0x7fa3834935fb
35 Link<SvTreeListBox *, void>::Call link.hxx 111 0x7fa382b8a339
36 SvTreeListBox::SelectHdl treelistbox.cxx 452 0x7fa38307f5c2
37 SvTreeListBox::Select treelistbox.cxx 2111 0x7fa383085b4a
38 SvImpLBox::SetCursor svimpbox.cxx 614 0x7fa3830a66c3
39 ImpLBSelEng::SetCursorAtPoint svimpbox.cxx 2575 0x7fa3830aeaa8
40 SelectionEngine::SelMouseButtonDown seleng.cxx 172 0x7fa382d09354
41 SvImpLBox::MouseButtonDown svimpbox.cxx 2004 0x7fa3830ac9f8
42 SvTreeListBox::MouseButtonDown treelistbox.cxx 2260 0x7fa383086422
43 ImplHandleMouseEvent winproc.cxx 707 0x7fa382daed00
44 ImplHandleSalMouseButtonDown winproc.cxx 2340 0x7fa382db5c5d
45 ImplWindowFrameProc winproc.cxx 2685 0x7fa382db6f7e
46 SalFrame::CallCallback salframe.hxx 310 0x7fa378ca4edc
47 QtFrame::CallCallback QtFrame.hxx 230 0x7fa378ca6418
48 QtWidget::handleMouseButtonEvent QtWidget.cxx 181 0x7fa378cf959b
49 QtWidget::mousePressEvent QtWidget.cxx 186 0x7fa378cf95f3
50 QWidget::event qwidget.cpp 8978 0x7fa376a2f327
51 QtWidget::event QtWidget.cxx 730 0x7fa378cfb2f6
52 QApplicationPrivate::notify_helper qapplication.cpp 3287 0x7fa3769a666a
53 QApplication::notify qapplication.cpp 2774 0x7fa3769a4539
54 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1125 0x7fa3783a5ed0
55 QCoreApplication::sendSpontaneousEvent qcoreapplication.cpp 1573 0x7fa3783a6a1d
56 QApplicationPrivate::sendMouseEvent qapplication.cpp 2358 0x7fa3769a31a2
57 QWidgetWindow::handleMouseEvent qwidgetwindow.cpp 627 0x7fa376a5f7cb
58 QWidgetWindow::event qwidgetwindow.cpp 241 0x7fa376a5dcfd
59 QApplicationPrivate::notify_helper qapplication.cpp 3287 0x7fa3769a666a
60 QApplication::notify qapplication.cpp 3238 0x7fa3769a647a
61 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1125 0x7fa3783a5ed0
62 QCoreApplication::sendSpontaneousEvent qcoreapplication.cpp 1573 0x7fa3783a6a1d
63 QGuiApplicationPrivate::processMouseEvent qguiapplication.cpp 2315 0x7fa3775f21cd
64 QGuiApplicationPrivate::processWindowSystemEvent qguiapplication.cpp 2061 0x7fa3775f15cf
65 QWindowSystemInterface::sendWindowSystemEvents qwindowsysteminterface.cpp 1109 0x7fa37769ce23
66 xcbSourceDispatch qxcbeventdispatcher.cpp 57 0x7fa376064df7
67 ?? 0x7fa37df2b5b4
68 ?? 0x7fa37df2e607
69 g_main_context_iteration 0x7fa37df2ebfc
70 QEventDispatcherGlib::processEvents qeventdispatcher_glib.cpp 395 0x7fa3787b6b33
71 QXcbGlibEventDispatcher::processEvents qxcbeventdispatcher.cpp 96 0x7fa37606502c
72 QtInstance::ImplYield QtInstance.cxx 421 0x7fa378cc7502
73 QtInstance::DoYield QtInstance.cxx 432 0x7fa378cc762b
74 ImplYield svapp.cxx 372 0x7fa3835220ea
75 Application::Yield svapp.cxx 456 0x7fa383522e88
76 Dialog::Execute dialog.cxx 1078 0x7fa382c063e1
77 SalInstanceDialog::run salvtables.cxx 1877 0x7fa38347c313
78 weld::DialogController::run weld.hxx 2659 0x7fa3504a26e6
79 OfaTreeOptionsDialog::run treeopt.cxx 2587 0x7fa3508035fd
80 CuiAbstractController_Impl::Execute dlgfact.cxx 144 0x7fa35069d829
81 SfxApplication::OfaExec_Impl appserv.cxx 1463 0x7fa388faf85e
82 SfxStubSfxApplicationOfaExec_Impl sfxslots.hxx 1309 0x7fa388f88faf
83 SfxDispatcher::Call_Impl dispatch.cxx 254 0x7fa3890bfb4a
84 SfxDispatcher::Execute_ dispatch.cxx 753 0x7fa3890c31f4
85 SfxBindings::Execute_Impl bindings.cxx 1061 0x7fa3890aefa0
86 SfxDispatchController_Impl::dispatch unoctitm.cxx 688 0x7fa389185ba6
87 SfxOfficeDispatch::dispatch unoctitm.cxx 250 0x7fa389183867
88 framework::MenuBarManager::Select menubarmanager.cxx 827 0x7fa38a7e2dff
89 framework::MenuBarManager::LinkStubSelect menubarmanager.cxx 791 0x7fa38a7e2ab7
90 Link<Menu *, bool>::Call link.hxx 111 0x7fa382cb0337
91 Menu::Select menu.cxx 358 0x7fa382ca1c90
92 Menu::ImplCallSelect menu.cxx 2135 0x7fa382caa907
93 Menu::LinkStubImplCallSelect menu.cxx 2132 0x7fa382caa8d9
94 Link<void *, void>::Call link.hxx 111 0x7fa382db870d
95 ImplHandleUserEvent winproc.cxx 2287 0x7fa382db57ca
96 ImplWindowFrameProc winproc.cxx 2851 0x7fa382db76f7
97 SalFrame::CallCallback salframe.hxx 310 0x7fa378ca4edc
98 QtInstance::ProcessEvent QtInstance.cxx 484 0x7fa378cc799b
99 operator() salusereventlist.cxx 119 0x7fa383465b7b
100 SalUserEventList::DispatchUserEvents salusereventlist.cxx 120 0x7fa383465e4f
101 QtInstance::ImplYield QtInstance.cxx 410 0x7fa378cc7480
102 QtInstance::DoYield QtInstance.cxx 432 0x7fa378cc762b
103 ImplYield svapp.cxx 372 0x7fa3835220ea
104 Application::Yield svapp.cxx 456 0x7fa383522e88
105 Application::Execute svapp.cxx 350 0x7fa383521ddd
106 desktop::Desktop::Main app.cxx 1601 0x7fa38ca36276
107 ImplSVMain svmain.cxx 204 0x7fa383541e84
108 SVMain svmain.cxx 236 0x7fa383541fb9
109 soffice_main sofficemain.cxx 94 0x7fa38caa1b5d
110 sal_main main.c 51 0x5568fd6859d4
111 main main.c 49 0x5568fd6859ba
Change-Id: I247648a7a707f02bf1fdd339d3c329694636d835
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156645
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx
index cdf7596..2f897ae 100644
--- a/svtools/source/control/valueacc.cxx
+++ b/svtools/source/control/valueacc.cxx
@@ -29,6 +29,7 @@
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
using namespace ::com::sun::star;
@@ -470,7 +471,8 @@ void ValueSetAcc::LoseFocus()
uno::Reference< accessibility::XAccessibleContext > SAL_CALL ValueSetAcc::getAccessibleContext()
{
ThrowIfDisposed();
// still allow retrieving a11y context when not disposed yet, but ValueSet is unset
ThrowIfDisposed(false);
return this;
}
@@ -886,16 +888,16 @@ void SAL_CALL ValueSetAcc::deselectAccessibleChild( sal_Int64 nChildIndex )
mpParent->SetNoSelection();
}
void ValueSetAcc::Invalidate()
{
mpParent = nullptr;
}
void ValueSetAcc::disposing(std::unique_lock<std::mutex>& rGuard)
{
// Make a copy of the list and clear the original.
::std::vector<uno::Reference<accessibility::XAccessibleEventListener> > aListenerListCopy = std::move(mxEventListeners);
// Reset the pointer to the parent. It has to be the one who has
// disposed us because he is dying.
mpParent = nullptr;
if (aListenerListCopy.empty())
return;
@@ -946,7 +948,7 @@ ValueSetItem* ValueSetAcc::getItem (sal_uInt16 nIndex) const
}
void ValueSetAcc::ThrowIfDisposed()
void ValueSetAcc::ThrowIfDisposed(bool bCheckParent)
{
if (m_bDisposed)
{
@@ -955,9 +957,11 @@ void ValueSetAcc::ThrowIfDisposed()
"object has been already disposed",
getXWeak());
}
else
if (bCheckParent && !mpParent)
{
DBG_ASSERT (mpParent!=nullptr, "ValueSetAcc not disposed but mpParent == NULL");
assert(false && "ValueSetAcc not disposed but mpParent == NULL");
throw css::uno::RuntimeException("ValueSetAcc not disposed but mpParent == NULL");
}
}
diff --git a/svtools/source/control/valueimp.hxx b/svtools/source/control/valueimp.hxx
index ed34aa3..fca4e43 100644
--- a/svtools/source/control/valueimp.hxx
+++ b/svtools/source/control/valueimp.hxx
@@ -97,6 +97,9 @@ public:
*/
void LoseFocus();
/** Called by the corresponding ValueSet when it gets destroyed. */
void Invalidate();
// XAccessible
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override;
@@ -167,9 +170,12 @@ private:
state of being disposed). If that is the case then
DisposedException is thrown to inform the (indirect) caller of the
foul deed.
@param bCheckValueSet
Whether to also check that the ValueSet (parent)
is non-null.
@throws css::lang::DisposedException
*/
void ThrowIfDisposed();
void ThrowIfDisposed(bool bCheckParent = true);
/** Check whether the value set has a 'none' field, i.e. a field (button)
that deselects any items (selects none of them).
diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx
index e40da61..89ce7f8 100644
--- a/svtools/source/control/valueset.cxx
+++ b/svtools/source/control/valueset.cxx
@@ -124,7 +124,7 @@ Reference<XAccessible> ValueSet::CreateAccessible()
ValueSet::~ValueSet()
{
if (mxAccessible)
mxAccessible->dispose();
mxAccessible->Invalidate();
ImplDeleteItems();
}