Merge branch 'a11y/atspi' into 'master'

A11y/atspi

See merge request GNOME/gtk!2698
This commit is contained in:
Matthias Clasen 2020-10-15 14:59:24 +00:00
commit 9c28ecb0da
112 changed files with 10821 additions and 161 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

@ -48,18 +48,28 @@ Each role name is part of the #GtkAccessibleRole enumeration.
| `BUTTON` | A control that performs an action when pressed | #GtkButton, #GtkLinkButton, #GtkExpander |
| `CHECKBOX` | A control that has three possible value: `true`, `false`, or `undefined` | #GtkCheckButton |
| `COMBOBOX` | A control that can be expanded to show a list of possible values to select | #GtkComboBox |
| `COLUMN_HEADER` | A header in a columned list | #GtkColumnView |
| `DIALOG` | A dialog that prompts the user to enter information or require a response | #GtkDialog and subclasses |
| `GRID` | A grid of items | #GtkFlowBox, #GtkGridView |
| `GRID_CELL` | An item in a grid | #GtkFlowBoxChild, #GtkGridView, #GtkColumnView |
| `IMG` | An image | #GtkImage, #GtkPicture |
| `LABEL` | A visible name or caption for a user interface component | #GtkLabel |
| `LIST` | A list of items | #GtkListBox |
| `LIST_ITEM` | An item in a list | #GtkListBoxRow |
| `METER` | Represents a value within a known range | #GtkLevelBar |
| `PROGRESS_BAR` | An element that display progress | #GtkProgressBar |
| `RADIO` | A checkable input in a group of radio roles | #GtkCheckButton |
| `ROW` | A row in a columned list | #GtkColumnView |
| `SCROLLBAR` | A graphical object controlling the scrolling of content | #GtkScrollbar |
| `SEARCH_BOX` | A text box for entering search criteria | #GtkSearchEntry |
| `SEPARATOR` | A divider that separates sections of content or groups of items | #GtkSeparator |
| `SPIN_BUTTON` | A range control that allows seelcting among discrete choices | #GtkSpinButton |
| `SWITCH` | A control that represents on/off values | #GtkSwitch |
| `TAB` | A tab in a list of tabs for switching pages | #GtkStackSwitcher, #GtkNotebook |
| `TAB_LIST` | A list of tabs for switching pages | #GtkStackSwitcher, #GtkNotebook |
| `TAB_PANEL` | A page in a notebook or stack | #GtkStack |
| `TEXT_BOX` | A type of input that allows free-form text as its value. | #GtkEntry, #GtkPasswordEntry, #GtkTextView |
| `TREE_GRID` | A treeview-like columned list | #GtkColumnView |
| `WINDOW` | An application window | #GtkWindow |
| `...` | … |

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

1416
gtk/a11y/gtkatspicontext.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
/* 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);
GVariant *
gtk_at_spi_context_to_ref (GtkAtSpiContext *self);
G_END_DECLS

View File

@ -0,0 +1,356 @@
/* 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 "gtkeditable.h"
#include "gtkentry.h"
#include "gtksearchentry.h"
#include "gtkpasswordentry.h"
#include "gtkspinbutton.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
entry_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 entry_vtable = {
entry_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 (GtkAccessible *accessible)
{
if (GTK_IS_ENTRY (accessible) ||
GTK_IS_SEARCH_ENTRY (accessible) ||
GTK_IS_PASSWORD_ENTRY (accessible) ||
GTK_IS_SPIN_BUTTON (accessible))
return &entry_vtable;
else if (GTK_IS_TEXT_VIEW (accessible))
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 "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_editable_text_vtable (GtkAccessible *accessible);
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

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

@ -0,0 +1,603 @@
/* 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 "gtkaccessibleprivate.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

1060
gtk/a11y/gtkatspiselection.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
/* gtkatspiselectionprivate.h: AT-SPI Selection 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 "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_selection_vtable (GtkAccessible *accessible,
GtkAccessibleRole role);
typedef void (GtkAtspiSelectionCallback) (gpointer data);
void gtk_atspi_connect_selection_signals (GtkAccessible *accessible,
GtkAtspiSelectionCallback selection_changed,
gpointer data);
void gtk_atspi_disconnect_selection_signals (GtkAccessible *accessible);
G_END_DECLS

1452
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,55 @@
/* 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,45 @@
/* 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 "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_text_vtable (GtkAccessible *accessible);
typedef void (GtkAtspiTextChangedCallback) (gpointer data,
const char *kind,
int start,
int end,
const char *text);
typedef void (GtkAtspiTextSelectionCallback) (gpointer data,
const char *kind,
int position);
void gtk_atspi_connect_text_signals (GtkAccessible *accessible,
GtkAtspiTextChangedCallback text_changed,
GtkAtspiTextSelectionCallback selection_changed,
gpointer data);
void gtk_atspi_disconnect_text_signals (GtkAccessible *accessible);
G_END_DECLS

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

@ -0,0 +1,307 @@
/* 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"
#include "gtkenums.h"
#include "gtkpasswordentry.h"
/*< private >
* gtk_accessible_role_to_atspi_role:
* @role: a #GtkAccessibleRole
*
* Converts a #GtkAccessibleRole value to the equivalent ATSPI role.
*
* Returns: an #AtspiRole
*/
static 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_PAGE_TAB;
case GTK_ACCESSIBLE_ROLE_TABLE:
return ATSPI_ROLE_TABLE;
case GTK_ACCESSIBLE_ROLE_TAB_LIST:
return ATSPI_ROLE_PAGE_TAB_LIST;
case GTK_ACCESSIBLE_ROLE_TAB_PANEL:
return ATSPI_ROLE_PANEL;
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;
}
/*<private>
* gtk_atspi_role_for_context:
* @context: a #GtkATContext
*
* Returns a suitable ATSPI role for a context, taking into account
* both the #GtkAccessibleRole set on the context and the type
* of accessible.
*
* Returns: an #AtspiRole
*/
AtspiRole
gtk_atspi_role_for_context (GtkATContext *context)
{
GtkAccessible *accessible = gtk_at_context_get_accessible (context);
GtkAccessibleRole role = gtk_at_context_get_accessible_role (context);
if (GTK_IS_PASSWORD_ENTRY (accessible))
return ATSPI_ROLE_PASSWORD_TEXT;
return gtk_accessible_role_to_atspi_role (role);
}
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 "gtkatcontextprivate.h"
G_BEGIN_DECLS
AtspiRole
gtk_atspi_role_for_context (GtkATContext *context);
GVariant *
gtk_at_spi_null_ref (void);
G_END_DECLS

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

@ -0,0 +1,129 @@
/* gtkatspivalue.c: 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/>.
*/
#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 (GtkAccessible *accessible)
{
if (GTK_IS_LEVEL_BAR (accessible) ||
GTK_IS_PANED (accessible) ||
GTK_IS_PROGRESS_BAR (accessible) ||
GTK_IS_RANGE (accessible) ||
GTK_IS_SCALE_BUTTON (accessible) ||
GTK_IS_SPIN_BUTTON (accessible))
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 "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_value_vtable (GtkAccessible *accessible);
G_END_DECLS

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

@ -0,0 +1,23 @@
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',
'gtkatspiselection.c',
])
endif

View File

@ -102,7 +102,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkInfoBar, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLevelBar, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLinkButton, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkListStore, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkListView, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLockButton, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkMenuButton, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkMessageDialog, g_object_unref)

View File

