diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2025-01-14 11:32:25 +0100 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2025-01-14 15:24:32 +0100 |
commit | 3eaa35e8bacc19a85f5c9d907450846bfa8bffae (patch) | |
tree | 7fc39e6d5cc04d8d76af786c3fe8b2dbe17a4657 | |
parent | 91a97c7d11d77935ff459679ddcacd59014771d2 (diff) |
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.weghorn@posteo.de>
-rw-r--r-- | vcl/qt5/QtAccessibleWidget.cxx | 20 |
1 files changed, 16 insertions, 4 deletions
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 |