Accessibility/qt-atspi: Difference between revisions
(Old content) |
(Try to breathe new life into old information) |
||
Line 1: | Line 1: | ||
{{Note|This page has old content. See page history.}} | {{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. | |||
[ | |||
[https://webstats.gnome.org/Accessibility/PythonPoweredAccessibility#Code_example Python] | == 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 === | === 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 | 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]: | ||
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)'' | |||
GetApplicationBusAddress seems | [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 | 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 | ||
* Test apps with | * [[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 === | === Widgets === | ||
<div style="columns: 3; padding-left: 10em;"> | |||
* Combobox | * Combobox | ||
* List | * List | ||
Line 53: | Line 46: | ||
* Spinner | * Spinner | ||
* Scrollbar | * Scrollbar | ||
</div> | |||
=== | === === | ||
{| | {| class="wikitable" style="margin: 1em auto 1.5em; min-width: 28vw;" | ||
|''' | |+ '''<big>KDE Widgets</big>''' | ||
| | ! style="min-width: 13em;" | Widget | ||
|- | ! Status | ||
|ExampleWidget1 | |- | ||
|Ready. | | style="font-weight: 500; text-align: center;" | ExampleWidget1 | ||
|- | | style="padding-left: 2em;" | Ready. | ||
|ExampleWidget2 | |- | ||
|Mostly done, still needs fooBar() call. | | style="font-weight: 500; text-align: center;" | ExampleWidget2 | ||
|- | | style="padding-left: 2em;" | Mostly done, still needs fooBar() call. | ||
|KCharSelect | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKCharSelect.html KCharSelect] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KColorButton | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKColorButton.html KColorButton] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KColorCombo | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | KColorCombo | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KComboBox | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | KComboBox | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KCModule | |- | ||
|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 | ||
|KDateWidget | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | KDateWidget | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KDatePicker | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | KDatePicker | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KDialog | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://develop.kde.org/docs/administration/kdialog/ KDialog] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KEditListBox | |- | ||
|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 | ||
|KFontComboBox | |- | ||
|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 | ||
|KFontChooser | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKFontChooser.html KFontChooser] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KFontRequester | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKFontRequester.html KFontRequester] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KGradientSelector | |- | ||
|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 | ||
|KHistoryComboBox | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kcompletion/html/classKHistoryComboBox.html KHistoryComboBox] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KHueSaturationSelector | |- | ||
|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 | ||
|KHtmlView | |- | ||
|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 | ||
|KLed | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKLed.html KLed] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KListWidget | |- | ||
|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 | ||
|KLineEdit | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kcompletion/html/classKLineEdit.html KLineEdit] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KPushButton | |- | ||
|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 | ||
|KRestrictedLine | |- | ||
|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 | ||
|KIntSpinBox | |- | ||
|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 | ||
|KRuler | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKRuler.html KRuler] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KSqueezedTextLabel | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKSqueezedTextLabel.html KSqueezedTextLabel] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KTextBrowser | |- | ||
|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 | ||
|KTextEdit | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/ktextwidgets/html/classKTextEdit.html KTextEdit] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KURLLabel | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kwidgetsaddons/html/classKUrlLabel.html KURLLabel] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KURLComboRequester | |- | ||
|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 | ||
|KURLRequester | |- | ||
|Unknown | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/frameworks/kio/html/classKUrlRequester.html KURLRequester] | ||
|- | | style="padding-left: 2em;" | Unknown | ||
|KIntNumInput | |- | ||
|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 | ||
|KDoubleNumInput | |- | ||
|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 | ||
|- | |- | ||
|KDateTimeWidget | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/4.12-api/kdelibs-apidocs/kdeui/html/classKDateTimeWidget.html KDateTimeWidget] | ||
|Unknown | | style="padding-left: 2em;" | Unknown | ||
|- | |- | ||
|KDateTable | | style="font-weight: 500; text-align: center;" | [https://api.kde.org/legacy/3.5-api/kdelibs-apidocs/kdeui/html/classKDateTable.html KDateTable] | ||
|Unknown | | style="padding-left: 2em;" | Unknown | ||
|} | |} | ||
=== Memory Management === | === Memory Management === | ||
Qt's current QAccessibleInterface is a pain to deal with. | 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.
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)