Compare commits

...

64 Commits

Author SHA1 Message Date
Matthias Clasen
670e0cbb14 atspi: Unregister objects on the bus
When a widget is going away, we need to remove
the context from the bus, or else ATs might have
the idea to call methods on them, leading to badness.
2020-10-12 14:41:38 -04:00
Matthias Clasen
539d3d21f1 atspi: Emit property changes for focus
With this orca, actually speaks \o/.  Sadly, it only
says 'gtk modelbutton widget' so far, but its a start.
2020-10-12 14:11:30 -04:00
Matthias Clasen
2195314b3c atspi: Cosmetics
Use simple wrappers instead of opencoding bit twiddling
all over the place.
2020-10-12 13:15:05 -04:00
Matthias Clasen
cff7106751 widget: Notify a11y of focus changes
This is using the new 'platform changes' mechanism
to tell the a11y backends when focus changes.
2020-10-12 13:13:00 -04:00
Matthias Clasen
113e4b9a80 a11y: Pass on platform changes
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.
2020-10-12 13:05:43 -04:00
Matthias Clasen
084e1c1b51 atspi: Be more careful about indexes
Don't return a number for IndexInParent when we
don't have one.
2020-10-12 09:50:57 -04:00
Matthias Clasen
944ce59e1b atspi: Set some more atspi states
Pass on more of the states that are represented
as properties in aria: modal, multi-line, orientation.
2020-10-12 00:21:14 -04:00
Matthias Clasen
6cedd65829 Pass orientation property to accessible
We should set the accessible properties we have,
where they make sense. So set orientation, if the
widget is orientable.
2020-10-12 00:19:55 -04:00
Matthias Clasen
a21df8f009 wip: Emit StateChanged signals
This is not fully baked, but it is enough to make accerciser
notice when a text entry goes from editable to not editable.
2020-10-11 23:51:28 -04:00
Matthias Clasen
fc2e3c8006 atspi: Derive readonly state from aria properties
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.
2020-10-11 23:51:00 -04:00
Matthias Clasen
efebc3e9a9 text: Set the readonly accessible property
This mirrors what we already do for GtkTextView.
2020-10-11 23:51:00 -04:00
Matthias Clasen
089f75169f atspi: Set editable state
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.
2020-10-11 19:01:12 -04:00
Matthias Clasen
909383a15e atspi: Implement EditableText interface
Implement EditableText for GtkText and GtkTextView.
2020-10-11 19:00:44 -04:00
Matthias Clasen
68e85d08b9 atspi: Break out the Value implementation
This isn't necessarily very big, but it keeps
the widget checks out of gtkatspicontext.c, and
it is a nice pattern.
2020-10-11 16:23:40 -04:00
Matthias Clasen
71b0dd4024 atspi: Break out the Text implementations
Move the implementation of the Text interface
to its own source file, and split it up along
widget lines, to avoid it becoming too messy.
2020-10-11 16:22:34 -04:00
Matthias Clasen
9f2342f04e scalebutton: Set accessible value properties
This is what we did in GTK 3.
2020-10-11 11:47:14 -04:00
Matthias Clasen
0fda8f5211 paned: Set accessible value properties
This is what we did in GTK 3.
2020-10-11 11:47:14 -04:00
Matthias Clasen
4b212f9e04 Simplify GetInterfaces handling
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.
2020-10-11 11:47:13 -04:00
Matthias Clasen
464ec29e27 atspi: Implement Value for more widgets
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.
2020-10-11 11:47:13 -04:00
Matthias Clasen
2648f34b1b atspi: Implement Value interface for ranges 2020-10-11 00:27:55 -04:00
Matthias Clasen
8fdd4285f9 atspi: Implement Text interface for text views
With this, all relevant widgets support the
Text interface.
2020-10-10 23:51:23 -04:00
Matthias Clasen
7478ff1a4b atspi: Add textview utilities
These are very similar to the pango utilities,
and are copying code from the textview accessible
implementation in GTK 3.
2020-10-10 23:51:23 -04:00
Matthias Clasen
7969287148 atspi: Export more pango utils
We are going to reuse some of the code that does
the pango -> atspi attribute conversion for text
tags.
2020-10-10 23:50:39 -04:00
Matthias Clasen
9d3c28e4db atspi: Implement text for GtkText widgets too
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.
2020-10-10 20:38:24 -04:00
Matthias Clasen
021e8e4e3a atspi: Implement Text interface for labels
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.
2020-10-10 19:43:42 -04:00
Matthias Clasen
5382717616 atspi: Add pango utilities
This code is more or less a direct copy of what
we had in gtkpango.c in 3.x.
2020-10-10 19:43:42 -04:00
Matthias Clasen
b027d773ca atspicontext: Fix GetIndexInParent for toplevels
For toplevels, we need to return the index in the
list of toplevels, since that is what GtkAtspiRoot
is using.
2020-10-10 13:45:18 -04:00
Matthias Clasen
77935f73cc atcontext: labelled-by has a reference list
This is unclear - our docs state that all the
relations have value type reference, but in fact
they all have value type reference list.
2020-10-10 13:45:18 -04:00
Matthias Clasen
450e51fd4b atspicontext: Implement GetRelationSet
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.
2020-10-10 13:45:18 -04:00
Matthias Clasen
b13d3666f9 atspiroot: Stub out GetRelationSet
This needs to be fully implemented, for now sending
an empty relation set back prevents accerciser from
getting hung up.
2020-10-10 13:45:18 -04:00
Matthias Clasen
5152bea86f atspi: Add the AtspiRelationType enum
This is what we need to map the aria relation
types to.
2020-10-10 13:45:18 -04:00
Matthias Clasen
1f01546232 Move atspi enums to gtkatspiprivate.h 2020-10-10 13:45:18 -04:00
Matthias Clasen
8173fb7a08 Add a GetInterfaces method
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.
2020-10-10 13:45:18 -04:00
Matthias Clasen
2f33ef6f02 Don't pass NULL to g_variant_new_string
That does not work.
2020-10-10 13:45:18 -04:00
Matthias Clasen
2c812d5437 atspi utils: Fix an oversight
gtk_accessible_role_to_atspi_role must always return
an atspi role. The fallback was returning an aria
role.
2020-10-10 13:45:18 -04:00
Matthias Clasen
c5d9694573 Fixup: Add a forgotten #pragma once 2020-10-10 13:45:18 -04:00
Emmanuele Bassi
3b92caba7d a11y: Convenience API for referencing ATSPI root node
We turn the root node into a reference fairly often, so it's worth it to
have a utility function that does this for us.
2020-10-10 13:23:21 +01:00
Emmanuele Bassi
d7e4e8bfeb a11y: Add utility function for null refs
ATSPI was written for CORBA, which allows passing around "nil"
as valid object references.
2020-10-10 13:16:15 +01:00
Matthias Clasen
ab48a745dd atspicontext: Implement GetState
Translate the aria states to at-spi's interpretation
of atk states.
2020-10-10 13:10:36 +01:00
Matthias Clasen
e823218ee7 atspiroot: Fix GetState implementation
When the GetState signature says 'au', it actually
means a bitset that is sent as a pair of 32bit integers.
2020-10-10 13:10:36 +01:00
Matthias Clasen
9ab449e0af atspiroot: Implement GetIndexInParent
Just for good measure
2020-10-10 13:10:36 +01:00
Matthias Clasen
049a06b6a6 atspicontext: Implement GetIndexInParent
This is needed for ATs to take our tree seriously.
2020-10-10 13:10:36 +01:00
Matthias Clasen
b39f2b6465 atspicontext: Implement more accessible api
Implement GetChildAtIndex, GetChildren and ChildCount.
2020-10-10 13:10:36 +01:00
Matthias Clasen
c78019852e atspiroot: Implement GetChildren
No surprises here.
2020-10-10 13:10:36 +01:00
Matthias Clasen
948845b28b atspiroot: Don't leak references
The reffing getter trap, lurking behind g_list_model_get_item().
2020-10-10 13:10:36 +01:00
Matthias Clasen
416d7de267 atspiroot: Implement GetLocale 2020-10-10 13:10:36 +01:00
Matthias Clasen
af99e4ca4b atspicontext: Print out the a11y bus address
Make our debug spew useful: Having the bus address
makes it easy to jump on the a11y bus to look around
with dbus tools.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
5a733854b6 a11y: Localise the role name of the root node 2020-10-10 13:10:36 +01:00
Emmanuele Bassi
19eb3019fe ci: Use test AT context with installed tests
Otherwise we're going to need an AT-SPI service on the session, and the
accessibility bus.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
ad5277145e a11y: Register the Accessible interface on all AtSpiContext instances
This is not a complement implementation.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
32ab032cfa a11y: Implement more ATSPI methods on the root node 2020-10-10 13:10:36 +01:00
Emmanuele Bassi
7661759acd a11y: Add method to extract desktop data
We are going to need the desktop name and path to populate the parent
property of AtSpiContexts associated to top level widgets.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
468317fef2 a11y: Validate the DBus context path
UUIDs use dashes to separate the various blocks; unfortunately, this
results in an invalid DBus object path. Replace the dashes with an
underscore.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
343c9ca4fc a11y: Turn accessible roles to string
Add a simple utility function to turn GtkAccessibleRole values into the
appropriate string, including localization.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
edd05cd69b a11y: Convert GTK roles to ATSPI ones
There's not a precise, 1:1 mapping between the newer ARIA roles and the
older ATSPI ones. We make do with what we have.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
47e537678d a11y: Compute the label for a GtkATContext
The ARIA spec defines the mechanism for determining the name of an
accessible element—see §4.3 of the WAI-ARIA spec.

We follow the specification as much as it makes sense for GTK to do
so:

 1. if the element is hidden, return an empty string
 1. if the element has a labelled-by relation set, retrieve the
    label of the related element
 2. if the element has a label property set, use the value of
    the property
 3. if neither labelled-by nor label attributes are set, we use
    the role to compute the name:
   - for a `range` role, we return the contents of the value of
     the `value-text` or `value-now` properties
   - for any other role, we return a textual representation of
     the GtkAccessibleRole enumeration value
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
fb552ba10a tests: Use the test ATContext for every test
Otherwise we're going to need a full desktop session in order to run the
test suite.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
33d9f46574 a11y: Return the ATSPI role for the root element 2020-10-10 13:10:36 +01:00
Emmanuele Bassi
ae7429a7d0 a11y: Add AT-SPI cache object
Right now, the cache is unused, and we still need to implement the
serialisation method and emit the signals.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
d6554e37b6 a11y: Ignore widgets during destruction
There's no point in creating a GtkATContext when a widget is getting
destroyed.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
67c91bad5f a11y: Register the accessible root object
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.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
65e6e9854e a11y: Add a display to GtkATContext
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.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
a9a5453a4b a11y: Add dummy AT-SPI context
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.
2020-10-10 13:10:36 +01:00
Emmanuele Bassi
5b4ae36c64 a11y: Add the AT-SPI DBus descriptions
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.
2020-10-10 13:10:36 +01:00
66 changed files with 8504 additions and 79 deletions

View File

@@ -99,6 +99,7 @@ installed-tests:
needs: []
variables:
EXTRA_MESON_FLAGS: "--prefix=/usr --libdir=/usr/lib64 -Dinstall-tests=true"
G_TEST_ACCESSIBLE: 1
script:
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="Accessible.xml" parse="xml"/>
<xi:include href="Action.xml" parse="xml"/>
<xi:include href="Application.xml" parse="xml"/>
<xi:include href="Collection.xml" parse="xml"/>
<xi:include href="Component.xml" parse="xml"/>
<xi:include href="Document.xml" parse="xml"/>
<xi:include href="Hypertext.xml" parse="xml"/>
<xi:include href="Hyperlink.xml" parse="xml"/>
<xi:include href="Image.xml" parse="xml"/>
<xi:include href="Selection.xml" parse="xml"/>
<xi:include href="Table.xml" parse="xml"/>
<xi:include href="TableCell.xml" parse="xml"/>
<xi:include href="Text.xml" parse="xml"/>
<xi:include href="EditableText.xml" parse="xml"/>
<xi:include href="Cache.xml" parse="xml"/>
<xi:include href="Value.xml" parse="xml"/>
<xi:include href="Registry.xml" parse="xml"/>
<xi:include href="DeviceEventController.xml" parse="xml"/>
<xi:include href="DeviceEventListener.xml" parse="xml"/>
</spec>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Accessible">
<property name="Name" type="s" access="read"/>
<property name="Description" type="s" access="read"/>
<property name="Parent" type="(so)" access="read">
<annotation name="com.trolltech.QtDBus.QtTypeName" value="QSpiObjectReference"/>
</property>
<property name="ChildCount" type="i" access="read"/>
<property name="Locale" type="s" access="read"/>
<property name="AccessibleId" type="s" access="read"/>
<method name="GetChildAtIndex">
<arg direction="in" name="index" type="i"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetChildren">
<arg direction="out" type="a(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReferenceArray"/>
</method>
<method name="GetIndexInParent">
<arg direction="out" type="i"/>
</method>
<method name="GetRelationSet">
<arg direction="out" type="a(ua(so))"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiRelationArray"/>
</method>
<method name="GetRole">
<arg direction="out" type="u"/>
</method>
<method name="GetRoleName">
<arg direction="out" type="s"/>
</method>
<method name="GetLocalizedRoleName">
<arg direction="out" type="s"/>
</method>
<method name="GetState">
<arg direction="out" type="au"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiIntList"/>
</method>
<method name="GetAttributes">
<arg direction="out" type="a{ss}"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiAttributeSet"/>
</method>
<method name="GetApplication">
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetInterfaces">
<arg direction="out" type="as"/>
</method>
</interface>
</node>

38
gtk/a11y/atspi/Action.xml Normal file
View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Action">
<property name="NActions" type="i" access="read"/>
<method name="GetDescription">
<arg type="i" name="index" direction="in"/>
<arg type="s" direction="out"/>
</method>
<method name="GetName">
<arg type="i" name="index" direction="in"/>
<arg type="s" direction="out"/>
</method>
<method name="GetLocalizedName">
<arg type="i" name="index" direction="in"/>
<arg type="s" direction="out"/>
</method>
<method name="GetKeyBinding">
<arg type="i" name="index" direction="in"/>
<arg type="s" direction="out"/>
</method>
<method name="GetActions">
<arg direction="out" type="a(sss)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiActionArray"/>
</method>
<method name="DoAction">
<arg direction="in" name="index" type="i"/>
<arg direction="out" type="b"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Application">
<property name="ToolkitName" type="s" access="read"/>
<property name="Version" type="s" access="read"/>
<property name="AtspiVersion" type="s" access="read"/>
<property name="Id" type="i" access="readwrite"/>
<method name="GetLocale">
<arg direction="in" name="lctype" type="u"/>
<arg direction="out" type="s"/>
</method>
<method name="RegisterEventListener">
<arg direction="in" name="event" type="s"/>
</method>
<method name="DeregisterEventListener">
<arg direction="in" name="event" type="s"/>
</method>
</interface>
</node>

21
gtk/a11y/atspi/Cache.xml Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Cache">
<method name="GetItems">
<arg name="nodes" type="a((so)(so)iiassusau)" direction="out"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiAccessibleCacheArray"/>
</method>
<signal name="AddAccessible">
<arg name="nodeAdded" type="((so)(so)iiassusau)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiAccessibleCacheItem"/>
</signal>
<signal name="RemoveAccessible">
<arg name="nodeRemoved" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
</signal>
</interface>
</node>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Collection">
<method name="GetMatches">
<arg direction="in" name="rule" type="(auuasuauusub)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QSpiMatchRule"/>
<arg direction="in" name="sortby" type="u"/>
<arg direction="in" name="count" type="i"/>
<arg direction="in" name="traverse" type="b"/>
<arg direction="out" type="a(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiReferenceSet"/>
</method>
<method name="GetMatchesTo">
<arg direction="in" name="current_object" type="o"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
<arg direction="in" name="rule" type="(auuasuauusub)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QSpiMatchRule"/>
<arg direction="in" name="sortby" type="u"/>
<arg direction="in" name="tree" type="u"/>
<arg direction="in" name="limit_scope" type="b"/>
<arg direction="in" name="count" type="i"/>
<arg direction="in" name="traverse" type="b"/>
<arg direction="out" type="a(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiReferenceSet"/>
</method>
<method name="GetMatchesFrom">
<arg direction="in" name="current_object" type="o"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
<arg direction="in" name="rule" type="(auuasuauusub)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QSpiMatchRule"/>
<arg direction="in" name="sortby" type="u"/>
<arg direction="in" name="tree" type="u"/>
<arg direction="in" name="count" type="i"/>
<arg direction="in" name="traverse" type="b"/>
<arg direction="out" type="a(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiReferenceSet"/>
</method>
<method name="GetActiveDescendant">
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiReferenceSet"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Component">
<method name="Contains">
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
<arg direction="in" name="coord_type" type="u"/>
<arg direction="out" type="b"/>
</method>
<method name="GetAccessibleAtPoint">
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
<arg direction="in" name="coord_type" type="u"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetExtents">
<arg direction="in" name="coord_type" type="u"/>
<arg direction="out" type="(iiii)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiRect"/>
</method>
<method name="GetPosition">
<arg direction="in" name="coord_type" type="u"/>
<arg direction="out" name="x" type="i"/>
<arg direction="out" name="y" type="i"/>
</method>
<method name="GetSize">
<arg direction="out" name="width" type="i"/>
<arg direction="out" name="height" type="i"/>
</method>
<method name="GetLayer">
<arg direction="out" type="u"/>
</method>
<method name="GetMDIZOrder">
<arg direction="out" type="n"/>
</method>
<method name="GrabFocus">
<arg direction="out" type="b"/>
</method>
<method name="GetAlpha">
<arg direction="out" type="d"/>
</method>
<method name="SetExtents">
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
<arg direction="in" name="width" type="i"/>
<arg direction="in" name="height" type="i"/>
<arg direction="in" name="coord_type" type="u"/>
<arg direction="out" type="b"/>
</method>
<method name="SetPosition">
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
<arg direction="in" name="coord_type" type="u"/>
<arg direction="out" type="b"/>
</method>
<method name="SetSize">
<arg direction="in" name="width" type="i"/>
<arg direction="in" name="height" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="ScrollTo">
<arg direction="in" name="type" type="u"/>
</method>
<method name="ScrollToPoint">
<arg direction="in" name="type" type="u"/>
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.DeviceEventController">
<method name="RegisterKeystrokeListener">
<arg direction="in" name="listener" type="o"/>
<arg direction="in" name="keys" type="a(iisi)">
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QSpiKeyTypeArray"/>
</arg>
<arg direction="in" name="mask" type="u"/>
<arg direction="in" name="type" type="au">
<annotation name="com.trolltech.QtDBus.QtTypeName.In3" value="QSpiEventTypeArray"/>
</arg>
<arg direction="in" name="mode" type="(bbb)">
<annotation name="com.trolltech.QtDBus.QtTypeName.In4" value="QSpiEventMode"/>
</arg>
<arg direction="out" type="b"/>
</method>
<method name="DeregisterKeystrokeListener">
<arg direction="in" name="listener" type="o"/>
<arg direction="in" name="keys" type="a(iisi)">
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QSpiKeyTypeArray"/>
</arg>
<arg direction="in" name="mask" type="u"/>
<arg direction="in" name="type" type="u"/>
</method>
<method name="RegisterDeviceEventListener">
<arg direction="in" name="listener" type="o"/>
<arg direction="in" name="types" type="u"/>
<arg direction="out" type="b"/>
</method>
<method name="DeregisterDeviceEventListener">
<arg direction="in" name="listener" type="o"/>
<arg direction="in" name="types" type="u"/>
</method>
<method name="GenerateKeyboardEvent">
<arg direction="in" name="keycode" type="i"/>
<arg direction="in" name="keystring" type="s"/>
<arg direction="in" name="type" type="u"/>
</method>
<method name="GenerateMouseEvent">
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
<arg direction="in" name="eventName" type="s"/>
</method>
<method name="NotifyListenersSync">
<arg direction="in" name="event" type="(uiuuisb)"/>
<arg direction="out" type="b"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiDeviceEvent"/>
</method>
<method name="NotifyListenersAsync">
<arg direction="in" name="event" type="(uiuuisb)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiDeviceEvent"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.DeviceEventListener">
<method name="NotifyEvent">
<arg direction="in" name="event" type="(uiuuisb)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiDeviceEvent"/>
<arg direction="out" type="b"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Document">
<property name="CurrentPageNumber" type="i" access="read"/>
<property name="PageCount" type="i" access="read"/>
<method name="GetLocale">
<arg direction="out" type="s"/>
</method>
<method name="GetAttributeValue">
<arg direction="in" name="attributename" type="s"/>
<arg direction="out" type="s"/>
</method>
<method name="GetAttributes">
<arg direction="out" type="{ss}"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiAttrubutes"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.EditableText">
<method name="SetTextContents">
<arg direction="in" name="newContents" type="s"/>
<arg direction="out" type="b"/>
</method>
<method name="InsertText">
<arg direction="in" name="position" type="i"/>
<arg direction="in" name="text" type="s"/>
<arg direction="in" name="length" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="CopyText">
<arg direction="in" name="startPos" type="i"/>
<arg direction="in" name="endPos" type="i"/>
</method>
<method name="CutText">
<arg direction="in" name="startPos" type="i"/>
<arg direction="in" name="endPos" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="DeleteText">
<arg direction="in" name="startPos" type="i"/>
<arg direction="in" name="endPos" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="PasteText">
<arg direction="in" name="position" type="i"/>
<arg direction="out" type="b"/>
</method>
</interface>
</node>

