/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright (C) 2010 Igalia, S.L. * * Author: Alejandro PiƱeiro Iglesias * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include "shell-a11y.h" #define INIT_METHOD "gnome_accessibility_module_init" #define DESKTOP_SCHEMA "org.gnome.desktop.interface" #define ACCESSIBILITY_ENABLED_KEY "toolkit-accessibility" #define AT_SPI_SCHEMA "org.a11y.atspi" #define ATK_BRIDGE_LOCATION_KEY "atk-bridge-location" static gboolean should_enable_a11y (void) { GSettings *desktop_settings = NULL; gboolean value = FALSE; desktop_settings = g_settings_new (DESKTOP_SCHEMA); value = g_settings_get_boolean (desktop_settings, ACCESSIBILITY_ENABLED_KEY); g_object_unref (desktop_settings); return value; } static char* get_atk_bridge_path (void) { GSettings *atspi_settings = NULL; GVariant *variant = NULL; char *value = NULL; const char * const *schemas = NULL; gboolean found = FALSE; int i = 0; schemas = g_settings_list_schemas (); for (i = 0; schemas [i]; i++) { if (!strcmp (schemas[i], AT_SPI_SCHEMA)) { found = TRUE; break; } } if (!found) { g_warning ("Accessibility: %s schema not found. Are you sure that at-spi or" " at-spi2 is installed on your system?", AT_SPI_SCHEMA); return NULL; } atspi_settings = g_settings_new (AT_SPI_SCHEMA); variant = g_settings_get_value (atspi_settings, ATK_BRIDGE_LOCATION_KEY); value = g_variant_dup_bytestring (variant, NULL); g_variant_unref (variant); g_object_unref (atspi_settings); return value; } static gboolean a11y_invoke_module (const char *module_path) { GModule *handle; void (*invoke_fn) (void); if (!module_path) { g_warning ("Accessibility: invalid module path (NULL)"); return FALSE; } if (!(handle = g_module_open (module_path, 0))) { g_warning ("Accessibility: failed to load module '%s': '%s'", module_path, g_module_error ()); return FALSE; } if (!g_module_symbol (handle, INIT_METHOD, (gpointer *)&invoke_fn)) { g_warning ("Accessibility: error library '%s' does not include " "method '%s' required for accessibility support", module_path, INIT_METHOD); g_module_close (handle); return FALSE; } invoke_fn (); return TRUE; } /* * It loads the atk-bridge if required. It checks: * * If the proper gsetting key is set * * If clutter has already enabled the accessibility * * You need to ensure that the atk-bridge was not loaded before this * call, because in that case the application would be already * registered on at-spi using the AtkUtil implementation on that * moment (if any, although without anyone the application would * crash). Anyway this is the reason of NO_AT_BRIDGE. * */ void shell_a11y_init (void) { char *bridge_path = NULL; if (!should_enable_a11y ()) return; if (clutter_get_accessibility_enabled () == FALSE) { g_warning ("Accessibility: clutter has no accessibility enabled" " skipping the atk-bridge load"); return; } bridge_path = get_atk_bridge_path (); if (a11y_invoke_module (bridge_path) == FALSE) { g_warning ("Accessibility: error loading the atk-bridge. Although the" " accessibility on the system is enabled and clutter" " accessibility is also enabled, accessibility support on" " GNOME Shell will not work"); } /* NOTE: We avoid to load gail module, as gail-cally interaction is * not fully supported right now. */ g_free (bridge_path); }