stack: Turn pages into accessibles

This requires some cleanup to remove assumptions
about accessibles being widgets in the backend,
and some code to navigate the tree with these
extra objects in between widgets.

The accessibles for stack pages have the role
GTK_ACCESSIBLE_ROLE_TAB_PANEL. This is the first
step towards implementing the tabs patterns
as described in the aria authoring guidelines
for GtkStack.
This commit is contained in:
Matthias Clasen 2020-10-13 23:44:50 -04:00
parent 2142c6c086
commit 7c6c718e19
11 changed files with 241 additions and 120 deletions

View File

@ -45,6 +45,7 @@
#include "gtkroot.h"
#include "gtktextview.h"
#include "gtkwindow.h"
#include "gtkstack.h"
#include <gio/gio.h>
@ -432,20 +433,32 @@ handle_accessible_method (GDBusConnection *connection,
g_variant_get (parameters, "(i)", &idx);
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
GtkWidget *widget = GTK_WIDGET (accessible);
real_idx = 0;
for (child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (child))
if (GTK_IS_WIDGET (accessible))
{
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
continue;
GtkWidget *widget = GTK_WIDGET (accessible);
if (real_idx == idx)
break;
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;
real_idx += 1;
if (real_idx == idx)
break;
real_idx += 1;
}
}
else if (GTK_IS_STACK_PAGE (accessible))
{
if (idx == 0)
{
child = gtk_stack_page_get_child (GTK_STACK_PAGE (accessible));
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
child = NULL;
}
}
if (child == NULL)
@ -469,22 +482,37 @@ 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));
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_IS_WIDGET (accessible))
{
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
continue;
GtkWidget *widget = GTK_WIDGET (accessible);
GtkWidget *child;
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (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;
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));
GtkATContext *context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
g_variant_builder_add (&builder, "(so)", name, path);
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);
}
}
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));
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));
@ -496,6 +524,10 @@ handle_accessible_method (GDBusConnection *connection,
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));
@ -530,10 +562,16 @@ handle_accessible_get_property (GDBusConnection *connection,
GVariant *res = NULL;
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
GtkWidget *widget = GTK_WIDGET (accessible);
if (g_strcmp0 (property_name, "Name") == 0)
res = g_variant_new_string (gtk_widget_get_name (widget));
{
if (GTK_IS_WIDGET (accessible))
res = g_variant_new_string (gtk_widget_get_name (GTK_WIDGET (accessible)));
else if (GTK_IS_STACK_PAGE (accessible))
res = g_variant_new_string (gtk_stack_page_get_name (GTK_STACK_PAGE (accessible)));
else
res = g_variant_new_string ("Name");
}
else if (g_strcmp0 (property_name, "Description") == 0)
{
char *label = gtk_at_context_get_label (GTK_AT_CONTEXT (self));
@ -546,14 +584,40 @@ handle_accessible_get_property (GDBusConnection *connection,
res = g_variant_new_string ("");
else if (g_strcmp0 (property_name, "Parent") == 0)
{
GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (accessible));
if (GTK_IS_WIDGET (accessible))
{
GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (accessible));
if (parent == NULL)
{
res = gtk_at_spi_root_to_ref (self->root);
if (parent == NULL)
{
res = gtk_at_spi_root_to_ref (self->root);
}
else if (GTK_IS_STACK (parent))
{
GtkStackPage *page =
gtk_stack_get_page (GTK_STACK (parent), GTK_WIDGET (accessible));
GtkATContext *parent_context =
gtk_accessible_get_at_context (GTK_ACCESSIBLE (page));
if (parent_context != NULL)
res = g_variant_new ("(so)",
g_dbus_connection_get_unique_name (self->connection),
GTK_AT_SPI_CONTEXT (parent_context)->context_path);
}
else
{
GtkATContext *parent_context =
gtk_accessible_get_at_context (GTK_ACCESSIBLE (parent));
if (parent_context != NULL)
res = g_variant_new ("(so)",
g_dbus_connection_get_unique_name (self->connection),
GTK_AT_SPI_CONTEXT (parent_context)->context_path);
}
}
else
else if (GTK_IS_STACK_PAGE (accessible))
{
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));
@ -569,16 +633,24 @@ handle_accessible_get_property (GDBusConnection *connection,
else if (g_strcmp0 (property_name, "ChildCount") == 0)
{
int n_children = 0;
GtkWidget *child;
for (child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (child))
if (GTK_IS_WIDGET (accessible))
{
if (!gtk_accessible_should_present (GTK_ACCESSIBLE (child)))
continue;
GtkWidget *child;
n_children++;
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;
}
res = g_variant_new_int32 (n_children);
@ -599,7 +671,7 @@ static const GDBusInterfaceVTable accessible_vtable = {
static void
gtk_at_spi_context_register_object (GtkAtSpiContext *self)
{
GtkWidget *widget = GTK_WIDGET (gtk_at_context_get_accessible (GTK_AT_CONTEXT (self)));
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
GVariantBuilder interfaces = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_STRING_ARRAY);
const GDBusInterfaceVTable *vtable;
@ -614,7 +686,7 @@ gtk_at_spi_context_register_object (GtkAtSpiContext *self)
NULL);
self->n_registered_objects++;
vtable = gtk_atspi_get_text_vtable (widget);
vtable = gtk_atspi_get_text_vtable (accessible);
if (vtable)
{
g_variant_builder_add (&interfaces, "s", atspi_text_interface.name);
@ -629,7 +701,7 @@ gtk_at_spi_context_register_object (GtkAtSpiContext *self)
self->n_registered_objects++;
}
vtable = gtk_atspi_get_editable_text_vtable (widget);
vtable = gtk_atspi_get_editable_text_vtable (accessible);
if (vtable)
{
g_variant_builder_add (&interfaces, "s", atspi_editable_text_interface.name);
@ -643,7 +715,7 @@ gtk_at_spi_context_register_object (GtkAtSpiContext *self)
NULL);
self->n_registered_objects++;
}
vtable = gtk_atspi_get_value_vtable (widget);
vtable = gtk_atspi_get_value_vtable (accessible);
if (vtable)
{
g_variant_builder_add (&interfaces, "s", atspi_value_interface.name);
@ -658,7 +730,7 @@ gtk_at_spi_context_register_object (GtkAtSpiContext *self)
self->n_registered_objects++;
}
vtable = gtk_atspi_get_selection_vtable (widget);
vtable = gtk_atspi_get_selection_vtable (accessible);
if (vtable)
{
g_variant_builder_add (&interfaces, "s", atspi_selection_interface.name);
@ -945,8 +1017,8 @@ gtk_at_spi_context_dispose (GObject *gobject)
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
gtk_at_spi_context_unregister_object (self);
gtk_atspi_disconnect_text_signals (GTK_WIDGET (accessible));
gtk_atspi_disconnect_selection_signals (GTK_WIDGET (accessible));
gtk_atspi_disconnect_text_signals (accessible);
gtk_atspi_disconnect_selection_signals (accessible);
G_OBJECT_CLASS (gtk_at_spi_context_parent_class)->dispose (gobject);
}
@ -1068,11 +1140,11 @@ gtk_at_spi_context_constructed (GObject *gobject)
g_free (uuid);
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
gtk_atspi_connect_text_signals (GTK_WIDGET (accessible),
gtk_atspi_connect_text_signals (accessible,
(GtkAtspiTextChangedCallback *)emit_text_changed,
(GtkAtspiTextSelectionCallback *)emit_text_selection_changed,
self);
gtk_atspi_connect_selection_signals (GTK_WIDGET (accessible),
gtk_atspi_connect_selection_signals (accessible,
(GtkAtspiSelectionCallback *)emit_selection_changed,
self);
gtk_at_spi_context_register_object (self);

View File

@ -341,14 +341,14 @@ static const GDBusInterfaceVTable text_view_vtable = {
const GDBusInterfaceVTable *
gtk_atspi_get_editable_text_vtable (GtkWidget *widget)
gtk_atspi_get_editable_text_vtable (GtkAccessible *accessible)
{
if (GTK_IS_ENTRY (widget) ||
GTK_IS_SEARCH_ENTRY (widget) ||
GTK_IS_PASSWORD_ENTRY (widget) ||
GTK_IS_SPIN_BUTTON (widget))
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 (widget))
else if (GTK_IS_TEXT_VIEW (accessible))
return &text_view_vtable;
return NULL;

View File

@ -21,10 +21,10 @@
#pragma once
#include <gio/gio.h>
#include "gtkwidget.h"
#include "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_editable_text_vtable (GtkWidget *widget);
const GDBusInterfaceVTable *gtk_atspi_get_editable_text_vtable (GtkAccessible *accessible);
G_END_DECLS

View File

@ -460,13 +460,13 @@ static const GDBusInterfaceVTable combobox_vtable = {
};
const GDBusInterfaceVTable *
gtk_atspi_get_selection_vtable (GtkWidget *widget)
gtk_atspi_get_selection_vtable (GtkAccessible *accessible)
{
if (GTK_IS_LIST_BOX (widget))
if (GTK_IS_LIST_BOX (accessible))
return &listbox_vtable;
else if (GTK_IS_FLOW_BOX (widget))
else if (GTK_IS_FLOW_BOX (accessible))
return &flowbox_vtable;
else if (GTK_IS_COMBO_BOX (widget))
else if (GTK_IS_COMBO_BOX (accessible))
return &combobox_vtable;
return NULL;
@ -478,11 +478,11 @@ typedef struct {
} SelectionChanged;
void
gtk_atspi_connect_selection_signals (GtkWidget *widget,
gtk_atspi_connect_selection_signals (GtkAccessible *accessible,
GtkAtspiSelectionCallback selection_changed,
gpointer data)
{
if (GTK_IS_LIST_BOX (widget))
if (GTK_IS_LIST_BOX (accessible))
{
SelectionChanged *changed;
@ -490,11 +490,11 @@ gtk_atspi_connect_selection_signals (GtkWidget *widget,
changed->changed = selection_changed;
changed->data = data;
g_object_set_data_full (G_OBJECT (widget), "accessible-selection-data", changed, g_free);
g_object_set_data_full (G_OBJECT (accessible), "accessible-selection-data", changed, g_free);
g_signal_connect_swapped (widget, "selected-rows-changed", G_CALLBACK (selection_changed), data);
g_signal_connect_swapped (accessible, "selected-rows-changed", G_CALLBACK (selection_changed), data);
}
else if (GTK_IS_FLOW_BOX (widget))
else if (GTK_IS_FLOW_BOX (accessible))
{
SelectionChanged *changed;
@ -502,11 +502,11 @@ gtk_atspi_connect_selection_signals (GtkWidget *widget,
changed->changed = selection_changed;
changed->data = data;
g_object_set_data_full (G_OBJECT (widget), "accessible-selection-data", changed, g_free);
g_object_set_data_full (G_OBJECT (accessible), "accessible-selection-data", changed, g_free);
g_signal_connect_swapped (widget, "selected-children-changed", G_CALLBACK (selection_changed), data);
g_signal_connect_swapped (accessible, "selected-children-changed", G_CALLBACK (selection_changed), data);
}
else if (GTK_IS_COMBO_BOX (widget))
else if (GTK_IS_COMBO_BOX (accessible))
{
SelectionChanged *changed;
@ -514,25 +514,25 @@ gtk_atspi_connect_selection_signals (GtkWidget *widget,
changed->changed = selection_changed;
changed->data = data;
g_object_set_data_full (G_OBJECT (widget), "accessible-selection-data", changed, g_free);
g_object_set_data_full (G_OBJECT (accessible), "accessible-selection-data", changed, g_free);
g_signal_connect_swapped (widget, "changed", G_CALLBACK (selection_changed), data);
g_signal_connect_swapped (accessible, "changed", G_CALLBACK (selection_changed), data);
}
}
void
gtk_atspi_disconnect_selection_signals (GtkWidget *widget)
gtk_atspi_disconnect_selection_signals (GtkAccessible *accessible)
{
if (GTK_IS_LIST_BOX (widget) ||
GTK_IS_FLOW_BOX (widget) ||
GTK_IS_COMBO_BOX (widget))
if (GTK_IS_LIST_BOX (accessible) ||
GTK_IS_FLOW_BOX (accessible) ||
GTK_IS_COMBO_BOX (accessible))
{
SelectionChanged *changed;
changed = g_object_get_data (G_OBJECT (widget), "accessible-selection-data");
changed = g_object_get_data (G_OBJECT (accessible), "accessible-selection-data");
g_signal_handlers_disconnect_by_func (widget, changed->changed, changed->data);
g_signal_handlers_disconnect_by_func (accessible, changed->changed, changed->data);
g_object_set_data (G_OBJECT (widget), "accessible-selection-data", NULL);
g_object_set_data (G_OBJECT (accessible), "accessible-selection-data", NULL);
}
}

View File

@ -21,18 +21,18 @@
#pragma once
#include <gio/gio.h>
#include "gtkwidget.h"
#include "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_selection_vtable (GtkWidget *widget);
const GDBusInterfaceVTable *gtk_atspi_get_selection_vtable (GtkAccessible *accessible);
typedef void (GtkAtspiSelectionCallback) (gpointer data);
void gtk_atspi_connect_selection_signals (GtkWidget *widget,
void gtk_atspi_connect_selection_signals (GtkAccessible *accessible,
GtkAtspiSelectionCallback selection_changed,
gpointer data);
void gtk_atspi_disconnect_selection_signals (GtkWidget *widget);
void gtk_atspi_disconnect_selection_signals (GtkAccessible *accessible);
G_END_DECLS

View File

@ -1156,16 +1156,16 @@ static const GDBusInterfaceVTable text_view_vtable = {
};
const GDBusInterfaceVTable *
gtk_atspi_get_text_vtable (GtkWidget *widget)
gtk_atspi_get_text_vtable (GtkAccessible *accessible)
{
if (GTK_IS_LABEL (widget))
if (GTK_IS_LABEL (accessible))
return &label_vtable;
else if (GTK_IS_ENTRY (widget) ||
GTK_IS_SEARCH_ENTRY (widget) ||
GTK_IS_PASSWORD_ENTRY (widget) ||
GTK_IS_SPIN_BUTTON (widget))
else 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 (widget))
else if (GTK_IS_TEXT_VIEW (accessible))
return &text_view_vtable;
return NULL;
@ -1379,15 +1379,15 @@ buffer_changed (GtkWidget *widget,
}
void
gtk_atspi_connect_text_signals (GtkWidget *widget,
gtk_atspi_connect_text_signals (GtkAccessible *accessible,
GtkAtspiTextChangedCallback text_changed,
GtkAtspiTextSelectionCallback selection_changed,
gpointer data)
{
TextChanged *changed;
if (!GTK_IS_EDITABLE (widget) &&
!GTK_IS_TEXT_VIEW (widget))
if (!GTK_IS_EDITABLE (accessible) &&
!GTK_IS_TEXT_VIEW (accessible))
return;
changed = g_new0 (TextChanged, 1);
@ -1395,11 +1395,11 @@ gtk_atspi_connect_text_signals (GtkWidget *widget,
changed->selection_changed = selection_changed;
changed->data = data;
g_object_set_data_full (G_OBJECT (widget), "accessible-text-data", changed, g_free);
g_object_set_data_full (G_OBJECT (accessible), "accessible-text-data", changed, g_free);
if (GTK_IS_EDITABLE (widget))
if (GTK_IS_EDITABLE (accessible))
{
GtkText *text = gtk_editable_get_text_widget (widget);
GtkText *text = gtk_editable_get_text_widget (GTK_WIDGET (accessible));
if (text)
{
@ -1410,23 +1410,23 @@ gtk_atspi_connect_text_signals (GtkWidget *widget,
gtk_editable_get_selection_bounds (GTK_EDITABLE (text), &changed->cursor_position, &changed->selection_bound);
}
}
else if (GTK_IS_TEXT_VIEW (widget))
else if (GTK_IS_TEXT_VIEW (accessible))
{
g_signal_connect (widget, "notify::buffer", G_CALLBACK (buffer_changed), changed);
buffer_changed (widget, NULL, changed);
g_signal_connect (accessible, "notify::buffer", G_CALLBACK (buffer_changed), changed);
buffer_changed (GTK_WIDGET (accessible), NULL, changed);
}
}
void
gtk_atspi_disconnect_text_signals (GtkWidget *widget)
gtk_atspi_disconnect_text_signals (GtkAccessible *accessible)
{
TextChanged *changed;
changed = g_object_get_data (G_OBJECT (widget), "accessible-text-data");
changed = g_object_get_data (G_OBJECT (accessible), "accessible-text-data");
if (GTK_IS_EDITABLE (widget))
if (GTK_IS_EDITABLE (accessible))
{
GtkText *text = gtk_editable_get_text_widget (widget);
GtkText *text = gtk_editable_get_text_widget (GTK_WIDGET (accessible));
if (text)
{
@ -1435,9 +1435,9 @@ gtk_atspi_disconnect_text_signals (GtkWidget *widget)
g_signal_handlers_disconnect_by_func (text, notify_cb, changed);
}
}
else if (GTK_IS_TEXT_VIEW (widget))
else if (GTK_IS_TEXT_VIEW (accessible))
{
g_signal_handlers_disconnect_by_func (widget, buffer_changed, changed);
g_signal_handlers_disconnect_by_func (accessible, buffer_changed, changed);
if (changed->buffer)
{
g_signal_handlers_disconnect_by_func (changed->buffer, insert_range_cb, changed);
@ -1448,5 +1448,5 @@ gtk_atspi_disconnect_text_signals (GtkWidget *widget)
g_clear_object (&changed->buffer);
}
g_object_set_data (G_OBJECT (widget), "accessible-text-data", NULL);
g_object_set_data (G_OBJECT (accessible), "accessible-text-data", NULL);
}

View File

@ -21,11 +21,11 @@
#pragma once
#include <gio/gio.h>
#include "gtkwidget.h"
#include "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_text_vtable (GtkWidget *widget);
const GDBusInterfaceVTable *gtk_atspi_get_text_vtable (GtkAccessible *accessible);
typedef void (GtkAtspiTextChangedCallback) (gpointer data,
const char *kind,
@ -36,10 +36,10 @@ typedef void (GtkAtspiTextSelectionCallback) (gpointer data,
const char *kind,
int position);
void gtk_atspi_connect_text_signals (GtkWidget *widget,
void gtk_atspi_connect_text_signals (GtkAccessible *accessible,
GtkAtspiTextChangedCallback text_changed,
GtkAtspiTextSelectionCallback selection_changed,
gpointer data);
void gtk_atspi_disconnect_text_signals (GtkWidget *widget);
void gtk_atspi_disconnect_text_signals (GtkAccessible *accessible);
G_END_DECLS

View File

@ -230,16 +230,16 @@ gtk_accessible_role_to_atspi_role (GtkAccessibleRole role)
return ATSPI_ROLE_CHECK_BOX;
case GTK_ACCESSIBLE_ROLE_TAB:
return ATSPI_ROLE_FILLER;
return ATSPI_ROLE_PAGE_TAB;
case GTK_ACCESSIBLE_ROLE_TABLE:
return ATSPI_ROLE_TABLE;
case GTK_ACCESSIBLE_ROLE_TAB_LIST:
return ATSPI_ROLE_FILLER;
return ATSPI_ROLE_PAGE_TAB_LIST;
case GTK_ACCESSIBLE_ROLE_TAB_PANEL:
return ATSPI_ROLE_FILLER;
return ATSPI_ROLE_PANEL;
case GTK_ACCESSIBLE_ROLE_TEXT_BOX:
return ATSPI_ROLE_TEXT;

View File

@ -114,14 +114,14 @@ static const GDBusInterfaceVTable value_vtable = {
};
const GDBusInterfaceVTable *
gtk_atspi_get_value_vtable (GtkWidget *widget)
gtk_atspi_get_value_vtable (GtkAccessible *accessible)
{
if (GTK_IS_LEVEL_BAR (widget) ||
GTK_IS_PANED (widget) ||
GTK_IS_PROGRESS_BAR (widget) ||
GTK_IS_RANGE (widget) ||
GTK_IS_SCALE_BUTTON (widget) ||
GTK_IS_SPIN_BUTTON (widget))
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

@ -21,10 +21,10 @@
#pragma once
#include <gio/gio.h>
#include "gtkwidget.h"
#include "gtkaccessible.h"
G_BEGIN_DECLS
const GDBusInterfaceVTable *gtk_atspi_get_value_vtable (GtkWidget *widget);
const GDBusInterfaceVTable *gtk_atspi_get_value_vtable (GtkAccessible *accessible);
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"
@ -181,7 +184,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 +198,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 +215,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 +310,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 +358,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 +433,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 ())