193
gtk/a11y/atspi/Event.xml Normal file
View File

@@ -0,0 +1,193 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Event.Object">
<signal name="PropertyChange"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="BoundsChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="LinkSelected"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="StateChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ChildrenChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="VisibleDataChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="SelectionChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ModelChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ActiveDescendantChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="RowInserted"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="RowReordered"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="RowDeleted"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ColumnInserted"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ColumnReordered"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ColumnDeleted"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="TextBoundsChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="TextSelectionChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="TextChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="TextAttributesChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="TextCaretMoved"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="AttributesChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
</interface>
<interface name="org.a11y.atspi.Event.Window">
<signal name="PropertyChange"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Minimize"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Maximize"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Restore"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Close"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Create"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Reparent"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="DesktopCreate"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="DesktopDestroy"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Destroy"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Activate"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Deactivate"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Raise"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Lower"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Move"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Resize"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Shade"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="uUshade"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Restyle"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
</interface>
<interface name="org.a11y.atspi.Event.Mouse">
<signal name="Abs"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Rel"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Button"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
</interface>
<interface name="org.a11y.atspi.Event.Keyboard">
<signal name="Modifiers"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
</interface>
<interface name="org.a11y.atspi.Event.Terminal">
<signal name="LineChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ColumncountChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="LinecountChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ApplicationChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="CharwidthChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
</interface>
<interface name="org.a11y.atspi.Event.Document">
<signal name="LoadComplete"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="Reload"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="LoadStopped"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="ContentChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="AttributesChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
<signal name="PageChanged"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
</interface>
<interface name="org.a11y.atspi.Event.Focus">
<signal name="Focus"><arg direction="in" type="(suuv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiEvent"/>
</signal>
</interface>
</node>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Hyperlink">
<property name="NAnchors" type="n" access="read"/>
<property name="StartIndex" type="i" access="read"/>
<property name="EndIndex" type="i" access="read"/>
<method name="GetObject">
<arg direction="in" name="i" type="i"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetURI">
<arg direction="in" name="i" type="i"/>
<arg direction="out" type="s"/>
</method>
<method name="IsValid">
<arg direction="out" type="b"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Hypertext">
<method name="GetNLinks">
<arg direction="out" type="i"/>
</method>
<method name="GetLink">
<arg direction="in" name="linkIndex" type="i"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetLinkIndex">
<arg direction="in" name="characterIndex" type="i"/>
<arg direction="out" type="i"/>
</method>
</interface>
</node>

27
gtk/a11y/atspi/Image.xml Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Image">
<property name="ImageDescription" type="s" access="read"/>
<property name="ImageLocale" type="s" access="read"/>
<method name="GetImageExtents">
<arg direction="in" name="coordType" type="u"/>
<arg direction="out" type="(iiii)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiRect"/>
</method>
<method name="GetImagePosition">
<arg direction="out" name="x" type="i"/>
<arg direction="out" name="y" type="i"/>
<arg direction="in" name="coordType" type="u"/>
</method>
<method name="GetImageSize">
<arg direction="out" name="width" type="i"/>
<arg direction="out" name="height" type="i"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Registry">
<method name="RegisterEvent">
<arg direction="in" name="event" type="s">
</arg>
</method>
<method name="DeregisterEvent">
<arg direction="in" name="event" type="s">
</arg>
</method>
<method name="GetRegisteredEvents">
<arg direction="out" name="events" type="a(ss)">
</arg>
</method>
<signal name="EventListenerRegistered">
<arg direction="out" name="bus" type="s"/>
<arg direction="out" name="path" type="s"/>
</signal>
<signal name="EventListenerDeregistered">
<arg direction="out" name="bus" type="s"/>
<arg direction="out" name="path" type="s"/>
</signal>
</interface>
</node>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Selection">
<property name="NSelectedChildren" type="i" access="read"/>
<method name="GetSelectedChild">
<arg direction="in" name="selectedChildIndex" type="i"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="SelectChild">
<arg direction="in" name="childIndex" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="DeselectSelectedChild">
<arg direction="in" name="selectedChildIndex" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="IsChildSelected">
<arg direction="in" name="childIndex" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="SelectAll">
<arg direction="out" type="b"/>
</method>
<method name="ClearSelection">
<arg direction="out" type="b"/>
</method>
<method name="DeselectChild">
<arg direction="in" name="childIndex" type="i"/>
<arg direction="out" type="b"/>
</method>
</interface>
</node>

27
gtk/a11y/atspi/Socket.xml Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Socket">
<method name="Embed">
<arg direction="in" name="plug" type="(so)">
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
</arg>
<arg direction="out" name="socket" type="(so)">
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</arg>
</method>
<method name="Unembed">
<arg direction="in" name="plug" type="(so)">
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
</arg>
</method>
<signal name="Available">
<arg direction="in" name="socket" type="(so)">
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
</arg>
</signal>
</interface>
</node>

135
gtk/a11y/atspi/Table.xml Normal file
View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Table">
<property name="NRows" type="i" access="read"/>
<property name="NColumns" type="i" access="read"/>
<property name="Caption" type="(so)" access="read">
<annotation name="com.trolltech.QtDBus.QtTypeName" value="QSpiObjectReference"/>
</property>
<property name="Summary" type="(so)" access="read">
<annotation name="com.trolltech.QtDBus.QtTypeName" value="QSpiObjectReference"/>
</property>
<property name="NSelectedRows" type="i" access="read"/>
<property name="NSelectedColumns" type="i" access="read"/>
<method name="GetAccessibleAt">
<arg direction="in" name="row" type="i"/>
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetIndexAt">
<arg direction="in" name="row" type="i"/>
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="i"/>
</method>
<method name="GetRowAtIndex">
<arg direction="in" name="index" type="i"/>
<arg direction="out" type="i"/>
</method>
<method name="GetColumnAtIndex">
<arg direction="in" name="index" type="i"/>
<arg direction="out" type="i"/>
</method>
<method name="GetRowDescription">
<arg direction="in" name="row" type="i"/>
<arg direction="out" type="s"/>
</method>
<method name="GetColumnDescription">
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="s"/>
</method>
<method name="GetRowExtentAt">
<arg direction="in" name="row" type="i"/>
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="i"/>
</method>
<method name="GetColumnExtentAt">
<arg direction="in" name="row" type="i"/>
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="i"/>
</method>
<method name="GetRowHeader">
<arg direction="in" name="row" type="i"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetColumnHeader">
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="(so)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
</method>
<method name="GetSelectedRows">
<arg direction="out" type="ai"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiIntList"/>
</method>
<method name="GetSelectedColumns">
<arg direction="out" type="ai"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiIntList"/>
</method>
<method name="IsRowSelected">
<arg direction="in" name="row" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="IsColumnSelected">
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="IsSelected">
<arg direction="in" name="row" type="i"/>
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="AddRowSelection">
<arg direction="in" name="row" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="AddColumnSelection">
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="RemoveRowSelection">
<arg direction="in" name="row" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="RemoveColumnSelection">
<arg direction="in" name="column" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="GetRowColumnExtentsAtIndex">
<arg direction="in" name="index" type="i"/>
<arg direction="out" type="b"/>
<arg direction="out" name="row" type="i"/>
<arg direction="out" name="col" type="i"/>
<arg direction="out" name="row_extents" type="i"/>
<arg direction="out" name="col_extents" type="i"/>
<arg direction="out" name="is_selected" type="b"/>
</method>
</interface>
</node>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.TableCell">
<property access="read" name="ColumnSpan" type="i" />
<property access="read" name="Position" type="(ii)" />
<property access="read" name="RowSpan" type="i" />
<property access="read" name="Table" type="(so)" />
<method name="GetRowColumnSpan">
<arg direction="out" type="b" />
<arg direction="out" name="row" type="i" />
<arg direction="out" name="col" type="i" />
<arg direction="out" name="row_extents" type="i" />
<arg direction="out" name="col_extents" type="i" />
</method>
</interface>
</node>

170
gtk/a11y/atspi/Text.xml Normal file
View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Text">
<property name="CharacterCount" type="i" access="read"/>
<property name="CaretOffset" type="i" access="read"/>
<method name="GetStringAtOffset">
<arg direction="in" name="offset" type="i"/>
<arg direction="in" name="granularity" type="u"/>
<arg direction="out" type="s"/>
<arg direction="out" name="startOffset" type="i"/>
<arg direction="out" name="endOffset" type="i"/>
</method>
<method name="GetText">
<arg direction="in" name="startOffset" type="i"/>
<arg direction="in" name="endOffset" type="i"/>
<arg direction="out" type="s"/>
</method>
<method name="SetCaretOffset">
<arg direction="in" name="offset" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="GetTextBeforeOffset">
<arg direction="in" name="offset" type="i"/>
<arg direction="in" name="type" type="u"/>
<arg direction="out" type="s"/>
<arg direction="out" name="startOffset" type="i"/>
<arg direction="out" name="endOffset" type="i"/>
</method>
<method name="GetTextAtOffset">
<arg direction="in" name="offset" type="i"/>
<arg direction="in" name="type" type="u"/>
<arg direction="out" type="s"/>
<arg direction="out" name="startOffset" type="i"/>
<arg direction="out" name="endOffset" type="i"/>
</method>
<method name="GetTextAfterOffset">
<arg direction="in" name="offset" type="i"/>
<arg direction="in" name="type" type="u"/>
<arg direction="out" type="s"/>
<arg direction="out" name="startOffset" type="i"/>
<arg direction="out" name="endOffset" type="i"/>
</method>
<method name="GetCharacterAtOffset">
<arg name="offset" type="i" direction="in"/>
<arg type="i" direction="out"/>
</method>
<method name="GetAttributeValue">
<arg direction="in" name="offset" type="i"/>
<arg direction="in" name="attributeName" type="s"/>
<arg direction="out" type="s"/>
</method>
<method name="GetAttributes">
<arg direction="in" name="offset" type="i"/>
<arg direction="out" type="a{ss}"/>
<arg direction="out" name="startOffset" type="i"/>
<arg direction="out" name="endOffset" type="i"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiAttributeSet"/>
</method>
<method name="GetDefaultAttributes">
<arg direction="out" type="a{ss}"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiAttributeSet"/>
</method>
<method name="GetCharacterExtents">
<arg direction="in" name="offset" type="i"/>
<arg direction="out" name="x" type="i"/>
<arg direction="out" name="y" type="i"/>
<arg direction="out" name="width" type="i"/>
<arg direction="out" name="height" type="i"/>
<arg direction="in" name="coordType" type="u"/>
</method>
<method name="GetOffsetAtPoint">
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
<arg direction="in" name="coordType" type="u"/>
<arg direction="out" type="i"/>
</method>
<method name="GetNSelections">
<arg direction="out" type="i"/>
</method>
<method name="GetSelection">
<arg direction="in" name="selectionNum" type="i"/>
<arg direction="out" name="startOffset" type="i"/>
<arg direction="out" name="endOffset" type="i"/>
</method>
<method name="AddSelection">
<arg direction="in" name="startOffset" type="i"/>
<arg direction="in" name="endOffset" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="RemoveSelection">
<arg direction="in" name="selectionNum" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="SetSelection">
<arg direction="in" name="selectionNum" type="i"/>
<arg direction="in" name="startOffset" type="i"/>
<arg direction="in" name="endOffset" type="i"/>
<arg direction="out" type="b"/>
</method>
<method name="GetRangeExtents">
<arg direction="in" name="startOffset" type="i"/>
<arg direction="in" name="endOffset" type="i"/>
<arg direction="out" name="x" type="i"/>
<arg direction="out" name="y" type="i"/>
<arg direction="out" name="width" type="i"/>
<arg direction="out" name="height" type="i"/>
<arg direction="in" name="coordType" type="u"/>
</method>
<method name="GetBoundedRanges">
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
<arg direction="in" name="width" type="i"/>
<arg direction="in" name="height" type="i"/>
<arg direction="in" name="coordType" type="u"/>
<arg direction="in" name="xClipType" type="u"/>
<arg direction="in" name="yClipType" type="u"/>
<arg direction="out" type="a(iisv)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiRangeList"/>
</method>
<method name="GetAttributeRun">
<arg direction="in" name="offset" type="i"/>
<arg direction="in" name="includeDefaults" type="b"/>
<arg direction="out" type="a{ss}"/>
<arg direction="out" name="startOffset" type="i"/>
<arg direction="out" name="endOffset" type="i"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QSpiAttributeSet"/>
</method>
<method name="GetDefaultAttributeSet">
<arg direction="out" type="a{ss}"/>
</method>
<method name="ScrollSubstringTo">
<arg direction="in" name="startOffset" type="i"/>
<arg direction="in" name="endOffset" type="i"/>
<arg direction="in" name="type" type="u"/>
</method>
<method name="ScrollSubstringToPoint">
<arg direction="in" name="startOffset" type="i"/>
<arg direction="in" name="endOffset" type="i"/>
<arg direction="in" name="type" type="u"/>
<arg direction="in" name="x" type="i"/>
<arg direction="in" name="y" type="i"/>
</method>
</interface>
</node>

14
gtk/a11y/atspi/Value.xml Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/node">
<interface name="org.a11y.atspi.Value">
<property name="MinimumValue" type="d" access="read"/>
<property name="MaximumValue" type="d" access="read"/>
<property name="MinimumIncrement" type="d" access="read"/>
<property name="CurrentValue" type="d" access="readwrite"/>
</interface>
</node>

View File

@@ -0,0 +1,65 @@
atspi_xml = [
'Accessible.xml',
'Action.xml',
'Application.xml',
'Cache.xml',
'Collection.xml',
'Component.xml',
'DeviceEventController.xml',
'DeviceEventListener.xml',
'Document.xml',
'EditableText.xml',
'Event.xml',
'Hyperlink.xml',
'Hypertext.xml',
'Image.xml',
'Registry.xml',
'Selection.xml',
'Socket.xml',
'Table.xml',
'TableCell.xml',
'Text.xml',
'Value.xml',
]
gdbus_codegen = find_program('gdbus-codegen')
atspi_src = []
foreach xml: atspi_xml
obj_name = xml.split('.').get(0)
# We cannot use gnome.gdbus_codegen() directly because we only care about
# the interface definitions, not the whole GTypeInterface/GObject proxy
# classes
gen_hdr = custom_target('atspi-' + obj_name.to_lower() + '-hdr',
input: xml,
output: 'atspi-' + obj_name.to_lower() + '.h',
command: [
gdbus_codegen,
'--interface-prefix=org.a11y.atspi',
'--c-namespace=Atspi',
'--pragma-once',
'--interface-info-header',
'--output=@OUTPUT@',
'@INPUT@',
],
build_by_default: true,
)
gen_src = custom_target('atspi-' + obj_name.to_lower() + '-src',
input: xml,
output: 'atspi-' + obj_name.to_lower() + '.c',
command: [
gdbus_codegen,
'--interface-prefix=org.a11y.atspi',
'--c-namespace=Atspi',
'--interface-info-body',
'--output=@OUTPUT@',
'@INPUT@',
],
build_by_default: true,
)
atspi_src += [gen_src, gen_hdr]
endforeach
gtk_a11y_src += atspi_src

218
gtk/a11y/gtkatspicache.c Normal file
View File

