vcl/qt5/QtAccessibleWidget.cxx |   20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

New commits:
commit 3eaa35e8bacc19a85f5c9d907450846bfa8bffae
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Tue Jan 14 11:32:25 2025 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Tue Jan 14 15:24:32 2025 +0100

    tdf#163335 qt a11y: Work around broken sw selection handling
    
    When using the qt6 vcl plugin with the Orca screen reader
    running, selecting text in Writer resulted in a crash
    due to an IndexOutOfBoundsException being thrown.
    
    Backtrace:
    
        Thread 1 received signal SIGABRT, Aborted.
        __pthread_kill_implementation (threadid=<optimized out>, 
signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
        warning: 44     ./nptl/pthread_kill.c: No such file or directory
        (rr) bt
        #0  __pthread_kill_implementation (threadid=<optimized out>, 
signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
        #1  0x00007f889b09ddef in __pthread_kill_internal (threadid=<optimized 
out>, signo=6) at ./nptl/pthread_kill.c:78
        #2  0x00007f889b049d02 in __GI_raise (sig=sig@entry=6) at 
../sysdeps/posix/raise.c:26
        #3  0x00007f889b0324f0 in __GI_abort () at ./stdlib/abort.c:79
        #4  0x00007f889aca1a3d in ??? () at /lib/x86_64-linux-gnu/libstdc++.so.6
        #5  0x00007f889acb300a in ??? () at /lib/x86_64-linux-gnu/libstdc++.so.6
        #6  0x00007f889aca15e9 in std::terminate() () at 
/lib/x86_64-linux-gnu/libstdc++.so.6
        #7  0x00007f889acb3288 in __cxa_throw () at 
/lib/x86_64-linux-gnu/libstdc++.so.6
        #8  0x00007f8862346900 in 
SwAccessibleSelectionHelper::throwIndexOutOfBoundsException 
(this=0x561f2f8d1910) at 
.../libreoffice/sw/source/core/access/accselectionhelper.cxx:72
        #9  0x00007f8862347df8 in 
SwAccessibleSelectionHelper::getSelectedAccessibleChild (this=0x561f2f8d1910, 
nSelectedChildIndex=0) at 
.../libreoffice/sw/source/core/access/accselectionhelper.cxx:283
        #10 0x00007f8862298e6f in 
SwAccessibleDocument::getSelectedAccessibleChild (this=0x561f2f8d1800, 
nSelectedChildIndex=0) at .../libreoffice/sw/source/core/access/accdoc.cxx:467
        #11 0x00007f8862298eaf in non-virtual thunk to 
SwAccessibleDocument::getSelectedAccessibleChild(long) () at 
.../libreoffice/sw/source/core/access/accdoc.cxx:467
        #12 0x00007f88878c6200 in QtAccessibleWidget::selectedItem 
(this=0x7f887c014ac0, nSelectionIndex=0) at 
vcl/qt6/../qt5/QtAccessibleWidget.cxx:1861
        #13 0x00007f8885f08ba0 in AtSpiAdaptor::selectionInterface 
(this=0x561f2b8a7070, interface=0x7f887c014ac0, function=..., message=..., 
connection=...)
            at .../qt5/qtbase/src/gui/accessible/linux/atspiadaptor.cpp:2596
        #14 0x00007f8885f03ce1 in AtSpiAdaptor::handleMessage 
(this=0x561f2b8a7070, message=..., connection=...) at 
.../qt5/qtbase/src/gui/accessible/linux/atspiadaptor.cpp:1479
        #15 0x00007f888366d217 in QDBusConnectionPrivate::activateObject 
(this=0x7f887c00a390, node=..., msg=..., pathStartPos=27) at 
.../qt5/qtbase/src/dbus/qdbusintegrator.cpp:1448
        #16 0x00007f888366e1d0 in QDBusActivateObjectEvent::placeMetaCall 
(this=0x7f887c03aca0) at .../qt5/qtbase/src/dbus/qdbusintegrator.cpp:1604
        #17 0x00007f8886b09bb1 in QObject::event (this=0x561f2b8a7070, 
e=0x7f887c03aca0) at .../qt5/qtbase/src/corelib/kernel/qobject.cpp:1431
        #18 0x00007f88849e2dd0 in QApplicationPrivate::notify_helper 
(this=0x561f2a554ae0, receiver=0x561f2b8a7070, e=0x7f887c03aca0) at 
.../qt5/qtbase/src/widgets/kernel/qapplication.cpp:3305
        #19 0x00007f88849e6ced in QApplication::notify (this=0x561f2a541420, 
receiver=0x561f2b8a7070, e=0x7f887c03aca0) at 
.../qt5/qtbase/src/widgets/kernel/qapplication.cpp:3255
        #20 0x00007f8886a481b9 in QCoreApplication::notifyInternal2 
(receiver=0x561f2b8a7070, event=0x7f887c03aca0) at 
.../qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1118
        #21 0x00007f8886a48e29 in QCoreApplication::sendEvent 
(receiver=0x561f2b8a7070, event=0x7f887c03aca0) at 
.../qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1558
        #22 0x00007f8886a49d68 in QCoreApplicationPrivate::sendPostedEvents 
(receiver=0x0, event_type=0, data=0x561f2a56fee0) at 
.../qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1898
        #23 0x00007f8886a48c6c in QCoreApplication::sendPostedEvents 
