Merge branch 'ebassi/public-accessible' into 'main'

Make GtkAccessible public

Closes #4240

See merge request GNOME/gtk!5470
This commit is contained in:
Matthias Clasen 2023-02-03 11:31:06 +00:00
commit c2f5b64b5d
9 changed files with 633 additions and 412 deletions

View File

@ -82,6 +82,10 @@
* hold the TAB_PANEL role and be the target of the CONTROLS
* relation with their corresponding tabs (in the stack
* switcher or notebook).
*
* These are the exceptions implemented by GTK itself, but note that application
* developers can customize the accessibility tree by implementing the
* [iface@Gtk.Accessible] interface in any way they choose.
*/
struct _GtkAtSpiContext
@ -329,32 +333,43 @@ collect_relations (GtkAtSpiContext *self,
/* }}} */
/* {{{ Accessible implementation */
static int
get_index_in_parent (GtkWidget *widget)
get_index_in (GtkAccessible *parent,
GtkAccessible *child)
{
GtkWidget *parent = gtk_widget_get_parent (widget);
GtkWidget *child;
int idx;
GtkAccessible *candidate;
guint res;
if (parent == NULL)
return -1;
idx = 0;
for (child = gtk_widget_get_first_child (parent);
child;
child = gtk_widget_get_next_sibling (child))
res = 0;
for (candidate = gtk_accessible_get_first_accessible_child (parent);
candidate != NULL;
candidate = gtk_accessible_get_next_accessible_sibling (candidate))
{
if (child == widget)
return idx;
if (candidate == child)
return res;
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
if (!gtk_accessible_should_present (candidate))
continue;
idx++;
res++;
}
return -1;
}
static int
get_index_in_parent (GtkAccessible *accessible)
{
GtkAccessible *parent = gtk_accessible_get_accessible_parent (accessible);
if (parent != NULL)
return get_index_in (parent, accessible);
return -1;
}
static int
get_index_in_toplevels (GtkWidget *widget)
{
@ -387,61 +402,21 @@ get_parent_context_ref (GtkAccessible *accessible)
{
GVariant *res = NULL;
if (GTK_IS_WIDGET (accessible))
GtkAccessible *parent = gtk_accessible_get_accessible_parent (accessible);
if (parent == NULL)
{
GtkWidget *widget = GTK_WIDGET (accessible);
GtkWidget *parent = gtk_widget_get_parent (widget);
GtkATContext *context = gtk_accessible_get_at_context (accessible);
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (context);
if (parent == NULL)
{
GtkATContext *context = gtk_accessible_get_at_context (accessible);
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (context);
res = gtk_at_spi_root_to_ref (self->root);
}
else if (GTK_IS_STACK (parent))
{
GtkStackPage *page =
gtk_stack_get_page (GTK_STACK (parent), widget);
GtkATContext *parent_context =
gtk_accessible_get_at_context (GTK_ACCESSIBLE (page));
if (parent_context != NULL)
{
gtk_at_context_realize (parent_context);
res = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (parent_context));
}
}
else
{
GtkATContext *parent_context =
gtk_accessible_get_at_context (GTK_ACCESSIBLE (parent));
if (parent_context != NULL)
{
/* XXX: This realize() is needed otherwise opening a GtkPopover will
* emit a warning when getting the context's reference
*/
gtk_at_context_realize (parent_context);
res = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (parent_context));
}
}
res = gtk_at_spi_root_to_ref (self->root);
}
else if (GTK_IS_STACK_PAGE (accessible))
else
{
GtkWidget *parent =
gtk_widget_get_parent (gtk_stack_page_get_child (GTK_STACK_PAGE (accessible)));
GtkATContext *parent_context =
gtk_accessible_get_at_context (GTK_ACCESSIBLE (parent));
GtkATContext *parent_context = gtk_accessible_get_at_context (parent);
gtk_at_context_realize (parent_context);
if (parent_context != NULL)
{
gtk_at_context_realize (parent_context);
res = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (parent_context));
}
res = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (parent_context));
}
if (res == NULL)
@ -522,49 +497,30 @@ handle_accessible_method (GDBusConnection *connection,
{
GtkATContext *context = NULL;
GtkAccessible *accessible;
int idx, real_idx = 0;
int idx, presentable_idx;
g_variant_get (parameters, "(i)", &idx);
accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
if (GTK_IS_STACK_PAGE (accessible))
{
if (idx == 0)
{
GtkWidget *child;
GtkAccessible *child;
presentable_idx = 0;
for (child = gtk_accessible_get_first_accessible_child (accessible);
child != NULL;
child = gtk_accessible_get_next_accessible_sibling (child))
{
if (!gtk_accessible_should_present (child))
continue;
if (presentable_idx == idx)
break;
presentable_idx++;
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))
if (child)
{
GtkWidget *widget = GTK_WIDGET (accessible);
GtkWidget *child;
real_idx = 0;
for (child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (child))
{
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
continue;
if (real_idx == idx)
break;
real_idx += 1;
}
if (child)
{
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));
}
context = gtk_accessible_get_at_context (child);
}
if (context == NULL)
@ -588,45 +544,24 @@ handle_accessible_method (GDBusConnection *connection,
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a(so)"));
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
if (GTK_IS_WIDGET (accessible))
{
GtkWidget *widget = GTK_WIDGET (accessible);
GtkWidget *child;
for (child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (child))
{
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
continue;
GtkAccessible *child;
for (child = gtk_accessible_get_first_accessible_child (accessible);
child != NULL;
child = gtk_accessible_get_next_accessible_sibling (child))
{
if (!gtk_accessible_should_present (child))
continue;
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
GtkATContext *context = gtk_accessible_get_at_context (child);
/* Realize the child ATContext in order to get its ref */
gtk_at_context_realize (context);
/* Realize the child ATContext in order to get its ref */
gtk_at_context_realize (context);
GVariant *ref = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (context));
GVariant *ref = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (context));
if (ref != NULL)
g_variant_builder_add (&builder, "@(so)", ref);
}
}
else if (GTK_IS_STACK_PAGE (accessible))
{
GtkWidget *child = gtk_stack_page_get_child (GTK_STACK_PAGE (accessible));
if (gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
{
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
/* Realize the child ATContext in order to get its ref */
gtk_at_context_realize (context);
GVariant *ref = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (context));
if (ref != NULL)
g_variant_builder_add (&builder, "@(so)", ref);
}
if (ref != NULL)
g_variant_builder_add (&builder, "@(so)", ref);
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a(so))", &builder));
@ -915,7 +850,7 @@ gtk_at_spi_context_state_change (GtkATContext *ctx,
if (changed_states & GTK_ACCESSIBLE_STATE_CHANGE_HIDDEN)
{
GtkWidget *parent;
GtkAccessible *parent;
GtkATContext *context;
GtkAccessibleChildChange change;
@ -932,14 +867,9 @@ gtk_at_spi_context_state_change (GtkATContext *ctx,
}
else
{
if (GTK_IS_WIDGET (accessible))
parent = gtk_widget_get_parent (GTK_WIDGET (accessible));
else if (GTK_IS_STACK_PAGE (accessible))
parent = gtk_widget_get_parent (gtk_stack_page_get_child (GTK_STACK_PAGE (accessible)));
else
g_assert_not_reached ();
parent = gtk_accessible_get_accessible_parent (accessible);
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (parent));
context = gtk_accessible_get_at_context (parent);
gtk_at_context_child_changed (context, change, accessible);
}
}
@ -1168,29 +1098,9 @@ gtk_at_spi_context_bounds_change (GtkATContext *ctx)
{
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (ctx);
GtkAccessible *accessible = gtk_at_context_get_accessible (ctx);
GtkWidget *widget;
GtkWidget *parent;
double x, y;
int width, height;
if (!GTK_IS_WIDGET (accessible))
return;
widget = GTK_WIDGET (accessible);
if (!gtk_widget_get_realized (widget))
return;
parent = gtk_widget_get_parent (widget);
if (parent)
gtk_widget_translate_coordinates (widget, parent, 0., 0., &x, &y);
else
x = y = 0.;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
emit_bounds_changed (self, (int)x, (int)y, width, height);
int x, y, width, height;
if (gtk_accessible_get_bounds (accessible, &x, &y, &width, &height))
emit_bounds_changed (self, x, y, width, height);
}
static void
@ -1201,99 +1111,17 @@ gtk_at_spi_context_child_change (GtkATContext *ctx,
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (ctx);
GtkAccessible *accessible = gtk_at_context_get_accessible (ctx);
GtkATContext *child_context = gtk_accessible_get_at_context (child);
GtkWidget *parent_widget;
GtkWidget *child_widget;
int idx = 0;
if (!GTK_IS_WIDGET (accessible))
return;
if (child_context == NULL)
return;
/* handle the stack page special case */
if (GTK_IS_WIDGET (child) &&
GTK_IS_STACK (gtk_widget_get_parent (GTK_WIDGET (child))))
{
GtkWidget *stack;
GtkStackPage *page;
GListModel *pages;
GtkAccessible *parent = gtk_accessible_get_accessible_parent (child);
int idx = 0;
stack = gtk_widget_get_parent (GTK_WIDGET (child));
page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (child));
pages = G_LIST_MODEL (gtk_stack_get_pages (GTK_STACK (stack)));
idx = 0;
for (guint i = 0; i < g_list_model_get_n_items (pages); i++)
{
GtkStackPage *item = g_list_model_get_item (pages, i);
g_object_unref (item);
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (item)))
continue;
if (item == page)
break;
idx++;
}
g_object_unref (pages);
if (change & GTK_ACCESSIBLE_CHILD_CHANGE_ADDED)
{
emit_children_changed (GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (GTK_ACCESSIBLE (stack))),
GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (GTK_ACCESSIBLE (page))),
idx,
GTK_ACCESSIBLE_CHILD_STATE_ADDED);
emit_children_changed (GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (GTK_ACCESSIBLE (page))),
GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (child)),
0,
GTK_ACCESSIBLE_CHILD_STATE_ADDED);
}
if (change & GTK_ACCESSIBLE_CHILD_CHANGE_REMOVED)
{
emit_children_changed (GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (GTK_ACCESSIBLE (page))),
GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (child)),
0,
GTK_ACCESSIBLE_CHILD_STATE_REMOVED);
emit_children_changed (GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (GTK_ACCESSIBLE (stack))),
GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (GTK_ACCESSIBLE (page))),
idx,
GTK_ACCESSIBLE_CHILD_STATE_REMOVED);
}
return;
}
parent_widget = GTK_WIDGET (accessible);
if (GTK_IS_STACK_PAGE (child))
child_widget = gtk_stack_page_get_child (GTK_STACK_PAGE (child));
else
child_widget = GTK_WIDGET (child);
if (gtk_widget_get_parent (child_widget) != parent_widget)
{
idx = 0;
}
else
{
for (GtkWidget *iter = gtk_widget_get_first_child (parent_widget);
iter != NULL;
iter = gtk_widget_get_next_sibling (iter))
{
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (iter)))
continue;
if (iter == child_widget)
break;
idx += 1;
}
}
if (parent == NULL)
idx = -1;
else if (parent == accessible)
idx = get_index_in (accessible, child);
if (change & GTK_ACCESSIBLE_CHILD_CHANGE_ADDED)
emit_children_changed (self,
@ -1858,12 +1686,8 @@ gtk_at_spi_context_get_index_in_parent (GtkAtSpiContext *self)
if (GTK_IS_ROOT (accessible))
idx = get_index_in_toplevels (GTK_WIDGET (accessible));
else if (GTK_IS_STACK_PAGE (accessible))
idx = get_index_in_parent (gtk_stack_page_get_child (GTK_STACK_PAGE (accessible)));
else if (GTK_IS_STACK (gtk_widget_get_parent (GTK_WIDGET (accessible))))
idx = 1;
else
idx = get_index_in_parent (GTK_WIDGET (accessible));
idx = get_index_in_parent (accessible);
return idx;
}
@ -1874,26 +1698,18 @@ gtk_at_spi_context_get_child_count (GtkAtSpiContext *self)
g_return_val_if_fail (GTK_IS_AT_SPI_CONTEXT (self), -1);
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
int n_children = -1;
int n_children = 0;
if (GTK_IS_WIDGET (accessible))
GtkAccessible *child = NULL;
for (child = gtk_accessible_get_first_accessible_child (accessible);
child != NULL;
child = gtk_accessible_get_next_accessible_sibling (child))
{
GtkWidget *child;
if (!gtk_accessible_should_present (child))
continue;
n_children = 0;
for (child = gtk_widget_get_first_child (GTK_WIDGET (accessible));
child;
child = gtk_widget_get_next_sibling (child))
{
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
continue;
n_children++;
}
}
else if (GTK_IS_STACK_PAGE (accessible))
{
n_children = 1;
n_children++;
}
return n_children;

