aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Riddell <jriddell@canonical.com>2009-08-05 00:20:06 +0100
committerJonathan Riddell <jriddell@canonical.com>2009-08-05 00:20:06 +0100
commitda961bf7ff575e04fcff8c7da1a6d551510898f5 (patch)
tree5923df29689fb2326c897ef1d90b28982148d3b8
parent9e66afc1bb6adc0726ee6f1bda22f18df0b69acd (diff)
parentd20d4bf298defb4c60e76b3e463b352f276a3b8e (diff)
downloadayatana-indicator-messages-da961bf7ff575e04fcff8c7da1a6d551510898f5.tar.gz
ayatana-indicator-messages-da961bf7ff575e04fcff8c7da1a6d551510898f5.tar.bz2
ayatana-indicator-messages-da961bf7ff575e04fcff8c7da1a6d551510898f5.zip
merge current package for upload, https://code.edge.launchpad.net/~indicator-applet-developers/indicator-applet/messages-packaging/+merge/9670
-rw-r--r--.bzrignore3
-rwxr-xr-xautogen.sh2
-rw-r--r--configure.ac27
-rw-r--r--data/Makefile.am3
-rw-r--r--data/indicator-messages.service.in3
-rw-r--r--debian/changelog59
-rw-r--r--debian/control6
-rwxr-xr-xdebian/rules4
-rw-r--r--src/Makefile.am10
-rw-r--r--src/app-menu-item.c47
-rw-r--r--src/app-menu-item.h5
-rw-r--r--src/dbus-data.h8
-rw-r--r--src/im-menu-item.c78
-rw-r--r--src/im-menu-item.h5
-rw-r--r--src/indicator-messages.c480
-rw-r--r--src/indicator-service.c504
-rw-r--r--test/indicator-messages-service-activate.build.sh3
-rw-r--r--test/indicator-messages-service-activate.c53
18 files changed, 754 insertions, 546 deletions
diff --git a/.bzrignore b/.bzrignore
index 3bdb145..42bdaa3 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -16,3 +16,6 @@ debian/stamp-autotools-files
debian/stamp-makefile-build
libmessaging_la-im-menu-item.lo
src/libmessaging_la-app-menu-item.lo
+data/indicator-messages.service
+indicator-messages-service
+indicator-messages-service-activate
diff --git a/autogen.sh b/autogen.sh
index f0cc344..1abf3a7 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-PKG_NAME="indicator-applet"
+PKG_NAME="indicator-messages"
which gnome-autogen.sh || {
echo "You need gnome-common from GNOME SVN"
diff --git a/configure.ac b/configure.ac
index 9363693..9093512 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ AC_INIT(src/indicator-messages.c)
AC_PREREQ(2.53)
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(indicator-messages, 0.1.6)
+AM_INIT_AUTOMAKE(indicator-messages, 0.2.0dev)
AM_MAINTAINER_MODE
@@ -24,15 +24,34 @@ AC_CONFIG_MACRO_DIR([m4])
GTK_REQUIRED_VERSION=2.12
GIO_UNIX_REQUIRED_VERSION=2.18
PANEL_REQUIRED_VERSION=2.0.0
-INDICATE_REQUIRED_VERSION=0.1.5
+INDICATE_REQUIRED_VERSION=0.2.0
+INDICATOR_REQUIRED_VERSION=0.2.0
+DBUSMENUGTK_REQUIRED_VERSION=0.0.0
PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION
gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION
- indicate >= $INDICATE_REQUIRED_VERSION)
+ indicator >= $INDICATOR_REQUIRED_VERSION
+ indicate >= $INDICATE_REQUIRED_VERSION
+ indicate-gtk >= $INDICATE_REQUIRED_VERSION
+ dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION)
AC_SUBST(APPLET_CFLAGS)
AC_SUBST(APPLET_LIBS)
###########################
+# Indicator Info
+###########################
+
+INDICATORDIR=`$PKG_CONFIG --variable=indicatordir indicator`
+AC_SUBST(INDICATORDIR)
+
+###########################
+# DBus Service Info
+###########################
+
+DBUSSERVICEDIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`
+AC_SUBST(DBUSSERVICEDIR)
+
+###########################
# Files
###########################
@@ -40,6 +59,7 @@ AC_OUTPUT([
Makefile
src/Makefile
data/Makefile
+data/indicator-messages.service
data/icons/Makefile
data/icons/16x16/Makefile
data/icons/16x16/status/Makefile
@@ -64,4 +84,5 @@ AC_MSG_NOTICE([
Messaging Indicator Configuration:
Prefix: $prefix
+ Indicator Dir: $INDICATORDIR
])
diff --git a/data/Makefile.am b/data/Makefile.am
index 61a1a63..6177c6d 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -1 +1,4 @@
SUBDIRS = icons
+
+dbus_servicesdir = $(DBUSSERVICEDIR)
+dbus_services_DATA = indicator-messages.service
diff --git a/data/indicator-messages.service.in b/data/indicator-messages.service.in
new file mode 100644
index 0000000..908079a
--- /dev/null
+++ b/data/indicator-messages.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=com.ubuntu.indicator.messages
+Exec=@prefix@/bin/indicator-messages-service
diff --git a/debian/changelog b/debian/changelog
index 4a16997..3ca4fff 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,62 @@
+indicator-messages (0.2.0~bzr121-0ubuntu1~ppa4) karmic; urgency=low
+
+ * debian/control: Adding in a build dep on libindicate-gtk-dev
+
+ -- Ted Gould <ted@ubuntu.com> Tue, 04 Aug 2009 17:54:44 +0100
+
+indicator-messages (0.2.0~bzr121-0ubuntu1~ppa3) karmic; urgency=low
+
+ * Changes for the changing libindicate stuff.
+
+ -- Ted Gould <ted@ubuntu.com> Tue, 04 Aug 2009 17:46:17 +0100
+
+indicator-messages (0.2.0~bzr121-0ubuntu1~ppa2) karmic; urgency=low
+
+ * Forgot to run ./autogen.sh
+
+ -- Ted Gould <ted@ubuntu.com> Tue, 04 Aug 2009 17:38:41 +0100
+
+indicator-messages (0.2.0~bzr121-0ubuntu1~ppa1) karmic; urgency=low
+
+ * Merge in the dbusmenu changes from the dbusmenu branch
+ * debian/control: Adding in a build dependency on libdbusmenu-glib and
+ libdbusmenu-gtk to catch up with the merge.
+
+ -- Ted Gould <ted@ubuntu.com> Tue, 04 Aug 2009 12:50:10 +0100
+
+indicator-messages (0.2.0~bzr120-0ubuntu1) jaunty; urgency=low
+
+ * Fix to track the timer. (LP: #365187)
+
+ -- Ted Gould <ted@ubuntu.com> Wed, 13 May 2009 09:56:20 -0500
+
+indicator-messages (0.2.0~bzr119-0ubuntu1) jaunty; urgency=low
+
+ * Upstream update
+
+ -- Ted Gould <ted@ubuntu.com> Wed, 22 Apr 2009 23:34:21 -0500
+
+indicator-messages (0.2.0~bzr116-0ubuntu3) jaunty; urgency=low
+
+ * debian/rules: Adding a rule to remove the .la/.a clutter
+
+ -- Ted Gould <ted@ubuntu.com> Wed, 22 Apr 2009 16:46:59 -0500
+
+indicator-messages (0.2.0~bzr116-0ubuntu2) jaunty; urgency=low
+
+ * debian/control: libindicator-dev to ~bzr301
+
+ -- Ted Gould <ted@ubuntu.com> Wed, 22 Apr 2009 15:58:45 -0500
+
+indicator-messages (0.2.0~bzr116-0ubuntu1) jaunty; urgency=low
+
+ * Upstream release
+ * Bug fixes
+ * Update API to new libindicator
+ * debian/control: Adding new dependency on libindicator-dev
+
+ -- Ted Gould <ted@ubuntu.com> Wed, 22 Apr 2009 15:45:21 -0500
+
indicator-messages (0.1.6-0ubuntu1) jaunty; urgency=low
* New upstream version
diff --git a/debian/control b/debian/control
index f403ed8..32b0ae9 100644
--- a/debian/control
+++ b/debian/control
@@ -9,7 +9,11 @@ Build-Depends: debhelper (>= 5.0),
gnome-doc-utils,
scrollkeeper,
intltool,
- libindicate-dev (>= 0.1.5)
+ libindicate-dev (>= 0.2.0~bzr298),
+ libindicate-gtk-dev (>= 0.2.0~bzr298),
+ libindicator-dev (>= 0.2.0~bzr301),
+ libdbusmenu-gtk-dev,
+ libdbusmenu-glib-dev
Standards-Version: 3.8.0
Homepage: https://launchpad.net/indicator-applet
Vcs-Bzr: http://bazaar.launchpad.net/~ubuntu-core-dev/indicator-applet/messages-ubuntu
diff --git a/debian/rules b/debian/rules
index 1c64b91..e813915 100755
--- a/debian/rules
+++ b/debian/rules
@@ -6,3 +6,7 @@ include /usr/share/cdbs/1/class/gnome.mk
DEB_CONFIGURE_EXTRA_FLAGS += --disable-scrollkeeper
LDFLAGS += -Wl,-z,defs -Wl,--as-needed
+binary-install/indicator-messages::
+ # remove .a/.la clutter
+ rm -f debian/$(cdbs_curpkg)/usr/lib/indicators/*/*.a
+ rm -f debian/$(cdbs_curpkg)/usr/lib/indicators/*/*.la
diff --git a/src/Makefile.am b/src/Makefile.am
index eb6ba12..74db2df 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,13 @@
-messaginglibdir = $(libdir)/indicators/1
+bin_PROGRAMS = indicator-messages-service
+
+messaginglibdir = $(INDICATORDIR)
messaginglib_LTLIBRARIES = libmessaging.la
libmessaging_la_SOURCES = indicator-messages.c im-menu-item.c im-menu-item.h app-menu-item.c app-menu-item.h
-libmessaging_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed
+libmessaging_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed -Werror
libmessaging_la_LIBADD = $(APPLET_LIBS)
libmessaging_la_LDFLAGS = -module -avoid-version
+
+indicator_messages_service_SOURCES = indicator-service.c im-menu-item.c im-menu-item.h app-menu-item.c app-menu-item.h
+indicator_messages_service_CFLAGS = $(APPLET_CFLAGS) -Wall -Wl,-Bsymbolic-functions -Wl,-z,defs -Wl,--as-needed -Werror
+indicator_messages_service_LDADD = $(APPLET_LIBS)
diff --git a/src/app-menu-item.c b/src/app-menu-item.c
index c769d47..f973e33 100644
--- a/src/app-menu-item.c
+++ b/src/app-menu-item.c
@@ -25,7 +25,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#include <glib/gi18n.h>
-#include <gtk/gtk.h>
#include <gio/gdesktopappinfo.h>
#include "app-menu-item.h"
@@ -48,8 +47,6 @@ struct _AppMenuItemPrivate
GAppInfo * appinfo;
guint unreadcount;
gboolean count_on_label;
-
- GtkWidget * name;
};
#define APP_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_MENU_ITEM_TYPE, AppMenuItemPrivate))
@@ -68,7 +65,7 @@ static void update_label (AppMenuItem * self);
-G_DEFINE_TYPE (AppMenuItem, app_menu_item, GTK_TYPE_MENU_ITEM);
+G_DEFINE_TYPE (AppMenuItem, app_menu_item, DBUSMENU_TYPE_MENUITEM);
static void
app_menu_item_class_init (AppMenuItemClass *klass)
@@ -106,7 +103,6 @@ app_menu_item_init (AppMenuItem *self)
priv->listener = NULL;
priv->server = NULL;
- priv->name = NULL;
priv->type = NULL;
priv->appinfo = NULL;
priv->unreadcount = 0;
@@ -119,6 +115,14 @@ app_menu_item_init (AppMenuItem *self)
static void
app_menu_item_dispose (GObject *object)
{
+ AppMenuItem * self = APP_MENU_ITEM(object);
+ AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
+
+ g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), G_CALLBACK(indicator_added_cb), self);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), G_CALLBACK(indicator_removed_cb), self);
+
+ g_object_unref(priv->listener);
+
G_OBJECT_CLASS (app_menu_item_parent_class)->dispose (object);
}
@@ -128,8 +132,13 @@ app_menu_item_finalize (GObject *object)
AppMenuItem * self = APP_MENU_ITEM(object);
AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
- g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), G_CALLBACK(indicator_added_cb), self);
- g_signal_handlers_disconnect_by_func(G_OBJECT(priv->listener), G_CALLBACK(indicator_removed_cb), self);
+ if (priv->type != NULL) {
+ g_free(priv->type);
+ }
+
+ if (priv->appinfo != NULL) {
+ g_object_unref(priv->appinfo);
+ }
G_OBJECT_CLASS (app_menu_item_parent_class)->finalize (object);
@@ -144,21 +153,17 @@ app_menu_item_new (IndicateListener * listener, IndicateListenerServer * server)
AppMenuItemPrivate * priv = APP_MENU_ITEM_GET_PRIVATE(self);
priv->listener = listener;
+ g_object_ref(G_OBJECT(listener));
priv->server = server;
+ /* Can not ref as not real GObject */
g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added_cb), self);
g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed_cb), self);
- priv->name = gtk_label_new(INDICATE_LISTENER_SERVER_DBUS_NAME(server));
- gtk_misc_set_alignment(GTK_MISC(priv->name), 0.0, 0.5);
- gtk_widget_show(GTK_WIDGET(priv->name));
-
- gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(priv->name));
-
indicate_listener_server_get_type(listener, server, type_cb, self);
indicate_listener_server_get_desktop(listener, server, desktop_cb, self);
- g_signal_connect(G_OBJECT(self), "activate", G_CALLBACK(activate_cb), NULL);
+ g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL);
indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_SERVER_DISPLAY);
indicate_listener_server_show_interest(listener, server, INDICATE_INTEREST_SERVER_SIGNAL);
@@ -174,8 +179,14 @@ type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * v
if (priv->type != NULL) {
g_free(priv->type);
+ priv->type = NULL;
}
+ if (value == NULL) {
+ g_warning("Type value is NULL, that shouldn't really happen");
+ return;
+ }
+
priv->type = g_strdup(value);
if (!(!g_strcmp0(priv->type, "message.instant") || !g_strcmp0(priv->type, "message.micro") || !g_strcmp0(priv->type, "message.im"))) {
@@ -200,11 +211,11 @@ update_label (AppMenuItem * self)
if (priv->count_on_label && !priv->unreadcount < 1) {
/* TRANSLATORS: This is the name of the program and the number of indicators. So it
would read something like "Mail Client (5)" */
- gchar * label = g_strdup_printf(_("%s (%d)"), g_app_info_get_name(priv->appinfo), priv->unreadcount);
- gtk_label_set_text(GTK_LABEL(priv->name), label);
+ gchar * label = g_strdup_printf(_("%s (%d)"), app_menu_item_get_name(self), priv->unreadcount);
+ dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), "label", label);
g_free(label);
} else {
- gtk_label_set_text(GTK_LABEL(priv->name), g_app_info_get_name(priv->appinfo));
+ dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), "label", app_menu_item_get_name(self));
}
return;
@@ -228,7 +239,7 @@ desktop_cb (IndicateListener * listener, IndicateListenerServer * server, gchar
g_return_if_fail(priv->appinfo != NULL);
update_label(self);
- g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, g_app_info_get_name(priv->appinfo), TRUE);
+ g_signal_emit(G_OBJECT(self), signals[NAME_CHANGED], 0, app_menu_item_get_name(self), TRUE);
return;
}
diff --git a/src/app-menu-item.h b/src/app-menu-item.h
index 1e1b5eb..dda4765 100644
--- a/src/app-menu-item.h
+++ b/src/app-menu-item.h
@@ -25,6 +25,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
#include <glib-object.h>
+#include <libdbusmenu-glib/menuitem.h>
#include <libindicate/listener.h>
G_BEGIN_DECLS
@@ -43,14 +44,14 @@ typedef struct _AppMenuItem AppMenuItem;
typedef struct _AppMenuItemClass AppMenuItemClass;
struct _AppMenuItemClass {
- GtkMenuItemClass parent_class;
+ DbusmenuMenuitemClass parent_class;
void (* count_changed) (guint count);
void (* name_changed) (gchar * name);
};
struct _AppMenuItem {
- GtkMenuItem parent;
+ DbusmenuMenuitem parent;
};
GType app_menu_item_get_type (void);
diff --git a/src/dbus-data.h b/src/dbus-data.h
new file mode 100644
index 0000000..4aeedf0
--- /dev/null
+++ b/src/dbus-data.h
@@ -0,0 +1,8 @@
+
+#ifndef __DBUS_DATA_H__
+#define __DBUS_DATA_H__ 1
+
+#define INDICATOR_MESSAGES_DBUS_NAME "com.ubuntu.indicator.messages"
+#define INDICATOR_MESSAGES_DBUS_OBJECT "/com/ubuntu/indicator/messages"
+
+#endif /* __DBUS_DATA_H__ */
diff --git a/src/im-menu-item.c b/src/im-menu-item.c
index 6e3a461..d35684e 100644
--- a/src/im-menu-item.c
+++ b/src/im-menu-item.c
@@ -24,7 +24,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#include <glib/gi18n.h>
-#include <gtk/gtk.h>
+#include <libindicate-gtk/indicator.h>
+#include <libindicate-gtk/listener.h>
#include "im-menu-item.h"
enum {
@@ -47,11 +48,6 @@ struct _ImMenuItemPrivate
gulong indicator_changed;
guint time_update_min;
-
- GtkHBox * hbox;
- GtkLabel * user;
- GtkLabel * time;
- GtkImage * icon;
};
#define IM_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IM_MENU_ITEM_TYPE, ImMenuItemPrivate))
@@ -88,13 +84,7 @@ static void indicator_modified_cb (IndicateListener * listener,
gchar * property,
ImMenuItem * self);
-
-static GtkSizeGroup * icon_group = NULL;
-static GtkSizeGroup * user_group = NULL;
-static GtkSizeGroup * time_group = NULL;
-
-
-G_DEFINE_TYPE (ImMenuItem, im_menu_item, GTK_TYPE_MENU_ITEM);
+G_DEFINE_TYPE (ImMenuItem, im_menu_item, DBUSMENU_TYPE_MENUITEM);
static void
im_menu_item_class_init (ImMenuItemClass *klass)
@@ -129,35 +119,6 @@ im_menu_item_init (ImMenuItem *self)
priv->seconds = 0;
- /* build widgets first */
- priv->icon = GTK_IMAGE(gtk_image_new());
- priv->user = GTK_LABEL(gtk_label_new(""));
- priv->time = GTK_LABEL(gtk_label_new(""));
-
- gtk_misc_set_alignment(GTK_MISC(priv->user), 0.0, 0.5);
- gtk_misc_set_alignment(GTK_MISC(priv->time), 0.0, 0.5);
-
- if (icon_group == NULL) {
- icon_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- }
- if (user_group == NULL) {
- user_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- }
- if (time_group == NULL) {
- time_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- }
- gtk_size_group_add_widget(icon_group, GTK_WIDGET(priv->icon));
- gtk_size_group_add_widget(user_group, GTK_WIDGET(priv->user));
- gtk_size_group_add_widget(time_group, GTK_WIDGET(priv->time));
-
- priv->hbox = GTK_HBOX(gtk_hbox_new(FALSE, 3));
- gtk_box_pack_start(GTK_BOX(priv->hbox), GTK_WIDGET(priv->icon), FALSE, TRUE, 3);
- gtk_box_pack_start(GTK_BOX(priv->hbox), GTK_WIDGET(priv->user), TRUE, TRUE, 3);
- gtk_box_pack_start(GTK_BOX(priv->hbox), GTK_WIDGET(priv->time), FALSE, TRUE, 3);
- gtk_widget_show(GTK_WIDGET(priv->hbox));
-
- gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(priv->hbox));
-
return;
}
@@ -188,19 +149,7 @@ im_menu_item_finalize (GObject *object)
static void
icon_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, GdkPixbuf * propertydata, gpointer data)
{
- ImMenuItem * self = IM_MENU_ITEM(data);
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- gint height, width;
- gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
-
- GdkPixbuf * scaled = gdk_pixbuf_scale_simple(propertydata, width, height, GDK_INTERP_BILINEAR);
- g_object_unref(propertydata);
-
- gtk_image_set_from_pixbuf(priv->icon, scaled);
- g_object_unref(scaled);
-
- gtk_widget_show(GTK_WIDGET(priv->icon));
+ /* dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), "icon", propertydata); */
return;
}
@@ -211,7 +160,7 @@ update_time (ImMenuItem * self)
ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
if (!priv->show_time) {
- gtk_label_set_label(priv->time, "");
+ dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), "right-column", "");
return;
}
@@ -242,9 +191,7 @@ update_time (ImMenuItem * self)
}
if (timestring != NULL) {
- gtk_label_set_label(priv->time, timestring);
- gtk_widget_show(GTK_WIDGET(priv->time));
-
+ dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), "right-column", "");
g_free(timestring);
}
@@ -283,7 +230,7 @@ time_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateL
update_time(self);
if (priv->time_update_min == 0) {
- g_timeout_add_seconds(60, time_update_cb, self);
+ priv->time_update_min = g_timeout_add_seconds(60, time_update_cb, self);
}
g_signal_emit(G_OBJECT(self), signals[TIME_CHANGED], 0, priv->seconds, TRUE);
@@ -306,13 +253,7 @@ sender_cb (IndicateListener * listener, IndicateListenerServer * server, Indicat
return;
}
- ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
-
- gtk_label_set_label(priv->user, propertydata);
- gtk_widget_show(GTK_WIDGET(priv->user));
-
- /* Once we have the user we'll show the menu item */
- gtk_widget_show(GTK_WIDGET(self));
+ dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), "label", propertydata);
return;
}
@@ -348,7 +289,6 @@ indicator_modified_cb (IndicateListener * listener, IndicateListenerServer * ser
ImMenuItem *
im_menu_item_new (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gboolean show_time)
{
- g_debug("Building a new IM Menu Item");
ImMenuItem * self = g_object_new(IM_MENU_ITEM_TYPE, NULL);
ImMenuItemPrivate * priv = IM_MENU_ITEM_GET_PRIVATE(self);
@@ -363,7 +303,7 @@ im_menu_item_new (IndicateListener * listener, IndicateListenerServer * server,
indicate_listener_get_property_time(listener, server, indicator, "time", time_cb, self);
indicate_listener_get_property_icon(listener, server, indicator, "icon", icon_cb, self);
- g_signal_connect(G_OBJECT(self), "activate", G_CALLBACK(activate_cb), NULL);
+ g_signal_connect(G_OBJECT(self), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), NULL);
priv->indicator_changed = g_signal_connect(G_OBJECT(listener), INDICATE_LISTENER_SIGNAL_INDICATOR_MODIFIED, G_CALLBACK(indicator_modified_cb), self);
return self;
diff --git a/src/im-menu-item.h b/src/im-menu-item.h
index f1f95ea..51414de 100644
--- a/src/im-menu-item.h
+++ b/src/im-menu-item.h
@@ -25,6 +25,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
#include <glib-object.h>
+#include <libdbusmenu-glib/menuitem.h>
#include <libindicate/listener.h>
G_BEGIN_DECLS
@@ -42,13 +43,13 @@ typedef struct _ImMenuItem ImMenuItem;
typedef struct _ImMenuItemClass ImMenuItemClass;
struct _ImMenuItemClass {
- GtkMenuItemClass parent_class;
+ DbusmenuMenuitemClass parent_class;
void (*time_changed) (glong seconds);
};
struct _ImMenuItem {
- GtkMenuItem parent;
+ DbusmenuMenuitem parent;
};
GType im_menu_item_get_type (void);
diff --git a/src/indicator-messages.c b/src/indicator-messages.c
index 3df1329..efb52b2 100644
--- a/src/indicator-messages.c
+++ b/src/indicator-messages.c
@@ -22,476 +22,60 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <string.h>
#include <gtk/gtk.h>
-#include <libindicate/listener.h>
+#include <libdbusmenu-gtk/menu.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
-#include "im-menu-item.h"
-#include "app-menu-item.h"
+#include <libindicator/indicator.h>
+INDICATOR_SET_VERSION
+INDICATOR_SET_NAME("messages")
-static IndicateListener * listener;
-static GList * serverList;
-static GtkWidget * main_image;
-static GtkWidget * main_menu;
+#include "dbus-data.h"
-static void server_count_changed (AppMenuItem * appitem, guint count, gpointer data);
-static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data);
-static void im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data);
-static void reconsile_list_and_menu (GList * serverlist, GtkMenuShell * menushell);
-static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data);
+static GtkWidget * main_image;
#define DESIGN_TEAM_SIZE design_team_size
static GtkIconSize design_team_size;
-typedef struct _serverList_t serverList_t;
-struct _serverList_t {
- IndicateListenerServer * server;
- AppMenuItem * menuitem;
- GList * imList;
-};
-
-static gint
-serverList_equal (gconstpointer a, gconstpointer b)
-{
- serverList_t * pa, * pb;
-
- pa = (serverList_t *)a;
- pb = (serverList_t *)b;
-
- const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
- const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
-
- return g_strcmp0(pas, pbs);
-}
-
-static gint
-serverList_sort (gconstpointer a, gconstpointer b)
-{
- serverList_t * pa, * pb;
-
- pa = (serverList_t *)a;
- pb = (serverList_t *)b;
-
- const gchar * pan = app_menu_item_get_name(pa->menuitem);
- const gchar * pbn = app_menu_item_get_name(pb->menuitem);
-
- return g_strcmp0(pan, pbn);
-}
-
-typedef struct _imList_t imList_t;
-struct _imList_t {
- IndicateListenerServer * server;
- IndicateListenerIndicator * indicator;
- GtkWidget * menuitem;
- gulong timechange_cb;
-};
-
-static gboolean
-imList_equal (gconstpointer a, gconstpointer b)
-{
- imList_t * pa, * pb;
-
- pa = (imList_t *)a;
- pb = (imList_t *)b;
-
- const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
- const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
-
- guint pai = INDICATE_LISTENER_INDICATOR_ID(pa->indicator);
- guint pbi = INDICATE_LISTENER_INDICATOR_ID(pb->indicator);
-
- g_debug("\tComparing (%s %d) to (%s %d)", pas, pai, pbs, pbi);
-
- return !((!g_strcmp0(pas, pbs)) && (pai == pbi));
-}
-
-static gint
-imList_sort (gconstpointer a, gconstpointer b)
-{
- imList_t * pa, * pb;
-
- pa = (imList_t *)a;
- pb = (imList_t *)b;
-
- return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem)));
-}
-
-static void
-server_added (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
-{
- g_debug("Server Added '%s' of type '%s'.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), type);
- if (type == NULL) {
- return;
- }
-
- if (type[0] == '\0') {
- return;
- }
-
- if (strncmp(type, "message", strlen("message"))) {
- g_debug("\tServer type '%s' is not a message based type.", type);
- return;
- }
-
- GtkMenuShell * menushell = GTK_MENU_SHELL(data);
- if (menushell == NULL) {
- g_error("\tData in callback is not a menushell");
- return;
- }
-
- AppMenuItem * menuitem = app_menu_item_new(listener, server);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, G_CALLBACK(server_count_changed), NULL);
- g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_NAME_CHANGED, G_CALLBACK(server_name_changed), menushell);
-
- serverList_t * sl_item = g_new0(serverList_t, 1);
- sl_item->server = server;
- sl_item->menuitem = menuitem;
- sl_item->imList = NULL;
-
- /* Incase we got an indicator first */
- GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal);
- if (alreadythere != NULL) {
- g_free(sl_item);
- sl_item = (serverList_t *)alreadythere->data;
- sl_item->menuitem = menuitem;
- serverList = g_list_sort(serverList, serverList_sort);
- } else {
- serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
- }
-
- gtk_menu_shell_prepend(menushell, GTK_WIDGET(menuitem));
- gtk_widget_show(GTK_WIDGET(menuitem));
- gtk_widget_show(GTK_WIDGET(main_menu));
-
- reconsile_list_and_menu(serverList, menushell);
-
- return;
-}
-
-static void
-server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data)
-{
- serverList = g_list_sort(serverList, serverList_sort);
- reconsile_list_and_menu(serverList, GTK_MENU_SHELL(data));
- return;
-}
-
-static void
-server_count_changed (AppMenuItem * appitem, guint count, gpointer data)
-{
- static gboolean showing_new_icon = FALSE;
-
- /* Quick check for a common case */
- if (count != 0 && showing_new_icon) {
- return;
- }
-
- /* Odd that we'd get a signal in this case, but let's
- take it out of the mix too */
- if (count == 0 && !showing_new_icon) {
- return;
- }
-
- if (count != 0) {
- g_debug("Setting image to 'new'");
- showing_new_icon = TRUE;
- gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages-new", DESIGN_TEAM_SIZE);
- return;
- }
-
- /* Okay, now at this point the count is zero and it
- might result in a switching of the icon back to being
- the plain one. Let's check. */
-
- gboolean we_have_indicators = FALSE;
- GList * appitems = serverList;
- for (; appitems != NULL; appitems = appitems->next) {
- AppMenuItem * appitem = ((serverList_t *)appitems->data)->menuitem;
- if (app_menu_item_get_count(appitem) != 0) {
- we_have_indicators = TRUE;
- break;
- }
- }
-
- if (!we_have_indicators) {
- g_debug("Setting image to boring");
- showing_new_icon = FALSE;
- gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages", DESIGN_TEAM_SIZE);
- }
-
- return;
-}
-
-static void
-im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data)
-{
- serverList_t * sl = (serverList_t *)data;
- sl->imList = g_list_sort(sl->imList, imList_sort);
- reconsile_list_and_menu(serverList, GTK_MENU_SHELL(gtk_widget_get_parent(GTK_WIDGET(imitem))));
- return;
-}
-
-static void
-server_removed (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
-{
- g_debug("Removing server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
- serverList_t slt;
- slt.server = server;
- GList * lookup = g_list_find_custom(serverList, &slt, serverList_equal);
-
- if (lookup == NULL) {
- g_debug("\tUnable to find server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
- return;
- }
-
- serverList_t * sltp = (serverList_t *)lookup->data;
-
- while (sltp->imList) {
- imList_t * imitem = (imList_t *)sltp->imList->data;
- indicator_removed(listener, server, imitem->indicator, "message", data);
- }
-
- serverList = g_list_remove(serverList, sltp);
-
- if (sltp->menuitem != NULL) {
- gtk_widget_hide(GTK_WIDGET(sltp->menuitem));
- gtk_container_remove(GTK_CONTAINER(data), GTK_WIDGET(sltp->menuitem));
- }
-
- g_free(sltp);
-
- if (g_list_length(serverList) == 0) {
- gtk_widget_hide(main_menu);
- } else {
- /* Simulate a server saying zero to recalculate icon */
- server_count_changed(NULL, 0, NULL);
- }
-
- return;
-}
-
-typedef struct _menushell_location menushell_location_t;
-struct _menushell_location {
- const IndicateListenerServer * server;
- gint position;
- gboolean found;
-};
-
-static void
-menushell_foreach_cb (GtkWidget * data_mi, gpointer data_ms) {
- menushell_location_t * msl = (menushell_location_t *)data_ms;
-
- if (msl->found) return;
-
- msl->position++;
-
- if (!IS_APP_MENU_ITEM(data_mi)) {
- return;
- }
-
- AppMenuItem * appmenu = APP_MENU_ITEM(data_mi);
- if (!g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME((IndicateListenerServer*)msl->server), INDICATE_LISTENER_SERVER_DBUS_NAME(app_menu_item_get_server(appmenu)))) {
- msl->found = TRUE;
- }
-
- return;
-}
-
-static void
-reconsile_list_and_menu (GList * serverlist, GtkMenuShell * menushell)
+GtkLabel *
+get_label (void)
{
- guint position = 0;
- GList * serverentry;
-
- g_debug("Reordering Menu:");
-
- for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) {
- serverList_t * si = (serverList_t *)serverentry->data;
- if (si->menuitem != NULL) {
- g_debug("\tMoving app %s to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position);
- gtk_menu_reorder_child(GTK_MENU(menushell), GTK_WIDGET(si->menuitem), position);
- position++;
- }
-
- GList * imentry;
- for (imentry = si->imList; imentry != NULL; imentry = imentry->next) {
- imList_t * imi = (imList_t *)imentry->data;
-
- if (imi->menuitem != NULL) {
- g_debug("\tMoving indicator on %s id %d to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(imi->server), INDICATE_LISTENER_INDICATOR_ID(imi->indicator), position);
- gtk_menu_reorder_child(GTK_MENU(menushell), imi->menuitem, position);
- position++;
- }
- }
- }
-
- return;
+ return NULL;
}
-static void
-subtype_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, gchar * propertydata, gpointer data)
+GtkImage *
+get_icon (void)
{
- GtkMenuShell * menushell = GTK_MENU_SHELL(data);
- if (menushell == NULL) {
- g_error("Data in callback is not a menushell");
- return;
- }
-
- if (property == NULL || g_strcmp0(property, "subtype")) {
- /* We should only ever get subtypes, but just in case */
- g_warning("Subtype callback got a property '%s'", property);
- return;
- }
-
- if (propertydata == NULL || propertydata[0] == '\0') {
- /* It's possible that this message didn't have a subtype. That's
- * okay, but we don't want to display those */
- g_debug("No subtype");
- return;
- }
-
- g_debug("Message subtype: %s", propertydata);
-
- if (!g_strcmp0(propertydata, "im") || !g_strcmp0(propertydata, "login")) {
- imList_t * listItem = g_new0(imList_t, 1);
- listItem->server = server;
- listItem->indicator = indicator;
-
- g_debug("Building IM Item");
- ImMenuItem * menuitem = im_menu_item_new(listener, server, indicator, !g_strcmp0(propertydata, "im"));
- g_object_ref(G_OBJECT(menuitem));
- listItem->menuitem = GTK_WIDGET(menuitem);
-
- g_debug("Finding the server entry");
- serverList_t sl_item_local;
- serverList_t * sl_item = NULL;
- sl_item_local.server = server;
- GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
-
- if (serverentry == NULL) {
- /* This sucks, we got an indicator before the server. I guess
- that's the joy of being asynchronous */
- serverList_t * sl_item = g_new0(serverList_t, 1);
- sl_item->server = server;
- sl_item->menuitem = NULL;
- sl_item->imList = NULL;
-
- serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
- } else {
- sl_item = (serverList_t *)serverentry->data;
- }
-
- g_debug("Adding to IM List");
- sl_item->imList = g_list_insert_sorted(sl_item->imList, listItem, imList_sort);
- listItem->timechange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_TIME_CHANGED, G_CALLBACK(im_time_changed), sl_item);
-
- g_debug("Placing in Shell");
- menushell_location_t msl;
- msl.found = FALSE;
- msl.position = 0;
- msl.server = server;
-
- gtk_container_foreach(GTK_CONTAINER(menushell), menushell_foreach_cb, &msl);
- if (msl.found) {
- gtk_menu_shell_insert(menushell, GTK_WIDGET(menuitem), msl.position);
- } else {
- g_warning("Unable to find server menu item");
- gtk_menu_shell_append(menushell, GTK_WIDGET(menuitem));
- }
- }
+ design_team_size = gtk_icon_size_register("design-team-size", 22, 22);
- return;
-}
+ main_image = gtk_image_new_from_icon_name("indicator-messages", DESIGN_TEAM_SIZE);
+ gtk_widget_show(main_image);
-static void
-indicator_added (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data)
-{
- if (type == NULL || g_strcmp0(type, "message")) {
- /* We only care about message type indicators
- all of the others can go to the bit bucket */
- g_debug("Ignoreing indicator of type '%s'", type);
- return;
- }
- g_debug("Got a message");
+ /* Need a proxy here to figure out when the icon changes */
- indicate_listener_get_property(listener, server, indicator, "subtype", subtype_cb, data);
- return;
+ return GTK_IMAGE(main_image);
}
-static void
-indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data)
+GtkMenu *
+get_menu (void)
{
- g_debug("Removing %s %d", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
- if (type == NULL || g_strcmp0(type, "message")) {
- /* We only care about message type indicators
- all of the others can go to the bit bucket */
- g_debug("Ignoreing indicator of type '%s'", type);
- return;
- }
-
- gboolean removed = FALSE;
+ guint returnval = 0;
+ GError * error = NULL;
- serverList_t sl_item_local;
- serverList_t * sl_item = NULL;
- sl_item_local.server = server;
- GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
- if (serverentry == NULL) {
- return;
- }
- sl_item = (serverList_t *)serverentry->data;
-
- /* Look in the IM Hash Table */
- imList_t listData;
- listData.server = server;
- listData.indicator = indicator;
-
- GList * listItem = g_list_find_custom(sl_item->imList, &listData, imList_equal);
- GtkWidget * menuitem = NULL;
- imList_t * ilt = NULL;
- if (listItem != NULL) {
- ilt = (imList_t *)listItem->data;
- menuitem = ilt->menuitem;
- }
-
- if (!removed && menuitem != NULL) {
- sl_item->imList = g_list_remove(sl_item->imList, ilt);
- g_signal_handler_disconnect(menuitem, ilt->timechange_cb);
- g_free(ilt);
+ DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+ DBusGProxy * proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
- gtk_widget_hide(menuitem);
- gtk_container_remove(GTK_CONTAINER(data), menuitem);
- removed = TRUE;
+ if (!org_freedesktop_DBus_start_service_by_name (proxy, INDICATOR_MESSAGES_DBUS_NAME, 0, &returnval, &error)) {
+ g_error("Unable to send message to DBus to start service: %s", error != NULL ? error->message : "(NULL error)" );
+ g_error_free(error);
+ return NULL;
}
- if (!removed) {
- g_warning("We were asked to remove %s %d but we didn't.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
+ if (returnval != DBUS_START_REPLY_SUCCESS && returnval != DBUS_START_REPLY_ALREADY_RUNNING) {
+ g_error("Return value isn't indicative of success: %d", returnval);
+ return NULL;
}
- return;
-}
-
-GtkWidget *
-get_menu_item (void)
-{
- design_team_size = gtk_icon_size_register("design-team-size", 22, 22);
-
- listener = indicate_listener_new();
- serverList = NULL;
-
- main_menu = gtk_menu_item_new();
- gtk_widget_set_name(main_menu, "fast-user-switch-menuitem");
-
- main_image = gtk_image_new_from_icon_name("indicator-messages", DESIGN_TEAM_SIZE);
- gtk_widget_show(main_image);
- gtk_container_add(GTK_CONTAINER(main_menu), main_image);
-
- GtkWidget * submenu = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(main_menu), submenu);
- gtk_widget_show(submenu);
-
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added), submenu);
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed), submenu);
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), submenu);
- g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), submenu);
-
- return main_menu;
+ return GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_MESSAGES_DBUS_NAME, INDICATOR_MESSAGES_DBUS_OBJECT));
}
diff --git a/src/indicator-service.c b/src/indicator-service.c
new file mode 100644
index 0000000..77d42e6
--- /dev/null
+++ b/src/indicator-service.c
@@ -0,0 +1,504 @@
+/*
+An indicator to show information that is in messaging applications
+that the user is using.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <libindicate/listener.h>
+
+#include <libdbusmenu-glib/server.h>
+
+#include "im-menu-item.h"
+#include "app-menu-item.h"
+#include "dbus-data.h"
+
+static IndicateListener * listener;
+static GList * serverList;
+
+static DbusmenuMenuitem * root_menuitem = NULL;
+static GMainLoop * mainloop = NULL;
+
+
+static void server_count_changed (AppMenuItem * appitem, guint count, gpointer data);
+static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data);
+static void im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data);
+static void reconsile_list_and_menu (GList * serverlist, DbusmenuMenuitem * menushell);
+static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data);
+
+typedef struct _serverList_t serverList_t;
+struct _serverList_t {
+ IndicateListenerServer * server;
+ AppMenuItem * menuitem;
+ GList * imList;
+};
+
+static gint
+serverList_equal (gconstpointer a, gconstpointer b)
+{
+ serverList_t * pa, * pb;
+
+ pa = (serverList_t *)a;
+ pb = (serverList_t *)b;
+
+ const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
+ const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
+
+ return g_strcmp0(pas, pbs);
+}
+
+static gint
+serverList_sort (gconstpointer a, gconstpointer b)
+{
+ serverList_t * pa, * pb;
+
+ pa = (serverList_t *)a;
+ pb = (serverList_t *)b;
+
+ const gchar * pan = app_menu_item_get_name(pa->menuitem);
+ const gchar * pbn = app_menu_item_get_name(pb->menuitem);
+
+ return g_strcmp0(pan, pbn);
+}
+
+typedef struct _imList_t imList_t;
+struct _imList_t {
+ IndicateListenerServer * server;
+ IndicateListenerIndicator * indicator;
+ DbusmenuMenuitem * menuitem;
+ gulong timechange_cb;
+};
+
+static gboolean
+imList_equal (gconstpointer a, gconstpointer b)
+{
+ imList_t * pa, * pb;
+
+ pa = (imList_t *)a;
+ pb = (imList_t *)b;
+
+ const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server);
+ const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server);
+
+ guint pai = INDICATE_LISTENER_INDICATOR_ID(pa->indicator);
+ guint pbi = INDICATE_LISTENER_INDICATOR_ID(pb->indicator);
+
+ g_debug("\tComparing (%s %d) to (%s %d)", pas, pai, pbs, pbi);
+
+ return !((!g_strcmp0(pas, pbs)) && (pai == pbi));
+}
+
+static gint
+imList_sort (gconstpointer a, gconstpointer b)
+{
+ imList_t * pa, * pb;
+
+ pa = (imList_t *)a;
+ pb = (imList_t *)b;
+
+ return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem)));
+}
+
+static void
+server_added (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
+{
+ g_debug("Server Added '%s' of type '%s'.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), type);
+ if (type == NULL) {
+ return;
+ }
+
+ if (type[0] == '\0') {
+ return;
+ }
+
+ if (strncmp(type, "message", strlen("message"))) {
+ g_debug("\tServer type '%s' is not a message based type.", type);
+ return;
+ }
+
+ DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
+ if (menushell == NULL) {
+ g_error("\tData in callback is not a menushell");
+ return;
+ }
+
+ AppMenuItem * menuitem = app_menu_item_new(listener, server);
+ g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, G_CALLBACK(server_count_changed), NULL);
+ g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_NAME_CHANGED, G_CALLBACK(server_name_changed), menushell);
+
+ serverList_t * sl_item = g_new0(serverList_t, 1);
+ sl_item->server = server;
+ sl_item->menuitem = menuitem;
+ sl_item->imList = NULL;
+
+ /* Incase we got an indicator first */
+ GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal);
+ if (alreadythere != NULL) {
+ g_free(sl_item);
+ sl_item = (serverList_t *)alreadythere->data;
+ sl_item->menuitem = menuitem;
+ serverList = g_list_sort(serverList, serverList_sort);
+ } else {
+ serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
+ }
+
+ dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem));
+ /* Should be prepend ^ */
+
+ reconsile_list_and_menu(serverList, menushell);
+
+ return;
+}
+
+static void
+server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data)
+{
+ serverList = g_list_sort(serverList, serverList_sort);
+ reconsile_list_and_menu(serverList, DBUSMENU_MENUITEM(data));
+ return;
+}
+
+static void
+server_count_changed (AppMenuItem * appitem, guint count, gpointer data)
+{
+ static gboolean showing_new_icon = FALSE;
+
+ /* Quick check for a common case */
+ if (count != 0 && showing_new_icon) {
+ return;
+ }
+
+ /* Odd that we'd get a signal in this case, but let's
+ take it out of the mix too */
+ if (count == 0 && !showing_new_icon) {
+ return;
+ }
+
+ if (count != 0) {
+ g_debug("Setting image to 'new'");
+ showing_new_icon = TRUE;
+ /* gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages-new", DESIGN_TEAM_SIZE); */
+ return;
+ }
+
+ /* Okay, now at this point the count is zero and it
+ might result in a switching of the icon back to being
+ the plain one. Let's check. */
+
+ gboolean we_have_indicators = FALSE;
+ GList * appitems = serverList;
+ for (; appitems != NULL; appitems = appitems->next) {
+ AppMenuItem * appitem = ((serverList_t *)appitems->data)->menuitem;
+ if (app_menu_item_get_count(appitem) != 0) {
+ we_have_indicators = TRUE;
+ break;
+ }
+ }
+
+ if (!we_have_indicators) {
+ g_debug("Setting image to boring");
+ showing_new_icon = FALSE;
+ /* gtk_image_set_from_icon_name(GTK_IMAGE(main_image), "indicator-messages", DESIGN_TEAM_SIZE); */
+ }
+
+ return;
+}
+
+static void
+im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data)
+{
+ serverList_t * sl = (serverList_t *)data;
+ sl->imList = g_list_sort(sl->imList, imList_sort);
+ reconsile_list_and_menu(serverList, root_menuitem);
+ return;
+}
+
+static void
+server_removed (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
+{
+ g_debug("Removing server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
+ serverList_t slt;
+ slt.server = server;
+ GList * lookup = g_list_find_custom(serverList, &slt, serverList_equal);
+
+ if (lookup == NULL) {
+ g_debug("\tUnable to find server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server));
+ return;
+ }
+
+ serverList_t * sltp = (serverList_t *)lookup->data;
+
+ while (sltp->imList) {
+ imList_t * imitem = (imList_t *)sltp->imList->data;
+ indicator_removed(listener, server, imitem->indicator, "message", data);
+ }
+
+ serverList = g_list_remove(serverList, sltp);
+
+ if (sltp->menuitem != NULL) {
+ dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sltp->menuitem), "visibile", "false");
+ dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->menuitem));
+ }
+
+ g_free(sltp);
+
+ /* Simulate a server saying zero to recalculate icon */
+ server_count_changed(NULL, 0, NULL);
+
+ return;
+}
+
+typedef struct _menushell_location menushell_location_t;
+struct _menushell_location {
+ const IndicateListenerServer * server;
+ gint position;
+ gboolean found;
+};
+
+static void
+menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) {
+ menushell_location_t * msl = (menushell_location_t *)data_ms;
+
+ if (msl->found) return;
+
+ msl->position++;
+
+ if (!IS_APP_MENU_ITEM(data_mi)) {
+ return;
+ }
+
+ AppMenuItem * appmenu = APP_MENU_ITEM(data_mi);
+ if (!g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME((IndicateListenerServer*)msl->server), INDICATE_LISTENER_SERVER_DBUS_NAME(app_menu_item_get_server(appmenu)))) {
+ msl->found = TRUE;
+ }
+
+ return;
+}
+
+static void
+reconsile_list_and_menu (GList * serverlist, DbusmenuMenuitem * menushell)
+{
+ guint position = 0;
+ GList * serverentry;
+
+ g_debug("Reordering Menu:");
+
+ for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) {
+ serverList_t * si = (serverList_t *)serverentry->data;
+ if (si->menuitem != NULL) {
+ g_debug("\tMoving app %s to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position);
+ dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->menuitem), position);
+ position++;
+ }
+
+ GList * imentry;
+ for (imentry = si->imList; imentry != NULL; imentry = imentry->next) {
+ imList_t * imi = (imList_t *)imentry->data;
+
+ if (imi->menuitem != NULL) {
+ g_debug("\tMoving indicator on %s id %d to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(imi->server), INDICATE_LISTENER_INDICATOR_ID(imi->indicator), position);
+ dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(imi->menuitem), position);
+ position++;
+ }
+ }
+ }
+
+ return;
+}
+
+static void
+subtype_cb (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, gchar * propertydata, gpointer data)
+{
+ DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data);
+ if (menushell == NULL) {
+ g_error("Data in callback is not a menushell");
+ return;
+ }
+
+ if (property == NULL || g_strcmp0(property, "subtype")) {
+ /* We should only ever get subtypes, but just in case */
+ g_warning("Subtype callback got a property '%s'", property);
+ return;
+ }
+
+ if (propertydata == NULL || propertydata[0] == '\0') {
+ /* It's possible that this message didn't have a subtype. That's
+ * okay, but we don't want to display those */
+ g_debug("No subtype");
+ return;
+ }
+
+ g_debug("Message subtype: %s", propertydata);
+
+ if (!g_strcmp0(propertydata, "im") || !g_strcmp0(propertydata, "login")) {
+ imList_t * listItem = g_new0(imList_t, 1);
+ listItem->server = server;
+ listItem->indicator = indicator;
+
+ g_debug("Building IM Item");
+ ImMenuItem * menuitem = im_menu_item_new(listener, server, indicator, !g_strcmp0(propertydata, "im"));
+ g_object_ref(G_OBJECT(menuitem));
+ listItem->menuitem = DBUSMENU_MENUITEM(menuitem);
+
+ g_debug("Finding the server entry");
+ serverList_t sl_item_local;
+ serverList_t * sl_item = NULL;
+ sl_item_local.server = server;
+ GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
+
+ if (serverentry == NULL) {
+ /* This sucks, we got an indicator before the server. I guess
+ that's the joy of being asynchronous */
+ serverList_t * sl_item = g_new0(serverList_t, 1);
+ sl_item->server = server;
+ sl_item->menuitem = NULL;
+ sl_item->imList = NULL;
+
+ serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort);
+ } else {
+ sl_item = (serverList_t *)serverentry->data;
+ }
+
+ g_debug("Adding to IM List");
+ sl_item->imList = g_list_insert_sorted(sl_item->imList, listItem, imList_sort);
+ listItem->timechange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_TIME_CHANGED, G_CALLBACK(im_time_changed), sl_item);
+
+ g_debug("Placing in Shell");
+ menushell_location_t msl;
+ msl.found = FALSE;
+ msl.position = 0;
+ msl.server = server;
+
+ dbusmenu_menuitem_foreach(DBUSMENU_MENUITEM(menushell), menushell_foreach_cb, &msl);
+ if (msl.found) {
+ dbusmenu_menuitem_child_add_position(menushell, DBUSMENU_MENUITEM(menuitem), msl.position);
+ } else {
+ g_warning("Unable to find server menu item");
+ dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem));
+ }
+ }
+
+ return;
+}
+
+static void
+indicator_added (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data)
+{
+ if (type == NULL || g_strcmp0(type, "message")) {
+ /* We only care about message type indicators
+ all of the others can go to the bit bucket */
+ g_debug("Ignoreing indicator of type '%s'", type);
+ return;
+ }
+ g_debug("Got a message");
+
+ indicate_listener_get_property(listener, server, indicator, "subtype", subtype_cb, data);
+ return;
+}
+
+static void
+indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * type, gpointer data)
+{
+ g_debug("Removing %s %d", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
+ if (type == NULL || g_strcmp0(type, "message")) {
+ /* We only care about message type indicators
+ all of the others can go to the bit bucket */
+ g_debug("Ignoreing indicator of type '%s'", type);
+ return;
+ }
+
+ gboolean removed = FALSE;
+
+ serverList_t sl_item_local;
+ serverList_t * sl_item = NULL;
+ sl_item_local.server = server;
+ GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal);
+ if (serverentry == NULL) {
+ return;
+ }
+ sl_item = (serverList_t *)serverentry->data;
+
+ /* Look in the IM Hash Table */
+ imList_t listData;
+ listData.server = server;
+ listData.indicator = indicator;
+
+ GList * listItem = g_list_find_custom(sl_item->imList, &listData, imList_equal);
+ DbusmenuMenuitem * menuitem = NULL;
+ imList_t * ilt = NULL;
+ if (listItem != NULL) {
+ ilt = (imList_t *)listItem->data;
+ menuitem = ilt->menuitem;
+ }
+
+ if (!removed && menuitem != NULL) {
+ sl_item->imList = g_list_remove(sl_item->imList, ilt);
+ g_signal_handler_disconnect(menuitem, ilt->timechange_cb);
+ g_free(ilt);
+
+ dbusmenu_menuitem_property_set(menuitem, "visibile", "false");
+ dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), menuitem);
+ removed = TRUE;
+ }
+
+ if (!removed) {
+ g_warning("We were asked to remove %s %d but we didn't.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator));
+ }
+
+ return;
+}
+
+int
+main (int argc, char ** argv)
+{
+ g_type_init();
+
+ DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+ DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+ GError * error = NULL;
+ guint nameret = 0;
+
+ if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_MESSAGES_DBUS_NAME, 0, &nameret, &error)) {
+ g_error("Unable to call to request name");
+ return 1;
+ }
+
+ if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ g_error("Unable to get name");
+ return 1;
+ }
+
+ listener = indicate_listener_ref_default();
+ serverList = NULL;
+
+ root_menuitem = dbusmenu_menuitem_new();
+ DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT);
+ dbusmenu_server_set_root(server, root_menuitem);
+
+ g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added), root_menuitem);
+ g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed), root_menuitem);
+ g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), root_menuitem);
+ g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), root_menuitem);
+
+ mainloop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(mainloop);
+
+ return 0;
+}
diff --git a/test/indicator-messages-service-activate.build.sh b/test/indicator-messages-service-activate.build.sh
new file mode 100644
index 0000000..87a0316
--- /dev/null
+++ b/test/indicator-messages-service-activate.build.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+gcc -o indicator-messages-service-activate indicator-messages-service-activate.c `pkg-config --cflags --libs dbus-1 dbus-glib-1`
diff --git a/test/indicator-messages-service-activate.c b/test/indicator-messages-service-activate.c
new file mode 100644
index 0000000..98c6522
--- /dev/null
+++ b/test/indicator-messages-service-activate.c
@@ -0,0 +1,53 @@
+/*
+An indicator to show information that is in messaging applications
+that the user is using.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
+#include "../src/dbus-data.h"
+
+int
+main (int argc, char ** argv)
+{
+ g_type_init();
+
+ guint returnval = 0;
+ GError * error = NULL;
+
+ DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+ DBusGProxy * proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+
+ g_debug("Activating service: %s", INDICATOR_MESSAGES_DBUS_NAME);
+ if (!org_freedesktop_DBus_start_service_by_name (proxy, INDICATOR_MESSAGES_DBUS_NAME, 0, &returnval, &error)) {
+ g_error("Unable to send message to DBus to start service: %s", error != NULL ? error->message : "(NULL error)" );
+ g_error_free(error);
+ return 1;
+ }
+
+ if (returnval != DBUS_START_REPLY_SUCCESS && returnval != DBUS_START_REPLY_ALREADY_RUNNING) {
+ g_error("Return value isn't indicative of success: %d", returnval);
+ return 1;
+ }
+
+ return 0;
+}
+