Merge lp:~rodrigo-moya/unity/sync-geometries into lp:unity

Proposed by Rodrigo Moya
Status: Merged
Approved by: Rodrigo Moya
Approved revision: no longer in the source branch.
Merged at revision: 965
Proposed branch: lp:~rodrigo-moya/unity/sync-geometries
Merge into: lp:unity
Diff against target: 962 lines (+414/-100)
16 files modified
po/unity.pot (+0/-69)
services/CMakeLists.txt (+25/-15)
services/panel-a11y.c (+6/-0)
services/panel-indicator-accessible.c (+111/-4)
services/panel-indicator-entry-accessible.c (+85/-7)
services/panel-main.c (+31/-3)
services/panel-marshal.list (+1/-0)
services/panel-service.c (+28/-0)
services/panel-service.h (+7/-0)
src/IndicatorObjectFactory.h (+1/-0)
src/IndicatorObjectFactoryRemote.cpp (+3/-0)
src/PanelIndicatorObjectView.cpp (+2/-1)
src/PanelIndicatorObjectView.h (+1/-1)
src/PanelView.cpp (+101/-0)
src/PanelView.h (+3/-0)
tests/CMakeLists.txt (+9/-0)
To merge this branch: bzr merge lp:~rodrigo-moya/unity/sync-geometries
Reviewer Review Type Date Requested Status
Rodrigo Moya (community) Approve
Neil J. Patel (community) Approve
Alejandro Piñeiro (community) Approve
Review via email: mp+51929@code.launchpad.net

Description of the change

Sync geometries of the indicators from unity to the panel service, so that that information can be used to implement AtkComponent for both PanelIndicatorAccessible and PanelIndicatorEntryAccessible

To post a comment you must log in.
Revision history for this message
Rodrigo Moya (rodrigo-moya) wrote :

Note that there's something wrong with the geometries, and not all indicator objects/entries get highlighted in the correct position when selected in accerciser

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

I have tested it with accerciser, and about this comment:
"Note that there's something wrong with the geometries, and not all indicator objects/entries get highlighted in the correct position when selected in accerciser"

I only got one indicator object/entry having the proper position.

About the code, in general seems good, although it would be required a review of the non accessibility related code (the methods and signals used by the AtkComponent implementation) except in one detail:

149 +panel_indicator_accessible_get_extents (AtkComponent *component,
150 + gint *x,
151 + gint *y,
152 + gint *width,
153 + gint *height,
154 + AtkCoordType coord_type)

309 +panel_indicator_entry_accessible_get_extents (AtkComponent *component,
310 + gint *x,
311 + gint *y,
312 + gint *width,
313 + gint *height,
314 + AtkCoordType coord_type)

You don't check coord_type at all. Take into account that the data that you return are totally different depending on coord_type. As far as I see, in both cases you try to return the result assuming global screen positions (ATK_XY_SCREEN), so it is missing the ATK_XY_WINDOW

In the same way, taking into account that you are already using the signal geometries_changed, I think that it would be easy to also emit the signal "bounds-changed":

http://library.gnome.org/devel/atk/stable/AtkComponent.html#AtkComponent-bounds-changed

BTW, about the signals. Each time that you receive this signal the size is updated, but, what happen with the initial state? Initially this is set to zero. That means that if the indicators/entry has already his position/size set before the accessible object is created, it will have a wrong position/size value? (as it is not updated by the signal)?

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

BTW, although we already commented that via IRC, just to comment that the gen-marshal addition on cmake seems to not work properly, as I needed to execute it by hand.

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

All issues fixed, so please review again

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

519 + root = atk_get_root ();
520 +
521 gtk_main ();

This get_root could mean a crash if the a11y is not enabled. So options:

a) Add a method on panel-a11y to check if the accessibility is enabled.
b) Move this call inside panel_a11y_init. As it is required that the service is created to this root, that would mean move panel_a11y_init to the line of this atk_get_root

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

Code seems ok, and I tested it and the position is more accurate.

Anyway:

 * Be careful with the .pot file included on this branch
 * I'm not used to cmake and you modify non-a11y related code, so it would be good to have a second opinion here

review: Approve
Revision history for this message
Neil J. Patel (njpatel) wrote :

Looks good, approved.

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