@ -47,6 +47,9 @@
#include "gtkatcontextprivate.h"
#include "gtkenums.h"
#include "gtktypebuiltins.h"
#include "gtkwidget.h"
#include <glib/gi18n-lib.h>
#include <stdarg.h>
@ -532,3 +535,192 @@ 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];
}
/*<private>
* gtk_accessible_platform_changed:
* @self: a #GtkAccessible
* @change: the platform state change to report
*
* ARIA discriminates between author-controlled states
* and 'platform' states, which are not. This function
* can be used by widgets to inform ATs that a platform
* state, such as focus, has changed.
*
* Note that the state itself is not included in this API.
* AT backends should use gtk_accessible_get_platform_state()
* to obtain the actual state.
*/
void
gtk_accessible_platform_changed (GtkAccessible *self,
GtkAccessiblePlatformChange change)
{
GtkATContext *context;
if (GTK_IS_WIDGET (self) &&
gtk_widget_get_root (GTK_WIDGET (self)) == NULL)
return;
context = gtk_accessible_get_at_context (self);
/* propagate changes up from ignored widgets */
if (gtk_accessible_get_accessible_role (self) == GTK_ACCESSIBLE_ROLE_NONE)
{
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (gtk_widget_get_parent (GTK_WIDGET (self))));
}
if (context == NULL)
return;
gtk_at_context_platform_changed (context, change);
gtk_at_context_update (context);
}
/*<private>
* gtk_accessible_get_platform_state:
* @self: a #GtkAccessible
* @state: platform state to query
*
* Query a platform state, such as focus.
*
* See gtk_accessible_platform_changed().
*
* This functionality can be overridden by #GtkAccessible
* implementations, e.g. to get platform state from an ignored
* child widget, as is the case for #GtkText wrappers.
*
* Returns: the value of @state for the accessible
*/
gboolean
gtk_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
return GTK_ACCESSIBLE_GET_IFACE (self)->get_platform_state (self, state);
}
/*<private>
* gtk_accessible_should_present:
* @self: a #GtkAccessible
*
* Returns whether this accessible should be represented to ATs.
*
* By default, hidden widgets are are among these, but there can
* be other reasons to return %FALSE, e.g. for widgets that are
* purely presentations, or for widgets whose functionality is
* represented elsewhere, as is the case for #GtkText widgets.
*
* Returns: %TRUE if the widget should be represented
*/
gboolean
gtk_accessible_should_present (GtkAccessible *self)
{
if (GTK_IS_WIDGET (self) &&
!gtk_widget_get_visible (GTK_WIDGET (self)))
return FALSE;
if (gtk_accessible_get_accessible_role (self) == GTK_ACCESSIBLE_ROLE_NONE)
return FALSE;
return TRUE;
}

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
@ -30,8 +30,21 @@ struct _GtkAccessibleInterface
GTypeInterface g_iface;
GtkATContext * (* get_at_context) (GtkAccessible *self);
gboolean (* get_platform_state) (GtkAccessible *self,
GtkAccessiblePlatformState state);
};
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);
gboolean gtk_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state);
gboolean gtk_accessible_should_present (GtkAccessible *self);
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,31 @@ 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;
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 +506,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 +519,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 +729,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,23 @@ typedef enum {
GTK_ACCESSIBLE_STATE_CHANGE_SELECTED = 1 << GTK_ACCESSIBLE_STATE_SELECTED
} GtkAccessibleStateChange;
typedef enum {
GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
} GtkAccessiblePlatformState;
typedef enum {
GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSABLE = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
} GtkAccessiblePlatformChange;
struct _GtkATContext
{
GObject parent_instance;
GtkAccessibleRole accessible_role;
GtkAccessible *accessible;
GdkDisplay *display;
GtkAccessibleAttributeSet *states;
GtkAccessibleAttributeSet *properties;
@ -94,6 +105,7 @@ struct _GtkATContext
GtkAccessibleStateChange updated_states;
GtkAccessiblePropertyChange updated_properties;
GtkAccessibleRelationChange updated_relations;
GtkAccessiblePlatformChange updated_platform;
};
struct _GtkATContextClass
@ -104,11 +116,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 +148,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

