diff options
22 files changed, 146 insertions, 81 deletions
@@ -0,0 +1,35 @@ +The indicator service file format +================================= + +Unity's panel finds out about indicator by looking at indicator service +files in `/usr/share/unity/indicators`. These files have to have the same +name as the well-known D-Bus name that the corresponding service owns. + +An indicator file is a normal key file (like desktop files). It must have +an `[Indicator Service]` section, that contains the service's name +(`Name`) and optionally the object path at which its action group is found +(`ObjectPath`). For example: + + [Indicator Service] + Name=indicator-example + ObjectPath=/com/canonical/indicator/example + +An indicator can only export one action group, but a menu for each profile +("desktop", "greeter", "phone") supports. There must be a section for each +of those profiles, containing the object path on which the menu is +exported: + + [desktop] + ObjectPath=/com/canonical/indicator/example/desktop + + [greeter] + ObjectPath=/com/canonical/indicator/example/desktop + + [phone] + ObjectPath=/com/canonical/indicator/example/phone + +Object paths can be reused for different profiles (the greeter uses the +same menu as the desktop in the above example). + +There are no fallbacks. If a profile is not mentioned in the service file, +the indicator will not show up for that profile. diff --git a/debian/changelog b/debian/changelog index 17f10ee..75d0828 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,25 @@ +libindicator (12.10.2daily13.06.07-0ubuntu1) saucy; urgency=low + + [ Ted Gould ] + * Migrating away from deprecated gtk_icon_info_free(). + + [ William Hua ] + * Use GIcon's serialization/deserialization interface for indicator + icons so that we can load icons as PNG data transmitted over the + bus. + + [ Marco Trevisan (TreviƱo) ] + * IndicatorDesktopShortcuts: Use the proper way to create an AppInfo + from command-line Removed the hack that we used to create a .desktop + app-info from a locally generated keyfile, using + g_app_info_create_from_commandline instead. (LP: #1168373) + * tests: fix compilation and make check. + + [ Ubuntu daily release ] + * Automatic snapshot from revision 492 + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 07 Jun 2013 02:02:37 +0000 + libindicator (12.10.2daily13.05.02-0ubuntu1) saucy; urgency=low * Automatic snapshot from revision 487 diff --git a/libindicator/indicator-desktop-shortcuts.c b/libindicator/indicator-desktop-shortcuts.c index 70d964e..740d7e1 100644 --- a/libindicator/indicator-desktop-shortcuts.c +++ b/libindicator/indicator-desktop-shortcuts.c @@ -625,46 +625,34 @@ indicator_desktop_shortcuts_nick_exec_with_context (IndicatorDesktopShortcuts * NULL, NULL); - /* Build a new desktop file with the name and exec in the desktop - group. We have to do this with data as apparently there isn't - and add_group function in g_key_file. Go figure. */ - gchar * desktopdata = g_strdup_printf("[" G_KEY_FILE_DESKTOP_GROUP "]\n" - G_KEY_FILE_DESKTOP_KEY_TYPE "=" G_KEY_FILE_DESKTOP_TYPE_APPLICATION "\n" - G_KEY_FILE_DESKTOP_KEY_NAME "=%s\n" - G_KEY_FILE_DESKTOP_KEY_EXEC "=%s\n" - G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY "=%s\n", - name, exec, launch_context ? "true" : "false"); + GAppInfoCreateFlags flags = G_APP_INFO_CREATE_NONE; - g_free(name); g_free(exec); - /* g_debug("Desktop file: \n%s", desktopdata); */ + if (launch_context) { + flags |= G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION; + } - GKeyFile * launcher = g_key_file_new(); - g_key_file_load_from_data(launcher, desktopdata, -1, G_KEY_FILE_NONE, &error); - g_free(desktopdata); + GAppInfo * appinfo = g_app_info_create_from_commandline(exec, name, flags, &error); + g_free(name); g_free(exec); if (error != NULL) { - g_warning("Unable to build desktop keyfile for executing shortcut '%s': %s", nick, error->message); + g_warning("Unable to build Command line App info: %s", error->message); g_error_free(error); return FALSE; } - GDesktopAppInfo * appinfo = g_desktop_app_info_new_from_keyfile(launcher); if (appinfo == NULL) { - g_warning("Unable to build Desktop App info (unknown)"); - g_key_file_free(launcher); + g_warning("Unable to build Command line App info (unknown)"); return FALSE; } - gboolean launched = g_app_info_launch(G_APP_INFO(appinfo), NULL, launch_context, &error); + + gboolean launched = g_app_info_launch(appinfo, NULL, launch_context, &error); if (error != NULL) { g_warning("Unable to launch file from nick '%s': %s", nick, error->message); - g_error_free(error); - g_key_file_free(launcher); - return FALSE; + g_clear_error(&error); } g_object_unref(appinfo); - g_key_file_free(launcher); return launched; } diff --git a/libindicator/indicator-image-helper.c b/libindicator/indicator-image-helper.c index aff9e39..9f48895 100644 --- a/libindicator/indicator-image-helper.c +++ b/libindicator/indicator-image-helper.c @@ -119,7 +119,13 @@ refresh_image (GtkImage * image) } if (icon_info != NULL) { +#if GTK_CHECK_VERSION(3, 8, 0) + g_object_unref(icon_info); +#else + /* NOTE: Leaving this in for lower version as it seems + the object_unref() doesn't work on earlier versions. */ gtk_icon_info_free (icon_info); +#endif } } diff --git a/libindicator/indicator-ng.c b/libindicator/indicator-ng.c index fd78662..88db31c 100644 --- a/libindicator/indicator-ng.c +++ b/libindicator/indicator-ng.c @@ -29,6 +29,7 @@ struct _IndicatorNg gchar *service_file; gchar *name; gchar *object_path; + gchar *menu_object_path; gchar *bus_name; gchar *profile; gchar *header_action; @@ -152,6 +153,7 @@ indicator_ng_finalize (GObject *object) g_free (self->service_file); g_free (self->name); g_free (self->object_path); + g_free (self->menu_object_path); g_free (self->bus_name); g_free (self->accessible_desc); g_free (self->header_action); @@ -254,15 +256,12 @@ indicator_ng_update_entry (IndicatorNg *self) state = g_action_group_get_action_state (self->actions, self->header_action); if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(sssb)"))) { - gchar *iconstr = NULL; + const gchar *iconstr = NULL; g_variant_get (state, "(&s&s&sb)", &label, &iconstr, &accessible_desc, &visible); if (iconstr) - { - icon = g_variant_ref_sink (g_variant_new_string (iconstr)); - g_free (iconstr); - } + icon = g_variant_ref_sink (g_variant_new_string (iconstr)); } else if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("a{sv}"))) { @@ -362,11 +361,13 @@ indicator_ng_service_appeared (GDBusConnection *connection, gpointer user_data) { IndicatorNg *self = user_data; - gchar *menu_object_path; g_assert (!self->actions); g_assert (!self->menu); + /* watch is not established when menu_object_path == NULL */ + g_assert (self->menu_object_path); + self->session_bus = g_object_ref (connection); self->actions = G_ACTION_GROUP (g_dbus_action_group_get (connection, name_owner, self->object_path)); @@ -375,15 +376,12 @@ indicator_ng_service_appeared (GDBusConnection *connection, g_signal_connect_swapped (self->actions, "action-removed", G_CALLBACK (indicator_ng_update_entry), self); g_signal_connect_swapped (self->actions, "action-state-changed", G_CALLBACK (indicator_ng_update_entry), self); - menu_object_path = g_strconcat (self->object_path, "/", self->profile, NULL); - self->menu = G_MENU_MODEL (g_dbus_menu_model_get (connection, name_owner, menu_object_path)); + self->menu = G_MENU_MODEL (g_dbus_menu_model_get (connection, name_owner, self->menu_object_path)); g_signal_connect (self->menu, "items-changed", G_CALLBACK (indicator_ng_menu_changed), self); if (g_menu_model_get_n_items (self->menu)) indicator_ng_menu_changed (self->menu, 0, 0, 1, self); indicator_ng_update_entry (self); - - g_free (menu_object_path); } static void @@ -460,39 +458,70 @@ indicator_ng_service_vanished (GDBusConnection *connection, } static gboolean +indicator_ng_load_from_keyfile (IndicatorNg *self, + GKeyFile *keyfile, + GError **error) +{ + g_assert (self->name == NULL); + g_assert (self->object_path == NULL); + g_assert (self->menu_object_path == NULL); + + self->name = g_key_file_get_string (keyfile, "Indicator Service", "Name", error); + if (self->name == NULL) + return FALSE; + + self->object_path = g_key_file_get_string (keyfile, "Indicator Service", "ObjectPath", error); + if (self->object_path == NULL) + return FALSE; + + /* + * Don't throw an error when the profile doesn't exist. Non-existant + * profiles are silently ignored by not showing an indicator at all. + */ + if (g_key_file_has_group (keyfile, self->profile)) + { + /* however, if the profile exists, it must have "ObjectPath" */ + self->menu_object_path = g_key_file_get_string (keyfile, self->profile, "ObjectPath", error); + if (self->menu_object_path == NULL) + return FALSE; + } + + return TRUE; +} + +static gboolean indicator_ng_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { IndicatorNg *self = INDICATOR_NG (initable); GKeyFile *keyfile; + gboolean success; - keyfile = g_key_file_new (); - if (!g_key_file_load_from_file (keyfile, self->service_file, G_KEY_FILE_NONE, error)) - goto out; - - if (!(self->name = g_key_file_get_string (keyfile, "Indicator Service", "Name", error))) - goto out; - - self->entry.name_hint = self->name; + self->bus_name = g_path_get_basename (self->service_file); - if (!(self->bus_name = g_key_file_get_string (keyfile, "Indicator Service", "BusName", error))) - goto out; + keyfile = g_key_file_new (); + if (g_key_file_load_from_file (keyfile, self->service_file, G_KEY_FILE_NONE, error) && + indicator_ng_load_from_keyfile (self, keyfile, error)) + { + self->entry.name_hint = self->name; - if (!(self->object_path = g_key_file_get_string (keyfile, "Indicator Service", "ObjectPath", error))) - goto out; + /* only watch the service when it supports the proile we're interested in */ + if (self->menu_object_path) + { + self->name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + self->bus_name, + G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + indicator_ng_service_appeared, + indicator_ng_service_vanished, + self, NULL); + } - self->name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, - self->bus_name, - G_BUS_NAME_WATCHER_FLAGS_AUTO_START, - indicator_ng_service_appeared, - indicator_ng_service_vanished, - self, NULL); + success = TRUE; + } -out: g_key_file_free (keyfile); - - return self->name_watch_id > 0; + return success; } static void diff --git a/tests/com.canonical.test.indicator b/tests/com.canonical.indicator.no-such-service index dad4c94..54cc4fd 100644 --- a/tests/com.canonical.test.indicator +++ b/tests/com.canonical.indicator.no-such-service @@ -1,4 +1,3 @@ [Indicator Service] Name=indicator-test -BusName=com.canonical.indicator.test ObjectPath=/com/canonical/indicator/test diff --git a/tests/com.canonical.test.nosuchservice.indicator b/tests/com.canonical.indicator.test index 8464749..0c7122f 100644 --- a/tests/com.canonical.test.nosuchservice.indicator +++ b/tests/com.canonical.indicator.test @@ -1,4 +1,6 @@ [Indicator Service] Name=indicator-test -BusName=com.canonical.indicator.test.nosuchservice ObjectPath=/com/canonical/indicator/test + +[desktop] +ObjectPath=/com/canonical/indicator/test/desktop diff --git a/tests/service-manager-connect-service.c b/tests/service-manager-connect-service.c index 09a7ba1..e56060a 100644 --- a/tests/service-manager-connect-service.c +++ b/tests/service-manager-connect-service.c @@ -48,8 +48,6 @@ shutdown (void) int main (int argc, char ** argv) { - g_type_init(); - g_debug("Starting service"); IndicatorService * is = indicator_service_new("org.ayatana.test"); diff --git a/tests/service-manager-connect.c b/tests/service-manager-connect.c index 5e7684f..5b07972 100644 --- a/tests/service-manager-connect.c +++ b/tests/service-manager-connect.c @@ -62,7 +62,6 @@ connection (IndicatorServiceManager * sm, gboolean connected, gpointer user_data int main (int argc, char ** argv) { - g_type_init(); g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); IndicatorServiceManager * is = indicator_service_manager_new("org.ayatana.test"); diff --git a/tests/service-manager-no-connect.c b/tests/service-manager-no-connect.c index fab0607..ad28507 100644 --- a/tests/service-manager-no-connect.c +++ b/tests/service-manager-no-connect.c @@ -48,7 +48,6 @@ connection (void) int main (int argc, char ** argv) { - g_type_init(); g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); IndicatorServiceManager * is = indicator_service_manager_new("my.test.name"); diff --git a/tests/service-manager-nostart-connect.c b/tests/service-manager-nostart-connect.c index ce0ac80..48f4997 100644 --- a/tests/service-manager-nostart-connect.c +++ b/tests/service-manager-nostart-connect.c @@ -62,7 +62,6 @@ connection (IndicatorServiceManager * sm, gboolean connected, gpointer user_data int main (int argc, char ** argv) { - g_type_init(); g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); g_usleep(150000); diff --git a/tests/service-shutdown-timeout.c b/tests/service-shutdown-timeout.c index e461af0..b909077 100644 --- a/tests/service-shutdown-timeout.c +++ b/tests/service-shutdown-timeout.c @@ -48,8 +48,6 @@ shutdown (void) int main (int argc, char ** argv) { - g_type_init(); - IndicatorService * is = indicator_service_new("my.test.name"); g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, shutdown, NULL); diff --git a/tests/service-version-bad-service.c b/tests/service-version-bad-service.c index 12081d1..556575e 100644 --- a/tests/service-version-bad-service.c +++ b/tests/service-version-bad-service.c @@ -49,8 +49,6 @@ shutdown (void) int main (int argc, char ** argv) { - g_type_init(); - IndicatorService * is = indicator_service_new_version("org.ayatana.version.bad", SERVICE_VERSION_BAD); g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, shutdown, NULL); diff --git a/tests/service-version-good-service.c b/tests/service-version-good-service.c index 17f987e..9c0dde7 100644 --- a/tests/service-version-good-service.c +++ b/tests/service-version-good-service.c @@ -62,8 +62,6 @@ shutdown (void) int main (int argc, char ** argv) { - g_type_init(); - is = indicator_service_new_version("org.ayatana.version.good", SERVICE_VERSION_GOOD); g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, shutdown, NULL); diff --git a/tests/service-version-manager.c b/tests/service-version-manager.c index 9e582f5..63bd6b0 100644 --- a/tests/service-version-manager.c +++ b/tests/service-version-manager.c @@ -58,7 +58,6 @@ connection_good (IndicatorServiceManager * sm, gboolean connected, gpointer user int main (int argc, char ** argv) { - g_type_init(); g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); g_print("Manager: DBUS_SESSION_BUS_ADDRESS = %s\n", g_getenv("DBUS_SESSION_BUS_ADDRESS")); diff --git a/tests/service-version-multiwatch-manager-impolite.c b/tests/service-version-multiwatch-manager-impolite.c index b4cd1c8..68788b9 100644 --- a/tests/service-version-multiwatch-manager-impolite.c +++ b/tests/service-version-multiwatch-manager-impolite.c @@ -64,7 +64,6 @@ delay_start (gpointer data) int main (int argc, char ** argv) { - g_type_init(); g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); g_print("Manager: DBUS_SESSION_BUS_ADDRESS = %s\n", g_getenv("DBUS_SESSION_BUS_ADDRESS")); diff --git a/tests/service-version-multiwatch-manager.c b/tests/service-version-multiwatch-manager.c index 4db6769..633ee59 100644 --- a/tests/service-version-multiwatch-manager.c +++ b/tests/service-version-multiwatch-manager.c @@ -64,7 +64,6 @@ delay_start (gpointer data) int main (int argc, char ** argv) { - g_type_init(); g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); g_print("Manager: DBUS_SESSION_BUS_ADDRESS = %s\n", g_getenv("DBUS_SESSION_BUS_ADDRESS")); diff --git a/tests/service-version-multiwatch-service.c b/tests/service-version-multiwatch-service.c index 30b7f00..1333d7a 100644 --- a/tests/service-version-multiwatch-service.c +++ b/tests/service-version-multiwatch-service.c @@ -49,7 +49,6 @@ shutdown (void) int main (int argc, char ** argv) { - g_type_init(); g_debug("Service starting"); IndicatorService * is = indicator_service_new_version("org.ayatana.version.good", SERVICE_VERSION_GOOD); diff --git a/tests/test-desktop-shortcuts.c b/tests/test-desktop-shortcuts.c index 2e121fa..4f20d3e 100644 --- a/tests/test-desktop-shortcuts.c +++ b/tests/test-desktop-shortcuts.c @@ -125,7 +125,7 @@ test_desktop_shortcuts_launch (void) const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(ids); g_assert(nicks_contains(nicks, "touch")); - g_assert(indicator_desktop_shortcuts_nick_exec(ids, "touch")); + g_assert(indicator_desktop_shortcuts_nick_exec_with_context(ids, "touch", NULL)); g_usleep(100000); g_assert(g_file_test(BUILD_DIR "/test-desktop-shortcuts-touch-test", G_FILE_TEST_EXISTS)); @@ -149,7 +149,6 @@ test_desktop_shortcuts_suite (void) int main (int argc, char ** argv) { - g_type_init (); g_test_init (&argc, &argv, NULL); gtk_init(&argc, &argv); diff --git a/tests/test-indicator-ng.c b/tests/test-indicator-ng.c index 150cc37..7b677d3 100644 --- a/tests/test-indicator-ng.c +++ b/tests/test-indicator-ng.c @@ -50,11 +50,11 @@ test_instantiation (void) GError *error = NULL; GMainLoop *loop; - indicator = indicator_ng_new (SRCDIR "/com.canonical.test.nosuchservice.indicator", &error); + indicator = indicator_ng_new (SRCDIR "/com.canonical.indicator.no-such-service", &error); g_assert (indicator); g_assert (error == NULL); - g_assert_cmpstr (indicator_ng_get_service_file (indicator), ==, SRCDIR "/com.canonical.test.nosuchservice.indicator"); + g_assert_cmpstr (indicator_ng_get_service_file (indicator), ==, SRCDIR "/com.canonical.indicator.no-such-service"); g_assert_cmpstr (indicator_ng_get_profile (indicator), ==, "desktop"); { @@ -65,7 +65,7 @@ test_instantiation (void) "profile", &profile, NULL); - g_assert_cmpstr (service_file, ==, SRCDIR "/com.canonical.test.nosuchservice.indicator"); + g_assert_cmpstr (service_file, ==, SRCDIR "/com.canonical.indicator.no-such-service"); g_assert_cmpstr (profile, ==, "desktop"); g_free (service_file); @@ -89,7 +89,7 @@ test_instantiation_with_profile (void) IndicatorNg *indicator; GError *error = NULL; - indicator = indicator_ng_new_for_profile (SRCDIR "/com.canonical.test.indicator", "greeter", &error); + indicator = indicator_ng_new_for_profile (SRCDIR "/com.canonical.indicator.test", "greeter", &error); g_assert (indicator); g_assert (error == NULL); @@ -107,7 +107,7 @@ test_menu (void) GList *entries; IndicatorObjectEntry *entry; - indicator = indicator_ng_new (SRCDIR "/com.canonical.test.indicator", &error); + indicator = indicator_ng_new (SRCDIR "/com.canonical.indicator.test", &error); g_assert (indicator); g_assert (error == NULL); diff --git a/tests/test-loader.c b/tests/test-loader.c index 45901cb..28187ad 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -362,7 +362,6 @@ test_loader_creation_deletion_suite (void) int main (int argc, char ** argv) { - g_type_init (); g_test_init (&argc, &argv, NULL); gtk_init(&argc, &argv); diff --git a/tools/indicator-loader.c b/tools/indicator-loader.c index ca34bf0..ff3a71b 100644 --- a/tools/indicator-loader.c +++ b/tools/indicator-loader.c @@ -151,7 +151,7 @@ load_module (const gchar * name, GtkWidget * menu) io = indicator_object_new_from_file(name); } #if GTK_MAJOR_VERSION == 3 - else if (g_str_has_suffix(name, ".indicator")) { + else { GError *error = NULL; io = INDICATOR_OBJECT (indicator_ng_new_for_profile (name, profile, &error)); @@ -163,9 +163,10 @@ load_module (const gchar * name, GtkWidget * menu) title = g_strdup_printf ("%s %s", profile, name); } -#endif +#else else return FALSE; +#endif /* Connect to it's signals */ g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(entry_added), menu); |