Merge lp:~rodrigo-moya/unity/indicators-a11y into lp:unity

Proposed by Rodrigo Moya
Status: Merged
Approved by: Neil J. Patel
Approved revision: no longer in the source branch.
Merged at revision: 859
Proposed branch: lp:~rodrigo-moya/unity/indicators-a11y
Merge into: lp:unity
Diff against target: 670 lines (+388/-62)
9 files modified
services/CMakeLists.txt (+2/-0)
services/panel-indicator-accessible.c (+107/-14)
services/panel-indicator-accessible.h (+3/-1)
services/panel-indicator-entry-accessible.c (+131/-0)
services/panel-indicator-entry-accessible.h (+57/-0)
services/panel-root-accessible.c (+47/-15)
services/panel-service.c (+9/-2)
services/panel-service.h (+31/-27)
services/panel-util-accessible.c (+1/-3)
To merge this branch: bzr merge lp:~rodrigo-moya/unity/indicators-a11y
Reviewer Review Type Date Requested Status
Alejandro Piñeiro (community) Approve
Review via email: mp+48943@code.launchpad.net

Description of the change

Add A11Y objects hierarchy for indicators in the panel service

To post a comment you must log in.
Revision history for this message
Alejandro Piñeiro (apinheiro) wrote :

250 + if (GTK_IS_LABEL (piea->priv->entry->label))
251 + {
252 + atk_object_set_role (accessible, ATK_ROLE_LABEL);
253 + atk_object_set_name (accessible, gtk_label_get_text (piea->priv->entry->label));
254 + }
255 + if (GTK_IS_IMAGE (piea->priv->entry->image))
256 + {
257 + atk_object_set_role (accessible, ATK_ROLE_IMAGE);
258 + }

Those are the only types (LABEL, IMAGE)? Is it ok if a non-image-label is set a UNKNOWN role?

133 + if (entry != NULL)
134 + child = panel_indicator_entry_accessible_new (entry);

With this code you are creating a new accessible object with each call to this method, but for the same base object you should return the same accessible object.

261 +static gint
262 +panel_indicator_entry_accessible_get_n_children (AtkObject *accessible)
263 +{
264 + PanelIndicatorEntryAccessible *piea;
265 + gint n_children = 0;
266 +
267 + g_return_val_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (accessible), 0);
268 +
269 + piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (accessible);
270 + if (GTK_IS_MENU (piea->priv->entry->menu)
271 + && gtk_widget_get_visible (GTK_WIDGET (piea->priv->entry->menu)))

Why do you count the menu entry only if it is visible? (this question also applies to ref_child)

