Lines
93.31 %
Functions
91.67 %
Branches
62.5 %
/*
* AT-SPI - Assistive Technology Service Provider Interface
* (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
*
* Copyright 2008 Novell, Inc.
* Copyright 2008, 2009, 2010 Codethink Ltd.
* 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.1 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
* This module contains utility functions for exporting AT-SPI
* objects based upon an ATK object.
* It incudes functions for marshalling object references
* and supported interfaces to a D-Bus message.
#include "atspi/atspi.h"
#include "spi-dbus.h"
#include <atk/atk.h>
#include "accessible-cache.h"
#include "accessible-leasing.h"
#include "accessible-register.h"
#include "bridge.h"
/*---------------------------------------------------------------------------*/
* This is the all important function that decides whether an object should
* be leased or not.
* The choice of algorithm for this is somewhat vuage. We want ideally to lease
* all atk objects that are not owned by their parent.
* The 'cache' object attempts to cache all objects that are owned by their
* parent by traversing the tree of accessibles, ignoring the children of
* manages-descendants and transient objects.
* This function will simply look for all the accessibles that the cache object
* has not found and assume that they need to be leased.
void
spi_object_lease_if_needed (GObject *obj)
{
if (!spi_cache_in (spi_global_cache, obj))
spi_leasing_take (spi_global_leasing, obj);
}
* It is assumed that all of these functions are returning an accessible
* object to the client side.
* All of them will lease the AtkObject if it is deemed neccessary.
spi_object_append_null_reference (DBusMessageIter *iter)
DBusMessageIter iter_struct;
const char *name;
const char *path = ATSPI_DBUS_PATH_NULL;
name = dbus_bus_get_unique_name (spi_global_app_data->bus);
dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
&iter_struct);
dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name);
dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
dbus_message_iter_close_container (iter, &iter_struct);
spi_object_append_reference (DBusMessageIter *iter, AtkObject *obj)
const gchar *name;
gchar *path;
if (!obj)
spi_object_append_null_reference (iter);
return;
spi_object_lease_if_needed (G_OBJECT (obj));
path = spi_register_object_to_path (spi_global_register, G_OBJECT (obj));
if (!path)
path = g_strdup (SPI_DBUS_PATH_NULL);
g_free (path);
/* TODO: Perhaps combine with spi_object_append_reference. Leaving separate
* for now in case we want to use a different path for hyperlinks. */
spi_hyperlink_append_reference (DBusMessageIter *iter, AtkHyperlink *obj)
spi_object_append_v_reference (DBusMessageIter *iter, AtkObject *obj)
DBusMessageIter iter_variant;
dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
&iter_variant);
spi_object_append_reference (&iter_variant, obj);
dbus_message_iter_close_container (iter, &iter_variant);
spi_object_append_desktop_reference (DBusMessageIter *iter)
const char *name = spi_global_app_data->desktop_name;
const char *path = spi_global_app_data->desktop_path;
DBusMessage *
spi_object_return_reference (DBusMessage *msg, AtkObject *obj)
DBusMessage *reply;
reply = dbus_message_new_method_return (msg);
if (reply)
DBusMessageIter iter;
dbus_message_iter_init_append (reply, &iter);
spi_object_append_reference (&iter, obj);
return reply;
spi_hyperlink_return_reference (DBusMessage *msg, AtkHyperlink *obj)
spi_hyperlink_append_reference (&iter, obj);
if (obj)
g_object_unref (G_OBJECT (obj));
spi_object_append_interfaces (DBusMessageIter *iter, AtkObject *obj)
const gchar *itf;
itf = ATSPI_DBUS_INTERFACE_ACCESSIBLE;
dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf);
if (ATK_IS_ACTION (obj))
itf = ATSPI_DBUS_INTERFACE_ACTION;
if (atk_object_get_role (obj) == ATK_ROLE_APPLICATION)
itf = ATSPI_DBUS_INTERFACE_APPLICATION;
if (ATK_IS_COMPONENT (obj))
itf = ATSPI_DBUS_INTERFACE_COMPONENT;
if (ATK_IS_EDITABLE_TEXT (obj))
itf = ATSPI_DBUS_INTERFACE_EDITABLE_TEXT;
if (ATK_IS_TEXT (obj))
itf = ATSPI_DBUS_INTERFACE_TEXT;
if (ATK_IS_HYPERTEXT (obj))
itf = ATSPI_DBUS_INTERFACE_HYPERTEXT;
if (ATK_IS_IMAGE (obj))
itf = ATSPI_DBUS_INTERFACE_IMAGE;
if (ATK_IS_SELECTION (obj))
itf = ATSPI_DBUS_INTERFACE_SELECTION;
if (ATK_IS_TABLE (obj))
itf = ATSPI_DBUS_INTERFACE_TABLE;
if (ATK_IS_TABLE_CELL (obj))
itf = ATSPI_DBUS_INTERFACE_TABLE_CELL;
if (ATK_IS_VALUE (obj))
itf = ATSPI_DBUS_INTERFACE_VALUE;
#if 0
if (ATK_IS_STREAMABLE_CONTENT (obj))
itf = "org.a11y.atspi.StreamableContent";
#endif
if (ATK_IS_OBJECT (obj))
itf = "org.a11y.atspi.Collection";
if (ATK_IS_DOCUMENT (obj))
itf = ATSPI_DBUS_INTERFACE_DOCUMENT;
if (ATK_IS_HYPERLINK_IMPL (obj))
itf = ATSPI_DBUS_INTERFACE_HYPERLINK;
spi_object_append_attribute_set (DBusMessageIter *iter, AtkAttributeSet *attr)
DBusMessageIter dictIter;
dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &dictIter);
while (attr)
DBusMessageIter dictEntryIter;
AtkAttribute *attribute = (AtkAttribute *) attr->data;
const char *key = attribute->name;
const char *value = attribute->value;
if (key == NULL)
key = "";
if (value == NULL)
value = "";
dbus_message_iter_open_container (&dictIter, DBUS_TYPE_DICT_ENTRY, NULL,
&dictEntryIter);
dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING,
&key);
&value);
dbus_message_iter_close_container (&dictIter, &dictEntryIter);
attr = g_slist_next (attr);
dbus_message_iter_close_container (iter, &dictIter);
static gboolean
init_role_lookup_table (AtspiRole *role_table)
int i;
/* if it's not in the list below, dunno what it is */
for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i)
role_table[i] = ATSPI_ROLE_UNKNOWN;
role_table[ATK_ROLE_INVALID] = ATSPI_ROLE_INVALID;
role_table[ATK_ROLE_ACCEL_LABEL] = ATSPI_ROLE_ACCELERATOR_LABEL;
role_table[ATK_ROLE_ALERT] = ATSPI_ROLE_ALERT;
role_table[ATK_ROLE_ANIMATION] = ATSPI_ROLE_ANIMATION;
role_table[ATK_ROLE_ARROW] = ATSPI_ROLE_ARROW;
role_table[ATK_ROLE_CALENDAR] = ATSPI_ROLE_CALENDAR;
role_table[ATK_ROLE_CANVAS] = ATSPI_ROLE_CANVAS;
role_table[ATK_ROLE_CHECK_BOX] = ATSPI_ROLE_CHECK_BOX;
role_table[ATK_ROLE_CHECK_MENU_ITEM] = ATSPI_ROLE_CHECK_MENU_ITEM;
role_table[ATK_ROLE_COLOR_CHOOSER] = ATSPI_ROLE_COLOR_CHOOSER;
role_table[ATK_ROLE_COLUMN_HEADER] = ATSPI_ROLE_COLUMN_HEADER;
role_table[ATK_ROLE_COMBO_BOX] = ATSPI_ROLE_COMBO_BOX;
role_table[ATK_ROLE_DATE_EDITOR] = ATSPI_ROLE_DATE_EDITOR;
role_table[ATK_ROLE_DESKTOP_ICON] = ATSPI_ROLE_DESKTOP_ICON;
role_table[ATK_ROLE_DESKTOP_FRAME] = ATSPI_ROLE_DESKTOP_FRAME;
role_table[ATK_ROLE_DIAL] = ATSPI_ROLE_DIAL;
role_table[ATK_ROLE_DIALOG] = ATSPI_ROLE_DIALOG;
role_table[ATK_ROLE_DIRECTORY_PANE] = ATSPI_ROLE_DIRECTORY_PANE;
role_table[ATK_ROLE_DRAWING_AREA] = ATSPI_ROLE_DRAWING_AREA;
role_table[ATK_ROLE_FILE_CHOOSER] = ATSPI_ROLE_FILE_CHOOSER;
role_table[ATK_ROLE_FILLER] = ATSPI_ROLE_FILLER;
role_table[ATK_ROLE_FONT_CHOOSER] = ATSPI_ROLE_FONT_CHOOSER;
role_table[ATK_ROLE_FRAME] = ATSPI_ROLE_FRAME;
role_table[ATK_ROLE_GLASS_PANE] = ATSPI_ROLE_GLASS_PANE;
role_table[ATK_ROLE_HTML_CONTAINER] = ATSPI_ROLE_HTML_CONTAINER;
role_table[ATK_ROLE_ICON] = ATSPI_ROLE_ICON;
role_table[ATK_ROLE_IMAGE] = ATSPI_ROLE_IMAGE;
role_table[ATK_ROLE_INTERNAL_FRAME] = ATSPI_ROLE_INTERNAL_FRAME;
role_table[ATK_ROLE_LABEL] = ATSPI_ROLE_LABEL;
role_table[ATK_ROLE_LAYERED_PANE] = ATSPI_ROLE_LAYERED_PANE;
role_table[ATK_ROLE_LIST] = ATSPI_ROLE_LIST;
role_table[ATK_ROLE_LIST_ITEM] = ATSPI_ROLE_LIST_ITEM;
role_table[ATK_ROLE_MENU] = ATSPI_ROLE_MENU;
role_table[ATK_ROLE_MENU_BAR] = ATSPI_ROLE_MENU_BAR;
role_table[ATK_ROLE_MENU_ITEM] = ATSPI_ROLE_MENU_ITEM;
role_table[ATK_ROLE_OPTION_PANE] = ATSPI_ROLE_OPTION_PANE;
role_table[ATK_ROLE_PAGE_TAB] = ATSPI_ROLE_PAGE_TAB;
role_table[ATK_ROLE_PAGE_TAB_LIST] = ATSPI_ROLE_PAGE_TAB_LIST;
role_table[ATK_ROLE_PANEL] = ATSPI_ROLE_PANEL;
role_table[ATK_ROLE_PASSWORD_TEXT] = ATSPI_ROLE_PASSWORD_TEXT;
role_table[ATK_ROLE_POPUP_MENU] = ATSPI_ROLE_POPUP_MENU;
role_table[ATK_ROLE_PROGRESS_BAR] = ATSPI_ROLE_PROGRESS_BAR;
role_table[ATK_ROLE_PUSH_BUTTON] = ATSPI_ROLE_PUSH_BUTTON;
role_table[ATK_ROLE_RADIO_BUTTON] = ATSPI_ROLE_RADIO_BUTTON;
role_table[ATK_ROLE_RADIO_MENU_ITEM] = ATSPI_ROLE_RADIO_MENU_ITEM;
role_table[ATK_ROLE_ROOT_PANE] = ATSPI_ROLE_ROOT_PANE;
role_table[ATK_ROLE_ROW_HEADER] = ATSPI_ROLE_ROW_HEADER;
role_table[ATK_ROLE_SCROLL_BAR] = ATSPI_ROLE_SCROLL_BAR;
role_table[ATK_ROLE_SCROLL_PANE] = ATSPI_ROLE_SCROLL_PANE;
role_table[ATK_ROLE_SEPARATOR] = ATSPI_ROLE_SEPARATOR;
role_table[ATK_ROLE_SLIDER] = ATSPI_ROLE_SLIDER;
role_table[ATK_ROLE_SPIN_BUTTON] = ATSPI_ROLE_SPIN_BUTTON;
role_table[ATK_ROLE_SPLIT_PANE] = ATSPI_ROLE_SPLIT_PANE;
role_table[ATK_ROLE_STATUSBAR] = ATSPI_ROLE_STATUS_BAR;
role_table[ATK_ROLE_TABLE] = ATSPI_ROLE_TABLE;
role_table[ATK_ROLE_TABLE_CELL] = ATSPI_ROLE_TABLE_CELL;
role_table[ATK_ROLE_TABLE_COLUMN_HEADER] =
ATSPI_ROLE_TABLE_COLUMN_HEADER;
role_table[ATK_ROLE_TABLE_ROW_HEADER] = ATSPI_ROLE_TABLE_ROW_HEADER;
role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] =
ATSPI_ROLE_TEAROFF_MENU_ITEM;
role_table[ATK_ROLE_TERMINAL] = ATSPI_ROLE_TERMINAL;
role_table[ATK_ROLE_TEXT] = ATSPI_ROLE_TEXT;
role_table[ATK_ROLE_TOGGLE_BUTTON] = ATSPI_ROLE_TOGGLE_BUTTON;
role_table[ATK_ROLE_TOOL_BAR] = ATSPI_ROLE_TOOL_BAR;
role_table[ATK_ROLE_TOOL_TIP] = ATSPI_ROLE_TOOL_TIP;
role_table[ATK_ROLE_TREE] = ATSPI_ROLE_TREE;
role_table[ATK_ROLE_TREE_TABLE] = ATSPI_ROLE_TREE_TABLE;
role_table[ATK_ROLE_UNKNOWN] = ATSPI_ROLE_UNKNOWN;
role_table[ATK_ROLE_VIEWPORT] = ATSPI_ROLE_VIEWPORT;
role_table[ATK_ROLE_WINDOW] = ATSPI_ROLE_WINDOW;
role_table[ATK_ROLE_HEADER] = ATSPI_ROLE_HEADER;
role_table[ATK_ROLE_FOOTER] = ATSPI_ROLE_FOOTER;
role_table[ATK_ROLE_PARAGRAPH] = ATSPI_ROLE_PARAGRAPH;
role_table[ATK_ROLE_RULER] = ATSPI_ROLE_RULER;
role_table[ATK_ROLE_APPLICATION] = ATSPI_ROLE_APPLICATION;
role_table[ATK_ROLE_AUTOCOMPLETE] = ATSPI_ROLE_AUTOCOMPLETE;
role_table[ATK_ROLE_EDITBAR] = ATSPI_ROLE_EDITBAR;
role_table[ATK_ROLE_EMBEDDED] = ATSPI_ROLE_EMBEDDED;
role_table[ATK_ROLE_ENTRY] = ATSPI_ROLE_ENTRY;
role_table[ATK_ROLE_CHART] = ATSPI_ROLE_CHART;
role_table[ATK_ROLE_CAPTION] = ATSPI_ROLE_CAPTION;
role_table[ATK_ROLE_DOCUMENT_FRAME] = ATSPI_ROLE_DOCUMENT_FRAME;
role_table[ATK_ROLE_HEADING] = ATSPI_ROLE_HEADING;
role_table[ATK_ROLE_PAGE] = ATSPI_ROLE_PAGE;
role_table[ATK_ROLE_SECTION] = ATSPI_ROLE_SECTION;
role_table[ATK_ROLE_FORM] = ATSPI_ROLE_FORM;
role_table[ATK_ROLE_REDUNDANT_OBJECT] = ATSPI_ROLE_REDUNDANT_OBJECT;
role_table[ATK_ROLE_LINK] = ATSPI_ROLE_LINK;
role_table[ATK_ROLE_INPUT_METHOD_WINDOW] =
ATSPI_ROLE_INPUT_METHOD_WINDOW;
role_table[ATK_ROLE_TABLE_ROW] = ATSPI_ROLE_TABLE_ROW;
role_table[ATK_ROLE_TREE_ITEM] = ATSPI_ROLE_TREE_ITEM;
role_table[ATK_ROLE_DOCUMENT_SPREADSHEET] =
ATSPI_ROLE_DOCUMENT_SPREADSHEET;
role_table[ATK_ROLE_DOCUMENT_PRESENTATION] =
ATSPI_ROLE_DOCUMENT_PRESENTATION;
role_table[ATK_ROLE_DOCUMENT_TEXT] = ATSPI_ROLE_DOCUMENT_TEXT;
role_table[ATK_ROLE_DOCUMENT_WEB] = ATSPI_ROLE_DOCUMENT_WEB;
role_table[ATK_ROLE_DOCUMENT_EMAIL] = ATSPI_ROLE_DOCUMENT_EMAIL;
role_table[ATK_ROLE_COMMENT] = ATSPI_ROLE_COMMENT;
role_table[ATK_ROLE_LIST_BOX] = ATSPI_ROLE_LIST_BOX;
role_table[ATK_ROLE_GROUPING] = ATSPI_ROLE_GROUPING;
role_table[ATK_ROLE_IMAGE_MAP] = ATSPI_ROLE_IMAGE_MAP;
role_table[ATK_ROLE_NOTIFICATION] = ATSPI_ROLE_NOTIFICATION;
role_table[ATK_ROLE_INFO_BAR] = ATSPI_ROLE_INFO_BAR;
role_table[ATK_ROLE_LEVEL_BAR] = ATSPI_ROLE_LEVEL_BAR;
role_table[ATK_ROLE_TITLE_BAR] = ATSPI_ROLE_TITLE_BAR;
role_table[ATK_ROLE_BLOCK_QUOTE] = ATSPI_ROLE_BLOCK_QUOTE;
role_table[ATK_ROLE_AUDIO] = ATSPI_ROLE_AUDIO;
role_table[ATK_ROLE_VIDEO] = ATSPI_ROLE_VIDEO;
role_table[ATK_ROLE_DEFINITION] = ATSPI_ROLE_DEFINITION;
role_table[ATK_ROLE_ARTICLE] = ATSPI_ROLE_ARTICLE;
role_table[ATK_ROLE_LANDMARK] = ATSPI_ROLE_LANDMARK;
role_table[ATK_ROLE_LOG] = ATSPI_ROLE_LOG;
role_table[ATK_ROLE_MARQUEE] = ATSPI_ROLE_MARQUEE;
role_table[ATK_ROLE_MATH] = ATSPI_ROLE_MATH;
role_table[ATK_ROLE_RATING] = ATSPI_ROLE_RATING;
role_table[ATK_ROLE_TIMER] = ATSPI_ROLE_TIMER;
role_table[ATK_ROLE_STATIC] = ATSPI_ROLE_STATIC;
role_table[ATK_ROLE_MATH_FRACTION] = ATSPI_ROLE_MATH_FRACTION;
role_table[ATK_ROLE_MATH_ROOT] = ATSPI_ROLE_MATH_ROOT;
role_table[ATK_ROLE_SUBSCRIPT] = ATSPI_ROLE_SUBSCRIPT;
role_table[ATK_ROLE_SUPERSCRIPT] = ATSPI_ROLE_SUPERSCRIPT;
role_table[ATK_ROLE_DESCRIPTION_LIST] = ATSPI_ROLE_DESCRIPTION_LIST;
role_table[ATK_ROLE_DESCRIPTION_TERM] = ATSPI_ROLE_DESCRIPTION_TERM;
role_table[ATK_ROLE_DESCRIPTION_VALUE] = ATSPI_ROLE_DESCRIPTION_VALUE;
role_table[ATK_ROLE_FOOTNOTE] = ATSPI_ROLE_FOOTNOTE;
role_table[ATK_ROLE_CONTENT_DELETION] = ATSPI_ROLE_CONTENT_DELETION;
role_table[ATK_ROLE_CONTENT_INSERTION] = ATSPI_ROLE_CONTENT_INSERTION;
role_table[ATK_ROLE_MARK] = ATSPI_ROLE_MARK;
role_table[ATK_ROLE_SUGGESTION] = ATSPI_ROLE_SUGGESTION;
role_table[ATK_ROLE_PUSH_BUTTON_MENU] = ATSPI_ROLE_PUSH_BUTTON_MENU;
return TRUE;
AtspiRole
spi_accessible_role_from_atk_role (AtkRole role)
static gboolean is_initialized = FALSE;
static AtspiRole spi_role_table[ATK_ROLE_LAST_DEFINED];
AtspiRole spi_role;
if (!is_initialized)
is_initialized = init_role_lookup_table (spi_role_table);
if (role >= 0 && role < ATK_ROLE_LAST_DEFINED)
spi_role = spi_role_table[role];
else
spi_role = ATSPI_ROLE_EXTENDED;
return spi_role;
/*END------------------------------------------------------------------------*/