Compare commits

...

9 Commits

Author SHA1 Message Date
Matthias Clasen
80bfd895a4 atspi: Implement Selection for notebook tabs
This is a bit different from the way things were done
in GTK 3 - we follow what was done for GtkStackSwitcher,
and make the tab bar carry the GTK_ACCESSIBLE_TAB_LIST
role, and implement Selection there.
2020-10-14 20:52:33 -04:00
Matthias Clasen
fdca39205c notebook: Set accessible roles and properties
Set up the necessary roles, relations and properties
for the tab patterns. This parallels what we have done
for GtkStackSwitcher, and implements the Tabs pattern
as described in the ARIA authoring guidelines.
2020-10-14 20:52:15 -04:00
Matthias Clasen
c676977cec atspi: Don't crash on unnamed stack pages
GtkNotebook creates unnamed stack pages, and we should
not crash when that happens.
2020-10-14 19:05:36 -04:00
Matthias Clasen
144f549cc6 gizmo: Add a way to set accessible role
This will be used for some of the gizmo used
inside GtkNotebook.
2020-10-14 18:37:14 -04:00
Matthias Clasen
b13b7e63a3 atspi: Implement Selection for GtkStackSwitcher 2020-10-14 01:06:04 -04:00
Matthias Clasen
5d962412c7 stackswitcher: Set up relations and states
Set up a CONTROLS relation between each tab button
and its page, and update the SELECTED property of
the buttons to match their active state.
2020-10-14 00:34:30 -04:00
Matthias Clasen
359881df8a stackswitcher: Use the tablist and tab roles
Set the tablist role on the stackswitcher itself, and
the tab role on the buttons. This is another step towards
implementing the tabs pattern for GtkStack.
2020-10-14 00:18:02 -04:00
Matthias Clasen
342f7db5db accessible: Avoid realizing the context prematurely
platform change is called from gtk_widget_set_focusable
which is likely to be called early on in init(). We don't
want to create an AT context that early if we can help
it, e.g. since it makes it impossible to override the
accessible-role with a construct property.
2020-10-14 00:16:23 -04:00
Matthias Clasen
de3fabd38f Make stack pages 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.
2020-10-13 23:44:50 -04:00
16 changed files with 636 additions and 134 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,21 @@ 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))
{
const char *name = gtk_stack_page_get_name (GTK_STACK_PAGE (accessible));
if (name == NULL)
name = G_OBJECT_TYPE_NAME (accessible);
res = g_variant_new_string (name);
}
else
res = g_variant_new_string (G_OBJECT_TYPE_NAME (accessible));
}
else if (g_strcmp0 (property_name, "Description") == 0)
{
char *label = gtk_at_context_get_label (GTK_AT_CONTEXT (self));
@@ -546,14 +589,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 +638,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 +676,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 +691,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 +706,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 +720,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 +735,11 @@ gtk_at_spi_context_register_object (GtkAtSpiContext *self)
self->n_registered_objects++;
}
vtable = gtk_atspi_get_selection_vtable (widget);
/* Calling gtk_accessible_get_accessible_role() in here will recurse,
* so pass the role in explicitly.
*/
vtable = gtk_atspi_get_selection_vtable (accessible,
GTK_AT_CONTEXT (self)->accessible_role);
if (vtable)
{
g_variant_builder_add (&interfaces, "s", atspi_selection_interface.name);
@@ -945,8 +1026,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 +1149,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

@@ -31,6 +31,8 @@
#include "gtklistbox.h"
#include "gtkflowbox.h"
#include "gtkcombobox.h"
#include "gtkstackswitcher.h"
#include "gtknotebook.h"
#include <gio/gio.h>
@@ -459,15 +461,272 @@ static const GDBusInterfaceVTable combobox_vtable = {
NULL
};
const GDBusInterfaceVTable *
gtk_atspi_get_selection_vtable (GtkWidget *widget)
static void
stackswitcher_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)
{
if (GTK_IS_LIST_BOX (widget))
GtkATContext *self = user_data;
GtkAccessible *accessible = gtk_at_context_get_accessible (self);
GtkWidget *widget = GTK_WIDGET (accessible);
GtkStack *stack = gtk_stack_switcher_get_stack (GTK_STACK_SWITCHER (widget));
if (g_strcmp0 (method_name, "GetSelectedChild") == 0)
{
guint i, n;
GtkSelectionModel *pages;
GtkWidget *child;
pages = gtk_stack_get_pages (stack);
n = g_list_model_get_n_items (G_LIST_MODEL (pages));
for (i = 0, child = gtk_widget_get_first_child (widget);
i < n && child;
i++, child = gtk_widget_get_next_sibling (child))
{
if (gtk_selection_model_is_selected (pages, i))
break;
}
g_object_unref (pages);
if (child == NULL)
g_dbus_method_invocation_return_error_literal (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"No selected child");
else
{
GtkATContext *ctx = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(@(so))", gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (ctx))));
}
}
else if (g_strcmp0 (method_name, "SelectChild") == 0)
{
int idx;
GtkSelectionModel *pages;
g_variant_get (parameters, "(i)", &idx);
pages = gtk_stack_get_pages (stack);
gtk_selection_model_select_item (pages, idx, TRUE);
g_object_unref (pages);
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
}
else if (g_strcmp0 (method_name, "DeselectChild") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
else if (g_strcmp0 (method_name, "DeselectSelectedChild") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
else if (g_strcmp0 (method_name, "IsChildSelected") == 0)
{
int idx;
GtkSelectionModel *pages;
gboolean active;
g_variant_get (parameters, "(i)", &idx);
pages = gtk_stack_get_pages (stack);
active = gtk_selection_model_is_selected (pages, idx);
g_object_unref (pages);
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", active));
}
else if (g_strcmp0 (method_name, "SelectAll") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
else if (g_strcmp0 (method_name, "ClearSelection") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
}
static GVariant *
stackswitcher_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 *self = GTK_AT_CONTEXT (user_data);
GtkAccessible *accessible = gtk_at_context_get_accessible (self);
GtkWidget *widget = GTK_WIDGET (accessible);
if (g_strcmp0 (property_name, "NSelectedChildren") == 0)
{
GtkStack *stack = gtk_stack_switcher_get_stack (GTK_STACK_SWITCHER (widget));
if (stack == NULL || gtk_stack_get_visible_child (stack) == NULL)
return g_variant_new_int32 (0);
else
return g_variant_new_int32 (1);
}
return NULL;
}
static const GDBusInterfaceVTable stackswitcher_vtable = {
stackswitcher_handle_method,
stackswitcher_get_property,
NULL
};
static void
notebook_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);
GtkWidget *notebook = gtk_widget_get_parent (gtk_widget_get_parent (widget));
if (g_strcmp0 (method_name, "GetSelectedChild") == 0)
{
int i;
GtkWidget *child;
i = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
for (child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (widget))
{
/* skip actions */
if (gtk_accessible_get_accessible_role (GTK_ACCESSIBLE (child)) != GTK_ACCESSIBLE_ROLE_TAB)
continue;
if (i == 0)
break;
i--;
}
if (child == NULL)
{
g_dbus_method_invocation_return_error_literal (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"No selected child");
}
else
{
GtkATContext *ctx = gtk_accessible_get_at_context (GTK_ACCESSIBLE (child));
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(@(so))", gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (ctx))));
}
}
else if (g_strcmp0 (method_name, "SelectChild") == 0)
{
int i;
GtkWidget *child;
g_variant_get (parameters, "(i)", &i);
/* skip an action widget */
child = gtk_widget_get_first_child (widget);
if (gtk_accessible_get_accessible_role (GTK_ACCESSIBLE (child)) != GTK_ACCESSIBLE_ROLE_TAB)
i--;
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), i);
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
}
else if (g_strcmp0 (method_name, "DeselectChild") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
else if (g_strcmp0 (method_name, "DeselectSelectedChild") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
else if (g_strcmp0 (method_name, "IsChildSelected") == 0)
{
int i;
gboolean active;
GtkWidget *child;
g_variant_get (parameters, "(i)", &i);
/* skip an action widget */
child = gtk_widget_get_first_child (widget);
if (gtk_accessible_get_accessible_role (GTK_ACCESSIBLE (child)) != GTK_ACCESSIBLE_ROLE_TAB)
i--;
active = i == gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", active));
}
else if (g_strcmp0 (method_name, "SelectAll") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
else if (g_strcmp0 (method_name, "ClearSelection") == 0)
{
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
}
}
static GVariant *
notebook_get_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data)
{
if (g_strcmp0 (property_name, "NSelectedChildren") == 0)
{
return g_variant_new_int32 (1);
}
return NULL;
}
static const GDBusInterfaceVTable notebook_vtable = {
notebook_handle_method,
notebook_get_property,
NULL
};
#define IS_NOTEBOOK_TAB_LIST(s,r) \
((r == GTK_ACCESSIBLE_ROLE_TAB_LIST) && \
(gtk_widget_get_parent (GTK_WIDGET (s)) != NULL) && \
GTK_IS_NOTEBOOK (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (s)))))
const GDBusInterfaceVTable *
gtk_atspi_get_selection_vtable (GtkAccessible *accessible,
GtkAccessibleRole role)
{
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;
else if (GTK_IS_STACK_SWITCHER (accessible))
return &stackswitcher_vtable;
else if (IS_NOTEBOOK_TAB_LIST (accessible, role))
return &notebook_vtable;
return NULL;
}
@@ -478,11 +737,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 +749,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 +761,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 +773,62 @@ 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);
}
else if (GTK_IS_STACK_SWITCHER (accessible))
{
SelectionChanged *changed;
changed = g_new (SelectionChanged, 1);
changed->changed = selection_changed;
changed->data = data;
g_object_set_data_full (G_OBJECT (accessible), "accessible-selection-data", changed, g_free);
g_signal_connect_swapped (accessible, "notify::visible-child", G_CALLBACK (selection_changed), data);
}
else if (IS_NOTEBOOK_TAB_LIST (accessible, GTK_AT_CONTEXT (data)->accessible_role))
{
GtkWidget *notebook = gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (accessible)));
SelectionChanged *changed;
changed = g_new (SelectionChanged, 1);
changed->changed = selection_changed;
changed->data = data;
g_object_set_data_full (G_OBJECT (accessible), "accessible-selection-data", changed, g_free);
g_signal_connect_swapped (notebook, "notify::page", 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) ||
GTK_IS_STACK_SWITCHER (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);
}
else if (IS_NOTEBOOK_TAB_LIST (accessible, gtk_accessible_get_accessible_role (accessible)))
{
GtkWidget *notebook = gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (accessible)));
SelectionChanged *changed;
changed = g_object_get_data (G_OBJECT (accessible), "accessible-selection-data");
g_signal_handlers_disconnect_by_func (notebook, changed->changed, changed->data);
g_object_set_data (G_OBJECT (accessible), "accessible-selection-data", NULL);
}
}

View File

@@ -21,18 +21,19 @@
#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,
GtkAccessibleRole role);
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

@@ -656,14 +656,17 @@ void
gtk_accessible_platform_changed (GtkAccessible *self,
GtkAccessiblePlatformChange change)
{
GtkATContext *context = gtk_accessible_get_at_context (self);
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)
{
if (gtk_widget_get_parent (GTK_WIDGET (self)) == NULL)
return;
context = gtk_accessible_get_at_context (GTK_ACCESSIBLE (gtk_widget_get_parent (GTK_WIDGET (self))));
}

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

@@ -1404,13 +1404,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 +3916,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 +3931,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 +3960,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 +5321,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

@@ -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 ())

View File

@@ -248,7 +248,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 ();
@@ -265,6 +267,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);
@@ -329,6 +339,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);
}
@@ -498,6 +512,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);
}
/**