summaryrefslogtreecommitdiff
path: root/a11y
diff options
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2015-12-17 16:35:11 +0100
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2015-12-17 16:35:11 +0100
commit9f5548b87d39d29908c16b03e14e5842e7c8b0a9 (patch)
tree46d617d2abca2140e325de22fab610f3b51983ed /a11y
parentc01a01cbeae97ccb1f0a77b6503af8208996e0e1 (diff)
a11y: move accessibility stuff to its own directory, adding a private lib for building
(bzr r4054.2.4)
Diffstat (limited to 'a11y')
-rw-r--r--a11y/CMakeLists.txt48
-rw-r--r--a11y/nux-area-accessible.cpp601
-rw-r--r--a11y/nux-area-accessible.h70
-rw-r--r--a11y/nux-base-window-accessible.cpp203
-rw-r--r--a11y/nux-base-window-accessible.h63
-rw-r--r--a11y/nux-layout-accessible.cpp226
-rw-r--r--a11y/nux-layout-accessible.h56
-rw-r--r--a11y/nux-object-accessible.cpp169
-rw-r--r--a11y/nux-object-accessible.h60
-rw-r--r--a11y/nux-text-entry-accessible.cpp113
-rw-r--r--a11y/nux-text-entry-accessible.h57
-rw-r--r--a11y/nux-view-accessible.cpp302
-rw-r--r--a11y/nux-view-accessible.h60
-rw-r--r--a11y/pch/a11y_pch.hh33
-rw-r--r--a11y/unity-dash-view-accessible.cpp114
-rw-r--r--a11y/unity-dash-view-accessible.h57
-rw-r--r--a11y/unity-expander-view-accessible.cpp205
-rw-r--r--a11y/unity-expander-view-accessible.h60
-rw-r--r--a11y/unity-filter-basic-button-accessible.cpp281
-rw-r--r--a11y/unity-filter-basic-button-accessible.h53
-rw-r--r--a11y/unity-launcher-accessible.cpp451
-rw-r--r--a11y/unity-launcher-accessible.h57
-rw-r--r--a11y/unity-launcher-icon-accessible.cpp554
-rw-r--r--a11y/unity-launcher-icon-accessible.h60
-rw-r--r--a11y/unity-panel-view-accessible.cpp118
-rw-r--r--a11y/unity-panel-view-accessible.h53
-rw-r--r--a11y/unity-places-group-accessible.cpp168
-rw-r--r--a11y/unity-places-group-accessible.h57
-rw-r--r--a11y/unity-quicklist-accessible.cpp180
-rw-r--r--a11y/unity-quicklist-accessible.h57
-rw-r--r--a11y/unity-quicklist-menu-accessible.cpp373
-rw-r--r--a11y/unity-quicklist-menu-accessible.h57
-rw-r--r--a11y/unity-quicklist-menu-item-accessible.cpp319
-rw-r--r--a11y/unity-quicklist-menu-item-accessible.h57
-rw-r--r--a11y/unity-result-accessible.cpp132
-rw-r--r--a11y/unity-result-accessible.h56
-rw-r--r--a11y/unity-root-accessible.cpp365
-rw-r--r--a11y/unity-root-accessible.h58
-rw-r--r--a11y/unity-rvgrid-accessible.cpp394
-rw-r--r--a11y/unity-rvgrid-accessible.h57
-rw-r--r--a11y/unity-scope-bar-icon-accessible.cpp191
-rw-r--r--a11y/unity-scope-bar-icon-accessible.h57
-rw-r--r--a11y/unity-sctext-accessible.cpp159
-rw-r--r--a11y/unity-sctext-accessible.h57
-rw-r--r--a11y/unity-search-bar-accessible.cpp151
-rw-r--r--a11y/unity-search-bar-accessible.h57
-rw-r--r--a11y/unity-session-button-accessible.cpp288
-rw-r--r--a11y/unity-session-button-accessible.h56
-rw-r--r--a11y/unity-switcher-accessible.cpp410
-rw-r--r--a11y/unity-switcher-accessible.h57
-rw-r--r--a11y/unity-text-input-accessible.cpp90
-rw-r--r--a11y/unity-text-input-accessible.h57
-rw-r--r--a11y/unity-util-accessible.cpp493
-rw-r--r--a11y/unity-util-accessible.h60
-rw-r--r--a11y/unitya11y.cpp318
-rw-r--r--a11y/unitya11y.h40
-rw-r--r--a11y/unitya11ytests.cpp333
-rw-r--r--a11y/unitya11ytests.h35
58 files changed, 9363 insertions, 0 deletions
diff --git a/a11y/CMakeLists.txt b/a11y/CMakeLists.txt
new file mode 100644
index 000000000..9a4714d67
--- /dev/null
+++ b/a11y/CMakeLists.txt
@@ -0,0 +1,48 @@
+pkg_check_modules(A11Y_DEPS REQUIRED atk atk-bridge-2.0)
+
+set(CFLAGS
+ ${CACHED_UNITY_DEPS_CFLAGS}
+ ${CACHED_UNITY_DEPS_CFLAGS_OTHER}
+ ${PIC_FLAGS}
+ ${A11Y_DEPS_CFLAGS})
+
+include_directories(.. ../unity-shared ../dash ../panel ../launcher ../shutdown ../plugins/unityshell/src ${CMAKE_BINARY_DIR})
+
+string(REPLACE ";" " " CFLAGS "${CFLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CFLAGS}")
+set(LIBS ${CACHED_UNITY_DEPS_LDFLAGS} ${A11Y_DEPS_LDFLAGS})
+
+set(A11Y_SOURCES
+ nux-area-accessible.cpp
+ nux-base-window-accessible.cpp
+ nux-layout-accessible.cpp
+ nux-object-accessible.cpp
+ nux-text-entry-accessible.cpp
+ nux-view-accessible.cpp
+ unity-dash-view-accessible.cpp
+ unity-expander-view-accessible.cpp
+ unity-filter-basic-button-accessible.cpp
+ unity-launcher-accessible.cpp
+ unity-launcher-icon-accessible.cpp
+ unity-panel-view-accessible.cpp
+ unity-places-group-accessible.cpp
+ unity-quicklist-accessible.cpp
+ unity-quicklist-menu-accessible.cpp
+ unity-quicklist-menu-item-accessible.cpp
+ unity-result-accessible.cpp
+ unity-root-accessible.cpp
+ unity-rvgrid-accessible.cpp
+ unity-scope-bar-icon-accessible.cpp
+ unity-sctext-accessible.cpp
+ unity-search-bar-accessible.cpp
+ unity-session-button-accessible.cpp
+ unity-switcher-accessible.cpp
+ unity-text-input-accessible.cpp
+ unity-util-accessible.cpp
+ unitya11y.cpp
+ unitya11ytests.cpp
+)
+
+add_library(a11y-lib STATIC ${A11Y_SOURCES})
+target_link_libraries(a11y-lib ${LIBS})
+add_pch(pch/a11y_pch.hh a11y-lib)
diff --git a/a11y/nux-area-accessible.cpp b/a11y/nux-area-accessible.cpp
new file mode 100644
index 000000000..bffad5ad3
--- /dev/null
+++ b/a11y/nux-area-accessible.cpp
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-area-accessible
+ * @Title: NuxAreaAccessible
+ * @short_description: Implementation of the ATK interfaces for #nux::Area
+ * @see_also: nux::Area
+ *
+ * #NuxAreaAccessible implements the required ATK interfaces of
+ * nux::Area, exposing the common elements on each basic individual
+ * element (position, extents, etc)
+ *
+ * In this object the main support for the focused object is also
+ * implemented. This is complex due to several reasons:
+ *
+ * * We need to ensure the proper order when the objects get the focus
+ *
+ * * It doesn't make sense to give the focus to an object that is
+ * inside an inactive window too, so it is also convenient to emit
+ * the window:active event before the focus change.
+ *
+ * => this is the reason why there is a system to delay the focus
+ * notification, until the top level window becomes active, implemented
+ *
+ * * But the main complexity comes from the fact that not all the
+ * objects of Unity are implementing key nav the same way.
+ *
+ * * The Launcher uses InputArea methods like
+ * SetKeyboardFocus, OnStartKeyboardReceiver, etc exclusively.
+ * This is the key focus at a low level abstraction
+ *
+ * * Dash objects use the events from Focusable. But in the same
+ * way, they require the low level key focus (OnStartFocus) and
+ * so on
+ *
+ *
+ */
+
+#include "nux-area-accessible.h"
+
+#include "unitya11y.h"
+
+/* GObject */
+static void nux_area_accessible_class_init(NuxAreaAccessibleClass* klass);
+static void nux_area_accessible_init(NuxAreaAccessible* area_accessible);
+
+/* AtkObject.h */
+static void nux_area_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkObject* nux_area_accessible_get_parent(AtkObject* obj);
+static AtkStateSet* nux_area_accessible_ref_state_set(AtkObject* obj);
+
+/* AtkComponent.h */
+static void atk_component_interface_init(AtkComponentIface* iface);
+static void nux_area_accessible_get_extents(AtkComponent* component,
+ gint* x,
+ gint* y,
+ gint* width,
+ gint* height,
+ AtkCoordType coord_type);
+static gboolean nux_area_accessible_grab_focus(AtkComponent* component);
+static guint nux_area_accessible_add_focus_handler(AtkComponent* component,
+ AtkFocusHandler handler);
+static void nux_area_accessible_remove_focus_handler(AtkComponent* component,
+ guint handler_id);
+static void nux_area_accessible_focus_handler(AtkObject* accessible,
+ gboolean focus_in);
+/* private */
+static void on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible);
+static void on_parent_window_activate_cb(AtkObject* parent_window,
+ NuxAreaAccessible* self);
+static void on_parent_window_deactivate_cb(AtkObject* parent_window,
+ NuxAreaAccessible* self);
+static AtkObject* search_for_parent_window(AtkObject* object);
+static gboolean nux_area_accessible_real_check_pending_notification(NuxAreaAccessible* self);
+static void check_parent_window_connected(NuxAreaAccessible* self);
+static void check_focus(NuxAreaAccessible* self);
+
+G_DEFINE_TYPE_WITH_CODE(NuxAreaAccessible,
+ nux_area_accessible,
+ NUX_TYPE_OBJECT_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT,
+ atk_component_interface_init))
+
+#define NUX_AREA_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NUX_TYPE_AREA_ACCESSIBLE, \
+ NuxAreaAccessiblePrivate))
+
+struct _NuxAreaAccessiblePrivate
+{
+ /* focused as Focusable events */
+ gboolean focused;
+
+ /* if there is any pending notification */
+ gboolean pending_notification;
+
+ /* Top level parent window, it is not required to be the direct
+ parent */
+ AtkObject* parent_window;
+};
+
+
+static void
+nux_area_accessible_class_init(NuxAreaAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+ NuxAreaAccessibleClass* area_class = NUX_AREA_ACCESSIBLE_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = nux_area_accessible_initialize;
+ atk_class->get_parent = nux_area_accessible_get_parent;
+ atk_class->ref_state_set = nux_area_accessible_ref_state_set;
+
+ /* NuxAreaAccessible */
+ area_class->check_pending_notification = nux_area_accessible_real_check_pending_notification;
+
+ g_type_class_add_private(gobject_class, sizeof(NuxAreaAccessiblePrivate));
+}
+
+static void
+nux_area_accessible_init(NuxAreaAccessible* area_accessible)
+{
+ NuxAreaAccessiblePrivate* priv =
+ NUX_AREA_ACCESSIBLE_GET_PRIVATE(area_accessible);
+
+ area_accessible->priv = priv;
+}
+
+AtkObject*
+nux_area_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<nux::Area*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(NUX_TYPE_AREA_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+nux_area_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ nux::Area* area = NULL;
+
+ ATK_OBJECT_CLASS(nux_area_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_UNKNOWN;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ area = static_cast<nux::Area*>(nux_object);
+
+ /* focus support based on Focusable, used on the Dash */
+ area->key_nav_focus_change.connect(sigc::bind(sigc::ptr_fun(on_focus_changed_cb), accessible));
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ atk_component_add_focus_handler(ATK_COMPONENT(accessible),
+ nux_area_accessible_focus_handler);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ /* NOTE: we can't search for the parent window on initialization as a
+ general rule, or we could enter an infinite loop. At area this
+ is done on the focus event. On the Switcher this is done on their
+ initialization itself */
+}
+
+static AtkObject*
+nux_area_accessible_get_parent(AtkObject* obj)
+{
+ nux::Object* nux_object = NULL;
+ nux::Area* area = NULL;
+ nux::Area* parent = NULL;
+
+ g_return_val_if_fail(NUX_IS_AREA_ACCESSIBLE(obj), NULL);
+
+ if (obj->accessible_parent)
+ return obj->accessible_parent;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return NULL;
+
+ area = static_cast<nux::Area*>(nux_object);
+ parent = area->GetParentObject();
+
+ return parent ? unity_a11y_get_accessible(parent) : NULL;
+}
+
+/*
+ * Checks if the parent actor, and his parent, etc are all visible
+ * Used to check the showing state
+ */
+static gboolean
+_check_all_parents_visible(nux::Area* area)
+{
+ nux::Area* iter_parent = NULL;
+ gboolean result = TRUE;
+
+ for (iter_parent = area; iter_parent;
+ iter_parent = iter_parent->GetParentObject())
+ {
+ if (!iter_parent->IsVisible())
+ {
+ result = FALSE;
+ break;
+ }
+ }
+
+ return result;
+}
+
+static AtkStateSet*
+nux_area_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+ nux::Area* area = NULL;
+
+ g_return_val_if_fail(NUX_IS_AREA_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(nux_area_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ area = static_cast<nux::Area*>(nux_object);
+
+ if (area->IsSensitive())
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
+ }
+
+ if (area->IsVisible())
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
+
+ if (_check_all_parents_visible(area))
+ atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
+ }
+
+ // FIXME CanFocus is no longer part of Nux API
+// if (area->CanFocus())
+// atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+
+ if (area->HasKeyFocus())
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+
+ return state_set;
+}
+
+/* AtkComponent implementation */
+static void
+atk_component_interface_init(AtkComponentIface* iface)
+{
+ g_return_if_fail(iface != NULL);
+
+ /* placement */
+ iface->get_extents = nux_area_accessible_get_extents;
+
+ /* focus management based on Focusable */
+ iface->grab_focus = nux_area_accessible_grab_focus;
+ iface->add_focus_handler = nux_area_accessible_add_focus_handler;
+ iface->remove_focus_handler = nux_area_accessible_remove_focus_handler;
+}
+
+static void
+nux_area_accessible_get_extents(AtkComponent* component,
+ gint* x,
+ gint* y,
+ gint* width,
+ gint* height,
+ AtkCoordType coord_type)
+{
+ gint top_level_x = 0;
+ gint top_level_y = 0;
+ nux::Object* nux_object = NULL;
+ nux::Area* area = NULL;
+ nux::Geometry geometry;
+
+ g_return_if_fail(NUX_IS_AREA_ACCESSIBLE(component));
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(component));
+
+ if (nux_object == NULL) /* defunct */
+ return;
+
+ area = static_cast<nux::Area*>(nux_object);
+ geometry = area->GetGeometry();
+
+ *width = geometry.GetWidth();
+ *height = geometry.GetWidth();
+ *x = geometry.x;
+ *y = geometry.y;
+
+ /* In the ATK_XY_WINDOW case
+ *
+ * http://library.gnome.org/devel/atk/stable/AtkUtil.html#AtkCoordType
+ */
+
+ if (coord_type == ATK_XY_SCREEN)
+ {
+ /* For the moment Unity is a full-screen app, so ATK_XY_SCREEN
+ and ATK_XY_WINDOW are the same */
+ *x += top_level_x;
+ *y += top_level_y;
+ }
+
+ return;
+}
+
+static gboolean
+nux_area_accessible_grab_focus(AtkComponent* component)
+{
+ nux::Object* nux_object = NULL;
+ //nux::Area* area = NULL;
+
+ g_return_val_if_fail(NUX_IS_AREA_ACCESSIBLE(component), FALSE);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(component));
+ if (nux_object == NULL) /* defunct */
+ return FALSE;
+
+ /* FIXME: SetFocused doesn't return if the force was successful or
+ not, we suppose that this is the case like in cally and gail */
+
+ return TRUE;
+}
+
+/*
+ * comment C&P from cally-actor:
+ *
+ * "These methods are basically taken from gail, as I don't see any
+ * reason to modify it. It makes me wonder why it is really required
+ * to be implemented in the toolkit"
+ */
+
+static guint
+nux_area_accessible_add_focus_handler(AtkComponent* component,
+ AtkFocusHandler handler)
+{
+ GSignalMatchType match_type;
+ gulong ret;
+ guint signal_id;
+
+ g_return_val_if_fail(NUX_IS_AREA_ACCESSIBLE(component), 0);
+
+ match_type = (GSignalMatchType)(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC);
+ signal_id = g_signal_lookup("focus-event", ATK_TYPE_OBJECT);
+
+ ret = g_signal_handler_find(component, match_type, signal_id, 0, NULL,
+ (gpointer) handler, NULL);
+ if (!ret)
+ {
+ return g_signal_connect_closure_by_id(component,
+ signal_id, 0,
+ g_cclosure_new(G_CALLBACK(handler), NULL,
+ (GClosureNotify) NULL),
+ FALSE);
+ }
+ else
+ return 0;
+}
+
+static void
+nux_area_accessible_remove_focus_handler(AtkComponent* component,
+ guint handler_id)
+{
+ g_return_if_fail(NUX_IS_AREA_ACCESSIBLE(component));
+
+ g_signal_handler_disconnect(component, handler_id);
+}
+
+static void
+nux_area_accessible_focus_handler(AtkObject* accessible,
+ gboolean focus_in)
+{
+ g_return_if_fail(NUX_IS_AREA_ACCESSIBLE(accessible));
+
+ atk_object_notify_state_change(accessible, ATK_STATE_FOCUSED, focus_in);
+}
+
+/* private */
+static void
+check_parent_window_connected(NuxAreaAccessible* self)
+{
+ AtkObject* window = NULL;
+
+ if (self->priv->parent_window != NULL)
+ return;
+
+ window = search_for_parent_window(ATK_OBJECT(self));
+
+ if (window != NULL)
+ {
+ self->priv->parent_window = window;
+
+ g_signal_connect(self->priv->parent_window,
+ "activate",
+ G_CALLBACK(on_parent_window_activate_cb),
+ self);
+ g_signal_connect(self->priv->parent_window,
+ "deactivate",
+ G_CALLBACK(on_parent_window_deactivate_cb),
+ self);
+ }
+}
+
+/*
+ * nux_area_accessible_parent_window_active
+ * @self: The accessible to check the focus change
+ *
+ * Returns if the top level parent window contains
+ * the state ATK_STATE_ACTIVE
+ *
+ * Returns: TRUE if the parent top level window contains
+ * ATK_STATE_ACTIVE, FALSE otherwise
+ */
+gboolean
+nux_area_accessible_parent_window_active(NuxAreaAccessible* self)
+{
+ AtkStateSet* state_set = NULL;
+ gboolean active = FALSE;
+
+ check_parent_window_connected(self);
+
+ if (ATK_IS_OBJECT(self->priv->parent_window))
+ {
+ state_set = atk_object_ref_state_set(ATK_OBJECT(self->priv->parent_window));
+ active = atk_state_set_contains_state(state_set, ATK_STATE_ACTIVE);
+ g_object_unref(state_set);
+ }
+
+ return active;
+}
+
+static void
+on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible)
+{
+ check_focus(NUX_AREA_ACCESSIBLE(accessible));
+}
+
+/* Check to use GetTopLevelViewWindow */
+static AtkObject*
+search_for_parent_window(AtkObject* object)
+{
+ AtkObject* parent = NULL;
+
+ for (parent = atk_object_get_parent(object);
+ (parent != NULL) && (atk_object_get_role(parent) != ATK_ROLE_WINDOW);
+ parent = atk_object_get_parent(parent));
+
+ return parent;
+}
+
+static void
+on_parent_window_activate_cb(AtkObject* parent_window,
+ NuxAreaAccessible* self)
+{
+ nux_area_accessible_check_pending_notification(self);
+}
+
+static void
+on_parent_window_deactivate_cb(AtkObject* parent_window,
+ NuxAreaAccessible* self)
+{
+ g_return_if_fail(NUX_IS_AREA_ACCESSIBLE(self));
+
+ self->priv->focused = FALSE;
+}
+
+
+/*
+ * nux_area_check_pending_notification:
+ * @self: The accessible
+ *
+ * This method checks if there is any pending notification, and emits
+ * it if it is possible
+ *
+ * Returns: TRUE if an atk notification was emitted, FALSE otherwise
+ */
+gboolean
+nux_area_accessible_check_pending_notification(NuxAreaAccessible* self)
+{
+ NuxAreaAccessibleClass* klass = NULL;
+
+ klass = NUX_AREA_ACCESSIBLE_GET_CLASS(self);
+ if (klass->check_pending_notification)
+ return klass->check_pending_notification(self);
+ else
+ return FALSE;
+}
+
+static gboolean
+nux_area_accessible_real_check_pending_notification(NuxAreaAccessible* self)
+{
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(NUX_IS_AREA_ACCESSIBLE(self), FALSE);
+
+ if (self->priv->pending_notification == FALSE)
+ return FALSE;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (nux_object == NULL) /* defunct */
+ return FALSE;
+
+ g_signal_emit_by_name(self, "focus-event", self->priv->focused);
+ atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, self->priv->focused);
+ self->priv->pending_notification = FALSE;
+
+ return TRUE;
+}
+
+static void
+check_focus(NuxAreaAccessible* self)
+{
+ gboolean focus_in = FALSE;
+ nux::Area* area = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_if_fail(NUX_IS_AREA_ACCESSIBLE(self));
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (nux_object == NULL) /* defunct */
+ return;
+
+ area = static_cast<nux::Area*>(nux_object);
+
+ if (nux::GetWindowCompositor().GetKeyFocusArea() == area)
+ focus_in = TRUE;
+
+ if (self->priv->focused != focus_in)
+ {
+ self->priv->focused = focus_in;
+ gboolean is_parent_window_active = nux_area_accessible_parent_window_active(self);
+
+ /* we don't emit focus_in=TRUE events until the top level window
+ is active */
+ if ((focus_in) && (!is_parent_window_active))
+ {
+ self->priv->pending_notification = TRUE;
+ }
+ else
+ {
+ g_signal_emit_by_name(self, "focus_event", focus_in);
+ atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, focus_in);
+ self->priv->pending_notification = FALSE;
+ }
+ }
+}
+
+
+/* public */
+/*
+ * nux_area_get_parent_window:
+ * @self: The accessible
+ *
+ * Returns: the top level window that contains this object
+ */
+AtkObject*
+nux_area_accessible_get_parent_window(NuxAreaAccessible* self)
+{
+ g_return_val_if_fail(NUX_IS_AREA_ACCESSIBLE(self), NULL);
+
+ /* At least ensure that we made a search for it */
+ check_parent_window_connected(self);
+
+ return self->priv->parent_window;
+}
diff --git a/a11y/nux-area-accessible.h b/a11y/nux-area-accessible.h
new file mode 100644
index 000000000..a5326c63f
--- /dev/null
+++ b/a11y/nux-area-accessible.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef NUX_AREA_ACCESSIBLE_H
+#define NUX_AREA_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-object-accessible.h"
+
+G_BEGIN_DECLS
+
+#define NUX_TYPE_AREA_ACCESSIBLE (nux_area_accessible_get_type ())
+#define NUX_AREA_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NUX_TYPE_AREA_ACCESSIBLE, NuxAreaAccessible))
+#define NUX_AREA_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NUX_TYPE_AREA_ACCESSIBLE, NuxAreaAccessibleClass))
+#define NUX_IS_AREA_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NUX_TYPE_AREA_ACCESSIBLE))
+#define NUX_IS_AREA_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NUX_TYPE_AREA_ACCESSIBLE))
+#define NUX_AREA_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NUX_TYPE_AREA_ACCESSIBLE, NuxAreaAccessibleClass))
+
+typedef struct _NuxAreaAccessible NuxAreaAccessible;
+typedef struct _NuxAreaAccessibleClass NuxAreaAccessibleClass;
+typedef struct _NuxAreaAccessiblePrivate NuxAreaAccessiblePrivate;
+
+struct _NuxAreaAccessible
+{
+ NuxObjectAccessible parent;
+
+ /*< private >*/
+ NuxAreaAccessiblePrivate* priv;
+};
+
+struct _NuxAreaAccessibleClass
+{
+ NuxObjectAccessibleClass parent_class;
+
+ /*
+ * Usually objects shouldn't emit events like focus or selection
+ * changes until the toplevel window is active. This method is
+ * called when the toplevel window becomes active. Redefine it if you
+ * need to check any pending state change notification.
+ */
+ gboolean(*check_pending_notification)(NuxAreaAccessible* self);
+
+};
+
+GType nux_area_accessible_get_type(void);
+AtkObject* nux_area_accessible_new(nux::Object* object);
+
+gboolean nux_area_accessible_check_pending_notification(NuxAreaAccessible* self);
+gboolean nux_area_accessible_parent_window_active(NuxAreaAccessible* self);
+AtkObject* nux_area_accessible_get_parent_window(NuxAreaAccessible* self);
+
+G_END_DECLS
+
+#endif /* __NUX_AREA_ACCESSIBLE_H__ */
diff --git a/a11y/nux-base-window-accessible.cpp b/a11y/nux-base-window-accessible.cpp
new file mode 100644
index 000000000..e82b536d7
--- /dev/null
+++ b/a11y/nux-base-window-accessible.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-base_window-accessible
+ * @Title: NuxBaseWindowAccessible
+ * @short_description: Implementation of the ATK interfaces for #nux::BaseWindow
+ * @see_also: nux::BaseWindow
+ *
+ * Right now it is used to:
+ * * Expose the child of BaseWindow (the layout)
+ * * Window event notification (activate, deactivate, and so on)
+ *
+ * BTW: we consider that one window is active, if it directly has
+ * keyboard focus, or if one of its children has keyboard focus (ie:
+ * the Launcher via GrabKeyboardFocus)
+ *
+ * HasKeyboardFocus is not reliable to check that:
+ * see bug https://bugs.launchpad.net/nux/+bug/745049
+ *
+ * So we need to update the state of the objects using the information
+ * from the signals OnStartKeyboardReceiver and OnStopKeyboardReceiver
+ *
+ * #NuxBaseWindowAccessible implements the required ATK interfaces of
+ * nux::BaseWindow, exposing as a child the BaseWindow layout
+ *
+ */
+
+#include "nux-base-window-accessible.h"
+
+#include <Nux/Area.h>
+#include <Nux/Layout.h>
+
+/* GObject */
+static void nux_base_window_accessible_class_init(NuxBaseWindowAccessibleClass* klass);
+static void nux_base_window_accessible_init(NuxBaseWindowAccessible* base_window_accessible);
+
+/* AtkObject.h */
+static void nux_base_window_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkObject* nux_base_window_accessible_get_parent(AtkObject* obj);
+static AtkStateSet* nux_base_window_accessible_ref_state_set(AtkObject* obj);
+
+/* AtkWindow.h */
+static void atk_window_interface_init(AtkWindowIface* iface);
+
+
+G_DEFINE_TYPE_WITH_CODE(NuxBaseWindowAccessible, nux_base_window_accessible,
+ NUX_TYPE_VIEW_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_WINDOW,
+ atk_window_interface_init))
+
+struct _NuxBaseWindowAccessiblePrivate
+{
+ /* Cached values (used to avoid extra notifications) */
+ gboolean active;
+};
+
+#define NUX_BASE_WINDOW_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NUX_TYPE_BASE_WINDOW_ACCESSIBLE, \
+ NuxBaseWindowAccessiblePrivate))
+
+static void
+nux_base_window_accessible_class_init(NuxBaseWindowAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = nux_base_window_accessible_initialize;
+ atk_class->get_parent = nux_base_window_accessible_get_parent;
+ atk_class->ref_state_set = nux_base_window_accessible_ref_state_set;
+
+ g_type_class_add_private(gobject_class, sizeof(NuxBaseWindowAccessiblePrivate));
+}
+
+static void
+nux_base_window_accessible_init(NuxBaseWindowAccessible* base_window_accessible)
+{
+ NuxBaseWindowAccessiblePrivate* priv =
+ NUX_BASE_WINDOW_ACCESSIBLE_GET_PRIVATE(base_window_accessible);
+
+ base_window_accessible->priv = priv;
+}
+
+AtkObject*
+nux_base_window_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<nux::BaseWindow*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(NUX_TYPE_BASE_WINDOW_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+nux_base_window_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ ATK_OBJECT_CLASS(nux_base_window_accessible_parent_class)->initialize(accessible, data);
+
+ atk_object_set_role(accessible, ATK_ROLE_WINDOW);
+}
+
+static AtkObject*
+nux_base_window_accessible_get_parent(AtkObject* obj)
+{
+ return atk_get_root();
+}
+
+static AtkStateSet*
+nux_base_window_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ NuxBaseWindowAccessible* self = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(NUX_IS_BASE_WINDOW_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(nux_base_window_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ self = NUX_BASE_WINDOW_ACCESSIBLE(obj);
+
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+
+ /* HasKeyboardFocus is not reliable here:
+ see bug https://bugs.launchpad.net/nux/+bug/745049 */
+ if (self->priv->active)
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_ACTIVE);
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+ }
+
+ return state_set;
+}
+
+/* AtkWindow */
+static void
+atk_window_interface_init(AtkWindowIface* iface)
+{
+ /* AtkWindow just defines signals at this moment */
+}
+
+/* public */
+/*
+ * Checks if we are the active window.
+ */
+void
+nux_base_window_accessible_check_active(NuxBaseWindowAccessible* self,
+ nux::BaseWindow* active_window)
+{
+ gboolean is_active;
+ nux::Object* nux_object = NULL;
+ nux::BaseWindow* bwindow = NULL;
+
+ g_return_if_fail(NUX_IS_BASE_WINDOW_ACCESSIBLE(self));
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ bwindow = dynamic_cast<nux::BaseWindow*>(nux_object);
+ if (bwindow == NULL) /* defunct */
+ return;
+
+ is_active = (bwindow == active_window);
+
+ if (self->priv->active != is_active)
+ {
+ const gchar* signal_name;
+ self->priv->active = is_active;
+
+ if (is_active)
+ signal_name = "activate";
+ else
+ signal_name = "deactivate";
+
+ atk_object_notify_state_change(ATK_OBJECT(self),
+ ATK_STATE_ACTIVE, is_active);
+ g_signal_emit_by_name(self, signal_name, 0);
+ }
+}
diff --git a/a11y/nux-base-window-accessible.h b/a11y/nux-base-window-accessible.h
new file mode 100644
index 000000000..0fa6382d4
--- /dev/null
+++ b/a11y/nux-base-window-accessible.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef NUX_BASE_WINDOW_ACCESSIBLE_H
+#define NUX_BASE_WINDOW_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include <Nux/Nux.h>
+#include <Nux/BaseWindow.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define NUX_TYPE_BASE_WINDOW_ACCESSIBLE (nux_base_window_accessible_get_type ())
+#define NUX_BASE_WINDOW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NUX_TYPE_BASE_WINDOW_ACCESSIBLE, NuxBaseWindowAccessible))
+#define NUX_BASE_WINDOW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NUX_TYPE_BASE_WINDOW_ACCESSIBLE, NuxBaseWindowAccessibleClass))
+#define NUX_IS_BASE_WINDOW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NUX_TYPE_BASE_WINDOW_ACCESSIBLE))
+#define NUX_IS_BASE_WINDOW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NUX_TYPE_BASE_WINDOW_ACCESSIBLE))
+#define NUX_BASE_WINDOW_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NUX_TYPE_BASE_WINDOW_ACCESSIBLE, NuxBaseWindowAccessibleClass))
+
+typedef struct _NuxBaseWindowAccessible NuxBaseWindowAccessible;
+typedef struct _NuxBaseWindowAccessibleClass NuxBaseWindowAccessibleClass;
+typedef struct _NuxBaseWindowAccessiblePrivate NuxBaseWindowAccessiblePrivate;
+
+struct _NuxBaseWindowAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ NuxBaseWindowAccessiblePrivate* priv;
+};
+
+struct _NuxBaseWindowAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType nux_base_window_accessible_get_type(void);
+AtkObject* nux_base_window_accessible_new(nux::Object* object);
+void nux_base_window_accessible_check_active(NuxBaseWindowAccessible* self,
+ nux::BaseWindow* active_window);
+
+
+G_END_DECLS
+
+#endif /* __NUX_BASE_WINDOW_ACCESSIBLE_H__ */
diff --git a/a11y/nux-layout-accessible.cpp b/a11y/nux-layout-accessible.cpp
new file mode 100644
index 000000000..d4a3e3b4a
--- /dev/null
+++ b/a11y/nux-layout-accessible.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-layout-accessible
+ * @Title: NuxLayoutAccessible
+ * @short_description: Implementation of the ATK interfaces for #nux::Layout
+ * @see_also: nux::Layout
+ *
+ * #NuxLayoutAccessible implements the required ATK interfaces of
+ * nux::Layout, implementing the container related methods on
+ * AtkObject, in order to expose its objects
+ *
+ */
+
+#include "nux-layout-accessible.h"
+#include "unity-util-accessible.h"
+
+#include "unitya11y.h"
+
+/* GObject */
+static void nux_layout_accessible_class_init(NuxLayoutAccessibleClass* klass);
+static void nux_layout_accessible_init(NuxLayoutAccessible* layout_accessible);
+
+/* AtkObject.h */
+static void nux_layout_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static gint nux_layout_accessible_get_n_children(AtkObject* obj);
+static AtkObject* nux_layout_accessible_ref_child(AtkObject* obj,
+ gint i);
+
+/* private */
+static void on_view_changed_cb(nux::Layout* layout,
+ nux::Area* area,
+ AtkObject* acccessible,
+ gboolean is_add);
+static int search_for_child(AtkObject* accessible,
+ nux::Layout* layout,
+ nux::Area* area);
+
+G_DEFINE_TYPE(NuxLayoutAccessible, nux_layout_accessible, NUX_TYPE_AREA_ACCESSIBLE)
+
+static void
+nux_layout_accessible_class_init(NuxLayoutAccessibleClass* klass)
+{
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = nux_layout_accessible_initialize;
+ atk_class->ref_child = nux_layout_accessible_ref_child;
+ atk_class->get_n_children = nux_layout_accessible_get_n_children;
+}
+
+static void
+nux_layout_accessible_init(NuxLayoutAccessible* layout_accessible)
+{
+}
+
+AtkObject*
+nux_layout_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(static_cast<nux::Layout*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(NUX_TYPE_LAYOUT_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+nux_layout_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ nux::Layout* layout = NULL;
+
+ ATK_OBJECT_CLASS(nux_layout_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_PANEL;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ layout = static_cast<nux::Layout*>(nux_object);
+
+ layout->ViewAdded.connect(sigc::bind(sigc::ptr_fun(on_view_changed_cb),
+ accessible, TRUE));
+
+ layout->ViewRemoved.connect(sigc::bind(sigc::ptr_fun(on_view_changed_cb),
+ accessible, FALSE));
+}
+
+static gint
+nux_layout_accessible_get_n_children(AtkObject* obj)
+{
+ nux::Object* nux_object = NULL;
+ nux::Layout* layout = NULL;
+ std::list<nux::Area*> element_list;
+
+ g_return_val_if_fail(NUX_IS_LAYOUT_ACCESSIBLE(obj), 0);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ layout = static_cast<nux::Layout*>(nux_object);
+
+ element_list = layout->GetChildren();
+
+ return element_list.size();
+}
+
+static AtkObject*
+nux_layout_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ nux::Object* nux_object = NULL;
+ nux::Object* child = NULL;
+ AtkObject* child_accessible = NULL;
+ nux::Layout* layout = NULL;
+ std::list<nux::Area*> element_list;
+ gint num = 0;
+ std::list<nux::Area*>::iterator it;
+ AtkObject* parent = NULL;
+
+ g_return_val_if_fail(NUX_IS_LAYOUT_ACCESSIBLE(obj), 0);
+ num = atk_object_get_n_accessible_children(obj);
+ g_return_val_if_fail((i < num) && (i >= 0), NULL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ layout = static_cast<nux::Layout*>(nux_object);
+
+ element_list = layout->GetChildren();
+
+ it = element_list.begin();
+ std::advance(it, i);
+
+ child = static_cast<nux::Object*>(*it);
+ child_accessible = unity_a11y_get_accessible(child);
+
+ parent = atk_object_get_parent(child_accessible);
+ if (parent != obj)
+ atk_object_set_parent(child_accessible, obj);
+
+ g_object_ref(child_accessible);
+
+ return child_accessible;
+}
+
+/* private */
+static void
+on_view_changed_cb(nux::Layout* layout,
+ nux::Area* area,
+ AtkObject* accessible,
+ gboolean is_add)
+{
+ const gchar* signal_name = NULL;
+ AtkObject* atk_child = NULL;
+ gint index;
+
+ g_return_if_fail(NUX_IS_LAYOUT_ACCESSIBLE(accessible));
+
+ atk_child = unity_a11y_get_accessible(area);
+
+ if (is_add)
+ {
+ signal_name = "children-changed::add";
+ index = nux_layout_accessible_get_n_children(accessible) - 1;
+ explore_children(accessible);
+ }
+ else
+ {
+ signal_name = "children-changed::remove";
+ index = search_for_child(accessible, layout, area);
+ }
+
+ g_signal_emit_by_name(accessible, signal_name, index, atk_child, NULL);
+}
+
+static int
+search_for_child(AtkObject* accessible,
+ nux::Layout* layout,
+ nux::Area* area)
+{
+ std::list<nux::Area*> element_list;
+ std::list<nux::Area*>::iterator it;
+ nux::Area* current_area = NULL;
+ gint result = 0;
+ gboolean found = FALSE;
+
+ element_list = layout->GetChildren();
+
+ for (it = element_list.begin(); it != element_list.end(); ++it, result++)
+ {
+ current_area = *it;
+ if (current_area == area)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) result = -1;
+
+ return result;
+}
diff --git a/a11y/nux-layout-accessible.h b/a11y/nux-layout-accessible.h
new file mode 100644
index 000000000..cc9a50cd3
--- /dev/null
+++ b/a11y/nux-layout-accessible.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef NUX_LAYOUT_ACCESSIBLE_H
+#define NUX_LAYOUT_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-area-accessible.h"
+
+#include <Nux/Nux.h>
+#include <Nux/Layout.h>
+
+G_BEGIN_DECLS
+
+#define NUX_TYPE_LAYOUT_ACCESSIBLE (nux_layout_accessible_get_type ())
+#define NUX_LAYOUT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NUX_TYPE_LAYOUT_ACCESSIBLE, NuxLayoutAccessible))
+#define NUX_LAYOUT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NUX_TYPE_LAYOUT_ACCESSIBLE, NuxLayoutAccessibleClass))
+#define NUX_IS_LAYOUT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NUX_TYPE_LAYOUT_ACCESSIBLE))
+#define NUX_IS_LAYOUT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NUX_TYPE_LAYOUT_ACCESSIBLE))
+#define NUX_LAYOUT_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NUX_TYPE_LAYOUT_ACCESSIBLE, NuxLayoutAccessibleClass))
+
+typedef struct _NuxLayoutAccessible NuxLayoutAccessible;
+typedef struct _NuxLayoutAccessibleClass NuxLayoutAccessibleClass;
+
+struct _NuxLayoutAccessible
+{
+ NuxAreaAccessible parent;
+};
+
+struct _NuxLayoutAccessibleClass
+{
+ NuxAreaAccessibleClass parent_class;
+};
+
+GType nux_layout_accessible_get_type(void);
+AtkObject* nux_layout_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __NUX_LAYOUT_ACCESSIBLE_H__ */
diff --git a/a11y/nux-object-accessible.cpp b/a11y/nux-object-accessible.cpp
new file mode 100644
index 000000000..4e25c2963
--- /dev/null
+++ b/a11y/nux-object-accessible.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-object-accessible
+ * @Title: NuxObjectAccessible
+ * @short_description: Implementation of the ATK interfaces for #nux::Object
+ * @see_also: nux::Object
+ *
+ * #NuxObjectAccessible implements the required ATK interfaces of
+ * nux::Object, exposing the common elements of each basic individual
+ * element (position, extents, etc)
+ *
+ */
+
+#include "nux-object-accessible.h"
+
+#include <sigc++/connection.h>
+
+/* GObject */
+static void nux_object_accessible_class_init(NuxObjectAccessibleClass* klass);
+static void nux_object_accessible_init(NuxObjectAccessible* object_accessible);
+static void nux_object_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void nux_object_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* nux_object_accessible_ref_state_set(AtkObject* accessible);
+
+/* Private methods */
+static void on_object_destroy_cb(nux::Object* base_object,
+ NuxObjectAccessible* object_accessible);
+
+
+#define NUX_OBJECT_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NUX_TYPE_OBJECT_ACCESSIBLE, NuxObjectAccessiblePrivate))
+
+G_DEFINE_TYPE(NuxObjectAccessible, nux_object_accessible, ATK_TYPE_OBJECT)
+
+struct _NuxObjectAccessiblePrivate
+{
+ nux::Object* object;
+ sigc::connection on_destroyed_connection;
+};
+
+static void
+nux_object_accessible_class_init(NuxObjectAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = nux_object_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->initialize = nux_object_accessible_initialize;
+ atk_class->ref_state_set = nux_object_accessible_ref_state_set;
+
+ g_type_class_add_private(gobject_class, sizeof(NuxObjectAccessiblePrivate));
+}
+
+static void
+nux_object_accessible_init(NuxObjectAccessible* object_accessible)
+{
+ object_accessible->priv = NUX_OBJECT_ACCESSIBLE_GET_PRIVATE(object_accessible);
+
+ object_accessible->priv->object = NULL;
+}
+
+AtkObject*
+nux_object_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<nux::Object*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(NUX_TYPE_OBJECT_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+static void
+nux_object_accessible_finalize(GObject* object)
+{
+ NuxObjectAccessible* self = NUX_OBJECT_ACCESSIBLE(object);
+
+ self->priv->on_destroyed_connection.disconnect();
+
+ G_OBJECT_CLASS(nux_object_accessible_parent_class)->finalize(object);
+}
+
+/* AtkObject.h */
+static void
+nux_object_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ NuxObjectAccessible* self = NULL;
+ nux::Object* object = NULL;
+
+ ATK_OBJECT_CLASS(nux_object_accessible_parent_class)->initialize(accessible, data);
+
+ self = NUX_OBJECT_ACCESSIBLE(accessible);
+ object = (nux::Object*) data;
+
+ self->priv->object = object;
+
+ self->priv->on_destroyed_connection =
+ object->OnDestroyed.connect(sigc::bind(sigc::ptr_fun(on_object_destroy_cb), self));
+
+ accessible->role = ATK_ROLE_UNKNOWN;
+}
+
+/**
+ * nux_object_accessible_get_object:
+ *
+ * Returns the nux::Object this object is providing accessibility support for.
+ *
+ * Note that there isn't a _set method. This is because setting that
+ * should only be done during initialization, and it doesn't make sense
+ * to change that during the lifetime of the object.
+ *
+ */
+nux::Object*
+nux_object_accessible_get_object(NuxObjectAccessible* self)
+{
+ return self->priv->object;
+}
+
+static AtkStateSet*
+nux_object_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+
+ g_return_val_if_fail(NUX_IS_OBJECT_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(nux_object_accessible_parent_class)->ref_state_set(obj);
+
+ if (NUX_OBJECT_ACCESSIBLE(obj)->priv->object == NULL)
+ atk_state_set_add_state(state_set, ATK_STATE_DEFUNCT);
+
+ return state_set;
+}
+
+/* Private methods */
+static void
+on_object_destroy_cb(nux::Object* base_object,
+ NuxObjectAccessible* object_accessible)
+{
+ object_accessible->priv->object = NULL;
+ object_accessible->priv->on_destroyed_connection.disconnect();
+ atk_object_notify_state_change(ATK_OBJECT(object_accessible), ATK_STATE_DEFUNCT,
+ TRUE);
+}
diff --git a/a11y/nux-object-accessible.h b/a11y/nux-object-accessible.h
new file mode 100644
index 000000000..decf9b358
--- /dev/null
+++ b/a11y/nux-object-accessible.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef NUX_OBJECT_ACCESSIBLE_H
+#define NUX_OBJECT_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include <Nux/Nux.h>
+#include <NuxCore/Object.h>
+
+G_BEGIN_DECLS
+
+#define NUX_TYPE_OBJECT_ACCESSIBLE (nux_object_accessible_get_type ())
+#define NUX_OBJECT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NUX_TYPE_OBJECT_ACCESSIBLE, NuxObjectAccessible))
+#define NUX_OBJECT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NUX_TYPE_OBJECT_ACCESSIBLE, NuxObjectAccessibleClass))
+#define NUX_IS_OBJECT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NUX_TYPE_OBJECT_ACCESSIBLE))
+#define NUX_IS_OBJECT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NUX_TYPE_OBJECT_ACCESSIBLE))
+#define NUX_OBJECT_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NUX_TYPE_OBJECT_ACCESSIBLE, NuxObjectAccessibleClass))
+
+typedef struct _NuxObjectAccessible NuxObjectAccessible;
+typedef struct _NuxObjectAccessibleClass NuxObjectAccessibleClass;
+typedef struct _NuxObjectAccessiblePrivate NuxObjectAccessiblePrivate;
+
+struct _NuxObjectAccessible
+{
+ AtkObject parent;
+
+ /* < private > */
+ NuxObjectAccessiblePrivate* priv;
+};
+
+struct _NuxObjectAccessibleClass
+{
+ AtkObjectClass parent_class;
+};
+
+GType nux_object_accessible_get_type(void);
+AtkObject* nux_object_accessible_new(nux::Object* object);
+
+nux::Object* nux_object_accessible_get_object(NuxObjectAccessible* self);
+
+G_END_DECLS
+
+#endif /* __NUX_OBJECT_ACCESSIBLE_H__ */
diff --git a/a11y/nux-text-entry-accessible.cpp b/a11y/nux-text-entry-accessible.cpp
new file mode 100644
index 000000000..bda50a611
--- /dev/null
+++ b/a11y/nux-text-entry-accessible.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-text_entry-accessible
+ * @Title: NuxTextEntryAccessible
+ * @short_description: Implementation of the ATK interfaces for #TextEntry
+ * @see_also: nux::TextEntry
+ *
+ * #NuxTextEntryAccessible implements the required ATK interfaces for
+ * #StaticCairoText, mainly exposing the text as his name, as this
+ * #object is mainly used as a label
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "nux-text-entry-accessible.h"
+
+#include "unitya11y.h"
+#include <Nux/TextEntry.h>
+
+/* GObject */
+static void nux_text_entry_accessible_class_init(NuxTextEntryAccessibleClass* klass);
+static void nux_text_entry_accessible_init(NuxTextEntryAccessible* self);
+
+/* AtkObject.h */
+static void nux_text_entry_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* nux_text_entry_accessible_ref_state_set(AtkObject* obj);
+
+/* Fixme: it should implement AtkText/AtkTextEditable interfaces */
+G_DEFINE_TYPE(NuxTextEntryAccessible, nux_text_entry_accessible, NUX_TYPE_VIEW_ACCESSIBLE);
+
+
+static void
+nux_text_entry_accessible_class_init(NuxTextEntryAccessibleClass* klass)
+{
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->ref_state_set = nux_text_entry_accessible_ref_state_set;
+ atk_class->initialize = nux_text_entry_accessible_initialize;
+}
+
+static void
+nux_text_entry_accessible_init(NuxTextEntryAccessible* self)
+{}
+
+AtkObject*
+nux_text_entry_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<nux::TextEntry*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(NUX_TYPE_TEXT_ENTRY_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+nux_text_entry_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ nux::TextEntry* text_entry = NULL;
+
+ ATK_OBJECT_CLASS(nux_text_entry_accessible_parent_class)->initialize(accessible, data);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ text_entry = dynamic_cast<nux::TextEntry*>(nux_object);
+
+ atk_object_set_role(accessible, text_entry->PasswordMode() ? ATK_ROLE_PASSWORD_TEXT : ATK_ROLE_ENTRY);
+}
+
+static AtkStateSet*
+nux_text_entry_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(NUX_IS_TEXT_ENTRY_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(nux_text_entry_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ /* Text entry is editable by default */
+ atk_state_set_add_state(state_set, ATK_STATE_EDITABLE);
+
+ return state_set;
+}
diff --git a/a11y/nux-text-entry-accessible.h b/a11y/nux-text-entry-accessible.h
new file mode 100644
index 000000000..b618bd85a
--- /dev/null
+++ b/a11y/nux-text-entry-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef NUX_TEXT_ENTRY_ACCESSIBLE_H
+#define NUX_TEXT_ENTRY_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define NUX_TYPE_TEXT_ENTRY_ACCESSIBLE (nux_text_entry_accessible_get_type ())
+#define NUX_TEXT_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NUX_TYPE_TEXT_ENTRY_ACCESSIBLE, NuxTextEntryAccessible))
+#define NUX_TEXT_ENTRY_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NUX_TYPE_TEXT_ENTRY_ACCESSIBLE, NuxTextEntryAccessibleClass))
+#define NUX_IS_TEXT_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NUX_TYPE_TEXT_ENTRY_ACCESSIBLE))
+#define NUX_IS_TEXT_ENTRY_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NUX_TYPE_TEXT_ENTRY_ACCESSIBLE))
+#define NUX_TEXT_ENTRY_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NUX_TYPE_TEXT_ENTRY_ACCESSIBLE, NuxTextEntryAccessibleClass))
+
+typedef struct _NuxTextEntryAccessible NuxTextEntryAccessible;
+typedef struct _NuxTextEntryAccessibleClass NuxTextEntryAccessibleClass;
+typedef struct _NuxTextEntryAccessiblePrivate NuxTextEntryAccessiblePrivate;
+
+struct _NuxTextEntryAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ NuxTextEntryAccessiblePrivate* priv;
+};
+
+struct _NuxTextEntryAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType nux_text_entry_accessible_get_type(void);
+AtkObject* nux_text_entry_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __NUX_TEXT_ENTRY_ACCESSIBLE_H__ */
diff --git a/a11y/nux-view-accessible.cpp b/a11y/nux-view-accessible.cpp
new file mode 100644
index 000000000..2718437eb
--- /dev/null
+++ b/a11y/nux-view-accessible.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-view-accessible
+ * @Title: NuxViewAccessible
+ * @short_description: Implementation of the ATK interfaces for #nux::View
+ * @see_also: nux::View
+ *
+ * #NuxViewAccessible implements the required ATK interfaces of
+ * nux::View
+ *
+ */
+
+#include "nux-view-accessible.h"
+#include "unity-util-accessible.h"
+#include "unitya11y.h"
+#include "nux-base-window-accessible.h"
+
+#include <Nux/Layout.h>
+#include <Nux/Area.h>
+
+/* GObject */
+static void nux_view_accessible_class_init(NuxViewAccessibleClass* klass);
+static void nux_view_accessible_init(NuxViewAccessible* view_accessible);
+
+/* AtkObject.h */
+static void nux_view_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* nux_view_accessible_ref_state_set(AtkObject* obj);
+static gint nux_view_accessible_get_n_children(AtkObject* obj);
+static AtkObject* nux_view_accessible_ref_child(AtkObject* obj,
+ gint i);
+static AtkStateSet* nux_view_accessible_ref_state_set(AtkObject* obj);
+static gint nux_view_accessible_get_n_children(AtkObject* obj);
+static AtkObject* nux_view_accessible_ref_child(AtkObject* obj,
+ gint i);
+/* NuxAreaAccessible */
+static gboolean nux_view_accessible_check_pending_notification(NuxAreaAccessible* self);
+
+/* private methods */
+static void on_layout_changed_cb(nux::View* view,
+ nux::Layout* layout,
+ AtkObject* accessible,
+ gboolean is_add);
+static void on_change_keyboard_receiver_cb(AtkObject* accessible,
+ gboolean focus_in);
+
+G_DEFINE_TYPE(NuxViewAccessible,
+ nux_view_accessible,
+ NUX_TYPE_AREA_ACCESSIBLE)
+
+#define NUX_VIEW_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NUX_TYPE_VIEW_ACCESSIBLE, \
+ NuxViewAccessiblePrivate))
+
+struct _NuxViewAccessiblePrivate
+{
+ /* focused using InputArea OnStartKeyboardReceiver and OnStop... signals */
+ gboolean key_focused;
+
+ /* if the state from key_focused was notified or not */
+ gboolean pending_notification;
+};
+
+
+static void
+nux_view_accessible_class_init(NuxViewAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+ NuxAreaAccessibleClass* area_class = NUX_AREA_ACCESSIBLE_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = nux_view_accessible_initialize;
+ atk_class->ref_state_set = nux_view_accessible_ref_state_set;
+ atk_class->ref_child = nux_view_accessible_ref_child;
+ atk_class->get_n_children = nux_view_accessible_get_n_children;
+
+ /* NuxAreaAccessible */
+ area_class->check_pending_notification = nux_view_accessible_check_pending_notification;
+
+ g_type_class_add_private(gobject_class, sizeof(NuxViewAccessiblePrivate));
+}
+
+static void
+nux_view_accessible_init(NuxViewAccessible* view_accessible)
+{
+ NuxViewAccessiblePrivate* priv =
+ NUX_VIEW_ACCESSIBLE_GET_PRIVATE(view_accessible);
+
+ view_accessible->priv = priv;
+}
+
+AtkObject*
+nux_view_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<nux::View*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(NUX_TYPE_VIEW_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+nux_view_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ nux::View* view = NULL;
+
+ ATK_OBJECT_CLASS(nux_view_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_UNKNOWN;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ view = static_cast<nux::View*>(nux_object);
+
+ view->LayoutAdded.connect(sigc::bind(sigc::ptr_fun(on_layout_changed_cb),
+ accessible, TRUE));
+ view->LayoutRemoved.connect(sigc::bind(sigc::ptr_fun(on_layout_changed_cb),
+ accessible, FALSE));
+
+ /* Some extra focus things as Focusable is not used on Launcher and
+ some BaseWindow */
+ view->begin_key_focus.connect(sigc::bind(sigc::ptr_fun(on_change_keyboard_receiver_cb),
+ accessible, TRUE));
+ view->end_key_focus.connect(sigc::bind(sigc::ptr_fun(on_change_keyboard_receiver_cb),
+ accessible, FALSE));
+}
+
+static AtkStateSet*
+nux_view_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+ NuxViewAccessible* self = NULL;
+
+ g_return_val_if_fail(NUX_IS_VIEW_ACCESSIBLE(obj), NULL);
+ self = NUX_VIEW_ACCESSIBLE(obj);
+
+ state_set = ATK_OBJECT_CLASS(nux_view_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ /* HasKeyboardFocus is not reliable here:
+ see bug https://bugs.launchpad.net/nux/+bug/745049 */
+ if (self->priv->key_focused)
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+
+ return state_set;
+}
+
+static gint
+nux_view_accessible_get_n_children(AtkObject* obj)
+{
+ nux::Object* nux_object = NULL;
+ nux::View* view = NULL;
+ nux::Layout* layout = NULL;
+
+ g_return_val_if_fail(NUX_IS_VIEW_ACCESSIBLE(obj), 0);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (nux_object == NULL) /* state is defunct */
+ return 0;
+
+ view = static_cast<nux::View*>(nux_object);
+ layout = view->GetLayout();
+
+ if (layout == NULL)
+ return 0;
+ else
+ return 1;
+}
+
+static AtkObject*
+nux_view_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ nux::Object* nux_object = NULL;
+ nux::View* view = NULL;
+ nux::Layout* layout = NULL;
+ AtkObject* layout_accessible = NULL;
+ gint num = 0;
+
+ g_return_val_if_fail(NUX_IS_VIEW_ACCESSIBLE(obj), 0);
+
+ num = atk_object_get_n_accessible_children(obj);
+ g_return_val_if_fail((i < num) && (i >= 0), NULL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (nux_object == NULL) /* state is defunct */
+ return 0;
+
+ view = static_cast<nux::View*>(nux_object);
+ layout = view->GetLayout();
+
+ layout_accessible = unity_a11y_get_accessible(layout);
+
+ if (layout_accessible != NULL)
+ g_object_ref(layout_accessible);
+
+ return layout_accessible;
+}
+
+static void
+on_layout_changed_cb(nux::View* view,
+ nux::Layout* layout,
+ AtkObject* accessible,
+ gboolean is_add)
+{
+ const gchar* signal_name = NULL;
+ AtkObject* atk_child = NULL;
+
+ g_return_if_fail(NUX_IS_VIEW_ACCESSIBLE(accessible));
+
+ atk_child = unity_a11y_get_accessible(layout);
+
+ if (is_add)
+ {
+ signal_name = "children-changed::add";
+ explore_children(accessible);
+ }
+ else
+ {
+ signal_name = "children-changed::remove";
+ }
+
+ /* index is always 0 as there is always just one layout */
+ g_signal_emit_by_name(accessible, signal_name, 0, atk_child, NULL);
+}
+
+static void
+on_change_keyboard_receiver_cb(AtkObject* accessible,
+ gboolean focus_in)
+{
+ NuxViewAccessible* self = NULL;
+
+ g_return_if_fail(NUX_IS_VIEW_ACCESSIBLE(accessible));
+ self = NUX_VIEW_ACCESSIBLE(accessible);
+
+ if (self->priv->key_focused != focus_in)
+ {
+ self->priv->key_focused = focus_in;
+
+ /* we always lead the focus notification to
+ _check_pending_notification, in order to allow the proper
+ window_activate -> focus_change order */
+ self->priv->pending_notification = TRUE;
+ }
+}
+
+static gboolean
+nux_view_accessible_check_pending_notification(NuxAreaAccessible* area_accessible)
+{
+ NuxViewAccessible* self = NULL;
+ nux::Object* nux_object = NULL;
+
+ /* We also call the parent implementation, as we are not totally
+ overriding check_pending_notification, just adding extra
+ functionality*/
+ NUX_AREA_ACCESSIBLE_CLASS(nux_view_accessible_parent_class)->check_pending_notification(area_accessible);
+
+ g_return_val_if_fail(NUX_IS_VIEW_ACCESSIBLE(area_accessible), FALSE);
+ self = NUX_VIEW_ACCESSIBLE(area_accessible);
+
+ if (self->priv->pending_notification == FALSE)
+ return FALSE;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (nux_object == NULL) /* defunct */
+ return FALSE;
+
+ g_signal_emit_by_name(self, "focus_event", self->priv->key_focused);
+ atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, self->priv->key_focused);
+ self->priv->pending_notification = FALSE;
+
+ return TRUE;
+}
diff --git a/a11y/nux-view-accessible.h b/a11y/nux-view-accessible.h
new file mode 100644
index 000000000..bca728ce6
--- /dev/null
+++ b/a11y/nux-view-accessible.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef NUX_VIEW_ACCESSIBLE_H
+#define NUX_VIEW_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-area-accessible.h"
+
+#include <Nux/Nux.h>
+#include <Nux/View.h>
+
+G_BEGIN_DECLS
+
+#define NUX_TYPE_VIEW_ACCESSIBLE (nux_view_accessible_get_type ())
+#define NUX_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NUX_TYPE_VIEW_ACCESSIBLE, NuxViewAccessible))
+#define NUX_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NUX_TYPE_VIEW_ACCESSIBLE, NuxViewAccessibleClass))
+#define NUX_IS_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NUX_TYPE_VIEW_ACCESSIBLE))
+#define NUX_IS_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NUX_TYPE_VIEW_ACCESSIBLE))
+#define NUX_VIEW_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NUX_TYPE_VIEW_ACCESSIBLE, NuxViewAccessibleClass))
+
+typedef struct _NuxViewAccessible NuxViewAccessible;
+typedef struct _NuxViewAccessibleClass NuxViewAccessibleClass;
+typedef struct _NuxViewAccessiblePrivate NuxViewAccessiblePrivate;
+
+struct _NuxViewAccessible
+{
+ NuxAreaAccessible parent;
+
+ /*< private >*/
+ NuxViewAccessiblePrivate* priv;
+};
+
+struct _NuxViewAccessibleClass
+{
+ NuxAreaAccessibleClass parent_class;
+};
+
+GType nux_view_accessible_get_type(void);
+AtkObject* nux_view_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __NUX_VIEW_ACCESSIBLE_H__ */
diff --git a/a11y/pch/a11y_pch.hh b/a11y/pch/a11y_pch.hh
new file mode 100644
index 000000000..ecae45c9c
--- /dev/null
+++ b/a11y/pch/a11y_pch.hh
@@ -0,0 +1,33 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+/*
+ * These are the precompiled header includes for this module.
+ * Only system header files can be listed here.
+ */
+
+#include <atk/atk.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <gmodule.h>
+#include <stdio.h>
+#include <atk-bridge.h>
+#include <Nux/Nux.h>
+#include <Nux/WindowThread.h>
+#include <NuxCore/Object.h>
diff --git a/a11y/unity-dash-view-accessible.cpp b/a11y/unity-dash-view-accessible.cpp
new file mode 100644
index 000000000..76258e128
--- /dev/null
+++ b/a11y/unity-dash-view-accessible.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-dash_view-accessible
+ * @Title: UnityDashViewAccessible
+ * @short_description: Implementation of the ATK interfaces for #DashView
+ * @see_also: DashView
+ *
+ * #UnityDashViewAccessible implements the required ATK interfaces for
+ * #DashView, ie: exposing the different DashViewIcon on the model as
+ * #child of the object.
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-dash-view-accessible.h"
+
+#include "unitya11y.h"
+#include "DashView.h"
+
+using namespace unity::dash;
+
+/* GObject */
+static void unity_dash_view_accessible_class_init(UnityDashViewAccessibleClass* klass);
+static void unity_dash_view_accessible_init(UnityDashViewAccessible* self);
+static void unity_dash_view_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_dash_view_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+
+G_DEFINE_TYPE(UnityDashViewAccessible, unity_dash_view_accessible, NUX_TYPE_VIEW_ACCESSIBLE)
+
+#define UNITY_DASH_VIEW_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_DASH_VIEW_ACCESSIBLE, \
+ UnityDashViewAccessiblePrivate))
+
+struct _UnityDashViewAccessiblePrivate
+{
+
+};
+
+
+static void
+unity_dash_view_accessible_class_init(UnityDashViewAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = unity_dash_view_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->initialize = unity_dash_view_accessible_initialize;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityDashViewAccessiblePrivate));
+}
+
+static void
+unity_dash_view_accessible_init(UnityDashViewAccessible* self)
+{
+ UnityDashViewAccessiblePrivate* priv =
+ UNITY_DASH_VIEW_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+}
+
+static void
+unity_dash_view_accessible_finalize(GObject* object)
+{
+ G_OBJECT_CLASS(unity_dash_view_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_dash_view_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<DashView*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_DASH_VIEW_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+ atk_object_set_name(accessible, _("Dash"));
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_dash_view_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ ATK_OBJECT_CLASS(unity_dash_view_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_PANEL;
+}
+
diff --git a/a11y/unity-dash-view-accessible.h b/a11y/unity-dash-view-accessible.h
new file mode 100644
index 000000000..9d3ef7cc1
--- /dev/null
+++ b/a11y/unity-dash-view-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_DASH_VIEW_ACCESSIBLE_H
+#define UNITY_DASH_VIEW_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_DASH_VIEW_ACCESSIBLE (unity_dash_view_accessible_get_type ())
+#define UNITY_DASH_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_DASH_VIEW_ACCESSIBLE, UnityDashViewAccessible))
+#define UNITY_DASH_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_DASH_VIEW_ACCESSIBLE, UnityDashViewAccessibleClass))
+#define UNITY_IS_DASH_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_DASH_VIEW_ACCESSIBLE))
+#define UNITY_IS_DASH_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_DASH_VIEW_ACCESSIBLE))
+#define UNITY_DASH_VIEW_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_DASH_VIEW_ACCESSIBLE, UnityDashViewAccessibleClass))
+
+typedef struct _UnityDashViewAccessible UnityDashViewAccessible;
+typedef struct _UnityDashViewAccessibleClass UnityDashViewAccessibleClass;
+typedef struct _UnityDashViewAccessiblePrivate UnityDashViewAccessiblePrivate;
+
+struct _UnityDashViewAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityDashViewAccessiblePrivate* priv;
+};
+
+struct _UnityDashViewAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_dash_view_accessible_get_type(void);
+AtkObject* unity_dash_view_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_DASH_VIEW_ACCESSIBLE_H__ */
diff --git a/a11y/unity-expander-view-accessible.cpp b/a11y/unity-expander-view-accessible.cpp
new file mode 100644
index 000000000..b16f5c3d2
--- /dev/null
+++ b/a11y/unity-expander-view-accessible.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Luke Yelavich <luke.yelavich@canonical.com>
+ */
+
+/**
+ * SECTION:unity-expander-view-accessible
+ * @Title: UnityExpanderViewAccessible
+ * @short_description: Implementation of the ATK interfaces for #ExpanderView
+ * @see_also: ExpanderView
+ *
+ * #UnityExpanderViewAccessible implements the required ATK interfaces for
+ * #ExpanderView, mainly exposing the text as his name, as this
+ * #object is mainly used as a label
+ *
+ */
+
+#include <NuxCore/Logger.h>
+#include <glib/gi18n.h>
+
+#include "unity-expander-view-accessible.h"
+
+#include "ExpanderView.h"
+#include "StaticCairoText.h"
+
+DECLARE_LOGGER(logger, "unity.a11y.ExpanderView");
+
+using namespace unity;
+
+/* GObject */
+static void unity_expander_view_accessible_class_init(UnityExpanderViewAccessibleClass* klass);
+static void unity_expander_view_accessible_init(UnityExpanderViewAccessible* self);
+static void unity_expander_view_accessible_dispose(GObject* object);
+
+/* AtkObject.h */
+static void unity_expander_view_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static const gchar* unity_expander_view_accessible_get_name(AtkObject* obj);
+static void on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible);
+static void on_expanded_changed_cb(bool is_expanded,
+ AtkObject* accessible);
+static void on_name_changed_cb(std::string name,
+ AtkObject* accessible);
+
+G_DEFINE_TYPE(UnityExpanderViewAccessible, unity_expander_view_accessible, NUX_TYPE_VIEW_ACCESSIBLE);
+
+
+#define UNITY_EXPANDER_VIEW_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE, \
+ UnityExpanderViewAccessiblePrivate))
+
+struct _UnityExpanderViewAccessiblePrivate
+{
+ gchar* name;
+};
+
+
+static void
+unity_expander_view_accessible_class_init(UnityExpanderViewAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->dispose = unity_expander_view_accessible_dispose;
+
+ /* AtkObject */
+ atk_class->initialize = unity_expander_view_accessible_initialize;
+ atk_class->get_name = unity_expander_view_accessible_get_name;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityExpanderViewAccessiblePrivate));
+}
+
+static void
+unity_expander_view_accessible_init(UnityExpanderViewAccessible* self)
+{
+ UnityExpanderViewAccessiblePrivate* priv =
+ UNITY_EXPANDER_VIEW_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+ self->priv->name = NULL;
+}
+
+static void
+unity_expander_view_accessible_dispose(GObject* object)
+{
+ UnityExpanderViewAccessible* self = UNITY_EXPANDER_VIEW_ACCESSIBLE(object);
+
+ if (self->priv->name != NULL)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ G_OBJECT_CLASS(unity_expander_view_accessible_parent_class)->dispose(object);
+}
+
+AtkObject*
+unity_expander_view_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<ExpanderView*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_expander_view_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* object = NULL;
+ ExpanderView* view = NULL;
+
+ ATK_OBJECT_CLASS(unity_expander_view_accessible_parent_class)->initialize(accessible, data);
+
+ object = (nux::Object*)data;
+ view = static_cast<ExpanderView*>(object);
+ view->key_nav_focus_change.connect(sigc::bind(sigc::ptr_fun(on_focus_changed_cb), accessible));
+ view->expanded.changed.connect(sigc::bind(sigc::ptr_fun(on_expanded_changed_cb), accessible));
+ view->label.changed.connect(sigc::bind(sigc::ptr_fun(on_name_changed_cb), accessible));
+
+ atk_object_set_role(accessible, ATK_ROLE_PANEL);
+}
+
+static const gchar*
+unity_expander_view_accessible_get_name(AtkObject* obj)
+{
+ g_return_val_if_fail(UNITY_IS_EXPANDER_VIEW_ACCESSIBLE(obj), NULL);
+ UnityExpanderViewAccessible* self = UNITY_EXPANDER_VIEW_ACCESSIBLE(obj);
+
+ if (self->priv->name != NULL)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ self->priv->name = g_strdup(ATK_OBJECT_CLASS(unity_expander_view_accessible_parent_class)->get_name(obj));
+ if (self->priv->name == NULL)
+ {
+ ExpanderView* view = NULL;
+
+ view = dynamic_cast<ExpanderView*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
+
+ if (view == NULL) /* state is defunct */
+ return NULL;
+
+ if (view->expanded)
+ self->priv->name = g_strdup_printf(_("%s: expanded"), view->label().c_str());
+ else
+ self->priv->name = g_strdup_printf(_("%s: collapsed"), view->label().c_str());
+ }
+
+ return self->priv->name;
+}
+
+static void
+on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible)
+{
+ g_return_if_fail(UNITY_IS_EXPANDER_VIEW_ACCESSIBLE(accessible));
+
+ LOG_WARN(logger) << "has_focus = " << has_focus;
+ g_signal_emit_by_name(accessible, "focus-event", has_focus);
+}
+
+static void
+on_expanded_changed_cb(bool is_expanded,
+ AtkObject* accessible)
+{
+ g_return_if_fail(UNITY_IS_EXPANDER_VIEW_ACCESSIBLE(accessible));
+
+ g_object_notify(G_OBJECT(accessible), "accessible-name");
+}
+
+static void
+on_name_changed_cb(std::string name,
+ AtkObject* accessible)
+{
+ g_return_if_fail(UNITY_IS_EXPANDER_VIEW_ACCESSIBLE(accessible));
+
+ g_object_notify(G_OBJECT(accessible), "accessible-name");
+}
diff --git a/a11y/unity-expander-view-accessible.h b/a11y/unity-expander-view-accessible.h
new file mode 100644
index 000000000..0c9855d79
--- /dev/null
+++ b/a11y/unity-expander-view-accessible.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Luke Yelavich <luke.yelavich@canonical.com>
+ */
+
+#ifndef UNITY_EXPANDER_VIEW_ACCESSIBLE_H
+#define UNITY_EXPANDER_VIEW_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include <Nux/Nux.h>
+#include <Nux/Layout.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE (unity_expander_view_accessible_get_type ())
+#define UNITY_EXPANDER_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE, UnityExpanderViewAccessible))
+#define UNITY_EXPANDER_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE, UnityExpanderViewAccessibleClass))
+#define UNITY_IS_EXPANDER_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE))
+#define UNITY_IS_EXPANDER_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE))
+#define UNITY_EXPANDER_VIEW_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_EXPANDER_VIEW_ACCESSIBLE, UnityExpanderViewAccessibleClass))
+
+typedef struct _UnityExpanderViewAccessible UnityExpanderViewAccessible;
+typedef struct _UnityExpanderViewAccessibleClass UnityExpanderViewAccessibleClass;
+typedef struct _UnityExpanderViewAccessiblePrivate UnityExpanderViewAccessiblePrivate;
+
+struct _UnityExpanderViewAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityExpanderViewAccessiblePrivate* priv;
+};
+
+struct _UnityExpanderViewAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_expander_view_accessible_get_type(void);
+AtkObject* unity_expander_view_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_EXPANDER_VIEW_ACCESSIBLE_H__ */
diff --git a/a11y/unity-filter-basic-button-accessible.cpp b/a11y/unity-filter-basic-button-accessible.cpp
new file mode 100644
index 000000000..1011e86f5
--- /dev/null
+++ b/a11y/unity-filter-basic-button-accessible.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Luke Yelavich <luke.yelavich@canonical.com>
+ */
+
+/**
+ * SECTION:unity-filter-basic-button_accessible
+ * @Title: UnityFilterBasicButtonAccessible
+ * @short_description: Implementation of the ATK interfaces for #unity::dash::FilterBasicButton
+ *
+ * #UnityFilterBasicButtonAccessible implements the required ATK interfaces of
+ * unity::dash::FilterBasicButton, exposing the common elements on each basic individual
+ * element (position, extents, etc)
+ *
+ */
+
+#include <NuxCore/Logger.h>
+#include "unity-filter-basic-button-accessible.h"
+#include "FilterBasicButton.h"
+
+#include "unitya11y.h"
+
+DECLARE_LOGGER(logger, "unity.a11y.UnityFilterBasicButtonAccessible");
+
+using namespace unity::dash;
+
+/* GObject */
+static void unity_filter_basic_button_accessible_class_init(UnityFilterBasicButtonAccessibleClass* klass);
+static void unity_filter_basic_button_accessible_init(UnityFilterBasicButtonAccessible* session_button_accessible);
+static void unity_filter_basic_button_accessible_dispose(GObject* object);
+static void unity_filter_basic_button_accessible_finalize(GObject* object);
+
+
+/* AtkObject.h */
+static void unity_filter_basic_button_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* unity_filter_basic_button_accessible_ref_state_set(AtkObject* obj);
+static const gchar* unity_filter_basic_button_accessible_get_name(AtkObject* obj);
+
+
+/* AtkAction */
+static void atk_action_interface_init(AtkActionIface *iface);
+static gboolean unity_filter_basic_button_accessible_do_action(AtkAction *action,
+ gint i);
+static gint unity_filter_basic_button_accessible_get_n_actions(AtkAction *action);
+static const gchar* unity_filter_basic_button_accessible_get_action_name(AtkAction *action,
+ gint i);
+static void on_layout_changed_cb(nux::View* view,
+ nux::Layout* layout,
+ AtkObject* accessible,
+ gboolean is_add);
+static void on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible);
+
+G_DEFINE_TYPE_WITH_CODE(UnityFilterBasicButtonAccessible,
+ unity_filter_basic_button_accessible,
+ NUX_TYPE_VIEW_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION,
+ atk_action_interface_init))
+
+static void
+unity_filter_basic_button_accessible_class_init(UnityFilterBasicButtonAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->dispose = unity_filter_basic_button_accessible_dispose;
+ gobject_class->finalize = unity_filter_basic_button_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->initialize = unity_filter_basic_button_accessible_initialize;
+ atk_class->get_name = unity_filter_basic_button_accessible_get_name;
+ atk_class->ref_state_set = unity_filter_basic_button_accessible_ref_state_set;
+}
+
+static void
+unity_filter_basic_button_accessible_init(UnityFilterBasicButtonAccessible* session_button_accessible)
+{
+}
+
+static void
+unity_filter_basic_button_accessible_dispose(GObject* object)
+{
+ G_OBJECT_CLASS(unity_filter_basic_button_accessible_parent_class)->dispose(object);
+}
+
+static void
+unity_filter_basic_button_accessible_finalize(GObject* object)
+{
+ G_OBJECT_CLASS(unity_filter_basic_button_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_filter_basic_button_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<FilterBasicButton*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_FILTER_BASIC_BUTTON_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_filter_basic_button_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ FilterBasicButton* button = NULL;
+
+ ATK_OBJECT_CLASS(unity_filter_basic_button_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_TOGGLE_BUTTON;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+
+ if (nux_object == NULL) /* defunct */
+ return;
+
+ button = dynamic_cast<FilterBasicButton*>(nux_object);
+
+ if (button == NULL) /* defunct */
+ return;
+
+ button->LayoutAdded.connect(sigc::bind(sigc::ptr_fun(on_layout_changed_cb),
+ accessible, TRUE));
+
+ button->key_nav_focus_change.connect(sigc::bind(sigc::ptr_fun(on_focus_changed_cb), accessible));
+}
+
+static const gchar*
+unity_filter_basic_button_accessible_get_name(AtkObject* obj)
+{
+ const gchar* name;
+
+ g_return_val_if_fail(UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(obj), NULL);
+
+ name = ATK_OBJECT_CLASS(unity_filter_basic_button_accessible_parent_class)->get_name(obj);
+ if (name == NULL)
+ {
+ FilterBasicButton* button = NULL;
+
+ button = dynamic_cast<FilterBasicButton*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
+
+ if (button == NULL) /* State is defunct */
+ name = NULL;
+ else
+ name = button->GetLabel().c_str();
+ }
+
+ if (name == NULL)
+ {
+ LOG_WARN(logger) << "Name == NULL";
+ }
+
+ return name;
+}
+
+static AtkStateSet*
+unity_filter_basic_button_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+ FilterBasicButton* button = NULL;
+
+ g_return_val_if_fail(UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(unity_filter_basic_button_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ button = static_cast<FilterBasicButton*>(nux_object);
+
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+ atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
+ atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
+
+ if (button->GetVisualState() == nux::ButtonVisualState::VISUAL_STATE_PRELIGHT)
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+ atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
+ atk_state_set_add_state(state_set, ATK_STATE_ACTIVE);
+ }
+
+ if (button->Active())
+ atk_state_set_add_state(state_set, ATK_STATE_CHECKED);
+
+ return state_set;
+}
+
+/* AtkAction */
+static void
+atk_action_interface_init(AtkActionIface *iface)
+{
+ iface->do_action = unity_filter_basic_button_accessible_do_action;
+ iface->get_n_actions = unity_filter_basic_button_accessible_get_n_actions;
+ iface->get_name = unity_filter_basic_button_accessible_get_action_name;
+}
+
+static gboolean
+unity_filter_basic_button_accessible_do_action(AtkAction *action,
+ gint i)
+{
+ FilterBasicButton* button = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(action), FALSE);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(action));
+ if (nux_object == NULL)
+ return FALSE;
+
+ button = static_cast<FilterBasicButton*>(nux_object);
+ button->Activate();
+
+ return TRUE;
+}
+
+static gint
+unity_filter_basic_button_accessible_get_n_actions(AtkAction *action)
+{
+ g_return_val_if_fail(UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(action), 0);
+
+ return 1;
+}
+
+static const gchar*
+unity_filter_basic_button_accessible_get_action_name(AtkAction *action,
+ gint i)
+{
+ g_return_val_if_fail(UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(action), NULL);
+ g_return_val_if_fail(i == 0, NULL);
+
+ return "activate";
+}
+
+static void
+on_layout_changed_cb(nux::View* view,
+ nux::Layout* layout,
+ AtkObject* accessible,
+ gboolean is_add)
+{
+ g_return_if_fail(UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(accessible));
+
+ g_object_notify(G_OBJECT(accessible), "accessible-name");
+}
+
+static void
+on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible)
+{
+ g_return_if_fail(UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(accessible));
+
+ g_signal_emit_by_name(accessible, "focus-event", has_focus);
+}
diff --git a/a11y/unity-filter-basic-button-accessible.h b/a11y/unity-filter-basic-button-accessible.h
new file mode 100644
index 000000000..a5eed8df0
--- /dev/null
+++ b/a11y/unity-filter-basic-button-accessible.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Luke Yelavich <luke.yelavich@canonical.com>
+ */
+
+#ifndef UNITY_FILTER_BASIC_BUTTON_ACCESSIBLE_H
+#define UNITY_FILTER_BASIC_BUTTON_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_FILTER_BASIC_BUTTON_ACCESSIBLE (unity_filter_basic_button_accessible_get_type ())
+#define UNITY_FILTER_BASIC_BUTTON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_FILTER_BASIC_BUTTON_ACCESSIBLE, UnityFilterBasicButtonAccessible))
+#define UNITY_FILTER_BASIC_BUTTON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_FILTER_BASIC_BUTTON_ACCESSIBLE, UnityFilterBasicButtonAccessibleClass))
+#define UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_FILTER_BASIC_BUTTON_ACCESSIBLE))
+#define UNITY_IS_FILTER_BASIC_BUTTON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_FILTER_BASIC_BUTTON_ACCESSIBLE))
+#define UNITY_FILTER_BASIC_BUTTON_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_FILTER_BASIC_BUTTON_ACCESSIBLE, UnityFilterBasicButtonAccessibleClass))
+
+typedef struct _UnityFilterBasicButtonAccessible UnityFilterBasicButtonAccessible;
+typedef struct _UnityFilterBasicButtonAccessibleClass UnityFilterBasicButtonAccessibleClass;
+
+struct _UnityFilterBasicButtonAccessible
+{
+ NuxViewAccessible parent;
+};
+
+struct _UnityFilterBasicButtonAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_filter_basic_button_accessible_get_type(void);
+AtkObject* unity_filter_basic_button_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_FILTER_BASIC_BUTTON_ACCESSIBLE_H__ */
diff --git a/a11y/unity-launcher-accessible.cpp b/a11y/unity-launcher-accessible.cpp
new file mode 100644
index 000000000..182ad524f
--- /dev/null
+++ b/a11y/unity-launcher-accessible.cpp
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-launcher-accessible
+ * @Title: UnityLauncherAccessible
+ * @short_description: Implementation of the ATK interfaces for #Launcher
+ * @see_also: Launcher
+ *
+ * #UnityLauncherAccessible implements the required ATK interfaces for
+ * #Launcher, ie: exposing the different AbstractLauncherIcon on the model as
+ * #child of the object.
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-launcher-accessible.h"
+#include "unity-launcher-icon-accessible.h"
+
+#include "unitya11y.h"
+#include "Launcher.h"
+#include "LauncherModel.h"
+
+using unity::launcher::Launcher;
+using unity::launcher::AbstractLauncherIcon;
+using unity::launcher::LauncherModel;
+
+/* GObject */
+static void unity_launcher_accessible_class_init(UnityLauncherAccessibleClass* klass);
+static void unity_launcher_accessible_init(UnityLauncherAccessible* self);
+static void unity_launcher_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_launcher_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static gint unity_launcher_accessible_get_n_children(AtkObject* obj);
+static AtkObject* unity_launcher_accessible_ref_child(AtkObject* obj,
+ gint i);
+static AtkStateSet* unity_launcher_accessible_ref_state_set(AtkObject* obj);
+
+/* AtkSelection */
+static void atk_selection_interface_init(AtkSelectionIface* iface);
+static AtkObject* unity_launcher_accessible_ref_selection(AtkSelection* selection,
+ gint i);
+static gint unity_launcher_accessible_get_selection_count(AtkSelection* selection);
+static gboolean unity_launcher_accessible_is_child_selected(AtkSelection* selection,
+ gint i);
+
+/* private */
+static void on_selection_change_cb(AbstractLauncherIcon::Ptr const& selection, UnityLauncherAccessible* launcher_accessible);
+static void on_icon_added_cb(AbstractLauncherIcon::Ptr const& icon, UnityLauncherAccessible* self);
+static void on_icon_removed_cb(AbstractLauncherIcon::Ptr const& icon, UnityLauncherAccessible* self);
+static void on_order_change_cb(UnityLauncherAccessible* self);
+static void update_children_index(UnityLauncherAccessible* self);
+
+G_DEFINE_TYPE_WITH_CODE(UnityLauncherAccessible, unity_launcher_accessible, NUX_TYPE_VIEW_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init))
+
+#define UNITY_LAUNCHER_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_LAUNCHER_ACCESSIBLE, \
+ UnityLauncherAccessiblePrivate))
+
+struct _UnityLauncherAccessiblePrivate
+{
+ sigc::connection on_selection_change_connection;
+ sigc::connection on_icon_added_connection;
+ sigc::connection on_icon_removed_connection;
+ sigc::connection on_order_changed_connection;
+};
+
+
+static void
+unity_launcher_accessible_class_init(UnityLauncherAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = unity_launcher_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->get_n_children = unity_launcher_accessible_get_n_children;
+ atk_class->ref_child = unity_launcher_accessible_ref_child;
+ atk_class->initialize = unity_launcher_accessible_initialize;
+ atk_class->ref_state_set = unity_launcher_accessible_ref_state_set;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityLauncherAccessiblePrivate));
+}
+
+static void
+unity_launcher_accessible_init(UnityLauncherAccessible* self)
+{
+ UnityLauncherAccessiblePrivate* priv =
+ UNITY_LAUNCHER_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+}
+
+static void
+unity_launcher_accessible_finalize(GObject* object)
+{
+ UnityLauncherAccessible* self = UNITY_LAUNCHER_ACCESSIBLE(object);
+
+ self->priv->on_selection_change_connection.disconnect();
+ self->priv->on_icon_added_connection.disconnect();
+ self->priv->on_icon_removed_connection.disconnect();
+ self->priv->on_order_changed_connection.disconnect();
+
+ G_OBJECT_CLASS(unity_launcher_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_launcher_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<Launcher*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_LAUNCHER_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+ atk_object_set_name(accessible, _("Launcher"));
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_launcher_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ Launcher* launcher = NULL;
+ nux::Object* nux_object = NULL;
+ UnityLauncherAccessible* self = NULL;
+ LauncherModel::Ptr model = NULL;
+
+ ATK_OBJECT_CLASS(unity_launcher_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_TOOL_BAR;
+
+ self = UNITY_LAUNCHER_ACCESSIBLE(accessible);
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+
+ launcher = static_cast<Launcher*>(nux_object);
+ model = launcher->GetModel();
+
+ if (model)
+ {
+ self->priv->on_selection_change_connection =
+ model->selection_changed.connect(sigc::bind(sigc::ptr_fun(on_selection_change_cb), self));
+
+ self->priv->on_icon_added_connection =
+ model->icon_added.connect(sigc::bind(sigc::ptr_fun(on_icon_added_cb), self));
+
+ self->priv->on_icon_removed_connection =
+ model->icon_removed.connect(sigc::bind(sigc::ptr_fun(on_icon_removed_cb), self));
+
+ self->priv->on_order_changed_connection =
+ model->order_changed.connect(sigc::bind(sigc::ptr_fun(on_order_change_cb), self));
+ }
+}
+
+static gint
+unity_launcher_accessible_get_n_children(AtkObject* obj)
+{
+ nux::Object* object = NULL;
+ Launcher* launcher = NULL;
+ LauncherModel::Ptr launcher_model;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(obj), 0);
+
+ object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (!object) /* state is defunct */
+ return 0;
+
+ launcher = static_cast<Launcher*>(object);
+
+ launcher_model = launcher->GetModel();
+
+ if (launcher_model)
+ return launcher_model->Size();
+ else
+ return 0;
+}
+
+static AtkObject*
+unity_launcher_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ gint num = 0;
+ nux::Object* nux_object = NULL;
+ Launcher* launcher = NULL;
+ LauncherModel::Ptr launcher_model;
+ LauncherModel::iterator it;
+ nux::Object* child = NULL;
+ AtkObject* child_accessible = NULL;
+ AtkObject* parent = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(obj), NULL);
+ num = atk_object_get_n_accessible_children(obj);
+ g_return_val_if_fail((i < num) && (i >= 0), NULL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ launcher = static_cast<Launcher*>(nux_object);
+ launcher_model = launcher->GetModel();
+
+ it = launcher_model->begin();
+ std::advance(it, i);
+
+ child = dynamic_cast<nux::Object*>((*it).GetPointer());
+ child_accessible = unity_a11y_get_accessible(child);
+
+ parent = atk_object_get_parent(child_accessible);
+ if (parent != obj)
+ atk_object_set_parent(child_accessible, obj);
+
+ g_object_ref(child_accessible);
+
+ return child_accessible;
+}
+
+static AtkStateSet*
+unity_launcher_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(obj), NULL);
+
+ state_set =
+ ATK_OBJECT_CLASS(unity_launcher_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ /* The Launcher is always focusable */
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+
+ return state_set;
+}
+
+/* AtkSelection */
+static void
+atk_selection_interface_init(AtkSelectionIface* iface)
+{
+ iface->ref_selection = unity_launcher_accessible_ref_selection;
+ iface->get_selection_count = unity_launcher_accessible_get_selection_count;
+ iface->is_child_selected = unity_launcher_accessible_is_child_selected;
+
+ /* NOTE: for the moment we don't provide the implementation for the
+ "interactable" methods, it is, the methods that allow to change
+ the selected icon. The Launcher doesn't provide that API, and
+ right now we are focusing on a normal user input.*/
+ /* iface->add_selection = unity_launcher_accessible_add_selection; */
+ /* iface->clear_selection = unity_launcher_accessible_clear_selection; */
+ /* iface->remove_selection = unity_launcher_accessible_remove_selection; */
+
+ /* This method will never be implemented, as select all the launcher
+ icons makes no sense */
+ /* iface->select_all = unity_launcher_accessible_select_all_selection; */
+}
+
+static AtkObject*
+unity_launcher_accessible_ref_selection(AtkSelection* selection,
+ gint i)
+{
+ Launcher* launcher = NULL;
+ nux::Object* nux_object = NULL;
+ AtkObject* accessible_selected = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(selection), 0);
+ /* there can be only just item selected */
+ g_return_val_if_fail(i == 0, NULL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ launcher = static_cast<Launcher*>(nux_object);
+ AbstractLauncherIcon::Ptr const& selected_icon = launcher->GetSelectedMenuIcon();
+
+ if (selected_icon)
+ {
+ accessible_selected = unity_a11y_get_accessible(selected_icon.GetPointer());
+ g_object_ref(accessible_selected);
+ }
+
+ return accessible_selected;
+}
+
+static gint
+unity_launcher_accessible_get_selection_count(AtkSelection* selection)
+{
+ Launcher* launcher = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(selection), 0);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ launcher = static_cast<Launcher*>(nux_object);
+
+ if (!launcher->GetSelectedMenuIcon())
+ return 0;
+ else
+ return 1;
+}
+
+static gboolean
+unity_launcher_accessible_is_child_selected(AtkSelection* selection,
+ gint i)
+{
+ Launcher* launcher = NULL;
+ LauncherModel::iterator it;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(selection), FALSE);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ launcher = static_cast<Launcher*>(nux_object);
+ LauncherModel::Ptr const& launcher_model = launcher->GetModel();
+ it = launcher_model->begin();
+ std::advance(it, i);
+
+ AbstractLauncherIcon::Ptr const& selected_icon = launcher->GetSelectedMenuIcon();
+
+ if (selected_icon == *it)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* private */
+static void on_selection_change_cb(AbstractLauncherIcon::Ptr const& selection, UnityLauncherAccessible* launcher_accessible)
+{
+ g_signal_emit_by_name(ATK_OBJECT(launcher_accessible), "selection-changed");
+}
+
+
+static void
+on_icon_added_cb(AbstractLauncherIcon::Ptr const& icon,
+ UnityLauncherAccessible* self)
+{
+ AtkObject* icon_accessible = NULL;
+ nux::Object* nux_object = NULL;
+ gint index = 0;
+
+ g_return_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(self));
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (nux_object == NULL) /* state is defunct */
+ return;
+
+ icon_accessible = unity_a11y_get_accessible(icon.GetPointer());
+ atk_object_set_parent(icon_accessible, ATK_OBJECT(self));
+
+ update_children_index(self);
+
+ index = atk_object_get_index_in_parent(icon_accessible);
+
+ g_signal_emit_by_name(self, "children-changed::add",
+ index, icon_accessible, NULL);
+}
+
+static void
+on_icon_removed_cb(AbstractLauncherIcon::Ptr const& icon,
+ UnityLauncherAccessible* self)
+{
+ AtkObject* icon_accessible = NULL;
+ nux::Object* nux_object = NULL;
+ gint index = 0;
+
+ g_return_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(self));
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (nux_object == NULL) /* state is defunct */
+ return;
+
+ icon_accessible = unity_a11y_get_accessible(icon.GetPointer());
+
+ index = atk_object_get_index_in_parent(icon_accessible);
+
+ g_signal_emit_by_name(self, "children-changed::remove",
+ index, icon_accessible, NULL);
+
+ update_children_index(self);
+}
+
+static void
+update_children_index(UnityLauncherAccessible* self)
+{
+ gint index = 0;
+ nux::Object* nux_object = NULL;
+ Launcher* launcher = NULL;
+ LauncherModel::Ptr launcher_model;
+ LauncherModel::iterator it;
+ nux::Object* child = NULL;
+ AtkObject* child_accessible = NULL;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (!nux_object) /* state is defunct */
+ return;
+
+ launcher = static_cast<Launcher*>(nux_object);
+ launcher_model = launcher->GetModel();
+
+ if (launcher_model == NULL)
+ return;
+
+ for (it = launcher_model->begin(); it != launcher_model->end(); ++it)
+ {
+ child = dynamic_cast<nux::Object*>((*it).GetPointer());
+ child_accessible = unity_a11y_get_accessible(child);
+
+ unity_launcher_icon_accessible_set_index(UNITY_LAUNCHER_ICON_ACCESSIBLE(child_accessible),
+ index++);
+ }
+}
+
+static void
+on_order_change_cb(UnityLauncherAccessible* self)
+{
+ g_return_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(self));
+
+ update_children_index(self);
+}
diff --git a/a11y/unity-launcher-accessible.h b/a11y/unity-launcher-accessible.h
new file mode 100644
index 000000000..faa9817a2
--- /dev/null
+++ b/a11y/unity-launcher-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_LAUNCHER_ACCESSIBLE_H
+#define UNITY_LAUNCHER_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_LAUNCHER_ACCESSIBLE (unity_launcher_accessible_get_type ())
+#define UNITY_LAUNCHER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_LAUNCHER_ACCESSIBLE, UnityLauncherAccessible))
+#define UNITY_LAUNCHER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_LAUNCHER_ACCESSIBLE, UnityLauncherAccessibleClass))
+#define UNITY_IS_LAUNCHER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_LAUNCHER_ACCESSIBLE))
+#define UNITY_IS_LAUNCHER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_LAUNCHER_ACCESSIBLE))
+#define UNITY_LAUNCHER_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_LAUNCHER_ACCESSIBLE, UnityLauncherAccessibleClass))
+
+typedef struct _UnityLauncherAccessible UnityLauncherAccessible;
+typedef struct _UnityLauncherAccessibleClass UnityLauncherAccessibleClass;
+typedef struct _UnityLauncherAccessiblePrivate UnityLauncherAccessiblePrivate;
+
+struct _UnityLauncherAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityLauncherAccessiblePrivate* priv;
+};
+
+struct _UnityLauncherAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_launcher_accessible_get_type(void);
+AtkObject* unity_launcher_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_LAUNCHER_ACCESSIBLE_H__ */
diff --git a/a11y/unity-launcher-icon-accessible.cpp b/a11y/unity-launcher-icon-accessible.cpp
new file mode 100644
index 000000000..8afb4e823
--- /dev/null
+++ b/a11y/unity-launcher-icon-accessible.cpp
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-launcher_icon-accessible
+ * @Title: UnityLauncherIconAccessible
+ * @short_description: Implementation of the ATK interfaces for #nux::LauncherIcon
+ * @see_also: nux::LauncherIcon
+ *
+ * #UnityLauncherIconAccessible implements the required ATK interfaces of
+ * nux::LauncherIcon, exposing the common elements on each basic individual
+ * element (position, extents, etc)
+ *
+ * Implementation notes: on previous implementations we implemented
+ * _get_parent using the LauncherIcon method GetLauncher. But this is
+ * not the case in all the situations. When the user is interacting
+ * with the Switcher, we consider that the parent of that LauncherIcon
+ * is the Switcher.
+ *
+ * The parent is set with atk_object_set_parent as usual.
+ *
+ * As this object is used both on UnityLauncherAccessible and
+ * UnitySwitcherAccessible, we have removed as much as possible any
+ * reference to the Launcher, LauncherModel, SwitcherView or
+ * SwitcherModel.
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-launcher-icon-accessible.h"
+#include "unity-launcher-accessible.h"
+#include "Launcher.h"
+#include "LauncherIcon.h"
+
+#include "unitya11y.h"
+
+using namespace unity::launcher;
+
+/* GObject */
+static void unity_launcher_icon_accessible_class_init(UnityLauncherIconAccessibleClass* klass);
+static void unity_launcher_icon_accessible_init(UnityLauncherIconAccessible* launcher_icon_accessible);
+static void unity_launcher_icon_accessible_dispose(GObject* object);
+
+
+/* AtkObject.h */
+static void unity_launcher_icon_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* unity_launcher_icon_accessible_ref_state_set(AtkObject* obj);
+static const gchar* unity_launcher_icon_accessible_get_name(AtkObject* obj);
+// static AtkObject* unity_launcher_icon_accessible_get_parent(AtkObject* obj);
+static gint unity_launcher_icon_accessible_get_index_in_parent(AtkObject* obj);
+
+/* AtkComponent.h */
+static void atk_component_interface_init(AtkComponentIface* iface);
+static guint unity_launcher_icon_accessible_add_focus_handler(AtkComponent* component,
+ AtkFocusHandler handler);
+static void unity_launcher_icon_accessible_remove_focus_handler(AtkComponent* component,
+ guint handler_id);
+static void unity_launcher_icon_accessible_focus_handler(AtkObject* accessible,
+ gboolean focus_in);
+
+/* AtkAction */
+static void atk_action_interface_init(AtkActionIface *iface);
+static gboolean unity_launcher_icon_accessible_do_action(AtkAction *action,
+ gint i);
+static gint unity_launcher_icon_accessible_get_n_actions(AtkAction *action);
+static const gchar* unity_launcher_icon_accessible_get_name(AtkAction *action,
+ gint i);
+
+/* private/utility methods*/
+static void check_selected(UnityLauncherIconAccessible* self);
+static void on_parent_selection_change_cb(AtkSelection* selection,
+ gpointer data);
+static void on_parent_focus_event_cb(AtkObject* object,
+ gboolean in,
+ gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE(UnityLauncherIconAccessible,
+ unity_launcher_icon_accessible,
+ NUX_TYPE_OBJECT_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT,
+ atk_component_interface_init)
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION,
+ atk_action_interface_init))
+
+#define UNITY_LAUNCHER_ICON_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE, \
+ UnityLauncherIconAccessiblePrivate))
+
+struct _UnityLauncherIconAccessiblePrivate
+{
+ /* Cached values (used to avoid extra notifications) */
+ gboolean selected;
+ gboolean parent_focused;
+ gboolean index_in_parent;
+
+ guint on_parent_change_id;
+ guint on_parent_selection_change_id;
+ guint on_parent_focus_event_id;
+
+ /* A textual representation of the icon's name and its quirks */
+ gchar* name;
+};
+
+static void
+unity_launcher_icon_accessible_class_init(UnityLauncherIconAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->dispose = unity_launcher_icon_accessible_dispose;
+
+ /* AtkObject */
+ atk_class->initialize = unity_launcher_icon_accessible_initialize;
+ atk_class->get_name = unity_launcher_icon_accessible_get_name;
+ atk_class->ref_state_set = unity_launcher_icon_accessible_ref_state_set;
+ // atk_class->get_parent = unity_launcher_icon_accessible_get_parent;
+ atk_class->get_index_in_parent = unity_launcher_icon_accessible_get_index_in_parent;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityLauncherIconAccessiblePrivate));
+}
+
+static void
+unity_launcher_icon_accessible_init(UnityLauncherIconAccessible* launcher_icon_accessible)
+{
+ UnityLauncherIconAccessiblePrivate* priv =
+ UNITY_LAUNCHER_ICON_ACCESSIBLE_GET_PRIVATE(launcher_icon_accessible);
+
+ launcher_icon_accessible->priv = priv;
+ launcher_icon_accessible->priv->name = NULL;
+}
+
+static void
+unity_launcher_icon_accessible_dispose(GObject* object)
+{
+ UnityLauncherIconAccessible* self = UNITY_LAUNCHER_ICON_ACCESSIBLE(object);
+ AtkObject* parent = NULL;
+
+ parent = atk_object_get_parent(ATK_OBJECT(object));
+
+ if (parent != NULL)
+ {
+ if (self->priv->on_parent_selection_change_id != 0)
+ g_signal_handler_disconnect(parent, self->priv->on_parent_selection_change_id);
+
+ if (self->priv->on_parent_focus_event_id != 0)
+ g_signal_handler_disconnect(parent, self->priv->on_parent_focus_event_id);
+ }
+
+ if (self->priv->on_parent_change_id != 0)
+ g_signal_handler_disconnect(object, self->priv->on_parent_change_id);
+
+ if (self->priv->name != NULL)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ G_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->dispose(object);
+}
+
+
+AtkObject*
+unity_launcher_icon_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<LauncherIcon*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+on_parent_change_cb(gchar* property,
+ GValue* value,
+ gpointer data)
+{
+ AtkObject* parent = NULL;
+ UnityLauncherIconAccessible* self = NULL;
+ AtkStateSet* state_set = NULL;
+
+ g_return_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(data));
+
+ self = UNITY_LAUNCHER_ICON_ACCESSIBLE(data);
+ parent = atk_object_get_parent(ATK_OBJECT(data));
+
+ if (parent == NULL)
+ return;
+
+ self->priv->on_parent_selection_change_id =
+ g_signal_connect(parent, "selection-changed",
+ G_CALLBACK(on_parent_selection_change_cb), self);
+
+ self->priv->on_parent_focus_event_id =
+ g_signal_connect(parent, "focus-event",
+ G_CALLBACK(on_parent_focus_event_cb), self);
+
+ state_set = atk_object_ref_state_set(parent);
+ if (atk_state_set_contains_state(state_set, ATK_STATE_FOCUSED))
+ {
+ self->priv->parent_focused = TRUE;
+ }
+ g_object_unref(state_set);
+}
+
+static void
+on_quirks_change_cb(UnityLauncherIconAccessible* self)
+{
+ g_object_notify(G_OBJECT(self), "accessible-name");
+}
+
+static void
+unity_launcher_icon_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ UnityLauncherIconAccessible* self = NULL;
+ nux::Object* object = NULL;
+ LauncherIcon* icon = NULL;
+
+ ATK_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->initialize(accessible, data);
+ self = UNITY_LAUNCHER_ICON_ACCESSIBLE(accessible);
+ object = (nux::Object*) data;
+ icon = dynamic_cast<LauncherIcon*>(object);
+
+ accessible->role = ATK_ROLE_PUSH_BUTTON;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ atk_component_add_focus_handler(ATK_COMPONENT(accessible),
+ unity_launcher_icon_accessible_focus_handler);
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ /* we could do that by redefining ->set_parent */
+ self->priv->on_parent_change_id =
+ g_signal_connect(accessible, "notify::accessible-parent",
+ G_CALLBACK(on_parent_change_cb), self);
+
+ icon->quirks_changed.connect(sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(on_quirks_change_cb), self))));
+ icon->windows_changed.connect(sigc::hide(sigc::bind(sigc::ptr_fun(on_quirks_change_cb), self)));
+}
+
+
+static const gchar*
+unity_launcher_icon_accessible_get_name(AtkObject* obj)
+{
+ UnityLauncherIconAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(obj), NULL);
+ self = UNITY_LAUNCHER_ICON_ACCESSIBLE(obj);
+
+ if (self->priv->name != NULL)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ self->priv->name = g_strdup(ATK_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->get_name(obj));
+ if (self->priv->name == NULL)
+ {
+ LauncherIcon* icon = NULL;
+ Launcher* launcher = NULL;
+
+ icon = dynamic_cast<LauncherIcon*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
+ launcher = dynamic_cast<Launcher*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(atk_object_get_parent(obj))));
+
+ if (icon == NULL) /* State is defunct */
+ self->priv->name = NULL;
+ else
+ {
+ /* We do not want to present the running state of apps in the switcher,
+ * Because showing in the switcher implies they are running
+ */
+ if (launcher == NULL)
+ self->priv->name = g_strdup(icon->tooltip_text().c_str());
+ else
+ {
+ if (icon->GetQuirk(LauncherIcon::Quirk::RUNNING))
+ if (icon->Windows().size() > 0)
+ self->priv->name = g_strdup_printf(_("%s: running: %zu windows open"),
+ icon->tooltip_text().c_str(),
+ icon->Windows().size());
+ else
+ self->priv->name = g_strdup_printf(_("%s: running"), icon->tooltip_text().c_str());
+ else
+ self->priv->name = g_strdup(icon->tooltip_text().c_str());
+ }
+ }
+ }
+
+ return self->priv->name;
+}
+
+static AtkStateSet*
+unity_launcher_icon_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ UnityLauncherIconAccessible* self = NULL;
+ nux::Object* nux_object = NULL;
+ LauncherIcon* icon = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(obj), NULL);
+ self = UNITY_LAUNCHER_ICON_ACCESSIBLE(obj);
+
+ state_set = ATK_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ /* by default */
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+ atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
+
+ icon = dynamic_cast<LauncherIcon*>(nux_object);
+
+ if (icon->GetQuirk(LauncherIcon::Quirk::VISIBLE))
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
+ atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
+ }
+
+ if (self->priv->selected)
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+ atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
+ atk_state_set_add_state(state_set, ATK_STATE_ACTIVE);
+ }
+
+ return state_set;
+}
+
+/* private methods */
+
+/*
+ * Checks if the current item is selected, and notify a selection
+ * change if the selection has changed
+ */
+static void
+check_selected(UnityLauncherIconAccessible* self)
+{
+ AtkObject* parent = NULL;
+ gboolean found = FALSE;
+
+ parent = atk_object_get_parent(ATK_OBJECT(self));
+ if (parent == NULL)
+ return;
+
+ found = atk_selection_is_child_selected(ATK_SELECTION(parent),
+ self->priv->index_in_parent);
+
+ if ((found) && (self->priv->parent_focused == FALSE))
+ return;
+
+ if (found != self->priv->selected)
+ {
+ gboolean return_val = FALSE;
+
+ self->priv->selected = found;
+ atk_object_notify_state_change(ATK_OBJECT(self),
+ ATK_STATE_SELECTED,
+ found);
+ atk_object_notify_state_change(ATK_OBJECT(self),
+ ATK_STATE_ACTIVE,
+ found);
+
+ g_signal_emit_by_name(self, "focus-event", self->priv->selected, &return_val);
+ atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, self->priv->selected);
+ }
+}
+
+static void
+on_parent_selection_change_cb(AtkSelection* selection,
+ gpointer data)
+{
+ g_return_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(data));
+
+ check_selected(UNITY_LAUNCHER_ICON_ACCESSIBLE(data));
+}
+
+
+static void
+on_parent_focus_event_cb(AtkObject* object,
+ gboolean in,
+ gpointer data)
+{
+ UnityLauncherIconAccessible* self = NULL;
+
+ g_return_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(data));
+
+ self = UNITY_LAUNCHER_ICON_ACCESSIBLE(data);
+ self->priv->parent_focused = in;
+
+ /* we check the selection stuff again, to report the focus change
+ now */
+ check_selected(self);
+}
+
+/* AtkComponent.h */
+
+static void
+atk_component_interface_init(AtkComponentIface* iface)
+{
+ g_return_if_fail(iface != NULL);
+
+ /* focus management */
+ iface->add_focus_handler = unity_launcher_icon_accessible_add_focus_handler;
+ iface->remove_focus_handler = unity_launcher_icon_accessible_remove_focus_handler;
+
+ /* FIXME: still missing the size and position methods. Remember that
+ * this is not a nux::Area, and probably we would require to poke
+ * the Launcher to get those positions
+ */
+}
+
+/*
+ * comment C&P from cally-actor:
+ *
+ * "These methods are basically taken from gail, as I don't see any
+ * reason to modify it. It makes me wonder why it is really required
+ * to be implemented in the toolkit"
+ */
+
+static guint
+unity_launcher_icon_accessible_add_focus_handler(AtkComponent* component,
+ AtkFocusHandler handler)
+{
+ GSignalMatchType match_type;
+ gulong ret;
+ guint signal_id;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(component), 0);
+
+ match_type = (GSignalMatchType)(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC);
+ signal_id = g_signal_lookup("focus-event", ATK_TYPE_OBJECT);
+
+ ret = g_signal_handler_find(component, match_type, signal_id, 0, NULL,
+ (gpointer) handler, NULL);
+ if (!ret)
+ {
+ return g_signal_connect_closure_by_id(component,
+ signal_id, 0,
+ g_cclosure_new(G_CALLBACK(handler), NULL,
+ (GClosureNotify) NULL),
+ FALSE);
+ }
+ else
+ return 0;
+}
+
+static void
+unity_launcher_icon_accessible_remove_focus_handler(AtkComponent* component,
+ guint handler_id)
+{
+ g_return_if_fail(NUX_IS_VIEW_ACCESSIBLE(component));
+
+ g_signal_handler_disconnect(component, handler_id);
+}
+
+static void
+unity_launcher_icon_accessible_focus_handler(AtkObject* accessible,
+ gboolean focus_in)
+{
+ g_return_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(accessible));
+
+ atk_object_notify_state_change(accessible, ATK_STATE_FOCUSED, focus_in);
+}
+
+static gint
+unity_launcher_icon_accessible_get_index_in_parent(AtkObject* obj)
+{
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(obj), -1);
+
+ return UNITY_LAUNCHER_ICON_ACCESSIBLE(obj)->priv->index_in_parent;
+}
+
+/* AtkAction */
+static void
+atk_action_interface_init(AtkActionIface *iface)
+{
+ iface->do_action = unity_launcher_icon_accessible_do_action;
+ iface->get_n_actions = unity_launcher_icon_accessible_get_n_actions;
+ iface->get_name = unity_launcher_icon_accessible_get_name;
+}
+
+static gboolean
+unity_launcher_icon_accessible_do_action(AtkAction *action,
+ gint i)
+{
+ LauncherIcon* icon = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(action), FALSE);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(action));
+ if (nux_object == NULL)
+ return FALSE;
+
+ icon = dynamic_cast<LauncherIcon*>(nux_object);
+
+ icon->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0));
+
+ return TRUE;
+}
+
+static gint
+unity_launcher_icon_accessible_get_n_actions(AtkAction *action)
+{
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(action), 0);
+
+ return 1;
+}
+
+static const gchar*
+unity_launcher_icon_accessible_get_name(AtkAction *action,
+ gint i)
+{
+ g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(action), NULL);
+ g_return_val_if_fail(i == 0, NULL);
+
+ return "activate";
+}
+
+/* Public */
+
+void
+unity_launcher_icon_accessible_set_index(UnityLauncherIconAccessible* self,
+ gint index)
+{
+ g_return_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(self));
+
+ self->priv->index_in_parent = index;
+}
diff --git a/a11y/unity-launcher-icon-accessible.h b/a11y/unity-launcher-icon-accessible.h
new file mode 100644
index 000000000..94cd7cc13
--- /dev/null
+++ b/a11y/unity-launcher-icon-accessible.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_LAUNCHER_ICON_ACCESSIBLE_H
+#define UNITY_LAUNCHER_ICON_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-object-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE (unity_launcher_icon_accessible_get_type ())
+#define UNITY_LAUNCHER_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE, UnityLauncherIconAccessible))
+#define UNITY_LAUNCHER_ICON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE, UnityLauncherIconAccessibleClass))
+#define UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE))
+#define UNITY_IS_LAUNCHER_ICON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE))
+#define UNITY_LAUNCHER_ICON_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_LAUNCHER_ICON_ACCESSIBLE, UnityLauncherIconAccessibleClass))
+
+typedef struct _UnityLauncherIconAccessible UnityLauncherIconAccessible;
+typedef struct _UnityLauncherIconAccessibleClass UnityLauncherIconAccessibleClass;
+typedef struct _UnityLauncherIconAccessiblePrivate UnityLauncherIconAccessiblePrivate;
+
+struct _UnityLauncherIconAccessible
+{
+ NuxObjectAccessible parent;
+
+ /*< private >*/
+ UnityLauncherIconAccessiblePrivate* priv;
+};
+
+struct _UnityLauncherIconAccessibleClass
+{
+ NuxObjectAccessibleClass parent_class;
+};
+
+GType unity_launcher_icon_accessible_get_type(void);
+AtkObject* unity_launcher_icon_accessible_new(nux::Object* object);
+
+void unity_launcher_icon_accessible_set_index(UnityLauncherIconAccessible* self,
+ gint index);
+
+G_END_DECLS
+
+#endif /* __UNITY_LAUNCHER_ICON_ACCESSIBLE_H__ */
diff --git a/a11y/unity-panel-view-accessible.cpp b/a11y/unity-panel-view-accessible.cpp
new file mode 100644
index 000000000..4b23e7e4c
--- /dev/null
+++ b/a11y/unity-panel-view-accessible.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Rodrigo Moya <rodrigo.moya@canonical.com>
+ */
+
+/**
+ * SECTION:unity-panel-view-accessible
+ * @Title: UnityPanelViewAccessible
+ * @short_description: Implementation of the ATK interfaces for #PanelView
+ * @see_also: PanelView
+ *
+ * #UnityPanelViewAccessible implements the required ATK interfaces for
+ * #PanelView, ie: exposing the different items contained in the panel
+ * as children.
+ *
+ */
+
+#include "config.h"
+#include "unitya11y.h"
+
+#include <glib/gi18n-lib.h>
+#include <Nux/Nux.h>
+#include "PanelView.h"
+#include "unity-panel-view-accessible.h"
+
+using namespace unity::panel;
+
+/* GObject */
+static void unity_panel_view_accessible_class_init(UnityPanelViewAccessibleClass* klass);
+static void unity_panel_view_accessible_init(UnityPanelViewAccessible* self);
+
+/* AtkObject */
+static void unity_panel_view_accessible_initialize(AtkObject* accessible, gpointer data);
+static gint unity_panel_view_accessible_get_n_children(AtkObject* accessible);
+static AtkObject* unity_panel_view_accessible_ref_child(AtkObject* accessible, gint i);
+
+G_DEFINE_TYPE(UnityPanelViewAccessible, unity_panel_view_accessible, NUX_TYPE_VIEW_ACCESSIBLE)
+
+static void
+unity_panel_view_accessible_class_init(UnityPanelViewAccessibleClass* klass)
+{
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = unity_panel_view_accessible_initialize;
+ atk_class->get_n_children = unity_panel_view_accessible_get_n_children;
+ atk_class->ref_child = unity_panel_view_accessible_ref_child;
+}
+
+static void
+unity_panel_view_accessible_init(UnityPanelViewAccessible* self)
+{
+}
+
+AtkObject*
+unity_panel_view_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible;
+
+ g_return_val_if_fail(dynamic_cast<PanelView*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_PANEL_VIEW_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+static void
+unity_panel_view_accessible_initialize(AtkObject* accessible, gpointer data)
+{
+ ATK_OBJECT_CLASS(unity_panel_view_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_PANEL;
+}
+
+static gint
+unity_panel_view_accessible_get_n_children(AtkObject* accessible)
+{
+ nux::Object* nux_object = NULL;
+ gint rc = 0;
+
+ g_return_val_if_fail(UNITY_IS_PANEL_VIEW_ACCESSIBLE(accessible), 0);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ return rc;
+}
+
+static AtkObject*
+unity_panel_view_accessible_ref_child(AtkObject* accessible, gint i)
+{
+ nux::Object* nux_object = NULL;
+ AtkObject* child_accessible = NULL;
+
+ g_return_val_if_fail(UNITY_IS_PANEL_VIEW_ACCESSIBLE(accessible), NULL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ if (!nux_object) /* state is defunct */
+ return NULL;
+
+ return child_accessible;
+}
diff --git a/a11y/unity-panel-view-accessible.h b/a11y/unity-panel-view-accessible.h
new file mode 100644
index 000000000..dcca2e899
--- /dev/null
+++ b/a11y/unity-panel-view-accessible.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Rodrigo Moya <rodrigo.moya@canonical.com>
+ */
+
+#ifndef UNITY_PANEL_VIEW_ACCESSIBLE_H
+#define UNITY_PANEL_VIEW_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_PANEL_VIEW_ACCESSIBLE (unity_panel_view_accessible_get_type ())
+#define UNITY_PANEL_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_PANEL_VIEW_ACCESSIBLE, UnityPanelViewAccessible))
+#define UNITY_PANEL_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_PANEL_VIEW_ACCESSIBLE, UnityPanelViewAccessibleClass))
+#define UNITY_IS_PANEL_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_PANEL_VIEW_ACCESSIBLE))
+#define UNITY_IS_PANEL_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_PANEL_VIEW_ACCESSIBLE))
+#define UNITY_PANEL_VIEW_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_PANEL_VIEW_ACCESSIBLE, UnityPanelViewAccessibleClass))
+
+typedef struct _UnityPanelViewAccessible UnityPanelViewAccessible;
+typedef struct _UnityPanelViewAccessibleClass UnityPanelViewAccessibleClass;
+
+struct _UnityPanelViewAccessible
+{
+ NuxViewAccessible parent;
+};
+
+struct _UnityPanelViewAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_panel_view_accessible_get_type(void);
+AtkObject* unity_panel_view_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif
diff --git a/a11y/unity-places-group-accessible.cpp b/a11y/unity-places-group-accessible.cpp
new file mode 100644
index 000000000..8abfe78fa
--- /dev/null
+++ b/a11y/unity-places-group-accessible.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-places_group-accessible
+ * @Title: UnityPlacesGroupAccessible
+ * @short_description: Implementation of the ATK interfaces for #PlacesGroup
+ * @see_also: PlacesGroup
+ *
+ * #UnityPlacesGroupAccessible implements the required ATK interfaces for
+ * #PlacesGroup, mainly exposing the text as his name, as this
+ * #object is mainly used as a label
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-places-group-accessible.h"
+
+#include "unitya11y.h"
+#include "PlacesGroup.h"
+
+/* GObject */
+static void unity_places_group_accessible_class_init(UnityPlacesGroupAccessibleClass* klass);
+static void unity_places_group_accessible_init(UnityPlacesGroupAccessible* self);
+
+/* AtkObject.h */
+static void unity_places_group_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+
+G_DEFINE_TYPE(UnityPlacesGroupAccessible, unity_places_group_accessible, NUX_TYPE_VIEW_ACCESSIBLE);
+
+
+#define UNITY_PLACES_GROUP_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_PLACES_GROUP_ACCESSIBLE, \
+ UnityPlacesGroupAccessiblePrivate))
+
+struct _UnityPlacesGroupAccessiblePrivate
+{
+ gchar* stripped_name;
+};
+
+
+static void
+unity_places_group_accessible_class_init(UnityPlacesGroupAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = unity_places_group_accessible_initialize;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityPlacesGroupAccessiblePrivate));
+}
+
+static void
+unity_places_group_accessible_init(UnityPlacesGroupAccessible* self)
+{
+ UnityPlacesGroupAccessiblePrivate* priv =
+ UNITY_PLACES_GROUP_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+ priv->stripped_name = NULL;
+}
+
+AtkObject*
+unity_places_group_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<unity::dash::PlacesGroup*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_PLACES_GROUP_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+/* expand label are usually focused during the key nav, but it don't
+ * get a proper name always. In those cases we use the label.
+ *
+ * In the same way, it is possible that the PlacesGroup get focused
+ * so we also set the own name with this label
+ */
+static void
+ensure_proper_name(UnityPlacesGroupAccessible* self)
+{
+ unity::dash::PlacesGroup* group = NULL;
+ nux::Object* nux_object = NULL;
+ unity::StaticCairoText* label = NULL;
+ unity::StaticCairoText* expand_label = NULL;
+ AtkObject* label_accessible = NULL;
+ AtkObject* expand_label_accessible = NULL;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ group = dynamic_cast<unity::dash::PlacesGroup*>(nux_object);
+
+ if (group == NULL)
+ return;
+
+ label = group->GetLabel();
+ expand_label = group->GetExpandLabel();
+
+
+ label_accessible = unity_a11y_get_accessible(label);
+ expand_label_accessible = unity_a11y_get_accessible(expand_label);
+
+ if ((label_accessible == NULL) || (expand_label_accessible == NULL))
+ return;
+
+ atk_object_set_name(ATK_OBJECT(self), atk_object_get_name(label_accessible));
+
+ if (expand_label->GetText() == "")
+ atk_object_set_name(expand_label_accessible, atk_object_get_name(label_accessible));
+}
+
+
+static void
+on_label_text_change_cb(unity::StaticCairoText* label, UnityPlacesGroupAccessible* self)
+{
+ ensure_proper_name(self);
+}
+
+static void
+unity_places_group_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ unity::dash::PlacesGroup* group = NULL;
+ nux::Object* nux_object = NULL;
+ unity::StaticCairoText* label = NULL;
+
+ ATK_OBJECT_CLASS(unity_places_group_accessible_parent_class)->initialize(accessible, data);
+
+ atk_object_set_role(accessible, ATK_ROLE_PANEL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ group = dynamic_cast<unity::dash::PlacesGroup*>(nux_object);
+
+ if (group == NULL)
+ return;
+
+ label = group->GetLabel();
+
+ if (label == NULL)
+ return;
+
+ ensure_proper_name(UNITY_PLACES_GROUP_ACCESSIBLE(accessible));
+ label->sigTextChanged.connect(sigc::bind(sigc::ptr_fun(on_label_text_change_cb),
+ UNITY_PLACES_GROUP_ACCESSIBLE(accessible)));
+}
+
diff --git a/a11y/unity-places-group-accessible.h b/a11y/unity-places-group-accessible.h
new file mode 100644
index 000000000..594c9a219
--- /dev/null
+++ b/a11y/unity-places-group-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_PLACES_GROUP_ACCESSIBLE_H
+#define UNITY_PLACES_GROUP_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_PLACES_GROUP_ACCESSIBLE (unity_places_group_accessible_get_type ())
+#define UNITY_PLACES_GROUP_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_PLACES_GROUP_ACCESSIBLE, UnityPlacesGroupAccessible))
+#define UNITY_PLACES_GROUP_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_PLACES_GROUP_ACCESSIBLE, UnityPlacesGroupAccessibleClass))
+#define UNITY_IS_PLACES_GROUP_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_PLACES_GROUP_ACCESSIBLE))
+#define UNITY_IS_PLACES_GROUP_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_PLACES_GROUP_ACCESSIBLE))
+#define UNITY_PLACES_GROUP_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_PLACES_GROUP_ACCESSIBLE, UnityPlacesGroupAccessibleClass))
+
+typedef struct _UnityPlacesGroupAccessible UnityPlacesGroupAccessible;
+typedef struct _UnityPlacesGroupAccessibleClass UnityPlacesGroupAccessibleClass;
+typedef struct _UnityPlacesGroupAccessiblePrivate UnityPlacesGroupAccessiblePrivate;
+
+struct _UnityPlacesGroupAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityPlacesGroupAccessiblePrivate* priv;
+};
+
+struct _UnityPlacesGroupAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_places_group_accessible_get_type(void);
+AtkObject* unity_places_group_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_PLACES_GROUP_ACCESSIBLE_H__ */
diff --git a/a11y/unity-quicklist-accessible.cpp b/a11y/unity-quicklist-accessible.cpp
new file mode 100644
index 000000000..eaebd8bf4
--- /dev/null
+++ b/a11y/unity-quicklist-accessible.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-quicklist-accessible
+ * @Title: UnityQuicklistAccessible
+ * @short_description: Implementation of the ATK interfaces for #QuicklistView
+ * @see_also: QuicklistView
+ *
+ * #UnityQuicklistAccessible implements the required ATK interfaces for
+ * #QuicklistView.
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * The desired accessible object hierarchy is the following one:
+ * Role:menu
+ * Role:menu-item
+ * Role:menu-item.
+ *
+ * But this quicklist is also a base window, so we can't set a role
+ * menu, and then keeping it sending window messages.
+ *
+ * So a new object, with role menu will be added to the hierarchy:
+ * QuicklistMenu. It also hide the intermediate container objects.
+ *
+ * So we will have:
+ * Role:window (the quicklist itself)
+ * Role:menu (a dummy object having the role menu)
+ * Role:menuitem (From QuicklistView->GetChildren)
+ * Role:menuitem
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-quicklist-accessible.h"
+#include "unity-quicklist-menu-accessible.h"
+
+#include "unitya11y.h"
+#include "Launcher.h" /*without this I get a error with the following include*/
+#include "QuicklistView.h"
+
+/* GObject */
+static void unity_quicklist_accessible_class_init(UnityQuicklistAccessibleClass* klass);
+static void unity_quicklist_accessible_init(UnityQuicklistAccessible* self);
+
+/* AtkObject.h */
+static void unity_quicklist_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static gint unity_quicklist_accessible_get_n_children(AtkObject* obj);
+static AtkObject* unity_quicklist_accessible_ref_child(AtkObject* obj,
+ gint i);
+
+G_DEFINE_TYPE(UnityQuicklistAccessible, unity_quicklist_accessible, NUX_TYPE_BASE_WINDOW_ACCESSIBLE);
+
+
+#define UNITY_QUICKLIST_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_QUICKLIST_ACCESSIBLE, \
+ UnityQuicklistAccessiblePrivate))
+
+struct _UnityQuicklistAccessiblePrivate
+{
+ AtkObject* menu_accessible;
+};
+
+using unity::QuicklistView;
+
+static void
+unity_quicklist_accessible_class_init(UnityQuicklistAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = unity_quicklist_accessible_initialize;
+ atk_class->get_n_children = unity_quicklist_accessible_get_n_children;
+ atk_class->ref_child = unity_quicklist_accessible_ref_child;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityQuicklistAccessiblePrivate));
+}
+
+static void
+unity_quicklist_accessible_init(UnityQuicklistAccessible* self)
+{
+ UnityQuicklistAccessiblePrivate* priv =
+ UNITY_QUICKLIST_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+ priv->menu_accessible = NULL;
+}
+
+AtkObject*
+unity_quicklist_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<QuicklistView*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_QUICKLIST_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_quicklist_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ QuicklistView* quicklist = NULL;
+
+ ATK_OBJECT_CLASS(unity_quicklist_accessible_parent_class)->initialize(accessible, data);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL) /* status defunct */
+ return;
+}
+
+static gint
+unity_quicklist_accessible_get_n_children(AtkObject* obj)
+{
+ QuicklistView* quicklist = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_ACCESSIBLE(obj), 0);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL)
+ return 0;
+ else
+ return 1;
+}
+
+static AtkObject*
+unity_quicklist_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ UnityQuicklistAccessible* self = NULL;
+ QuicklistView* quicklist = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_ACCESSIBLE(obj), NULL);
+ self = UNITY_QUICKLIST_ACCESSIBLE(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+ if (quicklist == NULL)
+ return NULL;
+
+ if (self->priv->menu_accessible == NULL)
+ {
+ self->priv->menu_accessible = unity_quicklist_menu_accessible_new(quicklist);
+ atk_object_set_parent(self->priv->menu_accessible, ATK_OBJECT(self));
+ }
+
+ g_object_ref(self->priv->menu_accessible);
+
+ return self->priv->menu_accessible;
+}
diff --git a/a11y/unity-quicklist-accessible.h b/a11y/unity-quicklist-accessible.h
new file mode 100644
index 000000000..e1a30b85c
--- /dev/null
+++ b/a11y/unity-quicklist-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_QUICKLIST_ACCESSIBLE_H
+#define UNITY_QUICKLIST_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-base-window-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_QUICKLIST_ACCESSIBLE (unity_quicklist_accessible_get_type ())
+#define UNITY_QUICKLIST_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_QUICKLIST_ACCESSIBLE, UnityQuicklistAccessible))
+#define UNITY_QUICKLIST_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_QUICKLIST_ACCESSIBLE, UnityQuicklistAccessibleClass))
+#define UNITY_IS_QUICKLIST_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_QUICKLIST_ACCESSIBLE))
+#define UNITY_IS_QUICKLIST_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_QUICKLIST_ACCESSIBLE))
+#define UNITY_QUICKLIST_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_QUICKLIST_ACCESSIBLE, UnityQuicklistAccessibleClass))
+
+typedef struct _UnityQuicklistAccessible UnityQuicklistAccessible;
+typedef struct _UnityQuicklistAccessibleClass UnityQuicklistAccessibleClass;
+typedef struct _UnityQuicklistAccessiblePrivate UnityQuicklistAccessiblePrivate;
+
+struct _UnityQuicklistAccessible
+{
+ NuxBaseWindowAccessible parent;
+
+ /*< private >*/
+ UnityQuicklistAccessiblePrivate* priv;
+};
+
+struct _UnityQuicklistAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_quicklist_accessible_get_type(void);
+AtkObject* unity_quicklist_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_QUICKLIST_ACCESSIBLE_H__ */
diff --git a/a11y/unity-quicklist-menu-accessible.cpp b/a11y/unity-quicklist-menu-accessible.cpp
new file mode 100644
index 000000000..8967b4738
--- /dev/null
+++ b/a11y/unity-quicklist-menu-accessible.cpp
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-quicklist-accessible
+ * @Title: UnityQuicklistMenuAccessible
+ * @short_description: Implementation of the ATK interfaces for #QuicklistView as a menu
+ * @see_also: QuicklistView
+ *
+ * #UnityQuicklistAccessible implements the required ATK interfaces for
+ * #QuicklistView, exposing himself as a menu.
+ *
+ * Note that this object is a QuicklistAccessible delegated object. If
+ * you call unitya11y->get_accessible with a Quicklist it will return
+ * a QuicklistAccessible. QuicklistMenuAccessible should only be
+ * instantiated by QuicklistAccessible
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * The desired accessible object hierarchy is the following one:
+ * Role:menu
+ * Role:menu-item
+ * Role:menu-item.
+ *
+ * But this quicklist is also a base window, so we can't set a role
+ * menu, and then keeping it sending window messages.
+ *
+ * So a new object, with role menu will be added to the hierarchy:
+ * QuicklistMenu. It also hide the intermediate container objects.
+ *
+ * So we will have:
+ * Role:window (the quicklist itself)
+ * Role:menu (a dummy object having the role menu)
+ * Role:menuitem (From QuicklistView->GetChildren)
+ * Role:menuitem
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-quicklist-menu-accessible.h"
+
+#include "unitya11y.h"
+#include "Launcher.h" /*without this I get a error with the following include*/
+#include "QuicklistView.h"
+
+/* GObject */
+static void unity_quicklist_menu_accessible_class_init(UnityQuicklistMenuAccessibleClass* klass);
+static void unity_quicklist_menu_accessible_init(UnityQuicklistMenuAccessible* self);
+static void unity_quicklist_menu_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_quicklist_menu_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static gint unity_quicklist_menu_accessible_get_n_children(AtkObject* obj);
+static AtkObject* unity_quicklist_menu_accessible_ref_child(AtkObject* obj,
+ gint i);
+
+/* AtkSelection */
+static void atk_selection_interface_init(AtkSelectionIface* iface);
+static AtkObject* unity_quicklist_menu_accessible_ref_selection(AtkSelection* selection,
+ gint i);
+static gint unity_quicklist_menu_accessible_get_selection_count(AtkSelection* selection);
+static gboolean unity_quicklist_menu_accessible_is_child_selected(AtkSelection* selection,
+ gint i);
+/* private */
+static void on_selection_change_cb(UnityQuicklistMenuAccessible* self);
+static void on_parent_activate_change_cb(AtkObject* parent_window,
+ UnityQuicklistMenuAccessible* self);
+static void on_parent_change_cb(gchar* property,
+ GValue* value,
+ gpointer data);
+
+G_DEFINE_TYPE_WITH_CODE(UnityQuicklistMenuAccessible,
+ unity_quicklist_menu_accessible, NUX_TYPE_OBJECT_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init));
+
+
+#define UNITY_QUICKLIST_MENU_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE, \
+ UnityQuicklistMenuAccessiblePrivate))
+
+struct _UnityQuicklistMenuAccessiblePrivate
+{
+ sigc::connection on_selection_change_connection;
+ guint on_parent_change_id;
+ guint on_parent_activate_change_id;
+};
+
+using unity::QuicklistView;
+using unity::QuicklistMenuItem;
+
+static void
+unity_quicklist_menu_accessible_class_init(UnityQuicklistMenuAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = unity_quicklist_menu_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->initialize = unity_quicklist_menu_accessible_initialize;
+ atk_class->get_n_children = unity_quicklist_menu_accessible_get_n_children;
+ atk_class->ref_child = unity_quicklist_menu_accessible_ref_child;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityQuicklistMenuAccessiblePrivate));
+}
+
+static void
+unity_quicklist_menu_accessible_init(UnityQuicklistMenuAccessible* self)
+{
+ UnityQuicklistMenuAccessiblePrivate* priv =
+ UNITY_QUICKLIST_MENU_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+}
+
+static void
+unity_quicklist_menu_accessible_finalize(GObject* object)
+{
+ UnityQuicklistMenuAccessible* self = UNITY_QUICKLIST_MENU_ACCESSIBLE(object);
+
+ self->priv->on_selection_change_connection.disconnect();
+
+ if (self->priv->on_parent_change_id != 0)
+ g_signal_handler_disconnect(object, self->priv->on_parent_change_id);
+
+ G_OBJECT_CLASS(unity_quicklist_menu_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_quicklist_menu_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<QuicklistView*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_quicklist_menu_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ QuicklistView* quicklist = NULL;
+ UnityQuicklistMenuAccessible* self = NULL;
+
+ ATK_OBJECT_CLASS(unity_quicklist_menu_accessible_parent_class)->initialize(accessible, data);
+ self = UNITY_QUICKLIST_MENU_ACCESSIBLE(accessible);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL) /* status defunct */
+ return;
+
+ atk_object_set_role(accessible, ATK_ROLE_MENU);
+ atk_object_set_name(accessible, _("Quicklist"));
+
+ self->priv->on_selection_change_connection =
+ quicklist->selection_change.connect(sigc::bind(sigc::ptr_fun(on_selection_change_cb), self));
+
+ self->priv->on_parent_change_id =
+ g_signal_connect(accessible, "notify::accessible-parent",
+ G_CALLBACK(on_parent_change_cb), self);
+}
+
+static gint
+unity_quicklist_menu_accessible_get_n_children(AtkObject* obj)
+{
+ QuicklistView* quicklist = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(obj), 0);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL)
+ return 0;
+
+ return quicklist->GetNumItems();
+}
+
+static AtkObject*
+unity_quicklist_menu_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ QuicklistView* quicklist = NULL;
+ QuicklistMenuItem* child = NULL;
+ AtkObject* child_accessible = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(obj), NULL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL)
+ return NULL;
+
+ child = quicklist->GetNthItems(i);
+ child_accessible = unity_a11y_get_accessible(child);
+
+ if (child_accessible != NULL)
+ {
+ AtkObject* parent = NULL;
+ g_object_ref(child_accessible);
+ parent = atk_object_get_parent(child_accessible);
+ if (parent != obj)
+ atk_object_set_parent(child_accessible, obj);
+ }
+
+ return child_accessible;
+}
+
+/* AtkSelection */
+static void
+atk_selection_interface_init(AtkSelectionIface* iface)
+{
+ iface->ref_selection = unity_quicklist_menu_accessible_ref_selection;
+ iface->get_selection_count = unity_quicklist_menu_accessible_get_selection_count;
+ iface->is_child_selected = unity_quicklist_menu_accessible_is_child_selected;
+
+ /* NOTE: for the moment we don't provide the implementation for the
+ "interactable" methods, it is, the methods that allow to change
+ the selected icon. The QuicklistView doesn't provide that API, and
+ right now we are focusing on a normal user input.*/
+}
+
+static AtkObject*
+unity_quicklist_menu_accessible_ref_selection(AtkSelection* selection,
+ gint i)
+{
+ QuicklistView* quicklist = NULL;
+ QuicklistMenuItem* child = NULL;
+ AtkObject* child_accessible = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(selection), NULL);
+ /* there can be only one item selected */
+ g_return_val_if_fail(i == 0, NULL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL) /*state is defunct */
+ return NULL;
+
+ child = quicklist->GetSelectedMenuItem();
+
+ if (child != NULL)
+ {
+ child_accessible = unity_a11y_get_accessible(child);
+
+ if (child_accessible != NULL)
+ g_object_ref(child_accessible);
+ }
+
+ return child_accessible;
+}
+
+static gint
+unity_quicklist_menu_accessible_get_selection_count(AtkSelection* selection)
+{
+ QuicklistView* quicklist = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(selection), 0);
+
+ /*
+ * Looking at QuicklistView code, there is always one item selected,
+ * anyway we check that there is at least one item
+ */
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL) /*state is defunct */
+ return 0;
+
+ if (quicklist->GetNumItems() > 0)
+ return 1;
+ else
+ return 0;
+}
+
+static gboolean
+unity_quicklist_menu_accessible_is_child_selected(AtkSelection* selection,
+ gint i)
+{
+ QuicklistView* quicklist = NULL;
+ QuicklistMenuItem* selected = NULL;
+ QuicklistMenuItem* ith_item = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(selection), FALSE);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ quicklist = dynamic_cast<QuicklistView*>(nux_object);
+
+ if (quicklist == NULL) /*state is defunct */
+ return FALSE;
+
+ selected = quicklist->GetSelectedMenuItem();
+ ith_item = quicklist->GetNthItems(i);
+
+ if (selected == ith_item)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* private */
+static void
+on_selection_change_cb(UnityQuicklistMenuAccessible* self)
+{
+ g_signal_emit_by_name(ATK_OBJECT(self), "selection-changed");
+}
+
+static void
+on_parent_activate_change_cb(AtkObject* parent_window,
+ UnityQuicklistMenuAccessible* self)
+{
+ /* We consider that when our parent window is activated, the focus
+ should be on the menu, specifically on one of the menu-item. So
+ we emit a selection-change in order to notify that a selection
+ was made */
+ g_signal_emit_by_name(ATK_OBJECT(self), "selection-changed");
+}
+
+
+static void
+on_parent_change_cb(gchar* property,
+ GValue* value,
+ gpointer data)
+{
+ AtkObject* parent = NULL;
+ UnityQuicklistMenuAccessible* self = NULL;
+
+ g_return_if_fail(UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(data));
+ self = UNITY_QUICKLIST_MENU_ACCESSIBLE(data);
+
+ parent = atk_object_get_parent(ATK_OBJECT(self));
+
+ if (parent == NULL)
+ return;
+
+ self->priv->on_parent_activate_change_id =
+ g_signal_connect(parent, "activate",
+ G_CALLBACK(on_parent_activate_change_cb), self);
+}
+
diff --git a/a11y/unity-quicklist-menu-accessible.h b/a11y/unity-quicklist-menu-accessible.h
new file mode 100644
index 000000000..99aeab75a
--- /dev/null
+++ b/a11y/unity-quicklist-menu-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_QUICKLIST_MENU_ACCESSIBLE_H
+#define UNITY_QUICKLIST_MENU_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-base-window-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE (unity_quicklist_menu_accessible_get_type ())
+#define UNITY_QUICKLIST_MENU_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE, UnityQuicklistMenuAccessible))
+#define UNITY_QUICKLIST_MENU_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE, UnityQuicklistMenuAccessibleClass))
+#define UNITY_IS_QUICKLIST_MENU_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE))
+#define UNITY_IS_QUICKLIST_MENU_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE))
+#define UNITY_QUICKLIST_MENU_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_QUICKLIST_MENU_ACCESSIBLE, UnityQuicklistMenuAccessibleClass))
+
+typedef struct _UnityQuicklistMenuAccessible UnityQuicklistMenuAccessible;
+typedef struct _UnityQuicklistMenuAccessibleClass UnityQuicklistMenuAccessibleClass;
+typedef struct _UnityQuicklistMenuAccessiblePrivate UnityQuicklistMenuAccessiblePrivate;
+
+struct _UnityQuicklistMenuAccessible
+{
+ NuxObjectAccessible parent;
+
+ /*< private >*/
+ UnityQuicklistMenuAccessiblePrivate* priv;
+};
+
+struct _UnityQuicklistMenuAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_quicklist_menu_accessible_get_type(void);
+AtkObject* unity_quicklist_menu_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_QUICKLIST_MENU_ACCESSIBLE_H__ */
diff --git a/a11y/unity-quicklist-menu-item-accessible.cpp b/a11y/unity-quicklist-menu-item-accessible.cpp
new file mode 100644
index 000000000..97bc898cc
--- /dev/null
+++ b/a11y/unity-quicklist-menu-item-accessible.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-quicklist_menu_item-accessible
+ * @Title: UnityQuicklistMenuItemAccessible
+ * @short_description: Implementation of the ATK interfaces for #QuicklistMenuItem
+ * @see_also: QuicklistMenuItem
+ *
+ * #UnityQuicklistMenuItemAccessible implements the required ATK interfaces for
+ * #QuicklistMenuItem, mainly exposing the text as his name, as this
+ * #object is mainly used as a label
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-quicklist-menu-item-accessible.h"
+
+#include "unitya11y.h"
+#include "QuicklistMenuItem.h"
+#include "QuicklistMenuItemLabel.h"
+#include "QuicklistMenuItemSeparator.h"
+
+/* GObject */
+static void unity_quicklist_menu_item_accessible_class_init(UnityQuicklistMenuItemAccessibleClass* klass);
+static void unity_quicklist_menu_item_accessible_init(UnityQuicklistMenuItemAccessible* self);
+static void unity_quicklist_menu_item_accessible_dispose(GObject* object);
+
+/* AtkObject.h */
+static void unity_quicklist_menu_item_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static const gchar* unity_quicklist_menu_item_accessible_get_name(AtkObject* obj);
+static AtkStateSet* unity_quicklist_menu_item_accessible_ref_state_set(AtkObject* obj);
+
+/* private */
+static void on_parent_selection_change_cb(AtkSelection* selection,
+ gpointer data);
+
+G_DEFINE_TYPE(UnityQuicklistMenuItemAccessible, unity_quicklist_menu_item_accessible, NUX_TYPE_VIEW_ACCESSIBLE);
+
+
+#define UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE, \
+ UnityQuicklistMenuItemAccessiblePrivate))
+
+struct _UnityQuicklistMenuItemAccessiblePrivate
+{
+ gboolean selected;
+
+ guint on_parent_selection_change_id;
+ guint on_parent_change_id;
+
+ gchar *name;
+};
+
+using unity::QuicklistMenuItem;
+using unity::QuicklistMenuItemLabel;
+using unity::QuicklistMenuItemSeparator;
+
+static void
+unity_quicklist_menu_item_accessible_class_init(UnityQuicklistMenuItemAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->dispose = unity_quicklist_menu_item_accessible_dispose;
+
+ /* AtkObject */
+ atk_class->get_name = unity_quicklist_menu_item_accessible_get_name;
+ atk_class->initialize = unity_quicklist_menu_item_accessible_initialize;
+ atk_class->ref_state_set = unity_quicklist_menu_item_accessible_ref_state_set;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityQuicklistMenuItemAccessiblePrivate));
+}
+
+static void
+unity_quicklist_menu_item_accessible_init(UnityQuicklistMenuItemAccessible* self)
+{
+ UnityQuicklistMenuItemAccessiblePrivate* priv =
+ UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+ self->priv->name = NULL;
+}
+
+static void
+unity_quicklist_menu_item_accessible_dispose(GObject* object)
+{
+ UnityQuicklistMenuItemAccessible* self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(object);
+ AtkObject* parent = NULL;
+
+ parent = atk_object_get_parent(ATK_OBJECT(object));
+
+ if (UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(parent))
+ {
+ if (self->priv->on_parent_selection_change_id != 0)
+ g_signal_handler_disconnect(parent, self->priv->on_parent_selection_change_id);
+ }
+
+ if (self->priv->on_parent_change_id != 0)
+ g_signal_handler_disconnect(object, self->priv->on_parent_change_id);
+
+ if (self->priv->name != NULL)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ G_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->dispose(object);
+}
+
+AtkObject*
+unity_quicklist_menu_item_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<QuicklistMenuItem*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static gboolean
+menu_item_is_a_separator(QuicklistMenuItem* menu_item)
+{
+ QuicklistMenuItemSeparator* separator = NULL;
+
+ separator = dynamic_cast<QuicklistMenuItemSeparator*>(menu_item);
+
+ if (separator != NULL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+on_parent_change_cb(gchar* property,
+ GValue* value,
+ gpointer data)
+{
+ AtkObject* parent = NULL;
+ UnityQuicklistMenuItemAccessible* self = NULL;
+
+ g_return_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(data));
+ self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(data);
+
+ parent = atk_object_get_parent(ATK_OBJECT(self));
+
+ if (parent == NULL)
+ return;
+
+ self->priv->on_parent_selection_change_id =
+ g_signal_connect(parent, "selection-changed",
+ G_CALLBACK(on_parent_selection_change_cb), self);
+}
+
+static void
+unity_quicklist_menu_item_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ QuicklistMenuItem* menu_item = NULL;
+ UnityQuicklistMenuItemAccessible* self = NULL;
+
+ ATK_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->initialize(accessible, data);
+ self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(accessible);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ menu_item = dynamic_cast<QuicklistMenuItem*>(nux_object);
+
+ if (menu_item == NULL)
+ return;
+
+ if (menu_item_is_a_separator(menu_item))
+ atk_object_set_role(accessible, ATK_ROLE_SEPARATOR);
+ else
+ atk_object_set_role(accessible, ATK_ROLE_MENU_ITEM);
+
+ /* we could do that by redefining ->set_parent */
+ self->priv->on_parent_change_id =
+ g_signal_connect(accessible, "notify::accessible-parent",
+ G_CALLBACK(on_parent_change_cb), self);
+}
+
+
+
+static const gchar*
+unity_quicklist_menu_item_accessible_get_name(AtkObject* obj)
+{
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj), NULL);
+ UnityQuicklistMenuItemAccessible *self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj);
+
+ if (self->priv->name)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ self->priv->name = g_strdup(ATK_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->get_name(obj));
+ if (self->priv->name == NULL)
+ {
+ QuicklistMenuItem* menu_item = NULL;
+
+ menu_item = dynamic_cast<QuicklistMenuItem*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
+ if (menu_item != NULL)
+ {
+ self->priv->name = g_strdup(menu_item->GetPlainTextLabel().c_str());
+ }
+ }
+
+ return self->priv->name;
+}
+
+static AtkStateSet*
+unity_quicklist_menu_item_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ UnityQuicklistMenuItemAccessible* self = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj), NULL);
+ self = UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj);
+
+ state_set = ATK_OBJECT_CLASS(unity_quicklist_menu_item_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ /* by default */
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+ atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
+
+ if (self->priv->selected)
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+ atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
+ atk_state_set_add_state(state_set, ATK_STATE_ACTIVE);
+ }
+ else
+ {
+ /* we clean the states that could come from NuxAreaAccessible */
+ atk_state_set_remove_state(state_set, ATK_STATE_FOCUSED);
+ }
+
+ return state_set;
+}
+
+/* private */
+static void
+check_selected(UnityQuicklistMenuItemAccessible* self)
+{
+ AtkObject* selected_item = NULL;
+ AtkObject* parent = NULL;
+ nux::Object* nux_object = NULL;
+ gboolean found = FALSE;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (nux_object == NULL) /* state is defunct */
+ return;
+
+ parent = atk_object_get_parent(ATK_OBJECT(self));
+ if (parent == NULL)
+ return;
+
+ selected_item = atk_selection_ref_selection(ATK_SELECTION(parent), 0);
+
+ if (ATK_OBJECT(self) == selected_item)
+ found = TRUE;
+
+ if (found != self->priv->selected)
+ {
+ gboolean return_val = FALSE;
+
+ self->priv->selected = found;
+ atk_object_notify_state_change(ATK_OBJECT(self),
+ ATK_STATE_FOCUSED,
+ found);
+ atk_object_notify_state_change(ATK_OBJECT(self),
+ ATK_STATE_SELECTED,
+ found);
+ atk_object_notify_state_change(ATK_OBJECT(self),
+ ATK_STATE_ACTIVE,
+ found);
+
+ g_signal_emit_by_name(self, "focus-event", self->priv->selected, &return_val);
+ }
+}
+
+static void
+on_parent_selection_change_cb(AtkSelection* selection,
+ gpointer data)
+{
+ g_return_if_fail(UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(data));
+
+ check_selected(UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(data));
+}
diff --git a/a11y/unity-quicklist-menu-item-accessible.h b/a11y/unity-quicklist-menu-item-accessible.h
new file mode 100644
index 000000000..5c0c2b3b1
--- /dev/null
+++ b/a11y/unity-quicklist-menu-item-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_H
+#define UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE (unity_quicklist_menu_item_accessible_get_type ())
+#define UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE, UnityQuicklistMenuItemAccessible))
+#define UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE, UnityQuicklistMenuItemAccessibleClass))
+#define UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE))
+#define UNITY_IS_QUICKLIST_MENU_ITEM_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE))
+#define UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_QUICKLIST_MENU_ITEM_ACCESSIBLE, UnityQuicklistMenuItemAccessibleClass))
+
+typedef struct _UnityQuicklistMenuItemAccessible UnityQuicklistMenuItemAccessible;
+typedef struct _UnityQuicklistMenuItemAccessibleClass UnityQuicklistMenuItemAccessibleClass;
+typedef struct _UnityQuicklistMenuItemAccessiblePrivate UnityQuicklistMenuItemAccessiblePrivate;
+
+struct _UnityQuicklistMenuItemAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityQuicklistMenuItemAccessiblePrivate* priv;
+};
+
+struct _UnityQuicklistMenuItemAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_quicklist_menu_item_accessible_get_type(void);
+AtkObject* unity_quicklist_menu_item_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_QUICKLIST_MENU_ITEM_ACCESSIBLE_H__ */
diff --git a/a11y/unity-result-accessible.cpp b/a11y/unity-result-accessible.cpp
new file mode 100644
index 000000000..b2f431e18
--- /dev/null
+++ b/a11y/unity-result-accessible.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:nux-result-accessible
+ * @Title: UnityResultAccessible
+ * @short_description: Implementation of the ATK interfaces for a #Result
+ * @see_also: unity::dash::Result
+ *
+ * #UnityResultAccessible implements the required ATK interfaces of
+ * nux::Result, in order to represent each one of the elements of a
+ * ResultGrid.
+ *
+ * The idea is having it as a fly-weight object. Note: it represents
+ * it, but it doesn't maintain a reference to it.
+ *
+ */
+
+#include "unity-result-accessible.h"
+#include "unity-rvgrid-accessible.h"
+
+#include "unitya11y.h"
+
+/* GObject */
+static void unity_result_accessible_class_init(UnityResultAccessibleClass* klass);
+static void unity_result_accessible_init(UnityResultAccessible* result_accessible);
+
+/* AtkObject.h */
+static void unity_result_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* unity_result_accessible_ref_state_set(AtkObject* obj);
+
+G_DEFINE_TYPE(UnityResultAccessible,
+ unity_result_accessible,
+ ATK_TYPE_OBJECT);
+
+#define UNITY_RESULT_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_RESULT_ACCESSIBLE, \
+ UnityResultAccessiblePrivate))
+
+struct _UnityResultAccessiblePrivate
+{
+};
+
+static void
+unity_result_accessible_class_init(UnityResultAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = unity_result_accessible_initialize;
+ atk_class->ref_state_set = unity_result_accessible_ref_state_set;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityResultAccessiblePrivate));
+}
+
+static void
+unity_result_accessible_init(UnityResultAccessible* result_accessible)
+{
+ UnityResultAccessiblePrivate* priv =
+ UNITY_RESULT_ACCESSIBLE_GET_PRIVATE(result_accessible);
+
+ result_accessible->priv = priv;
+}
+
+AtkObject*
+unity_result_accessible_new()
+{
+ AtkObject* accessible = NULL;
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_RESULT_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, NULL);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_result_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ ATK_OBJECT_CLASS(unity_result_accessible_parent_class)->initialize(accessible, data);
+
+ /* On unity Result is just data, but on the accessible
+ implementation we are using this object to represent each icon
+ selected on the result grid, so a push button */
+ atk_object_set_role(accessible, ATK_ROLE_PUSH_BUTTON);
+}
+
+static AtkStateSet*
+unity_result_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+
+ g_return_val_if_fail(UNITY_IS_RESULT_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(unity_result_accessible_parent_class)->ref_state_set(obj);
+
+ /* by default, this is a fly-weight/dummy object, so if created we have
+ this information */
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+ atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
+
+ atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
+ atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
+
+ /* This object is not focused, the focused is the parent
+ ResultViewGrid */
+ // atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+ atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
+ atk_state_set_add_state(state_set, ATK_STATE_ACTIVE);
+
+ return state_set;
+}
diff --git a/a11y/unity-result-accessible.h b/a11y/unity-result-accessible.h
new file mode 100644
index 000000000..764a4c70c
--- /dev/null
+++ b/a11y/unity-result-accessible.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_LAUNCHER_ICON_ACCESSIBLE_H
+#define UNITY_LAUNCHER_ICON_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_RESULT_ACCESSIBLE (unity_result_accessible_get_type ())
+#define UNITY_RESULT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_RESULT_ACCESSIBLE, UnityResultAccessible))
+#define UNITY_RESULT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_RESULT_ACCESSIBLE, UnityResultAccessibleClass))
+#define UNITY_IS_RESULT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_RESULT_ACCESSIBLE))
+#define UNITY_IS_RESULT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_RESULT_ACCESSIBLE))
+#define UNITY_RESULT_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_RESULT_ACCESSIBLE, UnityResultAccessibleClass))
+
+typedef struct _UnityResultAccessible UnityResultAccessible;
+typedef struct _UnityResultAccessibleClass UnityResultAccessibleClass;
+typedef struct _UnityResultAccessiblePrivate UnityResultAccessiblePrivate;
+
+struct _UnityResultAccessible
+{
+ AtkObject parent;
+
+ /*< private >*/
+ UnityResultAccessiblePrivate* priv;
+};
+
+struct _UnityResultAccessibleClass
+{
+ AtkObjectClass parent_class;
+};
+
+GType unity_result_accessible_get_type(void);
+AtkObject* unity_result_accessible_new();
+
+
+G_END_DECLS
+
+#endif /* __UNITY_RESULT_ACCESSIBLE_H__ */
diff --git a/a11y/unity-root-accessible.cpp b/a11y/unity-root-accessible.cpp
new file mode 100644
index 000000000..92dd63cd9
--- /dev/null
+++ b/a11y/unity-root-accessible.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-accessible-root
+ * @short_description: Root object for the UNITY accessible support
+ *
+ * #UnityRootAccessible is the root object of the accessibility
+ * tree-like hierarchy, exposing the application level. You can see it
+ * as the one exposing UnityScreen information to the a11y framework
+ *
+ */
+
+#include "unity-root-accessible.h"
+#include "unity-util-accessible.h"
+#include "nux-base-window-accessible.h"
+#include "unitya11y.h"
+
+#include <UnityCore/Variant.h>
+
+#include "UBusWrapper.h"
+#include "UBusMessages.h"
+
+/* GObject */
+static void unity_root_accessible_class_init(UnityRootAccessibleClass* klass);
+static void unity_root_accessible_init(UnityRootAccessible* root);
+static void unity_root_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_root_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static gint unity_root_accessible_get_n_children(AtkObject* obj);
+static AtkObject* unity_root_accessible_ref_child(AtkObject* obj,
+ gint i);
+static AtkObject* unity_root_accessible_get_parent(AtkObject* obj);
+/* private */
+static void check_active_window(UnityRootAccessible* self);
+static void register_interesting_messages(UnityRootAccessible* self);
+static void add_window(UnityRootAccessible* self,
+ nux::BaseWindow* window);
+static void remove_window(UnityRootAccessible* self,
+ nux::BaseWindow* window);
+
+#define UNITY_ROOT_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_ROOT_ACCESSIBLE, UnityRootAccessiblePrivate))
+
+G_DEFINE_TYPE(UnityRootAccessible, unity_root_accessible, ATK_TYPE_OBJECT)
+
+struct _UnityRootAccessiblePrivate
+{
+ /* we save on window_list the accessible object for the windows
+ registered */
+ GSList* window_list;
+ nux::BaseWindow* active_window;
+ nux::BaseWindow* launcher_window;
+};
+
+static void
+unity_root_accessible_class_init(UnityRootAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = unity_root_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->get_n_children = unity_root_accessible_get_n_children;
+ atk_class->ref_child = unity_root_accessible_ref_child;
+ atk_class->get_parent = unity_root_accessible_get_parent;
+ atk_class->initialize = unity_root_accessible_initialize;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityRootAccessiblePrivate));
+}
+
+static void
+unity_root_accessible_init(UnityRootAccessible* root)
+{
+ root->priv = UNITY_ROOT_ACCESSIBLE_GET_PRIVATE(root);
+
+ root->priv->window_list = NULL;
+ root->priv->active_window = NULL;
+ root->priv->launcher_window = NULL;
+}
+
+AtkObject*
+unity_root_accessible_new(void)
+{
+ AtkObject* accessible = NULL;
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_ROOT_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, NULL);
+
+ return accessible;
+}
+
+static void
+unity_root_accessible_finalize(GObject* object)
+{
+ UnityRootAccessible* root = UNITY_ROOT_ACCESSIBLE(object);
+
+ g_return_if_fail(UNITY_IS_ROOT_ACCESSIBLE(object));
+
+ if (root->priv->window_list)
+ {
+ g_slist_free_full(root->priv->window_list, g_object_unref);
+ root->priv->window_list = NULL;
+ }
+
+ G_OBJECT_CLASS(unity_root_accessible_parent_class)->finalize(object);
+}
+
+/* AtkObject.h */
+static void
+unity_root_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ accessible->role = ATK_ROLE_APPLICATION;
+
+ // FIXME: compiz doesn't set the program name using g_set_prgname,
+ // and AFAIK, there isn't a way to get it. Requires further investigation.
+ // accessible->name = g_get_prgname();
+ atk_object_set_name(accessible, "unity");
+ atk_object_set_parent(accessible, NULL);
+
+ register_interesting_messages(UNITY_ROOT_ACCESSIBLE(accessible));
+
+ ATK_OBJECT_CLASS(unity_root_accessible_parent_class)->initialize(accessible, data);
+}
+
+static gint
+unity_root_accessible_get_n_children(AtkObject* obj)
+{
+ UnityRootAccessible* root = UNITY_ROOT_ACCESSIBLE(obj);
+
+ return g_slist_length(root->priv->window_list);
+}
+
+static AtkObject*
+unity_root_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ UnityRootAccessible* root = NULL;
+ gint num = 0;
+ AtkObject* item = NULL;
+
+ root = UNITY_ROOT_ACCESSIBLE(obj);
+ num = atk_object_get_n_accessible_children(obj);
+ g_return_val_if_fail((i < num) && (i >= 0), NULL);
+
+ item = ATK_OBJECT(g_slist_nth_data(root->priv->window_list, i));
+
+ if (!item)
+ return NULL;
+
+ g_object_ref(item);
+
+ return item;
+}
+
+static AtkObject*
+unity_root_accessible_get_parent(AtkObject* obj)
+{
+ return NULL;
+}
+
+
+/* private */
+/*
+ * Call all the children (NuxBaseWindowAccessible) to check if they
+ * are in the proper active or deactive status.
+ */
+static void
+check_active_window(UnityRootAccessible* self)
+{
+ GSList* iter = NULL;
+ NuxBaseWindowAccessible* window = NULL;
+
+ for (iter = self->priv->window_list; iter != NULL; iter = g_slist_next(iter))
+ {
+ window = NUX_BASE_WINDOW_ACCESSIBLE(iter->data);
+ nux_base_window_accessible_check_active(window, self->priv->active_window);
+ }
+}
+
+/*
+ * It adds a window to the internal window_list managed by the Root object
+ *
+ * Checks if the object is already present. Adds a reference to the
+ * accessible object of the window.
+ */
+static void
+add_window(UnityRootAccessible* self,
+ nux::BaseWindow* window)
+{
+ AtkObject* window_accessible = NULL;
+ gint index = 0;
+
+ g_return_if_fail(UNITY_IS_ROOT_ACCESSIBLE(self));
+
+ window_accessible =
+ unity_a11y_get_accessible(window);
+
+ /* FIXME: temporal */
+ atk_object_set_name (window_accessible, window->GetWindowName().c_str());
+
+ if (g_slist_find(self->priv->window_list, window_accessible))
+ return;
+
+ self->priv->window_list =
+ g_slist_append(self->priv->window_list, window_accessible);
+ g_object_ref(window_accessible);
+
+ index = g_slist_index(self->priv->window_list, window_accessible);
+
+ explore_children(window_accessible);
+
+ g_signal_emit_by_name(self, "children-changed::add",
+ index, window_accessible, NULL);
+}
+
+
+/*
+ * It removes the window to the internal window_list managed by the
+ * Root object
+ *
+ * Checks if the object is already present. Removes a reference to the
+ * accessible object of the window.
+ */
+static void
+remove_window(UnityRootAccessible* self,
+ nux::BaseWindow* window)
+{
+ AtkObject* window_accessible = NULL;
+ gint index = 0;
+
+ g_return_if_fail(UNITY_IS_ROOT_ACCESSIBLE(self));
+
+ window_accessible =
+ unity_a11y_get_accessible(window);
+
+ return;
+
+ if (!g_slist_find(self->priv->window_list, window_accessible))
+ return;
+
+ index = g_slist_index(self->priv->window_list, window_accessible);
+
+ self->priv->window_list =
+ g_slist_remove(self->priv->window_list, window_accessible);
+ g_object_unref(window_accessible);
+
+ g_signal_emit_by_name(self, "children-changed::remove",
+ index, window_accessible, NULL);
+}
+
+static void
+set_active_window(UnityRootAccessible* self,
+ nux::BaseWindow* window)
+{
+ g_return_if_fail(UNITY_IS_ROOT_ACCESSIBLE(self));
+ g_return_if_fail(window != NULL);
+
+ self->priv->active_window = window;
+ check_active_window(self);
+}
+
+nux::BaseWindow*
+search_for_launcher_window(UnityRootAccessible* self)
+{
+ GSList*iter = NULL;
+ nux::Object* nux_object = NULL;
+ nux::BaseWindow* bwindow = NULL;
+ NuxObjectAccessible* accessible = NULL;
+ gboolean found = FALSE;
+
+ for (iter = self->priv->window_list; iter != NULL; iter = g_slist_next(iter))
+ {
+ accessible = NUX_OBJECT_ACCESSIBLE(iter->data);
+
+ nux_object = nux_object_accessible_get_object(accessible);
+ bwindow = dynamic_cast<nux::BaseWindow*>(nux_object);
+
+ if ((bwindow!= NULL) && (g_strcmp0(bwindow->GetWindowName().c_str(), "LauncherWindow") == 0))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ return bwindow;
+ else
+ return NULL;
+}
+
+static void
+ubus_launcher_register_interest_cb(unity::glib::Variant const& variant,
+ UnityRootAccessible* self)
+{
+ //launcher window is the same during all the life of Unity
+ if (self->priv->launcher_window == NULL)
+ self->priv->launcher_window = search_for_launcher_window(self);
+
+ //launcher window became the active window
+ set_active_window(self, self->priv->launcher_window);
+}
+
+
+static void
+wc_change_visibility_window_cb(nux::BaseWindow* window,
+ UnityRootAccessible* self,
+ gboolean visible)
+{
+ if (visible)
+ {
+ add_window(self, window);
+ //for the dash and quicklist
+ set_active_window(self, window);
+ }
+ else
+ {
+ AtkObject* accessible = NULL;
+
+ accessible = unity_a11y_get_accessible(window);
+ nux_base_window_accessible_check_active(NUX_BASE_WINDOW_ACCESSIBLE(accessible),
+ NULL);
+ remove_window(self, window);
+ }
+}
+
+static void
+register_interesting_messages(UnityRootAccessible* self)
+{
+ static unity::UBusManager ubus_manager;
+
+ ubus_manager.RegisterInterest(UBUS_LAUNCHER_START_KEY_NAV,
+ sigc::bind(sigc::ptr_fun(ubus_launcher_register_interest_cb),
+ self));
+
+ ubus_manager.RegisterInterest(UBUS_LAUNCHER_START_KEY_SWITCHER,
+ sigc::bind(sigc::ptr_fun(ubus_launcher_register_interest_cb),
+ self));
+
+ nux::GetWindowCompositor().sigVisibleViewWindow.
+ connect(sigc::bind(sigc::ptr_fun(wc_change_visibility_window_cb), self, TRUE));
+
+ nux::GetWindowCompositor().sigHiddenViewWindow.
+ connect(sigc::bind(sigc::ptr_fun(wc_change_visibility_window_cb), self, FALSE));
+}
diff --git a/a11y/unity-root-accessible.h b/a11y/unity-root-accessible.h
new file mode 100644
index 000000000..4e843e1df
--- /dev/null
+++ b/a11y/unity-root-accessible.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_ROOT_ACCESSIBLE_H
+#define UNITY_ROOT_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include <Nux/Nux.h>
+#include <Nux/BaseWindow.h>
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_ROOT_ACCESSIBLE (unity_root_accessible_get_type ())
+#define UNITY_ROOT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_ROOT_ACCESSIBLE, UnityRootAccessible))
+#define UNITY_ROOT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_ROOT_ACCESSIBLE, UnityRootAccessibleClass))
+#define UNITY_IS_ROOT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_ROOT_ACCESSIBLE))
+#define UNITY_IS_ROOT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_ROOT_ACCESSIBLE))
+#define UNITY_ROOT_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_ROOT_ACCESSIBLE, UnityRootAccessibleClass))
+
+typedef struct _UnityRootAccessible UnityRootAccessible;
+typedef struct _UnityRootAccessibleClass UnityRootAccessibleClass;
+typedef struct _UnityRootAccessiblePrivate UnityRootAccessiblePrivate;
+
+struct _UnityRootAccessible
+{
+ AtkObject parent;
+
+ /* < private > */
+ UnityRootAccessiblePrivate* priv;
+};
+
+struct _UnityRootAccessibleClass
+{
+ AtkObjectClass parent_class;
+};
+
+GType unity_root_accessible_get_type(void);
+AtkObject* unity_root_accessible_new(void);
+
+G_END_DECLS
+
+#endif /* __UNITY_ROOT_ACCESSIBLE_H__ */
diff --git a/a11y/unity-rvgrid-accessible.cpp b/a11y/unity-rvgrid-accessible.cpp
new file mode 100644
index 000000000..e17f15e2a
--- /dev/null
+++ b/a11y/unity-rvgrid-accessible.cpp
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-rvgrid-accessible
+ * @Title: UnityRvgridAccessible
+ * @short_description: Implementation of the ATK interfaces for #ResultViewGrid
+ * @see_also: Rvgrid
+ *
+ * #UnityRvgridAccessible implements the required ATK interfaces for
+ * #Rvgrid, ie: exposing the different RvgridIcon on the model as
+ * #child of the object.
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-rvgrid-accessible.h"
+#include "unity-result-accessible.h"
+#include "unity-places-group-accessible.h"
+
+#include "unitya11y.h"
+#include "ResultViewGrid.h"
+#include "PlacesGroup.h"
+
+using namespace unity::dash;
+
+/* GObject */
+static void unity_rvgrid_accessible_class_init(UnityRvgridAccessibleClass* klass);
+static void unity_rvgrid_accessible_init(UnityRvgridAccessible* self);
+static void unity_rvgrid_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_rvgrid_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* unity_rvgrid_accessible_ref_state_set(AtkObject* obj);
+static gint unity_rvgrid_accessible_get_n_children(AtkObject* obj);
+static AtkObject* unity_rvgrid_accessible_ref_child(AtkObject* obj,
+ gint i);
+
+/* AtkSelection */
+static void atk_selection_interface_init(AtkSelectionIface* iface);
+static AtkObject* unity_rvgrid_accessible_ref_selection(AtkSelection* selection,
+ gint i);
+static gint unity_rvgrid_accessible_get_selection_count(AtkSelection* selection);
+static gboolean unity_rvgrid_accessible_is_child_selected(AtkSelection* selection,
+ gint i);
+
+/* private */
+
+G_DEFINE_TYPE_WITH_CODE(UnityRvgridAccessible, unity_rvgrid_accessible, NUX_TYPE_VIEW_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init))
+
+#define UNITY_RVGRID_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_RVGRID_ACCESSIBLE, \
+ UnityRvgridAccessiblePrivate))
+
+struct _UnityRvgridAccessiblePrivate
+{
+ sigc::connection on_selection_change_connection;
+
+ /* dummy selected result object */
+ UnityResultAccessible* result;
+ gboolean has_selection;
+ gboolean focused;
+};
+
+
+static void
+unity_rvgrid_accessible_class_init(UnityRvgridAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* GObject */
+ gobject_class->finalize = unity_rvgrid_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->get_n_children = unity_rvgrid_accessible_get_n_children;
+ atk_class->ref_child = unity_rvgrid_accessible_ref_child;
+ atk_class->initialize = unity_rvgrid_accessible_initialize;
+ atk_class->ref_state_set = unity_rvgrid_accessible_ref_state_set;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityRvgridAccessiblePrivate));
+}
+
+static void
+unity_rvgrid_accessible_init(UnityRvgridAccessible* self)
+{
+ UnityRvgridAccessiblePrivate* priv =
+ UNITY_RVGRID_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+}
+
+static void
+unity_rvgrid_accessible_finalize(GObject* object)
+{
+ UnityRvgridAccessible* self = UNITY_RVGRID_ACCESSIBLE(object);
+
+ self->priv->on_selection_change_connection.disconnect();
+
+ if (self->priv->result != NULL)
+ {
+ g_object_unref(self->priv->result);
+ self->priv->result = NULL;
+ }
+
+ self->priv->on_selection_change_connection.disconnect();
+
+ G_OBJECT_CLASS(unity_rvgrid_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_rvgrid_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<ResultViewGrid*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_RVGRID_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+check_selection(UnityRvgridAccessible* self)
+{
+ AtkObject* child = NULL;
+ gint index = 0;
+ nux::Object* object = NULL;
+ ResultViewGrid* rvgrid = NULL;
+ std::string name;
+
+ /* we don't notify until the grid is focused */
+ if (self->priv->focused == FALSE)
+ return;
+
+ object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (!object) /* state is defunct */
+ return;
+
+ rvgrid = static_cast<ResultViewGrid*>(object);
+ index = rvgrid->GetSelectedIndex();
+
+ if (index >= 0)
+ {
+ Result result(*rvgrid->GetIteratorAtRow(index));
+ name = result.name;
+
+ child = ATK_OBJECT(self->priv->result);
+ self->priv->has_selection = TRUE;
+ atk_object_set_name(child, name.c_str());
+ }
+ else
+ {
+ child = NULL;
+ self->priv->has_selection = FALSE;
+ }
+
+ g_signal_emit_by_name(self, "active-descendant-changed", child);
+ g_signal_emit_by_name(self, "selection-changed");
+}
+
+static void
+on_selection_change_cb(UnityRvgridAccessible* self)
+{
+ check_selection(self);
+}
+
+static void
+search_for_label(UnityRvgridAccessible* self)
+{
+ AtkObject* label_accessible = NULL;
+ nux::Object* nux_object = NULL;
+ unity::dash::PlacesGroup* group = NULL;
+ AtkObject* iter = NULL;
+ unity::StaticCairoText* label = NULL;
+
+ /* Search for the places group */
+ for (iter = atk_object_get_parent(ATK_OBJECT(self)); iter != NULL;
+ iter = atk_object_get_parent(iter))
+ {
+ if (UNITY_IS_PLACES_GROUP_ACCESSIBLE(iter))
+ break;
+ }
+ if (iter == NULL)
+ return;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(iter));
+ group = dynamic_cast<unity::dash::PlacesGroup*>(nux_object);
+
+ if (group == NULL)
+ return;
+
+ label = group->GetLabel();
+
+ label_accessible = unity_a11y_get_accessible(label);
+
+ if (label_accessible == NULL)
+ return;
+
+ /* FIXME: I had a froze using relations, require further
+ investigation, meanwhile setting directly the name can do the
+ work*/
+ atk_object_set_name(ATK_OBJECT(self), atk_object_get_name(label_accessible));
+}
+
+static gboolean
+check_selection_on_idle(gpointer data)
+{
+ check_selection(UNITY_RVGRID_ACCESSIBLE(data));
+
+ return FALSE;
+}
+
+static void
+on_focus_event_cb(AtkObject* object,
+ gboolean in,
+ gpointer data)
+{
+ UnityRvgridAccessible* self = NULL;
+
+ g_return_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(data));
+
+ self = UNITY_RVGRID_ACCESSIBLE(data);
+ self->priv->focused = in;
+
+ /* we check the selection stuff again, to report the selection
+ change now */
+ g_idle_add(check_selection_on_idle, self);
+}
+
+static void
+unity_rvgrid_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ UnityRvgridAccessible* self = NULL;
+ ResultViewGrid* rvgrid = NULL;
+ nux::Object* nux_object = NULL;
+
+ ATK_OBJECT_CLASS(unity_rvgrid_accessible_parent_class)->initialize(accessible, data);
+
+ atk_object_set_role(accessible, ATK_ROLE_TOOL_BAR);
+
+ self = UNITY_RVGRID_ACCESSIBLE(accessible);
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+
+ rvgrid = dynamic_cast<ResultViewGrid*>(nux_object);
+
+ if (rvgrid == NULL)
+ return;
+
+ self->priv->on_selection_change_connection =
+ rvgrid->selection_change.connect(sigc::bind(sigc::ptr_fun(on_selection_change_cb), self));
+
+ g_signal_connect(self, "focus-event",
+ G_CALLBACK(on_focus_event_cb), self);
+
+ self->priv->result = UNITY_RESULT_ACCESSIBLE(unity_result_accessible_new());
+ atk_object_set_parent(ATK_OBJECT(self->priv->result), ATK_OBJECT(self));
+
+ search_for_label(self);
+}
+
+static gint
+unity_rvgrid_accessible_get_n_children(AtkObject* obj)
+{
+ g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(obj), 0);
+
+ /* we have the state MANAGES_DESCENDANT, clients should not ask for
+ the children, and just taking care of the relevant signals. So we
+ just don't expose the children */
+ return 0;
+}
+
+static AtkObject*
+unity_rvgrid_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(obj), NULL);
+
+ /* we have the state MANAGES_DESCENDANT, clients should not ask for
+ the children, and just taking care of the relevant signals. So we
+ just don't expose the children */
+ return NULL;
+}
+
+static AtkStateSet*
+unity_rvgrid_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(unity_rvgrid_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ atk_state_set_add_state(state_set, ATK_STATE_MANAGES_DESCENDANTS);
+
+ return state_set;
+}
+
+
+/* AtkSelection */
+static void
+atk_selection_interface_init(AtkSelectionIface* iface)
+{
+ iface->ref_selection = unity_rvgrid_accessible_ref_selection;
+ iface->get_selection_count = unity_rvgrid_accessible_get_selection_count;
+ iface->is_child_selected = unity_rvgrid_accessible_is_child_selected;
+
+ /* NOTE: for the moment we don't provide the implementation for the
+ "interactable" methods, it is, the methods that allow to change
+ the selected icon. The Rvgrid doesn't provide that API, and
+ right now we are focusing on a normal user input.*/
+ /* iface->add_selection = unity_rvgrid_accessible_add_selection; */
+ /* iface->clear_selection = unity_rvgrid_accessible_clear_selection; */
+ /* iface->remove_selection = unity_rvgrid_accessible_remove_selection; */
+
+ /* This method will never be implemented, as select all the rvgrid
+ icons makes no sense */
+ /* iface->select_all = unity_rvgrid_accessible_select_all_selection; */
+}
+
+static AtkObject*
+unity_rvgrid_accessible_ref_selection(AtkSelection* selection,
+ gint i)
+{
+ UnityRvgridAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(selection), NULL);
+
+ self = UNITY_RVGRID_ACCESSIBLE(selection);
+
+ if (self->priv->has_selection)
+ return ATK_OBJECT(g_object_ref(self->priv->result));
+ else
+ return NULL;
+}
+
+static gint
+unity_rvgrid_accessible_get_selection_count(AtkSelection* selection)
+{
+ UnityRvgridAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(selection), 0);
+
+ self = UNITY_RVGRID_ACCESSIBLE(selection);
+
+ if (self->priv->has_selection)
+ return 0;
+ else
+ return 1;
+}
+
+static gboolean
+unity_rvgrid_accessible_is_child_selected(AtkSelection* selection,
+ gint i)
+{
+ UnityRvgridAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_RVGRID_ACCESSIBLE(selection), FALSE);
+
+ self = UNITY_RVGRID_ACCESSIBLE(selection);
+
+ if (self->priv->has_selection && i == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/a11y/unity-rvgrid-accessible.h b/a11y/unity-rvgrid-accessible.h
new file mode 100644
index 000000000..bd9cc0fb0
--- /dev/null
+++ b/a11y/unity-rvgrid-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_RVGRID_ACCESSIBLE_H
+#define UNITY_RVGRID_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_RVGRID_ACCESSIBLE (unity_rvgrid_accessible_get_type ())
+#define UNITY_RVGRID_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_RVGRID_ACCESSIBLE, UnityRvgridAccessible))
+#define UNITY_RVGRID_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_RVGRID_ACCESSIBLE, UnityRvgridAccessibleClass))
+#define UNITY_IS_RVGRID_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_RVGRID_ACCESSIBLE))
+#define UNITY_IS_RVGRID_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_RVGRID_ACCESSIBLE))
+#define UNITY_RVGRID_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_RVGRID_ACCESSIBLE, UnityRvgridAccessibleClass))
+
+typedef struct _UnityRvgridAccessible UnityRvgridAccessible;
+typedef struct _UnityRvgridAccessibleClass UnityRvgridAccessibleClass;
+typedef struct _UnityRvgridAccessiblePrivate UnityRvgridAccessiblePrivate;
+
+struct _UnityRvgridAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityRvgridAccessiblePrivate* priv;
+};
+
+struct _UnityRvgridAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_rvgrid_accessible_get_type(void);
+AtkObject* unity_rvgrid_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_RVGRID_ACCESSIBLE_H__ */
diff --git a/a11y/unity-scope-bar-icon-accessible.cpp b/a11y/unity-scope-bar-icon-accessible.cpp
new file mode 100644
index 000000000..997e9364d
--- /dev/null
+++ b/a11y/unity-scope-bar-icon-accessible.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Luke Yelavich <luke.yelavich@canonical.com>
+ */
+
+/**
+ * SECTION:unity-scope_bar_icon-accessible
+ * @Title: UnityScopeBarIconAccessible
+ * @short_description: Implementation of the ATK interfaces for #ScopeBarIcon
+ * @see_also: ScopeBarIcon
+ *
+ * #UnityScopeBarIconAccessible implements the required ATK interfaces for
+ * #ScopeBarIcon, mainly exposing the text as his name, as this
+ * #object is mainly used as a label
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-scope-bar-icon-accessible.h"
+
+#include "unitya11y.h"
+#include "ScopeBarIcon.h"
+
+using namespace unity::dash;
+
+/* GObject */
+static void unity_scope_bar_icon_accessible_class_init(UnityScopeBarIconAccessibleClass* klass);
+static void unity_scope_bar_icon_accessible_init(UnityScopeBarIconAccessible* self);
+static void unity_scope_bar_icon_accessible_dispose(GObject* object);
+
+/* AtkObject.h */
+static void unity_scope_bar_icon_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static const gchar* unity_scope_bar_icon_accessible_get_name(AtkObject* obj);
+static void on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible);
+static void on_active_changed_cb(bool is_active,
+ AtkObject* accessible);
+
+G_DEFINE_TYPE(UnityScopeBarIconAccessible, unity_scope_bar_icon_accessible, NUX_TYPE_VIEW_ACCESSIBLE);
+
+#define UNITY_SCOPE_BAR_ICON_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE, \
+ UnityScopeBarIconAccessiblePrivate))
+
+struct _UnityScopeBarIconAccessiblePrivate
+{
+ gchar* name;
+};
+
+static void
+unity_scope_bar_icon_accessible_class_init(UnityScopeBarIconAccessibleClass* klass)
+{
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->dispose = unity_scope_bar_icon_accessible_dispose;
+
+ /* AtkObject */
+ atk_class->get_name = unity_scope_bar_icon_accessible_get_name;
+ atk_class->initialize = unity_scope_bar_icon_accessible_initialize;
+
+ g_type_class_add_private(gobject_class, sizeof(UnityScopeBarIconAccessiblePrivate));
+}
+
+static void
+unity_scope_bar_icon_accessible_init(UnityScopeBarIconAccessible* self)
+{
+ UnityScopeBarIconAccessiblePrivate* priv =
+ UNITY_SCOPE_BAR_ICON_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+ self->priv->name = NULL;
+}
+
+static void
+unity_scope_bar_icon_accessible_dispose(GObject* object)
+{
+ UnityScopeBarIconAccessible* self = UNITY_SCOPE_BAR_ICON_ACCESSIBLE(object);
+
+ if (self->priv->name != NULL)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ G_OBJECT_CLASS(unity_scope_bar_icon_accessible_parent_class)->dispose(object);
+}
+
+AtkObject*
+unity_scope_bar_icon_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<ScopeBarIcon*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_scope_bar_icon_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ ScopeBarIcon* icon = NULL;
+
+ ATK_OBJECT_CLASS(unity_scope_bar_icon_accessible_parent_class)->initialize(accessible, data);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ icon = dynamic_cast<ScopeBarIcon*>(nux_object);
+
+ if (icon == NULL)
+ return;
+
+ icon->key_nav_focus_change.connect(sigc::bind(sigc::ptr_fun(on_focus_changed_cb), accessible));
+
+ icon->active.changed.connect(sigc::bind(sigc::ptr_fun(on_active_changed_cb), accessible));
+
+ atk_object_set_role(accessible, ATK_ROLE_PUSH_BUTTON);
+}
+
+static const gchar*
+unity_scope_bar_icon_accessible_get_name(AtkObject* obj)
+{
+ g_return_val_if_fail(UNITY_IS_SCOPE_BAR_ICON_ACCESSIBLE(obj), NULL);
+ UnityScopeBarIconAccessible* self = UNITY_SCOPE_BAR_ICON_ACCESSIBLE(obj);
+
+ if (self->priv->name)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ self->priv->name = g_strdup(ATK_OBJECT_CLASS(unity_scope_bar_icon_accessible_parent_class)->get_name(obj));
+ if (self->priv->name == NULL)
+ {
+ ScopeBarIcon* icon = NULL;
+
+ icon = dynamic_cast<ScopeBarIcon*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
+ if (icon != NULL)
+ {
+ if (icon->active())
+ self->priv->name = g_strdup_printf(_("%s: selected"), icon->name().c_str());
+ else
+ self->priv->name = g_strdup(icon->name().c_str());
+ }
+ }
+
+ return self->priv->name;
+}
+
+static void
+on_focus_changed_cb(nux::Area* area,
+ bool has_focus,
+ nux::KeyNavDirection direction,
+ AtkObject* accessible)
+{
+ g_return_if_fail(UNITY_IS_SCOPE_BAR_ICON_ACCESSIBLE(accessible));
+
+ g_signal_emit_by_name(accessible, "focus-event", has_focus);
+}
+
+static void
+on_active_changed_cb(bool is_active,
+ AtkObject* accessible)
+{
+ g_return_if_fail(UNITY_IS_SCOPE_BAR_ICON_ACCESSIBLE(accessible));
+
+ g_object_notify(G_OBJECT(accessible), "accessible-name");
+}
diff --git a/a11y/unity-scope-bar-icon-accessible.h b/a11y/unity-scope-bar-icon-accessible.h
new file mode 100644
index 000000000..6fa67f160
--- /dev/null
+++ b/a11y/unity-scope-bar-icon-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Luke Yelavich <luke.yelavich@canonical.com>
+ */
+
+#ifndef UNITY_SCOPE_BAR_ICON_ACCESSIBLE_H
+#define UNITY_SCOPE_BAR_ICON_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE (unity_scope_bar_icon_accessible_get_type ())
+#define UNITY_SCOPE_BAR_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE, UnityScopeBarIconAccessible))
+#define UNITY_SCOPE_BAR_ICON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE, UnityScopeBarIconAccessibleClass))
+#define UNITY_IS_SCOPE_BAR_ICON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE))
+#define UNITY_IS_SCOPE_BAR_ICON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE))
+#define UNITY_SCOPE_BAR_ICON_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_SCOPE_BAR_ICON_ACCESSIBLE, UnityScopeBarIconAccessibleClass))
+
+typedef struct _UnityScopeBarIconAccessible UnityScopeBarIconAccessible;
+typedef struct _UnityScopeBarIconAccessibleClass UnityScopeBarIconAccessibleClass;
+typedef struct _UnityScopeBarIconAccessiblePrivate UnityScopeBarIconAccessiblePrivate;
+
+struct _UnityScopeBarIconAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityScopeBarIconAccessiblePrivate* priv;
+};
+
+struct _UnityScopeBarIconAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_scope_bar_icon_accessible_get_type(void);
+AtkObject* unity_scope_bar_icon_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_SCOPE_BAR_ICON_ACCESSIBLE_H__ */
diff --git a/a11y/unity-sctext-accessible.cpp b/a11y/unity-sctext-accessible.cpp
new file mode 100644
index 000000000..b1f043215
--- /dev/null
+++ b/a11y/unity-sctext-accessible.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-sctext-accessible
+ * @Title: UnitySctextAccessible
+ * @short_description: Implementation of the ATK interfaces for #StaticCairoText
+ * @see_also: StaticCairoText
+ *
+ * #UnitySctextAccessible implements the required ATK interfaces for
+ * #StaticCairoText, mainly exposing the text as his name, as this
+ * #object is mainly used as a label
+ *
+ */
+
+#include <glib/gi18n.h>
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+
+#include "unity-sctext-accessible.h"
+
+#include "unitya11y.h"
+#include "StaticCairoText.h"
+
+/* GObject */
+static void unity_sctext_accessible_class_init(UnitySctextAccessibleClass* klass);
+static void unity_sctext_accessible_init(UnitySctextAccessible* self);
+
+/* AtkObject.h */
+static void unity_sctext_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static const gchar* unity_sctext_accessible_get_name(AtkObject* obj);
+
+G_DEFINE_TYPE(UnitySctextAccessible, unity_sctext_accessible, NUX_TYPE_VIEW_ACCESSIBLE);
+
+
+#define UNITY_SCTEXT_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SCTEXT_ACCESSIBLE, \
+ UnitySctextAccessiblePrivate))
+
+struct _UnitySctextAccessiblePrivate
+{
+ gchar* stripped_name;
+};
+
+
+static void
+unity_sctext_accessible_class_init(UnitySctextAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->get_name = unity_sctext_accessible_get_name;
+ atk_class->initialize = unity_sctext_accessible_initialize;
+
+ g_type_class_add_private(gobject_class, sizeof(UnitySctextAccessiblePrivate));
+}
+
+static void
+unity_sctext_accessible_init(UnitySctextAccessible* self)
+{
+ UnitySctextAccessiblePrivate* priv =
+ UNITY_SCTEXT_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+ priv->stripped_name = NULL;
+}
+
+AtkObject*
+unity_sctext_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<unity::StaticCairoText*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SCTEXT_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+on_label_text_change_cb(unity::StaticCairoText* label, UnitySctextAccessible* self)
+{
+ g_object_notify(G_OBJECT(self), "accessible-name");
+}
+
+static void
+unity_sctext_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ unity::StaticCairoText* label = NULL;
+
+ ATK_OBJECT_CLASS(unity_sctext_accessible_parent_class)->initialize(accessible, data);
+
+ atk_object_set_role(accessible, ATK_ROLE_LABEL);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ label = dynamic_cast<unity::StaticCairoText*>(nux_object);
+
+ if (label == NULL) /* status defunct */
+ return;
+
+ label->sigTextChanged.connect(sigc::bind(sigc::ptr_fun(on_label_text_change_cb),
+ UNITY_SCTEXT_ACCESSIBLE(accessible)));
+}
+
+static const gchar*
+unity_sctext_accessible_get_name(AtkObject* obj)
+{
+ const gchar* name = NULL;
+ UnitySctextAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SCTEXT_ACCESSIBLE(obj), NULL);
+ self = UNITY_SCTEXT_ACCESSIBLE(obj);
+
+ name = ATK_OBJECT_CLASS(unity_sctext_accessible_parent_class)->get_name(obj);
+ if (name == NULL)
+ {
+ unity::StaticCairoText* text = NULL;
+
+ if (self->priv->stripped_name != NULL)
+ {
+ g_free(self->priv->stripped_name);
+ self->priv->stripped_name = NULL;
+ }
+
+ text = dynamic_cast<unity::StaticCairoText*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
+ if (text != NULL)
+ {
+ name = text->GetText().c_str();
+ pango_parse_markup(name, -1, 0, NULL,
+ &self->priv->stripped_name,
+ NULL, NULL);
+ name = self->priv->stripped_name;
+ }
+ }
+
+ return name;
+}
diff --git a/a11y/unity-sctext-accessible.h b/a11y/unity-sctext-accessible.h
new file mode 100644
index 000000000..2c1dd22c8
--- /dev/null
+++ b/a11y/unity-sctext-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_SCTEXT_ACCESSIBLE_H
+#define UNITY_SCTEXT_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_SCTEXT_ACCESSIBLE (unity_sctext_accessible_get_type ())
+#define UNITY_SCTEXT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_SCTEXT_ACCESSIBLE, UnitySctextAccessible))
+#define UNITY_SCTEXT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_SCTEXT_ACCESSIBLE, UnitySctextAccessibleClass))
+#define UNITY_IS_SCTEXT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_SCTEXT_ACCESSIBLE))
+#define UNITY_IS_SCTEXT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_SCTEXT_ACCESSIBLE))
+#define UNITY_SCTEXT_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_SCTEXT_ACCESSIBLE, UnitySctextAccessibleClass))
+
+typedef struct _UnitySctextAccessible UnitySctextAccessible;
+typedef struct _UnitySctextAccessibleClass UnitySctextAccessibleClass;
+typedef struct _UnitySctextAccessiblePrivate UnitySctextAccessiblePrivate;
+
+struct _UnitySctextAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnitySctextAccessiblePrivate* priv;
+};
+
+struct _UnitySctextAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_sctext_accessible_get_type(void);
+AtkObject* unity_sctext_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_SCTEXT_ACCESSIBLE_H__ */
diff --git a/a11y/unity-search-bar-accessible.cpp b/a11y/unity-search-bar-accessible.cpp
new file mode 100644
index 000000000..4c59cdc81
--- /dev/null
+++ b/a11y/unity-search-bar-accessible.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-search_bar-accessible
+ * @Title: UnitySearchBarAccessible
+ * @short_description: Implementation of the ATK interfaces for #SearchBar
+ * @see_also: SearchBar at SearchBar.h
+ *
+ * #UnitySearchBarAccessible implements the required ATK interfaces for
+ * #SearchBar, ie: exposing the different SearchBarIcon on the model as
+ * #child of the object.
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-search-bar-accessible.h"
+
+#include "unitya11y.h"
+#include "SearchBar.h"
+
+using namespace unity;
+
+/* GObject */
+static void unity_search_bar_accessible_class_init(UnitySearchBarAccessibleClass* klass);
+static void unity_search_bar_accessible_init(UnitySearchBarAccessible* self);
+static void unity_search_bar_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_search_bar_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+
+G_DEFINE_TYPE(UnitySearchBarAccessible, unity_search_bar_accessible, NUX_TYPE_VIEW_ACCESSIBLE)
+
+#define UNITY_SEARCH_BAR_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SEARCH_BAR_ACCESSIBLE, \
+ UnitySearchBarAccessiblePrivate))
+
+struct _UnitySearchBarAccessiblePrivate
+{
+
+};
+
+
+static void
+unity_search_bar_accessible_class_init(UnitySearchBarAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = unity_search_bar_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->initialize = unity_search_bar_accessible_initialize;
+
+ g_type_class_add_private(gobject_class, sizeof(UnitySearchBarAccessiblePrivate));
+}
+
+static void
+unity_search_bar_accessible_init(UnitySearchBarAccessible* self)
+{
+ UnitySearchBarAccessiblePrivate* priv =
+ UNITY_SEARCH_BAR_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+}
+
+static void
+unity_search_bar_accessible_finalize(GObject* object)
+{
+ G_OBJECT_CLASS(unity_search_bar_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_search_bar_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<SearchBar*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SEARCH_BAR_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+on_search_hint_change_cb(std::string const& s, UnitySearchBarAccessible* self)
+{
+ SearchBar* search_bar = NULL;
+ nux::TextEntry* text_entry = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_if_fail(UNITY_IS_SEARCH_BAR_ACCESSIBLE(self));
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ search_bar = dynamic_cast<SearchBar*>(nux_object);
+
+ if (search_bar == NULL) /* state defunct */
+ return;
+
+ text_entry = search_bar->text_entry();
+
+ if (text_entry != NULL)
+ {
+ AtkObject* text_entry_accessible = NULL;
+ text_entry_accessible = unity_a11y_get_accessible(text_entry);
+ atk_object_set_name(text_entry_accessible, s.c_str());
+ }
+}
+
+
+static void
+unity_search_bar_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ SearchBar* search_bar = NULL;
+ // nux::TextEntry* text_entry = NULL;
+
+ ATK_OBJECT_CLASS(unity_search_bar_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_PANEL;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ search_bar = dynamic_cast<SearchBar*>(nux_object);
+
+ if (search_bar == NULL)
+ return;
+
+ search_bar->search_hint.changed.connect(sigc::bind(sigc::ptr_fun(on_search_hint_change_cb),
+ UNITY_SEARCH_BAR_ACCESSIBLE(accessible)));
+}
diff --git a/a11y/unity-search-bar-accessible.h b/a11y/unity-search-bar-accessible.h
new file mode 100644
index 000000000..94664b77e
--- /dev/null
+++ b/a11y/unity-search-bar-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_SEARCH_BAR_ACCESSIBLE_H
+#define UNITY_SEARCH_BAR_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_SEARCH_BAR_ACCESSIBLE (unity_search_bar_accessible_get_type ())
+#define UNITY_SEARCH_BAR_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_SEARCH_BAR_ACCESSIBLE, UnitySearchBarAccessible))
+#define UNITY_SEARCH_BAR_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_SEARCH_BAR_ACCESSIBLE, UnitySearchBarAccessibleClass))
+#define UNITY_IS_SEARCH_BAR_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_SEARCH_BAR_ACCESSIBLE))
+#define UNITY_IS_SEARCH_BAR_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_SEARCH_BAR_ACCESSIBLE))
+#define UNITY_SEARCH_BAR_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_SEARCH_BAR_ACCESSIBLE, UnitySearchBarAccessibleClass))
+
+typedef struct _UnitySearchBarAccessible UnitySearchBarAccessible;
+typedef struct _UnitySearchBarAccessibleClass UnitySearchBarAccessibleClass;
+typedef struct _UnitySearchBarAccessiblePrivate UnitySearchBarAccessiblePrivate;
+
+struct _UnitySearchBarAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnitySearchBarAccessiblePrivate* priv;
+};
+
+struct _UnitySearchBarAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_search_bar_accessible_get_type(void);
+AtkObject* unity_search_bar_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_SEARCH_BAR_ACCESSIBLE_H__ */
diff --git a/a11y/unity-session-button-accessible.cpp b/a11y/unity-session-button-accessible.cpp
new file mode 100644
index 000000000..65653ef73
--- /dev/null
+++ b/a11y/unity-session-button-accessible.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Luke Yelavich <luke.yelavich@canonical.com>
+ */
+
+/**
+ * SECTION:unity-session_button_accessible
+ * @Title: UnitySessionButtonAccessible
+ * @short_description: Implementation of the ATK interfaces for #unity::session::Button
+ *
+ * #UnitySessionButtonAccessible implements the required ATK interfaces of
+ * unity::Button, exposing the common elements on each basic individual
+ * element (position, extents, etc)
+ *
+ */
+
+#include "unity-session-button-accessible.h"
+#include "SessionButton.h"
+
+#include "unitya11y.h"
+
+using namespace unity::session;
+
+/* GObject */
+static void unity_session_button_accessible_class_init(UnitySessionButtonAccessibleClass* klass);
+static void unity_session_button_accessible_init(UnitySessionButtonAccessible* session_button_accessible);
+static void unity_session_button_accessible_dispose(GObject* object);
+static void unity_session_button_accessible_finalize(GObject* object);
+
+
+/* AtkObject.h */
+static void unity_session_button_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static AtkStateSet* unity_session_button_accessible_ref_state_set(AtkObject* obj);
+static const gchar* unity_session_button_accessible_get_name(AtkObject* obj);
+
+
+/* AtkAction */
+static void atk_action_interface_init(AtkActionIface *iface);
+static gboolean unity_session_button_accessible_do_action(AtkAction *action,
+ gint i);
+static gint unity_session_button_accessible_get_n_actions(AtkAction *action);
+static const gchar* unity_session_button_accessible_get_name(AtkAction *action,
+ gint i);
+
+/* private/utility methods*/
+static void on_focus_change_cb(bool const& value, UnitySessionButtonAccessible* accessible);
+
+G_DEFINE_TYPE_WITH_CODE(UnitySessionButtonAccessible,
+ unity_session_button_accessible,
+ NUX_TYPE_OBJECT_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION,
+ atk_action_interface_init))
+
+#define UNITY_SESSION_BUTTON_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE, \
+ UnitySessionButtonAccessiblePrivate))
+
+struct _UnitySessionButtonAccessiblePrivate
+{
+ gchar *name;
+};
+
+static void
+unity_session_button_accessible_class_init(UnitySessionButtonAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ gobject_class->dispose = unity_session_button_accessible_dispose;
+ gobject_class->finalize = unity_session_button_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->initialize = unity_session_button_accessible_initialize;
+ atk_class->get_name = unity_session_button_accessible_get_name;
+ atk_class->ref_state_set = unity_session_button_accessible_ref_state_set;
+
+ g_type_class_add_private(gobject_class, sizeof(UnitySessionButtonAccessiblePrivate));
+}
+
+static void
+unity_session_button_accessible_init(UnitySessionButtonAccessible* session_button_accessible)
+{
+ UnitySessionButtonAccessiblePrivate *priv =
+ UNITY_SESSION_BUTTON_ACCESSIBLE_GET_PRIVATE(session_button_accessible);
+
+ session_button_accessible->priv = priv;
+ session_button_accessible->priv->name = NULL;
+}
+
+static void
+unity_session_button_accessible_dispose(GObject* object)
+{
+ UnitySessionButtonAccessible *self = UNITY_SESSION_BUTTON_ACCESSIBLE(object);
+
+ if (self->priv->name != NULL) {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ G_OBJECT_CLASS(unity_session_button_accessible_parent_class)->dispose(object);
+}
+
+static void
+unity_session_button_accessible_finalize(GObject* object)
+{
+ G_OBJECT_CLASS(unity_session_button_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_session_button_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<Button*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_session_button_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ UnitySessionButtonAccessible* self = NULL;
+ nux::Object* nux_object = NULL;
+ Button* button = NULL;
+
+ ATK_OBJECT_CLASS(unity_session_button_accessible_parent_class)->initialize(accessible, data);
+ self = UNITY_SESSION_BUTTON_ACCESSIBLE(accessible);
+
+ accessible->role = ATK_ROLE_PUSH_BUTTON;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+
+ if (nux_object == NULL) /* defunct */
+ return;
+
+ button = static_cast<Button*>(nux_object);
+ button->highlighted.changed.connect(sigc::bind(sigc::ptr_fun(on_focus_change_cb),
+ UNITY_SESSION_BUTTON_ACCESSIBLE(self)));
+}
+
+static const gchar*
+unity_session_button_accessible_get_name(AtkObject* obj)
+{
+ g_return_val_if_fail(UNITY_IS_SESSION_BUTTON_ACCESSIBLE(obj), NULL);
+
+ UnitySessionButtonAccessible *self = UNITY_SESSION_BUTTON_ACCESSIBLE(obj);
+
+ if (self->priv->name)
+ {
+ g_free(self->priv->name);
+ self->priv->name = NULL;
+ }
+
+ self->priv->name = g_strdup(ATK_OBJECT_CLASS(unity_session_button_accessible_parent_class)->get_name(obj));
+ if (self->priv->name == NULL)
+ {
+ Button* button = NULL;
+
+ button = dynamic_cast<Button*>(nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj)));
+
+ if (button == NULL) /* State is defunct */
+ self->priv->name = NULL;
+ else
+ self->priv->name = g_strdup(button->label().c_str());
+ }
+
+ return self->priv->name;
+}
+
+static AtkStateSet*
+unity_session_button_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+ Button* button = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SESSION_BUTTON_ACCESSIBLE(obj), NULL);
+
+ state_set = ATK_OBJECT_CLASS(unity_session_button_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ button = dynamic_cast<Button*>(nux_object);
+
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+ atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
+ atk_state_set_add_state(state_set, ATK_STATE_SENSITIVE);
+ atk_state_set_add_state(state_set, ATK_STATE_VISIBLE);
+ atk_state_set_add_state(state_set, ATK_STATE_SHOWING);
+
+ if (button->highlighted)
+ {
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+ atk_state_set_add_state(state_set, ATK_STATE_SELECTED);
+ atk_state_set_add_state(state_set, ATK_STATE_ACTIVE);
+ }
+
+ return state_set;
+}
+
+/* private methods */
+static void
+on_focus_change_cb(bool const& value, UnitySessionButtonAccessible* accessible)
+{
+ nux::Object* nux_object = NULL;
+ Button* button = NULL;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+
+ if (nux_object == NULL) /* defunct */
+ return;
+
+ button = dynamic_cast<Button*>(nux_object);
+
+ atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_FOCUSED, button->highlighted);
+ atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_SELECTED, button->highlighted);
+ atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_ACTIVE, button->highlighted);
+}
+
+/* AtkAction */
+static void
+atk_action_interface_init(AtkActionIface *iface)
+{
+ iface->do_action = unity_session_button_accessible_do_action;
+ iface->get_n_actions = unity_session_button_accessible_get_n_actions;
+ iface->get_name = unity_session_button_accessible_get_name;
+}
+
+static gboolean
+unity_session_button_accessible_do_action(AtkAction *action,
+ gint i)
+{
+ Button* button = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SESSION_BUTTON_ACCESSIBLE(action), FALSE);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(action));
+ if (nux_object == NULL)
+ return FALSE;
+
+ button = dynamic_cast<Button*>(nux_object);
+
+ button->activated.emit();
+
+ return TRUE;
+}
+
+static gint
+unity_session_button_accessible_get_n_actions(AtkAction *action)
+{
+ g_return_val_if_fail(UNITY_IS_SESSION_BUTTON_ACCESSIBLE(action), 0);
+
+ return 1;
+}
+
+static const gchar*
+unity_session_button_accessible_get_name(AtkAction *action,
+ gint i)
+{
+ g_return_val_if_fail(UNITY_IS_SESSION_BUTTON_ACCESSIBLE(action), NULL);
+ g_return_val_if_fail(i == 0, NULL);
+
+ return "activate";
+}
diff --git a/a11y/unity-session-button-accessible.h b/a11y/unity-session-button-accessible.h
new file mode 100644
index 000000000..ab3ae0429
--- /dev/null
+++ b/a11y/unity-session-button-accessible.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_SESSION_BUTTON_ACCESSIBLE_H
+#define UNITY_SESSION_BUTTON_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-object-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE (unity_session_button_accessible_get_type ())
+#define UNITY_SESSION_BUTTON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE, UnitySessionButtonAccessible))
+#define UNITY_SESSION_BUTTON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE, UnitySessionButtonAccessibleClass))
+#define UNITY_IS_SESSION_BUTTON_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE))
+#define UNITY_IS_SESSION_BUTTON_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE))
+#define UNITY_SESSION_BUTTON_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_SESSION_BUTTON_ACCESSIBLE, UnitySessionButtonAccessibleClass))
+
+typedef struct _UnitySessionButtonAccessible UnitySessionButtonAccessible;
+typedef struct _UnitySessionButtonAccessibleClass UnitySessionButtonAccessibleClass;
+typedef struct _UnitySessionButtonAccessiblePrivate UnitySessionButtonAccessiblePrivate;
+
+struct _UnitySessionButtonAccessible
+{
+ NuxObjectAccessible parent;
+
+ UnitySessionButtonAccessiblePrivate *priv;
+};
+
+struct _UnitySessionButtonAccessibleClass
+{
+ NuxObjectAccessibleClass parent_class;
+};
+
+GType unity_session_button_accessible_get_type(void);
+AtkObject* unity_session_button_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_SESSION_BUTTON_ACCESSIBLE_H__ */
diff --git a/a11y/unity-switcher-accessible.cpp b/a11y/unity-switcher-accessible.cpp
new file mode 100644
index 000000000..80651bc01
--- /dev/null
+++ b/a11y/unity-switcher-accessible.cpp
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+/**
+ * SECTION:unity-switcher-accessible
+ * @Title: UnitySwitcherAccessible
+ * @short_description: Implementation of the ATK interfaces for #SwitcherView
+ * @see_also: SwitcherView
+ *
+ * #UnitySwitcherAccessible implements the required ATK interfaces for
+ * #SwitcherView, ie: exposing the different AbstractLauncherIcon on the
+ * #model as child of the object.
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "unity-switcher-accessible.h"
+#include "unity-launcher-icon-accessible.h"
+
+#include "unitya11y.h"
+#include "SwitcherView.h"
+#include "SwitcherModel.h"
+
+using namespace unity::switcher;
+using namespace unity::launcher;
+
+/* GObject */
+static void unity_switcher_accessible_class_init(UnitySwitcherAccessibleClass* klass);
+static void unity_switcher_accessible_init(UnitySwitcherAccessible* self);
+static void unity_switcher_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_switcher_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+static gint unity_switcher_accessible_get_n_children(AtkObject* obj);
+static AtkObject* unity_switcher_accessible_ref_child(AtkObject* obj,
+ gint i);
+static AtkStateSet* unity_switcher_accessible_ref_state_set(AtkObject* obj);
+
+/* AtkSelection */
+static void atk_selection_interface_init(AtkSelectionIface* iface);
+static AtkObject* unity_switcher_accessible_ref_selection(AtkSelection* selection,
+ gint i);
+static gint unity_switcher_accessible_get_selection_count(AtkSelection* selection);
+static gboolean unity_switcher_accessible_is_child_selected(AtkSelection* selection,
+ gint i);
+/* NuxAreaAccessible */
+static gboolean unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self);
+
+/* private */
+static void on_selection_changed_cb(AbstractLauncherIcon::Ptr const& icon,
+ UnitySwitcherAccessible* switcher_accessible);
+static void create_children(UnitySwitcherAccessible* self);
+
+
+G_DEFINE_TYPE_WITH_CODE(UnitySwitcherAccessible, unity_switcher_accessible, NUX_TYPE_VIEW_ACCESSIBLE,
+ G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init))
+
+#define UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE, \
+ UnitySwitcherAccessiblePrivate))
+
+struct _UnitySwitcherAccessiblePrivate
+{
+ /* We maintain the children. Although the LauncherIcon are shared
+ * between the Switcher and Launcher, in order to keep a hierarchy
+ * coherence, we create a different accessible object */
+ GSList* children;
+
+ sigc::connection on_selection_changed_connection;
+};
+
+
+static void
+unity_switcher_accessible_class_init(UnitySwitcherAccessibleClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+ NuxAreaAccessibleClass* area_class = NUX_AREA_ACCESSIBLE_CLASS(klass);
+
+ gobject_class->finalize = unity_switcher_accessible_finalize;
+
+ /* AtkObject */
+ atk_class->get_n_children = unity_switcher_accessible_get_n_children;
+ atk_class->ref_child = unity_switcher_accessible_ref_child;
+ atk_class->initialize = unity_switcher_accessible_initialize;
+ atk_class->ref_state_set = unity_switcher_accessible_ref_state_set;
+
+ /* NuxAreaAccessible */
+ area_class->check_pending_notification = unity_switcher_accessible_check_pending_notification;
+
+ g_type_class_add_private(gobject_class, sizeof(UnitySwitcherAccessiblePrivate));
+}
+
+static void
+unity_switcher_accessible_init(UnitySwitcherAccessible* self)
+{
+ UnitySwitcherAccessiblePrivate* priv =
+ UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(self);
+
+ self->priv = priv;
+ self->priv->children = NULL;
+}
+
+static void
+unity_switcher_accessible_finalize(GObject* object)
+{
+ UnitySwitcherAccessible* self = UNITY_SWITCHER_ACCESSIBLE(object);
+
+ self->priv->on_selection_changed_connection.disconnect();
+
+ if (self->priv->children)
+ {
+ g_slist_free_full(self->priv->children, g_object_unref);
+ self->priv->children = NULL;
+ }
+
+ G_OBJECT_CLASS(unity_switcher_accessible_parent_class)->finalize(object);
+}
+
+AtkObject*
+unity_switcher_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<SwitcherView*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SWITCHER_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+ atk_object_set_name(accessible, _("Switcher"));
+
+ return accessible;
+}
+
+/* AtkObject.h */
+static void
+unity_switcher_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ SwitcherView* switcher = NULL;
+ nux::Object* nux_object = NULL;
+ UnitySwitcherAccessible* self = NULL;
+ SwitcherModel::Ptr model;
+
+ ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->initialize(accessible, data);
+
+ atk_object_set_role(accessible, ATK_ROLE_TOOL_BAR);
+
+ self = UNITY_SWITCHER_ACCESSIBLE(accessible);
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ switcher = dynamic_cast<SwitcherView*>(nux_object);
+ if (switcher == NULL)
+ return;
+
+ model = switcher->GetModel();
+
+ if (model)
+ {
+ self->priv->on_selection_changed_connection =
+ model->selection_changed.connect(sigc::bind(sigc::ptr_fun(on_selection_changed_cb),
+ self));
+
+ create_children(self);
+ }
+
+ /* To force being connected to the window::activate signal */
+ nux_area_accessible_parent_window_active(NUX_AREA_ACCESSIBLE(self));
+}
+
+static gint
+unity_switcher_accessible_get_n_children(AtkObject* obj)
+{
+ nux::Object* object = NULL;
+ UnitySwitcherAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), 0);
+ self = UNITY_SWITCHER_ACCESSIBLE(obj);
+
+ object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (!object) /* state is defunct */
+ return 0;
+
+ return g_slist_length(self->priv->children);
+}
+
+static AtkObject*
+unity_switcher_accessible_ref_child(AtkObject* obj,
+ gint i)
+{
+ gint num = 0;
+ nux::Object* nux_object = NULL;
+ AtkObject* child_accessible = NULL;
+ UnitySwitcherAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), NULL);
+ num = atk_object_get_n_accessible_children(obj);
+ g_return_val_if_fail((i < num) && (i >= 0), NULL);
+ self = UNITY_SWITCHER_ACCESSIBLE(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ child_accessible = ATK_OBJECT(g_slist_nth_data(self->priv->children, i));
+
+ g_object_ref(child_accessible);
+
+ return child_accessible;
+}
+
+static AtkStateSet*
+unity_switcher_accessible_ref_state_set(AtkObject* obj)
+{
+ AtkStateSet* state_set = NULL;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), NULL);
+
+ state_set =
+ ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->ref_state_set(obj);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
+
+ if (nux_object == NULL) /* defunct */
+ return state_set;
+
+ /* The Switcher is always focusable */
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
+
+ /* The Switcher is always focused. Looking SwitcherController code,
+ * SwitcherView is only created to be presented to the user */
+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
+
+ return state_set;
+}
+
+/* AtkSelection */
+static void
+atk_selection_interface_init(AtkSelectionIface* iface)
+{
+ iface->ref_selection = unity_switcher_accessible_ref_selection;
+ iface->get_selection_count = unity_switcher_accessible_get_selection_count;
+ iface->is_child_selected = unity_switcher_accessible_is_child_selected;
+
+ /* NOTE: for the moment we don't provide the implementation for the
+ "interactable" methods, it is, the methods that allow to change
+ the selected icon. The Switcher doesn't provide that API, and
+ right now we are focusing on a normal user input.*/
+ /* iface->add_selection = unity_switcher_accessible_add_selection; */
+ /* iface->clear_selection = unity_switcher_accessible_clear_selection; */
+ /* iface->remove_selection = unity_switcher_accessible_remove_selection; */
+
+ /* This method will never be implemented, as select all the switcher
+ icons makes no sense */
+ /* iface->select_all = unity_switcher_accessible_select_all_selection; */
+}
+
+static AtkObject*
+unity_switcher_accessible_ref_selection(AtkSelection* selection,
+ gint i)
+{
+ SwitcherView* switcher = NULL;
+ SwitcherModel::Ptr switcher_model;
+ nux::Object* nux_object = NULL;
+ gint selected_index = 0;
+ AtkObject* accessible_selected = NULL;
+ UnitySwitcherAccessible* self = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), 0);
+ /* there can be only just item selected */
+ g_return_val_if_fail(i == 0, NULL);
+ self = UNITY_SWITCHER_ACCESSIBLE(selection);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ switcher = static_cast<SwitcherView*>(nux_object);
+ switcher_model = switcher->GetModel();
+ selected_index = switcher_model->SelectionIndex();
+
+ accessible_selected = ATK_OBJECT(g_slist_nth_data(self->priv->children,
+ selected_index));
+
+ if (accessible_selected != NULL)
+ g_object_ref(accessible_selected);
+
+ return accessible_selected;
+}
+
+static gint
+unity_switcher_accessible_get_selection_count(AtkSelection* selection)
+{
+ SwitcherView* switcher = NULL;
+ SwitcherModel::Ptr switcher_model;
+ nux::Object* nux_object = NULL;
+
+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), 0);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ switcher = static_cast<SwitcherView*>(nux_object);
+ switcher_model = switcher->GetModel();
+
+ if (!switcher_model->Selection())
+ return 0;
+ else
+ return 1;
+}
+
+static gboolean
+unity_switcher_accessible_is_child_selected(AtkSelection* selection,
+ gint i)
+{
+ SwitcherView* switcher = NULL;
+ SwitcherModel::Ptr switcher_model;
+ SwitcherModel::iterator it;
+ nux::Object* nux_object = NULL;
+ gint selected_index = 0;
+
+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), FALSE);
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
+ if (!nux_object) /* state is defunct */
+ return 0;
+
+ switcher = static_cast<SwitcherView*>(nux_object);
+ switcher_model = switcher->GetModel();
+ selected_index = switcher_model->SelectionIndex();
+
+ if (selected_index == i)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* NuxAreaAccessible */
+static gboolean
+unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self)
+{
+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(self), FALSE);
+
+ /* Overriding the method: the switcher doesn't get the key focus of
+ * focus (Focusable) */
+ /* From SwitcherController: it shows that the switcher only exists
+ * to be shown to the user, so if the parent window gets actived, we
+ * assume that the switcher will be automatically focused
+ */
+ atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, TRUE);
+ g_signal_emit_by_name(self, "focus-event", TRUE, NULL);
+
+ return TRUE;
+}
+
+/* private */
+static void
+on_selection_changed_cb(AbstractLauncherIcon::Ptr const& icon,
+ UnitySwitcherAccessible* switcher_accessible)
+{
+ g_signal_emit_by_name(ATK_OBJECT(switcher_accessible), "selection-changed");
+}
+
+static void
+create_children(UnitySwitcherAccessible* self)
+{
+ gint index = 0;
+ nux::Object* nux_object = NULL;
+ SwitcherView* switcher = NULL;
+ SwitcherModel::iterator it;
+ AtkObject* child_accessible = NULL;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
+ if (!nux_object) /* state is defunct */
+ return;
+
+ switcher = static_cast<SwitcherView*>(nux_object);
+ SwitcherModel::Ptr const& switcher_model = switcher->GetModel();
+
+ if (!switcher_model)
+ return;
+
+ for (AbstractLauncherIcon::Ptr const& child : *switcher_model)
+ {
+ child_accessible = unity_launcher_icon_accessible_new(child.GetPointer());
+ atk_object_set_parent(child_accessible, ATK_OBJECT(self));
+ self->priv->children = g_slist_append(self->priv->children,
+ child_accessible);
+ unity_launcher_icon_accessible_set_index(UNITY_LAUNCHER_ICON_ACCESSIBLE(child_accessible),
+ index++);
+ }
+}
diff --git a/a11y/unity-switcher-accessible.h b/a11y/unity-switcher-accessible.h
new file mode 100644
index 000000000..b79d0683a
--- /dev/null
+++ b/a11y/unity-switcher-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_SWITCHER_ACCESSIBLE_H
+#define UNITY_SWITCHER_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_SWITCHER_ACCESSIBLE (unity_switcher_accessible_get_type ())
+#define UNITY_SWITCHER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE, UnitySwitcherAccessible))
+#define UNITY_SWITCHER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_SWITCHER_ACCESSIBLE, UnitySwitcherAccessibleClass))
+#define UNITY_IS_SWITCHER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE))
+#define UNITY_IS_SWITCHER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_SWITCHER_ACCESSIBLE))
+#define UNITY_SWITCHER_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE, UnitySwitcherAccessibleClass))
+
+typedef struct _UnitySwitcherAccessible UnitySwitcherAccessible;
+typedef struct _UnitySwitcherAccessibleClass UnitySwitcherAccessibleClass;
+typedef struct _UnitySwitcherAccessiblePrivate UnitySwitcherAccessiblePrivate;
+
+struct _UnitySwitcherAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnitySwitcherAccessiblePrivate* priv;
+};
+
+struct _UnitySwitcherAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_switcher_accessible_get_type(void);
+AtkObject* unity_switcher_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif /* __UNITY_SWITCHER_ACCESSIBLE_H__ */
diff --git a/a11y/unity-text-input-accessible.cpp b/a11y/unity-text-input-accessible.cpp
new file mode 100644
index 000000000..57d1a490a
--- /dev/null
+++ b/a11y/unity-text-input-accessible.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#include "unity-text-input-accessible.h"
+
+#include "unitya11y.h"
+#include "TextInput.h"
+
+using namespace unity;
+
+/* GObject */
+static void unity_text_input_accessible_class_init(UnityTextInputAccessibleClass* klass);
+static void unity_text_input_accessible_init(UnityTextInputAccessible* self);
+//static void unity_text_input_accessible_finalize(GObject* object);
+
+/* AtkObject.h */
+static void unity_text_input_accessible_initialize(AtkObject* accessible,
+ gpointer data);
+
+G_DEFINE_TYPE(UnityTextInputAccessible, unity_text_input_accessible, NUX_TYPE_VIEW_ACCESSIBLE)
+
+static void
+unity_text_input_accessible_class_init(UnityTextInputAccessibleClass* klass)
+{
+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
+
+ /* AtkObject */
+ atk_class->initialize = unity_text_input_accessible_initialize;
+}
+
+static void
+unity_text_input_accessible_init(UnityTextInputAccessible* self)
+{}
+
+AtkObject*
+unity_text_input_accessible_new(nux::Object* object)
+{
+ AtkObject* accessible = NULL;
+
+ g_return_val_if_fail(dynamic_cast<TextInput*>(object), NULL);
+
+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_TEXT_INPUT_ACCESSIBLE, NULL));
+
+ atk_object_initialize(accessible, object);
+
+ return accessible;
+}
+
+static void
+unity_text_input_accessible_initialize(AtkObject* accessible,
+ gpointer data)
+{
+ nux::Object* nux_object = NULL;
+ TextInput* text_input = NULL;
+ nux::TextEntry* text_entry = NULL;
+
+ ATK_OBJECT_CLASS(unity_text_input_accessible_parent_class)->initialize(accessible, data);
+
+ accessible->role = ATK_ROLE_PANEL;
+
+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ text_input = dynamic_cast<TextInput*>(nux_object);
+
+ if (text_input == NULL)
+ return;
+
+ text_entry = text_input->text_entry();
+
+ if (text_entry != NULL)
+ {
+ AtkObject* text_entry_accessible = NULL;
+ text_entry_accessible = unity_a11y_get_accessible(text_entry);
+ atk_object_set_name(text_entry_accessible, text_input->input_hint().c_str());
+ }
+}
diff --git a/a11y/unity-text-input-accessible.h b/a11y/unity-text-input-accessible.h
new file mode 100644
index 000000000..c1ab85636
--- /dev/null
+++ b/a11y/unity-text-input-accessible.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITY_TEXT_INPUT_ACCESSIBLE_H
+#define UNITY_TEXT_INPUT_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include "nux-view-accessible.h"
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_TEXT_INPUT_ACCESSIBLE (unity_text_input_accessible_get_type ())
+#define UNITY_TEXT_INPUT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_TEXT_INPUT_ACCESSIBLE, UnityTextInputAccessible))
+#define UNITY_TEXT_INPUT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_TEXT_INPUT_ACCESSIBLE, UnityTextInputAccessibleClass))
+#define UNITY_IS_TEXT_INPUT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_TEXT_INPUT_ACCESSIBLE))
+#define UNITY_IS_TEXT_INPUT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_TEXT_INPUT_ACCESSIBLE))
+#define UNITY_TEXT_INPUT_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_TEXT_INPUT_ACCESSIBLE, UnityTextInputAccessibleClass))
+
+typedef struct _UnityTextInputAccessible UnityTextInputAccessible;
+typedef struct _UnityTextInputAccessibleClass UnityTextInputAccessibleClass;
+typedef struct _UnityTextInputAccessiblePrivate UnityTextInputAccessiblePrivate;
+
+struct _UnityTextInputAccessible
+{
+ NuxViewAccessible parent;
+
+ /*< private >*/
+ UnityTextInputAccessiblePrivate* priv;
+};
+
+struct _UnityTextInputAccessibleClass
+{
+ NuxViewAccessibleClass parent_class;
+};
+
+GType unity_text_input_accessible_get_type(void);
+AtkObject* unity_text_input_accessible_new(nux::Object* object);
+
+G_END_DECLS
+
+#endif
diff --git a/a11y/unity-util-accessible.cpp b/a11y/unity-util-accessible.cpp
new file mode 100644
index 000000000..b850cd2ea
--- /dev/null
+++ b/a11y/unity-util-accessible.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ * Rodrigo Moya <rodrigo.moya@canonical.com>
+ */
+
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "unity-util-accessible.h"
+#include "unity-root-accessible.h"
+
+#include "nux-base-window-accessible.h"
+
+static void unity_util_accessible_class_init(UnityUtilAccessibleClass* klass);
+static void unity_util_accessible_init(UnityUtilAccessible* unity_util_accessible);
+
+/* atkutil.h */
+
+static guint unity_util_accessible_add_global_event_listener(GSignalEmissionHook listener,
+ const gchar* event_type);
+static void unity_util_accessible_remove_global_event_listener(guint remove_listener);
+static AtkObject* unity_util_accessible_get_root(void);
+static const gchar* unity_util_accessible_get_toolkit_name(void);
+static const gchar* unity_util_accessible_get_toolkit_version(void);
+static guint unity_util_accessible_add_key_event_listener(AtkKeySnoopFunc listener,
+ gpointer data);
+static void unity_util_accessible_remove_key_event_listener(guint remove_listener);
+
+typedef struct
+{
+ guint idx;
+ gulong hook_id;
+ guint signal_id;
+} UnityUtilListenerInfo;
+
+typedef struct
+{
+ AtkKeySnoopFunc func;
+ gpointer data;
+ guint key;
+} UnityKeyEventListener;
+
+/* FIXME: move this to a private structure on UnityUtilAccessible? */
+static GHashTable* listener_list = NULL;
+static AtkObject* root = NULL;
+static GSList* key_listener_list = NULL;
+static guint event_inspector_id = 0;
+static nux::WindowThread* unity_window_thread = NULL;
+
+G_DEFINE_TYPE(UnityUtilAccessible, unity_util_accessible, ATK_TYPE_UTIL);
+
+static void
+unity_util_accessible_class_init(UnityUtilAccessibleClass* klass)
+{
+ AtkUtilClass* atk_class;
+ gpointer data;
+
+ data = g_type_class_peek(ATK_TYPE_UTIL);
+ atk_class = ATK_UTIL_CLASS(data);
+
+ atk_class->add_global_event_listener = unity_util_accessible_add_global_event_listener;
+ atk_class->remove_global_event_listener = unity_util_accessible_remove_global_event_listener;
+ atk_class->add_key_event_listener = unity_util_accessible_add_key_event_listener;
+ atk_class->remove_key_event_listener = unity_util_accessible_remove_key_event_listener;
+ atk_class->get_root = unity_util_accessible_get_root;
+ atk_class->get_toolkit_name = unity_util_accessible_get_toolkit_name;
+ atk_class->get_toolkit_version = unity_util_accessible_get_toolkit_version;
+}
+
+static void
+unity_util_accessible_init(UnityUtilAccessible* unity_util_accessible)
+{
+}
+
+static AtkObject*
+unity_util_accessible_get_root(void)
+{
+ if (!root)
+ root = unity_root_accessible_new();
+
+ return root;
+}
+
+static const gchar*
+unity_util_accessible_get_toolkit_name(void)
+{
+ return "UNITY";
+}
+
+static const gchar*
+unity_util_accessible_get_toolkit_version(void)
+{
+ /*
+ * FIXME:
+ * Version is passed in as a -D flag when this file is
+ * compiled.
+ */
+ return "0.1";
+}
+
+static guint
+add_listener(GSignalEmissionHook listener,
+ const gchar* object_type,
+ const gchar* signal_name,
+ const gchar* hook_data)
+{
+ GType type;
+ guint signal_id;
+ guint rc = 0;
+ static guint listener_idx = 1;
+
+ if (!listener_list)
+ listener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, g_free);
+
+ type = g_type_from_name(object_type);
+ if (type)
+ {
+ signal_id = g_signal_lookup(signal_name, type);
+ if (signal_id > 0)
+ {
+ UnityUtilListenerInfo* listener_info;
+
+ rc = listener_idx;
+ listener_info = g_new0(UnityUtilListenerInfo, 1);
+ listener_info->idx = listener_idx;
+ listener_info->hook_id = g_signal_add_emission_hook(signal_id, 0, listener,
+ g_strdup(hook_data),
+ (GDestroyNotify) g_free);
+ listener_info->signal_id = signal_id;
+
+ g_hash_table_insert(listener_list, &(listener_info->idx), listener_info);
+
+ listener_idx++;
+ }
+ else
+ {
+ /* Mainly becase some "window::xxx" methods not implemented
+ on NuxBaseWindowAccessible */
+ g_debug("Signal type %s not supported\n", signal_name);
+ }
+ }
+ else
+ g_warning("Invalid object type %s\n", object_type);
+
+ return rc;
+}
+
+static void
+do_window_event_initialization(void)
+{
+ /*
+ * Ensure that NuxBaseWindowClass exists
+ */
+ g_type_class_unref(g_type_class_ref(NUX_TYPE_BASE_WINDOW_ACCESSIBLE));
+}
+
+static guint
+unity_util_accessible_add_global_event_listener(GSignalEmissionHook listener,
+ const gchar* event_type)
+{
+ gchar** split_string;
+ guint rc = 0;
+
+ split_string = g_strsplit(event_type, ":", 3);
+ if (split_string)
+ {
+ if (g_str_equal("window", split_string[0]))
+ {
+ /* Using NuxBaseWindow as the toplevelwindow */
+ static gboolean initialized = FALSE;
+
+ if (initialized == FALSE)
+ {
+ do_window_event_initialization();
+ initialized = TRUE;
+ }
+
+ rc = add_listener(listener, "NuxBaseWindowAccessible", split_string [1], event_type);
+ }
+ else
+ {
+ rc = add_listener(listener, split_string[1], split_string[2], event_type);
+ }
+
+ g_strfreev(split_string);
+ }
+
+ return rc;
+}
+
+static void
+unity_util_accessible_remove_global_event_listener(guint remove_listener)
+{
+ if (remove_listener > 0)
+ {
+ UnityUtilListenerInfo* listener_info;
+
+ listener_info = (UnityUtilListenerInfo*) g_hash_table_lookup(listener_list, &remove_listener);
+ if (listener_info != NULL)
+ {
+ if (listener_info->hook_id != 0 && listener_info->signal_id != 0)
+ {
+ g_signal_remove_emission_hook(listener_info->signal_id,
+ listener_info->hook_id);
+ g_hash_table_remove(listener_list, &remove_listener);
+ }
+ else
+ {
+ g_warning("Invalid listener hook_id %ld or signal_id %d",
+ listener_info->hook_id, listener_info->signal_id);
+ }
+ }
+ else
+ g_warning("No listener with the specified ID: %d", remove_listener);
+ }
+ else
+ g_warning("Invalid listener_id: %d", remove_listener);
+}
+
+static guint
+translate_nux_modifiers_to_gdk_state(unsigned long nux_modifier)
+{
+ guint result = 0;
+
+ if (nux_modifier & nux::NUX_STATE_SHIFT)
+ result |= GDK_SHIFT_MASK;
+
+ if (nux_modifier & nux::NUX_STATE_CAPS_LOCK)
+ result |= GDK_LOCK_MASK;
+
+ if (nux_modifier & nux::NUX_STATE_CTRL)
+ result |= GDK_CONTROL_MASK;
+
+ /* From gdk documentation
+
+ GDK_MOD1_MASK : the fourth modifier key (it depends on the
+ modifier mapping of the X server which key is interpreted as this
+ modifier, but normally it is the Alt key).
+ */
+
+ if (nux_modifier & nux::NUX_STATE_ALT)
+ result |= GDK_MOD1_MASK;
+
+ /* FIXME: not sure how to translate this ones */
+ // if (nux_modifier & NUX_STATE_SCROLLLOCK)
+ // if (nux_modifier & NUX_STATE_NUMLOCK)
+
+ return result;
+}
+
+static AtkKeyEventStruct*
+atk_key_event_from_nux_event_key(nux::Event* event)
+{
+ AtkKeyEventStruct* atk_event = g_new0(AtkKeyEventStruct, 1);
+ gunichar key_unichar;
+ static GdkDisplay* display = gdk_display_get_default();
+ static GdkKeymap* keymap = gdk_keymap_get_for_display(display);
+ GdkKeymapKey* keys = NULL;
+ gint n_keys = 0;
+ gboolean success = FALSE;
+
+ switch (event->type)
+ {
+ case nux::NUX_KEYDOWN:
+ atk_event->type = ATK_KEY_EVENT_PRESS;
+ break;
+ case nux::NUX_KEYUP:
+ atk_event->type = ATK_KEY_EVENT_RELEASE;
+ break;
+ default:
+ /* we don't call atk_key_event_from_nux_event_key if the event
+ is different to keydown or keyup */
+ g_assert_not_reached();
+ g_free(atk_event);
+ return NULL;
+ }
+
+ atk_event->state = translate_nux_modifiers_to_gdk_state(event->key_modifiers);
+
+ atk_event->keyval = event->x11_keysym;
+ atk_event->keycode = event->x11_keycode;
+
+ /* GDK applies the modifiers to the keyval, and ATK expects that, so
+ * we need to do this also here, as it is not done on the release */
+
+ success = gdk_keymap_get_entries_for_keyval(keymap, atk_event->keyval,
+ &keys, &n_keys);
+ success &= n_keys > 0;
+
+ if (success)
+ {
+ gint group;
+ guint new_keyval;
+ gint effective_group;
+ gint level;
+ GdkModifierType consumed;
+
+ group = keys [0].group;
+
+ success = gdk_keymap_translate_keyboard_state(keymap,
+ atk_event->keycode,
+ (GdkModifierType) atk_event->state,
+ group,
+ &new_keyval,
+ &effective_group,
+ &level,
+ &consumed);
+ if (success)
+ atk_event->keyval = new_keyval;
+ }
+
+ atk_event->string = NULL;
+ if (event->text && event->text[0])
+ {
+ key_unichar = g_utf8_get_char(event->text);
+
+ if (g_unichar_validate(key_unichar) && g_unichar_isgraph(key_unichar))
+ {
+ GString* new_string = NULL;
+
+ new_string = g_string_new("");
+ new_string = g_string_insert_unichar(new_string, 0, key_unichar);
+ atk_event->string = new_string->str;
+ g_string_free(new_string, FALSE);
+ }
+ }
+
+ /* If ->string is still NULL we compute it from the keyval*/
+ if (atk_event->string == NULL)
+ atk_event->string = g_strdup(gdk_keyval_name(atk_event->keyval));
+
+ /* e_x11_timestamp is zero, see bug LB#735645*/
+ atk_event->timestamp = g_get_real_time() / 1000;
+
+#ifdef DEBUG_ANY_KEY_EVENT
+ g_debug("[a11y] AtkKeyEvent:\n\t\tsym 0x%x\n\t\tmods %x\n\t\tcode %u\n\t\ttime %lx \n\t\tstring %s\n",
+ (unsigned int) atk_event->keyval,
+ (unsigned int) atk_event->state,
+ (unsigned int) atk_event->keycode,
+ (unsigned long int) atk_event->timestamp,
+ atk_event->string);
+#endif
+
+ return atk_event;
+}
+
+static int
+unity_util_event_inspector(nux::Area* area,
+ nux::Event* event,
+ void* data)
+{
+ GSList* list = NULL;
+ AtkKeyEventStruct* atk_key_event = NULL;
+ gint result = 0;
+
+ if ((event->type != nux::NUX_KEYDOWN) && (event->type != nux::NUX_KEYUP))
+ return 0;
+
+ atk_key_event = atk_key_event_from_nux_event_key(event);
+
+ for (list = key_listener_list; list; list = list->next)
+ {
+ UnityKeyEventListener* listener = (UnityKeyEventListener*) list->data;
+
+ result |= listener->func(atk_key_event, listener->data);
+ }
+
+ g_free(atk_key_event->string);
+ g_free(atk_key_event);
+
+ return result;
+}
+
+static guint
+unity_util_accessible_add_key_event_listener(AtkKeySnoopFunc listener_func,
+ gpointer data)
+{
+ static guint key = 0;
+ UnityKeyEventListener* listener;
+
+ if (event_inspector_id == 0)
+ {
+ if (unity_window_thread == NULL)
+ return 0;
+
+ event_inspector_id = unity_window_thread->InstallEventInspector(unity_util_event_inspector, NULL);
+ }
+
+ key++;
+
+ listener = g_slice_new0(UnityKeyEventListener);
+ listener->func = listener_func;
+ listener->data = data;
+ listener->key = key;
+
+ key_listener_list = g_slist_append(key_listener_list, listener);
+
+ return key;
+}
+
+static void
+unity_util_accessible_remove_key_event_listener(guint remove_listener)
+{
+ GSList* l;
+
+ for (l = key_listener_list; l; l = l->next)
+ {
+ UnityKeyEventListener* listener = (UnityKeyEventListener*) l->data;
+
+ if (listener->key == remove_listener)
+ {
+ g_slice_free(UnityKeyEventListener, listener);
+ key_listener_list = g_slist_delete_link(key_listener_list, l);
+
+ break;
+ }
+ }
+
+ if (key_listener_list == NULL)
+ {
+ if (unity_window_thread == NULL)
+ return;
+
+ unity_window_thread->RemoveEventInspector(event_inspector_id);
+ event_inspector_id = 0;
+ }
+}
+
+/* Public */
+void
+unity_util_accessible_set_window_thread(nux::WindowThread* wt)
+{
+ unity_window_thread = wt;
+}
+
+/*
+ * FIXME: temporal solution
+ *
+ * Normally not all the accessible objects on the hierarchy are
+ * available from the beginning, and they are being created by demand
+ * due the request on the AT (ie: orca) side
+ *
+ * It usually follows a top-down approach. Top objects emits a signal
+ * of interest, so AT apps get interest on it, and request their
+ * children. One example is the signal "window::activate". AT receives
+ * a signal meaning that a top level object is activated, so request
+ * their children (and gran-children).
+ *
+ * Due technical reasons, right now it is hard to find a suitable way
+ * to emit the signal "activate" on the BaseWindow. That means that
+ * objects on the bottom of the hierarchy are not created, so Orca
+ * doesn't react to changes on sections like the Launcher.
+ *
+ * So in order to prevent that, we make a manual exploration of the
+ * hierarchy in order to ensure that those objects are there.
+ *
+ * NOTE: this manual exploration is not required with at-spi2, just
+ * with at-spi.
+ *
+ */
+void
+explore_children(AtkObject* obj)
+{
+ gint num = 0;
+ gint i = 0;
+ AtkObject* atk_child = NULL;
+
+ g_return_if_fail(ATK_IS_OBJECT(obj));
+
+ num = atk_object_get_n_accessible_children(obj);
+
+ for (i = 0; i < num; i++)
+ {
+ atk_child = atk_object_ref_accessible_child(obj, i);
+ explore_children(atk_child);
+ g_object_unref(atk_child);
+ }
+}
diff --git a/a11y/unity-util-accessible.h b/a11y/unity-util-accessible.h
new file mode 100644
index 000000000..8ed12d037
--- /dev/null
+++ b/a11y/unity-util-accessible.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_UTIL_ACCESSIBLE_H
+#define UNITY_UTIL_ACCESSIBLE_H
+
+#include <atk/atk.h>
+
+#include <Nux/Nux.h>
+#include <Nux/BaseWindow.h>
+
+G_BEGIN_DECLS
+
+#define UNITY_TYPE_UTIL_ACCESSIBLE (unity_util_accessible_get_type ())
+#define UNITY_UTIL_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_UTIL_ACCESSIBLE, UnityUtilAccessible))
+#define UNITY_UTIL_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_UTIL_ACCESSIBLE, UnityUtilAccessibleClass))
+#define UNITY_IS_UTIL_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_UTIL_ACCESSIBLE))
+#define UNITY_IS_UTIL_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_UTIL_ACCESSIBLE))
+#define UNITY_UTIL_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_UTIL_ACCESSIBLE, UnityUtilAccessibleClass))
+
+typedef struct _UnityUtilAccessible UnityUtilAccessible;
+typedef struct _UnityUtilAccessibleClass UnityUtilAccessibleClass;
+typedef struct _UnityUtilAccessiblePrivate UnityUtilAccessiblePrivate;
+
+struct _UnityUtilAccessible
+{
+ AtkUtil parent;
+
+ /* < private > */
+ UnityUtilAccessiblePrivate* priv;
+};
+
+struct _UnityUtilAccessibleClass
+{
+ AtkUtilClass parent_class;
+};
+
+GType unity_util_accessible_get_type(void);
+
+void unity_util_accessible_set_window_thread(nux::WindowThread* wt);
+void explore_children(AtkObject* obj);
+
+G_END_DECLS
+
+#endif /* UNITY_UTIL_ACCESSIBLE_H */
diff --git a/a11y/unitya11y.cpp b/a11y/unitya11y.cpp
new file mode 100644
index 000000000..bcd670f5a
--- /dev/null
+++ b/a11y/unitya11y.cpp
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <gmodule.h>
+#include <stdio.h>
+#include <atk-bridge.h>
+
+#include "unitya11y.h"
+#include "unitya11ytests.h"
+#include "unity-util-accessible.h"
+
+/* nux accessible objects */
+#include "nux-view-accessible.h"
+#include "nux-base-window-accessible.h"
+#include "nux-layout-accessible.h"
+#include "nux-text-entry-accessible.h"
+
+/* unity accessible objects */
+#include "Launcher.h"
+#include "LauncherIcon.h"
+#include "SimpleLauncherIcon.h"
+#include "PanelView.h"
+#include "DashView.h"
+#include "PlacesGroup.h"
+#include "ExpanderView.h"
+#include "QuicklistView.h"
+#include "QuicklistMenuItem.h"
+#include "SwitcherView.h"
+#include "TextInput.h"
+#include "SessionButton.h"
+#include "FilterBasicButton.h"
+#include "unity-launcher-accessible.h"
+#include "unity-launcher-icon-accessible.h"
+#include "unity-panel-view-accessible.h"
+#include "unity-dash-view-accessible.h"
+#include "unity-scope-bar-icon-accessible.h"
+#include "unity-search-bar-accessible.h"
+#include "unity-sctext-accessible.h"
+#include "unity-rvgrid-accessible.h"
+#include "unity-places-group-accessible.h"
+#include "unity-expander-view-accessible.h"
+#include "unity-quicklist-accessible.h"
+#include "unity-quicklist-menu-item-accessible.h"
+#include "unity-switcher-accessible.h"
+#include "unity-text-input-accessible.h"
+#include "unity-session-button-accessible.h"
+#include "unity-filter-basic-button-accessible.h"
+
+using namespace unity;
+using namespace unity::dash;
+using namespace unity::launcher;
+using namespace unity::panel;
+using namespace unity::session;
+
+static GHashTable* accessible_table = NULL;
+/* FIXME: remove accessible objects when not required anymore */
+
+static gboolean a11y_initialized = FALSE;
+
+static void
+unity_a11y_restore_environment(void)
+{
+ g_unsetenv("NO_AT_BRIDGE");
+ g_unsetenv("NO_GAIL");
+}
+
+static void
+load_unity_atk_util(nux::WindowThread* wt)
+{
+ unity_util_accessible_set_window_thread(wt);
+ g_type_class_unref(g_type_class_ref(UNITY_TYPE_UTIL_ACCESSIBLE));
+}
+
+/*
+ * In order to avoid the atk-bridge loading and the GAIL
+ * initialization during the gtk_init, it is required to set some
+ * environment vars.
+ *
+ */
+void
+unity_a11y_preset_environment(void)
+{
+ g_setenv("NO_AT_BRIDGE", "1", TRUE);
+ g_setenv("NO_GAIL", "1", TRUE);
+}
+
+/*
+ * Initializes the accessibility (ATK) support on Unity
+ *
+ */
+void
+unity_a11y_init(nux::WindowThread* wt)
+{
+ if (a11y_initialized)
+ return;
+
+ unity_a11y_restore_environment();
+ load_unity_atk_util(wt);
+ atk_bridge_adaptor_init(NULL, NULL);
+ atk_get_root();
+
+ a11y_initialized = TRUE;
+
+// NOTE: we run the unit tests manually while developing by
+// uncommenting this. Take a look at the explanation in the
+// unitya11ytests.h header for more information
+
+// unity_run_a11y_unit_tests ();
+}
+
+/*
+ * Finalize the issues related with accessibility.
+ *
+ * It mainly cleans the resources related with accessibility
+ */
+void
+unity_a11y_finalize(void)
+{
+ if (accessible_table != NULL)
+ {
+ g_hash_table_unref(accessible_table);
+ accessible_table = NULL;
+ }
+ a11y_initialized = FALSE;
+}
+
+
+/*
+ * Creates the accessible object for a nux::Area object
+ *
+ * Method factory, equivalent to
+ * atk_object_factory_creeate_accessible, but required because
+ * AtkObjectFactory gives only support for GObject classes.
+ *
+ * FIXME: this should be a temporal method. The best way to implement
+ * that would be add a ->get_accessible method on the nux::View
+ * subclasses itself.
+ *
+ * WARNING: as a reason the previous comment is true. Take into
+ * account that you should be careful with the order in which you add
+ * those defines. The order will be from more specific classes to more
+ * abstracted classes.
+ *
+ */
+
+static AtkObject*
+unity_a11y_create_accessible(nux::Object* object)
+{
+ /* UNITY classes*/
+ if (object->Type().IsDerivedFromType(Launcher::StaticObjectType))
+ return unity_launcher_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(LauncherIcon::StaticObjectType))
+ return unity_launcher_icon_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(PanelView::StaticObjectType))
+ return unity_panel_view_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(DashView::StaticObjectType))
+ return unity_dash_view_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(ScopeBarIcon::StaticObjectType))
+ return unity_scope_bar_icon_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(PlacesGroup::StaticObjectType))
+ return unity_places_group_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(ExpanderView::StaticObjectType))
+ return unity_expander_view_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(FilterBasicButton::StaticObjectType))
+ return unity_filter_basic_button_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(QuicklistView::StaticObjectType))
+ return unity_quicklist_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(QuicklistMenuItem::StaticObjectType))
+ return unity_quicklist_menu_item_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(StaticCairoText::StaticObjectType))
+ return unity_sctext_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(unity::dash::ResultViewGrid::StaticObjectType))
+ return unity_rvgrid_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(unity::SearchBar::StaticObjectType))
+ return unity_search_bar_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(unity::TextInput::StaticObjectType))
+ return unity_text_input_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(unity::switcher::SwitcherView::StaticObjectType))
+ return unity_switcher_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(Button::StaticObjectType))
+ return unity_session_button_accessible_new(object);
+
+ /* NUX classes */
+ if (object->Type().IsDerivedFromType(nux::TextEntry::StaticObjectType))
+ return nux_text_entry_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(nux::BaseWindow::StaticObjectType))
+ return nux_base_window_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(nux::View::StaticObjectType))
+ return nux_view_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(nux::Layout::StaticObjectType))
+ return nux_layout_accessible_new(object);
+
+ if (object->Type().IsDerivedFromType(nux::Area::StaticObjectType))
+ return nux_area_accessible_new(object);
+
+ return nux_object_accessible_new(object);
+}
+
+static void
+on_object_destroy_cb(nux::Object* base_object,
+ AtkObject* accessible_object)
+{
+ /* NOTE: the pair key:value (base_object:accessible_object) could be
+ already removed on on_accessible_destroy_cb. That just means that
+ g_hash_table_remove would return FALSE. We don't add a
+ debug/warning message to avoid being too verbose */
+
+ g_hash_table_remove(accessible_table, base_object);
+}
+
+static void
+on_accessible_destroy_cb(gpointer data,
+ GObject* where_the_object_was)
+{
+ /* NOTE: the pair key:value (base_object:accessible_object) could be
+ already removed on on_object_destroy_cb. That just means that
+ g_hash_table_remove would return FALSE. We don't add a
+ debug/warning message to avoid being too verbose */
+
+ g_hash_table_remove(accessible_table, data);
+}
+
+/*
+ * Returns the accessible object of a nux::View object
+ *
+ * This method tries to:
+ * * Check if area already has a accessibility object
+ * * If this is the case, return that
+ * * If not, create it and return the object
+ *
+ * FIXME: this should be a temporal method. The best way to implement
+ * that would be add a ->get_accessible method on the nux::View
+ * subclasses itself.
+ *
+ */
+AtkObject*
+unity_a11y_get_accessible(nux::Object* object)
+{
+ AtkObject* accessible_object = NULL;
+
+ g_return_val_if_fail(object != NULL, NULL);
+
+ if (accessible_table == NULL)
+ {
+ accessible_table = g_hash_table_new(g_direct_hash, g_direct_equal);
+ }
+
+ accessible_object = ATK_OBJECT(g_hash_table_lookup(accessible_table, object));
+ if (accessible_object == NULL)
+ {
+ accessible_object = unity_a11y_create_accessible(object);
+
+ g_hash_table_insert(accessible_table, object, accessible_object);
+
+ /* there are two reasons the object should be removed from the
+ * table: base object destroyed or accessible object
+ * destroyed
+ */
+ g_object_weak_ref(G_OBJECT(accessible_object),
+ on_accessible_destroy_cb,
+ object);
+
+ object->OnDestroyed.connect(sigc::bind(sigc::ptr_fun(on_object_destroy_cb),
+ accessible_object));
+ }
+
+ return accessible_object;
+}
+
+/*
+ * Returns if the accessibility support is properly initialized
+ */
+gboolean unity_a11y_initialized(void)
+{
+ return a11y_initialized;
+}
+
+/* Returns the accessible_table. Just for unit testing purposes, you
+ should not require to use it */
+GHashTable* _unity_a11y_get_accessible_table()
+{
+ return accessible_table;
+}
diff --git a/a11y/unitya11y.h b/a11y/unitya11y.h
new file mode 100644
index 000000000..37b81e515
--- /dev/null
+++ b/a11y/unitya11y.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_A11Y_H
+#define UNITY_A11Y_H
+
+#include <atk/atk.h>
+
+#include <Nux/Nux.h>
+#include <Nux/WindowThread.h>
+#include <NuxCore/Object.h>
+
+void unity_a11y_preset_environment(void);
+void unity_a11y_init(nux::WindowThread* wt);
+void unity_a11y_finalize(void);
+
+AtkObject* unity_a11y_get_accessible(nux::Object* object);
+
+gboolean unity_a11y_initialized(void);
+
+/* For unit test purposes */
+
+GHashTable* _unity_a11y_get_accessible_table();
+
+#endif /* UNITY_A11Y_H */
diff --git a/a11y/unitya11ytests.cpp b/a11y/unitya11ytests.cpp
new file mode 100644
index 000000000..efc7968ca
--- /dev/null
+++ b/a11y/unitya11ytests.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#include "unitya11ytests.h"
+
+#include <glib.h>
+
+#include "unitya11y.h"
+#include "unity-util-accessible.h"
+
+/* nux accessible objects */
+#include "nux-view-accessible.h"
+#include "nux-base-window-accessible.h"
+#include "nux-layout-accessible.h"
+
+/* unity accessible objects */
+#include <Nux/Button.h>
+
+#include "Launcher.h"
+#include "LauncherIcon.h"
+#include "SimpleLauncherIcon.h"
+#include "PanelView.h"
+#include "DashView.h"
+#include "unity-launcher-accessible.h"
+#include "unity-launcher-icon-accessible.h"
+#include "unity-panel-view-accessible.h"
+
+using unity::launcher::Launcher;
+using unity::launcher::LauncherIcon;
+using unity::launcher::SimpleLauncherIcon;
+
+/*
+ * This unit test checks if the destroy management is working:
+ *
+ * - If the state of a accessibility object is properly updated after
+ * the object's destruction
+ *
+ */
+static gboolean
+a11y_unit_test_destroy_management(void)
+{
+ unity::QuicklistView* quicklist = NULL;
+ AtkObject* accessible = NULL;
+ nux::Object* base_object = NULL;
+ AtkStateSet* state_set = NULL;
+
+ quicklist = new unity::QuicklistView();
+ quicklist->SinkReference();
+ accessible = unity_a11y_get_accessible(quicklist);
+
+ base_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ if (base_object != quicklist)
+ {
+ g_debug("[a11y] destroy management unit test: base object"
+ " different to the original one");
+ return FALSE;
+ }
+
+ if (quicklist->UnReference() == false)
+ {
+ g_debug("[a11y] destroy management unit test: base object not destroyed");
+ return FALSE;
+ }
+
+ base_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
+ if (base_object != NULL)
+ {
+ g_debug("[a11y] destroy management unit test: base object"
+ " not NULL after base object destruction");
+ return FALSE;
+ }
+
+ state_set = atk_object_ref_state_set(accessible);
+ if (!atk_state_set_contains_state(state_set, ATK_STATE_DEFUNCT))
+ {
+ g_debug("[a11y] destroy management unit test: accessible object"
+ " doesn't include DEFUNCT state");
+ return FALSE;
+ }
+
+ g_object_unref(state_set);
+ g_object_unref(accessible);
+
+ return TRUE;
+}
+
+/**
+ * This unit test checks if the hash table destroy management is working:
+ *
+ * - If the hash table removes properly the accessible object once it
+ * is destroyed.
+ */
+static gboolean
+a11y_unit_test_hash_table_destroy_management(void)
+{
+ unity::QuicklistView* quicklist = NULL;
+ nux::Layout* layout = NULL;
+ AtkObject* accessible = NULL;
+ guint prev_hash_size = 0;
+ guint hash_size = 0;
+
+ /* test the hash table management with the accessible destroy */
+
+ prev_hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ layout = new nux::Layout();
+ layout->SinkReference();
+ accessible = unity_a11y_get_accessible(layout);
+
+ if (accessible == NULL)
+ {
+ g_debug("[a11y] hash table destroy management unit test: error creating"
+ " the accessible object (accessible == NULL)");
+ return FALSE;
+ }
+
+ hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ if ((hash_size - prev_hash_size) != 1)
+ {
+ g_debug("[a11y] hash table destroy management unit test: accessible object"
+ " not added to the hash table after his creation");
+ return FALSE;
+ }
+
+ prev_hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ g_object_unref(accessible);
+
+ hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ if ((prev_hash_size - hash_size) != 1)
+ {
+ g_debug("[a11y] hash table destroy management unit test: accessible object"
+ " not removed from the hash table after his destruction");
+ return FALSE;
+ }
+
+ layout->UnReference();
+
+ /* Test the hash table management after the object destroy */
+
+ prev_hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ quicklist = new unity::QuicklistView();
+ quicklist->SinkReference();
+ accessible = unity_a11y_get_accessible(quicklist);
+
+ if (accessible == NULL)
+ {
+ g_debug("[a11y] hash table destroy management unit test: error creating"
+ " the accessible object (accessible == NULL)");
+ return FALSE;
+ }
+
+ hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ if ((hash_size - prev_hash_size) != 1)
+ {
+ g_debug("[a11y] hash table destroy management unit test: accessible object"
+ " not added to the hash table after his creation");
+ return FALSE;
+ }
+
+ prev_hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ if (quicklist->UnReference() == false)
+ {
+ g_debug("[a11y] hash table destroy management unit test: base object not destroyed");
+ return FALSE;
+ }
+
+ hash_size = g_hash_table_size(_unity_a11y_get_accessible_table());
+
+ if ((prev_hash_size - hash_size) != 1)
+ {
+ g_debug("[a11y] hash table destroy management unit test: accessible object"
+ " not removed from the hash table after base object destruction");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * This unit test checks if the launcher connection process works
+ */
+static gboolean
+a11y_unit_test_launcher_connection(void)
+{
+ Launcher* launcher = NULL;
+ unity::MockableBaseWindow* window = NULL;
+ AtkObject* launcher_accessible = NULL;
+ LauncherIcon* launcher_icon = NULL;
+ AtkObject* launcher_icon_accessible = NULL;
+
+ window = new unity::MockableBaseWindow(TEXT(""));
+ launcher = new Launcher(window, NULL);
+ launcher->SinkReference();
+ launcher_accessible = unity_a11y_get_accessible(launcher);
+
+ if (!UNITY_IS_LAUNCHER_ACCESSIBLE(launcher_accessible))
+ {
+ g_debug("[a11y] wrong launcher accessible type");
+ return FALSE;
+ }
+ else
+ {
+ g_debug("[a11y] Launcher accessible created correctly");
+ }
+
+ launcher_icon = new SimpleLauncherIcon(unity::launcher::AbstractLauncherIcon::IconType::NONE);
+ launcher_icon->SinkReference();
+ launcher_icon_accessible = unity_a11y_get_accessible(launcher_icon);
+
+ if (!UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(launcher_icon_accessible))
+ {
+ g_debug("[a11y] wrong launcher icon accessible type");
+ return FALSE;
+ }
+ else
+ {
+ g_debug("[a11y] LauncherIcon accessible created correctly");
+ }
+
+ launcher->UnReference();
+ launcher_icon->UnReference();
+
+ return TRUE;
+}
+
+/**
+ * This unit test checks if the launcher connection process works
+ */
+static gboolean
+a11y_unit_test_children_addition(void)
+{
+ nux::View* view[3];
+ AtkObject* view_accessible[3];
+ nux::Layout* layout[2];
+ AtkObject* layout_accessible[2];
+ gint i = 0;
+
+ /* Test setting a layout on a view */
+ view[0] = new nux::Button("Test");
+ view[0]->SinkReference();
+ view_accessible[0] = unity_a11y_get_accessible(view[0]);
+
+ for (i = 0; i < 2; i++)
+ {
+ layout[i] = new nux::Layout();
+ layout[i]->SinkReference();
+ layout_accessible[i] = unity_a11y_get_accessible(layout[i]);
+ }
+
+ view[0]->SetLayout(layout[0]);
+ view[0]->SetLayout(layout[0]);
+
+ view[0]->UnReference();
+ g_object_unref(view_accessible[0]);
+
+ for (i = 0; i < 2; i++)
+ {
+ layout[i]->UnReference();
+ g_object_unref(layout_accessible[i]);
+ }
+
+ /* Test adding a view on a layout */
+ layout[0] = new nux::Layout();
+ layout[0]->SinkReference();
+ layout_accessible[0] = unity_a11y_get_accessible(layout[0]);
+
+ for (i = 0; i < 3; i ++)
+ {
+ view[i] = new nux::Button("Test");
+ view[i]->SinkReference();
+ view_accessible[i] = unity_a11y_get_accessible(view[i]);
+
+ layout[0]->AddView(view[i]);
+ }
+
+ /* when this is removed it should be notified the removal with index 1*/
+ layout[0]->RemoveChildObject(view[1]);
+ layout[0]->UnReference();
+ for (i = 0; i < 3; i++)
+ {
+ view[i]->UnReference();
+ g_object_unref(view_accessible [i]);
+ }
+
+ return TRUE;
+}
+
+/* public */
+
+void
+unity_run_a11y_unit_tests(void)
+{
+ if (a11y_unit_test_destroy_management())
+ g_debug("[a11y] destroy management unit test: SUCCESS");
+ else
+ g_debug("[a11y] destroy management unit test: FAIL");
+
+ if (a11y_unit_test_hash_table_destroy_management())
+ g_debug("[a11y] hash table destroy management unit test: SUCCESS");
+ else
+ g_debug("[a11y] hash table destroy management unit test: FAIL");
+
+ if (a11y_unit_test_launcher_connection())
+ g_debug("[a11y] launcher connection: SUCCESS");
+ else
+ g_debug("[a11y] launcher connection: FAIL");
+
+ if (a11y_unit_test_children_addition())
+ g_debug("[a11y] children addition: SUCCESS");
+ else
+ g_debug("[a11y] children addition: FAIL");
+}
diff --git a/a11y/unitya11ytests.h b/a11y/unitya11ytests.h
new file mode 100644
index 000000000..cfb3631b3
--- /dev/null
+++ b/a11y/unitya11ytests.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
+ */
+
+#ifndef UNITY_A11Y_TESTS_H
+#define UNITY_A11Y_TESTS_H
+
+/* For the moment we can't add the a11y tests to the current unity
+ tests, as it would require to include the Launcher, that right now
+ include symbols only available to a compiz plugin (so not available
+ for a standalone app.
+
+ So right now this tests are executed by hand during the developing
+ of the accessibility support, but not executed as a standalone test.
+
+ When the Launcher thing became solved (as planned), this tests
+ would be moved/adapted to the unity test system */
+
+void unity_run_a11y_unit_tests(void);
+
+#endif /* UNITY_A11Y_H */