Merge lp:~apinheiro/unity/a11y-switcher into lp:unity

Proposed by Alejandro Piñeiro
Status: Merged
Approved by: Alex Launi
Approved revision: no longer in the source branch.
Merged at revision: 1811
Proposed branch: lp:~apinheiro/unity/a11y-switcher
Merge into: lp:unity
Prerequisite: lp:~apinheiro/unity/a11y-improve-window-event-emission
Diff against target: 855 lines (+567/-80)
9 files modified
plugins/unityshell/src/nux-area-accessible.cpp (+4/-3)
plugins/unityshell/src/nux-area-accessible.h (+4/-1)
plugins/unityshell/src/nux-view-accessible.cpp (+4/-4)
plugins/unityshell/src/unity-launcher-accessible.cpp (+5/-1)
plugins/unityshell/src/unity-launcher-icon-accessible.cpp (+66/-71)
plugins/unityshell/src/unity-root-accessible.cpp (+5/-0)
plugins/unityshell/src/unity-switcher-accessible.cpp (+417/-0)
plugins/unityshell/src/unity-switcher-accessible.h (+57/-0)
plugins/unityshell/src/unitya11y.cpp (+5/-0)
To merge this branch: bzr merge lp:~apinheiro/unity/a11y-switcher
Reviewer Review Type Date Requested Status
Alex Launi (community) Approve
Neil J. Patel Pending
Review via email: mp+79291@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Alejandro Piñeiro (apinheiro) wrote :

BTW, this branch is already being tested by the users, as it is included on this branch:

https://launchpad.net/~apinheiro/+archive/unity-extra-a11y

I already received some positive feedback from ubuntu-accessibility mailing list

Revision history for this message
Alex Launi (alexlauni) wrote :

