GtkAtSpiRoot is not a context, which means it needs to emit
ChildrenChanged events by itself whenever a toplevel is added to, or
removed from, the list of toplevels.
The stack page objects were not properly integrated
in the accessible tree - they were appearing as parent
of the pages when navigating up, but not as children
of the stack when navigating down.
The ARIA spec determines the name and description of accessible elements
in a more complex way that simply mapping to a single property; instead,
it will chain up multiple definitions (if it finds them). For instance,
let's assume we have a button that saves a file selected from a file
selection widget; the widgets have the following attributes:
- the file selection widget has a "label" attribute set to the
selected file, e.g. "Final paper.pdf"
- the "download" button has a "label" attribute set to the
"Download" string
- the "download" button has a "labelled-by" attribute set to
reference the file selection widget
The ARIA spec says that the accessible name of the "Download" button
should be computed as "Download Final paper.pdf".
The algorithm defined in section 4.3 of the WAI-ARIA specification
applies to both accessible names (using the "label" and "labelled-by"
attributes), and to accessible descriptions (using the "description" and
"described-by" attributes).
Our Text implementation requires that we have
a GtkEditable with a delegate that is a GtkText
widget.
This change make the Text implementation work for
the custom widget in the tagged entry demo.
Implement the non-questionable parts of the Component interface
for accessibles which are widgets.
This does not include:
- global coordinates
- setters
- scrolling
- alpha, layers, zorder, and the like
We only want to show relevant, local actions for
widgets, but _gtk_widget_get_action_muxer() will
return the muxer of a parent widget (all the way
up to the toplevel), if the widget does not have
any actions of its own. To detect this situation,
compare what _gtk_widget_get_action_muxer() returns
for the parent widget, and act accordingly.
The Selection interface is defined in terms of child
positions, so we need to always translate from that
to model positions if we want to use the selection
model apis.
This implementation works for both GtkListView and
GtkGridView, and by extension, also for GtkColumnView
and GtkDropDown, since those just use a list view
internally.
This is a bit different from the way things were done
in GTK 3 - we follow what was done for GtkStackSwitcher,
and make the tab bar carry the GTK_ACCESSIBLE_TAB_LIST
role, and implement Selection there.
This requires some cleanup to remove assumptions
about accessibles being widgets in the backend,
and some code to navigate the tree with these
extra objects in between widgets.
The accessibles for stack pages have the role
GTK_ACCESSIBLE_ROLE_TAB_PANEL. This is the first
step towards implementing the tabs patterns
as described in the aria authoring guidelines
for GtkStack.
Non need to announce the same things for every context
we create, and the path is not really that interesting.
without knowing what it belongs to. I would suggest to
make it visible in the inspector instead, so you can
look it up for the widgets you are interested in.
We use to set the the 'password text' role for entries with
visibility = FALSE. Nowadays, we have a separate class for
password entries, so fix up the role mapping based on that.
Make text change notification work for editables, by connecting
to the ::insert-text and ::delete-text signals on the wrapped
GtkText widget, and for GtkTextView by connecting to the
corresponding GtkTextBuffer signals.
This code is more or less directly copied from GtkTextViewAccessible
and GtkEntryAccessible in GTK 3.
We are determining editable state based on the
accessible role (although we could make it platform
state now), so cover all the roles that we use for
entry wrappers.
Add an enum for 'platform changes' to the at context
change notification mechanism. This will let us pass
along things that ARIA considers 'platform state' such
as focus or editability. The difference between the
platform state and other ARIA states is that we don't
keep the platform state separately in the at context
- backends are expected to just query the widgets.
This is just about avoiding notify listeners for
change notification.
We can use the read-only property, together with the
accessible role, to determine whether to set editable
and read-only states for at-spi. This lets us avoid
directly poking at the widgets.
ATs look at not just the implemented interfaces, but
also the states to decide what to do. It turns out that
the EditableText interface is only used by accerciser
if the editable state is set. So set it.
It is error prone to keep the same conditions in sync
in two places. Instead, just assemble the list of interfaces
as we register objects, and use when GetInterfaces is called.
Apply the Value implementation to the widgets where
we had one in GTK 3: GtkLevelBar, GtkRange, GtkScaleButton,
GtkSpinButton, GtkPaned, GtkProgressBar. To make these
work, the widgets need to set the accessible value properties.
There is some open question here whether the interface
should be implemented on the outer or the inner widget
of the entry-text pairs. For now, our hand is forced,
since only GtkText provides access to the layout that
we need for implementing many of the interface methods.
This is a not-quite-complete implementation of the
Text interface for GtkLabel. The missing parts are
anything around extents and positions, as well as
the ScrollSubstring apis.
This translates relations as far as the match.
I'm not sure yet what we can do about the fact that
atspi expects relations to be bidirectional (ie have
label-for *and* labelled-by) while aria has only one
direction.
It turns out that accerciser depends on this undocumented
method that is not in the xml at all, otherwise interface
sections in the accerciser ui never get enabled.
When we create the first AT-SPI context we also need to register the
accessible root on the accessibility bus. The accessible root object is
the main entry point of an accessible application, and it holds the
global state to present to the ATs that connect to the bus.
Since we need to check at run time what kind of AT context to use, we
need a hook into the whole GDK backend machinery. The display connection
seems to be the best choice, in this case, as it allows us to determine
whether we're running on an X11 or Wayland system, and thus whether we
should create a GtkAtSpiContext.
This requires some surgery to fix the GtkATContext creation function, in
order to include a GdkDisplay instance.
Does not do anything, at the moment, but it's going to get filled out
soon.
The backend is selected depending on the platform being compiled in;
since we're using AT-SPI on X11 and Wayland, and we don't have other
accessibility implementations, we currently don't care about run time
selection, but we're going to have to deal with that.
And generate the code for the DBus interfaces.
We don't want the full object manager experience, here, because we're
going to have a single object responding to various interfaces and
remote method calls. For this reason, we're not using the gnome module
in Meson to call gdbus-codegen for us: we need to use the interface info
command line arguments, and those are not available from Meson.
To build a better world sometimes means having to tear the old one down.
-- Alexander Pierce, "Captain America: The Winter Soldier"
ATK served us well for nearly 20 years, but the world has changed, and
GTK has changed with it. Now ATK is mostly a hindrance towards improving
the accessibility stack:
- it maps to a very specific implementation, AT-SPI, which is Linux and
Unix specific
- it requires implementing the same functionality in three different
layers of the stack: AT-SPI, ATK, and GTK
- only GTK uses it; every other Linux and Unix toolkit and application
talks to AT-SPI directly, including assistive technologies
Sadly, we cannot incrementally port GTK to a new accessibility stack;
since ATK insulates us entirely from the underlying implementation, we
cannot replace it piecemeal. Instead, we're going to remove everything
and then incrementally build on a clean slate:
- add an "accessible" interface, implemented by GTK objects directly,
which describe the accessible role and state changes for every UI
element
- add an "assistive technology context" to proxy a native accessibility
API, and assign it to every widget
- implement the AT context depending on the platform
For more information, see: https://gitlab.gnome.org/GNOME/gtk/-/issues/2833
It's finally unused.
Accessible types should either watch properties they are interested in
directly, or should have (private) API to allow widgets to update the
accessible state directly.
Now that we don't have any additional subclasses of GtkEntryAccessible
in GTK, we can drop all the conditional fluff in the base class.
We still need to subscribe to the global notify signal, because of the
sheer amount of properties watched by GtkEntryAccessible.
GtkPasswordEntryAccessible is not a GtkEntryAccessible any more, so it
will need a proper implementation of various interfaces and
functionality in order to work like any other entry.
We're already listening to the adjustment property on the spin button,
there's no need to reset the adjustment on widget set/unset, since the
accessible instance is always tied to the same widget.
Drop the GtkWidgetAccessibleClass.notify_gtk and the
AtkObjectClass.initialize overrides: they don't do anything relevant.
Instead, have GtkProgressBar update the accessible state when the
fraction changes.
Do not use a generic "notify" signal handler.
Additionally, clean up the GtkIconViewAccessible implementation to bring
it up with modern idiomatic GObject.
The tooltip handling in GtkWidget is "special":
- the string is stored inside the qdata instead of the private
instance data
- the accessors call g_object_set() and g_object_get(), and the
logic is all inside the property implementation, instead of
being the other way around
- the getters return a copy of the string
- the setters don't really notify all the involved properties
The GtkWidgetAccessible uses the (escaped) tooltip text as a source for
the accessible object description, which means it has to store the
tooltip inside the object qdata, and update its copy at construction and
property notification time.
We can simplify this whole circus by making the tooltip properties (text
and markup) more idiomatic:
- notify all side-effect properties
- return a constant string from the getter
- if tooltip-text is set:
- store the text as is
- escape the markup and store it separately for the markup getter
- if tooltip-markup is set:
- store the markup as is
- parse the markup and store it separately for the text getter
The part of the testtooltips interactive test that checks that the
getters are doing the right thing is now part of the gtk testsuite, so
we ensure we don't regress in behaviour.
This commit is porting GtkPaned to be derived
from GtkWidget instead of GtkContainer, while adding
start-child and end-child properties. The existing
properties are renamed to follow the start/end naming
scheme, and we add proper getters and setters.
Update all users.
See #2719