summaryrefslogtreecommitdiff
path: root/gtk/a11y/gtkbuttonaccessible.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2011-07-01 21:25:53 -0400
committerMatthias Clasen <mclasen@redhat.com>2011-07-05 16:08:57 -0400
commit8432ea3574bc71a8a32d8613b84b54bbd84d0057 (patch)
tree644bae16f11286e18c622e34d03002f9aeb9da50 /gtk/a11y/gtkbuttonaccessible.c
parenta3113386dffbacbc6eb9c3b14d0e91e3c11b324b (diff)
downloadgtk+-8432ea3574bc71a8a32d8613b84b54bbd84d0057.tar.gz
Convert GailButton to GtkButtonAccessible
This drops the AtkText implementation, and also strips handling of children out. Instead of listening for enter/leave/press/released, just listen for state changes on the widget.
Diffstat (limited to 'gtk/a11y/gtkbuttonaccessible.c')
-rw-r--r--gtk/a11y/gtkbuttonaccessible.c466
1 files changed, 466 insertions, 0 deletions
diff --git a/gtk/a11y/gtkbuttonaccessible.c b/gtk/a11y/gtkbuttonaccessible.c
new file mode 100644
index 0000000000..64b6d251a3
--- /dev/null
+++ b/gtk/a11y/gtkbuttonaccessible.c
@@ -0,0 +1,466 @@
+/* GAIL - The GNOME Accessibility Implementation Library
+ * Copyright 2001, 2002, 2003 Sun Microsystems 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include "gtkbuttonaccessible.h"
+#include <libgail-util/gailmisc.h>
+
+
+static void atk_action_interface_init (AtkActionIface *iface);
+static void atk_image_interface_init (AtkImageIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkButtonAccessible, gtk_button_accessible, GAIL_TYPE_CONTAINER,
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE, atk_image_interface_init))
+
+static void
+state_changed_cb (GtkWidget *widget, GtkStateFlags previous_flags)
+{
+ AtkObject *accessible;
+ GtkStateFlags flags;
+ gboolean was_active;
+ gboolean active;
+
+ flags = gtk_widget_get_state_flags (widget);
+
+ was_active = (previous_flags & GTK_STATE_FLAG_ACTIVE) != 0;
+ active = (flags & GTK_STATE_FLAG_ACTIVE) != 0;
+
+ accessible = gtk_widget_get_accessible (widget);
+ if (active && !was_active)
+ atk_object_notify_state_change (accessible, ATK_STATE_ARMED, TRUE);
+ else if (!active && was_active)
+ atk_object_notify_state_change (accessible, ATK_STATE_ARMED, FALSE);
+}
+
+static void
+gtk_button_accessible_initialize (AtkObject *obj,
+ gpointer data)
+{
+ GtkWidget *parent;
+
+ ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->initialize (obj, data);
+
+ g_signal_connect (data, "state-flags-changed", G_CALLBACK (state_changed_cb), NULL);
+
+ parent = gtk_widget_get_parent (gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)));
+ if (GTK_IS_TREE_VIEW (parent))
+ {
+ /* Even though the accessible parent of the column header will
+ * be reported as the table because the parent widget of the
+ * GtkTreeViewColumn's button is the GtkTreeView we set
+ * the accessible parent for column header to be the table
+ * to ensure that atk_object_get_index_in_parent() returns
+ * the correct value; see gail_widget_get_index_in_parent().
+ */
+ atk_object_set_parent (obj, gtk_widget_get_accessible (parent));
+ obj->role = ATK_ROLE_TABLE_COLUMN_HEADER;
+ }
+ else
+ obj->role = ATK_ROLE_PUSH_BUTTON;
+}
+
+static GtkWidget *
+get_image_from_button (GtkWidget *button)
+{
+ GtkWidget *image;
+
+ image = gtk_button_get_image (GTK_BUTTON (button));
+ if (GTK_IS_IMAGE (image))
+ return image;
+
+ return NULL;
+}
+
+static GtkWidget *
+find_label_child (GtkContainer *container)
+{
+ GList *children, *tmp_list;
+ GtkWidget *child;
+
+ children = gtk_container_get_children (container);
+
+ child = NULL;
+ for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next)
+ {
+ if (GTK_IS_LABEL (tmp_list->data))
+ {
+ child = GTK_WIDGET (tmp_list->data);
+ break;
+ }
+ else if (GTK_IS_CONTAINER (tmp_list->data))
+ {
+ child = find_label_child (GTK_CONTAINER (tmp_list->data));
+ if (child)
+ break;
+ }
+ }
+ g_list_free (children);
+ return child;
+}
+
+static GtkWidget *
+get_label_from_button (GtkWidget *button)
+{
+ GtkWidget *child;
+
+ child = gtk_bin_get_child (GTK_BIN (button));
+ if (GTK_IS_ALIGNMENT (child))
+ child = gtk_bin_get_child (GTK_BIN (child));
+
+ if (GTK_IS_CONTAINER (child))
+ child = find_label_child (GTK_CONTAINER (child));
+ else if (!GTK_IS_LABEL (child))
+ child = NULL;
+
+ return child;
+}
+
+static const gchar *
+gtk_button_accessible_get_name (AtkObject *obj)
+{
+ const gchar *name = NULL;
+ GtkWidget *widget;
+ GtkWidget *child;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
+ if (widget == NULL)
+ return NULL;
+
+ name = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->get_name (obj);
+ if (name != NULL)
+ return name;
+
+ child = get_label_from_button (widget);
+ if (GTK_IS_LABEL (child))
+ name = gtk_label_get_text (GTK_LABEL (child));
+ else
+ {
+ GtkWidget *image;
+
+ image = get_image_from_button (widget);
+ if (GTK_IS_IMAGE (image))
+ {
+ AtkObject *atk_obj;
+
+ atk_obj = gtk_widget_get_accessible (image);
+ name = atk_object_get_name (atk_obj);
+ }
+ }
+
+ return name;
+}
+
+static gint
+gtk_button_accessible_get_n_children (AtkObject* obj)
+{
+ return 0;
+}
+
+static AtkObject *
+gtk_button_accessible_ref_child (AtkObject *obj,
+ gint i)
+{
+ return NULL;
+}
+
+static AtkStateSet *
+gtk_button_accessible_ref_state_set (AtkObject *obj)
+{
+ AtkStateSet *state_set;
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
+ if (widget == NULL)
+ return NULL;
+
+ state_set = ATK_OBJECT_CLASS (gtk_button_accessible_parent_class)->ref_state_set (obj);
+
+ if ((gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_ACTIVE) != 0)
+ atk_state_set_add_state (state_set, ATK_STATE_ARMED);
+
+ if (!gtk_widget_get_can_focus (widget))
+ atk_state_set_remove_state (state_set, ATK_STATE_SELECTABLE);
+
+ return state_set;
+}
+
+static void
+gtk_button_accessible_notify_gtk (GObject *obj,
+ GParamSpec *pspec)
+{
+ GtkWidget *widget = GTK_WIDGET (obj);
+ AtkObject *atk_obj = gtk_widget_get_accessible (widget);
+
+ if (strcmp (pspec->name, "label") == 0)
+ {
+ if (atk_obj->name == NULL)
+ g_object_notify (G_OBJECT (atk_obj), "accessible-name");
+
+ g_signal_emit_by_name (atk_obj, "visible_data_changed");
+ }
+ else
+ GAIL_WIDGET_CLASS (gtk_button_accessible_parent_class)->notify_gtk (obj, pspec);
+}
+
+static void
+gtk_button_accessible_class_init (GtkButtonAccessibleClass *klass)
+{
+ AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
+ GailContainerClass *container_class = (GailContainerClass*)klass;
+ GailWidgetClass *widget_class = (GailWidgetClass*)klass;
+
+ class->get_name = gtk_button_accessible_get_name;
+ class->get_n_children = gtk_button_accessible_get_n_children;
+ class->ref_child = gtk_button_accessible_ref_child;
+ class->ref_state_set = gtk_button_accessible_ref_state_set;
+ class->initialize = gtk_button_accessible_initialize;
+
+ widget_class->notify_gtk = gtk_button_accessible_notify_gtk;
+
+ container_class->add_gtk = NULL;
+ container_class->remove_gtk = NULL;
+}
+
+static void
+gtk_button_accessible_init (GtkButtonAccessible *button)
+{
+}
+
+static gboolean
+gtk_button_accessible_do_action (AtkAction *action,
+ gint i)
+{
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
+ if (widget == NULL)
+ return FALSE;
+
+ if (i != 0)
+ return FALSE;
+
+ if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget))
+ return FALSE;
+
+ gtk_button_clicked (GTK_BUTTON (widget));
+ return TRUE;
+}
+
+static gint
+gtk_button_accessible_get_n_actions (AtkAction *action)
+{
+ return 1;
+}
+
+static const gchar *
+gtk_button_accessible_get_keybinding (AtkAction *action,
+ gint i)
+{
+ GtkButtonAccessible *button;
+ gchar *return_value = NULL;
+ GtkWidget *widget;
+ GtkWidget *label;
+ guint key_val;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
+ if (widget == NULL)
+ return NULL;
+
+ if (i != 0)
+ return NULL;
+
+ button = GTK_BUTTON_ACCESSIBLE (action);
+
+ label = get_label_from_button (widget);
+ if (GTK_IS_LABEL (label))
+ {
+ key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
+ if (key_val != GDK_KEY_VoidSymbol)
+ return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
+ }
+ if (return_value == NULL)
+ {
+ /* Find labelled-by relation */
+ AtkRelationSet *set;
+ AtkRelation *relation;
+ GPtrArray *target;
+ gpointer target_object;
+
+ set = atk_object_ref_relation_set (ATK_OBJECT (action));
+ if (set)
+ {
+ relation = atk_relation_set_get_relation_by_type (set, ATK_RELATION_LABELLED_BY);
+ if (relation)
+ {
+ target = atk_relation_get_target (relation);
+ target_object = g_ptr_array_index (target, 0);
+ label = gtk_accessible_get_widget (GTK_ACCESSIBLE (target_object));
+ }
+ g_object_unref (set);
+ }
+
+ if (GTK_IS_LABEL (label))
+ {
+ key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
+ if (key_val != GDK_KEY_VoidSymbol)
+ return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
+ }
+ }
+ return return_value;
+}
+
+static const gchar *
+gtk_button_accessible_action_get_name (AtkAction *action,
+ gint i)
+{
+ if (i != 0)
+ return NULL;
+
+ return "click";
+}
+
+static void
+atk_action_interface_init (AtkActionIface *iface)
+{
+ iface->do_action = gtk_button_accessible_do_action;
+ iface->get_n_actions = gtk_button_accessible_get_n_actions;
+ iface->get_keybinding = gtk_button_accessible_get_keybinding;
+ iface->get_name = gtk_button_accessible_action_get_name;
+}
+
+static const gchar *
+gtk_button_accessible_get_image_description (AtkImage *image)
+{
+ GtkWidget *widget;
+ GtkWidget *button_image;
+ AtkObject *obj;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
+ if (widget == NULL)
+ return NULL;
+
+ button_image = get_image_from_button (widget);
+ if (GTK_IS_IMAGE (button_image))
+ {
+ obj = gtk_widget_get_accessible (button_image);
+ return atk_image_get_image_description (ATK_IMAGE (obj));
+ }
+
+ return NULL;
+}
+
+static void
+gtk_button_accessible_get_image_position (AtkImage *image,
+ gint *x,
+ gint *y,
+ AtkCoordType coord_type)
+{
+ GtkWidget *widget;
+ GtkImage *button_image;
+ AtkObject *obj;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
+ if (widget == NULL)
+ {
+ *x = G_MININT;
+ *y = G_MININT;
+ return;
+ }
+
+ button_image = get_image_from_button (widget);
+
+ if (button_image != NULL)
+ {
+ obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
+ atk_component_get_position (ATK_COMPONENT (obj), x, y, coord_type);
+ }
+ else
+ {
+ *x = G_MININT;
+ *y = G_MININT;
+ }
+}
+
+static void
+gtk_button_accessible_get_image_size (AtkImage *image,
+ gint *width,
+ gint *height)
+{
+ GtkWidget *widget;
+ GtkImage *button_image;
+ AtkObject *obj;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
+ if (widget == NULL)
+ {
+ *width = -1;
+ *height = -1;
+ return;
+ }
+
+ button_image = get_image_from_button (widget);
+
+ if (button_image != NULL)
+ {
+ obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
+ atk_image_get_image_size (ATK_IMAGE (obj), width, height);
+ }
+ else
+ {
+ *width = -1;
+ *height = -1;
+ }
+}
+
+static gboolean
+gtk_button_accessible_set_image_description (AtkImage *image,
+ const gchar *description)
+{
+ GtkWidget *widget;
+ GtkImage *button_image;
+ AtkObject *obj;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (image));
+
+ if (widget == NULL)
+ return FALSE;
+
+ button_image = get_image_from_button (widget);
+
+ if (button_image != NULL)
+ {
+ obj = gtk_widget_get_accessible (GTK_WIDGET (button_image));
+ return atk_image_set_image_description (ATK_IMAGE (obj), description);
+ }
+
+ return FALSE;
+}
+
+static void
+atk_image_interface_init (AtkImageIface *iface)
+{
+ iface->get_image_description = gtk_button_accessible_get_image_description;
+ iface->get_image_position = gtk_button_accessible_get_image_position;
+ iface->get_image_size = gtk_button_accessible_get_image_size;
+ iface->set_image_description = gtk_button_accessible_set_image_description;
+}