(?source)
Requests from the screen reader
The Orca screen reader can explicitly request for information for a given widget of a given application, for instance getText:
- Orca calls pyatspi's
getTextmethod on a pyatspi object corresponding to the widget - pyatspi's
getTextmethod (implemented inpyatspi/pyatspi/text.py) callsAtspi.Text.get_text, which is a python binding for the Catspi_text_get_textfunction fromlibatspi.soprovided by at-spi2-core atspi_text_get_text(implemented inat-spi2-core/atspi/atspi-text.c) creates an RPC message for the dbus sender of the application and the path for the widget, using theorg.a11y.atspi.Textdbus interface, and theGetTextmethod.
dbus transmits the message to the application.
In the case of a GTK2/3 application:
impl_GetText(implemented inat-spi2-atk/atk-adaptor/adaptors/text-adaptor.c) gets called by dbus, it parses the parameters (offsets of beginning and end), and callsatk_text_get_textatk_text_get_text(implemented inatk1.0/./atk/atktext.c) calls theget_textmethod of the accessible object corresponding to the widget, for instance a textcell.gail_text_cell_get_text(implemented in the gail module of gtk,gtk+2.0/modules/other/gail/gailtextcell.corgtk_text_cell_accessible_get_textingtk+3.0/gtk/a11y/gtktextcellaccessible.c) fetches the text from the widget corresponding to the accessible object and returns itatk_text_get_textreturns itimpl_GetTextstuffes the string into a dbus response
TODO: In the case of a GTK4 application
In the case of a Java application:
impl_GetTextandatk_text_get_textget called like for a GTK application, theget_textmethod isjaw_text_get_textjaw_text_get_text(implemented injava-atk-wrapper/jni/src/jawtext.c) calls theget_textmethod of theAtkTextjava classget_text(implemented injava-atk-wrapper/wrapper/org/GNOME/Accessibility/AtkText.java) uses thegetAtIndexmethod of theAccessibleExtendedTextinterface of the widget and returns the text.atk_text_get_textreturns itimpl_GetTextstuffes the string into a dbus response
In the case of mozilla:
impl_GetTextandatk_text_get_textget called like for a GTK application, theget_textmethod isgetTextCBgetTextCB(implemented inmozilla/accessible/atk/nsMaiInterfaceText.cpp) uses theTextSubstringof theHyperTextAccessibleclass.
In the case of a Qt4 application:
AtSpiAdaptor::textInterface(implemented inqt-at-spi/src/atspiadaptor.cpp) gets called by qt dbus, it parses the parameters, and calls thetextmethod of thetextInterfaceof theQAccessibleInterfaceclass.QAccessibleTextWidget::text(implemented inqt4-x11/src/plugins/accessible/widgets/qaccessiblewidgets.cpp) fetches the text and returns it.AtSpiAdaptor::textInterfacestuffes the string into a dbus response.
In the case of a Qt5 application:
AtSpiAdaptor::textInterface(implemented in qtbase/src/platformsupport/linuxaccessibility/atspiadaptor.cpp`) gets called by qt dbus, the rest is happening as with Qt4.
dbus transmits the response to the application.
atspi_text_get_textgets the string from the response and returns it
Notifications from the application
The application can notify about e.g. an insertion of text in a widget. The Orca screen reader must first register for getting the event, before the toolkit will only send events if there are listeners for them:
- The default
getListenersmethod (implemented inorca/src/orca/scripts/default.py) returns to callonTextInsertedonobject:text-changed:insertsignal registerScriptListeners(implemented inorca/src/orca/event_manager.py) calls_registerListenerto record a callback to_enqueueon that signal_registerListenercallsregistry.registerEventListenerfor this.registerEventListener(implemented inpython-atspi/pyatspi/registry.py) callsAtspi.EventListener.register, which is a Python binding for the Catspi_event_listener_registerfunction.atspi_event_listener_register(implemented inat-spi2-core/atspi/atspi-event-listener.c) usesdbus_bus_add_matchon"org.a11y.atspi.Event"to make dbus make the_enqueuecallback when the event is received. It also makes an RPC to the at-spi-registryd (conventional dbus name"org.a11y.atspi.Registry"), on the"/org/a11y/atspi/registry"path, the"org.a11y.atspi.Registry"interface,RegisterEventmethod, to tell the registry to start notifying Orca about these events.
dbus transmits the RPC to at-spi2-registryd.
impl_register_event(implemented inat-spi2-core/registryd/registry.c) parses the request, records the registration in theregistry->eventslist, and sends aEventListenerRegisteredsignal on the bus
In the case of a GTK2/3 application (quite unsure about the details):
- When receiving the
EventListenerRegisteredsignal insignal_filter(implemented inat-spi2-atk/atk-adaptor/bridge.c),handle_event_listener_registeredis called handle_event_listener_registeredadds the event listening registration to theeventslist.The Atk adaptor has added in
spi_atk_register_event_listeners(implemented inat-spi2-atk/atk-adaptor/event.c)text_changed_event_listeneras listener for signals"Gtk:AtkText:text-insert"and"Gtk:AtkText:text-changed"- Atk has added in
atk_text_base_init(implemented inatk1.0/atk/atktext.c) the"text-insert"signal. Gail has added
gail_text_cell_update_cacheas update_cache callbackTODO textcell to
text_insertsignalgail_text_cell_update_cache(implemented ingtk+2.0/modules/other/gail/gailtextcell.corgtk_text_cell_accessible_update_cacheingtk+3.0/gtk/a11y/gtktextcellaccessible.c) emits the"text_changed::insert"glib signal.text_changed_event_listener(implemented inat-spi2-atk/atk-adaptor/event.c) callsemit_eventemit_eventcheckssignal_is_neededbefore emitting thetext-changed:insertevent on the bus.signal_is_neededchecks whether the signal is in theeventslist.
TODO: In the case of a GTK4 application
TODO: In the case of a Qt application
TODO: In the case of a Java application
jaw_impl_class_init sets jaw_impl_initialize as initializer for atk class
when receiving events about a yet-unseen object, jaw_impl_get_instance calls atk_object_initialize
- atk_object_initialize calls the atk class initializer, jaw_impl_initialize
- jaw_impl_initialize calls org.GNOME.Accessibility.AtkWrapper::registerPropertyChangeListener
registerPropertyChangeListener calls AccessibleContext::addPropertyChangeListener to register propertyChangeListener to beans
AtkWrapper.java's propertyChangeListener's propertyChange get called, calls org.GNOME.Accessibility.AtkWrapper::dispatchFocusEvent.
- dispatchFocusEvent calls focusNotify (implemented in C function Java_org_GNOME_Accessibility_AtkWrapper_focusNotify)
- Java_org_GNOME_Accessibility_AtkWrapper_focusNotify uses jni_main_idle_add or gdk_threads_add_idle to record having to call focus_notify_handler later.
- The glib loop calls focus_notify_handler.
- focus_notify_handler calls atk_object_notify_state_change
- atk_object_notify_state_change emits the signal
- The rest is like gtk
TODO: In the case of mozilla
dbus transmits the event on the bus.
- In Orca, the dbus filter calls
_enqueue _enqueue(implemented inorca/src/orca/event_manager.py) calls_addToQueue_addToQueuequeues an event- glib idle loop calls
_dequeue. _dequeuedequeues an event and calls_processObjectEvent_processObjectEventcallsprocessObjectEventprocessObjectEvent(implemented inorca/src/orca/script.py) calls the listener forobject:text-changed:insert.onTextInserted(implemented inorca/src/orca/scripts/default.pyfor instance) updates the user output.
Startup
In the case of a GTK application:
TODO
In the case of a java application:
The javax.accessibility.assistive_technologies system property, or assistive_technologies file property contains the name of the class to load. It is loaded by loadAssistiveTechnologies, called from getDefaultToolkit in src/jdk/src/share/classes/java/awt/Toolkit.java
In the case of a mozilla application:
TODO
In the case of a QT4 application:
TODO
In the case of a QT5 application:
TODO