Neil gave his +1 on irc

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'po/unity.pot'
2--- po/unity.pot 1970-01-01 00:00:00 +0000
3+++ po/unity.pot 2011-03-17 12:04:28 +0000
4@@ -0,0 +1,69 @@
5+# SOME DESCRIPTIVE TITLE.
6+# Copyright (C) YEAR Canonical\ Ltd
7+# This file is distributed under the same license as the PACKAGE package.
8+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
9+#
10+#, fuzzy
11+msgid ""
12+msgstr ""
13+"Project-Id-Version: PACKAGE VERSION\n"
14+"Report-Msgid-Bugs-To: ayatana-dev@lists.launchpad.net\n"
15+"POT-Creation-Date: 2011-02-21 19:06+0100\n"
16+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
17+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
18+"Language-Team: LANGUAGE <LL@li.org>\n"
19+"Language: \n"
20+"MIME-Version: 1.0\n"
21+"Content-Type: text/plain; charset=CHARSET\n"
22+"Content-Transfer-Encoding: 8bit\n"
23+
24+msgid "Keep In Launcher"
25+msgstr ""
26+
27+msgid "Quit"
28+msgstr ""
29+
30+msgid "Open"
31+msgstr ""
32+
33+msgid "Eject"
34+msgstr ""
35+
36+msgid "Workspace Switcher"
37+msgstr ""
38+
39+msgid "Find Media Apps"
40+msgstr ""
41+
42+msgid "Find Internet Apps"
43+msgstr ""
44+
45+msgid "Find More Apps"
46+msgstr ""
47+
48+msgid "Find Files"
49+msgstr ""
50+
51+msgid "Browse the Web"
52+msgstr ""
53+
54+msgid "View Photos"
55+msgstr ""
56+
57+msgid "Check Email"
58+msgstr ""
59+
60+msgid "Listen to Music"
61+msgstr ""
62+
63+msgid "Trash"
64+msgstr ""
65+
66+msgid "Empty Trash"
67+msgstr ""
68+
69+msgid "Empty all items from Trash?"
70+msgstr ""
71+
72+msgid "All items in the Trash will be permanently deleted."
73+msgstr ""
74
75=== removed file 'po/unity.pot'
76--- po/unity.pot 2011-02-22 13:14:15 +0000
77+++ po/unity.pot 1970-01-01 00:00:00 +0000
78@@ -1,69 +0,0 @@
79-# SOME DESCRIPTIVE TITLE.
80-# Copyright (C) YEAR Canonical\ Ltd
81-# This file is distributed under the same license as the PACKAGE package.
82-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
83-#
84-#, fuzzy
85-msgid ""
86-msgstr ""
87-"Project-Id-Version: PACKAGE VERSION\n"
88-"Report-Msgid-Bugs-To: ayatana-dev@lists.launchpad.net\n"
89-"POT-Creation-Date: 2011-02-21 19:06+0100\n"
90-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
91-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
92-"Language-Team: LANGUAGE <LL@li.org>\n"
93-"Language: \n"
94-"MIME-Version: 1.0\n"
95-"Content-Type: text/plain; charset=CHARSET\n"
96-"Content-Transfer-Encoding: 8bit\n"
97-
98-msgid "Keep In Launcher"
99-msgstr ""
100-
101-msgid "Quit"
102-msgstr ""
103-
104-msgid "Open"
105-msgstr ""
106-
107-msgid "Eject"
108-msgstr ""
109-
110-msgid "Workspace Switcher"
111-msgstr ""
112-
113-msgid "Find Media Apps"
114-msgstr ""
115-
116-msgid "Find Internet Apps"
117-msgstr ""
118-
119-msgid "Find More Apps"
120-msgstr ""
121-
122-msgid "Find Files"
123-msgstr ""
124-
125-msgid "Browse the Web"
126-msgstr ""
127-
128-msgid "View Photos"
129-msgstr ""
130-
131-msgid "Check Email"
132-msgstr ""
133-
134-msgid "Listen to Music"
135-msgstr ""
136-
137-msgid "Trash"
138-msgstr ""
139-
140-msgid "Empty Trash"
141-msgstr ""
142-
143-msgid "Empty all items from Trash?"
144-msgstr ""
145-
146-msgid "All items in the Trash will be permanently deleted."
147-msgstr ""
148
149=== modified file 'services/CMakeLists.txt'
150--- services/CMakeLists.txt 2011-02-24 14:51:30 +0000
151+++ services/CMakeLists.txt 2011-03-17 12:04:28 +0000
152@@ -7,6 +7,30 @@
153 execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator --variable indicatordir OUTPUT_VARIABLE _indicatordir OUTPUT_STRIP_TRAILING_WHITESPACE)
154 execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator --variable iconsdir OUTPUT_VARIABLE _iconsdir OUTPUT_STRIP_TRAILING_WHITESPACE)
155
156+set(PANEL_SOURCES
157+ panel-a11y.c
158+ panel-a11y.h
159+ panel-indicator-accessible.c
160+ panel-indicator-accessible.h
161+ panel-indicator-entry-accessible.c
162+ panel-indicator-entry-accessible.h
163+ panel-main.c
164+ ${CMAKE_SOURCE_DIR}/services/panel-marshal.c
165+ panel-root-accessible.c
166+ panel-root-accessible.h
167+ panel-service.c
168+ panel-service.h
169+ panel-util-accessible.c
170+ panel-util-accessible.h)
171+
172+find_program(GLIB_GENMARSHAL glib-genmarshal)
173+add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/services/panel-marshal.c
174+ COMMAND ${GLIB_GENMARSHAL} ARGS panel-marshal.list --body --prefix=panel_marshal > ${CMAKE_SOURCE_DIR}/services/panel-marshal.c
175+ COMMAND ${GLIB_GENMARSHAL} ARGS panel-marshal.list --header --prefix=panel_marshal > ${CMAKE_SOURCE_DIR}/services/panel-marshal.h
176+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
177+ DEPENDS panel-marshal.list
178+ COMMENT "Generating marshallers")
179+
180 set(CFLAGS
181 ${SERVICE_DEPS_CFLAGS}
182 ${SERVICE_DEPS_CFLAGS_OTHER}
183@@ -24,21 +48,7 @@
184 set(LIB_PATHS ${SERVICE_DEPS_LIBRARY_DIRS})
185 link_directories(${LIB_PATHS})
186
187-add_executable(unity-panel-service
188- panel-a11y.c
189- panel-a11y.h
190- panel-indicator-accessible.c
191- panel-indicator-accessible.h
192- panel-indicator-entry-accessible.c
193- panel-indicator-entry-accessible.h
194- panel-main.c
195- panel-root-accessible.c
196- panel-root-accessible.h
197- panel-service.c
198- panel-service.h
199- panel-util-accessible.c
200- panel-util-accessible.h
201- )
202+add_executable(unity-panel-service ${PANEL_SOURCES})
203 install(TARGETS unity-panel-service DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/unity/)
204
205 configure_file(com.canonical.Unity.Panel.Service.service.cmake ${CMAKE_CURRENT_BINARY_DIR}/com.canonical.Unity.Panel.Service.service)
206
207=== modified file 'services/panel-a11y.c'
208--- services/panel-a11y.c 2011-02-28 15:51:27 +0000
209+++ services/panel-a11y.c 2011-03-17 12:04:28 +0000
210@@ -127,6 +127,7 @@
211 void
212 panel_a11y_init (void)
213 {
214+ AtkObject *root;
215 gchar *bridge_path = NULL;
216
217 if (a11y_initialized)
218@@ -150,5 +151,10 @@
219
220 g_free (bridge_path);
221
222+ /* There might be cases when we start signalling about change of geometries but the
223+ accessible objects are not yet created, so to avoid that, instantiate here the
224+ A11Y root object, which will create them all */
225+ root = atk_get_root ();
226+
227 a11y_initialized = TRUE;
228 }
229
230=== modified file 'services/panel-indicator-accessible.c'
231--- services/panel-indicator-accessible.c 2011-03-14 17:01:34 +0000
232+++ services/panel-indicator-accessible.c 2011-03-17 12:04:28 +0000
233@@ -19,12 +19,11 @@
234 #include <glib/gi18n.h>
235 #include "panel-indicator-accessible.h"
236 #include "panel-indicator-entry-accessible.h"
237-
238-G_DEFINE_TYPE(PanelIndicatorAccessible, panel_indicator_accessible, ATK_TYPE_OBJECT)
239-
240-#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_INDICATOR_ACCESSIBLE, PanelIndicatorAccessiblePrivate))
241+#include "panel-service.h"
242
243 /* AtkObject methods */
244+static void pia_component_interface_init (AtkComponentIface *iface);
245+
246 static void panel_indicator_accessible_initialize (AtkObject *accessible, gpointer data);
247 static gint panel_indicator_accessible_get_n_children (AtkObject *accessible);
248 static AtkObject *panel_indicator_accessible_ref_child (AtkObject *accessible, gint i);
249@@ -33,9 +32,21 @@
250 struct _PanelIndicatorAccessiblePrivate
251 {
252 IndicatorObject *indicator;
253+ PanelService *service;
254 GSList *a11y_children;
255+ gint x;
256+ gint y;
257+ gint width;
258+ gint height;
259 };
260
261+G_DEFINE_TYPE_WITH_CODE(PanelIndicatorAccessible,
262+ panel_indicator_accessible,
263+ ATK_TYPE_OBJECT,
264+ G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, pia_component_interface_init))
265+
266+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_INDICATOR_ACCESSIBLE, PanelIndicatorAccessiblePrivate))
267+
268 /* Indicator callbacks */
269
270 static void
271@@ -100,6 +111,64 @@
272 }
273
274 static void
275+on_geometries_changed_cb (PanelService *service,
276+ IndicatorObject *object,
277+ IndicatorObjectEntry *entry,
278+ gint x,
279+ gint y,
280+ gint width,
281+ gint height,
282+ gpointer user_data)
283+{
284+ PanelIndicatorAccessible *pia;
285+ AtkRectangle rect;
286+ GSList *l;
287+ gboolean minimum_set = FALSE;
288+
289+ pia = PANEL_INDICATOR_ACCESSIBLE (user_data);
290+
291+ g_return_if_fail (PANEL_IS_INDICATOR_ACCESSIBLE (pia));
292+
293+ if (object != pia->priv->indicator)
294+ return;
295+
296+ /* Iterate over all children to get width and height */
297+ pia->priv->width = pia->priv->height = 0;
298+
299+ for (l = pia->priv->a11y_children; l != NULL; l = l->next)
300+ {
301+ gint e_x, e_y, e_width, e_height;
302+ AtkObject *accessible = ATK_OBJECT (l->data);
303+
304+ atk_component_get_extents (ATK_COMPONENT (accessible), &e_x, &e_y, &e_width, &e_height, ATK_XY_SCREEN);
305+ if (minimum_set)
306+ {
307+ if (e_x < pia->priv->x)
308+ pia->priv->x = e_x;
309+ if (e_y < pia->priv->y)
310+ pia->priv->y = e_y;
311+ }
312+ else
313+ {
314+ pia->priv->x = e_x;
315+ pia->priv->y = e_y;
316+ minimum_set = TRUE;
317+ }
318+
319+ pia->priv->width += e_width;
320+ if (e_height > pia->priv->height)
321+ pia->priv->height = e_height;
322+ }
323+
324+ /* Notify ATK objects of change of coordinates */
325+ rect.x = pia->priv->x;
326+ rect.y = pia->priv->y;
327+ rect.width = pia->priv->width;
328+ rect.height = pia->priv->height;
329+ g_signal_emit_by_name (ATK_COMPONENT (pia), "bounds-changed", &rect);
330+}
331+
332+static void
333 panel_indicator_accessible_finalize (GObject *object)
334 {
335 PanelIndicatorAccessible *pia = PANEL_INDICATOR_ACCESSIBLE (object);
336@@ -122,6 +191,8 @@
337 pia->priv->a11y_children = g_slist_remove (pia->priv->a11y_children, accessible);
338 g_object_unref (accessible);
339 }
340+
341+ g_signal_handlers_disconnect_by_func (pia->priv->service, on_geometries_changed_cb, pia);
342 }
343
344 G_OBJECT_CLASS (panel_indicator_accessible_parent_class)->finalize (object);
345@@ -152,6 +223,12 @@
346 {
347 pia->priv = GET_PRIVATE (pia);
348 pia->priv->a11y_children = NULL;
349+ pia->priv->x = pia->priv->y = pia->priv->width = pia->priv->height = 0;
350+
351+ /* Set up signals for listening to service changes */
352+ pia->priv->service = panel_service_get_default ();
353+ g_signal_connect (pia->priv->service, "geometries-changed",
354+ G_CALLBACK (on_geometries_changed_cb), pia);
355 }
356
357 AtkObject *
358@@ -168,6 +245,36 @@
359 /* Implementation of AtkObject methods */
360
361 static void
362+panel_indicator_accessible_get_extents (AtkComponent *component,
363+ gint *x,
364+ gint *y,
365+ gint *width,
366+ gint *height,
367+ AtkCoordType coord_type)
368+{
369+ PanelIndicatorAccessible *pia;
370+
371+ g_return_if_fail (PANEL_IS_INDICATOR_ACCESSIBLE (component));
372+
373+ pia = PANEL_INDICATOR_ACCESSIBLE (component);
374+
375+ /* We ignore AtkCoordType for now, as the panel is always at the top left
376+ corner and so relative and absolute coordinates are the same */
377+ *x = pia->priv->x;
378+ *y = pia->priv->y;
379+ *width = pia->priv->width;
380+ *height = pia->priv->height;
381+}
382+
383+static void
384+pia_component_interface_init (AtkComponentIface *iface)
385+{
386+ g_return_if_fail (iface != NULL);
387+
388+ iface->get_extents = panel_indicator_accessible_get_extents;
389+}
390+
391+static void
392 panel_indicator_accessible_initialize (AtkObject *accessible, gpointer data)
393 {
394 PanelIndicatorAccessible *pia;
395
396=== modified file 'services/panel-indicator-entry-accessible.c'
397--- services/panel-indicator-entry-accessible.c 2011-03-14 16:46:04 +0000
398+++ services/panel-indicator-entry-accessible.c 2011-03-17 12:04:28 +0000
399@@ -19,11 +19,9 @@
400 #include "panel-indicator-entry-accessible.h"
401 #include "panel-service.h"
402
403-G_DEFINE_TYPE(PanelIndicatorEntryAccessible, panel_indicator_entry_accessible, ATK_TYPE_OBJECT)
404-
405-#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, PanelIndicatorEntryAccessiblePrivate))
406-
407 /* AtkObject methods */
408+static void piea_component_interface_init (AtkComponentIface *iface);
409+
410 static void panel_indicator_entry_accessible_initialize (AtkObject *accessible, gpointer data);
411 static gint panel_indicator_entry_accessible_get_n_children (AtkObject *accessible);
412 static AtkObject *panel_indicator_entry_accessible_ref_child (AtkObject *accessible, gint i);
413@@ -33,17 +31,30 @@
414 {
415 IndicatorObjectEntry *entry;
416 PanelService *service;
417+ gint x;
418+ gint y;
419+ gint width;
420+ gint height;
421 gboolean active;
422 };
423
424+G_DEFINE_TYPE_WITH_CODE(PanelIndicatorEntryAccessible,
425+ panel_indicator_entry_accessible,
426+ ATK_TYPE_OBJECT,
427+ G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, piea_component_interface_init))
428+
429+#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, PanelIndicatorEntryAccessiblePrivate))
430+
431 static void
432 on_entry_activated_cb (PanelService *service, const gchar *entry_id, gpointer user_data)
433 {
434 gchar *s;
435 gboolean adding = FALSE;
436- PanelIndicatorEntryAccessible *piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (user_data);
437-
438- g_return_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (piea));
439+ PanelIndicatorEntryAccessible *piea;
440+
441+ g_return_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (user_data));
442+
443+ piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (user_data);
444
445 /* The PanelService sends us a string containing the pointer to the IndicatorObjectEntry */
446 s = g_strdup_printf ("%p", piea->priv->entry);
447@@ -66,6 +77,39 @@
448 }
449
450 static void
451+on_geometries_changed_cb (PanelService *service,
452+ IndicatorObject *object,
453+ IndicatorObjectEntry *entry,
454+ gint x,
455+ gint y,
456+ gint width,
457+ gint height,
458+ gpointer user_data)
459+{
460+ PanelIndicatorEntryAccessible *piea;
461+ AtkRectangle rect;
462+
463+ piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (user_data);
464+
465+ g_return_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (piea));
466+
467+ if (entry != piea->priv->entry)
468+ return;
469+
470+ piea->priv->x = x;
471+ piea->priv->y = y;
472+ piea->priv->width = width;
473+ piea->priv->height = height;
474+
475+ /* Notify ATK objects of change of coordinates */
476+ rect.x = piea->priv->x;
477+ rect.y = piea->priv->y;
478+ rect.width = piea->priv->width;
479+ rect.height = piea->priv->height;
480+ g_signal_emit_by_name (ATK_COMPONENT (piea), "bounds-changed", &rect);
481+}
482+
483+static void
484 panel_indicator_entry_accessible_finalize (GObject *object)
485 {
486 PanelIndicatorEntryAccessible *piea;
487@@ -77,6 +121,7 @@
488 if (piea->priv != NULL)
489 {
490 g_signal_handlers_disconnect_by_func (piea->priv->service, on_entry_activated_cb, piea);
491+ g_signal_handlers_disconnect_by_func (piea->priv->service, on_geometries_changed_cb, piea);
492 }
493
494 G_OBJECT_CLASS (panel_indicator_entry_accessible_parent_class)->finalize (object);
495@@ -106,10 +151,13 @@
496 panel_indicator_entry_accessible_init (PanelIndicatorEntryAccessible *piea)
497 {
498 piea->priv = GET_PRIVATE (piea);
499+ piea->priv->x = piea->priv->y = piea->priv->width = piea->priv->height = 0;
500
501 /* Set up signals for listening to service changes */
502 piea->priv->active = FALSE;
503 piea->priv->service = panel_service_get_default ();
504+ g_signal_connect (piea->priv->service, "geometries-changed",
505+ G_CALLBACK (on_geometries_changed_cb), piea);
506 g_signal_connect (piea->priv->service, "entry-activated",
507 G_CALLBACK (on_entry_activated_cb), piea);
508 }
509@@ -136,6 +184,36 @@
510 /* Implementation of AtkObject methods */
511
512 static void
513+panel_indicator_entry_accessible_get_extents (AtkComponent *component,
514+ gint *x,
515+ gint *y,
516+ gint *width,
517+ gint *height,
518+ AtkCoordType coord_type)
519+{
520+ PanelIndicatorEntryAccessible *piea;
521+
522+ g_return_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (component));
523+
524+ piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (component);
525+
526+ /* We ignore AtkCoordType for now, as the panel is always at the top left
527+ corner and so relative and absolute coordinates are the same */
528+ *x = piea->priv->x;
529+ *y = piea->priv->y;
530+ *width = piea->priv->width;
531+ *height = piea->priv->height;
532+}
533+
534+static void
535+piea_component_interface_init (AtkComponentIface *iface)
536+{
537+ g_return_if_fail (iface != NULL);
538+
539+ iface->get_extents = panel_indicator_entry_accessible_get_extents;
540+}
541+
542+static void
543 panel_indicator_entry_accessible_initialize (AtkObject *accessible, gpointer data)
544 {
545 PanelIndicatorEntryAccessible *piea;
546
547=== modified file 'services/panel-main.c'
548--- services/panel-main.c 2011-01-31 21:52:38 +0000
549+++ services/panel-main.c 2011-03-17 12:04:28 +0000
550@@ -55,6 +55,10 @@
551 " <arg type='a(sssbbusbb)' name='state' direction='out'/>"
552 " </method>"
553 ""
554+ " <method name='SyncGeometries'>"
555+ " <arg type='a(ssiiii)' name='geometries' direction='in'/>"
556+ " </method>"
557+ ""
558 " <method name='ShowEntry'>"
559 " <arg type='s' name='entry_id' direction='in'/>"
560 " <arg type='u' name='timestamp' direction='in'/>"
561@@ -140,6 +144,29 @@
562 id));
563 g_free (id);
564 }
565+ else if (g_strcmp0 (method_name, "SyncGeometries") == 0)
566+ {
567+ GVariantIter *iter;
568+ gchar *indicator_id, *entry_id;
569+ gint x, y, width, height;
570+
571+ g_variant_get (parameters, "(a(ssiiii))", &iter);
572+ while (g_variant_iter_loop (iter, "(ssiiii)",
573+ &indicator_id,
574+ &entry_id,
575+ &x,
576+ &y,
577+ &width,
578+ &height))
579+ {
580+ panel_service_sync_geometry (service, indicator_id,
581+ entry_id, x, y, width, height);
582+ }
583+
584+ g_variant_iter_free (iter);
585+
586+ g_dbus_method_invocation_return_value (invocation, NULL);
587+ }
588 else if (g_strcmp0 (method_name, "ShowEntry") == 0)
589 {
590 gchar *entry_id;
591@@ -309,13 +336,11 @@
592 gtk_icon_theme_append_search_path (gtk_icon_theme_get_default(),
593 INDICATORICONDIR);
594
595- panel_a11y_init ();
596-
597 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
598 g_assert (introspection_data != NULL);
599
600 service = panel_service_get_default ();
601-
602+
603 owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
604 S_NAME,
605 G_BUS_NAME_OWNER_FLAGS_NONE,
606@@ -324,6 +349,9 @@
607 on_name_lost,
608 service,
609 NULL);
610+
611+ panel_a11y_init ();
612+
613 gtk_main ();
614
615 g_bus_unown_name (owner_id);
616
617=== added file 'services/panel-marshal.list'
618--- services/panel-marshal.list 1970-01-01 00:00:00 +0000
619+++ services/panel-marshal.list 2011-03-17 12:04:28 +0000
620@@ -0,0 +1,1 @@
621+NONE:OBJECT,POINTER,INT,INT,INT,INT
622
623=== modified file 'services/panel-service.c'
624--- services/panel-service.c 2011-03-09 00:11:25 +0000
625+++ services/panel-service.c 2011-03-17 12:04:28 +0000
626@@ -21,6 +21,7 @@
627 #include <config.h>
628 #endif
629
630+#include "panel-marshal.h"
631 #include "panel-service.h"
632
633 #include <stdlib.h>
634@@ -67,6 +68,7 @@
635 RE_SYNC,
636 ACTIVE_MENU_POINTER_MOTION,
637 ENTRY_ACTIVATE_REQUEST,
638+ GEOMETRIES_CHANGED,
639
640 LAST_SIGNAL
641 };
642@@ -179,6 +181,16 @@
643 NULL, NULL,
644 g_cclosure_marshal_VOID__STRING,
645 G_TYPE_NONE, 1, G_TYPE_STRING);
646+ _service_signals[GEOMETRIES_CHANGED] =
647+ g_signal_new ("geometries-changed",
648+ G_OBJECT_CLASS_TYPE (obj_class),
649+ G_SIGNAL_RUN_LAST,
650+ 0,
651+ NULL, NULL,
652+ panel_marshal_VOID__OBJECT_POINTER_INT_INT_INT_INT,
653+ G_TYPE_NONE, 6,
654+ G_TYPE_OBJECT, G_TYPE_POINTER,
655+ G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
656
657
658 g_type_class_add_private (obj_class, sizeof (PanelServicePrivate));
659@@ -861,6 +873,22 @@
660 return g_variant_builder_end (&b);
661 }
662
663+void
664+panel_service_sync_geometry (PanelService *self,
665+ const gchar *indicator_id,
666+ const gchar *entry_id,
667+ gint x,
668+ gint y,
669+ gint width,
670+ gint height)
671+{
672+ PanelServicePrivate *priv = self->priv;
673+ IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);
674+ IndicatorObject *object = g_hash_table_lookup (priv->entry2indicator_hash, entry);
675+
676+ g_signal_emit (self, _service_signals[GEOMETRIES_CHANGED], 0, object, entry, x, y, width, height);
677+}
678+
679 static void
680 activate_next_prev_menu (PanelService *self,
681 IndicatorObject *object,
682
683=== modified file 'services/panel-service.h'
684--- services/panel-service.h 2011-02-23 16:49:18 +0000
685+++ services/panel-service.h 2011-03-17 12:04:28 +0000
686@@ -80,6 +80,13 @@
687
688 GVariant * panel_service_sync_one (PanelService *self,
689 const gchar *indicator_id);
690+void panel_service_sync_geometry (PanelService *self,
691+ const gchar *indicator_id,
692+ const gchar *entry_id,
693+ gint x,
694+ gint y,
695+ gint width,
696+ gint height);
697
698 void panel_service_show_entry (PanelService *self,
699 const gchar *entry_id,
700
701=== modified file 'src/IndicatorObjectFactory.h'
702--- src/IndicatorObjectFactory.h 2010-12-17 14:07:11 +0000
703+++ src/IndicatorObjectFactory.h 2011-03-17 12:04:28 +0000
704@@ -47,6 +47,7 @@
705 sigc::signal<void, int, int> OnMenuPointerMoved;
706 sigc::signal<void, const char *> OnEntryActivateRequest;
707 sigc::signal<void, const char *> OnEntryActivated;
708+ sigc::signal<void> OnSynced;
709
710 protected:
711 std::vector<IndicatorObjectProxy *>_indicators;
712
713=== modified file 'src/IndicatorObjectFactoryRemote.cpp'
714--- src/IndicatorObjectFactoryRemote.cpp 2011-01-11 15:48:03 +0000
715+++ src/IndicatorObjectFactoryRemote.cpp 2011-03-17 12:04:28 +0000
716@@ -358,6 +358,9 @@
717
718 g_free (current_proxy_id);
719 g_variant_iter_free (iter);
720+
721+ /* Notify listeners we have new data */
722+ OnSynced.emit ();
723 }
724
725 void
726
727=== modified file 'src/PanelIndicatorObjectView.cpp'
728--- src/PanelIndicatorObjectView.cpp 2011-02-22 23:11:20 +0000
729+++ src/PanelIndicatorObjectView.cpp 2011-03-17 12:04:28 +0000
730@@ -18,6 +18,7 @@
731 */
732
733 #include "Nux/Nux.h"
734+#include "Nux/Area.h"
735 #include "Nux/HLayout.h"
736 #include "Nux/VLayout.h"
737
738@@ -75,7 +76,6 @@
739 void
740 PanelIndicatorObjectView::Draw (nux::GraphicsEngine& GfxContext, bool force_draw)
741 {
742-
743 }
744
745 void
746@@ -153,3 +153,4 @@
747 g_variant_builder_add (builder, "{sv}", "width", g_variant_new_int32 (geo.width));
748 g_variant_builder_add (builder, "{sv}", "height", g_variant_new_int32 (geo.height));
749 }
750+
751
752=== modified file 'src/PanelIndicatorObjectView.h'
753--- src/PanelIndicatorObjectView.h 2011-01-25 15:45:12 +0000
754+++ src/PanelIndicatorObjectView.h 2011-03-17 12:04:28 +0000
755@@ -43,7 +43,7 @@
756 void OnEntryAdded (IndicatorObjectEntryProxy *proxy);
757 void OnEntryMoved (IndicatorObjectEntryProxy *proxy);
758 void OnEntryRemoved (IndicatorObjectEntryProxy *proxy);
759-
760+
761 nux::HLayout *_layout;
762
763 protected:
764
765=== modified file 'src/PanelView.cpp'
766--- src/PanelView.cpp 2011-03-16 09:45:39 +0000
767+++ src/PanelView.cpp 2011-03-17 12:04:28 +0000
768@@ -37,6 +37,10 @@
769 #include "IndicatorObjectFactoryRemote.h"
770 #include "PanelIndicatorObjectView.h"
771
772+#define S_NAME "com.canonical.Unity.Panel.Service"
773+#define S_PATH "/com/canonical/Unity/Panel/Service"
774+#define S_IFACE "com.canonical.Unity.Panel.Service"
775+
776 NUX_IMPLEMENT_OBJECT_TYPE (PanelView);
777
778 PanelView::PanelView (NUX_FILE_LINE_DECL)
779@@ -44,6 +48,7 @@
780 _is_dirty (true),
781 _opacity (1.0f)
782 {
783+ _needs_geo_sync = false;
784 _style = new PanelStyle ();
785 _style->changed.connect (sigc::mem_fun (this, &PanelView::ForceUpdateBackground));
786
787@@ -70,6 +75,7 @@
788 _remote->OnMenuPointerMoved.connect (sigc::mem_fun (this, &PanelView::OnMenuPointerMoved));
789 _remote->OnEntryActivateRequest.connect (sigc::mem_fun (this, &PanelView::OnEntryActivateRequest));
790 _remote->IndicatorObjectFactory::OnEntryActivated.connect (sigc::mem_fun (this, &PanelView::OnEntryActivated));
791+ _remote->IndicatorObjectFactory::OnSynced.connect (sigc::mem_fun (this, &PanelView::OnSynced));
792 }
793
794 PanelView::~PanelView ()
795@@ -122,6 +128,12 @@
796 gPainter.PopBackground ();
797
798 GfxContext.PopClippingRectangle ();
799+
800+ if (_needs_geo_sync)
801+ {
802+ SyncGeometries ();
803+ _needs_geo_sync = false;
804+ }
805 }
806
807 void
808@@ -333,6 +345,12 @@
809 _menu_view->AllMenusClosed ();
810 }
811
812+void
813+PanelView::OnSynced ()
814+{
815+ _needs_geo_sync = true;
816+}
817+
818 //
819 // Useful Public Methods
820 //
821@@ -390,3 +408,86 @@
822
823 ForceUpdateBackground ();
824 }
825+
826+static void
827+on_sync_geometries_done_cb (GObject *source,
828+ GAsyncResult *res,
829+ gpointer data)
830+{
831+ GVariant *args;
832+ GError *error = NULL;
833+
834+ args = g_dbus_proxy_call_finish ((GDBusProxy*) source, res, &error);
835+ if (error != NULL)
836+ {
837+ g_warning ("Error when calling SyncGeometries: %s", error->message);
838+ g_error_free (error);
839+ }
840+}
841+
842+void
843+PanelView::SyncGeometries ()
844+{
845+ GVariantBuilder b;
846+ GDBusProxy *bus_proxy;
847+ GVariant *method_args;
848+ std::list<Area *>::iterator it;
849+
850+ g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssiiii))"));
851+ g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssiiii)"));
852+
853+ std::list<Area *> my_children = _layout->GetChildren ();
854+ for (it = my_children.begin(); it != my_children.end(); it++)
855+ {
856+ PanelIndicatorObjectView *view = static_cast<PanelIndicatorObjectView *> (*it);
857+
858+ if (view->_layout == NULL)
859+ continue;
860+
861+ std::list<Area *>::iterator it2;
862+
863+ std::list<Area *> its_children = view->_layout->GetChildren ();
864+ for (it2 = its_children.begin (); it2 != its_children.end (); it2++)
865+ {
866+ nux::Geometry geo;
867+ PanelIndicatorObjectEntryView *entry = static_cast<PanelIndicatorObjectEntryView *> (*it2);
868+
869+ if (entry == NULL)
870+ continue;
871+
872+ geo = entry->GetAbsoluteGeometry ();
873+ g_variant_builder_add (&b, "(ssiiii)",
874+ GetName (),
875+ entry->_proxy->GetId (),
876+ geo.x,
877+ geo.y,
878+ geo.GetWidth (),
879+ geo.GetHeight ());
880+ }
881+ }
882+
883+ g_variant_builder_close (&b);
884+ method_args = g_variant_builder_end (&b);
885+
886+ // Send geometries to the panel service
887+ bus_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
888+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
889+ NULL,
890+ S_NAME,
891+ S_PATH,
892+ S_IFACE,
893+ NULL,
894+ NULL);
895+ if (bus_proxy != NULL)
896+ {
897+ g_dbus_proxy_call (bus_proxy, "SyncGeometries", method_args,
898+ G_DBUS_CALL_FLAGS_NONE,
899+ -1,
900+ NULL,
901+ on_sync_geometries_done_cb,
902+ this);
903+ g_object_unref (bus_proxy);
904+ }
905+
906+ g_variant_unref (method_args);
907+}
908
909=== modified file 'src/PanelView.h'
910--- src/PanelView.h 2011-03-16 09:45:39 +0000
911+++ src/PanelView.h 2011-03-17 12:04:28 +0000
912@@ -51,6 +51,7 @@
913 void OnMenuPointerMoved (int x, int y);
914 void OnEntryActivateRequest (const char *entry_id);
915 void OnEntryActivated (const char *entry_id);
916+ void OnSynced ();
917
918 PanelHomeButton * HomeButton ();
919
920@@ -70,6 +71,7 @@
921 private:
922 void UpdateBackground ();
923 void ForceUpdateBackground ();
924+ void SyncGeometries ();
925
926 private:
927 IndicatorObjectFactoryRemote *_remote;
928@@ -86,6 +88,7 @@
929 PanelStyle *_style;
930 bool _is_dirty;
931 float _opacity;
932+ bool _needs_geo_sync;
933 };
934
935 #endif // PANEL_VIEW_H
936
937=== modified file 'tests/CMakeLists.txt'
938--- tests/CMakeLists.txt 2011-03-11 14:43:50 +0000
939+++ tests/CMakeLists.txt 2011-03-17 12:04:28 +0000
940@@ -30,6 +30,14 @@
941
942 include_directories (. .. ../services ${CMAKE_BINARY_DIR})
943
944+find_program(GLIB_GENMARSHAL glib-genmarshal)
945+add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/services/panel-marshal.c
946+ COMMAND ${GLIB_GENMARSHAL} ARGS ${CMAKE_SOURCE_DIR}/services/panel-marshal.list --body --prefix=panel_marshal > ${CMAKE_SOURCE_DIR}/services/panel-marshal.c
947+ COMMAND ${GLIB_GENMARSHAL} ARGS ${CMAKE_SOURCE_DIR}/services/panel-marshal.list --header --prefix=panel_marshal > ${CMAKE_SOURCE_DIR}/services/panel-marshal.h
948+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
949+ DEPENDS ../services/panel-marshal.list
950+ COMMENT "Generating marshallers")
951+
952 # We can't have convenience libs so we need to rebuild with what we need
953 # Please keep actual test files alphabetically at top and then files
954 # from ../../src or ../../services in alphabetically after that
955@@ -44,6 +52,7 @@
956 ../src/ubus-server.h
957 ../services/panel-service.c
958 ../services/panel-service.h
959+ ${CMAKE_SOURCE_DIR}/services/panel-marshal.c
960 ../src/FavoriteStore.cpp
961 ../src/FavoriteStore.h
962 ../src/FavoriteStoreGSettings.cpp