View File

@ -37,6 +37,14 @@
* a way that should be reflected by assistive technologies. For instance,
* if a `GtkWidget` visibility changes, the %GTK_ACCESSIBLE_STATE_HIDDEN
* state will also change to reflect the [property@Gtk.Widget:visible] property.
*
* Every accessible implementation is part of a tree of accessible objects.
* Normally, this tree corresponds to the widget tree, but can be customized
* by reimplementing the [vfunc@Gtk.Accessible.get_accessible_parent],
* [vfunc@Gtk.Accessible.get_first_accessible_child] and
* [vfunc@Gtk.Accessible.get_next_accessible_sibling] virtual functions.
* Note that you can not create a top-level accessible object as of now,
* which means that you must always have a parent accessible object.
*/
#include "config.h"
@ -74,7 +82,7 @@ gtk_accessible_default_init (GtkAccessibleInterface *iface)
g_object_interface_install_property (iface, pspec);
}
/*< private >
/**
* gtk_accessible_get_at_context:
* @self: a `GtkAccessible`
*
@ -91,12 +99,68 @@ gtk_accessible_get_at_context (GtkAccessible *self)
}
/**
* gtk_accessible_get_accessible_role: (attributes org.gtk.Method.get_property=accessible-role)
* gtk_accessible_get_accessible_parent:
* @self: a `GtkAccessible`
*
* Retrieves the `GtkAccessibleRole` for the given `GtkAccessible`.
* Retrieves the accessible accessible for an accessible object
*
* Returns: a `GtkAccessibleRole`
* This function returns `NULL` for top level widgets
*
* Returns: (transfer none) (nullable): the accessible parent
*
* Since: 4.10
*/
GtkAccessible *
gtk_accessible_get_accessible_parent (GtkAccessible *self)
{
g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL);
return GTK_ACCESSIBLE_GET_IFACE (self)->get_accessible_parent (self);
}
/**
* gtk_accessible_get_first_accessible_child:
* @self: an accessible object
*
* Retrieves the first accessible child of an accessible object.
*
* Returns: (transfer none) (nullable): the first accessible child
*
* since: 4.10
*/
GtkAccessible *
gtk_accessible_get_first_accessible_child (GtkAccessible *self)
{
g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL);
return GTK_ACCESSIBLE_GET_IFACE (self)->get_first_accessible_child (self);
}
/**
* gtk_accessible_get_next_accessible_sibling:
* @self: an accessible object
*
* Retrieves the next accessible sibling of an accessible object
*
* Returns: (transfer none) (nullable): the next accessible sibling
*
* since: 4.10
*/
GtkAccessible *
gtk_accessible_get_next_accessible_sibling (GtkAccessible *self)
{
g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL);
return GTK_ACCESSIBLE_GET_IFACE (self)->get_next_accessible_sibling (self);
}
/**
* gtk_accessible_get_accessible_role:
* @self: an accessible object
*
* Retrieves the accessible role of an accessible object.
*
* Returns: the accessible role
*/
GtkAccessibleRole
gtk_accessible_get_accessible_role (GtkAccessible *self)
@ -127,6 +191,7 @@ gtk_accessible_get_accessible_role (GtkAccessible *self)
* state change must be communicated to assistive technologies.
*
* Example:
*
* ```c
* value = GTK_ACCESSIBLE_TRISTATE_MIXED;
* gtk_accessible_update_state (GTK_ACCESSIBLE (check_button),
@ -659,10 +724,10 @@ gtk_accessible_role_to_name (GtkAccessibleRole role,
/*< private >
* gtk_accessible_role_is_range_subclass:
* @role: a `GtkAccessibleRole`
*
*
* Checks if @role is considered to be a subclass of %GTK_ACCESSIBLE_ROLE_RANGE
* according to the WAI-ARIA specification.
*
*
* Returns: whether the @role is range-like
*/
gboolean
@ -683,7 +748,7 @@ gtk_accessible_role_is_range_subclass (GtkAccessibleRole role)
return FALSE;
}
/*<private>
/*< private >
* gtk_accessible_platform_changed:
* @self: a `GtkAccessible`
* @change: the platform state change to report
@ -712,7 +777,7 @@ gtk_accessible_platform_changed (GtkAccessible *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))));
context = gtk_accessible_get_at_context (gtk_accessible_get_accessible_parent (self));
if (context == NULL)
return;
@ -721,7 +786,7 @@ gtk_accessible_platform_changed (GtkAccessible *self,
gtk_at_context_update (context);
}
/*<private>
/**
* gtk_accessible_get_platform_state:
* @self: a `GtkAccessible`
* @state: platform state to query
@ -735,15 +800,19 @@ gtk_accessible_platform_changed (GtkAccessible *self,
* child widget, as is the case for `GtkText` wrappers.
*
* Returns: the value of @state for the accessible
*
* Since: 4.10
*/
gboolean
gtk_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state)
{
g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), FALSE);
return GTK_ACCESSIBLE_GET_IFACE (self)->get_platform_state (self, state);
}
/*<private>
/*< private >
* gtk_accessible_bounds_changed:
* @self: a `GtkAccessible`
*
@ -752,7 +821,7 @@ gtk_accessible_get_platform_state (GtkAccessible *self,
* changed.
*
* Note that the bounds are not included in this API.
* AT backends should use widget API to obtain them.
* AT backends should use [method@Gtk.Accessible.get_bounds] to get them.
*/
void
gtk_accessible_bounds_changed (GtkAccessible *self)
@ -770,7 +839,39 @@ gtk_accessible_bounds_changed (GtkAccessible *self)
gtk_at_context_bounds_changed (context);
}
/*<private>
/**
* gtk_accessible_get_bounds:
* @self: a `GtkAccessible`
* @x: (out): the x coordinate of the top left corner of the accessible
* @y: (out): the y coordinate of the top left corner of the widget
* @width: (out): the width of the accessible object
* @height: (out): the height of the accessible object
*
* Queries the coordinates and dimensions of this accessible
*
* This functionality can be overridden by `GtkAccessible`
* implementations, e.g. to get the bounds from an ignored
* child widget.
*
* Returns: true if the bounds are valid, and false otherwise
*
* Since: 4.10
*/
gboolean
gtk_accessible_get_bounds (GtkAccessible *self,
int *x,
int *y,
int *width,
int *height)
{
g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), FALSE);
g_return_val_if_fail (x != NULL && y != NULL, FALSE);
g_return_val_if_fail (width != NULL && height != NULL, FALSE);
return GTK_ACCESSIBLE_GET_IFACE (self)->get_bounds (self, x, y, width, height);
}
/*< private >
* gtk_accessible_should_present:
* @self: a `GtkAccessible`
*
@ -829,7 +930,7 @@ gtk_accessible_update_children (GtkAccessible *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))));
context = gtk_accessible_get_at_context (gtk_accessible_get_accessible_parent (self));
if (context == NULL)
return;

View File

@ -32,58 +32,199 @@ G_BEGIN_DECLS
#define GTK_TYPE_ACCESSIBLE (gtk_accessible_get_type())
GDK_AVAILABLE_IN_ALL
GDK_AVAILABLE_IN_4_10
G_DECLARE_INTERFACE (GtkAccessible, gtk_accessible, GTK, ACCESSIBLE, GObject)
GDK_AVAILABLE_IN_ALL
GtkAccessibleRole gtk_accessible_get_accessible_role (GtkAccessible *self);
/**
* GtkAccessiblePlatformState:
* @GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE: whether the accessible can be focused
* @GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED: whether the accessible has focus
* @GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE: whether the accessible is active
*
* The various platform states which can be queried
* using [method@Gtk.Accessible.get_platform_state].
*
* Since: 4.10
*/
typedef enum {
GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE
} GtkAccessiblePlatformState;
/**
* GtkAccessibleInterface:
* @get_at_context: retrieve the platform-specific accessibility context
* for the accessible implementation
* @get_platform_state: retrieve the accessible state
*
* The common interface for accessible objects.
*
* Since: 4.10
*/
struct _GtkAccessibleInterface
{
GTypeInterface g_iface;
/**
* GtkAccessibleInterface::get_at_context:
* @self: an accessible object
*
* Retrieves the platform-specific accessibility context for the
* accessible implementation.
*
* Returns: (transfer none) (nullable): the accessibility context
*
* Since: 4.10
*/
GtkATContext * (* get_at_context) (GtkAccessible *self);
/**
* GtkAccessibleInterface::get_platform_state:
* @self: an accessible object
* @state: the state to query
*
* Checks if the given @state applies to the accessible object.
*
* Returns: true if the @state is set, and false otherwise
*
* Since: 4.10
*/
gboolean (* get_platform_state) (GtkAccessible *self,
GtkAccessiblePlatformState state);
/**
* GtkAccessibleInterface::get_accessible_parent:
* @self: an accessible object
*
* Retrieves the accessible parent of an accessible object.
*
* This virtual function should return `NULL` for top level objects.
*
* Returns: (nullable) (transfer none): the accessible parent
*
* Since: 4.10
*/
GtkAccessible * (* get_accessible_parent) (GtkAccessible *self);
/**
* GtkaccessibleInterface::get_first_accessible_child:
* @self: an accessible object
*
* Retrieves the first accessible child of an accessible object.
*
* Returns: (transfer none) (nullable): an accessible object
*
* Since: 4.10
*/
GtkAccessible * (* get_first_accessible_child) (GtkAccessible *self);
/**
* GtkaccessibleInterface::get_next_accessible_sibling:
* @self: an accessible object
*
* Retrieves the next accessible sibling of an accessible object.
*
* Returns: (transfer none) (nullable): an accessible object
*
* Since: 4.10
*/
GtkAccessible * (* get_next_accessible_sibling) (GtkAccessible *self);
/**
* GtkAccessibleInterface::get_bounds:
* @self: an accessible object
* @x: (out): the horizontal coordinate of a rectangle
* @y: (out): the vertical coordinate of a rectangle
* @width: (out): the width of a rectangle
* @height: (out): the height of a rectangle
*
* Retrieves the dimensions and position of an accessible object in its
* parent's coordinate space, if those values can be determined.
*
* For top level accessible objects, the X and Y coordinates are always
* going to be set to zero.
*
* Returns: true if the values are value, and false otherwise
*/
gboolean (* get_bounds) (GtkAccessible *self,
int *x,
int *y,
int *width,
int *height);
};
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_state (GtkAccessible *self,
GtkAccessibleState first_state,
...);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_property (GtkAccessible *self,
GtkAccessibleProperty first_property,
...);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_relation (GtkAccessible *self,
GtkAccessibleRelation first_relation,
...);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_state_value (GtkAccessible *self,
int n_states,
GtkAccessibleState states[],
const GValue values[]);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_property_value (GtkAccessible *self,
int n_properties,
GtkAccessibleProperty properties[],
const GValue values[]);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_relation_value (GtkAccessible *self,
int n_relations,
GtkAccessibleRelation relations[],
const GValue values[]);
GtkATContext * gtk_accessible_get_at_context (GtkAccessible *self);
GDK_AVAILABLE_IN_4_10
gboolean gtk_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state);
GDK_AVAILABLE_IN_4_10
GtkAccessible * gtk_accessible_get_accessible_parent (GtkAccessible *self);
GDK_AVAILABLE_IN_4_10
GtkAccessible * gtk_accessible_get_first_accessible_child (GtkAccessible *self);
GDK_AVAILABLE_IN_4_10
GtkAccessible * gtk_accessible_get_next_accessible_sibling (GtkAccessible *self);
GDK_AVAILABLE_IN_4_10
gboolean gtk_accessible_get_bounds (GtkAccessible *self,
int *x,
int *y,
int *width,
int *height);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_reset_state (GtkAccessible *self,
GtkAccessibleState state);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_reset_property (GtkAccessible *self,
GtkAccessibleProperty property);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_reset_relation (GtkAccessible *self,
GtkAccessibleRelation relation);
GtkAccessibleRole gtk_accessible_get_accessible_role (GtkAccessible *self);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_state_init_value (GtkAccessibleState state,
GValue *value);
void gtk_accessible_update_state (GtkAccessible *self,
GtkAccessibleState first_state,
...);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_property_init_value (GtkAccessibleProperty property,
GValue *value);
void gtk_accessible_update_property (GtkAccessible *self,
GtkAccessibleProperty first_property,
...);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_relation_init_value (GtkAccessibleRelation relation,
GValue *value);
void gtk_accessible_update_relation (GtkAccessible *self,
GtkAccessibleRelation first_relation,
...);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_state_value (GtkAccessible *self,
int n_states,
GtkAccessibleState states[],
const GValue values[]);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_property_value (GtkAccessible *self,
int n_properties,
GtkAccessibleProperty properties[],
const GValue values[]);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_update_relation_value (GtkAccessible *self,
int n_relations,
GtkAccessibleRelation relations[],
const GValue values[]);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_reset_state (GtkAccessible *self,
GtkAccessibleState state);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_reset_property (GtkAccessible *self,
GtkAccessibleProperty property);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_reset_relation (GtkAccessible *self,
GtkAccessibleRelation relation);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_state_init_value (GtkAccessibleState state,
GValue *value);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_property_init_value (GtkAccessibleProperty property,
GValue *value);
GDK_AVAILABLE_IN_ALL
void gtk_accessible_relation_init_value (GtkAccessibleRelation relation,
GValue *value);
G_END_DECLS

View File

@ -21,21 +21,36 @@
#pragma once
#include "gtkaccessible.h"
#include "gtkatcontextprivate.h"
G_BEGIN_DECLS
struct _GtkAccessibleInterface
{
GTypeInterface g_iface;
/* < private >
* GtkAccessiblePlatformChange:
* @GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSABLE: whether the accessible has changed
* its focusable state
* @GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED: whether the accessible has changed its
* focused state
* @GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE: whether the accessible has changed its
* active state
*
* Represents the various platform changes which can occur and are communicated
* using [method@Gtk.Accessible.platform_changed].
*/
typedef enum {
GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSABLE = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE,
} GtkAccessiblePlatformChange;
GtkATContext * (* get_at_context) (GtkAccessible *self);
typedef enum {
GTK_ACCESSIBLE_CHILD_STATE_ADDED,
GTK_ACCESSIBLE_CHILD_STATE_REMOVED
} GtkAccessibleChildState;
gboolean (* get_platform_state) (GtkAccessible *self,
GtkAccessiblePlatformState state);
};
GtkATContext * gtk_accessible_get_at_context (GtkAccessible *self);
typedef enum {
GTK_ACCESSIBLE_CHILD_CHANGE_ADDED = 1 << GTK_ACCESSIBLE_CHILD_STATE_ADDED,
GTK_ACCESSIBLE_CHILD_CHANGE_REMOVED = 1 << GTK_ACCESSIBLE_CHILD_STATE_REMOVED
} GtkAccessibleChildChange;
const char * gtk_accessible_role_to_name (GtkAccessibleRole role,
const char *domain);
@ -44,15 +59,13 @@ gboolean gtk_accessible_role_is_range_subclass (GtkAccessibleRole role);
gboolean gtk_accessible_should_present (GtkAccessible *self);
void gtk_accessible_platform_changed (GtkAccessible *self,
GtkAccessiblePlatformChange change);
gboolean gtk_accessible_get_platform_state (GtkAccessible *self,
GtkAccessiblePlatformState state);
void gtk_accessible_bounds_changed (GtkAccessible *self);
void gtk_accessible_update_children (GtkAccessible *self,
GtkAccessible *child,
GtkAccessibleChildState state);
void gtk_accessible_bounds_changed (GtkAccessible *self);
void gtk_accessible_platform_changed (GtkAccessible *self,
GtkAccessiblePlatformChange change);
G_END_DECLS

View File

@ -22,6 +22,7 @@
#include "gtkatcontext.h"
#include "gtkaccessibleprivate.h"
#include "gtkaccessibleattributesetprivate.h"
G_BEGIN_DECLS
@ -80,28 +81,6 @@ 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,
GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE
} 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,
GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE,
} GtkAccessiblePlatformChange;
typedef enum {
GTK_ACCESSIBLE_CHILD_STATE_ADDED,
GTK_ACCESSIBLE_CHILD_STATE_REMOVED
} GtkAccessibleChildState;
typedef enum {
GTK_ACCESSIBLE_CHILD_CHANGE_ADDED = 1 << GTK_ACCESSIBLE_CHILD_STATE_ADDED,
GTK_ACCESSIBLE_CHILD_CHANGE_REMOVED = 1 << GTK_ACCESSIBLE_CHILD_STATE_REMOVED
} GtkAccessibleChildChange;
struct _GtkATContext
{
GObject parent_instance;

View File

@ -139,7 +139,7 @@ struct _GtkStackClass {
};
typedef struct {
GList *children;
GPtrArray *children;
GtkStackPage *visible_child;
@ -165,9 +165,12 @@ typedef struct {
} GtkStackPrivate;
static void gtk_stack_buildable_interface_init (GtkBuildableIface *iface);
static void gtk_stack_accessible_init (GtkAccessibleInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkStack, gtk_stack, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (GtkStack)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE,
gtk_stack_accessible_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_stack_buildable_interface_init))
enum {
@ -209,6 +212,8 @@ struct _GtkStackPage
char *icon_name;
GtkWidget *last_focus;
GtkStackPage *next_page;
GtkATContext *at_context;
guint needs_attention : 1;
@ -253,11 +258,59 @@ gtk_stack_page_accessible_get_platform_state (GtkAccessible *self,
return FALSE;
}
static GtkAccessible *
gtk_stack_page_accessible_get_accessible_parent (GtkAccessible *accessible)
{
GtkStackPage *page = GTK_STACK_PAGE (accessible);
if (page->widget == NULL)
return NULL;
else
return GTK_ACCESSIBLE (gtk_widget_get_parent (page->widget));
}
static GtkAccessible *
gtk_stack_page_accessible_get_first_accessible_child(GtkAccessible *accessible)
{
GtkStackPage *page = GTK_STACK_PAGE (accessible);
if (page->widget != NULL)
return GTK_ACCESSIBLE (page->widget);
else
return NULL;
}
static GtkAccessible *
gtk_stack_page_accessible_get_next_accessible_sibling(GtkAccessible *accessible)
{
GtkStackPage *page = GTK_STACK_PAGE (accessible);
return GTK_ACCESSIBLE (page->next_page);
}
static gboolean
gtk_stack_page_accessible_get_bounds (GtkAccessible *accessible,
int *x,
int *y,
int *width,
int *height)
{
GtkStackPage *page = GTK_STACK_PAGE (accessible);
if (page->widget != NULL)
return gtk_accessible_get_bounds (GTK_ACCESSIBLE (page->widget), x, y, width, height);
else
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;
iface->get_accessible_parent = gtk_stack_page_accessible_get_accessible_parent;
iface->get_first_accessible_child = gtk_stack_page_accessible_get_first_accessible_child;
iface->get_next_accessible_sibling = gtk_stack_page_accessible_get_next_accessible_sibling;
iface->get_bounds = gtk_stack_page_accessible_get_bounds;
}
G_DEFINE_TYPE_WITH_CODE (GtkStackPage, gtk_stack_page, G_TYPE_OBJECT,
@ -534,7 +587,7 @@ gtk_stack_pages_get_n_items (GListModel *model)
GtkStackPages *pages = GTK_STACK_PAGES (model);
GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack);
return g_list_length (priv->children);
return priv->children->len;
}
static gpointer
@ -545,11 +598,12 @@ gtk_stack_pages_get_item (GListModel *model,
GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack);
GtkStackPage *page;
page = g_list_nth_data (priv->children, position);
if (!page)
if (position > priv->children->len - 1)
return NULL;
page = g_ptr_array_index (priv->children, position);
return g_object_ref (page);
}
@ -569,9 +623,12 @@ gtk_stack_pages_is_selected (GtkSelectionModel *model,
GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack);
GtkStackPage *page;
page = g_list_nth_data (priv->children, position);
if (position > priv->children->len - 1)
return FALSE;
return page && page == priv->visible_child;
page = g_ptr_array_index (priv->children, position);
return page == priv->visible_child;
}
static void set_visible_child (GtkStack *stack,
@ -588,7 +645,7 @@ gtk_stack_pages_select_item (GtkSelectionModel *model,
GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack);
GtkStackPage *page;
page = g_list_nth_data (priv->children, position);
page = g_ptr_array_index (priv->children, position);
set_visible_child (pages->stack, page, priv->transition_type, priv->transition_duration);
@ -728,6 +785,21 @@ gtk_stack_buildable_interface_init (GtkBuildableIface *iface)
iface->add_child = gtk_stack_buildable_add_child;
}
static GtkAccessible *
gtk_stack_accessible_get_first_accessible_child (GtkAccessible *accessible)
{
GtkStack *stack = GTK_STACK (accessible);
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GtkStackPage *page = g_ptr_array_index (priv->children, 0);
return GTK_ACCESSIBLE (page);
}
static void
gtk_stack_accessible_init (GtkAccessibleInterface *iface)
{
iface->get_first_accessible_child = gtk_stack_accessible_get_first_accessible_child;
}
static void stack_remove (GtkStack *stack,
GtkWidget *child,
gboolean in_dispose);
@ -738,7 +810,7 @@ gtk_stack_dispose (GObject *obj)
GtkStack *stack = GTK_STACK (obj);
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GtkWidget *child;
guint n_pages = g_list_length (priv->children);
guint n_pages = priv->children->len;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (stack))))
stack_remove (stack, child, TRUE);
@ -763,6 +835,8 @@ gtk_stack_finalize (GObject *obj)
gtk_stack_unschedule_ticks (stack);
g_ptr_array_free (priv->children, TRUE);
G_OBJECT_CLASS (gtk_stack_parent_class)->finalize (obj);
}
@ -978,11 +1052,11 @@ find_child_info_for_widget (GtkStack *stack,
{
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GtkStackPage *info;
GList *l;
guint idx;
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
info = l->data;
info = g_ptr_array_index (priv->children, idx);
if (info->widget == child)
return info;
}
@ -1297,7 +1371,7 @@ set_visible_child (GtkStack *stack,
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GtkStackPage *info;
GtkWidget *widget = GTK_WIDGET (stack);
GList *l;
guint idx;
GtkWidget *focus;
gboolean contains_focus = FALSE;
guint old_pos = GTK_INVALID_LIST_POSITION;
@ -1312,9 +1386,9 @@ set_visible_child (GtkStack *stack,
/* If none, pick first visible */
if (child_info == NULL)
{
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
info = l->data;
info = g_ptr_array_index (priv->children, idx);
if (gtk_widget_get_visible (info->widget))
{
child_info = info;
@ -1329,9 +1403,9 @@ set_visible_child (GtkStack *stack,
if (priv->pages)
{
guint position;
for (l = priv->children, position = 0; l != NULL; l = l->next, position++)
for (idx = 0, position = 0; idx < priv->children->len; idx++, position++)
{
info = l->data;
info = g_ptr_array_index (priv->children, idx);
if (info == priv->visible_child)
old_pos = position;
else if (info == child_info)
@ -1399,14 +1473,14 @@ set_visible_child (GtkStack *stack,
else if (is_direction_dependent_transition (transition_type))
{
gboolean i_first = FALSE;
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
if (child_info == l->data)
if (child_info == g_ptr_array_index (priv->children, idx))
{
i_first = TRUE;
break;
}
if (priv->last_visible_child == l->data)
if (priv->last_visible_child == g_ptr_array_index (priv->children, idx))
break;
}
@ -1575,15 +1649,15 @@ gtk_stack_add_page (GtkStack *stack,
GtkStackPage *child_info)
{
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GList *l;
guint idx;
g_return_if_fail (child_info->widget != NULL);
if (child_info->name)
{
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
GtkStackPage *info = l->data;
GtkStackPage *info = g_ptr_array_index (priv->children, idx);
if (info->name &&
g_strcmp0 (info->name, child_info->name) == 0)
{
@ -1593,14 +1667,26 @@ gtk_stack_add_page (GtkStack *stack,
}
}
priv->children = g_list_append (priv->children, g_object_ref (child_info));
if (priv->children->len > 0)
{
GtkStackPage *prev_last = g_ptr_array_index (priv->children, priv->children->len - 1);
prev_last->next_page = child_info;
}
else
{
child_info->next_page = NULL;
}
g_ptr_array_add (priv->children, g_object_ref (child_info));
gtk_widget_set_child_visible (child_info->widget, FALSE);
gtk_widget_set_parent (child_info->widget, GTK_WIDGET (stack));
if (priv->pages)
{
g_list_model_items_changed (G_LIST_MODEL (priv->pages), g_list_length (priv->children) - 1, 0, 1);
g_list_model_items_changed (G_LIST_MODEL (priv->pages), priv->children->len - 1, 0, 1);
g_object_notify_by_pspec (G_OBJECT (priv->pages), pages_properties[PAGES_PROP_N_ITEMS]);
}
@ -1644,7 +1730,17 @@ stack_remove (GtkStack *stack,
g_clear_object (&child_info->widget);
priv->children = g_list_remove (priv->children, child_info);
g_ptr_array_remove (priv->children, child_info);
for (guint prev_idx = 0; prev_idx < priv->children->len; prev_idx++)
{
GtkStackPage *prev_page = g_ptr_array_index (priv->children, prev_idx);
if (prev_page->next_page == child_info)
{
prev_page->next_page = child_info->next_page;
break;
}
}
g_object_unref (child_info);
@ -1666,16 +1762,15 @@ gtk_stack_remove (GtkStack *stack,
GtkWidget *child)
{
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GList *l;
guint position;
g_return_if_fail (GTK_IS_STACK (stack));
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (stack));
for (l = priv->children, position = 0; l; l = l->next, position++)
for (position = 0; position < priv->children->len; position++)
{
GtkStackPage *page = l->data;
GtkStackPage *page = g_ptr_array_index (priv->children, position);
if (page->widget == child)
break;
}
@ -1723,14 +1818,14 @@ gtk_stack_get_child_by_name (GtkStack *stack,
{
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GtkStackPage *info;
GList *l;
guint idx;
g_return_val_if_fail (GTK_IS_STACK (stack), NULL);
g_return_val_if_fail (name != NULL, NULL);
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
info = l->data;
info = g_ptr_array_index (priv->children, idx);
if (info->name && strcmp (info->name, name) == 0)
return info->widget;
}
@ -2141,7 +2236,7 @@ gtk_stack_set_visible_child_full (GtkStack *stack,
{
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
GtkStackPage *child_info, *info;
GList *l;
guint idx;
g_return_if_fail (GTK_IS_STACK (stack));
@ -2149,9 +2244,9 @@ gtk_stack_set_visible_child_full (GtkStack *stack,
return;
child_info = NULL;
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
info = l->data;
info = g_ptr_array_index (priv->children, idx);
if (info->name != NULL &&
strcmp (info->name, name) == 0)
{
@ -2180,13 +2275,13 @@ gtk_stack_compute_expand (GtkWidget *widget,
gboolean hexpand, vexpand;
GtkStackPage *child_info;
GtkWidget *child;
GList *l;
guint idx;
hexpand = FALSE;
vexpand = FALSE;
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
child_info = l->data;
child_info = g_ptr_array_index (priv->children, idx);
child = child_info->widget;
if (!hexpand &&
@ -2618,14 +2713,14 @@ gtk_stack_measure (GtkWidget *widget,
GtkStackPage *child_info;
GtkWidget *child;
int child_min, child_nat;
GList *l;
guint idx;
*minimum = 0;
*natural = 0;
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
child_info = l->data;
child_info = g_ptr_array_index (priv->children, idx);
child = child_info->widget;
if (!priv->homogeneous[orientation] &&
@ -2674,6 +2769,7 @@ gtk_stack_init (GtkStack *stack)
priv->homogeneous[GTK_ORIENTATION_HORIZONTAL] = TRUE;
priv->transition_duration = 200;
priv->transition_type = GTK_STACK_TRANSITION_TYPE_NONE;
priv->children = g_ptr_array_new();
}
/**
@ -2855,14 +2951,14 @@ gtk_stack_page_set_name (GtkStackPage *self,
gtk_widget_get_parent (self->widget) &&
GTK_IS_STACK (gtk_widget_get_parent (self->widget)))
{
GList *l;
guint idx;
stack = GTK_STACK (gtk_widget_get_parent (self->widget));
priv = gtk_stack_get_instance_private (stack);
for (l = priv->children; l != NULL; l = l->next)
for (idx = 0; idx < priv->children->len; idx++)
{
GtkStackPage *info2 = l->data;
GtkStackPage *info2 = g_ptr_array_index (priv->children, idx);
if (self == info2)
continue;

View File

@ -34,6 +34,7 @@
G_BEGIN_DECLS
typedef struct _GtkAdjustment GtkAdjustment;
typedef struct _GtkATContext GtkATContext;
typedef struct _GtkBitset GtkBitset;
typedef struct _GtkBuilder GtkBuilder;
typedef struct _GtkBuilderScope GtkBuilderScope;

View File

@ -8465,11 +8465,78 @@ gtk_widget_accessible_get_platform_state (GtkAccessible *self,
}
}
static GtkAccessible *
gtk_widget_accessible_get_accessible_parent (GtkAccessible *self)
{
return GTK_ACCESSIBLE (gtk_widget_get_parent (GTK_WIDGET (self)));
}
static GtkAccessible *
gtk_widget_accessible_get_next_accessible_sibling (GtkAccessible *self)
{
return GTK_ACCESSIBLE (gtk_widget_get_next_sibling (GTK_WIDGET (self)));
}
static GtkAccessible *
gtk_widget_accessible_get_first_accessible_child (GtkAccessible *self)
{
return GTK_ACCESSIBLE (gtk_widget_get_first_child (GTK_WIDGET (self)));
}
static gboolean
gtk_widget_accessible_get_bounds (GtkAccessible *self,
int *x,
int *y,
int *width,
int *height)
{
GtkWidget *widget;
GtkWidget *parent;
GtkWidget *bounds_relative_to;
double translated_x, translated_y;
graphene_rect_t bounds = GRAPHENE_RECT_INIT_ZERO;
widget = GTK_WIDGET (self);
if (!gtk_widget_get_realized (widget))
return FALSE;
parent = gtk_widget_get_parent (widget);
if (parent != NULL)
{
gtk_widget_translate_coordinates (widget, parent, 0., 0., &translated_x, &translated_y);
*x = floorf (translated_x);
*y = floorf (translated_y);
bounds_relative_to = parent;
}
else
{
*x = *y = 0;
bounds_relative_to = widget;
}
if (!gtk_widget_compute_bounds (widget, bounds_relative_to, &bounds))
{
*width = 0;
*height = 0;
}
else
{
*width = ceilf (graphene_rect_get_width (&bounds));
*height = ceilf (graphene_rect_get_height (&bounds));
}
return TRUE;
}
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;
iface->get_accessible_parent = gtk_widget_accessible_get_accessible_parent;
iface->get_first_accessible_child = gtk_widget_accessible_get_first_accessible_child;
iface->get_next_accessible_sibling = gtk_widget_accessible_get_next_accessible_sibling;
iface->get_bounds = gtk_widget_accessible_get_bounds;
}
static void

View File

@ -236,7 +236,14 @@ update_path (GtkInspectorA11y *sl)
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object));
if (GTK_IS_AT_SPI_CONTEXT (context))
path = gtk_at_spi_context_get_context_path (GTK_AT_SPI_CONTEXT (context));
{
if (gtk_at_context_is_realized (context))
path = gtk_at_spi_context_get_context_path (GTK_AT_SPI_CONTEXT (context));
else
path = "not realized";
}
else
path = "not on bus";
#endif
gtk_label_set_label (GTK_LABEL (sl->path), path);
@ -422,7 +429,7 @@ gtk_inspector_a11y_set_object (GtkInspectorA11y *sl,
stack = gtk_widget_get_parent (GTK_WIDGET (sl));
page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
if (GTK_IS_ACCESSIBLE (object))
if (GTK_IS_ACCESSIBLE (sl->object))
{
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (sl->object));
if (context)