Merge branch 'matthiasc/for-master' into 'master'

Some a11y docs and fixes

See merge request GNOME/gtk!2724
This commit is contained in:
Matthias Clasen 2020-10-20 01:45:17 +00:00
commit a7bd6b094a
3 changed files with 74 additions and 19 deletions

View File

@ -183,7 +183,7 @@ with a form to fill out, you should ensure that:
* each text entry widget in the form has the `GTK_ACCESSIBLE_RELATION_LABELLED_BY`
relation pointing to the label widget that describes it
Another example: if you create a tool bar containing buttons with only icons,
Another example: if you create a toolbar containing buttons with only icons,
you should ensure that:
* the container has a `GTK_ACCESSIBLE_ROLE_TOOLBAR` role
@ -192,7 +192,7 @@ you should ensure that:
"Paste", "Add layer", or "Remove"
GTK will try to fill in some information by using ancillary UI control
property, for instance the accessible label will be taken from the label or
properties, for instance the accessible label will be taken from the label or
placeholder text used by the UI control, or from its tooltip, if the
`GTK_ACCESSIBLE_PROPERTY_LABEL` property or the `GTK_ACCESSIBLE_RELATION_LABELLED_BY`
relation are unset. Nevertheless, it is good practice and project hygiene
@ -287,4 +287,46 @@ widgets.
## Design patterns and custom widgets
...
When creating custom widgets, following established patterns can help
ensuring that the widgets work well for users of accessible technologies
as well.
### Custom entries
For custom entries, it is highly recommended that you implement the
#GtkEditable interface by using a #GtkText widget as delegate. If you
do this, GTK will make your widgets text editing functionality accessible
in the same way as a #GtkSpinButton or #GtkSearchEntry.
### Tab-based UI
If you make a tab-based interface, you should consider using #GtkStack
as the core, and just make a custom tab widget to control the active
stack page. When doing so, the following extra steps will ensure that
your tabs are accessible in the same way as #GtkStackSwitcher or #GtkNotebook:
- Give your tab container the role %GTK_ACCESSIBLE_ROLE_TAB_LIST
- Give your tab widgets the role %GTK_ACCESSIBLE_ROLE_TAB
- Set up the %GTK_ACCESSIBLE_RELATION_CONTROLS relation between each
tab and the #GtkStackPage object for its page
- Set the %GTK_ACCESSIBLE_PROPERTY_SELECTED property on each tab, with
the active tab getting the value %TRUE, all others %FALSE
To allow changing the active tab via accessible technologies, you can
export actions. Since the accessibility interfaces only support actions
without parameters, you can either provide `previous-tab` and `next-tab`
actions on the tab container that let users step through the tabs one-by-one,
or add a `activate-tab` action on each tab.
### Value controls
A value control (ie a widget that controls a one-dimensional quantity
that can be represented by a #GtkAdjustment) can be represented to
accessible technologies by setting the %GTK_ACCESSIBLE_PROPERTY_VALUE_MIN,
%GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, and %GTK_ACCESSIBLE_PROPERTY_VALUE_NOW
properties.
To allow changing the value via accessible technologies, you can export
actions. Since the accessibility interfaces only support actions
without parameters, you should provide actions such as `increase-value`
and `decrease-value`.

View File

@ -455,15 +455,31 @@ handle_accessible_method (GDBusConnection *connection,
}
else if (g_strcmp0 (method_name, "GetChildAtIndex") == 0)
{
GtkWidget *child = NULL;
GtkATContext *context = NULL;
GtkAccessible *accessible;
int idx, real_idx = 0;
const char *name;
const char *path;
g_variant_get (parameters, "(i)", &idx);
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
if (GTK_IS_WIDGET (accessible))
accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
if (GTK_IS_STACK_PAGE (accessible))
{
if (idx == 0)
{
GtkWidget *child;
child = gtk_stack_page_get_child (GTK_STACK_PAGE (accessible));
if (gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
}
}
else if (GTK_IS_WIDGET (accessible))
{
GtkWidget *widget = GTK_WIDGET (accessible);
GtkWidget *child;
real_idx = 0;
for (child = gtk_widget_get_first_child (widget);
@ -478,18 +494,17 @@ handle_accessible_method (GDBusConnection *connection,
real_idx += 1;
}
}
else if (GTK_IS_STACK_PAGE (accessible))
{
if (idx == 0)
if (child)
{
child = gtk_stack_page_get_child (GTK_STACK_PAGE (accessible));
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
child = NULL;
if (GTK_IS_STACK (accessible))
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (gtk_stack_get_page (GTK_STACK (accessible), child)));
else
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
}
}
if (child == NULL)
if (context == NULL)
{
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
@ -498,10 +513,8 @@ handle_accessible_method (GDBusConnection *connection,
return;
}
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
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));
name = g_dbus_connection_get_unique_name (self->connection);
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));
}

View File

@ -84,7 +84,7 @@
* # Accessibility
*
* GtkStack uses the #GTK_ACCESSIBLE_ROLE_TAB_PANEL for the stack
* pages.
* pages, which are the accessible parent objects of the child widgets.
*/
/**