aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Uebernickel <lars.uebernickel@canonical.com>2012-06-02 16:44:47 +0200
committerLars Uebernickel <lars.uebernickel@canonical.com>2012-06-02 16:44:47 +0200
commit21f3cac4cb191430abf89b7cebd0093952c827b0 (patch)
tree5aee144e7dac57d0c4cd764614b9dab7ebc9fa92
parentb4062c831c830df78baeecf092e7c5e7198afada (diff)
downloadayatana-indicator-messages-21f3cac4cb191430abf89b7cebd0093952c827b0.tar.gz
ayatana-indicator-messages-21f3cac4cb191430abf89b7cebd0093952c827b0.tar.bz2
ayatana-indicator-messages-21f3cac4cb191430abf89b7cebd0093952c827b0.zip
Listen to actions exported by applications
-rw-r--r--src/app-section.c68
-rw-r--r--src/app-section.h5
-rw-r--r--src/messages-service-dbus.c4
-rw-r--r--src/messages-service.c57
4 files changed, 114 insertions, 20 deletions
diff --git a/src/app-section.c b/src/app-section.c
index 6990611..6d00cf1 100644
--- a/src/app-section.c
+++ b/src/app-section.c
@@ -42,6 +42,9 @@ struct _AppSectionPrivate
GMenu *menu;
GSimpleActionGroup *static_shortcuts;
+ GActionGroup *actions;
+
+ guint name_watch_id;
};
#define APP_SECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_SECTION_TYPE, AppSectionPrivate))
@@ -155,6 +158,12 @@ app_section_dispose (GObject *object)
g_clear_object (&priv->menu);
g_clear_object (&priv->static_shortcuts);
+ if (priv->actions) {
+ g_clear_object (&priv->actions);
+ g_bus_unwatch_name (priv->name_watch_id);
+ priv->name_watch_id = 0;
+ }
+
if (priv->ids != NULL) {
g_object_unref(priv->ids);
priv->ids = NULL;
@@ -328,3 +337,62 @@ app_section_create_menu_item (AppSection *self)
return item;
}
+static void
+application_vanished (GDBusConnection *bus,
+ const gchar *name,
+ gpointer user_data)
+{
+ AppSection *self = user_data;
+
+ app_section_unset_object_path (self);
+}
+
+/*
+ * app_section_set_object_path:
+ * @self: an #AppSection
+ * @bus: a #GDBusConnection
+ * @bus_name: the bus name of the application
+ * @object_path: the object path on which the app exports its actions and menus
+ *
+ * Sets the D-Bus object path exported by an instance of the application
+ * associated with @self. Actions and menus exported on that path will be
+ * shown in the section.
+ */
+void
+app_section_set_object_path (AppSection *self,
+ GDBusConnection *bus,
+ const gchar *bus_name,
+ const gchar *object_path)
+{
+ AppSectionPrivate *priv = APP_SECTION_GET_PRIVATE (self);
+
+ if (priv->actions) {
+ g_clear_object (&priv->actions);
+ g_bus_unwatch_name (priv->name_watch_id);
+ }
+
+ priv->actions = G_ACTION_GROUP (g_dbus_action_group_get (bus, bus_name, object_path));
+ priv->name_watch_id = g_bus_watch_name_on_connection (bus, bus_name, 0,
+ NULL, application_vanished,
+ self, NULL);
+}
+
+/*
+ * app_section_unset_object_path:
+ * @self: an #AppSection
+ *
+ * Unsets the object path set with app_section_set_object_path(). The section
+ * will return to only showing application name and static shortcuts in the
+ * menu.
+ */
+void
+app_section_unset_object_path (AppSection *self)
+{
+ AppSectionPrivate *priv = APP_SECTION_GET_PRIVATE (self);
+
+ if (priv->actions) {
+ g_clear_object (&priv->actions);
+ g_bus_unwatch_name (priv->name_watch_id);
+ }
+}
+
diff --git a/src/app-section.h b/src/app-section.h
index e5c3892..aa6ef75 100644
--- a/src/app-section.h
+++ b/src/app-section.h
@@ -52,6 +52,11 @@ const gchar * app_section_get_desktop (AppSection * appitem);
GMenuModel * app_section_get_menu (AppSection *appitem);
GAppInfo * app_section_get_app_info (AppSection *appitem);
GMenuItem * app_section_create_menu_item (AppSection *self);
+void app_section_set_object_path (AppSection *self,
+ GDBusConnection *bus,
+ const gchar *bus_name,
+ const gchar *object_path);
+void app_section_unset_object_path (AppSection *self);
G_END_DECLS
diff --git a/src/messages-service-dbus.c b/src/messages-service-dbus.c
index fec15e9..3a39172 100644
--- a/src/messages-service-dbus.c
+++ b/src/messages-service-dbus.c
@@ -109,7 +109,7 @@ message_service_dbus_class_init (MessageServiceDbusClass *klass)
0,
NULL, NULL,
g_cclosure_marshal_generic,
- G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
+ G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
signals[UNREGISTER_APPLICATION] = g_signal_new(MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION,
G_TYPE_FROM_CLASS(klass),
@@ -439,7 +439,7 @@ bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar
} else if (g_strcmp0("RegisterApplication", method) == 0) {
const gchar *desktop_id, *object_path;
g_variant_get(params, "(&s&o)", &desktop_id, &object_path);
- g_signal_emit(ms, signals[REGISTER_APPLICATION], 0, desktop_id, object_path);
+ g_signal_emit(ms, signals[REGISTER_APPLICATION], 0, sender, desktop_id, object_path);
g_dbus_method_invocation_return_value(invocation, NULL);
} else if (g_strcmp0("UnregisterApplication", method) == 0) {
const gchar *desktop_id;
diff --git a/src/messages-service.c b/src/messages-service.c
index ddedee9..28a64a0 100644
--- a/src/messages-service.c
+++ b/src/messages-service.c
@@ -47,34 +47,36 @@ static GMainLoop * mainloop = NULL;
static MessageServiceDbus * dbus_interface = NULL;
-static void
-add_application (const gchar *desktop_id,
- const gchar *menu_path)
+static AppSection *
+add_application (const gchar *desktop_id)
{
GDesktopAppInfo *appinfo;
const gchar *desktop_file;
+ AppSection *section;
appinfo = g_desktop_app_info_new (desktop_id);
if (!appinfo) {
g_warning ("could not add '%s', there's no desktop file with that id", desktop_id);
- return;
+ return NULL;
}
desktop_file = g_desktop_app_info_get_filename (appinfo);
+ section = g_hash_table_lookup (applications, desktop_file);
- if (!g_hash_table_lookup (applications, desktop_file)) {
- AppSection *section = app_section_new(appinfo);
- GMenuItem *item = app_section_create_menu_item (section);
+ if (!section) {
+ GMenuItem *item;
+ section = app_section_new(appinfo);
g_hash_table_insert (applications, g_strdup (desktop_file), section);
+ item = app_section_create_menu_item (section);
/* TODO insert it at the right position (alphabetically by application name) */
g_menu_insert_item (menu, 2, item);
-
g_object_unref (item);
}
g_object_unref (appinfo);
+ return section;
}
/* g_menu_model_find_section:
@@ -133,7 +135,7 @@ build_launcher (gpointer data)
{
gchar *desktop_id = data;
- add_application (desktop_id, NULL);
+ add_application (desktop_id);
g_free (desktop_id);
return FALSE;
@@ -186,22 +188,43 @@ clear_action_handler (MessageServiceDbus *msd,
g_simple_action_set_enabled (action, attention);
}
+static gint
+g_strv_find (gchar **str_array,
+ const gchar *key)
+{
+ gchar **it;
+
+ g_return_val_if_fail (str_array != NULL, -1);
+
+ for (it = str_array; *it; it++) {
+ if (!g_strcmp0 (key, *it))
+ return it - str_array;
+ }
+
+ return -1;
+}
+
static void
register_application (MessageServiceDbus *msd,
+ const gchar *sender,
const gchar *desktop_id,
const gchar *menu_path,
gpointer user_data)
{
- gchar **applications = g_settings_get_strv (settings, "applications");
- gchar **app;
+ AppSection *section;
+ gchar **applications;
- for (app = applications; *app; app++) {
- if (!g_strcmp0 (desktop_id, *app))
- break;
- }
+ section = add_application (desktop_id);
+ if (!section)
+ return;
- if (*app == NULL) {
+ app_section_set_object_path (section, bus, sender, menu_path);
+
+ /* remember this application in the settings key */
+ applications = g_settings_get_strv (settings, "applications");
+ if (g_strv_find (applications, desktop_id) < 0) {
GVariantBuilder builder;
+ gchar **app;
g_variant_builder_init (&builder, (GVariantType *)"as");
for (app = applications; *app; app++)
@@ -210,8 +233,6 @@ register_application (MessageServiceDbus *msd,
g_settings_set_value (settings, "applications",
g_variant_builder_end (&builder));
-
- add_application (desktop_id, menu_path);
}
g_strfreev (applications);