Again, sorry for the large delay. This looks great.

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/nux-area-accessible.cpp'
2--- plugins/unityshell/src/nux-area-accessible.cpp 2011-11-07 22:37:27 +0000
3+++ plugins/unityshell/src/nux-area-accessible.cpp 2011-11-07 22:37:27 +0000
4@@ -177,9 +177,10 @@
5 atk_component_add_focus_handler(ATK_COMPONENT(accessible),
6 nux_area_accessible_focus_handler);
7
8- /* NOTE: we can't search for the parent window on initilization, or
9- we could enter on a infinite loop, as this is called on the
10- initalization */
11+ /* NOTE: we can't search for the parent window on initilization as a
12+ general rule, or we could enter on a infinite loop. At area this
13+ is done on the focus event. On the Switcher this is done on their
14+ initialize itself */
15 }
16
17 static AtkObject*
18
19=== modified file 'plugins/unityshell/src/nux-area-accessible.h'
20--- plugins/unityshell/src/nux-area-accessible.h 2011-08-01 17:53:14 +0000
21+++ plugins/unityshell/src/nux-area-accessible.h 2011-11-07 22:37:27 +0000
22@@ -49,7 +49,10 @@
23 NuxObjectAccessibleClass parent_class;
24
25 /*
26- * Virtual method to check if there is any pending state change notification
27+ * Usually objects shouldn emit events like focus or selection
28+ * changes until the toplevel window is active. This method is
29+ * called when the toplevel window became active. Redefine it if you
30+ * need to check any pending state change notification.
31 */
32 gboolean(*check_pending_notification)(NuxAreaAccessible* self);
33
34
35=== modified file 'plugins/unityshell/src/nux-view-accessible.cpp'
36--- plugins/unityshell/src/nux-view-accessible.cpp 2011-11-07 22:37:27 +0000
37+++ plugins/unityshell/src/nux-view-accessible.cpp 2011-11-07 22:37:27 +0000
38@@ -45,13 +45,13 @@
39 static gint nux_view_accessible_get_n_children(AtkObject* obj);
40 static AtkObject* nux_view_accessible_ref_child(AtkObject* obj,
41 gint i);
42+static AtkStateSet* nux_view_accessible_ref_state_set(AtkObject* obj);
43+static gint nux_view_accessible_get_n_children(AtkObject* obj);
44+static AtkObject* nux_view_accessible_ref_child(AtkObject* obj,
45+ gint i);
46 /* NuxAreaAccessible */
47 static gboolean nux_view_accessible_check_pending_notification(NuxAreaAccessible* self);
48
49-static AtkStateSet* nux_view_accessible_ref_state_set(AtkObject* obj);
50-static gint nux_view_accessible_get_n_children(AtkObject* obj);
51-static AtkObject* nux_view_accessible_ref_child(AtkObject* obj,
52- gint i);
53 /* private methods */
54 static void on_layout_changed_cb(nux::View* view,
55 nux::Layout* layout,
56
57=== modified file 'plugins/unityshell/src/unity-launcher-accessible.cpp'
58--- plugins/unityshell/src/unity-launcher-accessible.cpp 2011-11-07 22:37:27 +0000
59+++ plugins/unityshell/src/unity-launcher-accessible.cpp 2011-11-07 22:37:27 +0000
60@@ -36,7 +36,6 @@
61 #include "unitya11y.h"
62 #include "Launcher.h"
63 #include "LauncherModel.h"
64-#include "QuicklistView.h"
65
66 using unity::launcher::Launcher;
67 using unity::launcher::LauncherIcon;
68@@ -211,6 +210,7 @@
69 LauncherModel::iterator it;
70 nux::Object* child = NULL;
71 AtkObject* child_accessible = NULL;
72+ AtkObject* parent = NULL;
73
74 g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(obj), NULL);
75 num = atk_object_get_n_accessible_children(obj);
76@@ -230,6 +230,10 @@
77 child = dynamic_cast<nux::Object*>(*it);
78 child_accessible = unity_a11y_get_accessible(child);
79
80+ parent = atk_object_get_parent(child_accessible);
81+ if (parent != obj)
82+ atk_object_set_parent(child_accessible, obj);
83+
84 g_object_ref(child_accessible);
85
86 return child_accessible;
87
88=== modified file 'plugins/unityshell/src/unity-launcher-icon-accessible.cpp'
89--- plugins/unityshell/src/unity-launcher-icon-accessible.cpp 2011-11-07 22:37:27 +0000
90+++ plugins/unityshell/src/unity-launcher-icon-accessible.cpp 2011-11-07 22:37:27 +0000
91@@ -26,6 +26,19 @@
92 * nux::LauncherIcon, exposing the common elements on each basic individual
93 * element (position, extents, etc)
94 *
95+ * Implementation notes: on previous implementations we implemented
96+ * _get_parent using the LauncherIcon method GetLauncher. But this is
97+ * not the case in all the situations. When the user is interacting
98+ * with the Switcher, we consider that the parent of that LauncherIcon
99+ * is the Switcher.
100+ *
101+ * The parent is set with atk_object_set_parent as usual.
102+ *
103+ * As this object is used both on UnityLauncherAccessible and
104+ * UnitySwitcherAccessible, we have removed as much as possible any
105+ * reference to the Launcher, LauncherModel, SwitcherView or
106+ * SwitcherModel.
107+ *
108 */
109
110 #include "unity-launcher-icon-accessible.h"
111@@ -49,7 +62,7 @@
112 gpointer data);
113 static AtkStateSet* unity_launcher_icon_accessible_ref_state_set(AtkObject* obj);
114 static const gchar* unity_launcher_icon_accessible_get_name(AtkObject* obj);
115-static AtkObject* unity_launcher_icon_accessible_get_parent(AtkObject* obj);
116+// static AtkObject* unity_launcher_icon_accessible_get_parent(AtkObject* obj);
117 static gint unity_launcher_icon_accessible_get_index_in_parent(AtkObject* obj);
118
119 /* AtkComponent.h */
120@@ -86,6 +99,7 @@
121 gboolean parent_focused;
122 gboolean index_in_parent;
123
124+ guint on_parent_change_id;
125 guint on_parent_selection_change_id;
126 guint on_parent_focus_event_id;
127 };
128@@ -102,7 +116,7 @@
129 atk_class->initialize = unity_launcher_icon_accessible_initialize;
130 atk_class->get_name = unity_launcher_icon_accessible_get_name;
131 atk_class->ref_state_set = unity_launcher_icon_accessible_ref_state_set;
132- atk_class->get_parent = unity_launcher_icon_accessible_get_parent;
133+ // atk_class->get_parent = unity_launcher_icon_accessible_get_parent;
134 atk_class->get_index_in_parent = unity_launcher_icon_accessible_get_index_in_parent;
135
136 g_type_class_add_private(gobject_class, sizeof(UnityLauncherIconAccessiblePrivate));
137@@ -125,7 +139,7 @@
138
139 parent = atk_object_get_parent(ATK_OBJECT(object));
140
141- if (UNITY_IS_LAUNCHER_ACCESSIBLE(parent))
142+ if (parent != NULL)
143 {
144 if (self->priv->on_parent_selection_change_id != 0)
145 g_signal_handler_disconnect(parent, self->priv->on_parent_selection_change_id);
146@@ -134,6 +148,9 @@
147 g_signal_handler_disconnect(parent, self->priv->on_parent_focus_event_id);
148 }
149
150+ if (self->priv->on_parent_change_id != 0)
151+ g_signal_handler_disconnect(object, self->priv->on_parent_change_id);
152+
153 G_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->dispose(object);
154 }
155
156@@ -154,41 +171,56 @@
157
158 /* AtkObject.h */
159 static void
160+on_parent_change_cb(gchar* property,
161+ GValue* value,
162+ gpointer data)
163+{
164+ AtkObject* parent = NULL;
165+ UnityLauncherIconAccessible* self = NULL;
166+ AtkStateSet* state_set = NULL;
167+
168+ g_return_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(data));
169+
170+ self = UNITY_LAUNCHER_ICON_ACCESSIBLE(data);
171+ parent = atk_object_get_parent(ATK_OBJECT(data));
172+
173+ if (parent == NULL)
174+ return;
175+
176+ self->priv->on_parent_selection_change_id =
177+ g_signal_connect(parent, "selection-changed",
178+ G_CALLBACK(on_parent_selection_change_cb), self);
179+
180+ self->priv->on_parent_focus_event_id =
181+ g_signal_connect(parent, "focus-event",
182+ G_CALLBACK(on_parent_focus_event_cb), self);
183+
184+ state_set = atk_object_ref_state_set(parent);
185+ if (atk_state_set_contains_state(state_set, ATK_STATE_FOCUSED))
186+ {
187+ self->priv->parent_focused = TRUE;
188+ }
189+ g_object_unref(state_set);
190+}
191+
192+static void
193 unity_launcher_icon_accessible_initialize(AtkObject* accessible,
194 gpointer data)
195 {
196- LauncherIcon* icon = NULL;
197- Launcher* launcher = NULL;
198- UnityLauncherAccessible* launcher_accessible = NULL;
199 UnityLauncherIconAccessible* self = NULL;
200- nux::Object* nux_object = NULL;
201
202 ATK_OBJECT_CLASS(unity_launcher_icon_accessible_parent_class)->initialize(accessible, data);
203 self = UNITY_LAUNCHER_ICON_ACCESSIBLE(accessible);
204
205 accessible->role = ATK_ROLE_PUSH_BUTTON;
206
207- nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
208- icon = dynamic_cast<LauncherIcon*>(nux_object);
209- launcher = icon->GetLauncher();
210-
211- if (launcher == NULL)
212- return;
213-
214- /* NOTE: we could also get the launcher_accessible by just calling
215- atk_object_get_parent */
216- launcher_accessible = UNITY_LAUNCHER_ACCESSIBLE(unity_a11y_get_accessible(launcher));
217-
218- self->priv->on_parent_selection_change_id =
219- g_signal_connect(launcher_accessible, "selection-changed",
220- G_CALLBACK(on_parent_selection_change_cb), self);
221-
222- self->priv->on_parent_focus_event_id =
223- g_signal_connect(launcher_accessible, "focus-event",
224- G_CALLBACK(on_parent_focus_event_cb), self);
225-
226 atk_component_add_focus_handler(ATK_COMPONENT(accessible),
227 unity_launcher_icon_accessible_focus_handler);
228+
229+ /* we could do that by redefining ->set_parent */
230+ self->priv->on_parent_change_id =
231+ g_signal_connect(accessible, "notify::accessible-parent",
232+ G_CALLBACK(on_parent_change_cb), self);
233 }
234
235
236@@ -256,31 +288,6 @@
237 return state_set;
238 }
239
240-static AtkObject*
241-unity_launcher_icon_accessible_get_parent(AtkObject* obj)
242-{
243- nux::Object* nux_object = NULL;
244- LauncherIcon* icon = NULL;
245- Launcher* launcher = NULL;
246-
247- g_return_val_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(obj), NULL);
248-
249- if (obj->accessible_parent)
250- return obj->accessible_parent;
251-
252- nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
253-
254- if (nux_object == NULL) /* defunct */
255- return NULL;
256-
257- icon = dynamic_cast<LauncherIcon*>(nux_object);
258- launcher = icon->GetLauncher();
259-
260- g_return_val_if_fail(dynamic_cast<Launcher*>(launcher), NULL);
261-
262- return unity_a11y_get_accessible(launcher);
263-}
264-
265 /* private methods */
266
267 /*
268@@ -290,27 +297,15 @@
269 static void
270 check_selected(UnityLauncherIconAccessible* self)
271 {
272- LauncherIcon* icon = NULL;
273- LauncherIcon* selected_icon = NULL;
274- Launcher* launcher = NULL;
275- nux::Object* nux_object = NULL;
276+ AtkObject* parent = NULL;
277 gboolean found = FALSE;
278
279- nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
280-
281- if (nux_object == NULL) /* state is defunct */
282- return;
283-
284- icon = dynamic_cast<LauncherIcon*>(nux_object);
285- launcher = icon->GetLauncher();
286-
287- if (launcher == NULL)
288- return;
289-
290- selected_icon = launcher->GetSelectedMenuIcon();
291-
292- if (icon == selected_icon)
293- found = TRUE;
294+ parent = atk_object_get_parent(ATK_OBJECT(self));
295+ if (parent == NULL)
296+ return;
297+
298+ found = atk_selection_is_child_selected(ATK_SELECTION(parent),
299+ self->priv->index_in_parent);
300
301 if ((found) && (self->priv->parent_focused == FALSE))
302 return;
303@@ -326,6 +321,7 @@
304 atk_object_notify_state_change(ATK_OBJECT(self),
305 ATK_STATE_ACTIVE,
306 found);
307+
308 g_signal_emit_by_name(self, "focus-event", self->priv->selected, &return_val);
309 atk_focus_tracker_notify(ATK_OBJECT(self));
310 }
311@@ -335,7 +331,6 @@
312 on_parent_selection_change_cb(AtkSelection* selection,
313 gpointer data)
314 {
315- g_return_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(selection));
316 g_return_if_fail(UNITY_IS_LAUNCHER_ICON_ACCESSIBLE(data));
317
318 check_selected(UNITY_LAUNCHER_ICON_ACCESSIBLE(data));
319
320=== modified file 'plugins/unityshell/src/unity-root-accessible.cpp'
321--- plugins/unityshell/src/unity-root-accessible.cpp 2011-11-07 22:37:27 +0000
322+++ plugins/unityshell/src/unity-root-accessible.cpp 2011-11-07 22:37:27 +0000
323@@ -258,6 +258,9 @@
324 window_accessible =
325 unity_a11y_get_accessible(window);
326
327+ /* FIXME: temporal */
328+ atk_object_set_name (window_accessible, window->GetWindowName().GetTCharPtr());
329+
330 if (g_slist_find(self->priv->window_list, window_accessible))
331 return;
332
333@@ -293,6 +296,8 @@
334 window_accessible =
335 unity_a11y_get_accessible(window);
336
337+ return;
338+
339 if (!g_slist_find(self->priv->window_list, window_accessible))
340 return;
341
342
343=== added file 'plugins/unityshell/src/unity-switcher-accessible.cpp'
344--- plugins/unityshell/src/unity-switcher-accessible.cpp 1970-01-01 00:00:00 +0000
345+++ plugins/unityshell/src/unity-switcher-accessible.cpp 2011-11-07 22:37:27 +0000
346@@ -0,0 +1,417 @@
347+/*
348+ * Copyright (C) 2011 Canonical Ltd
349+ *
350+ * This program is free software: you can redistribute it and/or modify
351+ * it under the terms of the GNU General Public License version 3 as
352+ * published by the Free Software Foundation.
353+ *
354+ * This program is distributed in the hope that it will be useful,
355+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
356+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
357+ * GNU General Public License for more details.
358+ *
359+ * You should have received a copy of the GNU General Public License
360+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
361+ *
362+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
363+ */
364+
365+/**
366+ * SECTION:unity-switcher-accessible
367+ * @Title: UnitySwitcherAccessible
368+ * @short_description: Implementation of the ATK interfaces for #SwitcherView
369+ * @see_also: SwitcherView
370+ *
371+ * #UnitySwitcherAccessible implements the required ATK interfaces for
372+ * #SwitcherView, ie: exposing the different AbstractLauncherIcon on the
373+ * #model as child of the object.
374+ *
375+ */
376+
377+#include <glib/gi18n.h>
378+
379+#include "unity-switcher-accessible.h"
380+#include "unity-launcher-icon-accessible.h"
381+
382+#include "unitya11y.h"
383+#include "SwitcherView.h"
384+#include "SwitcherModel.h"
385+
386+using namespace unity::switcher;
387+using namespace unity::launcher;
388+
389+/* GObject */
390+static void unity_switcher_accessible_class_init(UnitySwitcherAccessibleClass* klass);
391+static void unity_switcher_accessible_init(UnitySwitcherAccessible* self);
392+static void unity_switcher_accessible_finalize(GObject* object);
393+
394+/* AtkObject.h */
395+static void unity_switcher_accessible_initialize(AtkObject* accessible,
396+ gpointer data);
397+static gint unity_switcher_accessible_get_n_children(AtkObject* obj);
398+static AtkObject* unity_switcher_accessible_ref_child(AtkObject* obj,
399+ gint i);
400+static AtkStateSet* unity_switcher_accessible_ref_state_set(AtkObject* obj);
401+
402+/* AtkSelection */
403+static void atk_selection_interface_init(AtkSelectionIface* iface);
404+static AtkObject* unity_switcher_accessible_ref_selection(AtkSelection* selection,
405+ gint i);
406+static gint unity_switcher_accessible_get_selection_count(AtkSelection* selection);
407+static gboolean unity_switcher_accessible_is_child_selected(AtkSelection* selection,
408+ gint i);
409+/* NuxAreaAccessible */
410+static gboolean unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self);
411+
412+/* private */
413+static void on_selection_changed_cb(AbstractLauncherIcon* icon,
414+ UnitySwitcherAccessible* switcher_accessible);
415+static void create_children(UnitySwitcherAccessible* self);
416+
417+
418+G_DEFINE_TYPE_WITH_CODE(UnitySwitcherAccessible, unity_switcher_accessible, NUX_TYPE_VIEW_ACCESSIBLE,
419+ G_IMPLEMENT_INTERFACE(ATK_TYPE_SELECTION, atk_selection_interface_init))
420+
421+#define UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(obj) \
422+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE, \
423+ UnitySwitcherAccessiblePrivate))
424+
425+struct _UnitySwitcherAccessiblePrivate
426+{
427+ /* We maintain the children. Although the LauncherIcon are shared
428+ * between the Switcher and Launcher, in order to keep a hierarchy
429+ * coherence, we create a different accessible object */
430+ GSList* children;
431+
432+ sigc::connection on_selection_changed_connection;
433+};
434+
435+
436+static void
437+unity_switcher_accessible_class_init(UnitySwitcherAccessibleClass* klass)
438+{
439+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
440+ AtkObjectClass* atk_class = ATK_OBJECT_CLASS(klass);
441+ NuxAreaAccessibleClass* area_class = NUX_AREA_ACCESSIBLE_CLASS(klass);
442+
443+ gobject_class->finalize = unity_switcher_accessible_finalize;
444+
445+ /* AtkObject */
446+ atk_class->get_n_children = unity_switcher_accessible_get_n_children;
447+ atk_class->ref_child = unity_switcher_accessible_ref_child;
448+ atk_class->initialize = unity_switcher_accessible_initialize;
449+ atk_class->ref_state_set = unity_switcher_accessible_ref_state_set;
450+
451+ /* NuxAreaAccessible */
452+ area_class->check_pending_notification = unity_switcher_accessible_check_pending_notification;
453+
454+ g_type_class_add_private(gobject_class, sizeof(UnitySwitcherAccessiblePrivate));
455+}
456+
457+static void
458+unity_switcher_accessible_init(UnitySwitcherAccessible* self)
459+{
460+ UnitySwitcherAccessiblePrivate* priv =
461+ UNITY_SWITCHER_ACCESSIBLE_GET_PRIVATE(self);
462+
463+ self->priv = priv;
464+ self->priv->children = NULL;
465+}
466+
467+static void
468+unity_switcher_accessible_finalize(GObject* object)
469+{
470+ UnitySwitcherAccessible* self = UNITY_SWITCHER_ACCESSIBLE(object);
471+
472+ self->priv->on_selection_changed_connection.disconnect();
473+
474+ if (self->priv->children)
475+ {
476+ g_slist_free_full(self->priv->children, g_object_unref);
477+ self->priv->children = NULL;
478+ }
479+
480+ G_OBJECT_CLASS(unity_switcher_accessible_parent_class)->finalize(object);
481+}
482+
483+AtkObject*
484+unity_switcher_accessible_new(nux::Object* object)
485+{
486+ AtkObject* accessible = NULL;
487+
488+ g_return_val_if_fail(dynamic_cast<SwitcherView*>(object), NULL);
489+
490+ accessible = ATK_OBJECT(g_object_new(UNITY_TYPE_SWITCHER_ACCESSIBLE, NULL));
491+
492+ atk_object_initialize(accessible, object);
493+ atk_object_set_name(accessible, _("Switcher"));
494+
495+ return accessible;
496+}
497+
498+/* AtkObject.h */
499+static void
500+unity_switcher_accessible_initialize(AtkObject* accessible,
501+ gpointer data)
502+{
503+ SwitcherView* switcher = NULL;
504+ nux::Object* nux_object = NULL;
505+ UnitySwitcherAccessible* self = NULL;
506+ SwitcherModel::Ptr model;
507+
508+ ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->initialize(accessible, data);
509+
510+ atk_object_set_role(accessible, ATK_ROLE_TOOL_BAR);
511+
512+ self = UNITY_SWITCHER_ACCESSIBLE(accessible);
513+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(accessible));
514+ switcher = dynamic_cast<SwitcherView*>(nux_object);
515+ if (switcher == NULL)
516+ return;
517+
518+ model = switcher->GetModel();
519+
520+ if (model)
521+ {
522+ self->priv->on_selection_changed_connection =
523+ model->selection_changed.connect(sigc::bind(sigc::ptr_fun(on_selection_changed_cb),
524+ self));
525+
526+ create_children(self);
527+ }
528+
529+ /* To force being connected to the window::activate signal */
530+ nux_area_accessible_parent_window_active(NUX_AREA_ACCESSIBLE(self));
531+}
532+
533+static gint
534+unity_switcher_accessible_get_n_children(AtkObject* obj)
535+{
536+ nux::Object* object = NULL;
537+ UnitySwitcherAccessible* self = NULL;
538+
539+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), 0);
540+ self = UNITY_SWITCHER_ACCESSIBLE(obj);
541+
542+ object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
543+ if (!object) /* state is defunct */
544+ return 0;
545+
546+ return g_slist_length(self->priv->children);
547+}
548+
549+static AtkObject*
550+unity_switcher_accessible_ref_child(AtkObject* obj,
551+ gint i)
552+{
553+ gint num = 0;
554+ nux::Object* nux_object = NULL;
555+ AtkObject* child_accessible = NULL;
556+ UnitySwitcherAccessible* self = NULL;
557+
558+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), NULL);
559+ num = atk_object_get_n_accessible_children(obj);
560+ g_return_val_if_fail((i < num) && (i >= 0), NULL);
561+ self = UNITY_SWITCHER_ACCESSIBLE(obj);
562+
563+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
564+ if (!nux_object) /* state is defunct */
565+ return 0;
566+
567+ child_accessible = ATK_OBJECT(g_slist_nth_data(self->priv->children, i));
568+
569+ g_object_ref(child_accessible);
570+
571+ return child_accessible;
572+}
573+
574+static AtkStateSet*
575+unity_switcher_accessible_ref_state_set(AtkObject* obj)
576+{
577+ AtkStateSet* state_set = NULL;
578+ nux::Object* nux_object = NULL;
579+
580+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(obj), NULL);
581+
582+ state_set =
583+ ATK_OBJECT_CLASS(unity_switcher_accessible_parent_class)->ref_state_set(obj);
584+
585+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(obj));
586+
587+ if (nux_object == NULL) /* defunct */
588+ return state_set;
589+
590+ /* The Switcher is always focusable */
591+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
592+
593+ /* The Switcher is always focused. Looking SwitcherController code,
594+ * SwitcherView is only created to be presented to the user */
595+ atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
596+
597+ return state_set;
598+}
599+
600+/* AtkSelection */
601+static void
602+atk_selection_interface_init(AtkSelectionIface* iface)
603+{
604+ iface->ref_selection = unity_switcher_accessible_ref_selection;
605+ iface->get_selection_count = unity_switcher_accessible_get_selection_count;
606+ iface->is_child_selected = unity_switcher_accessible_is_child_selected;
607+
608+ /* NOTE: for the moment we don't provide the implementation for the
609+ "interactable" methods, it is, the methods that allow to change
610+ the selected icon. The Switcher doesn't provide that API, and
611+ right now we are focusing on a normal user input.*/
612+ /* iface->add_selection = unity_switcher_accessible_add_selection; */
613+ /* iface->clear_selection = unity_switcher_accessible_clear_selection; */
614+ /* iface->remove_selection = unity_switcher_accessible_remove_selection; */
615+
616+ /* This method will never be implemented, as select all the switcher
617+ icons makes no sense */
618+ /* iface->select_all = unity_switcher_accessible_select_all_selection; */
619+}
620+
621+static AtkObject*
622+unity_switcher_accessible_ref_selection(AtkSelection* selection,
623+ gint i)
624+{
625+ SwitcherView* switcher = NULL;
626+ SwitcherModel::Ptr switcher_model;
627+ nux::Object* nux_object = NULL;
628+ gint selected_index = 0;
629+ AtkObject* accessible_selected = NULL;
630+ UnitySwitcherAccessible* self = NULL;
631+
632+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), 0);
633+ /* there can be only just item selected */
634+ g_return_val_if_fail(i == 0, NULL);
635+ self = UNITY_SWITCHER_ACCESSIBLE(selection);
636+
637+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
638+ if (!nux_object) /* state is defunct */
639+ return 0;
640+
641+ switcher = dynamic_cast<SwitcherView*>(nux_object);
642+
643+ switcher_model = switcher->GetModel();
644+ selected_index = switcher_model->SelectionIndex();
645+
646+ accessible_selected = ATK_OBJECT(g_slist_nth_data(self->priv->children,
647+ selected_index));
648+
649+ if (accessible_selected != NULL)
650+ g_object_ref(accessible_selected);
651+
652+ return accessible_selected;
653+}
654+
655+static gint
656+unity_switcher_accessible_get_selection_count(AtkSelection* selection)
657+{
658+ SwitcherView* switcher = NULL;
659+ SwitcherModel::Ptr switcher_model;
660+ AbstractLauncherIcon* selected_icon = NULL;
661+ nux::Object* nux_object = NULL;
662+
663+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), 0);
664+
665+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
666+ if (!nux_object) /* state is defunct */
667+ return 0;
668+
669+ switcher = dynamic_cast<SwitcherView*>(nux_object);
670+ switcher_model = switcher->GetModel();
671+
672+ selected_icon = switcher_model->Selection();
673+
674+ if (selected_icon == 0)
675+ return 0;
676+ else
677+ return 1;
678+}
679+
680+static gboolean
681+unity_switcher_accessible_is_child_selected(AtkSelection* selection,
682+ gint i)
683+{
684+ SwitcherView* switcher = NULL;
685+ SwitcherModel::Ptr switcher_model;
686+ SwitcherModel::iterator it;
687+ nux::Object* nux_object = NULL;
688+ gint selected_index = 0;
689+
690+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(selection), FALSE);
691+
692+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(selection));
693+ if (!nux_object) /* state is defunct */
694+ return 0;
695+
696+ switcher = dynamic_cast<SwitcherView*>(nux_object);
697+ switcher_model = switcher->GetModel();
698+ selected_index = switcher_model->SelectionIndex();
699+
700+ if (selected_index == i)
701+ return TRUE;
702+ else
703+ return FALSE;
704+}
705+
706+/* NuxAreaAccessible */
707+static gboolean
708+unity_switcher_accessible_check_pending_notification(NuxAreaAccessible* self)
709+{
710+ g_return_val_if_fail(UNITY_IS_SWITCHER_ACCESSIBLE(self), FALSE);
711+
712+ /* Overriding the method: the switcher doesn't get the key focus of
713+ * focus (Focusable) */
714+ /* From SwitcherController: it shows that the switcher only exists
715+ * to be shown to the user, so if the parent window gets actived, we
716+ * assume that the switcher will be automatically focused
717+ */
718+ atk_object_notify_state_change(ATK_OBJECT(self), ATK_STATE_FOCUSED, TRUE);
719+ g_signal_emit_by_name(self, "focus-event", TRUE, NULL);
720+
721+ return TRUE;
722+}
723+
724+/* private */
725+static void
726+on_selection_changed_cb(AbstractLauncherIcon* icon,
727+ UnitySwitcherAccessible* switcher_accessible)
728+{
729+ g_signal_emit_by_name(ATK_OBJECT(switcher_accessible), "selection-changed");
730+}
731+
732+static void
733+create_children(UnitySwitcherAccessible* self)
734+{
735+ gint index = 0;
736+ nux::Object* nux_object = NULL;
737+ SwitcherView* switcher = NULL;
738+ SwitcherModel::Ptr switcher_model;
739+ SwitcherModel::iterator it;
740+ LauncherIcon* child = NULL;
741+ AtkObject* child_accessible = NULL;
742+
743+ nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self));
744+ if (!nux_object) /* state is defunct */
745+ return;
746+
747+ switcher = dynamic_cast<SwitcherView*>(nux_object);
748+ switcher_model = switcher->GetModel();
749+
750+ if (switcher_model == NULL)
751+ return;
752+
753+ for (it = switcher_model->begin(); it != switcher_model->end(); it++)
754+ {
755+ child = dynamic_cast<LauncherIcon*>(*it);
756+ child_accessible = unity_launcher_icon_accessible_new(child);
757+ atk_object_set_parent(child_accessible, ATK_OBJECT(self));
758+ self->priv->children = g_slist_append(self->priv->children,
759+ child_accessible);
760+ unity_launcher_icon_accessible_set_index(UNITY_LAUNCHER_ICON_ACCESSIBLE(child_accessible),
761+ index++);
762+ }
763+}
764
765=== added file 'plugins/unityshell/src/unity-switcher-accessible.h'
766--- plugins/unityshell/src/unity-switcher-accessible.h 1970-01-01 00:00:00 +0000
767+++ plugins/unityshell/src/unity-switcher-accessible.h 2011-11-07 22:37:27 +0000
768@@ -0,0 +1,57 @@
769+/*
770+ * Copyright (C) 2011 Canonical Ltd
771+ *
772+ * This program is free software: you can redistribute it and/or modify
773+ * it under the terms of the GNU General Public License version 3 as
774+ * published by the Free Software Foundation.
775+ *
776+ * This program is distributed in the hope that it will be useful,
777+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
778+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
779+ * GNU General Public License for more details.
780+ *
781+ * You should have received a copy of the GNU General Public License
782+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
783+ *
784+ * Authored by: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
785+ */
786+
787+#ifndef UNITY_SWITCHER_ACCESSIBLE_H
788+#define UNITY_SWITCHER_ACCESSIBLE_H
789+
790+#include <atk/atk.h>
791+
792+#include "nux-view-accessible.h"
793+
794+G_BEGIN_DECLS
795+
796+#define UNITY_TYPE_SWITCHER_ACCESSIBLE (unity_switcher_accessible_get_type ())
797+#define UNITY_SWITCHER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE, UnitySwitcherAccessible))
798+#define UNITY_SWITCHER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UNITY_TYPE_SWITCHER_ACCESSIBLE, UnitySwitcherAccessibleClass))
799+#define UNITY_IS_SWITCHER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE))
800+#define UNITY_IS_SWITCHER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UNITY_TYPE_SWITCHER_ACCESSIBLE))
801+#define UNITY_SWITCHER_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UNITY_TYPE_SWITCHER_ACCESSIBLE, UnitySwitcherAccessibleClass))
802+
803+typedef struct _UnitySwitcherAccessible UnitySwitcherAccessible;
804+typedef struct _UnitySwitcherAccessibleClass UnitySwitcherAccessibleClass;
805+typedef struct _UnitySwitcherAccessiblePrivate UnitySwitcherAccessiblePrivate;
806+
807+struct _UnitySwitcherAccessible
808+{
809+ NuxViewAccessible parent;
810+
811+ /*< private >*/
812+ UnitySwitcherAccessiblePrivate* priv;
813+};
814+
815+struct _UnitySwitcherAccessibleClass
816+{
817+ NuxViewAccessibleClass parent_class;
818+};
819+
820+GType unity_switcher_accessible_get_type(void);
821+AtkObject* unity_switcher_accessible_new(nux::Object* object);
822+
823+G_END_DECLS
824+
825+#endif /* __UNITY_SWITCHER_ACCESSIBLE_H__ */
826
827=== modified file 'plugins/unityshell/src/unitya11y.cpp'
828--- plugins/unityshell/src/unitya11y.cpp 2011-11-07 22:37:27 +0000
829+++ plugins/unityshell/src/unitya11y.cpp 2011-11-07 22:37:27 +0000
830@@ -41,6 +41,7 @@
831 #include "PlacesGroup.h"
832 #include "QuicklistView.h"
833 #include "QuicklistMenuItem.h"
834+#include "SwitcherView.h"
835 #include "unity-launcher-accessible.h"
836 #include "unity-launcher-icon-accessible.h"
837 #include "unity-panel-view-accessible.h"
838@@ -52,6 +53,7 @@
839 #include "unity-places-group-accessible.h"
840 #include "unity-quicklist-accessible.h"
841 #include "unity-quicklist-menu-item-accessible.h"
842+#include "unity-switcher-accessible.h"
843
844 using namespace unity;
845 using namespace unity::dash;
846@@ -300,6 +302,9 @@
847 if (object->Type().IsDerivedFromType(unity::dash::SearchBar::StaticObjectType))
848 return unity_search_bar_accessible_new(object);
849
850+ if (object->Type().IsDerivedFromType(unity::switcher::SwitcherView::StaticObjectType))
851+ return unity_switcher_accessible_new(object);
852+
853 /* NUX classes */
854 if (object->Type().IsDerivedFromType(nux::TextEntry::StaticObjectType))
855 return nux_text_entry_accessible_new(object);