Accessibility/qt-atspi: Difference between revisions
Try to breathe new life into old information |
|||
(19 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{Note|This page has old content. See page history.}} | |||
= Qt AT-SPI 2 Bridge = | = Qt AT-SPI 2 Bridge = | ||
The '''Qt AT-SPI 2 bridge''' ([[wikipedia:Assistive Technology Service Provider Interface|Assistive Technology Service Provider Interface]]) is a [https://wiki.qt.io/Qt_Accessibility Qt Accessibility] plugin that exposes the internals of a Qt application to accessibility clients such as screen readers. | |||
== | == Source code == | ||
[ | The source code for the bridge is [https://invent.kde.org/unmaintained/qtatspi archived on KDE Invent] following the closure of the original Gitorious repository<ref name="gitorious">Formerly accessible at <code>git://gitorious.org/qt-at-spi.git</code>.</ref> by the Qt developers in 2016. | ||
== | == Tools == | ||
Thanks to the efforts of the GNOME Project to implement their AT-SPI 2 implementation (named ATK, the [[wikipedia:Accessibility Toolkit|'''A'''ccessibility '''T'''ool'''K'''it]]), we have some really helpful tools for further development in this area: | |||
* [https://help.gnome.org/users/accerciser/stable/index.html.en Accerciser], an interactive accessibility explorer written in Python. | |||
* [https://orca.gnome.org Orca], an extensible screen reader that converts textual content into speech and/or braille. | |||
* [https://webstats.gnome.org/Accessibility/PythonPoweredAccessibility#Code_example "Python-powered" Accessibility] code example. | |||
[[File:Accessibility - a11y.png|thumb|right|x152px|link=Category:Accessibility|illustration of the numeronym ''a11y'', where eleven refers to the number of letters omitted]] | |||
=== Testing/Development === | |||
Development of these components requires a very recent environment, most notably to include: | |||
* [https://gitlab.gnome.org/GNOME/at-spi2-core at-spi2-core], | |||
* [https://gitlab.gnome.org/Archive/at-spi2-atk at-spi2-atk], and | |||
* [https://gitlab.gnome.org/GNOME/pyatspi2 pyatspi2] | |||
Inside a GNOME session, the [[wikipedia:Computer accessibility|accessibility software]] and other [[wikipedia:Assistive technology|assistive technology]] (often referred to by the numeronym '''''a11y''''') use a dedicated D-Bus, so if you want to monitor what is going on you should use a tool like [https://dbus.freedesktop.org/doc/dbus-monitor.1.html dbus-monitor]: | |||
<syntaxhighlight lang="shell" highlight="1"> | |||
dbus-monitor --address $(xprop -root | grep AT_SPI_BUS | sed -e 's/.*= "//' -e 's/"$//') | |||
</syntaxhighlight> | |||
== To do == | |||
''Complex widgets with children? Tabs … clicking on a file in qgit … (crash fix committed, but still needs proper fix)'' | |||
[https://invent.kde.org/unmaintained/qtatspi/-/blob/15ab90659dbbbf81bedfd26a5b9656e08bdbe732/src/atspiadaptor.cpp#L206 <code>GetApplicationBusAddress</code>] seems to be [https://invent.kde.org/unmaintained/qtatspi/-/blob/535816e1176eda0a7e1e79f6b9d9734b66c7b149/xml/Application.xml#L17 undefined in the XML], but is actually called | |||
mgorse[''sic, ??''], that ought to be defined somewhere. It is used to try to set up a direct D-Bus connection between libatspi and the application. libatspi will revert to using the session bus if it returns an empty string or an error. | |||
* [[File:Checkbox blue unchecked.png|17px|link=]] Don't pretend to be [https://gitlab.gnome.org/Archive/gail gail], instead coordinate with the Orca developers | |||
* [[File:Checkbox blue unchecked.png|17px|link=]] Test apps with multiple windows | |||
* [[File:Checkbox blue unchecked.png|17px|link=]] Fix action for menus inside Qt | |||
* [[File:Checkbox blue unchecked.png|17px|link=]] Scroll bars have a value interface, but don't update and cannot be updated, value interface in general… | |||
* [[File:Checkbox blue unchecked.png|17px|link=]] Text attributes (bold, etc.) | |||
* [[File:Checkbox blue unchecked.png|17px|link=]] Tabs | |||
=== Widgets === | |||
<div style="columns: 3; padding-left: 10em;"> | |||
* Combobox | |||
* List | |||
* Tree | |||
* Table | |||
* Spinner | |||
* Scrollbar | |||
</div> | |||
=== === | |||
{| class="wikitable" style="margin: 1em auto 1.5em; min-width: 28vw;" | |||
|+ '''<big>KDE Widgets</big>''' | |||
! style="min-width: 13em;" | Widget | |||
! Status | |||
|- | |||
| style="font-weight: 500; text-align: center;" | ExampleWidget1 | |||
| style="padding-left: 2em;" | Ready. | |||
|- | |||
| style="font-weight: 500; text-align: center;" | ExampleWidget2 | |||
| style="padding-left: 2em;" | Mostly done, still needs fooBar() call. | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKCharSelect.html KCharSelect] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKColorButton.html KColorButton] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | KColorCombo | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | KComboBox | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/4.14-api/kdelibs-apidocs/kdeui/html/classKCModule.html KCModule] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | KDateWidget | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | KDatePicker | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://develop.kde.org/docs/administration/kdialog/ KDialog] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/2.1-api/classref/kdeui/KEditListBox.html KEditListBox] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/pykde-4.5-api/kdeui/KComboBox.html KFontComboBox] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKFontChooser.html KFontChooser] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKFontRequester.html KFontRequester] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/4.12-api/kdelibs-apidocs/kdeui/html/classKGradientSelector.html KGradientSelector] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kcompletion/html/classKHistoryComboBox.html KHistoryComboBox] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/4.12-api/kdelibs-apidocs/kdeui/html/classKHueSaturationSelector.html KHueSaturationSelector] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/pykde-4.7-api/khtml/index.html KHtmlView] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKLed.html KLed] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/4.14-api/kdelibs-apidocs/kdeui/html/dir_000011_000013.html KListWidget] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kcompletion/html/classKLineEdit.html KLineEdit] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/4.14-api/kdelibs-apidocs/kdeui/html/kpushbutton_8cpp_source.html KPushButton] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/3.5-api/kdelibs-apidocs/kdeui/html/classKRestrictedLine.html KRestrictedLine] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/pykde-4.7-api/kdeui/KIntSpinBox.html KIntSpinBox] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKRuler.html KRuler] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKSqueezedTextLabel.html KSqueezedTextLabel] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/3.5-api/kdelibs-apidocs/kdeui/html/classKTextBrowser.html KTextBrowser] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/ktextwidgets/html/classKTextEdit.html KTextEdit] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKUrlLabel.html KURLLabel] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/pykde-4.5-api/kio/KUrlComboRequester.html KURLComboRequester] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kio/html/classKUrlRequester.html KURLRequester] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/pykde-4.5-api/kdeui/KIntNumInput.html KIntNumInput] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/3.5-api/kdelibs-apidocs/kdeui/html/classKDoubleNumInput.html KDoubleNumInput] || style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/4.12-api/kdelibs-apidocs/kdeui/html/classKDateTimeWidget.html KDateTimeWidget] | |||
| style="padding-left: 2em;" | Unknown | |||
|- | |||
| style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/3.5-api/kdelibs-apidocs/kdeui/html/classKDateTable.html KDateTable] | |||
| style="padding-left: 2em;" | Unknown | |||
|} | |||
=== Memory Management === | |||
Qt's current [https://doc.qt.io/qt-6/qaccessibleinterface.html QAccessibleInterface] is a pain to deal with. | |||
# We can only (safely?) hold on to interfaces created by navigate or queryInterface. | |||
# Interfaces that we get through notifyAccessibility are deleted by Qt behind our back, so we need to never keep those around (Frederik will try to fix that now). | |||
== References == | |||
<references /> | |||
== External links == | |||
* [[techbase:Development/Tutorials/Accessibility|'''KDE Accessibility''' tutorial]] on Techbase | |||
* [https://www.freedesktop.org/wiki/Accessibility/AT-SPI2/ '''AT-SPI2'''] on Freedesktop.org Wiki | |||
* [https://wiki.linuxfoundation.org/accessibility/atk/at-spi/start Linux Foundation's ATK/AT-SPI Special Interest Group] | |||
** [https://wiki.linuxfoundation.org/accessibility/atk/at-spi/at-spi_on_d-bus '''AT-SPI on D-Bus'''] <small>(last updated on {{#formatdate:2011-06-01|mdy}})</small> | |||
[[Category:Accessibility|Qt AT-SPI 2 Bridge]] |
Latest revision as of 06:42, 3 August 2024
Qt AT-SPI 2 Bridge
The Qt AT-SPI 2 bridge (Assistive Technology Service Provider Interface) is a Qt Accessibility plugin that exposes the internals of a Qt application to accessibility clients such as screen readers.
Source code
The source code for the bridge is archived on KDE Invent following the closure of the original Gitorious repository[1] by the Qt developers in 2016.
Tools
Thanks to the efforts of the GNOME Project to implement their AT-SPI 2 implementation (named ATK, the Accessibility ToolKit), we have some really helpful tools for further development in this area:
- Accerciser, an interactive accessibility explorer written in Python.
- Orca, an extensible screen reader that converts textual content into speech and/or braille.
- "Python-powered" Accessibility code example.
![](/images.community/thumb/b/bd/Accessibility_-_a11y.png/322px-Accessibility_-_a11y.png)
Testing/Development
Development of these components requires a very recent environment, most notably to include:
- at-spi2-core,
- at-spi2-atk, and
- pyatspi2
Inside a GNOME session, the accessibility software and other assistive technology (often referred to by the numeronym a11y) use a dedicated D-Bus, so if you want to monitor what is going on you should use a tool like dbus-monitor:
dbus-monitor --address $(xprop -root | grep AT_SPI_BUS | sed -e 's/.*= "//' -e 's/"$//')
To do
Complex widgets with children? Tabs … clicking on a file in qgit … (crash fix committed, but still needs proper fix)
GetApplicationBusAddress
seems to be undefined in the XML, but is actually called
mgorse[sic, ??], that ought to be defined somewhere. It is used to try to set up a direct D-Bus connection between libatspi and the application. libatspi will revert to using the session bus if it returns an empty string or an error.
Don't pretend to be gail, instead coordinate with the Orca developers
Test apps with multiple windows
Fix action for menus inside Qt
Scroll bars have a value interface, but don't update and cannot be updated, value interface in general…
Text attributes (bold, etc.)
Tabs
Widgets
- Combobox
- List
- Tree
- Table
- Spinner
- Scrollbar
Widget | Status |
---|---|
ExampleWidget1 | Ready. |
ExampleWidget2 | Mostly done, still needs fooBar() call. |
KCharSelect | Unknown |
KColorButton | Unknown |
KColorCombo | Unknown |
KComboBox | Unknown |
KCModule | Unknown |
KDateWidget | Unknown |
KDatePicker | Unknown |
KDialog | Unknown |
KEditListBox | Unknown |
KFontComboBox | Unknown |
KFontChooser | Unknown |
KFontRequester | Unknown |
KGradientSelector | Unknown |
KHistoryComboBox | Unknown |
KHueSaturationSelector | Unknown |
KHtmlView | Unknown |
KLed | Unknown |
KListWidget | Unknown |
KLineEdit | Unknown |
KPushButton | Unknown |
KRestrictedLine | Unknown |
KIntSpinBox | Unknown |
KRuler | Unknown |
KSqueezedTextLabel | Unknown |
KTextBrowser | Unknown |
KTextEdit | Unknown |
KURLLabel | Unknown |
KURLComboRequester | Unknown |
KURLRequester | Unknown |
KIntNumInput | Unknown |
KDoubleNumInput | Unknown |
KDateTimeWidget | Unknown |
KDateTable | Unknown |
Memory Management
Qt's current QAccessibleInterface is a pain to deal with.
- We can only (safely?) hold on to interfaces created by navigate or queryInterface.
- Interfaces that we get through notifyAccessibility are deleted by Qt behind our back, so we need to never keep those around (Frederik will try to fix that now).
References
- ↑ Formerly accessible at
git://gitorious.org/qt-at-spi.git
.
External links
- KDE Accessibility tutorial on Techbase
- AT-SPI2 on Freedesktop.org Wiki
- Linux Foundation's ATK/AT-SPI Special Interest Group
- AT-SPI on D-Bus (last updated on June 1, 2011)