From 21f3cac4cb191430abf89b7cebd0093952c827b0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sat, 2 Jun 2012 16:44:47 +0200 Subject: Listen to actions exported by applications --- src/app-section.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ src/app-section.h | 5 ++++ src/messages-service-dbus.c | 4 +-- src/messages-service.c | 57 +++++++++++++++++++++++++------------ 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); -- cgit v1.2.3