@@ -0,0 +1,218 @@
/* gtkatspicache.c: AT-SPI object cache
*
* Copyright 2020 holder
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkatspicacheprivate.h"
#include "gtkdebug.h"
#include "a11y/atspi/atspi-cache.h"
struct _GtkAtSpiCache
{
GObject parent_instance;
char *cache_path;
GDBusConnection *connection;
GHashTable *contexts;
};
enum
{
PROP_CACHE_PATH = 1,
PROP_CONNECTION,
N_PROPS
};
static GParamSpec *obj_props[N_PROPS];
G_DEFINE_TYPE (GtkAtSpiCache, gtk_at_spi_cache, G_TYPE_OBJECT)
static void
gtk_at_spi_cache_finalize (GObject *gobject)
{
GtkAtSpiCache *self = GTK_AT_SPI_CACHE (gobject);
g_clear_pointer (&self->contexts, g_hash_table_unref);
g_clear_object (&self->connection);
g_free (self->cache_path);
G_OBJECT_CLASS (gtk_at_spi_cache_parent_class)->finalize (gobject);
}
static void
gtk_at_spi_cache_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkAtSpiCache *self = GTK_AT_SPI_CACHE (gobject);
switch (prop_id)
{
case PROP_CACHE_PATH:
g_free (self->cache_path);
self->cache_path = g_value_dup_string (value);
break;
case PROP_CONNECTION:
g_clear_object (&self->connection);
self->connection = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
handle_cache_method (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
g_printerr ("[Cache] Method '%s' on interface '%s' for object '%s' from '%s'\n",
method_name, interface_name, object_path, sender);
}
static GVariant *
handle_cache_get_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data)
{
GVariant *res = NULL;
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Unknown property '%s'", property_name);
return res;
}
static const GDBusInterfaceVTable cache_vtable = {
handle_cache_method,
handle_cache_get_property,
NULL,
};
static void
gtk_at_spi_cache_constructed (GObject *gobject)
{
GtkAtSpiCache *self = GTK_AT_SPI_CACHE (gobject);
g_assert (self->connection);
g_assert (self->cache_path);
g_dbus_connection_register_object (self->connection,
self->cache_path,
(GDBusInterfaceInfo *) &atspi_cache_interface,
&cache_vtable,
self,
NULL,
NULL);
GTK_NOTE (A11Y, g_message ("Cache registered at %s", self->cache_path));
G_OBJECT_CLASS (gtk_at_spi_cache_parent_class)->constructed (gobject);
}
static void
gtk_at_spi_cache_class_init (GtkAtSpiCacheClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = gtk_at_spi_cache_constructed;
gobject_class->set_property = gtk_at_spi_cache_set_property;
gobject_class->finalize = gtk_at_spi_cache_finalize;
obj_props[PROP_CACHE_PATH] =
g_param_spec_string ("cache-path", NULL, NULL,
NULL,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_CONNECTION] =
g_param_spec_object ("connection", NULL, NULL,
G_TYPE_DBUS_CONNECTION,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, obj_props);
}
static void
gtk_at_spi_cache_init (GtkAtSpiCache *self)
{
self->contexts = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
NULL);
}
GtkAtSpiCache *
gtk_at_spi_cache_new (GDBusConnection *connection,
const char *cache_path)
{
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
g_return_val_if_fail (cache_path != NULL, NULL);
return g_object_new (GTK_TYPE_AT_SPI_CACHE,
"connection", connection,
"cache-path", cache_path,
NULL);
}
void
gtk_at_spi_cache_add_context (GtkAtSpiCache *self,
const char *path,
GtkATContext *context)
{
g_return_if_fail (GTK_IS_AT_SPI_CACHE (self));
g_return_if_fail (path != NULL);
g_return_if_fail (GTK_IS_AT_CONTEXT (context));
if (g_hash_table_contains (self->contexts, path))
return;
g_hash_table_insert (self->contexts, g_strdup (path), context);
}
GtkATContext *
gtk_at_spi_cache_get_context (GtkAtSpiCache *self,
const char *path)
{
g_return_val_if_fail (GTK_IS_AT_SPI_CACHE (self), NULL);
g_return_val_if_fail (path != NULL, NULL);
return g_hash_table_lookup (self->contexts, path);
}

View File

@@ -0,0 +1,44 @@
/* gtkatspicacheprivate.h: AT-SPI object cache
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "gtkatcontextprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_AT_SPI_CACHE (gtk_at_spi_cache_get_type())
G_DECLARE_FINAL_TYPE (GtkAtSpiCache, gtk_at_spi_cache, GTK, AT_SPI_CACHE, GObject)
GtkAtSpiCache *
gtk_at_spi_cache_new (GDBusConnection *connection,
const char *cache_path);
void
gtk_at_spi_cache_add_context (GtkAtSpiCache *self,
const char *path,
GtkATContext *context);
GtkATContext *
gtk_at_spi_cache_get_context (GtkAtSpiCache *self,
const char *path);
G_END_DECLS

1207
gtk/a11y/gtkatspicontext.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/* gtkatspicontextprivate.h: AT-SPI GtkATContext implementation
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "gtkatcontextprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_AT_SPI_CONTEXT (gtk_at_spi_context_get_type())
G_DECLARE_FINAL_TYPE (GtkAtSpiContext, gtk_at_spi_context, GTK, AT_SPI_CONTEXT, GtkATContext)
GtkATContext *
gtk_at_spi_create_context (GtkAccessibleRole accessible_role,
GtkAccessible *accessible,
GdkDisplay *display);
const char *
gtk_at_spi_context_get_context_path (GtkAtSpiContext *self);
G_END_DECLS

View File

@@ -0,0 +1,349 @@
/* gtkatspieditabletext.c: EditableText interface for GtkAtspiContext
*
* Copyright 2020 Red Hat, Inc
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkatspieditabletextprivate.h"
#include "gtkatcontextprivate.h"
#include "a11y/atspi/atspi-editabletext.h"
#include "gtktext.h"
#include "gtktextview.h"
#include <gio/gio.h>
typedef struct
{
GtkWidget *widget;
int position;
} PasteData;
static void
text_received (GObject *source,
GAsyncResult *result,
gpointer data)
{
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
PasteData *pdata = data;
char *text;
text = gdk_clipboard_read_text_finish (clipboard, result, NULL);
if (text)
gtk_editable_insert_text (GTK_EDITABLE (pdata->widget), text, -1, &pdata->position);
g_free (text);
g_free (pdata);
}
static void
text_handle_method (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
GtkATContext *self = user_data;
GtkAccessible *accessible = gtk_at_context_get_accessible (self);
GtkWidget *widget = GTK_WIDGET (accessible);
if (g_strcmp0 (method_name, "SetTextContents") == 0)
{
char *text;
gboolean ret = FALSE;
g_variant_get (parameters, "(&s)", &text);
if (gtk_editable_get_editable (GTK_EDITABLE (widget)))
{
gtk_editable_set_text (GTK_EDITABLE (widget), text);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "InsertText") == 0)
{
int position;
char *text;
int len;
gboolean ret = FALSE;
g_variant_get (parameters, "(i&si)", &position, &text, &len);
if (gtk_editable_get_editable (GTK_EDITABLE (widget)))
{
gtk_editable_insert_text (GTK_EDITABLE (widget), text, -1, &position);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "CopyText") == 0)
{
int start, end;
char *str;
g_variant_get (parameters, "(ii)", &start, &end);
str = gtk_editable_get_chars (GTK_EDITABLE (widget), start, end);
gdk_clipboard_set_text (gtk_widget_get_clipboard (widget), str);
g_free (str);
g_dbus_method_invocation_return_value (invocation, NULL);
}
else if (g_strcmp0 (method_name, "CutText") == 0)
{
int start, end;
gboolean ret = FALSE;
g_variant_get (parameters, "(ii)", &start, &end);
if (gtk_editable_get_editable (GTK_EDITABLE (widget)))
{
char *str;
str = gtk_editable_get_chars (GTK_EDITABLE (widget), start, end);
gdk_clipboard_set_text (gtk_widget_get_clipboard (widget), str);
g_free (str);
gtk_editable_delete_text (GTK_EDITABLE (widget), start, end);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "DeleteText") == 0)
{
int start, end;
gboolean ret = FALSE;
g_variant_get (parameters, "(ii)", &start, &end);
if (gtk_editable_get_editable (GTK_EDITABLE (widget)))
{
gtk_editable_delete_text (GTK_EDITABLE (widget), start, end);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "PasteText") == 0)
{
int position;
gboolean ret = FALSE;
g_variant_get (parameters, "(i)", &position);
if (gtk_editable_get_editable (GTK_EDITABLE (widget)))
{
PasteData *data;
data = g_new (PasteData, 1);
data->widget = widget;
data->position = position;
gdk_clipboard_read_text_async (gtk_widget_get_clipboard (widget), NULL, text_received, data);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
}
static const GDBusInterfaceVTable text_vtable = {
text_handle_method,
NULL,
};
static void
text_view_received (GObject *source,
GAsyncResult *result,
gpointer data)
{
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
PasteData *pdata = data;
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (pdata->widget));
GtkTextIter iter;
char *text;
text = gdk_clipboard_read_text_finish (clipboard, result, NULL);
if (text)
{
gtk_text_buffer_get_iter_at_offset (buffer, &iter, pdata->position);
gtk_text_buffer_insert (buffer, &iter, text, -1);
}
g_free (text);
g_free (pdata);
}
static void
text_view_handle_method (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
GtkATContext *self = user_data;
GtkAccessible *accessible = gtk_at_context_get_accessible (self);
GtkWidget *widget = GTK_WIDGET (accessible);
if (g_strcmp0 (method_name, "SetTextContents") == 0)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
char *text;
gboolean ret = FALSE;
g_variant_get (parameters, "(&s)", &text);
if (gtk_text_view_get_editable (GTK_TEXT_VIEW (widget)))
{
gtk_text_buffer_set_text (buffer, text, -1);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "InsertText") == 0)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
GtkTextIter iter;
int position;
char *text;
int len;
gboolean ret = FALSE;
g_variant_get (parameters, "(i&si)", &position, &text, &len);
if (gtk_text_view_get_editable (GTK_TEXT_VIEW (widget)))
{
gtk_text_buffer_get_iter_at_offset (buffer, &iter, position);
gtk_text_buffer_insert (buffer, &iter, text, len);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "CopyText") == 0)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
GtkTextIter start_iter, end_iter;
int start, end;
char *str;
g_variant_get (parameters, "(ii)", &start, &end);
gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start);
gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end);
str = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
gdk_clipboard_set_text (gtk_widget_get_clipboard (widget), str);
g_free (str);
g_dbus_method_invocation_return_value (invocation, NULL);
}
else if (g_strcmp0 (method_name, "CutText") == 0)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
GtkTextIter start_iter, end_iter;
int start, end;
gboolean ret = FALSE;
g_variant_get (parameters, "(ii)", &start, &end);
if (gtk_text_view_get_editable (GTK_TEXT_VIEW (widget)))
{
char *str;
gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start);
gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end);
str = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
gdk_clipboard_set_text (gtk_widget_get_clipboard (widget), str);
g_free (str);
gtk_text_buffer_delete (buffer, &start_iter, &end_iter);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "DeleteText") == 0)
{
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
GtkTextIter start_iter, end_iter;
int start, end;
gboolean ret = FALSE;
g_variant_get (parameters, "(ii)", &start, &end);
if (gtk_text_view_get_editable (GTK_TEXT_VIEW (widget)))
{
gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start);
gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end);
gtk_text_buffer_delete (buffer, &start_iter, &end_iter);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
else if (g_strcmp0 (method_name, "PasteText") == 0)
{
int position;
gboolean ret = FALSE;
g_variant_get (parameters, "(i)", &position);
if (gtk_text_view_get_editable (GTK_TEXT_VIEW (widget)))
{
PasteData *data;
data = g_new (PasteData, 1);
data->widget = widget;
data->position = position;
gdk_clipboard_read_text_async (gtk_widget_get_clipboard (widget), NULL, text_view_received, data);
ret = TRUE;
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
}
}
static const GDBusInterfaceVTable text_view_vtable = {
text_view_handle_method,
NULL,
};
const GDBusInterfaceVTable *
gtk_atspi_get_editable_text_vtable (GtkWidget *widget)
{
if (GTK_IS_TEXT (widget))
return &text_vtable;
else if (GTK_IS_TEXT_VIEW (widget))
return &text_view_vtable;
return NULL;
}

View File

@@ -0,0 +1,30 @@
/* gtkatspieditabletextprivate.h: AT-SPI EditableText implementation
*
* Copyright 2020 Red Hat, Inc.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gio/gio.h>
#include "gtkwidget.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_editable_text_vtable (GtkWidget *widget);
G_END_DECLS

1257
gtk/a11y/gtkatspipango.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/* gtkatspipangoprivate.h: Utilities for pango and AT-SPI
* Copyright 2020 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <pango/pangocairo.h>
#include "gtkatspiprivate.h"
G_BEGIN_DECLS
const char *pango_wrap_mode_to_string (PangoWrapMode mode);
const char *pango_underline_to_string (PangoUnderline underline);
const char *pango_stretch_to_string (PangoStretch stretch);
const char *pango_style_to_string (PangoStyle style);
const char *pango_variant_to_string (PangoVariant variant);
void gtk_pango_get_font_attributes (PangoFontDescription *font,
GVariantBuilder *builder);
void gtk_pango_get_default_attributes (PangoLayout *layout,
GVariantBuilder *builder);
void gtk_pango_get_run_attributes (PangoLayout *layout,
GVariantBuilder *builder,
int offset,
int *start_offset,
int *end_offset);
char *gtk_pango_get_text_before (PangoLayout *layout,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset);
char *gtk_pango_get_text_at (PangoLayout *layout,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset);
char *gtk_pango_get_text_after (PangoLayout *layout,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset);
char *gtk_pango_get_string_at (PangoLayout *layout,
int offset,
AtspiTextGranularity granularity,
int *start_offset,
int *end_offset);
G_END_DECLS

249
gtk/a11y/gtkatspiprivate.h Normal file
View File

@@ -0,0 +1,249 @@
/* gtkatspiprivate.h: AT-SPI shared types
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
G_BEGIN_DECLS
typedef enum {
ATSPI_ROLE_INVALID,
ATSPI_ROLE_ACCELERATOR_LABEL,
ATSPI_ROLE_ALERT,
ATSPI_ROLE_ANIMATION,
ATSPI_ROLE_ARROW,
ATSPI_ROLE_CALENDAR,
ATSPI_ROLE_CANVAS,
ATSPI_ROLE_CHECK_BOX,
ATSPI_ROLE_CHECK_MENU_ITEM,
ATSPI_ROLE_COLOR_CHOOSER,
ATSPI_ROLE_COLUMN_HEADER,
ATSPI_ROLE_COMBO_BOX,
ATSPI_ROLE_DATE_EDITOR,
ATSPI_ROLE_DESKTOP_ICON,
ATSPI_ROLE_DESKTOP_FRAME,
ATSPI_ROLE_DIAL,
ATSPI_ROLE_DIALOG,
ATSPI_ROLE_DIRECTORY_PANE,
ATSPI_ROLE_DRAWING_AREA,
ATSPI_ROLE_FILE_CHOOSER,
ATSPI_ROLE_FILLER,
ATSPI_ROLE_FOCUS_TRAVERSABLE,
ATSPI_ROLE_FONT_CHOOSER,
ATSPI_ROLE_FRAME,
ATSPI_ROLE_GLASS_PANE,
ATSPI_ROLE_HTML_CONTAINER,
ATSPI_ROLE_ICON,
ATSPI_ROLE_IMAGE,
ATSPI_ROLE_INTERNAL_FRAME,
ATSPI_ROLE_LABEL,
ATSPI_ROLE_LAYERED_PANE,
ATSPI_ROLE_LIST,
ATSPI_ROLE_LIST_ITEM,
ATSPI_ROLE_MENU,
ATSPI_ROLE_MENU_BAR,
ATSPI_ROLE_MENU_ITEM,
ATSPI_ROLE_OPTION_PANE,
ATSPI_ROLE_PAGE_TAB,
ATSPI_ROLE_PAGE_TAB_LIST,
ATSPI_ROLE_PANEL,
ATSPI_ROLE_PASSWORD_TEXT,
ATSPI_ROLE_POPUP_MENU,
ATSPI_ROLE_PROGRESS_BAR,
ATSPI_ROLE_PUSH_BUTTON,
ATSPI_ROLE_RADIO_BUTTON,
ATSPI_ROLE_RADIO_MENU_ITEM,
ATSPI_ROLE_ROOT_PANE,
ATSPI_ROLE_ROW_HEADER,
ATSPI_ROLE_SCROLL_BAR,
ATSPI_ROLE_SCROLL_PANE,
ATSPI_ROLE_SEPARATOR,
ATSPI_ROLE_SLIDER,
ATSPI_ROLE_SPIN_BUTTON,
ATSPI_ROLE_SPLIT_PANE,
ATSPI_ROLE_STATUS_BAR,
ATSPI_ROLE_TABLE,
ATSPI_ROLE_TABLE_CELL,
ATSPI_ROLE_TABLE_COLUMN_HEADER,
ATSPI_ROLE_TABLE_ROW_HEADER,
ATSPI_ROLE_TEAROFF_MENU_ITEM,
ATSPI_ROLE_TERMINAL,
ATSPI_ROLE_TEXT,
ATSPI_ROLE_TOGGLE_BUTTON,
ATSPI_ROLE_TOOL_BAR,
ATSPI_ROLE_TOOL_TIP,
ATSPI_ROLE_TREE,
ATSPI_ROLE_TREE_TABLE,
ATSPI_ROLE_UNKNOWN,
ATSPI_ROLE_VIEWPORT,
ATSPI_ROLE_WINDOW,
ATSPI_ROLE_EXTENDED,
ATSPI_ROLE_HEADER,
ATSPI_ROLE_FOOTER,
ATSPI_ROLE_PARAGRAPH,
ATSPI_ROLE_RULER,
ATSPI_ROLE_APPLICATION,
ATSPI_ROLE_AUTOCOMPLETE,
ATSPI_ROLE_EDITBAR,
ATSPI_ROLE_EMBEDDED,
ATSPI_ROLE_ENTRY,
ATSPI_ROLE_CHART,
ATSPI_ROLE_CAPTION,
ATSPI_ROLE_DOCUMENT_FRAME,
ATSPI_ROLE_HEADING,
ATSPI_ROLE_PAGE,
ATSPI_ROLE_SECTION,
ATSPI_ROLE_REDUNDANT_OBJECT,
ATSPI_ROLE_FORM,
ATSPI_ROLE_LINK,
ATSPI_ROLE_INPUT_METHOD_WINDOW,
ATSPI_ROLE_TABLE_ROW,
ATSPI_ROLE_TREE_ITEM,
ATSPI_ROLE_DOCUMENT_SPREADSHEET,
ATSPI_ROLE_DOCUMENT_PRESENTATION,
ATSPI_ROLE_DOCUMENT_TEXT,
ATSPI_ROLE_DOCUMENT_WEB,
ATSPI_ROLE_DOCUMENT_EMAIL,
ATSPI_ROLE_COMMENT,
ATSPI_ROLE_LIST_BOX,
ATSPI_ROLE_GROUPING,
ATSPI_ROLE_IMAGE_MAP,
ATSPI_ROLE_NOTIFICATION,
ATSPI_ROLE_INFO_BAR,
ATSPI_ROLE_LEVEL_BAR,
ATSPI_ROLE_TITLE_BAR,
ATSPI_ROLE_BLOCK_QUOTE,
ATSPI_ROLE_AUDIO,
ATSPI_ROLE_VIDEO,
ATSPI_ROLE_DEFINITION,
ATSPI_ROLE_ARTICLE,
ATSPI_ROLE_LANDMARK,
ATSPI_ROLE_LOG,
ATSPI_ROLE_MARQUEE,
ATSPI_ROLE_MATH,
ATSPI_ROLE_RATING,
ATSPI_ROLE_TIMER,
ATSPI_ROLE_STATIC,
ATSPI_ROLE_MATH_FRACTION,
ATSPI_ROLE_MATH_ROOT,
ATSPI_ROLE_SUBSCRIPT,
ATSPI_ROLE_SUPERSCRIPT,
ATSPI_ROLE_DESCRIPTION_LIST,
ATSPI_ROLE_DESCRIPTION_TERM,
ATSPI_ROLE_DESCRIPTION_VALUE,
ATSPI_ROLE_FOOTNOTE,
ATSPI_ROLE_CONTENT_DELETION,
ATSPI_ROLE_CONTENT_INSERTION,
ATSPI_ROLE_MARK,
ATSPI_ROLE_SUGGESTION,
ATSPI_ROLE_LAST_DEFINED,
} AtspiRole;
typedef enum {
ATSPI_STATE_INVALID,
ATSPI_STATE_ACTIVE,
ATSPI_STATE_ARMED,
ATSPI_STATE_BUSY,
ATSPI_STATE_CHECKED,
ATSPI_STATE_COLLAPSED,
ATSPI_STATE_DEFUNCT,
ATSPI_STATE_EDITABLE,
ATSPI_STATE_ENABLED,
ATSPI_STATE_EXPANDABLE,
ATSPI_STATE_EXPANDED,
ATSPI_STATE_FOCUSABLE,
ATSPI_STATE_FOCUSED,
ATSPI_STATE_HAS_TOOLTIP,
ATSPI_STATE_HORIZONTAL,
ATSPI_STATE_ICONIFIED,
ATSPI_STATE_MODAL,
ATSPI_STATE_MULTI_LINE,
ATSPI_STATE_MULTISELECTABLE,
ATSPI_STATE_OPAQUE,
ATSPI_STATE_PRESSED,
ATSPI_STATE_RESIZABLE,
ATSPI_STATE_SELECTABLE,
ATSPI_STATE_SELECTED,
ATSPI_STATE_SENSITIVE,
ATSPI_STATE_SHOWING,
ATSPI_STATE_SINGLE_LINE,
ATSPI_STATE_STALE,
ATSPI_STATE_TRANSIENT,
ATSPI_STATE_VERTICAL,
ATSPI_STATE_VISIBLE,
ATSPI_STATE_MANAGES_DESCENDANTS,
ATSPI_STATE_INDETERMINATE,
ATSPI_STATE_REQUIRED,
ATSPI_STATE_TRUNCATED,
ATSPI_STATE_ANIMATED,
ATSPI_STATE_INVALID_ENTRY,
ATSPI_STATE_SUPPORTS_AUTOCOMPLETION,
ATSPI_STATE_SELECTABLE_TEXT,
ATSPI_STATE_IS_DEFAULT,
ATSPI_STATE_VISITED,
ATSPI_STATE_CHECKABLE,
ATSPI_STATE_HAS_POPUP,
ATSPI_STATE_READ_ONLY,
ATSPI_STATE_LAST_DEFINED,
} AtspiStateType;
typedef enum {
ATSPI_RELATION_NULL,
ATSPI_RELATION_LABEL_FOR,
ATSPI_RELATION_LABELLED_BY,
ATSPI_RELATION_CONTROLLER_FOR,
ATSPI_RELATION_CONTROLLED_BY,
ATSPI_RELATION_MEMBER_OF,
ATSPI_RELATION_TOOLTIP_FOR,
ATSPI_RELATION_NODE_CHILD_OF,
ATSPI_RELATION_NODE_PARENT_OF,
ATSPI_RELATION_EXTENDED,
ATSPI_RELATION_FLOWS_TO,
ATSPI_RELATION_FLOWS_FROM,
ATSPI_RELATION_SUBWINDOW_OF,
ATSPI_RELATION_EMBEDS,
ATSPI_RELATION_EMBEDDED_BY,
ATSPI_RELATION_POPUP_FOR,
ATSPI_RELATION_PARENT_WINDOW_OF,
ATSPI_RELATION_DESCRIPTION_FOR,
ATSPI_RELATION_DESCRIBED_BY,
ATSPI_RELATION_LAST_DEFINED,
} AtspiRelationType;
typedef enum {
ATSPI_TEXT_BOUNDARY_CHAR,
ATSPI_TEXT_BOUNDARY_WORD_START,
ATSPI_TEXT_BOUNDARY_WORD_END,
ATSPI_TEXT_BOUNDARY_SENTENCE_START,
ATSPI_TEXT_BOUNDARY_SENTENCE_END,
ATSPI_TEXT_BOUNDARY_LINE_START,
ATSPI_TEXT_BOUNDARY_LINE_END,
} AtspiTextBoundaryType;
typedef enum {
ATSPI_TEXT_GRANULARITY_CHAR,
ATSPI_TEXT_GRANULARITY_WORD,
ATSPI_TEXT_GRANULARITY_SENTENCE,
ATSPI_TEXT_GRANULARITY_LINE,
ATSPI_TEXT_GRANULARITY_PARAGRAPH
} AtspiTextGranularity;
G_END_DECLS

602
gtk/a11y/gtkatspiroot.c Normal file
View File

@@ -0,0 +1,602 @@
/* gtkatspiroot.c: AT-SPI root object
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkatspirootprivate.h"
#include "gtkatspicontextprivate.h"
#include "gtkatspiprivate.h"
#include "gtkatspiutilsprivate.h"
#include "gtkdebug.h"
#include "gtkwindow.h"
#include "a11y/atspi/atspi-accessible.h"
#include "a11y/atspi/atspi-application.h"
#include <locale.h>
#include <glib/gi18n-lib.h>
#include <gio/gio.h>
#define ATSPI_VERSION "2.1"
#define ATSPI_PATH_PREFIX "/org/a11y/atspi"
#define ATSPI_ROOT_PATH ATSPI_PATH_PREFIX "/accessible/root"
#define ATSPI_CACHE_PATH ATSPI_PATH_PREFIX "/cache"
struct _GtkAtSpiRoot
{
GObject parent_instance;
char *bus_address;
GDBusConnection *connection;
const char *root_path;
const char *toolkit_name;
const char *version;
const char *atspi_version;
char *desktop_name;
char *desktop_path;
gint32 application_id;
GtkAtSpiCache *cache;
GListModel *toplevels;
};
enum
{
PROP_BUS_ADDRESS = 1,
N_PROPS
};
static GParamSpec *obj_props[N_PROPS];
G_DEFINE_TYPE (GtkAtSpiRoot, gtk_at_spi_root, G_TYPE_OBJECT)
static void
gtk_at_spi_root_finalize (GObject *gobject)
{
GtkAtSpiRoot *self = GTK_AT_SPI_ROOT (gobject);
g_free (self->bus_address);
g_free (self->desktop_name);
g_free (self->desktop_path);
G_OBJECT_CLASS (gtk_at_spi_root_parent_class)->dispose (gobject);
}
static void
gtk_at_spi_root_dispose (GObject *gobject)
{
GtkAtSpiRoot *self = GTK_AT_SPI_ROOT (gobject);
g_clear_object (&self->cache);
g_clear_object (&self->connection);
G_OBJECT_CLASS (gtk_at_spi_root_parent_class)->dispose (gobject);
}
static void
gtk_at_spi_root_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkAtSpiRoot *self = GTK_AT_SPI_ROOT (gobject);
switch (prop_id)
{
case PROP_BUS_ADDRESS:
self->bus_address = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
gtk_at_spi_root_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkAtSpiRoot *self = GTK_AT_SPI_ROOT (gobject);
switch (prop_id)
{
case PROP_BUS_ADDRESS:
g_value_set_string (value, self->bus_address);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
handle_application_method (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
if (g_strcmp0 (method_name, "GetLocale") == 0)
{
guint lctype;
const char *locale;
int types[] = {
LC_MESSAGES, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME
};
g_variant_get (parameters, "(u)", &lctype);
if (lctype >= G_N_ELEMENTS (types))
{
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
"Not a known locale facet: %u", lctype);
return;
}
locale = setlocale (types[lctype], NULL);
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", locale));
}
}
static GVariant *
handle_application_get_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data)
{
GtkAtSpiRoot *self = user_data;
GVariant *res = NULL;
if (g_strcmp0 (property_name, "Id") == 0)
res = g_variant_new_int32 (self->application_id);
else if (g_strcmp0 (property_name, "ToolkitName") == 0)
res = g_variant_new_string (self->toolkit_name);
else if (g_strcmp0 (property_name, "Version") == 0)
res = g_variant_new_string (self->version);
else if (g_strcmp0 (property_name, "AtspiVersion") == 0)
res = g_variant_new_string (self->atspi_version);
else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Unknown property '%s'", property_name);
return res;
}
static gboolean
handle_application_set_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GVariant *value,
GError **error,
gpointer user_data)
{
GtkAtSpiRoot *self = user_data;
if (g_strcmp0 (property_name, "Id") == 0)
{
g_variant_get (value, "i", &(self->application_id));
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Invalid property '%s'", property_name);
return FALSE;
}
return TRUE;
}
static void
handle_accessible_method (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
GtkAtSpiRoot *self = user_data;
if (g_strcmp0 (method_name, "GetRole") == 0)
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", ATSPI_ROLE_APPLICATION));
else if (g_strcmp0 (method_name, "GetRoleName") == 0)
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", "application"));
else if (g_strcmp0 (method_name, "GetLocalizedRoleName") == 0)
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", C_("accessibility", "application")));
else if (g_strcmp0 (method_name, "GetState") == 0)
{
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(au)"));
g_variant_builder_open (&builder, G_VARIANT_TYPE ("au"));
g_variant_builder_add (&builder, "u", 0);
g_variant_builder_add (&builder, "u", 0);
g_variant_builder_close (&builder);
g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
}
else if (g_strcmp0 (method_name, "GetAttributes") == 0)
{
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(a{ss})"));
g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{ss}"));
g_variant_builder_add (&builder, "{ss}", "toolkit", "GTK");
g_variant_builder_close (&builder);
g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
}
else if (g_strcmp0 (method_name, "GetApplication") == 0)
{
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("((so))",
self->desktop_name,
self->desktop_path));
}
else if (g_strcmp0 (method_name, "GetChildAtIndex") == 0)
{
int idx, real_idx = 0;
g_variant_get (parameters, "(i)", &idx);
GtkWidget *window = NULL;
guint n_toplevels = g_list_model_get_n_items (self->toplevels);
for (guint i = 0; i < n_toplevels; i++)
{
window = g_list_model_get_item (self->toplevels, i);
g_object_unref (window);
if (!gtk_widget_get_visible (window))
continue;
if (real_idx == idx)
break;
real_idx += 1;
}
if (window == NULL)
return;
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (window));
const char *name = g_dbus_connection_get_unique_name (self->connection);
const char *path = gtk_at_spi_context_get_context_path (GTK_AT_SPI_CONTEXT (context));
g_dbus_method_invocation_return_value (invocation, g_variant_new ("((so))", name, path));
}
else if (g_strcmp0 (method_name, "GetChildren") == 0)
{
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a(so)"));
guint n_toplevels = g_list_model_get_n_items (self->toplevels);
for (guint i = 0; i < n_toplevels; i++)
{
GtkWidget *window = g_list_model_get_item (self->toplevels, i);
g_object_unref (window);
if (!gtk_widget_get_visible (window))
continue;
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (window));
const char *name = g_dbus_connection_get_unique_name (self->connection);
const char *path = gtk_at_spi_context_get_context_path (GTK_AT_SPI_CONTEXT (context));
g_variant_builder_add (&builder, "(so)", name, path);
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a(so))", &builder));
}
else if (g_strcmp0 (method_name, "GetIndexInParent") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", -1));
}
else if (g_strcmp0 (method_name, "GetRelationSet") == 0)
{
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a(ua(so))"));
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a(ua(so)))", &builder));
}
else if (g_strcmp0 (method_name, "GetInterfaces") == 0)
{
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("as"));
g_variant_builder_add (&builder, "s", "org.a11y.atspi.Accessible");
g_variant_builder_add (&builder, "s", "org.a11y.atspi.Application");
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(as)", &builder));
}
}
static GVariant *
handle_accessible_get_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data)
{
GtkAtSpiRoot *self = user_data;
GVariant *res = NULL;
if (g_strcmp0 (property_name, "Name") == 0)
res = g_variant_new_string (g_get_prgname () ? g_get_prgname () : "Unnamed");
else if (g_strcmp0 (property_name, "Description") == 0)
res = g_variant_new_string (g_get_application_name () ? g_get_application_name () : "No description");
else if (g_strcmp0 (property_name, "Locale") == 0)
res = g_variant_new_string (setlocale (LC_MESSAGES, NULL));
else if (g_strcmp0 (property_name, "AccessibleId") == 0)
res = g_variant_new_string ("");
else if (g_strcmp0 (property_name, "Parent") == 0)
res = g_variant_new ("(so)", self->desktop_name, self->desktop_path);
else if (g_strcmp0 (property_name, "ChildCount") == 0)
{
guint n_toplevels = g_list_model_get_n_items (self->toplevels);
int n_children = 0;
for (guint i = 0; i < n_toplevels; i++)
{
GtkWidget *window = g_list_model_get_item (self->toplevels, i);
if (gtk_widget_get_visible (window))
n_children += 1;
g_object_unref (window);
}
res = g_variant_new_int32 (n_children);
}
else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Unknown property '%s'", property_name);
return res;
}
static const GDBusInterfaceVTable root_application_vtable = {
handle_application_method,
handle_application_get_property,
handle_application_set_property,
};
static const GDBusInterfaceVTable root_accessible_vtable = {
handle_accessible_method,
handle_accessible_get_property,
NULL,
};
static void
on_registration_reply (GObject *gobject,
GAsyncResult *result,
gpointer user_data)
{
GtkAtSpiRoot *self = user_data;
GError *error = NULL;
GVariant *reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (gobject), result, &error);
if (error != NULL)
{
g_critical ("Unable to register the application: %s", error->message);
g_error_free (error);
return;
}
if (reply != NULL)
{
g_variant_get (reply, "((so))",
&self->desktop_name,
&self->desktop_path);
g_variant_unref (reply);
GTK_NOTE (A11Y, g_message ("Connected to the a11y registry at (%s, %s)",
self->desktop_name,
self->desktop_path));
}
/* Register the cache object */
self->cache = gtk_at_spi_cache_new (self->connection, ATSPI_CACHE_PATH);
/* Monitor the top levels */
self->toplevels = gtk_window_get_toplevels ();
}
static void
gtk_at_spi_root_register (GtkAtSpiRoot *self)
{
/* Register the root element; every application has a single root, so we only
* need to do this once.
*
* The root element is used to advertise our existence on the accessibility
* bus, and it's the entry point to the accessible objects tree.
*
* The announcement is split into two phases:
*
* 1. we register the org.a11y.atspi.Application and org.a11y.atspi.Accessible
* interfaces at the well-known object path
* 2. we invoke the org.a11y.atspi.Socket.Embed method with the connection's
* unique name and the object path
* 3. the ATSPI registry daemon will set the org.a11y.atspi.Application.Id
* property on the given object path
* 4. the registration concludes when the Embed method returns us the desktop
* name and object path
*/
self->toolkit_name = "GTK";
self->version = PACKAGE_VERSION;
self->atspi_version = ATSPI_VERSION;
self->root_path = ATSPI_ROOT_PATH;
g_dbus_connection_register_object (self->connection,
self->root_path,
(GDBusInterfaceInfo *) &atspi_application_interface,
&root_application_vtable,
self,
NULL,
NULL);
g_dbus_connection_register_object (self->connection,
self->root_path,
(GDBusInterfaceInfo *) &atspi_accessible_interface,
&root_accessible_vtable,
self,
NULL,
NULL);
GTK_NOTE (A11Y, g_message ("Registering (%s, %s) on the a11y bus",
g_dbus_connection_get_unique_name (self->connection),
self->root_path));
g_dbus_connection_call (self->connection,
"org.a11y.atspi.Registry",
ATSPI_ROOT_PATH,
"org.a11y.atspi.Socket",
"Embed",
g_variant_new ("((so))",
g_dbus_connection_get_unique_name (self->connection),
self->root_path
),
G_VARIANT_TYPE ("((so))"),
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
on_registration_reply,
self);
}
static void
gtk_at_spi_root_constructed (GObject *gobject)
{
GtkAtSpiRoot *self = GTK_AT_SPI_ROOT (gobject);
GError *error = NULL;
/* The accessibility bus is a fully managed bus */
self->connection =
g_dbus_connection_new_for_address_sync (self->bus_address,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
NULL, NULL,
&error);
if (error != NULL)
{
g_critical ("Unable to connect to the accessibility bus at '%s': %s",
self->bus_address,
error->message);
g_error_free (error);
goto out;
}
gtk_at_spi_root_register (self);
out:
G_OBJECT_CLASS (gtk_at_spi_root_parent_class)->constructed (gobject);
}
static void
gtk_at_spi_root_class_init (GtkAtSpiRootClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = gtk_at_spi_root_constructed;
gobject_class->set_property = gtk_at_spi_root_set_property;
gobject_class->get_property = gtk_at_spi_root_get_property;
gobject_class->dispose = gtk_at_spi_root_dispose;
gobject_class->finalize = gtk_at_spi_root_finalize;
obj_props[PROP_BUS_ADDRESS] =
g_param_spec_string ("bus-address", NULL, NULL,
NULL,
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, obj_props);
}
static void
gtk_at_spi_root_init (GtkAtSpiRoot *self)
{
}
GtkAtSpiRoot *
gtk_at_spi_root_new (const char *bus_address)
{
g_return_val_if_fail (bus_address != NULL, NULL);
return g_object_new (GTK_TYPE_AT_SPI_ROOT,
"bus-address", bus_address,
NULL);
}
GDBusConnection *
gtk_at_spi_root_get_connection (GtkAtSpiRoot *self)
{
g_return_val_if_fail (GTK_IS_AT_SPI_ROOT (self), NULL);
return self->connection;
}
GtkAtSpiCache *
gtk_at_spi_root_get_cache (GtkAtSpiRoot *self)
{
g_return_val_if_fail (GTK_IS_AT_SPI_ROOT (self), NULL);
return self->cache;
}
/*< private >
* gtk_at_spi_root_to_ref:
* @self: a #GtkAtSpiRoot
*
* Returns an ATSPI object reference for the #GtkAtSpiRoot node.
*
* Returns: (transfer floating): a #GVariant with the root reference
*/
GVariant *
gtk_at_spi_root_to_ref (GtkAtSpiRoot *self)
{
g_return_val_if_fail (GTK_IS_AT_SPI_ROOT (self), NULL);
if (self->desktop_path == NULL)
return gtk_at_spi_null_ref ();
return g_variant_new ("(so)", self->desktop_name, self->desktop_path);
}