(receiver=0x0, event_type=0) at 
.../qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1752
        #24 0x00007f88870377b1 in postEventSourceDispatch (s=0x561f2a5cce80) at 
.../qt5/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:246
        #25 0x00007f888d50b81f in ??? () at 
/lib/x86_64-linux-gnu/libglib-2.0.so.0
        #26 0x00007f888d50da57 in ??? () at 
/lib/x86_64-linux-gnu/libglib-2.0.so.0
        #27 0x00007f888d50e1c0 in g_main_context_iteration () at 
/lib/x86_64-linux-gnu/libglib-2.0.so.0
        #28 0x00007f88870369eb in QEventDispatcherGlib::processEvents 
(this=0x561f2a545d00, flags=...) at 
.../qt5/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:399
        #29 0x00007f8886164858 in QPAEventDispatcherGlib::processEvents 
(this=0x561f2a545d00, flags=...) at 
.../qt5/qtbase/src/gui/platform/unix/qeventdispatcher_glib.cpp:89
        #30 0x00007f888796a492 in QtInstance::ImplYield (this=0x561f2a5d16c0, 
bWait=true, bHandleAllCurrentEvents=false) at vcl/qt6/../qt5/QtInstance.cxx:464
        #31 0x00007f888796d511 in QtInstance::DoYield (this=0x561f2a5d16c0, 
bWait=true, bHandleAllCurrentEvents=false) at vcl/qt6/../qt5/QtInstance.cxx:475
        #32 0x00007f88924bd626 in ImplYield (i_bWait=true, i_bAllEvents=false) 
at .../libreoffice/vcl/source/app/svapp.cxx:385
        #33 0x00007f88924bcf3f in Application::Yield () at 
.../libreoffice/vcl/source/app/svapp.cxx:488
        #34 0x00007f88924bcd20 in Application::Execute () at 
.../libreoffice/vcl/source/app/svapp.cxx:360
        #35 0x00007f889b327b89 in desktop::Desktop::Main (this=0x7ffcd9ea1c00) 
at .../libreoffice/desktop/source/app/app.cxx:1679
        #36 0x00007f88924deaa6 in ImplSVMain () at 
.../libreoffice/vcl/source/app/svmain.cxx:230
        #37 0x00007f88924e0699 in SVMain () at 
.../libreoffice/vcl/source/app/svmain.cxx:248
        #38 0x00007f889b3a146a in soffice_main () at 
.../libreoffice/desktop/source/app/sofficemain.cxx:121
        #39 0x0000561ef2802a6d in sal_main () at 
.../libreoffice/desktop/source/app/main.c:51
        #40 0x0000561ef2802a47 in main (argc=2, argv=0x7ffcd9ea1e08) at 
.../libreoffice/desktop/source/app/main.c:49
    
    While QtAccessibleWidget::selectedItem already returns early
    if the passed selection index is too large according to what
    XAccessibleSelection::getSelectedAccessibleChildCount()
    returns, this is not enough because Writer's SwAccessibleSelectionHelper
    has an inconsistent/broken implementation:
    
    SwAccessibleSelectionHelper::getSelectedAccessibleChildCount
    returns the count of paragraphs that are (partially) selected
    by the text cursor if no other objects are selected.
    However, SwAccessibleSelectionHelper::getSelectedAccessibleChild
    doesn't take these into account and therefore throws the
    IndexOutOfBoundsException when called with any index.
    
    Temporarily (in particular for backporting to release branches),
    handle the exception in QtAccessibleWidget::selectedItem like
    other a11y bridges do (see e.g. `selection_ref_selection`
    for the gtk3 VCL plugin) to avoid the crash.
    
    The underlying Writer issue described above will be fixed in a
    separate commit (and for master only).
    
    Change-Id: I874ad4a7a9faf79492967c943517d83df5f47e75
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180228
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/vcl/qt5/QtAccessibleWidget.cxx b/vcl/qt5/QtAccessibleWidget.cxx
index 7438c5e368d1..f7f55f74f82d 100644
--- a/vcl/qt5/QtAccessibleWidget.cxx
+++ b/vcl/qt5/QtAccessibleWidget.cxx
@@ -51,6 +51,7 @@
 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
 #include <com/sun/star/uno/Sequence.hxx>
 
 #include <comphelper/AccessibleImplementationHelper.hxx>
@@ -1858,11 +1859,22 @@ QAccessibleInterface* 
QtAccessibleWidget::selectedItem(int nSelectionIndex) cons
         return nullptr;
     }
 
-    Reference<XAccessible> xChild = 
xSelection->getSelectedAccessibleChild(nSelectionIndex);
-    if (!xChild)
-        return nullptr;
+    try
+    {
+        Reference<XAccessible> xChild = 
xSelection->getSelectedAccessibleChild(nSelectionIndex);
+        if (xChild)
+            return 
QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xChild));
+    }
+    catch (const css::lang::IndexOutOfBoundsException&)
+    {
+        // tdf#163335: temporarily work around inconsistency in
+        // SwAccessibleSelectionHelper::getSelectedAccessibleChildCount
+        // returning a larger number of selected items than
+        // SwAccessibleSelectionHelper::getSelectedAccessibleChild supports
+        SAL_WARN("vcl.qt", "QtAccessibleWidget::selectedItem triggered an 
exception");
+    }
 
-    return 
QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xChild));
+    return nullptr;
 }
 
 bool QtAccessibleWidget::isSelected(QAccessibleInterface* pItem) const

Reply via email to