diff --git a/Makefile.am b/Makefile.am index 92bd0a38..2efaf090 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,10 @@ AM_VALAFLAGS = \ noinst_LTLIBRARIES = libegglistbox.la -libegglistbox_la_SOURCES = egg-list-box.c egg-list-box.h +libegglistbox_la_SOURCES = \ + egg-list-box.c egg-list-box.h \ + egg-list-box-accessible.c egg-list-box-accessible.h + libegglistbox_la_LIBADD = $(LISTBOX_LIBS) noinst_PROGRAMS = test-list test-scrolled test-focus test-sel diff --git a/egg-list-box-accessible.c b/egg-list-box-accessible.c new file mode 100644 index 00000000..56e29fc3 --- /dev/null +++ b/egg-list-box-accessible.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2013 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "egg-list-box.h" +#include "egg-list-box-accessible.h" + +static void atk_selection_interface_init (AtkSelectionIface *iface); + +G_DEFINE_TYPE_WITH_CODE (EggListBoxAccessible, egg_list_box_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE, + G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init)) + +static void +egg_list_box_accessible_init (EggListBoxAccessible *accessible) +{ +} + +static void +egg_list_box_accessible_class_init (EggListBoxAccessibleClass *klass) +{ +} + +static gboolean +egg_list_box_accessible_add_selection (AtkSelection *selection, + gint idx) +{ + GtkWidget *box; + GList *children; + GtkWidget *child; + + box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); + if (box == NULL) + return FALSE; + + children = gtk_container_get_children (GTK_CONTAINER (box)); + child = g_list_nth_data (children, idx); + g_list_free (children); + if (child) + { + egg_list_box_select_child (EGG_LIST_BOX (box), child); + return TRUE; + } + return FALSE; +} + +static gboolean +egg_list_box_accessible_clear_selection (AtkSelection *selection) +{ + GtkWidget *box; + + box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); + if (box == NULL) + return FALSE; + + egg_list_box_select_child (EGG_LIST_BOX (box), NULL); + return TRUE; +} + +static AtkObject * +egg_list_box_accessible_ref_selection (AtkSelection *selection, + gint idx) +{ + GtkWidget *box; + GtkWidget *widget; + AtkObject *accessible; + + if (idx != 0) + return NULL; + + box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); + if (box == NULL) + return NULL; + + widget = egg_list_box_get_selected_child (EGG_LIST_BOX (box)); + if (widget == NULL) + return NULL; + + accessible = gtk_widget_get_accessible (widget); + g_object_ref (accessible); + return accessible; +} + +static gint +egg_list_box_accessible_get_selection_count (AtkSelection *selection) +{ + GtkWidget *box; + GtkWidget *widget; + + box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); + if (box == NULL) + return 0; + + widget = egg_list_box_get_selected_child (EGG_LIST_BOX (box)); + if (widget == NULL) + return 0; + + return 1; +} + +static gboolean +egg_list_box_accessible_is_child_selected (AtkSelection *selection, + gint idx) +{ + GtkWidget *box; + GtkWidget *widget; + GList *children; + GtkWidget *child; + + box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); + if (box == NULL) + return FALSE; + + widget = egg_list_box_get_selected_child (EGG_LIST_BOX (box)); + if (widget == NULL) + return FALSE; + + children = gtk_container_get_children (GTK_CONTAINER (box)); + child = g_list_nth_data (children, idx); + g_list_free (children); + return child == widget; +} + +static void atk_selection_interface_init (AtkSelectionIface *iface) +{ + iface->add_selection = egg_list_box_accessible_add_selection; + iface->clear_selection = egg_list_box_accessible_clear_selection; + iface->ref_selection = egg_list_box_accessible_ref_selection; + iface->get_selection_count = egg_list_box_accessible_get_selection_count; + iface->is_child_selected = egg_list_box_accessible_is_child_selected; +} + +void +_egg_list_box_accessible_update_selected (EggListBox *box, + GtkWidget *child) +{ + AtkObject *accessible; + accessible = gtk_widget_get_accessible (GTK_WIDGET (box)); + g_signal_emit_by_name (accessible, "selection-changed"); +} + +void +_egg_list_box_accessible_update_cursor (EggListBox *box, + GtkWidget *child) +{ + AtkObject *accessible; + AtkObject *descendant; + accessible = gtk_widget_get_accessible (GTK_WIDGET (box)); + descendant = child ? gtk_widget_get_accessible (child) : NULL; + g_signal_emit_by_name (accessible, "active-descendant-changed", descendant); +} diff --git a/egg-list-box-accessible.h b/egg-list-box-accessible.h new file mode 100644 index 00000000..db5b00cf --- /dev/null +++ b/egg-list-box-accessible.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __EGG_LIST_BOX_ACCESSIBLE_H__ +#define __EGG_LIST_BOX_ACCESSIBLE_H__ + +#include + +G_BEGIN_DECLS + +#define EGG_TYPE_LIST_BOX_ACCESSIBLE (egg_list_box_accessible_get_type ()) +#define EGG_LIST_BOX_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_LIST_BOX_ACCESSIBLE, EggListBoxAccessible)) +#define EGG_LIST_BOX_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_LIST_BOX_ACCESSIBLE, EggListBoxAccessibleClass)) +#define EGG_IS_LIST_BOX_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_LIST_BOX_ACCESSIBLE)) +#define EGG_IS_LIST_BOX_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_LIST_BOX_ACCESSIBLE)) +#define EGG_LIST_BOX_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_LIST_BOX_ACCESSIBLE, EggListBoxAccessibleClass)) + +typedef struct _EggListBoxAccessible EggListBoxAccessible; +typedef struct _EggListBoxAccessibleClass EggListBoxAccessibleClass; +typedef struct _EggListBoxAccessiblePrivate EggListBoxAccessiblePrivate; + +struct _EggListBoxAccessible +{ + GtkContainerAccessible parent; + + EggListBoxAccessiblePrivate *priv; +}; + +struct _EggListBoxAccessibleClass +{ + GtkContainerAccessibleClass parent_class; +}; + +GType egg_list_box_accessible_get_type (void); + +void _egg_list_box_accessible_update_selected (EggListBox *box, GtkWidget *child); +void _egg_list_box_accessible_update_cursor (EggListBox *box, GtkWidget *child); + +G_END_DECLS + +#endif /* __EGG_LIST_BOX_ACCESSIBLE_H__ */ diff --git a/egg-list-box.c b/egg-list-box.c index 1532ab07..4d64a340 100644 --- a/egg-list-box.c +++ b/egg-list-box.c @@ -26,6 +26,7 @@ #include #include "egg-list-box.h" +#include "egg-list-box-accessible.h" /* This already exists in gtk as _gtk_marshal_VOID__ENUM_INT, inline it here for now to avoid separate marshallers file */ @@ -293,6 +294,8 @@ egg_list_box_class_init (EggListBoxClass *klass) g_type_class_add_private (klass, sizeof (EggListBoxPrivate)); + gtk_widget_class_set_accessible_type (widget_class, EGG_TYPE_LIST_BOX_ACCESSIBLE); + object_class->finalize = egg_list_box_finalize; widget_class->enter_notify_event = egg_list_box_real_enter_notify_event; widget_class->leave_notify_event = egg_list_box_real_leave_notify_event; @@ -709,6 +712,7 @@ egg_list_box_update_cursor (EggListBox *list_box, priv->cursor_child->y + allocation.y, priv->cursor_child->y + allocation.y + priv->cursor_child->height); } + _egg_list_box_accessible_update_cursor (list_box, child ? child->widget : NULL); } static void @@ -725,6 +729,7 @@ egg_list_box_update_selected (EggListBox *list_box, (priv->selected_child != NULL) ? priv->selected_child->widget : NULL); gtk_widget_queue_draw (GTK_WIDGET (list_box)); } + _egg_list_box_accessible_update_selected (list_box, child ? child->widget : NULL); if (child != NULL) egg_list_box_update_cursor (list_box, child); }