summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Weghorn <m.weghorn@posteo.de>2022-06-17 17:29:19 +0200
committerMichael Weghorn <m.weghorn@posteo.de>2022-06-17 19:30:29 +0200
commit8c3e8af0e60865ec6d38e2117efdb4ed2f10a20c (patch)
tree7e06c93d2e47ce37683ccfa53fe89b2d82baaff0
parent2e509b886f1d77ef158579385b55f1f94cfbc710 (diff)
qt a11y: Forward STATE_CHANGED event as such
Handle `AccessibleEventId::STATE_CHANGED` by sending a corresponding `QAccessibleStateChangeEvent`. The previous way of sending a `QAccessible::ForegroundChanged` event looked rather arbitrary and had no effect in practice, since that type of event is currently ignored in Qt's AT-SPI adapter anyway. At this point in time, the Qt library doesn't forward changes of all states to the AT-SPI layer. Most notably, it ignores changes to the focused state. (Qt itself uses events of type `QAccessible::Focus` instead of `QAccessibleStateChangeEvent` with the `focused` state set to notify about focus changes, but that's not exactly the same, and e.g. causes Orca to ignore some focus changes). I have submitted a change to Qt to implement forwarding of `QAccessibleStateChangeEvent`s for the focused state to the AT-SPI layer, currently awaiting review. [1] With that Qt change in place, Orca still ignored these events in LibreOffice message dialogs, since those use a11y role `ALERT`, which wasn't previously considered when trying to retrieve a potential dialog that an a11y object belonged to. The corresponding Orca merge request [2] has just been merged. With these two in place, Orca now announces the focused button when switching focus using the tab key e.g. in the "Save document?" dialog when using the qt6 VCL plugin. (Most other things in the LO UI are still usually not announced.) For some reason, forwarding changes to state `AccessibleStateType::ACTIVE` resulted in Orca becoming unresponsive (stop talking) quite quickly. That needs further analysis, so that state change isn't forwarded to Qt for now. [1] https://codereview.qt-project.org/c/qt/qtbase/+/416510 [2] https://gitlab.gnome.org/GNOME/orca/-/merge_requests/127 Change-Id: I81c9a0f5ec8c74f95943d3073bba5b304f995d31 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136057 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
-rw-r--r--vcl/inc/qt5/QtAccessibleEventListener.hxx3
-rw-r--r--vcl/qt5/QtAccessibleEventListener.cxx115
2 files changed, 116 insertions, 2 deletions
diff --git a/vcl/inc/qt5/QtAccessibleEventListener.hxx b/vcl/inc/qt5/QtAccessibleEventListener.hxx
index a73f6d31f2f8..1103dc9da598 100644
--- a/vcl/inc/qt5/QtAccessibleEventListener.hxx
+++ b/vcl/inc/qt5/QtAccessibleEventListener.hxx
@@ -33,6 +33,9 @@ public:
private:
css::uno::Reference<css::accessibility::XAccessible> m_xAccessible;
QtAccessibleWidget* m_pAccessibleWidget;
+
+ static void HandleStateChangedEvent(QAccessibleInterface* pQAccessibleInterface,
+ const css::accessibility::AccessibleEventObject& rEvent);
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/QtAccessibleEventListener.cxx b/vcl/qt5/QtAccessibleEventListener.cxx
index 515584351c74..ee9acc651599 100644
--- a/vcl/qt5/QtAccessibleEventListener.cxx
+++ b/vcl/qt5/QtAccessibleEventListener.cxx
@@ -23,6 +23,7 @@
#include <sal/log.hxx>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
#include <com/sun/star/accessibility/TextSegment.hpp>
@@ -41,6 +42,117 @@ QtAccessibleEventListener::QtAccessibleEventListener(const Reference<XAccessible
{
}
+void QtAccessibleEventListener::HandleStateChangedEvent(
+ QAccessibleInterface* pQAccessibleInterface,
+ const css::accessibility::AccessibleEventObject& rEvent)
+{
+ QAccessible::State aState;
+
+ short nState = 0;
+ rEvent.NewValue >>= nState;
+ // States in 'QAccessibleStateChangeEvent' indicate what states have changed, so if e.g.
+ // an object loses focus (not just if it gains it), 'focus' state needs to be set to 'true',
+ // so retrieve the old/previous value from the event if necessary.
+ if (nState == AccessibleStateType::INVALID)
+ rEvent.OldValue >>= nState;
+
+ switch (nState)
+ {
+ case AccessibleStateType::ACTIVE:
+ // ignore for now, since it somehow causes Orca to become unresponsive quite quickly
+ // TODO: analyze further and fix root cause
+ /*
+ aState.active = true;
+ break;
+ */
+ return;
+ case AccessibleStateType::BUSY:
+ aState.busy = true;
+ break;
+ case AccessibleStateType::CHECKED:
+ aState.checked = true;
+ break;
+ case AccessibleStateType::COLLAPSE:
+ aState.collapsed = true;
+ break;
+ case AccessibleStateType::DEFAULT:
+ aState.defaultButton = true;
+ break;
+ case AccessibleStateType::ENABLED:
+ aState.disabled = true;
+ break;
+ case AccessibleStateType::EDITABLE:
+ aState.editable = true;
+ break;
+ case AccessibleStateType::EXPANDABLE:
+ aState.expandable = true;
+ break;
+ case AccessibleStateType::EXPANDED:
+ aState.expanded = true;
+ break;
+ case AccessibleStateType::FOCUSABLE:
+ aState.focusable = true;
+ break;
+ case AccessibleStateType::FOCUSED:
+ aState.focused = true;
+ break;
+ case AccessibleStateType::INVALID:
+ aState.invalid = true;
+ break;
+ case AccessibleStateType::VISIBLE:
+ aState.invisible = true;
+ break;
+ case AccessibleStateType::MODAL:
+ aState.modal = true;
+ break;
+ case AccessibleStateType::MOVEABLE:
+ aState.movable = true;
+ break;
+ case AccessibleStateType::MULTI_LINE:
+ // comment in Qt's qaccessible.h has this:
+ // "// quint64 singleLine : 1; // we have multi line, this is redundant."
+ case AccessibleStateType::SINGLE_LINE:
+ aState.multiLine = true;
+ break;
+ case AccessibleStateType::MULTI_SELECTABLE:
+ aState.multiSelectable = true;
+ break;
+ case AccessibleStateType::OFFSCREEN:
+ aState.offscreen = true;
+ break;
+ case AccessibleStateType::PRESSED:
+ aState.pressed = true;
+ break;
+ case AccessibleStateType::RESIZABLE:
+ aState.sizeable = true;
+ break;
+ case AccessibleStateType::SELECTABLE:
+ aState.selectable = true;
+ break;
+ case AccessibleStateType::SELECTED:
+ aState.selected = true;
+ break;
+ // These don't seem to have a matching Qt equivalent
+ case AccessibleStateType::ARMED:
+ case AccessibleStateType::DEFUNC:
+ case AccessibleStateType::HORIZONTAL:
+ case AccessibleStateType::ICONIFIED:
+ case AccessibleStateType::INDETERMINATE:
+ case AccessibleStateType::MANAGES_DESCENDANTS:
+ case AccessibleStateType::OPAQUE:
+ case AccessibleStateType::SENSITIVE:
+ case AccessibleStateType::SHOWING:
+ case AccessibleStateType::STALE:
+ case AccessibleStateType::TRANSIENT:
+ case AccessibleStateType::VERTICAL:
+ default:
+ return;
+ }
+
+ QAccessible::updateAccessibility(
+ new QAccessibleStateChangeEvent(pQAccessibleInterface, aState));
+}
+
void QtAccessibleEventListener::notifyEvent(const css::accessibility::AccessibleEventObject& aEvent)
{
QAccessibleInterface* pQAccessibleInterface = m_pAccessibleWidget;
@@ -211,8 +323,7 @@ void QtAccessibleEventListener::notifyEvent(const css::accessibility::Accessible
new QAccessibleEvent(pQAccessibleInterface, QAccessible::LocationChanged));
return;
case AccessibleEventId::STATE_CHANGED:
- QAccessible::updateAccessibility(
- new QAccessibleEvent(pQAccessibleInterface, QAccessible::ForegroundChanged));
+ HandleStateChangedEvent(pQAccessibleInterface, aEvent);
return;
case AccessibleEventId::VALUE_CHANGED:
{