svtools/source/control/valueacc.cxx |   20 ++++++++++++--------
 svtools/source/control/valueimp.hxx |    8 +++++++-
 svtools/source/control/valueset.cxx |    2 +-
 3 files changed, 20 insertions(+), 10 deletions(-)

New commits:
commit 2f5e7a07775690e57d639eeca7a1e41733fa93a9
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Thu Sep 7 08:09:31 2023 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Thu Sep 7 13:13:18 2023 +0200

    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.wegh...@posteo.de>

diff --git a/svtools/source/control/valueacc.cxx 
b/svtools/source/control/valueacc.cxx
index cdf759621042..2f897ae015ce 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 ed34aa35995b..fca4e438f72f 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 e40da6193084..89ce7f8cdb23 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();
 }

Reply via email to