393 + indicator = panel_service_get_indicator (PANEL_ROOT_ACCESSIBLE (accessible)->priv->service, i);
394 + if (indicator != NULL)
395 + {
396 + child = panel_indicator_accessible_new (indicator);
397 + atk_object_set_parent (child, accessible);

As I said before, for the same base object you should return the same accessible object, not create a new accessible object each time.

Revision history for this message
Alejandro Piñeiro (apinheiro) wrote :

453 --- services/panel-service.h 2010-12-23 00:33:48 +0000
454 +++ services/panel-service.h 2011-02-09 12:51:59 +0000

Why do you modify the indentation of all the methods in this header?

review: Needs Fixing
Revision history for this message
Alejandro Piñeiro (apinheiro) wrote :

520 === modified file 'services/panel-service.h'
521 --- services/panel-service.h 2010-12-23 00:33:48 +0000
522 +++ services/panel-service.h 2011-02-14 10:55:50 +0000

Again, you are including changes on this file, that are mostly indentation of non-a11y-related methods. Not sure if fits here.

I still didn't test it, but although all code seems ok, I miss something. When we were talking about the list of accessible object, we also said that this list should be updated with the inclusion/removal of indicators/entries. As far as I see, with this code it creates the list at the beginning, but it doesn't update it.

review: Needs Information
Revision history for this message
Rodrigo Moya (rodrigo-moya) wrote :

> 520 === modified file 'services/panel-service.h'
> 521 --- services/panel-service.h 2010-12-23 00:33:48 +0000
> 522 +++ services/panel-service.h 2011-02-14 10:55:50 +0000
>
> Again, you are including changes on this file, that are mostly indentation of
> non-a11y-related methods. Not sure if fits here.
>
well, I changed the indentation to follow the coding style, which is to indent all function name prototypes

> I still didn't test it, but although all code seems ok, I miss something. When
> we were talking about the list of accessible object, we also said that this
> list should be updated with the inclusion/removal of indicators/entries. As
> far as I see, with this code it creates the list at the beginning, but it
> doesn't update it.
>
as we talked, that's for another branch: bug #715300

Revision history for this message
Alejandro Piñeiro (apinheiro) wrote :

> > 520 === modified file 'services/panel-service.h'
> > 521 --- services/panel-service.h 2010-12-23 00:33:48 +0000
> > 522 +++ services/panel-service.h 2011-02-14 10:55:50 +0000
> >
> > Again, you are including changes on this file, that are mostly indentation
> of
> > non-a11y-related methods. Not sure if fits here.
> >
> well, I changed the indentation to follow the coding style, which is to indent
> all function name prototypes

My concern is do changes not related with accessibility on a accessibility task. I would ask the other unity developers about it.

> > I still didn't test it, but although all code seems ok, I miss something.
> When
> > we were talking about the list of accessible object, we also said that this
> > list should be updated with the inclusion/removal of indicators/entries. As
> > far as I see, with this code it creates the list at the beginning, but it
> > doesn't update it.
> >
> as we talked, that's for another branch: bug #715300

Well, I remember that you said that you were splitting your tasks in bugs, but I don't remember specifically this one.

Anyway I'm not sure about not doing this task here. Take into account that without this change this branch is simple unstable, as there are the inherent risk to access to the wrong accessible, or access to a non existing object if someone is working with the accessible (as you are also not managing ATK_STATE_DEFUNCT management). If this is ok (as unity is in development state), then go on.

review: Needs Information
Revision history for this message
Alejandro Piñeiro (apinheiro) wrote :

Seems ok, just some nitpicks:

83 + return (AtkObject *) pia;
287 + return (AtkObject *) piea;

why don't use the usual gobject macros ATK_OBJECT (pia)?

Anyway, then, when I tested it, I found this warning messages:

[gshell-devel]@remigio:~/a11y-scripts$ python dump_tree.py

** (process:9834): WARNING **: AT-SPI: Accessibility bus not found - Using session bus.

Index: 0
Application name: unity-panel-service
** (unity-panel-service:9294): DEBUG: PanelRootAccessible has 5 children
Application elements: 5
** (unity-panel-service:9294): DEBUG: PanelRootAccessible has 5 children

(unity-panel-service:9294): GLib-GObject-WARNING **: g_type_instance_get_private() requires a prior call to g_type_class_add_private()
** (unity-panel-service:9294): DEBUG: Returning ATK child 0x8d3a190
 -- Role: label Name: An indicator

(unity-panel-service:9294): GLib-GObject-WARNING **: g_type_instance_get_private() requires a prior call to g_type_class_add_private()
** (unity-panel-service:9294): DEBUG: Returning ATK child 0x8d3d990
 -- Role: label Name: An indicator

(unity-panel-service:9294): GLib-GObject-WARNING **: g_type_instance_get_private() requires a prior call to g_type_class_add_private()
** (unity-panel-service:9294): DEBUG: Returning ATK child 0x8bd6d18
 -- Role: label Name: An indicator

(unity-panel-service:9294): GLib-GObject-WARNING **: g_type_instance_get_private() requires a prior call to g_type_class_add_private()
** (unity-panel-service:9294): DEBUG: Returning ATK child 0x8d3a340
 -- Role: label Name: An indicator

(unity-panel-service:9294): GLib-GObject-WARNING **: g_type_instance_get_private() requires a prior call to g_type_class_add_private()
** (unity-panel-service:9294): DEBUG: Returning ATK child 0x8bd6c28
 -- Role: label Name: An indicator

I used a custom script, but I also see them using accerciser.

review: Needs Fixing
Revision history for this message
Alejandro Piñeiro (apinheiro) wrote :

Well after last review, and test, I think that it is worth to merge this, and refine it on the next merges.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'services/CMakeLists.txt'
2--- services/CMakeLists.txt 2011-01-28 12:00:21 +0000
3+++ services/CMakeLists.txt 2011-02-15 12:55:42 +0000
4@@ -28,6 +28,8 @@
5 panel-a11y.h
6 panel-indicator-accessible.c
7 panel-indicator-accessible.h
8+ panel-indicator-entry-accessible.c
9+ panel-indicator-entry-accessible.h
10 panel-main.c
11 panel-root-accessible.c
12 panel-root-accessible.h
13
14=== modified file 'services/panel-indicator-accessible.c'
15--- services/panel-indicator-accessible.c 2011-01-30 17:46:02 +0000
16+++ services/panel-indicator-accessible.c 2011-02-15 12:55:42 +0000
17@@ -18,6 +18,7 @@
18
19 #include <glib/gi18n.h>
20 #include "panel-indicator-accessible.h"
21+#include "panel-indicator-entry-accessible.h"
22
23 G_DEFINE_TYPE(PanelIndicatorAccessible, panel_indicator_accessible, ATK_TYPE_OBJECT)
24
25@@ -30,9 +31,33 @@
26
27 struct _PanelIndicatorAccessiblePrivate
28 {
29+ IndicatorObject *indicator;
30+ GSList *a11y_children;
31 };
32
33 static void
34+panel_indicator_accessible_finalize (GObject *object)
35+{
36+ PanelIndicatorAccessible *pia = PANEL_INDICATOR_ACCESSIBLE (object);
37+
38+ if (pia->priv != NULL)
39+ {
40+ if (pia->priv->indicator != NULL)
41+ g_object_unref (G_OBJECT (pia->priv->indicator));
42+
43+ while (pia->priv->a11y_children != NULL)
44+ {
45+ AtkObject *accessible = ATK_OBJECT (pia->priv->a11y_children->data);
46+
47+ pia->priv->a11y_children = g_slist_remove (pia->priv->a11y_children, accessible);
48+ g_object_unref (accessible);
49+ }
50+ }
51+
52+ G_OBJECT_CLASS (panel_indicator_accessible_parent_class)->finalize (object);
53+}
54+
55+static void
56 panel_indicator_accessible_class_init (PanelIndicatorAccessibleClass *klass)
57 {
58 GObjectClass *object_class;
59@@ -40,6 +65,7 @@
60
61 /* GObject */
62 object_class = G_OBJECT_CLASS (klass);
63+ object_class->finalize = panel_indicator_accessible_finalize;
64
65 /* AtkObject */
66 atk_class = ATK_OBJECT_CLASS (klass);
67@@ -54,18 +80,58 @@
68 panel_indicator_accessible_init (PanelIndicatorAccessible *pia)
69 {
70 pia->priv = GET_PRIVATE (pia);
71+ pia->priv->a11y_children = NULL;
72 }
73
74 AtkObject *
75-panel_indicator_accessible_new (void)
76+panel_indicator_accessible_new (IndicatorObject *indicator)
77+{
78+ PanelIndicatorAccessible *pia;
79+
80+ pia = g_object_new (PANEL_TYPE_INDICATOR_ACCESSIBLE, NULL);
81+ atk_object_initialize (ATK_OBJECT (pia), indicator);
82+
83+ return ATK_OBJECT (pia);
84+}
85+
86+/* Indicator callbacks */
87+
88+static void
89+on_indicator_entry_added (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data)
90 {
91 AtkObject *accessible;
92-
93- accessible = ATK_OBJECT (g_object_new (PANEL_TYPE_INDICATOR_ACCESSIBLE, NULL));
94-
95- atk_object_initialize (accessible, NULL);
96-
97- return accessible;
98+ PanelIndicatorAccessible *pia = PANEL_INDICATOR_ACCESSIBLE (user_data);
99+
100+ accessible = panel_indicator_entry_accessible_new (entry);
101+ if (accessible != NULL)
102+ {
103+ pia->priv->a11y_children = g_slist_append (pia->priv->a11y_children, accessible);
104+ g_signal_emit_by_name (ATK_OBJECT (pia), "children-changed",
105+ g_slist_length (pia->priv->a11y_children) - 1,
106+ accessible);
107+ }
108+}
109+
110+static void
111+on_indicator_entry_removed (IndicatorObject *io, IndicatorObjectEntry *entry, gpointer user_data)
112+{
113+ GSList *l;
114+ guint count = 0;
115+ PanelIndicatorAccessible *pia = PANEL_INDICATOR_ACCESSIBLE (user_data);
116+
117+ for (l = pia->priv->a11y_children; l != NULL; l = l->next, count++)
118+ {
119+ AtkObject *accessible = ATK_OBJECT (l->data);
120+
121+ if (entry == panel_indicator_entry_accessible_get_entry (PANEL_INDICATOR_ENTRY_ACCESSIBLE (accessible)))
122+ {
123+ pia->priv->a11y_children = g_slist_remove (pia->priv->a11y_children, accessible);
124+ g_signal_emit_by_name (ATK_OBJECT (pia), "children-changed",
125+ count, accessible);
126+
127+ g_object_unref (accessible);
128+ }
129+ }
130 }
131
132 /* Implementation of AtkObject methods */
133@@ -73,26 +139,53 @@
134 static void
135 panel_indicator_accessible_initialize (AtkObject *accessible, gpointer data)
136 {
137+ PanelIndicatorAccessible *pia;
138+ GList *entries, *l;
139+
140 g_return_if_fail (PANEL_IS_INDICATOR_ACCESSIBLE (accessible));
141
142 ATK_OBJECT_CLASS (panel_indicator_accessible_parent_class)->initialize (accessible, data);
143
144+ pia = PANEL_INDICATOR_ACCESSIBLE (accessible);
145 atk_object_set_name (accessible, _("An indicator")); /* FIXME */
146- atk_object_set_role (accessible, ATK_ROLE_LABEL);
147+ atk_object_set_role (accessible, ATK_ROLE_PANEL);
148+
149+ /* Setup the indicator object */
150+ pia->priv->indicator = g_object_ref (data);
151+ g_signal_connect (G_OBJECT (pia->priv->indicator), "entry-added",
152+ G_CALLBACK (on_indicator_entry_added), pia);
153+ g_signal_connect (G_OBJECT (pia->priv->indicator), "entry-removed",
154+ G_CALLBACK (on_indicator_entry_removed), pia);
155+
156+ /* Retrieve all entries and create their accessible objects */
157+ entries = indicator_object_get_entries (pia->priv->indicator);
158+ for (l = entries; l != NULL; l = l->next)
159+ {
160+ AtkObject *accessible;
161+
162+ accessible = panel_indicator_entry_accessible_new ((IndicatorObjectEntry *) l->data);
163+ pia->priv->a11y_children = g_slist_append (pia->priv->a11y_children, accessible);
164+ }
165+
166+ g_list_free (entries);
167 }
168
169 static gint
170 panel_indicator_accessible_get_n_children (AtkObject *accessible)
171 {
172- g_return_val_if_fail (PANEL_IS_INDICATOR_ACCESSIBLE (accessible), 0);
173-
174- return 0;
175+ PanelIndicatorAccessible *pia = PANEL_INDICATOR_ACCESSIBLE (accessible);
176+
177+ g_return_val_if_fail (PANEL_IS_INDICATOR_ACCESSIBLE (pia), 0);
178+
179+ return g_slist_length (pia->priv->a11y_children);
180 }
181
182 static AtkObject *
183 panel_indicator_accessible_ref_child (AtkObject *accessible, gint i)
184 {
185- g_return_val_if_fail (PANEL_IS_INDICATOR_ACCESSIBLE (accessible), NULL);
186-
187- return NULL;
188+ PanelIndicatorAccessible *pia = PANEL_INDICATOR_ACCESSIBLE (accessible);
189+
190+ g_return_val_if_fail (PANEL_IS_INDICATOR_ACCESSIBLE (pia), NULL);
191+
192+ return g_object_ref (g_slist_nth_data (pia->priv->a11y_children, i));
193 }
194
195=== modified file 'services/panel-indicator-accessible.h'
196--- services/panel-indicator-accessible.h 2011-01-30 17:46:02 +0000
197+++ services/panel-indicator-accessible.h 2011-02-15 12:55:42 +0000
198@@ -20,6 +20,8 @@
199 #define _PANEL_INDICATOR_ACCESSIBLE_H_
200
201 #include <atk/atk.h>
202+#include <libindicator/indicator.h>
203+#include <libindicator/indicator-object.h>
204
205 G_BEGIN_DECLS
206
207@@ -46,7 +48,7 @@
208 };
209
210 GType panel_indicator_accessible_get_type (void);
211-AtkObject *panel_indicator_accessible_new (void);
212+AtkObject *panel_indicator_accessible_new (IndicatorObject *indicator);
213
214 G_END_DECLS
215
216
217=== added file 'services/panel-indicator-entry-accessible.c'
218--- services/panel-indicator-entry-accessible.c 1970-01-01 00:00:00 +0000
219+++ services/panel-indicator-entry-accessible.c 2011-02-15 12:55:42 +0000
220@@ -0,0 +1,131 @@
221+/*
222+ * Copyright (C) 2011 Canonical Ltd
223+ *
224+ * This program is free software: you can redistribute it and/or modify
225+ * it under the terms of the GNU General Public License version 3 as
226+ * published by the Free Software Foundation.
227+ *
228+ * This program is distributed in the hope that it will be useful,
229+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
230+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
231+ * GNU General Public License for more details.
232+ *
233+ * You should have received a copy of the GNU General Public License
234+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
235+ *
236+ * Authored by: Rodrigo Moya <rodrigo.moya@canonical.com>
237+ */
238+
239+#include "panel-indicator-entry-accessible.h"
240+
241+G_DEFINE_TYPE(PanelIndicatorEntryAccessible, panel_indicator_entry_accessible, ATK_TYPE_OBJECT)
242+
243+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, PanelIndicatorEntryAccessiblePrivate))
244+
245+/* AtkObject methods */
246+static void panel_indicator_entry_accessible_initialize (AtkObject *accessible, gpointer data);
247+static gint panel_indicator_entry_accessible_get_n_children (AtkObject *accessible);
248+static AtkObject *panel_indicator_entry_accessible_ref_child (AtkObject *accessible, gint i);
249+
250+struct _PanelIndicatorEntryAccessiblePrivate
251+{
252+ IndicatorObjectEntry *entry;
253+};
254+
255+static void
256+panel_indicator_entry_accessible_class_init (PanelIndicatorEntryAccessibleClass *klass)
257+{
258+ GObjectClass *object_class;
259+ AtkObjectClass *atk_class;
260+
261+ /* GObject */
262+ object_class = G_OBJECT_CLASS (klass);
263+
264+ /* AtkObject */
265+ atk_class = ATK_OBJECT_CLASS (klass);
266+ atk_class->initialize = panel_indicator_entry_accessible_initialize;
267+ atk_class->get_n_children = panel_indicator_entry_accessible_get_n_children;
268+ atk_class->ref_child = panel_indicator_entry_accessible_ref_child;
269+
270+ g_type_class_add_private (object_class, sizeof (PanelIndicatorEntryAccessiblePrivate));
271+}
272+
273+static void
274+panel_indicator_entry_accessible_init (PanelIndicatorEntryAccessible *piea)
275+{
276+ piea->priv = GET_PRIVATE (piea);
277+}
278+
279+AtkObject *
280+panel_indicator_entry_accessible_new (IndicatorObjectEntry *entry)
281+{
282+ PanelIndicatorEntryAccessible *piea;
283+
284+ piea = g_object_new (PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, NULL);
285+ atk_object_initialize (ATK_OBJECT (piea), entry);
286+
287+ return ATK_OBJECT (piea);
288+}
289+
290+IndicatorObjectEntry *
291+panel_indicator_entry_accessible_get_entry (PanelIndicatorEntryAccessible *piea)
292+{
293+ g_return_val_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (piea), NULL);
294+
295+ return piea->priv->entry;
296+}
297+
298+/* Implementation of AtkObject methods */
299+
300+static void
301+panel_indicator_entry_accessible_initialize (AtkObject *accessible, gpointer data)
302+{
303+ PanelIndicatorEntryAccessible *piea;
304+
305+ g_return_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (accessible));
306+
307+ ATK_OBJECT_CLASS (panel_indicator_entry_accessible_parent_class)->initialize (accessible, data);
308+
309+ piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (accessible);
310+ piea->priv->entry = (IndicatorObjectEntry *) data;
311+
312+ if (GTK_IS_LABEL (piea->priv->entry->label))
313+ {
314+ atk_object_set_role (accessible, ATK_ROLE_LABEL);
315+ atk_object_set_name (accessible, gtk_label_get_text (piea->priv->entry->label));
316+ }
317+ if (GTK_IS_IMAGE (piea->priv->entry->image))
318+ {
319+ atk_object_set_role (accessible, ATK_ROLE_IMAGE);
320+ }
321+}
322+
323+static gint
324+panel_indicator_entry_accessible_get_n_children (AtkObject *accessible)
325+{
326+ PanelIndicatorEntryAccessible *piea;
327+ gint n_children = 0;
328+
329+ g_return_val_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (accessible), 0);
330+
331+ piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (accessible);
332+ if (GTK_IS_MENU (piea->priv->entry->menu))
333+ n_children = 1;
334+
335+ return n_children;
336+}
337+
338+static AtkObject *
339+panel_indicator_entry_accessible_ref_child (AtkObject *accessible, gint i)
340+{
341+ PanelIndicatorEntryAccessible *piea;
342+ AtkObject *child = NULL;
343+
344+ g_return_val_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (accessible), NULL);
345+
346+ piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (accessible);
347+ if (GTK_IS_MENU (piea->priv->entry->menu))
348+ child = gtk_widget_get_accessible (GTK_WIDGET (piea->priv->entry->menu));
349+
350+ return child;
351+}
352
353=== added file 'services/panel-indicator-entry-accessible.h'
354--- services/panel-indicator-entry-accessible.h 1970-01-01 00:00:00 +0000
355+++ services/panel-indicator-entry-accessible.h 2011-02-15 12:55:42 +0000
356@@ -0,0 +1,57 @@
357+/*
358+ * Copyright (C) 2011 Canonical Ltd
359+ *
360+ * This program is free software: you can redistribute it and/or modify
361+ * it under the terms of the GNU General Public License version 3 as
362+ * published by the Free Software Foundation.
363+ *
364+ * This program is distributed in the hope that it will be useful,
365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
367+ * GNU General Public License for more details.
368+ *
369+ * You should have received a copy of the GNU General Public License
370+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
371+ *
372+ * Authored by: Rodrigo Moya <rodrigo.moya@canonical.com>
373+ */
374+
375+#ifndef _PANEL_INDICATOR_ENTRY_ACCESSIBLE_H_
376+#define _PANEL_INDICATOR_ENTRY_ACCESSIBLE_H_
377+
378+#include <atk/atk.h>
379+#include <libindicator/indicator.h>
380+#include <libindicator/indicator-object.h>
381+
382+G_BEGIN_DECLS
383+
384+#define PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE (panel_indicator_entry_accessible_get_type ())
385+#define PANEL_INDICATOR_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, PanelIndicatorEntryAccessible))
386+#define PANEL_INDICATOR_ENTRY_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, PanelIndicatorEntryAccessibleClass))
387+#define PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE))
388+#define PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE))
389+#define PANEL_INDICATOR_ENTRY_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, PanelIndicatorEntryAccessibleClass))
390+
391+typedef struct _PanelIndicatorEntryAccessible PanelIndicatorEntryAccessible;
392+typedef struct _PanelIndicatorEntryAccessibleClass PanelIndicatorEntryAccessibleClass;
393+typedef struct _PanelIndicatorEntryAccessiblePrivate PanelIndicatorEntryAccessiblePrivate;
394+
395+struct _PanelIndicatorEntryAccessible
396+{
397+ AtkObject parent;
398+ PanelIndicatorEntryAccessiblePrivate *priv;
399+};
400+
401+struct _PanelIndicatorEntryAccessibleClass
402+{
403+ AtkObjectClass parent_class;
404+};
405+
406+GType panel_indicator_entry_accessible_get_type (void);
407+AtkObject *panel_indicator_entry_accessible_new (IndicatorObjectEntry *entry);
408+
409+IndicatorObjectEntry *panel_indicator_entry_accessible_get_entry (PanelIndicatorEntryAccessible *piea);
410+
411+G_END_DECLS
412+
413+#endif
414
415=== modified file 'services/panel-root-accessible.c'
416--- services/panel-root-accessible.c 2011-01-30 17:46:02 +0000
417+++ services/panel-root-accessible.c 2011-02-15 12:55:42 +0000
418@@ -33,9 +33,28 @@
419
420 struct _PanelRootAccessiblePrivate
421 {
422+ PanelService *service;
423+ GSList *a11y_children;
424 };
425
426 static void
427+panel_root_accessible_finalize (GObject *object)
428+{
429+ PanelRootAccessible *root = PANEL_ROOT_ACCESSIBLE (object);
430+
431+ if (root->priv != NULL)
432+ {
433+ while (root->priv->a11y_children != NULL)
434+ {
435+ AtkObject *accessible = ATK_OBJECT (root->priv->a11y_children->data);
436+
437+ root->priv->a11y_children = g_slist_remove (root->priv->a11y_children, accessible);
438+ g_object_unref (accessible);
439+ }
440+ }
441+}
442+
443+static void
444 panel_root_accessible_class_init (PanelRootAccessibleClass *klass)
445 {
446 GObjectClass *object_class;
447@@ -43,6 +62,7 @@
448
449 /* GObject */
450 object_class = G_OBJECT_CLASS (klass);
451+ object_class->finalize = panel_root_accessible_finalize;
452
453 /* AtkObject */
454 atk_class = ATK_OBJECT_CLASS (klass);
455@@ -58,6 +78,8 @@
456 panel_root_accessible_init (PanelRootAccessible *root)
457 {
458 root->priv = GET_PRIVATE (root);
459+ root->priv->a11y_children = NULL;
460+ root->priv->service = panel_service_get_default ();
461 }
462
463 AtkObject *
464@@ -76,6 +98,9 @@
465 static void
466 panel_root_accessible_initialize (AtkObject *accessible, gpointer data)
467 {
468+ gint n_children, i;
469+ PanelRootAccessible *root = PANEL_ROOT_ACCESSIBLE (accessible);
470+
471 g_return_if_fail (PANEL_IS_ROOT_ACCESSIBLE (accessible));
472
473 ATK_OBJECT_CLASS (panel_root_accessible_parent_class)->initialize (accessible, data);
474@@ -83,41 +108,48 @@
475 accessible->role = ATK_ROLE_APPLICATION;
476 atk_object_set_name (accessible, g_get_prgname ());
477 atk_object_set_parent (accessible, NULL);
478+
479+ /* Retrieve all indicators and create their accessible objects */
480+ n_children = panel_service_get_n_indicators (root->priv->service);
481+ for (i = 0; i < n_children; i++)
482+ {
483+ IndicatorObject *indicator;
484+
485+ indicator = panel_service_get_indicator (root->priv->service, i);
486+ if (indicator != NULL)
487+ {
488+ AtkObject *accessible;
489+
490+ accessible = panel_indicator_accessible_new (indicator);
491+ root->priv->a11y_children = g_slist_append (root->priv->a11y_children, accessible);
492+ }
493+ }
494 }
495
496 static gint
497 panel_root_accessible_get_n_children (AtkObject *accessible)
498 {
499- guint n_children;
500+ PanelRootAccessible *root = PANEL_ROOT_ACCESSIBLE (accessible);
501
502 g_return_val_if_fail (PANEL_IS_ROOT_ACCESSIBLE (accessible), 0);
503
504- n_children = panel_service_get_n_indicators (panel_service_get_default ());
505-
506- g_debug ("PanelRootAccessible has %d children", n_children);
507-
508- return n_children;
509+ return g_slist_length (root->priv->a11y_children);
510 }
511
512 static AtkObject *
513 panel_root_accessible_ref_child (AtkObject *accessible, gint i)
514 {
515- AtkObject *child;
516+ PanelRootAccessible *root = PANEL_ROOT_ACCESSIBLE (accessible);
517
518 g_return_val_if_fail (PANEL_IS_ROOT_ACCESSIBLE (accessible), NULL);
519
520- child = panel_indicator_accessible_new (); /* FIXME */
521- atk_object_set_parent (child, accessible);
522-
523- g_debug ("Returning ATK child %p", child);
524-
525- return child;
526+ return g_object_ref (g_slist_nth_data (root->priv->a11y_children, i));
527 }
528
529 static AtkObject *
530 panel_root_accessible_get_parent (AtkObject *accessible)
531 {
532- g_return_val_if_fail (PANEL_IS_ROOT_ACCESSIBLE (accessible), NULL);
533+ g_return_val_if_fail (PANEL_IS_ROOT_ACCESSIBLE (accessible), NULL);
534
535- return NULL;
536+ return NULL;
537 }
538
539=== modified file 'services/panel-service.c'
540--- services/panel-service.c 2011-01-31 20:56:29 +0000
541+++ services/panel-service.c 2011-02-15 12:55:42 +0000
542@@ -14,6 +14,7 @@
543 * along with this program. If not, see <http://www.gnu.org/licenses/>.
544 *
545 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
546+ * Rodrigo Moya <rodrigo.moya@canonical.com>
547 */
548
549 #if HAVE_CONFIG_H
550@@ -23,8 +24,6 @@
551 #include "panel-service.h"
552
553 #include <stdlib.h>
554-#include <libindicator/indicator.h>
555-#include <libindicator/indicator-object.h>
556 #include <gtk/gtk.h>
557 #include <gdk/gdkx.h>
558
559@@ -341,6 +340,14 @@
560 return g_slist_length (self->priv->indicators);
561 }
562
563+IndicatorObject *
564+panel_service_get_indicator (PanelService *self, guint position)
565+{
566+ g_return_val_if_fail (PANEL_IS_SERVICE (self), NULL);
567+
568+ return (IndicatorObject *) g_slist_nth_data (self->priv->indicators, position);
569+}
570+
571 /*
572 * Private Methods
573 */
574
575=== modified file 'services/panel-service.h'
576--- services/panel-service.h 2010-12-23 00:33:48 +0000
577+++ services/panel-service.h 2011-02-15 12:55:42 +0000
578@@ -20,6 +20,8 @@
579 #define _PANEL_SERVICE_H_
580
581 #include <glib-object.h>
582+#include <libindicator/indicator.h>
583+#include <libindicator/indicator-object.h>
584
585 G_BEGIN_DECLS
586
587@@ -64,33 +66,35 @@
588 void (*_view_padding6) (void);
589 };
590
591-GType panel_service_get_type (void) G_GNUC_CONST;
592-
593-PanelService * panel_service_get_default ();
594-
595-PanelService * panel_service_get_default_with_indicators (GList *indicators);
596-
597-guint panel_service_get_n_indicators (PanelService *self);
598-
599-GVariant * panel_service_sync (PanelService *self);
600-
601-GVariant * panel_service_sync_one (PanelService *self,
602- const gchar *indicator_id);
603-
604-void panel_service_show_entry (PanelService *self,
605- const gchar *entry_id,
606- guint32 timestamp,
607- gint32 x,
608- gint32 y,
609- gint32 button);
610-
611-void panel_service_scroll_entry (PanelService *self,
612- const gchar *entry_id,
613- gint32 delta);
614-
615-void panel_service_get_last_xy (PanelService *self,
616- gint *x,
617- gint *y);
618+GType panel_service_get_type (void) G_GNUC_CONST;
619+
620+PanelService * panel_service_get_default ();
621+
622+PanelService * panel_service_get_default_with_indicators (GList *indicators);
623+
624+guint panel_service_get_n_indicators (PanelService *self);
625+
626+IndicatorObject * panel_service_get_indicator (PanelService *self, guint position);
627+
628+GVariant * panel_service_sync (PanelService *self);
629+
630+GVariant * panel_service_sync_one (PanelService *self,
631+ const gchar *indicator_id);
632+
633+void panel_service_show_entry (PanelService *self,
634+ const gchar *entry_id,
635+ guint32 timestamp,
636+ gint32 x,
637+ gint32 y,
638+ gint32 button);
639+
640+void panel_service_scroll_entry (PanelService *self,
641+ const gchar *entry_id,
642+ gint32 delta);
643+
644+void panel_service_get_last_xy (PanelService *self,
645+ gint *x,
646+ gint *y);
647
648 G_END_DECLS
649
650
651=== modified file 'services/panel-util-accessible.c'
652--- services/panel-util-accessible.c 2011-01-30 17:46:02 +0000
653+++ services/panel-util-accessible.c 2011-02-15 12:55:42 +0000
654@@ -22,7 +22,7 @@
655 G_DEFINE_TYPE(PanelUtilAccessible, panel_util_accessible, ATK_TYPE_UTIL)
656
657 /* AtkUtil methods */
658-static AtkObject *panel_util_accessible_get_root (void);
659+static AtkObject *panel_util_accessible_get_root (void);
660
661 static AtkObject *root = NULL;
662
663@@ -53,7 +53,5 @@
664 if (!root)
665 root = panel_root_accessible_new ();
666
667- g_debug ("Returning root A11Y object at %p", root);
668-
669 return root;
670 }