View File

@@ -0,0 +1,45 @@
/* gtkatspirootprivate.h: AT-SPI root object
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gio/gio.h>
#include "gtkatspicacheprivate.h"
G_BEGIN_DECLS
#define GTK_TYPE_AT_SPI_ROOT (gtk_at_spi_root_get_type())
G_DECLARE_FINAL_TYPE (GtkAtSpiRoot, gtk_at_spi_root, GTK, AT_SPI_ROOT, GObject)
GtkAtSpiRoot *
gtk_at_spi_root_new (const char *bus_address);
GDBusConnection *
gtk_at_spi_root_get_connection (GtkAtSpiRoot *self);
GtkAtSpiCache *
gtk_at_spi_root_get_cache (GtkAtSpiRoot *self);
GVariant *
gtk_at_spi_root_to_ref (GtkAtSpiRoot *self);
G_END_DECLS

1151
gtk/a11y/gtkatspitext.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,984 @@
/* gtkatspitextbuffer.c - GtkTextBuffer-related utilities for AT-SPI
*
* Copyright (c) 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
*/
#include "config.h"
#include "gtkatspitextbufferprivate.h"
#include "gtkatspipangoprivate.h"
#include "gtktextviewprivate.h"
static const char *
gtk_justification_to_string (GtkJustification just)
{
switch (just)
{
case GTK_JUSTIFY_LEFT:
return "left";
case GTK_JUSTIFY_RIGHT:
return "right";
case GTK_JUSTIFY_CENTER:
return "center";
case GTK_JUSTIFY_FILL:
return "fill";
default:
g_assert_not_reached ();
}
}
static const char *
gtk_text_direction_to_string (GtkTextDirection direction)
{
switch (direction)
{
case GTK_TEXT_DIR_NONE:
return "none";
case GTK_TEXT_DIR_LTR:
return "ltr";
case GTK_TEXT_DIR_RTL:
return "rtl";
default:
g_assert_not_reached ();
}
}
void
gtk_text_view_add_default_attributes (GtkTextView *view,
GVariantBuilder *builder)
{
GtkTextAttributes *text_attrs;
PangoFontDescription *font;
char *value;
text_attrs = gtk_text_view_get_default_attributes (view);
font = text_attrs->font;
if (font)
gtk_pango_get_font_attributes (font, builder);
g_variant_builder_add (builder, "{ss}", "justification",
gtk_justification_to_string (text_attrs->justification));
g_variant_builder_add (builder, "{ss}", "direction",
gtk_text_direction_to_string (text_attrs->direction));
g_variant_builder_add (builder, "{ss}", "wrap-mode",
pango_wrap_mode_to_string (text_attrs->wrap_mode));
g_variant_builder_add (builder, "{ss}", "editable",
text_attrs->editable ? "true" : "false");
g_variant_builder_add (builder, "{ss}", "invisible",
text_attrs->invisible ? "true" : "false");
g_variant_builder_add (builder, "{ss}", "bg-full-height",
text_attrs->bg_full_height ? "true" : "false");
g_variant_builder_add (builder, "{ss}", "strikethrough",
text_attrs->appearance.strikethrough ? "true" : "false");
g_variant_builder_add (builder, "{ss}", "underline",
pango_underline_to_string (text_attrs->appearance.underline));
value = g_strdup_printf ("%u,%u,%u",
(guint)(text_attrs->appearance.bg_rgba->red * 65535),
(guint)(text_attrs->appearance.bg_rgba->green * 65535),
(guint)(text_attrs->appearance.bg_rgba->blue * 65535));
g_variant_builder_add (builder, "{ss}", "bg-color", value);
g_free (value);
value = g_strdup_printf ("%u,%u,%u",
(guint)(text_attrs->appearance.fg_rgba->red * 65535),
(guint)(text_attrs->appearance.fg_rgba->green * 65535),
(guint)(text_attrs->appearance.fg_rgba->blue * 65535));
g_variant_builder_add (builder, "{ss}", "bg-color", value);
g_free (value);
value = g_strdup_printf ("%g", text_attrs->font_scale);
g_variant_builder_add (builder, "{ss}", "scale", value);
g_free (value);
value = g_strdup ((gchar *)(text_attrs->language));
g_variant_builder_add (builder, "{ss}", "language", value);
g_free (value);
value = g_strdup_printf ("%i", text_attrs->appearance.rise);
g_variant_builder_add (builder, "{ss}", "rise", value);
g_free (value);
value = g_strdup_printf ("%i", text_attrs->pixels_inside_wrap);
g_variant_builder_add (builder, "{ss}", "pixels-inside-wrap", value);
g_free (value);
value = g_strdup_printf ("%i", text_attrs->pixels_below_lines);
g_variant_builder_add (builder, "{ss}", "pixels-below-lines", value);
g_free (value);
value = g_strdup_printf ("%i", text_attrs->pixels_above_lines);
g_variant_builder_add (builder, "{ss}", "pixels-above-lines", value);
g_free (value);
value = g_strdup_printf ("%i", text_attrs->indent);
g_variant_builder_add (builder, "{ss}", "indent", value);
g_free (value);
value = g_strdup_printf ("%i", text_attrs->left_margin);
g_variant_builder_add (builder, "{ss}", "left-margin", value);
g_free (value);
value = g_strdup_printf ("%i", text_attrs->right_margin);
g_variant_builder_add (builder, "{ss}", "right-margin", value);
g_free (value);
gtk_text_attributes_unref (text_attrs);
}
void
gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
GVariantBuilder *builder,
int offset,
int *start_offset,
int *end_offset)
{
GtkTextIter iter;
GSList *tags, *temp_tags;
gdouble scale = 1;
gboolean val_set = FALSE;
gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
*end_offset = gtk_text_iter_get_offset (&iter);
gtk_text_iter_backward_to_tag_toggle (&iter, NULL);
*start_offset = gtk_text_iter_get_offset (&iter);
gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
tags = gtk_text_iter_get_tags (&iter);
tags = g_slist_reverse (tags);
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
PangoStyle style;
g_object_get (tag,
"style-set", &val_set,
"style", &style,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "style", pango_style_to_string (style));
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
PangoVariant variant;
g_object_get (tag,
"variant-set", &val_set,
"variant", &variant,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "variant", pango_variant_to_string (variant));
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
PangoStretch stretch;
g_object_get (tag,
"stretch-set", &val_set,
"stretch", &stretch,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "stretch", pango_stretch_to_string (stretch));
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
GtkJustification justification;
g_object_get (tag,
"justification-set", &val_set,
"justification", &justification,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "justification", gtk_justification_to_string (justification));
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
GtkTextDirection direction;
g_object_get (tag, "direction", &direction, NULL);
if (direction != GTK_TEXT_DIR_NONE)
{
val_set = TRUE;
g_variant_builder_add (builder, "{ss}", "direction", gtk_text_direction_to_string (direction));
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
GtkWrapMode wrap_mode;
g_object_get (tag,
"wrap-mode-set", &val_set,
"wrap-mode", &wrap_mode,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "wrap-mode", pango_wrap_mode_to_string (wrap_mode));
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
g_object_get (tag, "foreground-set", &val_set, NULL);
if (val_set)
{
GdkRGBA *rgba;
char *value;
g_object_get (tag, "foreground", &rgba, NULL);
value = g_strdup_printf ("%u,%u,%u",
(guint) rgba->red * 65535,
(guint) rgba->green * 65535,
(guint) rgba->blue * 65535);
gdk_rgba_free (rgba);
g_variant_builder_add (builder, "{ss}", "fg-color", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
g_object_get (tag, "background-set", &val_set, NULL);
if (val_set)
{
GdkRGBA *rgba;
char *value;
g_object_get (tag, "background-rgba", &rgba, NULL);
value = g_strdup_printf ("%u,%u,%u",
(guint) rgba->red * 65535,
(guint) rgba->green * 65535,
(guint) rgba->blue * 65535);
gdk_rgba_free (rgba);
g_variant_builder_add (builder, "{ss}", "bg-color", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
g_object_get (tag, "family-set", &val_set, NULL);
if (val_set)
{
char *value;
g_object_get (tag, "family", &value, NULL);
g_variant_builder_add (builder, "{ss}", "family-name", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
g_object_get (tag, "language-set", &val_set, NULL);
if (val_set)
{
char *value;
g_object_get (tag, "language", &value, NULL);
g_variant_builder_add (builder, "{ss}", "language", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int weight;
g_object_get (tag,
"weight-set", &val_set,
"weight", &weight,
NULL);
if (val_set)
{
char *value;
value = g_strdup_printf ("%d", weight);
g_variant_builder_add (builder, "{ss}", "weight", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
/* scale is special as the effective value is the product
* of all specified values
*/
temp_tags = tags;
while (temp_tags)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
gboolean scale_set;
g_object_get (tag, "scale-set", &scale_set, NULL);
if (scale_set)
{
double font_scale;
g_object_get (tag, "scale", &font_scale, NULL);
val_set = TRUE;
scale *= font_scale;
}
temp_tags = temp_tags->next;
}
if (val_set)
{
char *value = g_strdup_printf ("%g", scale);
g_variant_builder_add (builder, "{ss}", "scale", value);
g_free (value);
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int size;
g_object_get (tag,
"size-set", &val_set,
"size", &size,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", size);
g_variant_builder_add (builder, "{ss}", "size", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
gboolean strikethrough;
g_object_get (tag,
"strikethrough-set", &val_set,
"strikethrough", &strikethrough,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "strikethrough", strikethrough ? "true" : "false");
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
PangoUnderline underline;
g_object_get (tag,
"underline-set", &val_set,
"underline", &underline,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "underline",
pango_underline_to_string (underline));
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int rise;
g_object_get (tag,
"rise-set", &val_set,
"rise", &rise,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", rise);
g_variant_builder_add (builder, "{ss}", "rise", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
gboolean bg_full_height;
g_object_get (tag,
"background-full-height-set", &val_set,
"background-full-height", &bg_full_height,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "bg-full-height", bg_full_height ? "true" : "false");
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int pixels;
g_object_get (tag,
"pixels-inside-wrap-set", &val_set,
"pixels-inside-wrap", &pixels,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", pixels);
g_variant_builder_add (builder, "{ss}", "pixels-inside-wrap", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int pixels;
g_object_get (tag,
"pixels-below-lines-set", &val_set,
"pixels-below-lines", &pixels,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", pixels);
g_variant_builder_add (builder, "{ss}", "pixels-below-lines", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int pixels;
g_object_get (tag,
"pixels-above-lines-set", &val_set,
"pixels-above-lines", &pixels,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", pixels);
g_variant_builder_add (builder, "{ss}", "pixels-above-lines", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
gboolean editable;
g_object_get (tag,
"editable-set", &val_set,
"editable", &editable,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "editable", editable ? "true" : "false");
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
gboolean invisible;
g_object_get (tag,
"invisible-set", &val_set,
"invisible", &invisible,
NULL);
if (val_set)
g_variant_builder_add (builder, "{ss}", "invisible", invisible ? "true" : "false");
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int indent;
g_object_get (tag,
"indent-set", &val_set,
"indent", &indent,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", indent);
g_variant_builder_add (builder, "{ss}", "indent", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int margin;
g_object_get (tag,
"right-margin-set", &val_set,
"right-margin", &margin,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", margin);
g_variant_builder_add (builder, "{ss}", "right-margin", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
temp_tags = tags;
while (temp_tags && !val_set)
{
GtkTextTag *tag = GTK_TEXT_TAG (temp_tags->data);
int margin;
g_object_get (tag,
"left-margin-set", &val_set,
"left-margin", &margin,
NULL);
if (val_set)
{
char *value = g_strdup_printf ("%i", margin);
g_variant_builder_add (builder, "{ss}", "left-margin", value);
g_free (value);
}
temp_tags = temp_tags->next;
}
val_set = FALSE;
g_slist_free (tags);
}
char *
gtk_text_view_get_text_before (GtkTextView *view,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset)
{
GtkTextBuffer *buffer;
GtkTextIter pos, start, end;
buffer = gtk_text_view_get_buffer (view);
gtk_text_buffer_get_iter_at_offset (buffer, &pos, offset);
start = end = pos;
switch (boundary_type)
{
case ATSPI_TEXT_BOUNDARY_CHAR:
gtk_text_iter_backward_char (&start);
break;
case ATSPI_TEXT_BOUNDARY_WORD_START:
if (!gtk_text_iter_starts_word (&start))
gtk_text_iter_backward_word_start (&start);
end = start;
gtk_text_iter_backward_word_start (&start);
break;
case ATSPI_TEXT_BOUNDARY_WORD_END:
if (gtk_text_iter_inside_word (&start) &&
!gtk_text_iter_starts_word (&start))
gtk_text_iter_backward_word_start (&start);
while (!gtk_text_iter_ends_word (&start))
{
if (!gtk_text_iter_backward_char (&start))
break;
}
end = start;
gtk_text_iter_backward_word_start (&start);
while (!gtk_text_iter_ends_word (&start))
{
if (!gtk_text_iter_backward_char (&start))
break;
}
break;
case ATSPI_TEXT_BOUNDARY_SENTENCE_START:
if (!gtk_text_iter_starts_sentence (&start))
gtk_text_iter_backward_sentence_start (&start);
end = start;
gtk_text_iter_backward_sentence_start (&start);
break;
case ATSPI_TEXT_BOUNDARY_SENTENCE_END:
if (gtk_text_iter_inside_sentence (&start) &&
!gtk_text_iter_starts_sentence (&start))
gtk_text_iter_backward_sentence_start (&start);
while (!gtk_text_iter_ends_sentence (&start))
{
if (!gtk_text_iter_backward_char (&start))
break;
}
end = start;
gtk_text_iter_backward_sentence_start (&start);
while (!gtk_text_iter_ends_sentence (&start))
{
if (!gtk_text_iter_backward_char (&start))
break;
}
break;
case ATSPI_TEXT_BOUNDARY_LINE_START:
gtk_text_view_backward_display_line_start (view, &start);
end = start;
gtk_text_view_backward_display_line (view, &start);
gtk_text_view_backward_display_line_start (view, &start);
break;
case ATSPI_TEXT_BOUNDARY_LINE_END:
gtk_text_view_backward_display_line_start (view, &start);
if (!gtk_text_iter_is_start (&start))
{
gtk_text_view_backward_display_line (view, &start);
end = start;
gtk_text_view_forward_display_line_end (view, &end);
if (!gtk_text_iter_is_start (&start))
{
if (gtk_text_view_backward_display_line (view, &start))
gtk_text_view_forward_display_line_end (view, &start);
else
gtk_text_iter_set_offset (&start, 0);
}
}
else
end = start;
break;
default:
g_assert_not_reached ();
}
*start_offset = gtk_text_iter_get_offset (&start);
*end_offset = gtk_text_iter_get_offset (&end);
return gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
}
char *
gtk_text_view_get_text_at (GtkTextView *view,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset)
{
GtkTextBuffer *buffer;
GtkTextIter pos, start, end;
buffer = gtk_text_view_get_buffer (view);
gtk_text_buffer_get_iter_at_offset (buffer, &pos, offset);
start = end = pos;
switch (boundary_type)
{
case ATSPI_TEXT_BOUNDARY_CHAR:
gtk_text_iter_forward_char (&end);
break;
case ATSPI_TEXT_BOUNDARY_WORD_START:
if (!gtk_text_iter_starts_word (&start))
gtk_text_iter_backward_word_start (&start);
if (gtk_text_iter_inside_word (&end))
gtk_text_iter_forward_word_end (&end);
while (!gtk_text_iter_starts_word (&end))
{
if (!gtk_text_iter_forward_char (&end))
break;
}
break;
case ATSPI_TEXT_BOUNDARY_WORD_END:
if (gtk_text_iter_inside_word (&start) &&
!gtk_text_iter_starts_word (&start))
gtk_text_iter_backward_word_start (&start);
while (!gtk_text_iter_ends_word (&start))
{
if (!gtk_text_iter_backward_char (&start))
break;
}
gtk_text_iter_forward_word_end (&end);
break;
case ATSPI_TEXT_BOUNDARY_SENTENCE_START:
if (!gtk_text_iter_starts_sentence (&start))
gtk_text_iter_backward_sentence_start (&start);
if (gtk_text_iter_inside_sentence (&end))
gtk_text_iter_forward_sentence_end (&end);
while (!gtk_text_iter_starts_sentence (&end))
{
if (!gtk_text_iter_forward_char (&end))
break;
}
break;
case ATSPI_TEXT_BOUNDARY_SENTENCE_END:
if (gtk_text_iter_inside_sentence (&start) &&
!gtk_text_iter_starts_sentence (&start))
gtk_text_iter_backward_sentence_start (&start);
while (!gtk_text_iter_ends_sentence (&start))
{
if (!gtk_text_iter_backward_char (&start))
break;
}
gtk_text_iter_forward_sentence_end (&end);
break;
case ATSPI_TEXT_BOUNDARY_LINE_START:
gtk_text_view_backward_display_line_start (view, &start);
gtk_text_view_forward_display_line (view, &end);
break;
case ATSPI_TEXT_BOUNDARY_LINE_END:
gtk_text_view_backward_display_line_start (view, &start);
if (!gtk_text_iter_is_start (&start))
{
gtk_text_view_backward_display_line (view, &start);
gtk_text_view_forward_display_line_end (view, &start);
}
gtk_text_view_forward_display_line_end (view, &end);
break;
default:
g_assert_not_reached ();
}
*start_offset = gtk_text_iter_get_offset (&start);
*end_offset = gtk_text_iter_get_offset (&end);
return gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
}
char *
gtk_text_view_get_text_after (GtkTextView *view,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset)
{
GtkTextBuffer *buffer;
GtkTextIter pos, start, end;
buffer = gtk_text_view_get_buffer (view);
gtk_text_buffer_get_iter_at_offset (buffer, &pos, offset);
start = end = pos;
switch (boundary_type)
{
case ATSPI_TEXT_BOUNDARY_CHAR:
gtk_text_iter_forward_char (&start);
gtk_text_iter_forward_chars (&end, 2);
break;
case ATSPI_TEXT_BOUNDARY_WORD_START:
if (gtk_text_iter_inside_word (&end))
gtk_text_iter_forward_word_end (&end);
while (!gtk_text_iter_starts_word (&end))
{
if (!gtk_text_iter_forward_char (&end))
break;
}
start = end;
if (!gtk_text_iter_is_end (&end))
{
gtk_text_iter_forward_word_end (&end);
while (!gtk_text_iter_starts_word (&end))
{
if (!gtk_text_iter_forward_char (&end))
break;
}
}
break;
case ATSPI_TEXT_BOUNDARY_WORD_END:
gtk_text_iter_forward_word_end (&end);
start = end;
if (!gtk_text_iter_is_end (&end))
gtk_text_iter_forward_word_end (&end);
break;
case ATSPI_TEXT_BOUNDARY_SENTENCE_START:
if (gtk_text_iter_inside_sentence (&end))
gtk_text_iter_forward_sentence_end (&end);
while (!gtk_text_iter_starts_sentence (&end))
{
if (!gtk_text_iter_forward_char (&end))
break;
}
start = end;
if (!gtk_text_iter_is_end (&end))
{
gtk_text_iter_forward_sentence_end (&end);
while (!gtk_text_iter_starts_sentence (&end))
{
if (!gtk_text_iter_forward_char (&end))
break;
}
}
break;
case ATSPI_TEXT_BOUNDARY_SENTENCE_END:
gtk_text_iter_forward_sentence_end (&end);
start = end;
if (!gtk_text_iter_is_end (&end))
gtk_text_iter_forward_sentence_end (&end);
break;
case ATSPI_TEXT_BOUNDARY_LINE_START:
gtk_text_view_forward_display_line (view, &end);
start = end;
gtk_text_view_forward_display_line (view, &end);
break;
case ATSPI_TEXT_BOUNDARY_LINE_END:
gtk_text_view_forward_display_line_end (view, &end);
start = end;
gtk_text_view_forward_display_line (view, &end);
gtk_text_view_forward_display_line_end (view, &end);
break;
default:
g_assert_not_reached ();
}
*start_offset = gtk_text_iter_get_offset (&start);
*end_offset = gtk_text_iter_get_offset (&end);
return gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
}
char *
gtk_text_view_get_string_at (GtkTextView *view,
int offset,
AtspiTextGranularity granularity,
int *start_offset,
int *end_offset)
{
GtkTextBuffer *buffer;
GtkTextIter pos, start, end;
buffer = gtk_text_view_get_buffer (view);
gtk_text_buffer_get_iter_at_offset (buffer, &pos, offset);
start = end = pos;
if (granularity == ATSPI_TEXT_GRANULARITY_CHAR)
{
gtk_text_iter_forward_char (&end);
}
else if (granularity == ATSPI_TEXT_GRANULARITY_WORD)
{
if (!gtk_text_iter_starts_word (&start))
gtk_text_iter_backward_word_start (&start);
gtk_text_iter_forward_word_end (&end);
}
else if (granularity == ATSPI_TEXT_GRANULARITY_SENTENCE)
{
if (!gtk_text_iter_starts_sentence (&start))
gtk_text_iter_backward_sentence_start (&start);
gtk_text_iter_forward_sentence_end (&end);
}
else if (granularity == ATSPI_TEXT_GRANULARITY_LINE)
{
if (!gtk_text_view_starts_display_line (view, &start))
gtk_text_view_backward_display_line (view, &start);
gtk_text_view_forward_display_line_end (view, &end);
}
else if (granularity == ATSPI_TEXT_GRANULARITY_PARAGRAPH)
{
gtk_text_iter_set_line_offset (&start, 0);
gtk_text_iter_forward_to_line_end (&end);
}
*start_offset = gtk_text_iter_get_offset (&start);
*end_offset = gtk_text_iter_get_offset (&end);
return gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
}

View File

@@ -0,0 +1,54 @@
/* gtkatspitextbufferprivate.h: Utilities for GtkTextBuffer and AT-SPI
* Copyright 2020 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "gtkatspiprivate.h"
#include "gtktextview.h"
G_BEGIN_DECLS
void gtk_text_view_add_default_attributes (GtkTextView *view,
GVariantBuilder *builder);
void gtk_text_buffer_get_run_attributes (GtkTextBuffer *buffer,
GVariantBuilder *builder,
int offset,
int *start_offset,
int *end_offset);
char *gtk_text_view_get_text_before (GtkTextView *view,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset);
char *gtk_text_view_get_text_at (GtkTextView *view,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset);
char *gtk_text_view_get_text_after (GtkTextView *view,
int offset,
AtspiTextBoundaryType boundary_type,
int *start_offset,
int *end_offset);
char *gtk_text_view_get_string_at (GtkTextView *view,
int offset,
AtspiTextGranularity granularity,
int *start_offset,
int *end_offset);
G_END_DECLS

View File

@@ -0,0 +1,30 @@
/* gtkatspitextprivate.h: AT-SPI Text implementation
*
* Copyright 2020 Red Hat, Inc.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gio/gio.h>
#include "gtkwidget.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_text_vtable (GtkWidget *widget);
G_END_DECLS

283
gtk/a11y/gtkatspiutils.c Normal file
View File

@@ -0,0 +1,283 @@
/* gtkatspiutils.c: Shared utilities for ATSPI
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkatspiutilsprivate.h"
/*< private >
* gtk_accessible_role_to_atspi_role:
* @role: a #GtkAccessibleRole
*
* Converts a #GtkAccessibleRole value to the equivalent ATSPI role.
*
* Returns: an #AtspiRole
*/
AtspiRole
gtk_accessible_role_to_atspi_role (GtkAccessibleRole role)
{
switch (role)
{
case GTK_ACCESSIBLE_ROLE_ALERT:
return ATSPI_ROLE_ALERT;
case GTK_ACCESSIBLE_ROLE_ALERT_DIALOG:
return ATSPI_ROLE_DIALOG;
case GTK_ACCESSIBLE_ROLE_BANNER:
break;
case GTK_ACCESSIBLE_ROLE_BUTTON:
return ATSPI_ROLE_PUSH_BUTTON;
case GTK_ACCESSIBLE_ROLE_CAPTION:
return ATSPI_ROLE_CAPTION;
case GTK_ACCESSIBLE_ROLE_CELL:
return ATSPI_ROLE_TABLE_CELL;
case GTK_ACCESSIBLE_ROLE_CHECKBOX:
return ATSPI_ROLE_CHECK_BOX;
case GTK_ACCESSIBLE_ROLE_COLUMN_HEADER:
break;
case GTK_ACCESSIBLE_ROLE_COMBO_BOX:
return ATSPI_ROLE_COMBO_BOX;
case GTK_ACCESSIBLE_ROLE_COMMAND:
break;
case GTK_ACCESSIBLE_ROLE_COMPOSITE:
break;
case GTK_ACCESSIBLE_ROLE_DIALOG:
return ATSPI_ROLE_DIALOG;
case GTK_ACCESSIBLE_ROLE_DOCUMENT:
return ATSPI_ROLE_DOCUMENT_TEXT;
case GTK_ACCESSIBLE_ROLE_FEED:
break;
case GTK_ACCESSIBLE_ROLE_FORM:
break;
case GTK_ACCESSIBLE_ROLE_GENERIC:
break;
case GTK_ACCESSIBLE_ROLE_GRID:
return ATSPI_ROLE_TABLE;
case GTK_ACCESSIBLE_ROLE_GRID_CELL:
return ATSPI_ROLE_TABLE_CELL;
case GTK_ACCESSIBLE_ROLE_GROUP:
break;
case GTK_ACCESSIBLE_ROLE_HEADING:
break;
case GTK_ACCESSIBLE_ROLE_IMG:
return ATSPI_ROLE_IMAGE;
case GTK_ACCESSIBLE_ROLE_INPUT:
return ATSPI_ROLE_ENTRY;
case GTK_ACCESSIBLE_ROLE_LABEL:
return ATSPI_ROLE_LABEL;
case GTK_ACCESSIBLE_ROLE_LANDMARK:
break;
case GTK_ACCESSIBLE_ROLE_LEGEND:
break;
case GTK_ACCESSIBLE_ROLE_LINK:
return ATSPI_ROLE_LINK;
case GTK_ACCESSIBLE_ROLE_LIST:
return ATSPI_ROLE_LIST;
case GTK_ACCESSIBLE_ROLE_LIST_BOX:
return ATSPI_ROLE_LIST_BOX;
case GTK_ACCESSIBLE_ROLE_LIST_ITEM:
return ATSPI_ROLE_LIST_ITEM;
case GTK_ACCESSIBLE_ROLE_LOG:
return ATSPI_ROLE_LOG;
case GTK_ACCESSIBLE_ROLE_MAIN:
break;
case GTK_ACCESSIBLE_ROLE_MARQUEE:
return ATSPI_ROLE_MARQUEE;
case GTK_ACCESSIBLE_ROLE_MATH:
return ATSPI_ROLE_MATH;;
case GTK_ACCESSIBLE_ROLE_METER:
return ATSPI_ROLE_LEVEL_BAR;
case GTK_ACCESSIBLE_ROLE_MENU:
return ATSPI_ROLE_MENU;
case GTK_ACCESSIBLE_ROLE_MENU_BAR:
return ATSPI_ROLE_MENU_BAR;
case GTK_ACCESSIBLE_ROLE_MENU_ITEM:
return ATSPI_ROLE_MENU_ITEM;
case GTK_ACCESSIBLE_ROLE_MENU_ITEM_CHECKBOX:
return ATSPI_ROLE_CHECK_MENU_ITEM;
case GTK_ACCESSIBLE_ROLE_MENU_ITEM_RADIO:
return ATSPI_ROLE_RADIO_MENU_ITEM;
case GTK_ACCESSIBLE_ROLE_NAVIGATION:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_NONE:
return ATSPI_ROLE_INVALID;
case GTK_ACCESSIBLE_ROLE_NOTE:
return ATSPI_ROLE_FOOTNOTE;
case GTK_ACCESSIBLE_ROLE_OPTION:
return ATSPI_ROLE_OPTION_PANE;
case GTK_ACCESSIBLE_ROLE_PRESENTATION:
return ATSPI_ROLE_DOCUMENT_PRESENTATION;
case GTK_ACCESSIBLE_ROLE_PROGRESS_BAR:
return ATSPI_ROLE_PROGRESS_BAR;
case GTK_ACCESSIBLE_ROLE_RADIO:
return ATSPI_ROLE_RADIO_BUTTON;
case GTK_ACCESSIBLE_ROLE_RADIO_GROUP:
return ATSPI_ROLE_GROUPING;
case GTK_ACCESSIBLE_ROLE_RANGE:
break;
case GTK_ACCESSIBLE_ROLE_REGION:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_ROW:
return ATSPI_ROLE_TABLE_ROW;
case GTK_ACCESSIBLE_ROLE_ROW_GROUP:
return ATSPI_ROLE_GROUPING;
case GTK_ACCESSIBLE_ROLE_ROW_HEADER:
return ATSPI_ROLE_ROW_HEADER;
case GTK_ACCESSIBLE_ROLE_SCROLLBAR:
return ATSPI_ROLE_SCROLL_BAR;
case GTK_ACCESSIBLE_ROLE_SEARCH:
return ATSPI_ROLE_FORM;
case GTK_ACCESSIBLE_ROLE_SEARCH_BOX:
return ATSPI_ROLE_ENTRY;
case GTK_ACCESSIBLE_ROLE_SECTION:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_SECTION_HEAD:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_SELECT:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_SEPARATOR:
return ATSPI_ROLE_SEPARATOR;
case GTK_ACCESSIBLE_ROLE_SLIDER:
return ATSPI_ROLE_SLIDER;
case GTK_ACCESSIBLE_ROLE_SPIN_BUTTON:
return ATSPI_ROLE_SPIN_BUTTON;
case GTK_ACCESSIBLE_ROLE_STATUS:
return ATSPI_ROLE_STATUS_BAR;
case GTK_ACCESSIBLE_ROLE_STRUCTURE:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_SWITCH:
return ATSPI_ROLE_CHECK_BOX;
case GTK_ACCESSIBLE_ROLE_TAB:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_TABLE:
return ATSPI_ROLE_TABLE;
case GTK_ACCESSIBLE_ROLE_TAB_LIST:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_TAB_PANEL:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_TEXT_BOX:
return ATSPI_ROLE_TEXT;
case GTK_ACCESSIBLE_ROLE_TIME:
return ATSPI_ROLE_TEXT;
case GTK_ACCESSIBLE_ROLE_TIMER:
return ATSPI_ROLE_TIMER;
case GTK_ACCESSIBLE_ROLE_TOOLBAR:
return ATSPI_ROLE_TOOL_BAR;
case GTK_ACCESSIBLE_ROLE_TOOLTIP:
return ATSPI_ROLE_TOOL_TIP;
case GTK_ACCESSIBLE_ROLE_TREE:
return ATSPI_ROLE_TREE;
case GTK_ACCESSIBLE_ROLE_TREE_GRID:
return ATSPI_ROLE_TREE_TABLE;
case GTK_ACCESSIBLE_ROLE_TREE_ITEM:
return ATSPI_ROLE_TREE_ITEM;
case GTK_ACCESSIBLE_ROLE_WIDGET:
return ATSPI_ROLE_FILLER;
case GTK_ACCESSIBLE_ROLE_WINDOW:
return ATSPI_ROLE_WINDOW;
default:
break;
}
return ATSPI_ROLE_FILLER;
}
GVariant *
gtk_at_spi_null_ref (void)
{
return g_variant_new ("(so)", "", "/org/a11y/atspi/null");
}

View File

@@ -0,0 +1,34 @@
/* gtkatspiutilsprivate.h: Shared utilities for AT-SPI
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "gtkatspiprivate.h"
#include "gtkenums.h"
G_BEGIN_DECLS
AtspiRole
gtk_accessible_role_to_atspi_role (GtkAccessibleRole role);
GVariant *
gtk_at_spi_null_ref (void);
G_END_DECLS

129
gtk/a11y/gtkatspivalue.c Normal file
View File

@@ -0,0 +1,129 @@
/* gtkatspicontext.c: AT-SPI Value implementation
*
* Copyright 2020 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkatspivalueprivate.h"
#include "a11y/atspi/atspi-value.h"
#include "gtkatcontextprivate.h"
#include "gtkdebug.h"
#include "gtklevelbar.h"
#include "gtkpaned.h"
#include "gtkprogressbar.h"
#include "gtkrange.h"
#include "gtkscalebutton.h"
#include "gtkspinbutton.h"
#include <gio/gio.h>
static GVariant *
handle_value_get_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data)
{
GtkATContext *ctx = GTK_AT_CONTEXT (user_data);
struct {
const char *name;
GtkAccessibleProperty property;
} properties[] = {
{ "MinimumValue", GTK_ACCESSIBLE_PROPERTY_VALUE_MIN },
{ "MaximumValue", GTK_ACCESSIBLE_PROPERTY_VALUE_MAX },
{ "CurrentValue", GTK_ACCESSIBLE_PROPERTY_VALUE_NOW },
};
int i;
for (i = 0; i < G_N_ELEMENTS (properties); i++)
{
if (g_strcmp0 (property_name, properties[i].name) == 0)
{
if (gtk_at_context_has_accessible_property (ctx, properties[i].property))
{
GtkAccessibleValue *value;
value = gtk_at_context_get_accessible_property (ctx, properties[i].property);
return g_variant_new_double (gtk_number_accessible_value_get (value));
}
}
}
/* fall back for a) MinimumIncrement b) widgets that should have the
* properties but don't
*/
return g_variant_new_double (0.0);
}
static gboolean
handle_value_set_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GVariant *value,
GError **error,
gpointer user_data)
{
GtkATContext *self = user_data;
GtkWidget *widget = GTK_WIDGET (gtk_at_context_get_accessible (self));
if (g_strcmp0 (property_name, "CurrentValue") == 0)
{
/* we only allow setting values if that is part of the user-exposed
* functionality of the widget.
*/
if (GTK_IS_RANGE (widget))
gtk_range_set_value (GTK_RANGE (widget), g_variant_get_double (value));
else if (GTK_IS_PANED (widget))
gtk_paned_set_position (GTK_PANED (widget), (int)(g_variant_get_double (value) + 0.5));
else if (GTK_IS_SPIN_BUTTON (widget))
gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), g_variant_get_double (value));
else if (GTK_IS_SCALE_BUTTON (widget))
gtk_scale_button_set_value (GTK_SCALE_BUTTON (widget), g_variant_get_double (value));
return TRUE;
}
return FALSE;
}
static const GDBusInterfaceVTable value_vtable = {
NULL,
handle_value_get_property,
handle_value_set_property,
};
const GDBusInterfaceVTable *
gtk_atspi_get_value_vtable (GtkWidget *widget)
{
if (GTK_IS_LEVEL_BAR (widget) ||
GTK_IS_PANED (widget) ||
GTK_IS_PROGRESS_BAR (widget) ||
GTK_IS_RANGE (widget) ||
GTK_IS_SCALE_BUTTON (widget) ||
GTK_IS_SPIN_BUTTON (widget))
return &value_vtable;
return NULL;
}

View File

@@ -0,0 +1,30 @@
/* gtkatspivalueprivate.h: AT-SPI Value implementation
*
* Copyright 2020 Red Hat, Inc.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gio/gio.h>
#include "gtkwidget.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_value_vtable (GtkWidget *widget);
G_END_DECLS

22
gtk/a11y/meson.build Normal file
View File

@@ -0,0 +1,22 @@
gtk_a11y_src = []
gtk_a11y_backends = []
if os_unix
gtk_a11y_backends += 'atspi'
endif
if gtk_a11y_backends.contains('atspi')
subdir('atspi')
gtk_a11y_src += files([
'gtkatspicache.c',
'gtkatspicontext.c',
'gtkatspiroot.c',
'gtkatspiutils.c',
'gtkatspipango.c',
'gtkatspitextbuffer.c',
'gtkatspitext.c',
'gtkatspivalue.c',
'gtkatspieditabletext.c',
])
endif

View File

@@ -48,6 +48,8 @@
#include "gtkenums.h"
#include "gtktypebuiltins.h"
#include <glib/gi18n-lib.h>
#include <stdarg.h>
G_DEFINE_INTERFACE (GtkAccessible, gtk_accessible, G_TYPE_OBJECT)
@@ -532,3 +534,118 @@ gtk_accessible_reset_relation (GtkAccessible *self,
gtk_at_context_set_accessible_relation (context, relation, NULL);
gtk_at_context_update (context);
}
static const char *role_names[] = {
[GTK_ACCESSIBLE_ROLE_ALERT] = NC_("accessibility", "alert"),
[GTK_ACCESSIBLE_ROLE_ALERT_DIALOG] = NC_("accessibility", "alert dialog"),
[GTK_ACCESSIBLE_ROLE_BANNER] = NC_("accessibility", "banner"),
[GTK_ACCESSIBLE_ROLE_BUTTON] = NC_("accessibility", "button"),
[GTK_ACCESSIBLE_ROLE_CAPTION] = NC_("accessibility", "caption"),
[GTK_ACCESSIBLE_ROLE_CELL] = NC_("accessibility", "cell"),
[GTK_ACCESSIBLE_ROLE_CHECKBOX] = NC_("accessibility", "checkbox"),
[GTK_ACCESSIBLE_ROLE_COLUMN_HEADER] = NC_("accessibility", "column header"),
[GTK_ACCESSIBLE_ROLE_COMBO_BOX] = NC_("accessibility", "combo box"),
[GTK_ACCESSIBLE_ROLE_COMMAND] = NC_("accessibility", "command"),
[GTK_ACCESSIBLE_ROLE_COMPOSITE] = NC_("accessibility", "composite"),
[GTK_ACCESSIBLE_ROLE_DIALOG] = NC_("accessibility", "dialog"),
[GTK_ACCESSIBLE_ROLE_DOCUMENT] = NC_("accessibility", "document"),
[GTK_ACCESSIBLE_ROLE_FEED] = NC_("accessibility", "feed"),
[GTK_ACCESSIBLE_ROLE_FORM] = NC_("accessibility", "form"),
[GTK_ACCESSIBLE_ROLE_GENERIC] = NC_("accessibility", "generic"),
[GTK_ACCESSIBLE_ROLE_GRID] = NC_("accessibility", "grid"),
[GTK_ACCESSIBLE_ROLE_GRID_CELL] = NC_("accessibility", "grid cell"),
[GTK_ACCESSIBLE_ROLE_GROUP] = NC_("accessibility", "group"),
[GTK_ACCESSIBLE_ROLE_HEADING] = NC_("accessibility", "heading"),
[GTK_ACCESSIBLE_ROLE_IMG] = NC_("accessibility", "image"),
[GTK_ACCESSIBLE_ROLE_INPUT] = NC_("accessibility", "input"),
[GTK_ACCESSIBLE_ROLE_LABEL] = NC_("accessibility", "label"),
[GTK_ACCESSIBLE_ROLE_LANDMARK] = NC_("accessibility", "landmark"),
[GTK_ACCESSIBLE_ROLE_LEGEND] = NC_("accessibility", "legend"),
[GTK_ACCESSIBLE_ROLE_LINK] = NC_("accessibility", "link"),
[GTK_ACCESSIBLE_ROLE_LIST] = NC_("accessibility", "list"),
[GTK_ACCESSIBLE_ROLE_LIST_BOX] = NC_("accessibility", "list box"),
[GTK_ACCESSIBLE_ROLE_LIST_ITEM] = NC_("accessibility", "list item"),
[GTK_ACCESSIBLE_ROLE_LOG] = NC_("accessibility", "log"),
[GTK_ACCESSIBLE_ROLE_MAIN] = NC_("accessibility", "main"),
[GTK_ACCESSIBLE_ROLE_MARQUEE] = NC_("accessibility", "marquee"),
[GTK_ACCESSIBLE_ROLE_MATH] = NC_("accessibility", "math"),
[GTK_ACCESSIBLE_ROLE_METER] = NC_("accessibility", "meter"),
[GTK_ACCESSIBLE_ROLE_MENU] = NC_("accessibility", "menu"),
[GTK_ACCESSIBLE_ROLE_MENU_BAR] = NC_("accessibility", "menu bar"),
[GTK_ACCESSIBLE_ROLE_MENU_ITEM] = NC_("accessibility", "menu item"),
[GTK_ACCESSIBLE_ROLE_MENU_ITEM_CHECKBOX] = NC_("accessibility", "menu item checkbox"),
[GTK_ACCESSIBLE_ROLE_MENU_ITEM_RADIO] = NC_("accessibility", "menu item radio"),
[GTK_ACCESSIBLE_ROLE_NAVIGATION] = NC_("accessibility", "navigation"),
[GTK_ACCESSIBLE_ROLE_NONE] = NC_("accessibility", "none"),
[GTK_ACCESSIBLE_ROLE_NOTE] = NC_("accessibility", "note"),
[GTK_ACCESSIBLE_ROLE_OPTION] = NC_("accessibility", "option"),
[GTK_ACCESSIBLE_ROLE_PRESENTATION] = NC_("accessibility", "presentation"),
[GTK_ACCESSIBLE_ROLE_PROGRESS_BAR] = NC_("accessibility", "progress bar"),
[GTK_ACCESSIBLE_ROLE_RADIO] = NC_("accessibility", "radio"),
[GTK_ACCESSIBLE_ROLE_RADIO_GROUP] = NC_("accessibility", "radio group"),
[GTK_ACCESSIBLE_ROLE_RANGE] = NC_("accessibility", "range"),
[GTK_ACCESSIBLE_ROLE_REGION] = NC_("accessibility", "region"),
[GTK_ACCESSIBLE_ROLE_ROW] = NC_("accessibility", "row"),
[GTK_ACCESSIBLE_ROLE_ROW_GROUP] = NC_("accessibility", "row group"),
[GTK_ACCESSIBLE_ROLE_ROW_HEADER] = NC_("accessibility", "row header"),
[GTK_ACCESSIBLE_ROLE_SCROLLBAR] = NC_("accessibility", "scroll bar"),
[GTK_ACCESSIBLE_ROLE_SEARCH] = NC_("accessibility", "search"),
[GTK_ACCESSIBLE_ROLE_SEARCH_BOX] = NC_("accessibility", "search box"),
[GTK_ACCESSIBLE_ROLE_SECTION] = NC_("accessibility", "section"),
[GTK_ACCESSIBLE_ROLE_SECTION_HEAD] = NC_("accessibility", "section head"),
[GTK_ACCESSIBLE_ROLE_SELECT] = NC_("accessibility", "select"),
[GTK_ACCESSIBLE_ROLE_SEPARATOR] = NC_("accessibility", "separator"),
[GTK_ACCESSIBLE_ROLE_SLIDER] = NC_("accessibility", "slider"),
[GTK_ACCESSIBLE_ROLE_SPIN_BUTTON] = NC_("accessibility", "spin button"),
[GTK_ACCESSIBLE_ROLE_STATUS] = NC_("accessibility", "status"),
[GTK_ACCESSIBLE_ROLE_STRUCTURE] = NC_("accessibility", "structure"),
[GTK_ACCESSIBLE_ROLE_SWITCH] = NC_("accessibility", "switch"),
[GTK_ACCESSIBLE_ROLE_TAB] = NC_("accessibility", "tab"),
[GTK_ACCESSIBLE_ROLE_TABLE] = NC_("accessibility", "table"),
[GTK_ACCESSIBLE_ROLE_TAB_LIST] = NC_("accessibility", "tab list"),
[GTK_ACCESSIBLE_ROLE_TAB_PANEL] = NC_("accessibility", "tab panel"),
[GTK_ACCESSIBLE_ROLE_TEXT_BOX] = NC_("accessibility", "text box"),
[GTK_ACCESSIBLE_ROLE_TIME] = NC_("accessibility", "time"),
[GTK_ACCESSIBLE_ROLE_TIMER] = NC_("accessibility", "timer"),
[GTK_ACCESSIBLE_ROLE_TOOLBAR] = NC_("accessibility", "tool bar"),
[GTK_ACCESSIBLE_ROLE_TOOLTIP] = NC_("accessibility", "tool tip"),
[GTK_ACCESSIBLE_ROLE_TREE] = NC_("accessibility", "tree"),
[GTK_ACCESSIBLE_ROLE_TREE_GRID] = NC_("accessibility", "tree grid"),
[GTK_ACCESSIBLE_ROLE_TREE_ITEM] = NC_("accessibility", "tree item"),
[GTK_ACCESSIBLE_ROLE_WIDGET] = NC_("accessibility", "widget"),
[GTK_ACCESSIBLE_ROLE_WINDOW] = NC_("accessibility", "window"),
};
/*< private >
* gtk_accessible_role_to_name:
* @role: a #GtkAccessibleRole
* @domain: (nullable): the translation domain
*
* Converts a #GtkAccessibleRole value to the equivalent role name.
*
* If @domain is not %NULL, the returned string will be localized.
*
* Returns: (transfer none): the name of the role
*/
const char *
gtk_accessible_role_to_name (GtkAccessibleRole role,
const char *domain)
{
if (domain != NULL)
return g_dpgettext2 (domain, "accessibility", role_names[role]);
return role_names[role];
}
void
gtk_accessible_platform_changed (GtkAccessible *self,
GtkAccessiblePlatformChange change)
{
GtkATContext *context = gtk_accessible_get_at_context (self);
if (context == NULL)
return;
gtk_at_context_platform_changed (context, change);
gtk_at_context_update (context);
}

View File

@@ -20,7 +20,7 @@
#pragma once
#include "gtkaccessibleprivate.h"
#include "gtkaccessible.h"
#include "gtkaccessiblevalueprivate.h"
G_BEGIN_DECLS

View File

@@ -21,7 +21,7 @@
#pragma once
#include "gtkaccessible.h"
#include "gtkatcontext.h"
#include "gtkatcontextprivate.h"
G_BEGIN_DECLS
@@ -34,4 +34,10 @@ struct _GtkAccessibleInterface
GtkATContext * gtk_accessible_get_at_context (GtkAccessible *self);
const char * gtk_accessible_role_to_name (GtkAccessibleRole role,
const char *domain);
void gtk_accessible_platform_changed (GtkAccessible *self,
GtkAccessiblePlatformChange change);
G_END_DECLS

View File

@@ -36,15 +36,22 @@
#include "gtkatcontextprivate.h"
#include "gtkaccessiblevalueprivate.h"
#include "gtkaccessibleprivate.h"
#include "gtkdebug.h"
#include "gtktestatcontextprivate.h"
#include "gtktypebuiltins.h"
#if defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND)
#include "a11y/gtkatspicontextprivate.h"
#endif
G_DEFINE_ABSTRACT_TYPE (GtkATContext, gtk_at_context, G_TYPE_OBJECT)
enum
{
PROP_ACCESSIBLE_ROLE = 1,
PROP_ACCESSIBLE,
PROP_DISPLAY,
N_PROPS
};
@@ -90,6 +97,10 @@ gtk_at_context_set_property (GObject *gobject,
self->accessible = g_value_get_object (value);
break;
case PROP_DISPLAY:
self->display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
@@ -113,6 +124,10 @@ gtk_at_context_get_property (GObject *gobject,
g_value_set_object (value, self->accessible);
break;
case PROP_DISPLAY:
g_value_set_object (value, self->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
@@ -123,6 +138,7 @@ gtk_at_context_real_state_change (GtkATContext *self,
GtkAccessibleStateChange changed_states,
GtkAccessiblePropertyChange changed_properties,
GtkAccessibleRelationChange changed_relations,
GtkAccessiblePlatformChange changed_platform,
GtkAccessibleAttributeSet *states,
GtkAccessibleAttributeSet *properties,
GtkAccessibleAttributeSet *relations)
@@ -172,6 +188,20 @@ gtk_at_context_class_init (GtkATContextClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
* GtkATContext:display:
*
* The #GdkDisplay for the #GtkATContext.
*/
obj_props[PROP_DISPLAY] =
g_param_spec_object ("display",
"Display",
"The display connection",
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
* GtkATContext::state-change:
* @self: the #GtkATContext
@@ -354,13 +384,45 @@ gtk_at_context_get_accessible_role (GtkATContext *self)
return self->accessible_role;
}
/*< private >
* gtk_at_context_get_display:
* @self: a #GtkATContext
*
* Retrieves the #GdkDisplay used to create the context.
*
* Returns: (transfer none): a #GdkDisplay
*/
GdkDisplay *
gtk_at_context_get_display (GtkATContext *self)
{
g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL);
return self->display;
}
static const struct {
const char *name;
GtkATContext * (* create_context) (GtkAccessibleRole accessible_role,
GtkAccessible *accessible,
GdkDisplay *display);
} a11y_backends[] = {
#if defined(GDK_WINDOWING_WAYLAND)
{ "AT-SPI (Wayland)", gtk_at_spi_create_context },
#endif
#if defined(GDK_WINDOWING_X11)
{ "AT-SPI (X11)", gtk_at_spi_create_context },
#endif
{ NULL, NULL },
};
/**
* gtk_at_context_create: (constructor)
* @accessible_role: the accessible role used by the #GtkATContext
* @accessible: the #GtkAccessible implementation using the #GtkATContext
* @display: the #GdkDisplay used by the #GtkATContext
*
* Creates a new #GtkATContext instance for the given accessible role and
* accessible instance.
* Creates a new #GtkATContext instance for the given accessible role,
* accessible instance, and display connection.
*
* The #GtkATContext implementation being instantiated will depend on the
* platform.
@@ -369,7 +431,8 @@ gtk_at_context_get_accessible_role (GtkATContext *self)
*/
GtkATContext *
gtk_at_context_create (GtkAccessibleRole accessible_role,
GtkAccessible *accessible)
GtkAccessible *accessible,
GdkDisplay *display)
{
static const char *gtk_test_accessible;
static const char *gtk_no_a11y;
@@ -401,8 +464,32 @@ gtk_at_context_create (GtkAccessibleRole accessible_role,
if (gtk_no_a11y[0] == '1')
return NULL;
GtkATContext *res = NULL;
for (guint i = 0; i < G_N_ELEMENTS (a11y_backends); i++)
{
if (a11y_backends[i].name == NULL)
break;
GTK_NOTE (A11Y, g_message ("Trying %s a11y backend", a11y_backends[i].name));
if (a11y_backends[i].create_context != NULL)
{
res = a11y_backends[i].create_context (accessible_role, accessible, display);
if (res != NULL)
break;
}
}
/* Fall back to the test context, so we can get debugging data */
if (res == NULL)
res = g_object_new (GTK_TYPE_TEST_AT_CONTEXT,
"accessible_role", accessible_role,
"accessible", accessible,
"display", display,
NULL);
/* FIXME: Add GIOExtension for AT contexts */
return gtk_test_at_context_new (accessible_role, accessible);
return res;
}
/*< private >
@@ -420,7 +507,8 @@ gtk_at_context_update (GtkATContext *self)
/* There's no point in notifying of state changes if there weren't any */
if (self->updated_properties == 0 &&
self->updated_relations == 0 &&
self->updated_states == 0)
self->updated_states == 0 &&
self->updated_platform == 0)
return;
GtkAccessibleStateChange changed_states =
@@ -432,12 +520,14 @@ gtk_at_context_update (GtkATContext *self)
GTK_AT_CONTEXT_GET_CLASS (self)->state_change (self,
changed_states, changed_properties, changed_relations,
self->updated_platform,
self->states, self->properties, self->relations);
g_signal_emit (self, obj_signals[STATE_CHANGE], 0);
self->updated_properties = 0;
self->updated_relations = 0;
self->updated_states = 0;
self->updated_platform = 0;
}
/*< private >
@@ -640,3 +730,91 @@ gtk_at_context_get_accessible_relation (GtkATContext *self,
return gtk_accessible_attribute_set_get_value (self->relations, relation);
}
/*< private >
* gtk_at_context_get_label:
* @self: a #GtkATContext
*
* Retrieves the accessible label of the #GtkATContext.
*
* This is a convenience function meant to be used by #GtkATContext implementations.
*
* Returns: (transfer full): the label of the #GtkATContext
*/
char *
gtk_at_context_get_label (GtkATContext *self)
{
g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), NULL);
GtkAccessibleValue *value = NULL;
if (gtk_accessible_attribute_set_contains (self->states, GTK_ACCESSIBLE_STATE_HIDDEN))
{
value = gtk_accessible_attribute_set_get_value (self->states, GTK_ACCESSIBLE_STATE_HIDDEN);
if (gtk_boolean_accessible_value_get (value))
return g_strdup ("");
}
if (gtk_accessible_attribute_set_contains (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL))
{
value = gtk_accessible_attribute_set_get_value (self->properties, GTK_ACCESSIBLE_PROPERTY_LABEL);
return g_strdup (gtk_string_accessible_value_get (value));
}
if (gtk_accessible_attribute_set_contains (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY))
{
value = gtk_accessible_attribute_set_get_value (self->relations, GTK_ACCESSIBLE_RELATION_LABELLED_BY);
GList *list = gtk_reference_list_accessible_value_get (value);
GtkAccessible *rel = GTK_ACCESSIBLE (list->data);
GtkATContext *rel_context = gtk_accessible_get_at_context (rel);
return gtk_at_context_get_label (rel_context);
}
GtkAccessibleRole role = gtk_at_context_get_accessible_role (self);
switch ((int) role)
{
case GTK_ACCESSIBLE_ROLE_RANGE:
{
int range_attrs[] = {
GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT,
GTK_ACCESSIBLE_PROPERTY_VALUE_NOW,
};
for (int i = 0; i < G_N_ELEMENTS (range_attrs); i++)
{
if (gtk_accessible_attribute_set_contains (self->properties, range_attrs[i]))
{
value = gtk_accessible_attribute_set_get_value (self->properties, range_attrs[i]);
break;
}
}
if (value != NULL)
return g_strdup (gtk_string_accessible_value_get (value));
}
break;
default:
break;
}
GEnumClass *enum_class = g_type_class_peek (GTK_TYPE_ACCESSIBLE_ROLE);
GEnumValue *enum_value = g_enum_get_value (enum_class, role);
if (enum_value != NULL)
return g_strdup (enum_value->value_nick);
return g_strdup ("widget");
}
void
gtk_at_context_platform_changed (GtkATContext *self,
GtkAccessiblePlatformChange change)
{
self->updated_platform |= change;
}

View File

@@ -42,6 +42,7 @@ GtkAccessibleRole gtk_at_context_get_accessible_role (GtkATContext
GDK_AVAILABLE_IN_ALL
GtkATContext * gtk_at_context_create (GtkAccessibleRole accessible_role,
GtkAccessible *accessible);
GtkAccessible *accessible,
GdkDisplay *display);
G_END_DECLS

View File

@@ -80,12 +80,18 @@ typedef enum {
GTK_ACCESSIBLE_STATE_CHANGE_SELECTED = 1 << GTK_ACCESSIBLE_STATE_SELECTED
} GtkAccessibleStateChange;
typedef enum {
GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSABLE = 1 << 0,
GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED = 1 << 1,
} GtkAccessiblePlatformChange;
struct _GtkATContext
{
GObject parent_instance;
GtkAccessibleRole accessible_role;
GtkAccessible *accessible;
GdkDisplay *display;
GtkAccessibleAttributeSet *states;
GtkAccessibleAttributeSet *properties;
@@ -94,6 +100,7 @@ struct _GtkATContext
GtkAccessibleStateChange updated_states;
GtkAccessiblePropertyChange updated_properties;
GtkAccessibleRelationChange updated_relations;
GtkAccessiblePlatformChange updated_platform;
};
struct _GtkATContextClass
@@ -104,11 +111,14 @@ struct _GtkATContextClass
GtkAccessibleStateChange changed_states,
GtkAccessiblePropertyChange changed_properties,
GtkAccessibleRelationChange changed_relations,
GtkAccessiblePlatformChange changed_platform,
GtkAccessibleAttributeSet *states,
GtkAccessibleAttributeSet *properties,
GtkAccessibleAttributeSet *relations);
};
GdkDisplay * gtk_at_context_get_display (GtkATContext *self);
void gtk_at_context_update (GtkATContext *self);
void gtk_at_context_set_accessible_state (GtkATContext *self,
@@ -133,6 +143,11 @@ gboolean gtk_at_context_has_accessible_relation (GtkATContext
GtkAccessibleValue * gtk_at_context_get_accessible_relation (GtkATContext *self,
GtkAccessibleRelation relation);
char * gtk_at_context_get_label (GtkATContext *self);
void gtk_at_context_platform_changed (GtkATContext *self,
GtkAccessiblePlatformChange change);
const char * gtk_accessible_property_get_attribute_name (GtkAccessibleProperty property);
const char * gtk_accessible_relation_get_attribute_name (GtkAccessibleRelation relation);
const char * gtk_accessible_state_get_attribute_name (GtkAccessibleState state);

View File

@@ -1385,6 +1385,14 @@ gtk_paned_size_allocate (GtkWidget *widget,
gtk_widget_set_child_visible (paned->handle_widget, FALSE);
}
gtk_accessible_update_property (GTK_ACCESSIBLE (paned),
GTK_ACCESSIBLE_PROPERTY_VALUE_MIN, 0.0,
GTK_ACCESSIBLE_PROPERTY_VALUE_MAX,
(double) (paned->orientation == GTK_ORIENTATION_HORIZONTAL ? width : height),
GTK_ACCESSIBLE_PROPERTY_VALUE_NOW,
(double) paned->start_child_size,
-1);
}

View File

@@ -414,6 +414,12 @@ gtk_scale_button_init (GtkScaleButton *button)
g_object_ref_sink (priv->adjustment);
gtk_range_set_adjustment (GTK_RANGE (priv->scale), priv->adjustment);
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, gtk_adjustment_get_upper (priv->adjustment),
GTK_ACCESSIBLE_PROPERTY_VALUE_MIN, gtk_adjustment_get_lower (priv->adjustment),
GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, gtk_adjustment_get_value (priv->adjustment),
-1);
gtk_widget_add_css_class (GTK_WIDGET (button), "scale");
controller = gtk_event_controller_scroll_new (GTK_EVENT_CONTROLLER_SCROLL_VERTICAL);
@@ -677,6 +683,13 @@ gtk_scale_button_set_adjustment (GtkScaleButton *button,
gtk_range_set_adjustment (GTK_RANGE (priv->scale), adjustment);
g_object_notify (G_OBJECT (button), "adjustment");
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, gtk_adjustment_get_upper (adjustment),
GTK_ACCESSIBLE_PROPERTY_VALUE_MIN, gtk_adjustment_get_lower (adjustment),
GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, gtk_adjustment_get_value (adjustment),
-1);
}
}
@@ -939,6 +952,10 @@ cb_scale_value_changed (GtkRange *range,
g_signal_emit (button, signals[VALUE_CHANGED], 0, value);
g_object_notify (G_OBJECT (button), "value");
gtk_accessible_update_property (GTK_ACCESSIBLE (button),
GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, value,
-1);
}
static void

View File

@@ -23,6 +23,7 @@
#include "gtktestatcontextprivate.h"
#include "gtkatcontextprivate.h"
#include "gtkaccessibleprivate.h"
#include "gtkdebug.h"
#include "gtkenums.h"
#include "gtkprivate.h"
@@ -45,6 +46,7 @@ gtk_test_at_context_state_change (GtkATContext *self,
GtkAccessibleStateChange changed_states,
GtkAccessiblePropertyChange changed_properties,
GtkAccessibleRelationChange changed_relations,
GtkAccessiblePlatformChange changed_platform,
GtkAccessibleAttributeSet *states,
GtkAccessibleAttributeSet *properties,
GtkAccessibleAttributeSet *relations)

View File

@@ -1482,6 +1482,7 @@ gtk_text_class_init (GtkTextClass *class)
"text.redo", NULL);
gtk_widget_class_set_css_name (widget_class, I_("text"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_TEXT_BOX);
}
static void
@@ -5430,6 +5431,10 @@ gtk_text_set_editable (GtkText *self,
gtk_text_update_clipboard_actions (self);
gtk_text_update_emoji_action (self);
gtk_accessible_update_property (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_PROPERTY_READ_ONLY, !priv->editable,
-1);
g_object_notify (G_OBJECT (self), "editable");
}
}

View File

@@ -4947,6 +4947,9 @@ gtk_widget_set_focusable (GtkWidget *widget,
priv->focusable = focusable;
gtk_widget_queue_resize (widget);
gtk_accessible_platform_changed (GTK_ACCESSIBLE (widget), GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSABLE);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_FOCUSABLE]);
}
@@ -8091,10 +8094,14 @@ gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
GtkWidget *self = GTK_WIDGET (accessible);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (self);
if (priv->in_destruction)
return NULL;
if (priv->at_context == NULL)
{
GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (self);
GtkWidgetClassPrivate *class_priv = widget_class->priv;
GdkDisplay *display = _gtk_widget_get_display (self);
GtkAccessibleRole role;
/* Widgets have two options to set the accessible role: either they
@@ -8111,7 +8118,7 @@ gtk_widget_accessible_get_at_context (GtkAccessible *accessible)
role = class_priv->accessible_role;
priv->accessible_role = role;
priv->at_context = gtk_at_context_create (role, accessible);
priv->at_context = gtk_at_context_create (role, accessible, display);
}
return priv->at_context;
@@ -9752,6 +9759,8 @@ gtk_widget_set_has_focus (GtkWidget *widget,
priv->has_focus = has_focus;
gtk_accessible_platform_changed (GTK_ACCESSIBLE (widget), GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]);
}
@@ -12139,6 +12148,10 @@ gtk_widget_update_orientation (GtkWidget *widget,
gtk_widget_add_css_class (widget, "vertical");
gtk_widget_remove_css_class (widget, "horizontal");
}
gtk_accessible_update_property (GTK_ACCESSIBLE (widget),
GTK_ACCESSIBLE_PROPERTY_ORIENTATION, orientation,
-1);
}
/**

View File

@@ -1,3 +1,4 @@
subdir('a11y')
subdir('deprecated')
subdir('inspector')
@@ -961,6 +962,7 @@ gtk_gen_headers = [
]
gtk_sources += [
gtk_a11y_src,
gtk_dbus_src,
gtk_deprecated_sources,
inspector_sources,

View File

@@ -29,7 +29,9 @@ test_object_accessible_get_at_context (GtkAccessible *accessible)
TestObject *self = (TestObject*)accessible;
if (self->at_context == NULL)
self->at_context = gtk_at_context_create (self->role, accessible);
self->at_context = gtk_at_context_create (self->role,
accessible,
gdk_display_get_default ());
return self->at_context;
}

View File

@@ -9,14 +9,13 @@ test_change = executable(
install: get_option('install-tests'),
install_dir: testexecdir,
)
test('change', test_change,
args: [ '--tap', '-k' ],
protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
suite: 'css')
args: [ '--tap', '-k' ],
protocol: 'tap',
env: csstest_env,
suite: 'css',
)
test_data = [
'test1.css', 'test1.ui', 'test1.nodes',

View File

@@ -1,3 +1,12 @@
csstest_env = environment()
csstest_env.set('GTK_TEST_ACCESSIBLE', '1')
csstest_env.set('GSK_RENDERER', 'cairo')
csstest_env.set('G_TEST_SRCDIR', meson.current_source_dir())
csstest_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
csstest_env.set('GIO_USE_VFS', 'local')
csstest_env.set('GSETTINGS_BACKEND', 'memory')
csstest_env.set('G_ENABLE_DIAGNOSTIC', '0')
subdir('parser')
subdir('nodes')
subdir('style')
@@ -14,10 +23,7 @@ test_api = executable('api', 'api.c',
test('api', test_api,
args: ['--tap', '-k' ],
protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
env: csstest_env,
suite: 'css')
test_data = executable('data', ['data.c', '../../gtk/css/gtkcssdataurl.c'],
@@ -29,10 +35,7 @@ test_data = executable('data', ['data.c', '../../gtk/css/gtkcssdataurl.c'],
test('data', test_data,
args: ['--tap', '-k' ],
protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
env: csstest_env,
suite: 'css')
if get_option('install-tests')
@@ -46,20 +49,24 @@ endif
if false and get_option ('profiler')
adwaita_env = csstest_env
adwaita_env.set('GTK_THEME', 'Adwaita')
test('performance-adwaita', test_performance,
args: [ '--mark', 'css validation',
'--name', 'performance-adwaita',
'--output', join_paths(meson.current_build_dir(), 'output'),
join_paths(meson.current_build_dir(), '../../demos/widget-factory/gtk4-widget-factory') ],
env: [ 'GTK_THEME=Adwaita' ],
env: adwaita_env,
suite: [ 'css' ])
empty_env = csstest_env
empty_env.set('GTK_THEME', 'Empty')
test('performance-empty', test_performance,
args: [ '--mark', 'css validation',
'--name', 'performance-empty',
'--output', join_paths(meson.current_build_dir(), 'output'),
join_paths(meson.current_build_dir(), '../../demos/widget-factory/gtk4-widget-factory') ],
env: [ 'GTK_THEME=Empty' ],
env: empty_env,
suite: [ 'css' ])
endif

View File

@@ -7,13 +7,11 @@ test_nodes = executable('test-css-nodes', 'test-css-nodes.c',
install_dir: testexecdir,
dependencies: libgtk_dep)
test('nodes', test_nodes,
args: [ '--tap', '-k' ],
protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
suite: 'css')
args: [ '--tap', '-k' ],
protocol: 'tap',
env: csstest_env,
suite: 'css',
)
test_data = [
'box.ltr.nodes',
@@ -77,5 +75,4 @@ if get_option('install-tests')
install_dir: testdatadir)
install_data(test_data, install_dir: testexecdir)
endif

View File

@@ -17,13 +17,11 @@ test_style = executable(
install_dir: testexecdir,
)
test('style', test_style,
args: [ '--tap', '-k' ],
protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
suite: 'css')
args: [ '--tap', '-k' ],
protocol: 'tap',
env: csstest_env,
suite: 'css',
)
test_data = [
'adjacent-states.css',
@@ -65,5 +63,4 @@ if get_option('install-tests')
install_dir: testdatadir)
install_data(test_data, install_dir: testexecdir)
endif

View File

@@ -16,28 +16,31 @@ tests = [
foreach t : tests
test_exe = executable(t, '@0@.c'.format(t),
c_args: common_cflags,
dependencies: libgtk_dep,
install: get_option('install-tests'),
install_dir: testexecdir)
c_args: common_cflags,
dependencies: libgtk_dep,
install: get_option('install-tests'),
install_dir: testexecdir,
)
test(t, test_exe,
args: [ '--tap', '-k' ],
protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
suite: 'gdk')
args: [ '--tap', '-k' ],
protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
],
suite: 'gdk',
)
if get_option('install-tests')
test_cdata = configuration_data()
test_cdata.set('testexecdir', testexecdir)
test_cdata.set('test', t)
configure_file(input: 'gdk.test.in',
output: '@0@.test'.format(t),
configuration: test_cdata,
install: true,
install_dir: testdatadir)
output: '@0@.test'.format(t),
configuration: test_cdata,
install: true,
install_dir: testdatadir,
)
endif
endforeach

View File

@@ -101,6 +101,7 @@ foreach renderer : renderers
join_paths(meson.current_source_dir(), 'compare', test + '.png')],
env: [
'GSK_RENDERER=' + renderer[0],
'GTK_TEST_ACCESSIBLE=1',
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
@@ -178,6 +179,7 @@ foreach test : node_parser_tests
],
env: [
'GSK_RENDERER=opengl',
'GTK_TEST_ACCESSIBLE=1',
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
@@ -211,6 +213,7 @@ foreach t : tests
protocol: 'tap',
env: [
'GSK_RENDERER=cairo',
'GTK_TEST_ACCESSIBLE=1',
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],

View File

@@ -146,6 +146,15 @@ is_debug = get_option('buildtype').startswith('debug')
test_cargs = []
test_env = environment()
test_env.set('GTK_TEST_ACCESSIBLE', '1')
test_env.set('GSK_RENDERER', 'cairo')
test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
test_env.set('GIO_USE_VFS', 'local')
test_env.set('GSETTINGS_BACKEND', 'memory')
test_env.set('G_ENABLE_DIAGNOSTIC', '0')
if os_unix
# tests += [['defaultvalue']] # disabled in Makefile.am as well
test_cargs += ['-DHAVE_UNIX_PRINT_WIDGETS']
@@ -182,11 +191,7 @@ foreach t : tests
args: [ '--tap', '-k' ],
protocol: 'tap',
timeout: test_timeout,
env: [
'GSK_RENDERER=cairo',
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
],
env: test_env,
suite: ['gtk'] + test_extra_suites,
should_fail: expect_fail,
)
@@ -203,10 +208,7 @@ if add_languages('cpp', required: false)
test('c++ keywords', test_exe,
args: [ '--tap', '-k' ],
#protocol: 'tap',
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
],
env: test_env,
suite: 'gtk')
if get_option('install-tests')
conf = configuration_data()
@@ -254,10 +256,7 @@ foreach test : focus_chain_tests
test(test[0] + ' ' + test[1], focus_chain,
args: [ join_paths(meson.current_source_dir(), 'focus-chain', test[0] + '.ui'),
join_paths(meson.current_source_dir(), 'focus-chain', test[0] + '.' + test[1]) ],
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
env: test_env,
suite: [ 'gtk', 'focus' ])
endforeach
@@ -282,14 +281,17 @@ endif
if false and get_option ('profiler')
performance_env = test_env
performance_env.set('GTK_THEME', 'Empty')
test('performance-layout', test_performance,
args: [ '--mark', 'size allocation', join_paths(meson.current_build_dir(), '../../demos/widget-factory/gtk4-widget-factory') ],
env: [ 'GTK_THEME=Empty' ],
env: performance_env,
suite: [ 'gtk' ])
test('performance-snapshot', test_performance,
args: [ '--mark', 'widget snapshot', join_paths(meson.current_build_dir(), '../../demos/widget-factory/gtk4-widget-factory') ],
env: [ 'GTK_THEME=Empty' ],
env: performance_end,
suite: [ 'gtk' ])
endif

View File

@@ -450,6 +450,16 @@ xfails = [
'label-sizing.ui',
]
reftest_env = environment()
reftest_env.set('GTK_TEST_ACCESSIBLE', '1')
reftest_env.set('GSK_RENDERER', 'opengl')
reftest_env.set('G_TEST_SRCDIR', meson.current_source_dir())
reftest_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
reftest_env.set('GIO_USE_VFS', 'local')
reftest_env.set('GSETTINGS_BACKEND', 'memory')
reftest_env.set('G_ENABLE_DIAGNOSTIC', '0')
reftest_env.set('REFTEST_MODULE_DIR', meson.current_build_dir())
foreach testname : testdata
if testname.endswith('.ui') and not testname.endswith('.ref.ui')
test('reftest ' + testname, gtk_reftest,
@@ -459,12 +469,7 @@ foreach testname : testdata
join_paths(meson.current_source_dir(), testname),
],
protocol: 'tap',
env: [
'GSK_RENDERER=opengl',
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
'REFTEST_MODULE_DIR=@0@'.format(meson.current_build_dir())
],
env: reftest_env,
suite: 'reftest',
should_fail: xfails.contains(testname))
endif

View File

@@ -23,6 +23,7 @@ if bash.found()
env: [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
'GTK_TEST_ACCESSIBLE=1',
'GTK_BUILDER_TOOL=@0@'.format(get_variable('gtk4_builder_tool').full_path()),
'GTK_QUERY_SETTINGS=@0@'.format(get_variable('gtk4_query_settings').full_path())
],