@ -30,7 +30,7 @@
#include "gtkcssnodeprivate.h"
#include "gtkdropcontrollermotion.h"
#include "gtkintl.h"
#include "gtklistview.h"
#include "gtklistviewprivate.h"
#include "gtkmain.h"
#include "gtkprivate.h"
#include "gtkscrollable.h"
@ -106,6 +106,44 @@
* .rich-list, .navigation-sidebar or .data-table.
*/
/* We create a subclass of GtkListView for the sole purpose of overriding
* some parameters for item creation.
*/
#define GTK_TYPE_COLUMN_LIST_VIEW (gtk_column_list_view_get_type ())
G_DECLARE_FINAL_TYPE (GtkColumnListView, gtk_column_list_view, GTK, COLUMN_LIST_VIEW, GtkListView)
struct _GtkColumnListView
{
GtkListView parent_instance;
};
struct _GtkColumnListViewClass
{
GtkListViewClass parent_class;
};
G_DEFINE_TYPE (GtkColumnListView, gtk_column_list_view, GTK_TYPE_LIST_VIEW)
static void
gtk_column_list_view_init (GtkColumnListView *view)
{
}
static void
gtk_column_list_view_class_init (GtkColumnListViewClass *klass)
{
GtkListBaseClass *list_base_class = GTK_LIST_BASE_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
list_base_class->list_item_name = "row";
list_base_class->list_item_role = GTK_ACCESSIBLE_ROLE_ROW;
gtk_widget_class_set_css_name (widget_class, I_("listview"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_LIST);
}
struct _GtkColumnView
{
GtkWidget parent_instance;
@ -733,6 +771,7 @@ gtk_column_view_class_init (GtkColumnViewClass *klass)
g_cclosure_marshal_VOID__UINTv);
gtk_widget_class_set_css_name (widget_class, I_("columnview"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_TREE_GRID);
}
static void update_column_resize (GtkColumnView *self,
@ -1136,7 +1175,7 @@ gtk_column_view_init (GtkColumnView *self)
self->columns = g_list_store_new (GTK_TYPE_COLUMN_VIEW_COLUMN);
self->header = gtk_list_item_widget_new (NULL, "header");
self->header = gtk_list_item_widget_new (NULL, "header", GTK_ACCESSIBLE_ROLE_ROW);
gtk_widget_set_can_focus (self->header, FALSE);
gtk_widget_set_layout_manager (self->header, gtk_column_view_layout_new (self));
gtk_widget_set_parent (self->header, GTK_WIDGET (self));
@ -1164,8 +1203,8 @@ gtk_column_view_init (GtkColumnView *self)
self->sorter = GTK_SORTER (gtk_column_view_sorter_new ());
self->factory = gtk_column_list_item_factory_new (self);
self->listview = GTK_LIST_VIEW (gtk_list_view_new (NULL,
GTK_LIST_ITEM_FACTORY (g_object_ref (self->factory))));
self->listview = GTK_LIST_VIEW (g_object_new (GTK_TYPE_COLUMN_LIST_VIEW, NULL));
gtk_list_view_set_factory (self->listview, GTK_LIST_ITEM_FACTORY (self->factory));
gtk_widget_set_hexpand (GTK_WIDGET (self->listview), TRUE);
gtk_widget_set_vexpand (GTK_WIDGET (self->listview), TRUE);
g_signal_connect (self->listview, "activate", G_CALLBACK (gtk_column_view_activate_cb), self);

View File

@ -204,6 +204,7 @@ gtk_column_view_cell_class_init (GtkColumnViewCellClass *klass)
gobject_class->dispose = gtk_column_view_cell_dispose;
gtk_widget_class_set_css_name (widget_class, I_("cell"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GRID_CELL);
}
static void

View File

@ -171,6 +171,7 @@ gtk_column_view_title_class_init (GtkColumnViewTitleClass *klass)
gobject_class->dispose = gtk_column_view_title_dispose;
gtk_widget_class_set_css_name (widget_class, I_("button"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_COLUMN_HEADER);
}
static void

View File

@ -103,6 +103,10 @@
* contains a box with the .linked class. That box contains an entry and a
* button, both with the .combo class added.
* The button also contains another node with name arrow.
*
* # Accessibility
*
* GtkComboBox uses the #GTK_ACCESSIBLE_ROLE_COMBO_BOX role.
*/
@ -797,6 +801,7 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
gtk_widget_class_bind_template_callback (widget_class, gtk_combo_box_menu_hide);
gtk_widget_class_set_css_name (widget_class, I_("combobox"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_COMBO_BOX);
}
static void

View File

@ -71,6 +71,10 @@
*
* GtkDropDown has a single CSS node with name dropdown,
* with the button and popover nodes as children.
*
* # Accessibility
*
* GtkDropDown uses the #GTK_ACCESSIBLE_ROLE_COMBO_BOX role.
*/
struct _GtkDropDown
@ -525,6 +529,7 @@ gtk_drop_down_class_init (GtkDropDownClass *klass)
gtk_widget_class_bind_template_callback (widget_class, search_stop);
gtk_widget_class_set_css_name (widget_class, I_("dropdown"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_COMBO_BOX);
}
static void

View File

@ -30,6 +30,7 @@
#include "gtkentryprivate.h"
#include "gtkaccessibleprivate.h"
#include "gtkadjustment.h"
#include "gtkbox.h"
#include "gtkbutton.h"
@ -320,9 +321,12 @@ static void gtk_entry_measure (GtkWidget *widget,
static GtkBuildableIface *buildable_parent_iface = NULL;
static void gtk_entry_buildable_interface_init (GtkBuildableIface *iface);
static void gtk_entry_accessible_interface_init (GtkAccessibleInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkEntry)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE,
gtk_entry_accessible_interface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_entry_buildable_interface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
@ -330,6 +334,37 @@ G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
gtk_entry_cell_editable_init))
/* Implement the GtkAccessible interface, in order to obtain focus
* state from the #GtkText widget that we are wrapping. The GtkText
* widget is ignored for accessibility purposes (it has role NONE),
* and any a11y text functionality is implemented for GtkEntry and
* similar wrappers (GtkPasswordEntry, GtkSpinButton, etc).
*/
static gboolean
gtk_entry_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
GtkEntry *entry = GTK_ENTRY (self);
GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
switch (state)
{
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE:
return gtk_widget_get_focusable (GTK_WIDGET (priv->text));
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
return gtk_widget_has_focus (GTK_WIDGET (priv->text));
default:
g_assert_not_reached ();
}
}
static void
gtk_entry_accessible_interface_init (GtkAccessibleInterface *iface)
{
GtkAccessibleInterface *parent_iface = g_type_interface_peek_parent (iface);
iface->get_at_context = parent_iface->get_at_context;
iface->get_platform_state = gtk_entry_accessible_get_platform_state;
}
static const GtkBuildableParser pango_parser =
{

View File

@ -1161,7 +1161,7 @@ typedef enum {
* @GTK_ACCESSIBLE_ROLE_CELL: Unused
* @GTK_ACCESSIBLE_ROLE_CHECKBOX: A checkable input element that has
* three possible values: `true`, `false`, or `mixed`
* @GTK_ACCESSIBLE_ROLE_COLUMN_HEADER: Unused
* @GTK_ACCESSIBLE_ROLE_COLUMN_HEADER: A header in a columned list.
* @GTK_ACCESSIBLE_ROLE_COMBO_BOX: An input that controls another element,
* such as a list or a grid, that can dynamically pop up to help the user
* set the value of the input
@ -1175,8 +1175,8 @@ typedef enum {
* @GTK_ACCESSIBLE_ROLE_FEED: Unused
* @GTK_ACCESSIBLE_ROLE_FORM: Unused
* @GTK_ACCESSIBLE_ROLE_GENERIC: Unused
* @GTK_ACCESSIBLE_ROLE_GRID: Unused
* @GTK_ACCESSIBLE_ROLE_GRID_CELL: Unused
* @GTK_ACCESSIBLE_ROLE_GRID: A grid of items.
* @GTK_ACCESSIBLE_ROLE_GRID_CELL: An item in a grid or tree grid.
* @GTK_ACCESSIBLE_ROLE_GROUP: Unused
* @GTK_ACCESSIBLE_ROLE_HEADING: Unused
* @GTK_ACCESSIBLE_ROLE_IMG: An image.
@ -1185,9 +1185,9 @@ typedef enum {
* @GTK_ACCESSIBLE_ROLE_LANDMARK: Unused
* @GTK_ACCESSIBLE_ROLE_LEGEND: Unused
* @GTK_ACCESSIBLE_ROLE_LINK: Unused
* @GTK_ACCESSIBLE_ROLE_LIST: Unused
* @GTK_ACCESSIBLE_ROLE_LIST_BOX: Unused
* @GTK_ACCESSIBLE_ROLE_LIST_ITEM: Unused
* @GTK_ACCESSIBLE_ROLE_LIST: A list of items.
* @GTK_ACCESSIBLE_ROLE_LIST_BOX: Unused.
* @GTK_ACCESSIBLE_ROLE_LIST_ITEM: An item in a list.
* @GTK_ACCESSIBLE_ROLE_LOG: Unused
* @GTK_ACCESSIBLE_ROLE_MAIN: Unused
* @GTK_ACCESSIBLE_ROLE_MARQUEE: Unused
@ -1210,7 +1210,7 @@ typedef enum {
* @GTK_ACCESSIBLE_ROLE_RADIO_GROUP: Unused
* @GTK_ACCESSIBLE_ROLE_RANGE: Unused
* @GTK_ACCESSIBLE_ROLE_REGION: Unused
* @GTK_ACCESSIBLE_ROLE_ROW: Unused
* @GTK_ACCESSIBLE_ROLE_ROW: A row in a columned list.
* @GTK_ACCESSIBLE_ROLE_ROW_GROUP: Unused
* @GTK_ACCESSIBLE_ROLE_ROW_HEADER: Unused
* @GTK_ACCESSIBLE_ROLE_SCROLLBAR: A graphical object that controls the scrolling
@ -1232,10 +1232,10 @@ typedef enum {
* @GTK_ACCESSIBLE_ROLE_STRUCTURE: Unused
* @GTK_ACCESSIBLE_ROLE_SWITCH: A type of checkbox that represents on/off values,
* as opposed to checked/unchecked values.
* @GTK_ACCESSIBLE_ROLE_TAB: Unused
* @GTK_ACCESSIBLE_ROLE_TAB: An item in a list of tab used for switching pages.
* @GTK_ACCESSIBLE_ROLE_TABLE: Unused
* @GTK_ACCESSIBLE_ROLE_TAB_LIST: Unused
* @GTK_ACCESSIBLE_ROLE_TAB_PANEL: Unused
* @GTK_ACCESSIBLE_ROLE_TAB_LIST: A list of tabs for switching pages.
* @GTK_ACCESSIBLE_ROLE_TAB_PANEL: A page in a notebook or stack.
* @GTK_ACCESSIBLE_ROLE_TEXT_BOX: A type of input that allows free-form text
* as its value.
* @GTK_ACCESSIBLE_ROLE_TIME: Unused
@ -1243,7 +1243,7 @@ typedef enum {
* @GTK_ACCESSIBLE_ROLE_TOOLBAR: Unused
* @GTK_ACCESSIBLE_ROLE_TOOLTIP: Unused
* @GTK_ACCESSIBLE_ROLE_TREE: Unused
* @GTK_ACCESSIBLE_ROLE_TREE_GRID: Unused
* @GTK_ACCESSIBLE_ROLE_TREE_GRID: A treeview-like, columned list.
* @GTK_ACCESSIBLE_ROLE_TREE_ITEM: Unused
* @GTK_ACCESSIBLE_ROLE_WIDGET: An interactive component of a graphical user
* interface. This is the role that GTK uses by default for widgets.

View File

@ -75,6 +75,7 @@
#include "gtkflowboxprivate.h"
#include "gtkaccessible.h"
#include "gtkadjustment.h"
#include "gtkbinlayout.h"
#include "gtkbuildable.h"
@ -483,6 +484,18 @@ gtk_flow_box_child_compute_expand (GtkWidget *widget,
}
}
static void
gtk_flow_box_child_root (GtkWidget *widget)
{
GtkFlowBoxChild *child = GTK_FLOW_BOX_CHILD (widget);
GTK_WIDGET_CLASS (gtk_flow_box_child_parent_class)->root (widget);
gtk_accessible_update_state (GTK_ACCESSIBLE (child),
GTK_ACCESSIBLE_STATE_SELECTED, CHILD_PRIV (child)->selected,
-1);
}
/* GObject implementation {{{2 */
static void
@ -495,6 +508,7 @@ gtk_flow_box_child_class_init (GtkFlowBoxChildClass *class)
object_class->get_property = gtk_flow_box_child_get_property;
object_class->set_property = gtk_flow_box_child_set_property;
widget_class->root = gtk_flow_box_child_root;
widget_class->get_request_mode = gtk_flow_box_child_get_request_mode;
widget_class->compute_expand = gtk_flow_box_child_compute_expand;
widget_class->focus = gtk_flow_box_child_focus;
@ -533,6 +547,7 @@ gtk_flow_box_child_class_init (GtkFlowBoxChildClass *class)
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_css_name (widget_class, I_("flowboxchild"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GRID_CELL);
}
static void
@ -905,6 +920,9 @@ gtk_flow_box_child_set_selected (GtkFlowBoxChild *child,
gtk_widget_unset_state_flags (GTK_WIDGET (child),
GTK_STATE_FLAG_SELECTED);
gtk_accessible_update_state (GTK_ACCESSIBLE (child),
GTK_ACCESSIBLE_STATE_SELECTED, selected,
-1);
return TRUE;
}
@ -3870,6 +3888,7 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
NULL);
gtk_widget_class_set_css_name (widget_class, I_("flowbox"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GRID);
}
static void
@ -4724,6 +4743,10 @@ gtk_flow_box_set_selection_mode (GtkFlowBox *box,
BOX_PRIV (box)->selection_mode = mode;
gtk_accessible_update_property (GTK_ACCESSIBLE (box),
GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE, mode == GTK_SELECTION_MULTIPLE,
-1);
g_object_notify_by_pspec (G_OBJECT (box), props[PROP_SELECTION_MODE]);
if (dirty)

View File

@ -130,9 +130,30 @@ gtk_gizmo_new (const char *css_name,
GtkGizmoContainsFunc contains_func,
GtkGizmoFocusFunc focus_func,
GtkGizmoGrabFocusFunc grab_focus_func)
{
return gtk_gizmo_new_with_role (css_name,
GTK_ACCESSIBLE_ROLE_WIDGET,
measure_func,
allocate_func,
snapshot_func,
contains_func,
focus_func,
grab_focus_func);
}
GtkWidget *
gtk_gizmo_new_with_role (const char *css_name,
GtkAccessibleRole role,
GtkGizmoMeasureFunc measure_func,
GtkGizmoAllocateFunc allocate_func,
GtkGizmoSnapshotFunc snapshot_func,
GtkGizmoContainsFunc contains_func,
GtkGizmoFocusFunc focus_func,
GtkGizmoGrabFocusFunc grab_focus_func)
{
GtkGizmo *gizmo = GTK_GIZMO (g_object_new (GTK_TYPE_GIZMO,
"css-name", css_name,
"accessible-role", role,
NULL));
gizmo->measure_func = measure_func;

View File

@ -3,6 +3,7 @@
#define __GTK_GIZMO_H__
#include "gtkwidget.h"
#include "gtkenums.h"
#define GTK_TYPE_GIZMO (gtk_gizmo_get_type ())
#define GTK_GIZMO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_GIZMO, GtkGizmo))
@ -61,5 +62,14 @@ GtkWidget *gtk_gizmo_new (const char *css_name,
GtkGizmoFocusFunc focus_func,
GtkGizmoGrabFocusFunc grab_focus_func);
GtkWidget *gtk_gizmo_new_with_role (const char *css_name,
GtkAccessibleRole role,
GtkGizmoMeasureFunc measure_func,
GtkGizmoAllocateFunc allocate_func,
GtkGizmoSnapshotFunc snapshot_func,
GtkGizmoContainsFunc contains_func,
GtkGizmoFocusFunc focus_func,
GtkGizmoGrabFocusFunc grab_focus_func);
#endif

View File

@ -30,6 +30,7 @@
#include "gtkprivate.h"
#include "gtksingleselection.h"
#include "gtkwidgetprivate.h"
#include "gtkmultiselection.h"
/* Maximum number of list items created by the gridview.
* For debugging, you can set this to G_MAXUINT to ensure
@ -1025,6 +1026,7 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
list_base_class->list_item_name = "child";
list_base_class->list_item_role = GTK_ACCESSIBLE_ROLE_GRID_CELL;
list_base_class->list_item_size = sizeof (Cell);
list_base_class->list_item_augment_size = sizeof (CellAugment);
list_base_class->list_item_augment_func = cell_augment;
@ -1157,6 +1159,7 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
gtk_grid_view_activate_item);
gtk_widget_class_set_css_name (widget_class, I_("gridview"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GRID);
}
static void
@ -1246,6 +1249,10 @@ gtk_grid_view_set_model (GtkGridView *self,
if (!gtk_list_base_set_model (GTK_LIST_BASE (self), model))
return;
gtk_accessible_update_property (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE, GTK_IS_MULTI_SELECTION (model),
-1);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]);
}

View File

@ -1794,6 +1794,7 @@ gtk_list_base_init_real (GtkListBase *self,
priv->item_manager = gtk_list_item_manager_new_for_size (GTK_WIDGET (self),
g_class->list_item_name,
g_class->list_item_role,
g_class->list_item_size,
g_class->list_item_augment_size,
g_class->list_item_augment_func);

View File

@ -35,6 +35,7 @@ struct _GtkListBaseClass
GtkWidgetClass parent_class;
const char * list_item_name;
GtkAccessibleRole list_item_role;
gsize list_item_size;
gsize list_item_augment_size;
GtkRbTreeAugmentFunc list_item_augment_func;

View File

@ -19,6 +19,7 @@
#include "gtklistbox.h"
#include "gtkaccessible.h"
#include "gtkactionhelperprivate.h"
#include "gtkadjustmentprivate.h"
#include "gtkbinlayout.h"
@ -678,6 +679,7 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
NULL);
gtk_widget_class_set_css_name (widget_class, I_("list"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_LIST);
}
static void
@ -1119,6 +1121,10 @@ gtk_list_box_set_selection_mode (GtkListBox *box,
gtk_list_box_update_row_styles (box);
gtk_accessible_update_property (GTK_ACCESSIBLE (box),
GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE, mode == GTK_SELECTION_MULTIPLE,
-1);
g_object_notify_by_pspec (G_OBJECT (box), properties[PROP_SELECTION_MODE]);
if (dirty)
@ -1558,6 +1564,10 @@ gtk_list_box_row_set_selected (GtkListBoxRow *row,
gtk_widget_unset_state_flags (GTK_WIDGET (row),
GTK_STATE_FLAG_SELECTED);
gtk_accessible_update_state (GTK_ACCESSIBLE (row),
GTK_ACCESSIBLE_STATE_SELECTED, selected,
-1);
return TRUE;
}
@ -3019,6 +3029,19 @@ gtk_list_box_row_hide (GtkWidget *widget)
gtk_list_box_row_visibility_changed (box, row);
}
static void
gtk_list_box_row_root (GtkWidget *widget)
{
GtkListBoxRow *row = GTK_LIST_BOX_ROW (widget);
GTK_WIDGET_CLASS (gtk_list_box_row_parent_class)->root (widget);
if (ROW_PRIV (row)->selectable)
gtk_accessible_update_state (GTK_ACCESSIBLE (row),
GTK_ACCESSIBLE_STATE_SELECTED, ROW_PRIV (row)->selected,
-1);
}
/**
* gtk_list_box_row_changed:
* @row: a #GtkListBoxRow
@ -3228,10 +3251,19 @@ gtk_list_box_row_set_selectable (GtkListBoxRow *row,
{
if (!selectable)
gtk_list_box_row_set_selected (row, FALSE);
ROW_PRIV (row)->selectable = selectable;
if (selectable)
gtk_accessible_update_state (GTK_ACCESSIBLE (row),
GTK_ACCESSIBLE_STATE_SELECTED, FALSE,
-1);
else
gtk_accessible_reset_state (GTK_ACCESSIBLE (row),
GTK_ACCESSIBLE_STATE_SELECTED);
gtk_list_box_update_row_style (gtk_list_box_row_get_box (row), row);
g_object_notify_by_pspec (G_OBJECT (row), row_properties[ROW_PROP_SELECTABLE]);
}
}
@ -3413,6 +3445,7 @@ gtk_list_box_row_class_init (GtkListBoxRowClass *klass)
object_class->finalize = gtk_list_box_row_finalize;
object_class->dispose = gtk_list_box_row_dispose;
widget_class->root = gtk_list_box_row_root;
widget_class->show = gtk_list_box_row_show;
widget_class->hide = gtk_list_box_row_hide;
widget_class->focus = gtk_list_box_row_focus;
@ -3478,6 +3511,7 @@ gtk_list_box_row_class_init (GtkListBoxRowClass *klass)
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_css_name (widget_class, I_("row"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_LIST_ITEM);
}
static void

View File

@ -35,6 +35,7 @@ struct _GtkListItemManager
GtkListItemFactory *factory;
gboolean single_click_activate;
const char *item_css_name;
GtkAccessibleRole item_role;
GtkRbTree *items;
GSList *trackers;
@ -111,6 +112,7 @@ gtk_list_item_manager_clear_node (gpointer _item)
GtkListItemManager *
gtk_list_item_manager_new_for_size (GtkWidget *widget,
const char *item_css_name,
GtkAccessibleRole item_role,
gsize element_size,
gsize augment_size,
GtkRbTreeAugmentFunc augment_func)
@ -126,6 +128,7 @@ gtk_list_item_manager_new_for_size (GtkWidget *widget,
/* not taking a ref because the widget refs us */
self->widget = widget;
self->item_css_name = g_intern_string (item_css_name);
self->item_role = item_role;
self->items = gtk_rb_tree_new_for_size (element_size,
augment_size,
@ -923,7 +926,8 @@ gtk_list_item_manager_acquire_list_item (GtkListItemManager *self,
g_return_val_if_fail (prev_sibling == NULL || GTK_IS_WIDGET (prev_sibling), NULL);
result = gtk_list_item_widget_new (self->factory,
self->item_css_name);
self->item_css_name,
self->item_role);
gtk_list_item_widget_set_single_click_activate (GTK_LIST_ITEM_WIDGET (result), self->single_click_activate);

View File

@ -22,6 +22,7 @@
#define __GTK_LIST_ITEM_MANAGER_H__
#include "gtk/gtktypes.h"
#include "gtk/gtkenums.h"
#include "gtk/gtklistitemfactory.h"
#include "gtk/gtkrbtreeprivate.h"
@ -58,6 +59,7 @@ GType gtk_list_item_manager_get_type (void) G_GNUC_CO
GtkListItemManager * gtk_list_item_manager_new_for_size (GtkWidget *widget,
const char *item_css_name,
GtkAccessibleRole item_role,
gsize element_size,
gsize augment_size,
GtkRbTreeAugmentFunc augment_func);

View File

@ -453,12 +453,14 @@ gtk_list_item_widget_init (GtkListItemWidget *self)
GtkWidget *
gtk_list_item_widget_new (GtkListItemFactory *factory,
const char *css_name)
const char *css_name,
GtkAccessibleRole role)
{
g_return_val_if_fail (css_name != NULL, NULL);
return g_object_new (GTK_TYPE_LIST_ITEM_WIDGET,
"css-name", css_name,
"accessible-role", role,
"factory", factory,
NULL);
}
@ -480,6 +482,10 @@ gtk_list_item_widget_update (GtkListItemWidget *self,
gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE);
else
gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED);
gtk_accessible_update_state (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_STATE_SELECTED, selected,
-1);
}
void

View File

@ -50,7 +50,8 @@ struct _GtkListItemWidgetClass
GType gtk_list_item_widget_get_type (void) G_GNUC_CONST;
GtkWidget * gtk_list_item_widget_new (GtkListItemFactory *factory,
const char *css_name);
const char *css_name,
GtkAccessibleRole role);
void gtk_list_item_widget_update (GtkListItemWidget *self,
guint position,

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "gtklistview.h"
#include "gtklistviewprivate.h"
#include "gtkbitset.h"
#include "gtkintl.h"
@ -29,6 +29,7 @@
#include "gtkprivate.h"
#include "gtkrbtreeprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkmultiselection.h"
/* Maximum number of list items created by the listview.
* For debugging, you can set this to G_MAXUINT to ensure
@ -139,21 +140,6 @@
typedef struct _ListRow ListRow;
typedef struct _ListRowAugment ListRowAugment;
struct _GtkListView
{
GtkListBase parent_instance;
GtkListItemManager *item_manager;
gboolean show_separators;
int list_width;
};
struct _GtkListViewClass
{
GtkListBaseClass parent_class;
};
struct _ListRow
{
GtkListItemManagerItem parent;
@ -799,6 +785,7 @@ gtk_list_view_class_init (GtkListViewClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
list_base_class->list_item_name = "row";
list_base_class->list_item_role = GTK_ACCESSIBLE_ROLE_LIST_ITEM;
list_base_class->list_item_size = sizeof (ListRow);
list_base_class->list_item_augment_size = sizeof (ListRowAugment);
list_base_class->list_item_augment_func = list_row_augment;
@ -915,6 +902,7 @@ gtk_list_view_class_init (GtkListViewClass *klass)
gtk_list_view_activate_item);
gtk_widget_class_set_css_name (widget_class, I_("listview"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_LIST);
}
static void
@ -1000,6 +988,10 @@ gtk_list_view_set_model (GtkListView *self,
if (!gtk_list_base_set_model (GTK_LIST_BASE (self), model))
return;
gtk_accessible_update_property (GTK_ACCESSIBLE (self),
GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE, GTK_IS_MULTI_SELECTION (model),
-1);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]);
}

View File

@ -81,6 +81,8 @@ void gtk_list_view_set_enable_rubberband (GtkListView
GDK_AVAILABLE_IN_ALL
gboolean gtk_list_view_get_enable_rubberband (GtkListView *self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkListView, g_object_unref)
G_END_DECLS
#endif /* __GTK_LIST_VIEW_H__ */

45
gtk/gtklistviewprivate.h Normal file
View File

@ -0,0 +1,45 @@
/*
* 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.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/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_LIST_VIEW_PRIVATE_H__
#define __GTK_LIST_VIEW_PRIVATE_H__
#include <gtk/gtklistview.h>
#include <gtk/gtklistbaseprivate.h>
G_BEGIN_DECLS
struct _GtkListView
{
GtkListBase parent_instance;
GtkListItemManager *item_manager;
gboolean show_separators;
int list_width;
};
struct _GtkListViewClass
{
GtkListBaseClass parent_class;
};
G_END_DECLS
#endif /* __GTK_LIST_VIEW_H__ */

View File

@ -144,6 +144,12 @@
* A tab node gets the .dnd style class while it is moved with drag-and-drop.
*
* The nodes are always arranged from left-to-right, regardless of text direction.
*
* # Accessibility
*
* GtkNotebook uses the #GTK_ACCESSIBLE_ROLE_TAB_LIST and
* #GTK_ACCESSIBLE_ROLE_TAB roles for its list of tabs and the
* #GTK_ACCESSIBLE_ROLE_TAB_PANEL for the pages.
*/
@ -1404,13 +1410,14 @@ gtk_notebook_init (GtkNotebook *notebook)
gtk_widget_hide (notebook->header_widget);
gtk_widget_set_parent (notebook->header_widget, GTK_WIDGET (notebook));
notebook->tabs_widget = gtk_gizmo_new ("tabs",
gtk_notebook_measure_tabs,
gtk_notebook_allocate_tabs,
gtk_notebook_snapshot_tabs,
NULL,
(GtkGizmoFocusFunc)gtk_widget_focus_self,
(GtkGizmoGrabFocusFunc)gtk_widget_grab_focus_self);
notebook->tabs_widget = gtk_gizmo_new_with_role ("tabs",
GTK_ACCESSIBLE_ROLE_TAB_LIST,
gtk_notebook_measure_tabs,
gtk_notebook_allocate_tabs,
gtk_notebook_snapshot_tabs,
NULL,
(GtkGizmoFocusFunc)gtk_widget_focus_self,
(GtkGizmoGrabFocusFunc)gtk_widget_grab_focus_self);
gtk_widget_set_hexpand (notebook->tabs_widget, TRUE);
gtk_box_append (GTK_BOX (notebook->header_widget), notebook->tabs_widget);
@ -3915,6 +3922,7 @@ gtk_notebook_insert_notebook_page (GtkNotebook *notebook,
GList *list;
GtkWidget *sibling;
GtkEventController *controller;
GtkStackPage *stack_page;
nchildren = g_list_length (notebook->children);
if ((position < 0) || (position > nchildren))
@ -3929,7 +3937,14 @@ gtk_notebook_insert_notebook_page (GtkNotebook *notebook,
else
sibling = notebook->arrow_widget[ARROW_RIGHT_AFTER];
page->tab_widget = gtk_gizmo_new ("tab", measure_tab, allocate_tab, NULL, NULL, NULL, NULL);
page->tab_widget = gtk_gizmo_new_with_role ("tab",
GTK_ACCESSIBLE_ROLE_TAB,
measure_tab,
allocate_tab,
NULL,
NULL,
NULL,
NULL);
g_object_set_data (G_OBJECT (page->tab_widget), "notebook", notebook);
gtk_widget_insert_before (page->tab_widget, notebook->tabs_widget, sibling);
controller = gtk_drop_controller_motion_new ();
@ -3951,6 +3966,15 @@ gtk_notebook_insert_notebook_page (GtkNotebook *notebook,
g_object_set_data (G_OBJECT (page->tab_label), "notebook", notebook);
}
stack_page = gtk_stack_get_page (GTK_STACK (notebook->stack_widget), page->child);
gtk_accessible_update_relation (GTK_ACCESSIBLE (page->tab_widget),
GTK_ACCESSIBLE_RELATION_CONTROLS, g_list_append (NULL, stack_page),
-1);
gtk_accessible_update_state (GTK_ACCESSIBLE (page->tab_widget),
GTK_ACCESSIBLE_STATE_SELECTED, FALSE,
-1);
gtk_notebook_update_labels (notebook);
if (!notebook->first_tab)
@ -5303,12 +5327,20 @@ gtk_notebook_real_switch_page (GtkNotebook *notebook,
if (focus)
child_has_focus = gtk_widget_is_ancestor (focus, notebook->cur_page->child);
gtk_widget_unset_state_flags (notebook->cur_page->tab_widget, GTK_STATE_FLAG_CHECKED);
gtk_accessible_update_state (GTK_ACCESSIBLE (notebook->cur_page->tab_widget),
GTK_ACCESSIBLE_STATE_SELECTED, FALSE,
-1);
}
notebook->cur_page = page;
gtk_widget_set_state_flags (page->tab_widget, GTK_STATE_FLAG_CHECKED, FALSE);
gtk_widget_set_visible (notebook->header_widget, notebook->show_tabs);
gtk_accessible_update_state (GTK_ACCESSIBLE (notebook->cur_page->tab_widget),
GTK_ACCESSIBLE_STATE_SELECTED, TRUE,
-1);
if (!notebook->focus_tab ||
notebook->focus_tab->data != (gpointer) notebook->cur_page)
notebook->focus_tab =

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

@ -22,6 +22,7 @@
#include "gtkpasswordentryprivate.h"
#include "gtkaccessibleprivate.h"
#include "gtktextprivate.h"
#include "gtkeditable.h"
#include "gtkeventcontrollerkey.h"
@ -104,8 +105,10 @@ enum {
static GParamSpec *props[NUM_PROPERTIES] = { NULL, };
static void gtk_password_entry_editable_init (GtkEditableInterface *iface);
static void gtk_password_entry_accessible_init (GtkAccessibleInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkPasswordEntry, gtk_password_entry, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE, gtk_password_entry_accessible_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_password_entry_editable_init))
static void
@ -486,6 +489,31 @@ gtk_password_entry_editable_init (GtkEditableInterface *iface)
iface->get_delegate = gtk_password_entry_get_delegate;
}
static gboolean
gtk_password_entry_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
GtkPasswordEntry *entry = GTK_PASSWORD_ENTRY (self);
switch (state)
{
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE:
return gtk_widget_get_focusable (GTK_WIDGET (entry->entry));
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
return gtk_widget_has_focus (GTK_WIDGET (entry->entry));
default:
g_assert_not_reached ();
}
}
static void
gtk_password_entry_accessible_init (GtkAccessibleInterface *iface)
{
GtkAccessibleInterface *parent_iface = g_type_interface_peek_parent (iface);
iface->get_at_context = parent_iface->get_at_context;
iface->get_platform_state = gtk_password_entry_accessible_get_platform_state;
}
GtkText *
gtk_password_entry_get_text_widget (GtkPasswordEntry *entry)
{

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

@ -29,6 +29,7 @@
#include "gtksearchentryprivate.h"
#include "gtkaccessibleprivate.h"
#include "gtkeditable.h"
#include "gtkboxlayout.h"
#include "gtkgestureclick.h"
@ -135,8 +136,11 @@ struct _GtkSearchEntryClass
};
static void gtk_search_entry_editable_init (GtkEditableInterface *iface);
static void gtk_search_entry_accessible_init (GtkAccessibleInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkSearchEntry, gtk_search_entry, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE,
gtk_search_entry_accessible_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
gtk_search_entry_editable_init))
@ -438,6 +442,31 @@ gtk_search_entry_editable_init (GtkEditableInterface *iface)
iface->get_delegate = gtk_search_entry_get_delegate;
}
static gboolean
gtk_search_entry_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
GtkSearchEntry *entry = GTK_SEARCH_ENTRY (self);
switch (state)
{
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE:
return gtk_widget_get_focusable (GTK_WIDGET (entry->entry));
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
return gtk_widget_has_focus (GTK_WIDGET (entry->entry));
default:
g_assert_not_reached ();
}
}
static void
gtk_search_entry_accessible_init (GtkAccessibleInterface *iface)
{
GtkAccessibleInterface *parent_iface = g_type_interface_peek_parent (iface);
iface->get_at_context = parent_iface->get_at_context;
iface->get_platform_state = gtk_search_entry_accessible_get_platform_state;
}
static void
gtk_search_entry_icon_release (GtkGestureClick *press,
int n_press,

View File

@ -29,6 +29,9 @@
#include "gtkspinbutton.h"
#include "gtkspinbuttonprivate.h"
#include "gtkaccessibleprivate.h"
#include "gtkadjustment.h"
#include "gtkbox.h"
#include "gtkbutton.h"
@ -305,12 +308,15 @@ static void gtk_spin_button_default_output (GtkSpinButton *spin_button);
static void gtk_spin_button_update_width_chars (GtkSpinButton *spin_button);
static void gtk_spin_button_accessible_init (GtkAccessibleInterface *iface);
static guint spinbutton_signals[LAST_SIGNAL] = {0};
static GParamSpec *spinbutton_props[NUM_SPINBUTTON_PROPS] = {NULL, };
G_DEFINE_TYPE_WITH_CODE (GtkSpinButton, gtk_spin_button, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE,
gtk_spin_button_accessible_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
gtk_spin_button_editable_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
@ -572,6 +578,31 @@ gtk_spin_button_editable_init (GtkEditableInterface *iface)
iface->insert_text = gtk_spin_button_insert_text;
}
static gboolean
gtk_spin_button_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
GtkSpinButton *spin_button = GTK_SPIN_BUTTON (self);
switch (state)
{
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE:
return gtk_widget_get_focusable (spin_button->entry);
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
return gtk_widget_has_focus (spin_button->entry);
default:
g_assert_not_reached ();
}
}
static void
gtk_spin_button_accessible_init (GtkAccessibleInterface *iface)
{
GtkAccessibleInterface *parent_iface = g_type_interface_peek_parent (iface);
iface->get_at_context = parent_iface->get_at_context;
iface->get_platform_state = gtk_spin_button_accessible_get_platform_state;
}
static void
gtk_cell_editable_spin_button_activated (GtkText *text, GtkSpinButton *spin)
{
@ -2310,3 +2341,10 @@ gtk_spin_button_update (GtkSpinButton *spin_button)
else
gtk_spin_button_set_value (spin_button, val);
}
GtkText *
gtk_spin_button_get_text_widget (GtkSpinButton *spin_button)
{
return GTK_TEXT (spin_button->entry);
}

View File

@ -0,0 +1,27 @@
/* GTK - The GIMP Toolkit
* 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/>.
*/
#pragma once
#include <gtk/gtkspinbutton.h>
#include <gtk/gtktext.h>
G_BEGIN_DECLS
GtkText *gtk_spin_button_get_text_widget (GtkSpinButton *spin_button);
G_END_DECLS

View File

@ -23,6 +23,9 @@
#include <gtk/gtk.h>
#include "gtkstack.h"
#include "gtkenums.h"
#include "gtkaccessibleprivate.h"
#include "gtkatcontextprivate.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkprogresstrackerprivate.h"
@ -77,6 +80,11 @@
* # CSS nodes
*
* GtkStack has a single CSS node named stack.
*
* # Accessibility
*
* GtkStack uses the #GTK_ACCESSIBLE_ROLE_TAB_PANEL for the stack
* pages.
*/
/**
@ -181,7 +189,9 @@ enum
CHILD_PROP_NEEDS_ATTENTION,
CHILD_PROP_VISIBLE,
CHILD_PROP_USE_UNDERLINE,
LAST_CHILD_PROP
LAST_CHILD_PROP,
PROP_ACCESSIBLE_ROLE
};
struct _GtkStackPage
@ -193,6 +203,9 @@ struct _GtkStackPage
char *title;
char *icon_name;
GtkWidget *last_focus;
GtkATContext *at_context;
guint needs_attention : 1;
guint visible : 1;
guint use_underline : 1;
@ -207,7 +220,39 @@ struct _GtkStackPageClass
static GParamSpec *stack_props[LAST_PROP] = { NULL, };
static GParamSpec *stack_page_props[LAST_CHILD_PROP] = { NULL, };
G_DEFINE_TYPE (GtkStackPage, gtk_stack_page, G_TYPE_OBJECT)
static GtkATContext *
gtk_stack_page_accessible_get_at_context (GtkAccessible *accessible)
{
GtkStackPage *page = GTK_STACK_PAGE (accessible);
if (page->at_context == NULL)
{
GtkAccessibleRole role = GTK_ACCESSIBLE_ROLE_TAB_PANEL;
GdkDisplay *display = gtk_widget_get_display (page->widget);
page->at_context = gtk_at_context_create (role, accessible, display);
}
return page->at_context;
}
static gboolean
gtk_stack_page_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
return FALSE;
}
static void
gtk_stack_page_accessible_init (GtkAccessibleInterface *iface)
{
iface->get_at_context = gtk_stack_page_accessible_get_at_context;
iface->get_platform_state = gtk_stack_page_accessible_get_platform_state;
}
G_DEFINE_TYPE_WITH_CODE (GtkStackPage, gtk_stack_page, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE,
gtk_stack_page_accessible_init))
static void
gtk_stack_page_init (GtkStackPage *page)
@ -270,6 +315,10 @@ gtk_stack_page_get_property (GObject *object,
g_value_set_boolean (value, gtk_stack_page_get_use_underline (info));
break;
case PROP_ACCESSIBLE_ROLE:
g_value_set_enum (value, GTK_ACCESSIBLE_ROLE_TAB_PANEL);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -314,6 +363,9 @@ gtk_stack_page_set_property (GObject *object,
gtk_stack_page_set_use_underline (info, g_value_get_boolean (value));
break;
case PROP_ACCESSIBLE_ROLE:
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -386,6 +438,8 @@ gtk_stack_page_class_init (GtkStackPageClass *class)
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, LAST_CHILD_PROP, stack_page_props);
g_object_class_override_property (object_class, PROP_ACCESSIBLE_ROLE, "accessible-role");
}
#define GTK_TYPE_STACK_PAGES (gtk_stack_pages_get_type ())

View File

@ -58,6 +58,11 @@
* When circumstances require it, GtkStackSwitcher adds the
* .needs-attention style class to the widgets representing the
* stack pages.
*
* # Accessibility
*
* GtkStackSwitcher uses the #GTK_ACCESSIBLE_ROLE_TAB_LIST role
* and uses the #GTK_ACCESSIBLE_ROLE_TAB for its buttons.
*/
#define TIMEOUT_EXPAND 500
@ -247,7 +252,9 @@ add_child (guint position,
GtkStackPage *page;
GtkEventController *controller;
button = gtk_toggle_button_new ();
button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
"accessible-role", GTK_ACCESSIBLE_ROLE_TAB,
NULL);
gtk_widget_set_focus_on_click (button, FALSE);
controller = gtk_drop_controller_motion_new ();
@ -264,6 +271,14 @@ add_child (guint position,
selected = gtk_selection_model_is_selected (self->pages, position);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), selected);
gtk_accessible_update_state (GTK_ACCESSIBLE (button),
GTK_ACCESSIBLE_STATE_SELECTED, selected,
-1);
gtk_accessible_update_relation (GTK_ACCESSIBLE (button),
GTK_ACCESSIBLE_RELATION_CONTROLS, g_list_append (NULL, page),
-1);
g_signal_connect (button, "notify::active", G_CALLBACK (on_button_toggled), self);
g_signal_connect (page, "notify", G_CALLBACK (on_page_updated), self);
@ -328,6 +343,10 @@ selection_changed_cb (GtkSelectionModel *model,
{
selected = gtk_selection_model_is_selected (switcher->pages, i);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), selected);
gtk_accessible_update_state (GTK_ACCESSIBLE (button),
GTK_ACCESSIBLE_STATE_SELECTED, selected,
-1);
}
g_object_unref (page);
}
@ -497,6 +516,7 @@ gtk_stack_switcher_class_init (GtkStackSwitcherClass *class)
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
gtk_widget_class_set_css_name (widget_class, I_("stackswitcher"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_TAB_LIST);
}
/**

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_NONE);
}
static void
@ -3376,7 +3377,7 @@ gtk_text_delete_selection (GtkText *self)
int start_pos = MIN (priv->selection_bound, priv->current_pos);
int end_pos = MAX (priv->selection_bound, priv->current_pos);
gtk_text_delete_text (self, start_pos, end_pos);
gtk_editable_delete_text (GTK_EDITABLE (self), start_pos, end_pos);
}
static void
@ -3871,7 +3872,7 @@ gtk_text_insert_at_cursor (GtkText *self,
if (priv->editable)
{
gtk_text_reset_im_context (self);
gtk_text_insert_text (self, str, -1, &pos);
gtk_editable_insert_text (GTK_EDITABLE (self), str, -1, &pos);
gtk_text_set_selection_bounds (self, pos, pos);
}
}
@ -3904,7 +3905,7 @@ gtk_text_delete_from_cursor (GtkText *self,
{
case GTK_DELETE_CHARS:
end_pos = gtk_text_move_logically (self, priv->current_pos, count);
gtk_text_delete_text (self, MIN (start_pos, end_pos), MAX (start_pos, end_pos));
gtk_editable_delete_text (GTK_EDITABLE (self), MIN (start_pos, end_pos), MAX (start_pos, end_pos));
break;
case GTK_DELETE_WORDS:
@ -3934,21 +3935,21 @@ gtk_text_delete_from_cursor (GtkText *self,
count--;
}
gtk_text_delete_text (self, start_pos, end_pos);
gtk_editable_delete_text (GTK_EDITABLE (self), start_pos, end_pos);
break;
case GTK_DELETE_DISPLAY_LINE_ENDS:
case GTK_DELETE_PARAGRAPH_ENDS:
if (count < 0)
gtk_text_delete_text (self, 0, priv->current_pos);
gtk_editable_delete_text (GTK_EDITABLE (self), 0, priv->current_pos);
else
gtk_text_delete_text (self, priv->current_pos, -1);
gtk_editable_delete_text (GTK_EDITABLE (self), priv->current_pos, -1);
break;
case GTK_DELETE_DISPLAY_LINES:
case GTK_DELETE_PARAGRAPHS:
gtk_text_delete_text (self, 0, -1);
gtk_editable_delete_text (GTK_EDITABLE (self), 0, -1);
break;
case GTK_DELETE_WHITESPACE:
@ -4008,12 +4009,12 @@ gtk_text_backspace (GtkText *self)
G_NORMALIZE_NFD);
len = g_utf8_strlen (normalized_text, -1);
gtk_text_delete_text (self, prev_pos, priv->current_pos);
gtk_editable_delete_text (GTK_EDITABLE (self), prev_pos, priv->current_pos);
if (len > 1)
{
int pos = priv->current_pos;
gtk_text_insert_text (self, normalized_text,
gtk_editable_insert_text (GTK_EDITABLE (self), normalized_text,
g_utf8_offset_to_pointer (normalized_text, len - 1) - normalized_text,
&pos);
gtk_text_set_selection_bounds (self, pos, pos);
@ -4024,7 +4025,7 @@ gtk_text_backspace (GtkText *self)
}
else
{
gtk_text_delete_text (self, prev_pos, priv->current_pos);
gtk_editable_delete_text (GTK_EDITABLE (self), prev_pos, priv->current_pos);
}
}
else
@ -4238,9 +4239,9 @@ gtk_text_delete_surrounding_cb (GtkIMContext *context,
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
if (priv->editable)
gtk_text_delete_text (self,
priv->current_pos + offset,
priv->current_pos + offset + n_chars);
gtk_editable_delete_text (GTK_EDITABLE (self),
priv->current_pos + offset,
priv->current_pos + offset + n_chars);
return TRUE;
}
@ -4274,7 +4275,7 @@ gtk_text_enter_text (GtkText *self,
}
tmp_pos = priv->current_pos;
gtk_text_insert_text (self, str, strlen (str), &tmp_pos);
gtk_editable_insert_text (GTK_EDITABLE (self), str, strlen (str), &tmp_pos);
gtk_text_set_selection_bounds (self, tmp_pos, tmp_pos);
priv->need_im_reset = old_need_im_reset;
@ -5165,7 +5166,7 @@ gtk_text_delete_whitespace (GtkText *self)
end++;
if (start != end)
gtk_text_delete_text (self, start, end);
gtk_editable_delete_text (GTK_EDITABLE (self), start, end);
}
@ -5233,7 +5234,7 @@ paste_received (GObject *clipboard,
gtk_text_delete_selection (self);
pos = priv->current_pos;
gtk_text_insert_text (self, text, length, &pos);
gtk_editable_insert_text (GTK_EDITABLE (self), text, length, &pos);
gtk_text_set_selection_bounds (self, pos, pos);
end_change (self);
@ -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");
}
}
@ -5454,9 +5459,9 @@ gtk_text_set_text (GtkText *self,
begin_change (self);
g_object_freeze_notify (G_OBJECT (self));
gtk_text_delete_text (self, 0, -1);
gtk_editable_delete_text (GTK_EDITABLE (self), 0, -1);
tmp_pos = 0;
gtk_text_insert_text (self, text, strlen (text), &tmp_pos);
gtk_editable_insert_text (GTK_EDITABLE (self), text, strlen (text), &tmp_pos);
g_object_thaw_notify (G_OBJECT (self));
end_change (self);
@ -6240,7 +6245,7 @@ gtk_text_drag_drop (GtkDropTarget *dest,
drop_position < priv->selection_bound ||
drop_position > priv->current_pos)
{
gtk_text_insert_text (self, str, length, &drop_position);
gtk_editable_insert_text (GTK_EDITABLE (self), str, length, &drop_position);
}
else
{
@ -6249,7 +6254,7 @@ gtk_text_drag_drop (GtkDropTarget *dest,
begin_change (self);
gtk_text_delete_selection (self);
pos = MIN (priv->selection_bound, priv->current_pos);
gtk_text_insert_text (self, str, length, &pos);
gtk_editable_insert_text (GTK_EDITABLE (self), str, length, &pos);
end_change (self);
}
@ -6811,7 +6816,7 @@ emoji_picked (GtkEmojiChooser *chooser,
gtk_text_delete_selection (self);
pos = priv->current_pos;
gtk_text_insert_text (self, text, -1, &pos);
gtk_editable_insert_text (GTK_EDITABLE (self), text, -1, &pos);
gtk_text_set_selection_bounds (self, pos, pos);
end_change (self);
}

View File

@ -4948,6 +4948,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]);
}
@ -8092,10 +8095,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
@ -8112,16 +8119,32 @@ 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;
}
static gboolean
gtk_widget_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
switch (state)
{
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE:
return gtk_widget_get_focusable (GTK_WIDGET (self));
case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
return gtk_widget_has_focus (GTK_WIDGET (self));
default:
g_assert_not_reached ();
}
}
static void
gtk_widget_accessible_interface_init (GtkAccessibleInterface *iface)
{
iface->get_at_context = gtk_widget_accessible_get_at_context;
iface->get_platform_state = gtk_widget_accessible_get_platform_state;
}
/*
@ -9751,6 +9774,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]);
}
@ -12138,6 +12163,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

@ -1,4 +1,4 @@
[Test]
Exec=@libexecdir@/installed-tests/gtk-4.0/css/api --tap -k
Exec=/bin/sh -c "env G_ENABLE_DIAGNOSTIC=0 GTK_TEST_ACCESSIBLE=1 @libexecdir@/installed-tests/gtk-4.0/css/api --tap -k"
Type=session
Output=TAP

View File

@ -1,4 +1,4 @@
[Test]
Exec=@libexecdir@/installed-tests/gtk-4.0/css/change/test-css-change --tap -k
Exec=/bin/sh -c "env G_ENABLE_DIAGNOSTIC=0 GTK_TEST_ACCESSIBLE=1 @libexecdir@/installed-tests/gtk-4.0/css/change/test-css-change --tap -k"
Type=session
Output=TAP

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

@ -1,4 +1,4 @@
[Test]
Exec=@libexecdir@/installed-tests/gtk-4.0/css/nodes/test-css-nodes --tap -k
Exec=/bin/sh -c "env G_ENABLE_DIAGNOSTIC=0 GTK_TEST_ACCESSIBLE=1 @libexecdir@/installed-tests/gtk-4.0/css/nodes/test-css-nodes --tap -k"
Type=session
Output=TAP

View File

@ -1,4 +1,4 @@
[Test]
Exec=@libexecdir@/installed-tests/gtk-4.0/css/parser/test-css-parser --tap -k
Exec=/bin/sh -c "env G_ENABLE_DIAGNOSTIC=0 GTK_TEST_ACCESSIBLE=1 @libexecdir@/installed-tests/gtk-4.0/css/parser/test-css-parser --tap -k"
Type=session
Output=TAP

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

@ -1,4 +1,4 @@
[Test]
Exec=@libexecdir@/installed-tests/gtk-4.0/css/style/test-css-style --tap -k
Exec=/bin/sh -c "env G_ENABLE_DIAGNOSTIC=0 GTK_TEST_ACCESSIBLE=1 @libexecdir@/installed-tests/gtk-4.0/css/style/test-css-style --tap -k"
Type=session
Output=TAP

View File

@ -1,4 +1,4 @@
[Test]
Exec=@testexecdir@/@test@ --tap -k --verbose
Exec=/bin/sh -c "env G_ENABLE_DIAGNOSTIC=0 GTK_TEST_ACCESSIBLE=1 @testexecdir@/@test@ --tap -k --verbose"
Type=session
Output=TAP

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

Some files were not shown because too many files have changed in this diff Show More