diff options
Diffstat (limited to 'eel/eel-accessibility.c')
-rw-r--r-- | eel/eel-accessibility.c | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/eel/eel-accessibility.c b/eel/eel-accessibility.c new file mode 100644 index 00000000..1a8a8037 --- /dev/null +++ b/eel/eel-accessibility.c @@ -0,0 +1,432 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* eel-accessibility.h - Utility functions for accessibility + + Copyright (C) 2002 Anders Carlsson, Sun Microsystems, Inc. + + The Eel Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Eel 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Eel Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: + Anders Carlsson <[email protected]> + Michael Meeks <[email protected]> +*/ +#include <config.h> +#include <gtk/gtk.h> +#include <atk/atkrelationset.h> +#include <eel/eel-accessibility.h> + +void +eel_accessibility_set_up_label_widget_relation (GtkWidget *label, GtkWidget *widget) +{ + AtkObject *atk_widget, *atk_label; + + atk_label = gtk_widget_get_accessible (label); + atk_widget = gtk_widget_get_accessible (widget); + + /* Create the label -> widget relation */ + atk_object_add_relationship (atk_label, ATK_RELATION_LABEL_FOR, atk_widget); + + /* Create the widget -> label relation */ + atk_object_add_relationship (atk_widget, ATK_RELATION_LABELLED_BY, atk_label); +} + +/* + * Hacks to make re-using gail somewhat easier. + */ + +/** + * eel_accessibility_create_derived_type: + * @type_name: the name for the new accessible type eg. CajaIconCanvasItemAccessible + * @existing_gobject_with_proxy: the GType of an object that has a registered factory that + * manufactures the type we want to inherit from. ie. to inherit from a GailCanvasItem + * we need to pass MATE_TYPE_CANVAS_ITEM - since GailCanvasItem is registered against + * that type. + * @opt_gail_parent_class: the name of the Gail class to derive from eg. GailCanvasItem + * @class_init: the init function to run for this class + * + * This should be run to register the type, it can subsequently be run with + * the same name and will not re-register it, but simply return it. + * + * NB. to do instance init, you prolly want to override AtkObject::initialize + * + * Return value: the registered type, or 0 on failure. + **/ +GType +eel_accessibility_create_derived_type (const char *type_name, + GType existing_gobject_with_proxy, + EelAccessibilityClassInitFn class_init) +{ + GType type; + GType parent_atk_type; + GTypeInfo tinfo = { 0 }; + GTypeQuery query; + AtkObjectFactory *factory; + + if ((type = g_type_from_name (type_name))) + { + return type; + } + + factory = atk_registry_get_factory + (atk_get_default_registry (), + existing_gobject_with_proxy); + if (!factory) + { + return G_TYPE_INVALID; + } + + parent_atk_type = atk_object_factory_get_accessible_type (factory); + if (!parent_atk_type) + { + return G_TYPE_INVALID; + } + + /* + * Figure out the size of the class and instance + * we are deriving from + */ + g_type_query (parent_atk_type, &query); + + if (class_init) + { + tinfo.class_init = (GClassInitFunc) class_init; + } + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + /* Register the type */ + type = g_type_register_static ( + parent_atk_type, type_name, &tinfo, 0); + + return type; +} + + +static GQuark +get_quark_accessible (void) +{ + static GQuark quark_accessible_object = 0; + + if (!quark_accessible_object) + { + quark_accessible_object = g_quark_from_static_string + ("accessible-object"); + } + + return quark_accessible_object; +} + +static GQuark +get_quark_gobject (void) +{ + static GQuark quark_accessible_gobject = 0; + + if (!quark_accessible_gobject) + { + quark_accessible_gobject = g_quark_from_static_string + ("object-for-accessible"); + } + + return quark_accessible_gobject; +} + +/** + * eel_accessibility_get_atk_object: + * @object: a GObject of some sort + * + * gets an AtkObject associated with a GObject + * + * Return value: the associated accessible if one exists or NULL + **/ +AtkObject * +eel_accessibility_get_atk_object (gpointer object) +{ + return g_object_get_qdata (object, get_quark_accessible ()); +} + +/** + * eel_accessibilty_for_object: + * @object: a GObject of some sort + * + * gets an AtkObject associated with a GObject and if it doesn't + * exist creates a suitable accessible object. + * + * Return value: an associated accessible. + **/ +AtkObject * +eel_accessibility_for_object (gpointer object) +{ + if (GTK_IS_WIDGET (object)) + return gtk_widget_get_accessible (object); + + return atk_gobject_accessible_for_object (object); +} + +/** + * eel_accessibility_get_gobject: + * @object: an AtkObject + * + * gets the GObject associated with the AtkObject, for which + * @object provides accessibility support. + * + * Return value: the accessible's associated GObject + **/ +gpointer +eel_accessibility_get_gobject (AtkObject *object) +{ + return g_object_get_qdata (G_OBJECT (object), get_quark_gobject ()); +} + +static void +eel_accessibility_destroy (gpointer data, + GObject *where_the_object_was) +{ + atk_object_notify_state_change + (ATK_OBJECT (data), ATK_STATE_DEFUNCT, TRUE); +} + +/** + * eel_accessibility_set_atk_object_return: + * @object: a GObject + * @atk_object: it's AtkObject + * + * used to register and return a new accessible object for something + * + * Return value: @atk_object. + **/ +AtkObject * +eel_accessibility_set_atk_object_return (gpointer object, + AtkObject *atk_object) +{ + atk_object_initialize (atk_object, object); + + if (!ATK_IS_GOBJECT_ACCESSIBLE (atk_object)) + { + g_object_set_qdata_full + (object, get_quark_accessible (), atk_object, + (GDestroyNotify)eel_accessibility_destroy); + g_object_set_qdata + (G_OBJECT (atk_object), get_quark_gobject (), object); + } + + return atk_object; +} + +static GailTextUtil * +get_simple_text (gpointer object) +{ + GObject *gobject; + EelAccessibleTextIface *aif; + + if (GTK_IS_ACCESSIBLE (object)) + { + gobject = G_OBJECT (gtk_accessible_get_widget (GTK_ACCESSIBLE (object))); + } + else + { + gobject = eel_accessibility_get_gobject (object); + } + + if (!gobject) + { + return NULL; + } + + aif = EEL_ACCESSIBLE_TEXT_GET_IFACE (gobject); + if (!aif) + { + g_warning ("No accessible text inferface on '%s'", + g_type_name_from_instance ((gpointer) gobject)); + + } + else if (aif->get_text) + { + return aif->get_text (gobject); + } + + return NULL; +} + +char * +eel_accessibility_text_get_text (AtkText *text, + gint start_pos, + gint end_pos) +{ + GailTextUtil *util = get_simple_text (text); + g_return_val_if_fail (util != NULL, NULL); + + return gail_text_util_get_substring (util, start_pos, end_pos); +} + +gunichar +eel_accessibility_text_get_character_at_offset (AtkText *text, + gint offset) +{ + char *txt, *index; + gint sucks1 = 0, sucks2 = -1; + gunichar c; + GailTextUtil *util = get_simple_text (text); + g_return_val_if_fail (util != NULL, 0); + + txt = gail_text_util_get_substring (util, sucks1, sucks2); + + index = g_utf8_offset_to_pointer (txt, offset); + c = g_utf8_get_char (index); + g_free (txt); + + return c; +} + +char * +eel_accessibility_text_get_text_before_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + GailTextUtil *util = get_simple_text (text); + g_return_val_if_fail (util != NULL, NULL); + + return gail_text_util_get_text ( + util, NULL, GAIL_BEFORE_OFFSET, + boundary_type, offset, start_offset, end_offset); +} + +char * +eel_accessibility_text_get_text_at_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + GailTextUtil *util = get_simple_text (text); + g_return_val_if_fail (util != NULL, NULL); + + return gail_text_util_get_text ( + util, NULL, GAIL_AT_OFFSET, + boundary_type, offset, start_offset, end_offset); +} + +gchar* +eel_accessibility_text_get_text_after_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + GailTextUtil *util = get_simple_text (text); + g_return_val_if_fail (util != NULL, NULL); + + return gail_text_util_get_text ( + util, NULL, GAIL_AFTER_OFFSET, + boundary_type, offset, start_offset, end_offset); +} + +gint +eel_accessibility_text_get_character_count (AtkText *text) +{ + GailTextUtil *util = get_simple_text (text); + g_return_val_if_fail (util != NULL, -1); + + return gtk_text_buffer_get_char_count (util->buffer); +} + +static void +eel_accessibility_simple_text_interface_init (AtkTextIface *iface) +{ + iface->get_text = eel_accessibility_text_get_text; + iface->get_character_at_offset = eel_accessibility_text_get_character_at_offset; + iface->get_text_before_offset = eel_accessibility_text_get_text_before_offset; + iface->get_text_at_offset = eel_accessibility_text_get_text_at_offset; + iface->get_text_after_offset = eel_accessibility_text_get_text_after_offset; + iface->get_character_count = eel_accessibility_text_get_character_count; + + /* iface->get_caret_offset = eel_accessibility_text_get_caret_offset; + iface->set_caret_offset = eel_accessibility_text_set_caret_offset; + iface->get_selection = eel_accessibility_text_get_selection; + iface->get_n_selections = eel_accessibility_text_get_n_selections; + iface->add_selection = eel_accessibility_text_add_selection; + iface->remove_selection = eel_accessibility_text_remove_selection; + iface->set_selection = eel_accessibility_text_set_selection; + iface->get_run_attributes = eel_accessibility_text_get_run_attributes; + iface->get_default_attributes = eel_accessibility_text_get_default_attributes; + iface->get_character_extents = eel_accessibility_text_get_character_extents; + iface->get_offset_at_point = eel_accessibility_text_get_offset_at_point; */ +} + +void +eel_accessibility_add_simple_text (GType type) +{ + const GInterfaceInfo simple_text_info = + { + (GInterfaceInitFunc) + eel_accessibility_simple_text_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + g_return_if_fail (type != G_TYPE_INVALID); + + g_type_add_interface_static ( + type, ATK_TYPE_TEXT, &simple_text_info); +} + +GType +eel_accessible_text_get_type (void) +{ + static GType type = 0; + + if (!type) + { + const GTypeInfo tinfo = + { + sizeof (AtkTextIface), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) NULL, + (GClassFinalizeFunc) NULL + }; + + type = g_type_register_static ( + G_TYPE_INTERFACE, "EelAccessibleText", &tinfo, 0); + } + + return type; +} + +void +eel_accessibility_set_name (gpointer object, + const char *name) +{ + AtkObject *atk_object = eel_accessibility_for_object (object); + + if (atk_object) + { + atk_object_set_name (atk_object, name); + } +} + +void +eel_accessibility_set_description (gpointer object, + const char *description) +{ + AtkObject *atk_object = eel_accessibility_for_object (object); + + if (atk_object) + { + atk_object_set_description (atk_object, description); + } +} |