aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2010-01-08 15:35:23 -0600
committerTed Gould <ted@gould.cx>2010-01-08 15:35:23 -0600
commit98237f0789319b6133411618d505a2c945e669a5 (patch)
treeab1abf5193e2cddec2e6df706506d5043919e133
parenta5753822cc80f3f579aa61801b54134b3baa8076 (diff)
parentbb71fc2d4c0b555f23940b8c9d4f6973307cbd20 (diff)
downloadayatana-indicator-application-98237f0789319b6133411618d505a2c945e669a5.tar.gz
ayatana-indicator-application-98237f0789319b6133411618d505a2c945e669a5.tar.bz2
ayatana-indicator-application-98237f0789319b6133411618d505a2c945e669a5.zip
Supporting icons changing and status changing.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/application-service-appstore.c360
-rw-r--r--src/application-service-appstore.h7
-rw-r--r--src/application-service-marshal.list1
-rw-r--r--src/application-service.c2
-rw-r--r--src/application-service.xml4
-rw-r--r--src/dbus-properties-client.h139
-rw-r--r--src/indicator-application.c33
-rw-r--r--src/libappindicator/app-indicator.c10
9 files changed, 517 insertions, 40 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f101d12..d9b7963 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -101,7 +101,6 @@ libappindicator_la_LIBADD = \
DBUS_SPECS = \
application-service.xml \
- dbus-properties.xml \
notification-item.xml \
notification-watcher.xml
diff --git a/src/application-service-appstore.c b/src/application-service-appstore.c
index f76bbe2..fa1b9d2 100644
--- a/src/application-service-appstore.c
+++ b/src/application-service-appstore.c
@@ -43,6 +43,10 @@ static gboolean _application_service_server_get_applications (ApplicationService
#define NOTIFICATION_ITEM_PROP_ICON_PATH "IconThemePath"
#define NOTIFICATION_ITEM_PROP_MENU "Menu"
+#define NOTIFICATION_ITEM_SIG_NEW_ICON "NewIcon"
+#define NOTIFICATION_ITEM_SIG_NEW_AICON "NewAttentionIcon"
+#define NOTIFICATION_ITEM_SIG_NEW_STATUS "NewStatus"
+
/* Private Stuff */
typedef struct _ApplicationServiceAppstorePrivate ApplicationServiceAppstorePrivate;
struct _ApplicationServiceAppstorePrivate {
@@ -50,6 +54,17 @@ struct _ApplicationServiceAppstorePrivate {
GList * applications;
};
+#define APP_STATUS_PASSIVE_STR "passive"
+#define APP_STATUS_ACTIVE_STR "active"
+#define APP_STATUS_ATTENTION_STR "attention"
+
+typedef enum _ApplicationStatus ApplicationStatus;
+enum _ApplicationStatus {
+ APP_STATUS_PASSIVE,
+ APP_STATUS_ACTIVE,
+ APP_STATUS_ATTENTION
+};
+
typedef struct _Application Application;
struct _Application {
gchar * dbus_name;
@@ -57,6 +72,13 @@ struct _Application {
ApplicationServiceAppstore * appstore; /* not ref'd */
DBusGProxy * dbus_proxy;
DBusGProxy * prop_proxy;
+ gboolean validated; /* Whether we've gotten all the parameters and they look good. */
+ ApplicationStatus status;
+ gchar * icon;
+ gchar * aicon;
+ gchar * menu;
+ gchar * icon_path;
+ gboolean currently_free;
};
#define APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(o) \
@@ -66,6 +88,7 @@ struct _Application {
enum {
APPLICATION_ADDED,
APPLICATION_REMOVED,
+ APPLICATION_ICON_CHANGED,
LAST_SIGNAL
};
@@ -76,6 +99,8 @@ static void application_service_appstore_class_init (ApplicationServiceAppstoreC
static void application_service_appstore_init (ApplicationServiceAppstore *self);
static void application_service_appstore_dispose (GObject *object);
static void application_service_appstore_finalize (GObject *object);
+static ApplicationStatus string_to_status(const gchar * status_string);
+static void apply_status (Application * app, ApplicationStatus status);
G_DEFINE_TYPE (ApplicationServiceAppstore, application_service_appstore, G_TYPE_OBJECT);
@@ -92,18 +117,24 @@ application_service_appstore_class_init (ApplicationServiceAppstoreClass *klass)
signals[APPLICATION_ADDED] = g_signal_new ("application-added",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ApplicationServiceAppstore, application_added),
+ G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_added),
NULL, NULL,
_application_service_marshal_VOID__STRING_INT_STRING_STRING_STRING,
G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE);
signals[APPLICATION_REMOVED] = g_signal_new ("application-removed",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ApplicationServiceAppstore, application_removed),
+ G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_removed),
NULL, NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_NONE);
-
+ signals[APPLICATION_ICON_CHANGED] = g_signal_new ("application-icon-changed",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_icon_changed),
+ NULL, NULL,
+ _application_service_marshal_VOID__INT_STRING,
+ G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING, G_TYPE_NONE);
dbus_g_object_type_install_info(APPLICATION_SERVICE_APPSTORE_TYPE,
&dbus_glib__application_service_server_object_info);
@@ -156,6 +187,9 @@ application_service_appstore_finalize (GObject *object)
return;
}
+/* Return from getting the properties from the item. We're looking at those
+ and making sure we have everythign that we need. If we do, then we'll
+ move on up to sending this onto the indicator. */
static void
get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
{
@@ -167,45 +201,77 @@ get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * err
Application * app = (Application *)data;
if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU) == NULL ||
+ g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS) == NULL ||
g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME) == NULL) {
g_warning("Notification Item on object %s of %s doesn't have enough properties.", app->dbus_object, app->dbus_name);
g_free(app); // Need to do more than this, but it gives the idea of the flow we're going for.
return;
}
- ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(app->appstore);
- priv->applications = g_list_prepend(priv->applications, app);
-
- /* TODO: We need to have the position determined better. This
- would involve looking at the name and category and sorting
- it with the other entries. */
+ app->validated = TRUE;
+
+ app->icon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME));
+ app->menu = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU));
+ if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_AICON_NAME) != NULL) {
+ app->aicon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME));
+ }
- const gchar * icon_path = NULL;
gpointer icon_path_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_PATH);
if (icon_path_data != NULL) {
- icon_path = g_value_get_string((GValue *)icon_path_data);
+ app->icon_path = g_value_dup_string((GValue *)icon_path_data);
} else {
- icon_path = "";
+ app->icon_path = g_strdup("");
}
- g_signal_emit(G_OBJECT(app->appstore),
- signals[APPLICATION_ADDED], 0,
- g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME)),
- 0, /* Position */
- app->dbus_name,
- g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU)),
- icon_path,
- TRUE);
+ apply_status(app, string_to_status(g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS))));
return;
}
+/* Simple translation function -- could be optimized */
+static ApplicationStatus
+string_to_status(const gchar * status_string)
+{
+ if (!g_strcmp0(status_string, APP_STATUS_ACTIVE_STR))
+ return APP_STATUS_ACTIVE;
+ if (!g_strcmp0(status_string, APP_STATUS_ATTENTION_STR))
+ return APP_STATUS_ATTENTION;
+ return APP_STATUS_PASSIVE;
+}
+
+/* A small helper function to get the position of an application
+ in the app list. */
+static gint
+get_position (Application * app) {
+ ApplicationServiceAppstore * appstore = app->appstore;
+ ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(appstore);
+
+ GList * applistitem = g_list_find(priv->applications, app);
+ if (applistitem == NULL) {
+ return -1;
+ }
+
+ return g_list_position(priv->applications, applistitem);
+}
+
/* A simple global function for dealing with freeing the information
in an Application structure */
static void
application_free (Application * app)
{
if (app == NULL) return;
+
+ /* Handle the case where this could be called by unref'ing one of
+ the proxy objects. */
+ if (app->currently_free) return;
+ app->currently_free = TRUE;
+
+ if (app->dbus_proxy) {
+ g_object_unref(app->dbus_proxy);
+ }
+ if (app->prop_proxy) {
+ g_object_unref(app->prop_proxy);
+ }
if (app->dbus_name != NULL) {
g_free(app->dbus_name);
@@ -213,6 +279,18 @@ application_free (Application * app)
if (app->dbus_object != NULL) {
g_free(app->dbus_object);
}
+ if (app->icon != NULL) {
+ g_free(app->icon);
+ }
+ if (app->aicon != NULL) {
+ g_free(app->aicon);
+ }
+ if (app->menu != NULL) {
+ g_free(app->menu);
+ }
+ if (app->icon_path != NULL) {
+ g_free(app->icon_path);
+ }
g_free(app);
return;
@@ -224,24 +302,198 @@ static void
application_removed_cb (DBusGProxy * proxy, gpointer userdata)
{
Application * app = (Application *)userdata;
+
+ /* Remove from the panel */
+ apply_status(app, APP_STATUS_PASSIVE);
+
+ /* Destroy the data */
+ application_free(app);
+ return;
+}
+
+/* Change the status of the application. If we're going passive
+ it removes it from the panel. If we're coming online, then
+ it add it to the panel. Otherwise it changes the icon. */
+static void
+apply_status (Application * app, ApplicationStatus status)
+{
+ if (app->status == status) {
+ return;
+ }
+ g_debug("Changing app status to: %d", status);
+
ApplicationServiceAppstore * appstore = app->appstore;
ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(appstore);
- GList * applistitem = g_list_find(priv->applications, app);
- if (applistitem == NULL) {
- g_warning("Removing an application that isn't in the application list?");
+ /* This means we're going off line */
+ if (status == APP_STATUS_PASSIVE) {
+ gint position = get_position(app);
+ if (position == -1) return;
+
+ g_signal_emit(G_OBJECT(appstore),
+ signals[APPLICATION_REMOVED], 0,
+ position, TRUE);
+
+ priv->applications = g_list_remove(priv->applications, app);
+ } else {
+ /* Figure out which icon we should be using */
+ gchar * newicon = app->icon;
+ if (status == APP_STATUS_ATTENTION && app->aicon != NULL) {
+ newicon = app->aicon;
+ }
+
+ /* Determine whether we're already shown or not */
+ if (app->status == APP_STATUS_PASSIVE) {
+ /* Put on panel */
+ priv->applications = g_list_prepend(priv->applications, app);
+
+ /* TODO: We need to have the position determined better. This
+ would involve looking at the name and category and sorting
+ it with the other entries. */
+
+ g_signal_emit(G_OBJECT(app->appstore),
+ signals[APPLICATION_ADDED], 0,
+ newicon,
+ 0, /* Position */
+ app->dbus_name,
+ app->menu,
+ app->icon_path,
+ TRUE);
+ } else {
+ /* Icon update */
+ gint position = get_position(app);
+ if (position == -1) return;
+
+ g_signal_emit(G_OBJECT(appstore),
+ signals[APPLICATION_ICON_CHANGED], 0,
+ position, newicon, TRUE);
+ }
+ }
+
+ app->status = status;
+
+ return;
+}
+
+/* Gets the data back on an updated icon signal. Hopefully
+ a new fun icon. */
+static void
+new_icon_cb (DBusGProxy * proxy, GValue value, GError * error, gpointer userdata)
+{
+ /* Check for errors */
+ if (error != NULL) {
+ g_warning("Unable to get updated icon name: %s", error->message);
return;
}
- gint position = g_list_position(priv->applications, applistitem);
+ /* Grab the icon and make sure we have one */
+ const gchar * newicon = g_value_get_string(&value);
+ if (newicon == NULL) {
+ g_warning("Bad new icon :(");
+ return;
+ }
- g_signal_emit(G_OBJECT(appstore),
- signals[APPLICATION_REMOVED], 0,
- position, TRUE);
+ Application * app = (Application *) userdata;
- priv->applications = g_list_remove(priv->applications, app);
+ if (g_strcmp0(newicon, app->icon)) {
+ /* If the new icon is actually a new icon */
+ if (app->icon != NULL) g_free(app->icon);
+ app->icon = g_strdup(newicon);
+
+ if (app->status == APP_STATUS_ACTIVE) {
+ gint position = get_position(app);
+ if (position == -1) return;
+
+ g_signal_emit(G_OBJECT(app->appstore),
+ signals[APPLICATION_ICON_CHANGED], 0,
+ position, newicon, TRUE);
+ }
+ }
+
+ return;
+}
+
+/* Gets the data back on an updated aicon signal. Hopefully
+ a new fun icon. */
+static void
+new_aicon_cb (DBusGProxy * proxy, GValue value, GError * error, gpointer userdata)
+{
+ /* Check for errors */
+ if (error != NULL) {
+ g_warning("Unable to get updated icon name: %s", error->message);
+ return;
+ }
+
+ /* Grab the icon and make sure we have one */
+ const gchar * newicon = g_value_get_string(&value);
+ if (newicon == NULL) {
+ g_warning("Bad new icon :(");
+ return;
+ }
+
+ Application * app = (Application *) userdata;
+
+ if (g_strcmp0(newicon, app->aicon)) {
+ /* If the new icon is actually a new icon */
+ if (app->aicon != NULL) g_free(app->aicon);
+ app->aicon = g_strdup(newicon);
+
+ if (app->status == APP_STATUS_ATTENTION) {
+ gint position = get_position(app);
+ if (position == -1) return;
+
+ g_signal_emit(G_OBJECT(app->appstore),
+ signals[APPLICATION_ICON_CHANGED], 0,
+ position, newicon, TRUE);
+ }
+ }
+
+ return;
+}
+
+/* Called when the Notification Item signals that it
+ has a new icon. */
+static void
+new_icon (DBusGProxy * proxy, gpointer data)
+{
+ Application * app = (Application *)data;
+ if (!app->validated) return;
+
+ org_freedesktop_DBus_Properties_get_async(app->prop_proxy,
+ NOTIFICATION_ITEM_DBUS_IFACE,
+ NOTIFICATION_ITEM_PROP_ICON_NAME,
+ new_icon_cb,
+ app);
+ return;
+}
+
+/* Called when the Notification Item signals that it
+ has a new attention icon. */
+static void
+new_aicon (DBusGProxy * proxy, gpointer data)
+{
+ Application * app = (Application *)data;
+ if (!app->validated) return;
+
+ org_freedesktop_DBus_Properties_get_async(app->prop_proxy,
+ NOTIFICATION_ITEM_DBUS_IFACE,
+ NOTIFICATION_ITEM_PROP_AICON_NAME,
+ new_aicon_cb,
+ app);
+
+ return;
+}
+
+/* Called when the Notification Item signals that it
+ has a new status. */
+static void
+new_status (DBusGProxy * proxy, const gchar * status, gpointer data)
+{
+ Application * app = (Application *)data;
+ if (!app->validated) return;
+
+ apply_status(app, string_to_status(status));
- application_free(app);
return;
}
@@ -261,11 +513,18 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst
/* Build the application entry. This will be carried
along until we're sure we've got everything. */
- Application * app = g_new(Application, 1);
+ Application * app = g_new0(Application, 1);
+ app->validated = FALSE;
app->dbus_name = g_strdup(dbus_name);
app->dbus_object = g_strdup(dbus_object);
app->appstore = appstore;
+ app->status = APP_STATUS_PASSIVE;
+ app->icon = NULL;
+ app->aicon = NULL;
+ app->menu = NULL;
+ app->icon_path = NULL;
+ app->currently_free = FALSE;
/* Get the DBus proxy for the NotificationItem interface */
GError * error = NULL;
@@ -300,6 +559,34 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst
return;
}
+ /* Connect to signals */
+ dbus_g_proxy_add_signal(app->dbus_proxy,
+ NOTIFICATION_ITEM_SIG_NEW_ICON,
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(app->dbus_proxy,
+ NOTIFICATION_ITEM_SIG_NEW_AICON,
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(app->dbus_proxy,
+ NOTIFICATION_ITEM_SIG_NEW_STATUS,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(app->dbus_proxy,
+ NOTIFICATION_ITEM_SIG_NEW_ICON,
+ G_CALLBACK(new_icon),
+ app,
+ NULL);
+ dbus_g_proxy_connect_signal(app->dbus_proxy,
+ NOTIFICATION_ITEM_SIG_NEW_AICON,
+ G_CALLBACK(new_aicon),
+ app,
+ NULL);
+ dbus_g_proxy_connect_signal(app->dbus_proxy,
+ NOTIFICATION_ITEM_SIG_NEW_STATUS,
+ G_CALLBACK(new_status),
+ app,
+ NULL);
+
/* Get all the propertiees */
org_freedesktop_DBus_Properties_get_all_async(app->prop_proxy,
NOTIFICATION_ITEM_DBUS_IFACE,
@@ -311,6 +598,8 @@ application_service_appstore_application_add (ApplicationServiceAppstore * appst
return;
}
+/* Removes an application. Currently only works for the apps
+ that are shown. /TODO Need to fix that. */
void
application_service_appstore_application_remove (ApplicationServiceAppstore * appstore, const gchar * dbus_name, const gchar * dbus_object)
{
@@ -318,6 +607,17 @@ application_service_appstore_application_remove (ApplicationServiceAppstore * ap
g_return_if_fail(dbus_name != NULL && dbus_name[0] != '\0');
g_return_if_fail(dbus_object != NULL && dbus_object[0] != '\0');
+ ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(appstore);
+ GList * listpntr;
+
+ for (listpntr = priv->applications; listpntr != NULL; listpntr = g_list_next(listpntr)) {
+ Application * app = (Application *)listpntr->data;
+
+ if (!g_strcmp0(app->dbus_name, dbus_name) && !g_strcmp0(app->dbus_object, dbus_object)) {
+ application_removed_cb(NULL, app);
+ break; /* NOTE: Must break as the list will become inconsistent */
+ }
+ }
return;
}
diff --git a/src/application-service-appstore.h b/src/application-service-appstore.h
index edf1a37..6bd7a01 100644
--- a/src/application-service-appstore.h
+++ b/src/application-service-appstore.h
@@ -40,13 +40,14 @@ typedef struct _ApplicationServiceAppstoreClass ApplicationServiceAppstoreClass;
struct _ApplicationServiceAppstoreClass {
GObjectClass parent_class;
+
+ void (*application_added) (ApplicationServiceAppstore * appstore, gchar *, gint, gchar *, gchar *, gpointer);
+ void (*application_removed) (ApplicationServiceAppstore * appstore, gint, gpointer);
+ void (*application_icon_changed)(ApplicationServiceAppstore * appstore, gint, const gchar *, gpointer);
};
struct _ApplicationServiceAppstore {
GObject parent;
-
- void (*application_added) (ApplicationServiceAppstore * appstore, gchar *, gint, gchar *, gchar *, gpointer);
- void (*application_removed) (ApplicationServiceAppstore * appstore, gint, gpointer);
};
GType application_service_appstore_get_type (void);
diff --git a/src/application-service-marshal.list b/src/application-service-marshal.list
index 6cfbada..4ac8398 100644
--- a/src/application-service-marshal.list
+++ b/src/application-service-marshal.list
@@ -17,3 +17,4 @@
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
VOID: STRING, INT, STRING, STRING, STRING
+VOID: INT, STRING
diff --git a/src/application-service.c b/src/application-service.c
index 45295a1..351e9aa 100644
--- a/src/application-service.c
+++ b/src/application-service.c
@@ -57,7 +57,7 @@ main (int argc, char ** argv)
/* Bring us up as a basic indicator service */
service = indicator_service_new(INDICATOR_APPLICATION_DBUS_ADDR);
- g_signal_connect(G_OBJECT(service), "disconnected", G_CALLBACK(service_disconnected), NULL);
+ g_signal_connect(G_OBJECT(service), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_disconnected), NULL);
/* Building our app store */
appstore = APPLICATION_SERVICE_APPSTORE(g_object_new(APPLICATION_SERVICE_APPSTORE_TYPE, NULL));
diff --git a/src/application-service.xml b/src/application-service.xml
index d354943..d74aaa9 100644
--- a/src/application-service.xml
+++ b/src/application-service.xml
@@ -40,6 +40,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
<signal name="ApplicationRemoved">
<arg type="i" name="position" direction="out" />
</signal>
+ <signal name="ApplicationIconChanged">
+ <arg type="i" name="position" direction="out" />
+ <arg type="s" name="icon_name" direction="out" />
+ </signal>
</interface>
</node>
diff --git a/src/dbus-properties-client.h b/src/dbus-properties-client.h
new file mode 100644
index 0000000..dc9f299
--- /dev/null
+++ b/src/dbus-properties-client.h
@@ -0,0 +1,139 @@
+/* Generated by dbus-binding-tool; do not edit! */
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#ifndef _DBUS_GLIB_ASYNC_DATA_FREE
+#define _DBUS_GLIB_ASYNC_DATA_FREE
+static
+#ifdef G_HAVE_INLINE
+inline
+#endif
+void
+_dbus_glib_async_data_free (gpointer stuff)
+{
+ g_slice_free (DBusGAsyncData, stuff);
+}
+#endif
+
+#ifndef DBUS_GLIB_CLIENT_WRAPPERS_org_freedesktop_DBus_Properties
+#define DBUS_GLIB_CLIENT_WRAPPERS_org_freedesktop_DBus_Properties
+
+static
+#ifdef G_HAVE_INLINE
+inline
+#endif
+gboolean
+org_freedesktop_DBus_Properties_get (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, GValue* OUT_Value, GError **error)
+
+{
+ return dbus_g_proxy_call (proxy, "Get", error, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_INVALID, G_TYPE_VALUE, OUT_Value, G_TYPE_INVALID);
+}
+
+typedef void (*org_freedesktop_DBus_Properties_get_reply) (DBusGProxy *proxy, GValue OUT_Value, GError *error, gpointer userdata);
+
+static void
+org_freedesktop_DBus_Properties_get_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
+{
+ DBusGAsyncData *data = (DBusGAsyncData*) user_data;
+ GError *error = NULL;
+ GValue OUT_Value = {0};
+ dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_VALUE, &OUT_Value, G_TYPE_INVALID);
+ (*(org_freedesktop_DBus_Properties_get_reply)data->cb) (proxy, OUT_Value, error, data->userdata);
+ return;
+}
+
+static
+#ifdef G_HAVE_INLINE
+inline
+#endif
+DBusGProxyCall*
+org_freedesktop_DBus_Properties_get_async (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, org_freedesktop_DBus_Properties_get_reply callback, gpointer userdata)
+
+{
+ DBusGAsyncData *stuff;
+ stuff = g_slice_new (DBusGAsyncData);
+ stuff->cb = G_CALLBACK (callback);
+ stuff->userdata = userdata;
+ return dbus_g_proxy_begin_call (proxy, "Get", org_freedesktop_DBus_Properties_get_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_INVALID);
+}
+static
+#ifdef G_HAVE_INLINE
+inline
+#endif
+gboolean
+org_freedesktop_DBus_Properties_set (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, const GValue* IN_Value, GError **error)
+
+{
+ return dbus_g_proxy_call (proxy, "Set", error, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_VALUE, IN_Value, G_TYPE_INVALID, G_TYPE_INVALID);
+}
+
+typedef void (*org_freedesktop_DBus_Properties_set_reply) (DBusGProxy *proxy, GError *error, gpointer userdata);
+
+static void
+org_freedesktop_DBus_Properties_set_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
+{
+ DBusGAsyncData *data = (DBusGAsyncData*) user_data;
+ GError *error = NULL;
+ dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID);
+ (*(org_freedesktop_DBus_Properties_set_reply)data->cb) (proxy, error, data->userdata);
+ return;
+}
+
+static
+#ifdef G_HAVE_INLINE
+inline
+#endif
+DBusGProxyCall*
+org_freedesktop_DBus_Properties_set_async (DBusGProxy *proxy, const char * IN_Interface_Name, const char * IN_Property_Name, const GValue* IN_Value, org_freedesktop_DBus_Properties_set_reply callback, gpointer userdata)
+
+{
+ DBusGAsyncData *stuff;
+ stuff = g_slice_new (DBusGAsyncData);
+ stuff->cb = G_CALLBACK (callback);
+ stuff->userdata = userdata;
+ return dbus_g_proxy_begin_call (proxy, "Set", org_freedesktop_DBus_Properties_set_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_STRING, IN_Interface_Name, G_TYPE_STRING, IN_Property_Name, G_TYPE_VALUE, IN_Value, G_TYPE_INVALID);
+}
+static
+#ifdef G_HAVE_INLINE
+inline
+#endif
+gboolean
+org_freedesktop_DBus_Properties_get_all (DBusGProxy *proxy, const char * IN_Interface_Name, GHashTable** OUT_Properties, GError **error)
+
+{
+ return dbus_g_proxy_call (proxy, "GetAll", error, G_TYPE_STRING, IN_Interface_Name, G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), OUT_Properties, G_TYPE_INVALID);
+}
+
+typedef void (*org_freedesktop_DBus_Properties_get_all_reply) (DBusGProxy *proxy, GHashTable *OUT_Properties, GError *error, gpointer userdata);
+
+static void
+org_freedesktop_DBus_Properties_get_all_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
+{
+ DBusGAsyncData *data = (DBusGAsyncData*) user_data;
+ GError *error = NULL;
+ GHashTable* OUT_Properties;
+ dbus_g_proxy_end_call (proxy, call, &error, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &OUT_Properties, G_TYPE_INVALID);
+ (*(org_freedesktop_DBus_Properties_get_all_reply)data->cb) (proxy, OUT_Properties, error, data->userdata);
+ return;
+}
+
+static
+#ifdef G_HAVE_INLINE
+inline
+#endif
+DBusGProxyCall*
+org_freedesktop_DBus_Properties_get_all_async (DBusGProxy *proxy, const char * IN_Interface_Name, org_freedesktop_DBus_Properties_get_all_reply callback, gpointer userdata)
+
+{
+ DBusGAsyncData *stuff;
+ stuff = g_slice_new (DBusGAsyncData);
+ stuff->cb = G_CALLBACK (callback);
+ stuff->userdata = userdata;
+ return dbus_g_proxy_begin_call (proxy, "GetAll", org_freedesktop_DBus_Properties_get_all_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_STRING, IN_Interface_Name, G_TYPE_INVALID);
+}
+#endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_org_freedesktop_DBus_Properties */
+
+G_END_DECLS
diff --git a/src/indicator-application.c b/src/indicator-application.c
index fbfbd40..c330645 100644
--- a/src/indicator-application.c
+++ b/src/indicator-application.c
@@ -94,6 +94,7 @@ static GList * get_entries (IndicatorObject * io);
static void connected (IndicatorServiceManager * sm, gboolean connected, IndicatorApplication * application);
static void application_added (DBusGProxy * proxy, const gchar * iconname, gint position, const gchar * dbusaddress, const gchar * dbusobject, const gchar * icon_path, IndicatorApplication * application);
static void application_removed (DBusGProxy * proxy, gint position , IndicatorApplication * application);
+static void application_icon_changed (DBusGProxy * proxy, gint position, const gchar * iconname, IndicatorApplication * application);
static void get_applications (DBusGProxy *proxy, GPtrArray *OUT_applications, GError *error, gpointer userdata);
G_DEFINE_TYPE (IndicatorApplication, indicator_application, INDICATOR_OBJECT_TYPE);
@@ -120,6 +121,11 @@ indicator_application_class_init (IndicatorApplicationClass *klass)
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_INVALID);
+ dbus_g_object_register_marshaller(_application_service_marshal_VOID__INT_STRING,
+ G_TYPE_NONE,
+ G_TYPE_INT,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
return;
}
@@ -219,6 +225,11 @@ connected (IndicatorServiceManager * sm, gboolean connected, IndicatorApplicatio
"ApplicationRemoved",
G_TYPE_INT,
G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(priv->service_proxy,
+ "ApplicationIconChanged",
+ G_TYPE_INT,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
/* Connect to them */
g_debug("Connect to them.");
@@ -232,6 +243,11 @@ connected (IndicatorServiceManager * sm, gboolean connected, IndicatorApplicatio
G_CALLBACK(application_removed),
application,
NULL /* Disconnection Signal */);
+ dbus_g_proxy_connect_signal(priv->service_proxy,
+ "ApplicationIconChanged",
+ G_CALLBACK(application_icon_changed),
+ application,
+ NULL /* Disconnection Signal */);
/* Query it for existing applications */
g_debug("Request current apps");
@@ -330,6 +346,23 @@ application_removed (DBusGProxy * proxy, gint position, IndicatorApplication * a
return;
}
+/* The callback for the signal that the icon for an application
+ has changed. */
+static void
+application_icon_changed (DBusGProxy * proxy, gint position, const gchar * iconname, IndicatorApplication * application)
+{
+ IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
+ ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
+
+ if (app == NULL) {
+ g_warning("Unable to find application at position: %d", position);
+ return;
+ }
+
+ gtk_image_set_from_icon_name(app->entry.image, iconname, GTK_ICON_SIZE_MENU);
+ return;
+}
+
/* This repsonds to the list of applications that the service
has and calls application_added on each one of them. */
static void
diff --git a/src/libappindicator/app-indicator.c b/src/libappindicator/app-indicator.c
index 9a2e2a1..5868a4d 100644
--- a/src/libappindicator/app-indicator.c
+++ b/src/libappindicator/app-indicator.c
@@ -698,14 +698,14 @@ app_indicator_set_icon (AppIndicator *self, const gchar *icon_name)
g_return_if_fail (IS_APP_INDICATOR (self));
g_return_if_fail (icon_name != NULL);
- if (g_strcmp0 (self->priv->attention_icon_name, icon_name) != 0)
+ if (g_strcmp0 (self->priv->icon_name, icon_name) != 0)
{
- if (self->priv->attention_icon_name)
- g_free (self->priv->attention_icon_name);
+ if (self->priv->icon_name)
+ g_free (self->priv->icon_name);
- self->priv->attention_icon_name = g_strdup (icon_name);
+ self->priv->icon_name = g_strdup (icon_name);
- g_signal_emit (self, signals[NEW_ATTENTION_ICON], 0, TRUE);
+ g_signal_emit (self, signals[NEW_ICON], 0, TRUE);
}
}