diff options
author | Jonathan Riddell <jriddell@canonical.com> | 2009-08-05 00:20:06 +0100 |
---|---|---|
committer | Jonathan Riddell <jriddell@canonical.com> | 2009-08-05 00:20:06 +0100 |
commit | da961bf7ff575e04fcff8c7da1a6d551510898f5 (patch) | |
tree | 5923df29689fb2326c897ef1d90b28982148d3b8 | |
parent | 9e66afc1bb6adc0726ee6f1bda22f18df0b69acd (diff) | |
parent | d20d4bf298defb4c60e76b3e463b352f276a3b8e (diff) | |
download | ayatana-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-- | .bzrignore | 3 | ||||
-rwxr-xr-x | autogen.sh | 2 | ||||
-rw-r--r-- | configure.ac | 27 | ||||
-rw-r--r-- | data/Makefile.am | 3 | ||||
-rw-r--r-- | data/indicator-messages.service.in | 3 | ||||
-rw-r--r-- | debian/changelog | 59 | ||||
-rw-r--r-- | debian/control | 6 | ||||
-rwxr-xr-x | debian/rules | 4 | ||||
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/app-menu-item.c | 47 | ||||
-rw-r--r-- | src/app-menu-item.h | 5 | ||||
-rw-r--r-- | src/dbus-data.h | 8 | ||||
-rw-r--r-- | src/im-menu-item.c | 78 | ||||
-rw-r--r-- | src/im-menu-item.h | 5 | ||||
-rw-r--r-- | src/indicator-messages.c | 480 | ||||
-rw-r--r-- | src/indicator-service.c | 504 | ||||
-rw-r--r-- | test/indicator-messages-service-activate.build.sh | 3 | ||||
-rw-r--r-- | test/indicator-messages-service-activate.c | 53 |
18 files changed, 754 insertions, 546 deletions
@@ -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 @@ -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; +} + |