← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~cjcurran/indicator-session/menu-reshuffle into lp:indicator-session

 

Conor Curran has proposed merging lp:~cjcurran/indicator-session/menu-reshuffle into lp:indicator-session.

Requested reviews:
  Ted Gould (ted)

For more details, see:
https://code.launchpad.net/~cjcurran/indicator-session/menu-reshuffle/+merge/67983

initial big session refactor to cater for the new spec.
-- 
https://code.launchpad.net/~cjcurran/indicator-session/menu-reshuffle/+merge/67983
Your team ayatana-commits is subscribed to branch lp:indicator-session.
=== modified file 'src/Makefile.am'
--- src/Makefile.am	2011-07-07 16:23:24 +0000
+++ src/Makefile.am	2011-07-14 15:41:23 +0000
@@ -14,6 +14,8 @@
 	gen-session-dbus.xml.h \
 	dbus-shared-names.h \
 	dbusmenu-shared.h \
+	user-widget.c \
+	user-widget.h \
 	accounts-service-client.h \
 	accounts-service-user-client.h
 libsession_la_CFLAGS = \

=== modified file 'src/dbus-shared-names.h'
--- src/dbus-shared-names.h	2011-01-14 03:07:18 +0000
+++ src/dbus-shared-names.h	2011-07-14 15:41:23 +0000
@@ -24,12 +24,7 @@
 #ifndef __DBUS_SHARED_NAMES_H__
 #define __DBUS_SHARED_NAMES_H__ 1
 
-#define INDICATOR_STATUS_DBUS_NAME  "com.canonical.indicator.status"
-#define INDICATOR_STATUS_DBUS_OBJECT "/com/canonical/indicator/status/menu"
-#define INDICATOR_STATUS_SERVICE_DBUS_OBJECT "/com/canonical/indicator/status/service"
-#define INDICATOR_STATUS_SERVICE_DBUS_INTERFACE "com.canonical.indicator.status.service"
-
-#define INDICATOR_USERS_DBUS_NAME  "com.canonical.indicator.users"
+#define INDICATOR_USERS_DBUS_NAME  INDICATOR_SESSION_DBUS_NAME
 #define INDICATOR_USERS_DBUS_OBJECT "/com/canonical/indicator/users/menu"
 #define INDICATOR_USERS_SERVICE_DBUS_OBJECT "/org/gnome/DisplayManager/UserManager"
 #define INDICATOR_USERS_SERVICE_DBUS_INTERFACE "org.gnome.DisplayManager.UserManager"
@@ -44,8 +39,9 @@
 #define USER_ITEM_TYPE            "x-canonical-user-item"
 #define USER_ITEM_PROP_NAME       "user-item-name"
 #define USER_ITEM_PROP_LOGGED_IN  "user-item-logged-in"
+#define USER_ITEM_PROP_IS_CURRENT_USER "user-item-is-current-user"
 #define USER_ITEM_PROP_ICON       "user-item-icon-path"
-#define USER_ITEM_ICON_DEFAULT    "default-icon"
+#define USER_ITEM_ICON_DEFAULT    "user-offline"
 
 #define RESTART_ITEM_TYPE         "x-canonical-restart-item"
 #define RESTART_ITEM_LABEL        "restart-label"

=== modified file 'src/indicator-session.c'
--- src/indicator-session.c	2011-05-26 15:54:30 +0000
+++ src/indicator-session.c	2011-07-14 15:41:23 +0000
@@ -20,6 +20,7 @@
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+//TODO - remember to reinsert Ted's comments.
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -43,6 +44,7 @@
 
 #include "dbus-shared-names.h"
 #include "dbusmenu-shared.h"
+#include "user-widget.h"
 
 #define INDICATOR_SESSION_TYPE            (indicator_session_get_type ())
 #define INDICATOR_SESSION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SESSION_TYPE, IndicatorSession))
@@ -61,8 +63,9 @@
 struct _IndicatorSession {
 	IndicatorObject parent;
 	IndicatorServiceManager * service;
-	GtkImage * status_image;
-	DbusmenuGtkMenu * menu;
+  IndicatorObjectEntry users;
+  IndicatorObjectEntry devices;
+  gboolean show_users_entry;
 	GCancellable * service_proxy_cancel;
 	GDBusProxy * service_proxy;
 };
@@ -74,26 +77,37 @@
 INDICATOR_SET_TYPE(INDICATOR_SESSION_TYPE)
 
 /* Prototypes */
-static GtkLabel * get_label (IndicatorObject * io);
-static GtkImage * get_icon (IndicatorObject * io);
-static GtkMenu * get_menu (IndicatorObject * io);
-static const gchar * get_accessible_desc (IndicatorObject * io);
-static gboolean build_menu_switch (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
-static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
-static void icon_changed (IndicatorSession * session, const gchar * icon_name);
+static gboolean build_menu_switch (DbusmenuMenuitem * newitem,
+                                   DbusmenuMenuitem * parent,
+                                   DbusmenuClient * client,
+                                   gpointer user_data);
+static gboolean new_user_item (DbusmenuMenuitem * newitem,
+                               DbusmenuMenuitem * parent,
+                               DbusmenuClient * client,
+                               gpointer user_data);
+static gboolean build_restart_item (DbusmenuMenuitem * newitem,
+                                    DbusmenuMenuitem * parent,
+                                    DbusmenuClient * client,
+                                    gpointer user_data);
+static void indicator_session_update_users_label (IndicatorSession* self,
+                                                  const gchar* name);
 static void service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data);
-static gboolean build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
 static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
 static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
+static void user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data);
+static void user_menu_visibility_get_cb (GObject* obj, GAsyncResult* res, gpointer user_data);
 
 static void indicator_session_class_init (IndicatorSessionClass *klass);
 static void indicator_session_init       (IndicatorSession *self);
 static void indicator_session_dispose    (GObject *object);
 static void indicator_session_finalize   (GObject *object);
-
+static GList* indicator_session_get_entries (IndicatorObject* obj);
+static guint indicator_session_get_location (IndicatorObject * io,
+                                             IndicatorObjectEntry * entry);
+                                             
 G_DEFINE_TYPE (IndicatorSession, indicator_session, INDICATOR_OBJECT_TYPE);
 
-static void
+static void 
 indicator_session_class_init (IndicatorSessionClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -102,82 +116,89 @@
 	object_class->finalize = indicator_session_finalize;
 
 	IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
-	io_class->get_label = get_label;
-	io_class->get_image = get_icon;
-	io_class->get_menu = get_menu;
-	io_class->get_accessible_desc = get_accessible_desc;
-
+  io_class->get_entries = indicator_session_get_entries;
+  io_class->get_location = indicator_session_get_location;
 	return;
 }
 
 static void
 indicator_session_init (IndicatorSession *self)
 {
-	/* Set good defaults */
 	self->service = NULL;
 	self->service_proxy_cancel = NULL;
 	self->service_proxy = NULL;
-
+  self->show_users_entry = FALSE;
+  
 	/* Now let's fire these guys up. */
-	self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_VERSION);
-	g_signal_connect(G_OBJECT(self->service), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(service_connection_cb), self);
-
-	self->status_image = indicator_image_helper(ICON_DEFAULT);
-	self->menu = dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_OBJECT);
-
-	DbusmenuClient * client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(self->menu));
-	dbusmenu_client_add_type_handler(client, MENU_SWITCH_TYPE, build_menu_switch);
-	dbusmenu_client_add_type_handler(client, USER_ITEM_TYPE, new_user_item);
-	dbusmenu_client_add_type_handler(client, RESTART_ITEM_TYPE, build_restart_item);
-
+	self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME,
+                                                        INDICATOR_SESSION_DBUS_VERSION);
+	g_signal_connect(G_OBJECT(self->service),
+                   INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
+                   G_CALLBACK(service_connection_cb), self);
+
+  GtkWidget* avatar_icon = NULL;
+  // users
+  self->users.menu =  GTK_MENU (dbusmenu_gtkmenu_new (INDICATOR_USERS_DBUS_NAME,
+                                                      INDICATOR_USERS_DBUS_OBJECT));
+  // Set the image to the default avator image
+  GdkPixbuf* pixbuf  = NULL; 
+  GError* error = NULL;
+  pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+                                     "avatar-default",
+                                     17,
+                                     GTK_ICON_LOOKUP_FORCE_SIZE,
+                                     &error);
+  
+  // I think the avatar image is available always but just in case have a fallback
+  if (error != NULL) {
+    g_warning ("Could not load the default avatar image for some reason");
+    self->users.image = indicator_image_helper (USER_ITEM_ICON_DEFAULT);
+  }
+  else{
+    avatar_icon = gtk_image_new ();
+    gtk_image_set_from_pixbuf (GTK_IMAGE (avatar_icon), pixbuf);
+    self->users.image = GTK_IMAGE (avatar_icon);
+    g_object_unref (pixbuf);
+    g_error_free (error);
+  }
+                                                      
+  self->users.label = GTK_LABEL (gtk_label_new (NULL));
+  // Only show once we have a valid username
+  // gtk_widget_hide (GTK_WIDGET(self->users.label));
+
+  // devices
+  self->devices.menu = GTK_MENU (dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME,
+                                                      INDICATOR_SESSION_DBUS_OBJECT));
+  self->devices.image = indicator_image_helper (ICON_DEFAULT);
+  
+  gtk_widget_show (GTK_WIDGET(self->devices.menu));
+  gtk_widget_show (GTK_WIDGET(self->devices.image));
+  gtk_widget_show (GTK_WIDGET(self->users.image));
+  gtk_widget_show (GTK_WIDGET(self->users.menu));
+  
+  g_object_ref (self->users.menu);
+  g_object_ref (self->users.image);
+  g_object_ref (self->devices.menu);
+  g_object_ref (self->devices.image);
+  
+  // Setup the handlers for users
+	DbusmenuClient * users_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->users.menu)));
+	dbusmenu_client_add_type_handler (users_client,
+                                    USER_ITEM_TYPE,
+                                    new_user_item);
+	dbusmenu_client_add_type_handler_full (users_client,
+                                         MENU_SWITCH_TYPE,
+                                         build_menu_switch,
+                                         self, NULL);
+  
+  // Setup the handlers for devices
+	DbusmenuClient * devices_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->devices.menu)));
+	dbusmenu_client_add_type_handler (devices_client,
+                                    RESTART_ITEM_TYPE,
+                                    build_restart_item);
+  
 	GtkAccelGroup * agroup = gtk_accel_group_new();
-	dbusmenu_gtkclient_set_accel_group(DBUSMENU_GTKCLIENT(client), agroup);
-
-	self->service_proxy_cancel = g_cancellable_new();
-
-	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
-		                  G_DBUS_PROXY_FLAGS_NONE,
-		                  NULL,
-		                  INDICATOR_SESSION_DBUS_NAME,
-		                  INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
-		                  INDICATOR_SESSION_SERVICE_DBUS_IFACE,
-		                  self->service_proxy_cancel,
-		                  service_proxy_cb,
-	                          self);
-
-	return;
-}
-
-/* Callback from trying to create the proxy for the serivce, this
-   could include starting the service.  Sometime it'll fail and
-   we'll try to start that dang service again! */
-static void
-service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
-{
-	GError * error = NULL;
-
-	IndicatorSession * self = INDICATOR_SESSION(user_data);
-	g_return_if_fail(self != NULL);
-
-	GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
-
-	if (self->service_proxy_cancel != NULL) {
-		g_object_unref(self->service_proxy_cancel);
-		self->service_proxy_cancel = NULL;
-	}
-
-	if (error != NULL) {
-		g_warning("Could not grab DBus proxy for %s: %s", INDICATOR_SESSION_DBUS_NAME, error->message);
-		g_error_free(error);
-		return;
-	}
-
-	/* Okay, we're good to grab the proxy at this point, we're
-	sure that it's ours. */
-	self->service_proxy = proxy;
-
-	g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self);
-
+	dbusmenu_gtkclient_set_accel_group(DBUSMENU_GTKCLIENT(devices_client), agroup);
 	return;
 }
 
@@ -201,6 +222,14 @@
 		g_object_unref(self->service_proxy_cancel);
 		self->service_proxy_cancel = NULL;
 	}
+  
+  if (self->users.menu != NULL) {
+    g_object_unref (self->users.menu);
+  }
+  
+  if (self->devices.menu != NULL) {
+    g_object_unref (self->devices.menu);
+  }
 
 	G_OBJECT_CLASS (indicator_session_parent_class)->dispose (object);
 	return;
@@ -214,256 +243,348 @@
 	return;
 }
 
-static void
-icon_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
+static GList*
+indicator_session_get_entries (IndicatorObject* obj)
 {
-	IndicatorSession * self = INDICATOR_SESSION(user_data);
-	GError * error = NULL;
-	gchar * name;
-	GVariant * result;
-
-	result = g_dbus_proxy_call_finish(self->service_proxy, res, &error);
-
-	if (error != NULL) {
-		return;
-	}
-
-	g_variant_get(result, "(&s)", &name);
-
-	if (name == NULL || name[0] == '\0') {
-		return;
-	}
-
-	indicator_image_helper_update(self->status_image, name);
-	return;
-}
-
+	g_return_val_if_fail(IS_INDICATOR_SESSION(obj), NULL);
+  IndicatorSession* self = INDICATOR_SESSION (obj);
+  
+  g_debug ("get entries");
+	GList * retval = NULL;
+  // Only show the users menu if we have more than one
+  if (self->show_users_entry == TRUE){
+    retval = g_list_prepend (retval, &self->users);
+  }
+  retval = g_list_prepend (retval, &self->devices);
+
+	if (retval != NULL) {
+		retval = g_list_reverse(retval);
+	}
+	return retval;  
+}
+
+static guint
+indicator_session_get_location (IndicatorObject * io,
+                                IndicatorObjectEntry * entry)
+{  
+	IndicatorSession * self = INDICATOR_SESSION (io);
+  if (entry == &self->users){
+    return 1;
+  }
+  else if (entry == &self->devices){
+    return 0;
+  }
+  g_warning ("IOEntry handed to us to position but we don't own it!");
+  return -1;
+}
+
+/* callback for the service manager state of being */
 static void
 service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
 {
-	IndicatorSession * self = INDICATOR_SESSION(user_data);
+	IndicatorSession * self = INDICATOR_SESSION (user_data);
 
 	if (connected) {
-		g_dbus_proxy_call(self->service_proxy, "GetIcon", NULL,
-		                  G_DBUS_CALL_FLAGS_NONE, -1, NULL,
-		                  icon_name_get_cb, user_data);
-	} else {
-		indicator_image_helper_update(self->status_image, ICON_DEFAULT);
-	}
-
-	return;
-}
-
-static GtkLabel *
-get_label (IndicatorObject * io)
-{
-	return NULL;
-}
-
-static const gchar *
-get_accessible_desc (IndicatorObject * io)
-{
-	return _("Session");
-}
-
-static void
-icon_changed (IndicatorSession * session, const gchar * icon_name)
-{
-	indicator_image_helper_update(session->status_image, icon_name);
-	return;
+    if (self->service_proxy != NULL){
+      // Its a reconnect !
+      // Fetch synchronisation data and return (proxy is still legit)
+      g_dbus_proxy_call (self->service_proxy,
+                         "GetUserMenuVisibility",
+                         NULL,
+                         G_DBUS_CALL_FLAGS_NONE,
+                         -1,
+                         NULL,
+                         user_menu_visibility_get_cb,
+                         user_data);                               
+      g_dbus_proxy_call (self->service_proxy,
+                         "GetUserRealName",
+                         NULL,
+                         G_DBUS_CALL_FLAGS_NONE,
+                         -1,
+                         NULL,
+                         user_real_name_get_cb,
+                         user_data);      
+      return;
+    }
+    
+	  self->service_proxy_cancel = g_cancellable_new();
+	  g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                              G_DBUS_PROXY_FLAGS_NONE,
+                              NULL,
+                              INDICATOR_SESSION_DBUS_NAME,
+                              INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
+                              INDICATOR_SESSION_SERVICE_DBUS_IFACE,
+                              self->service_proxy_cancel,
+                              service_proxy_cb,
+                              self);
+  }    
+	return;
+}
+
+
+static void
+service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
+{
+	GError * error = NULL;
+
+	IndicatorSession * self = INDICATOR_SESSION(user_data);
+	g_return_if_fail(self != NULL);
+
+	GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
+
+	if (self->service_proxy_cancel != NULL) {
+		g_object_unref(self->service_proxy_cancel);
+		self->service_proxy_cancel = NULL;
+	}
+
+	if (error != NULL) {
+		g_warning("Could not grab DBus proxy for %s: %s", INDICATOR_SESSION_DBUS_NAME, error->message);
+		g_error_free(error);
+		return;
+	}
+
+	/* Okay, we're good to grab the proxy at this point, we're
+	sure that it's ours. */
+	self->service_proxy = proxy;
+
+	g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self);
+  
+  // Figure out whether we should show the user menu at all.
+  g_dbus_proxy_call (self->service_proxy,
+                     "GetUserMenuVisibility",
+                     NULL,
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     NULL,
+                     user_menu_visibility_get_cb,
+                     user_data);                               
+  
+  // Fetch the user's real name for the user entry label
+  g_dbus_proxy_call (self->service_proxy,
+                     "GetUserRealName",
+                     NULL,
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     NULL,
+                     user_real_name_get_cb,
+                     user_data);
+	return;
+}
+
+
+static gboolean
+new_user_item (DbusmenuMenuitem * newitem,
+               DbusmenuMenuitem * parent,
+               DbusmenuClient * client,
+               gpointer user_data)
+{
+  
+
+  GtkWidget* user_item = NULL;
+
+  g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
+  g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
+
+  user_item = user_widget_new(newitem);
+
+  GtkMenuItem *user_widget = GTK_MENU_ITEM(user_item);
+
+  dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client),
+                                   newitem,
+                                   user_widget,
+                                   parent);
+
+  g_debug ("%s (\"%s\")", __func__,
+           dbusmenu_menuitem_property_get (newitem,
+                                           USER_ITEM_PROP_NAME));
+  gtk_widget_show_all (user_item);
+
+  return TRUE;
+}
+
+
+static void
+user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
+{
+	IndicatorSession * self = INDICATOR_SESSION(user_data);
+	GError * error = NULL;
+	GVariant * result;
+
+	result = g_dbus_proxy_call_finish(self->service_proxy, res, &error);
+
+	if (error != NULL) {
+    g_warning ("unable to complete real name dbus query");
+    g_error_free (error);
+		return;
+	}
+  
+  const gchar* username = NULL;
+  g_variant_get (result, "(s)", &username);
+  indicator_session_update_users_label (self, username);
+	return;
+}
+
+static void 
+user_menu_visibility_get_cb (GObject* obj, GAsyncResult* res, gpointer user_data)
+{
+	IndicatorSession * self = INDICATOR_SESSION(user_data);
+	GError * error = NULL;
+	GVariant * result;
+
+	result = g_dbus_proxy_call_finish(self->service_proxy, res, &error);
+
+	if (error != NULL) {
+    g_warning ("unable to complete real name dbus query");
+    g_error_free (error);
+		return;
+	}
+  gboolean update;
+  g_variant_get (result, "(b)", &update);
+  
+  // If it is what we had before no need to do anything...
+  if (self->show_users_entry == update){
+    return;
+  }
+  
+  //Otherwise
+  self->show_users_entry = update;
+
+  IndicatorObjectEntry user_entry = self->users;
+  
+  if (self->show_users_entry == TRUE){
+    g_signal_emit_by_name ((gpointer)self,
+                           "entry-added",
+                           &user_entry);   
+  }
+  else{
+    g_signal_emit_by_name ((gpointer)self,
+                           "entry-removed",
+                           &user_entry);       
+  }
 }
 
 /* Receives all signals from the service, routed to the appropriate functions */
 static void
-receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name,
-                GVariant * parameters, gpointer user_data)
+receive_signal (GDBusProxy * proxy,
+                gchar * sender_name,
+                gchar * signal_name,
+                GVariant * parameters,
+                gpointer user_data)
 {
 	IndicatorSession * self = INDICATOR_SESSION(user_data);
 
-	if (g_strcmp0(signal_name, "IconUpdated") == 0) {
-		const gchar *name;
-		g_variant_get (parameters, "(&s)", &name);
-		icon_changed(self, name);
-	}
-
-	return;
-}
-
-static GtkImage *
-get_icon (IndicatorObject * io)
-{
-	gtk_widget_show(GTK_WIDGET(INDICATOR_SESSION(io)->status_image));
-	return INDICATOR_SESSION(io)->status_image;
-}
-
-static void
-user_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data)
-{
-	if (g_strcmp0(property, USER_ITEM_PROP_LOGGED_IN) == 0) {
-		if (g_variant_get_boolean(variant)) {
-			gtk_widget_show(GTK_WIDGET(user_data));
-		} else {
-			gtk_widget_hide(GTK_WIDGET(user_data));
-		}
-	}
-	return;
-}
-
-/* Builds an item with a hip little logged in icon. */
-static gboolean
-new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
-{
-	GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
-	gint padding = 0;
-	gtk_widget_style_get(GTK_WIDGET(gmi), "horizontal-padding", &padding, NULL);
-	GtkWidget * hbox = gtk_hbox_new(FALSE, padding);
-
-	GtkWidget * usericon = NULL;
-	const gchar * icon_name = dbusmenu_menuitem_property_get(newitem, USER_ITEM_PROP_ICON);
-	g_debug("Using user icon for '%s' from file: %s", dbusmenu_menuitem_property_get(newitem, USER_ITEM_PROP_NAME), icon_name);
-	if (icon_name != NULL && icon_name[0] != '\0') {
-		if (g_strcmp0(icon_name, USER_ITEM_ICON_DEFAULT) != 0 && g_file_test(icon_name, G_FILE_TEST_EXISTS)) {
-			gint width, height;
-			gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
-
-			GError * error = NULL;
-			GdkPixbuf * pixbuf = gdk_pixbuf_new_from_file_at_size(icon_name, width, height, &error);
-
-			if (error == NULL) {
-				usericon = gtk_image_new_from_pixbuf(pixbuf);
-				g_object_unref(pixbuf);
-			} else {
-				g_warning("Unable to load user icon '%s': %s", icon_name, error->message);
-				g_error_free(error);
-			}
-		}
-
-		if (usericon == NULL) {
-			GIcon * gicon = g_themed_icon_new_with_default_fallbacks("stock_person-panel");
-			usericon = gtk_image_new_from_gicon(gicon, GTK_ICON_SIZE_MENU);
-			g_object_unref(gicon);
-		}
-	}
-	if (usericon != NULL) {
-		gtk_misc_set_alignment(GTK_MISC(usericon), 0.0, 0.5);
-		gtk_box_pack_start(GTK_BOX(hbox), usericon, FALSE, FALSE, 0);
-		gtk_widget_show(usericon);
-	}
-
-	GtkWidget * label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, USER_ITEM_PROP_NAME));
-	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-	gtk_widget_show(label);
-
-	GtkWidget * icon = gtk_image_new_from_icon_name("account-logged-in", GTK_ICON_SIZE_MENU);
-	gtk_misc_set_alignment(GTK_MISC(icon), 1.0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 0);
-	if (dbusmenu_menuitem_property_get_bool(newitem, USER_ITEM_PROP_LOGGED_IN)) {
-		gtk_widget_show(icon);
-	} else {
-		gtk_widget_hide(icon);
-	}
-
-	gtk_container_add(GTK_CONTAINER(gmi), hbox);
-	gtk_widget_show(hbox);
-
-	dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
-
-	g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(user_property_change), icon);
-
-	return TRUE;
-}
-
-/* Indicator based function to get the menu for the whole
-   applet.  This starts up asking for the parts of the menu
-   from the various services. */
-static GtkMenu *
-get_menu (IndicatorObject * io)
-{
-	return GTK_MENU(INDICATOR_SESSION(io)->menu);
-}
-
-static void
-switch_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data)
-{
-	if (g_strcmp0(property, MENU_SWITCH_USER) != 0) {
-		return;
-	}
+	if (g_strcmp0(signal_name, "UserRealNameUpdated") == 0) {
+    const gchar* username = NULL;
+    g_variant_get (parameters, "(s)", &username);
+    indicator_session_update_users_label (self, username);	
+  }
+  else if (g_strcmp0(signal_name, "UserMenuIsVisible") == 0) {
+    gboolean update;
+    g_variant_get (parameters, "(b)", &update);
+    
+    // If it is what we had before no need to do anything...
+    if (self->show_users_entry == update){
+      return;
+    }
+    
+    //Otherwise
+    self->show_users_entry = update;
+
+    IndicatorObjectEntry user_entry = self->users;
+    
+    if (self->show_users_entry == TRUE){
+      g_signal_emit_by_name ((gpointer)self,
+                             "entry-added",
+                             &user_entry);
+    }   
+    else{
+      g_signal_emit_by_name ((gpointer)self,
+                             "entry-removed",
+                             &user_entry);       
+    }
+  }
+}
+
+
+
+static void
+switch_property_change (DbusmenuMenuitem * item,
+                        const gchar * property,
+                        GVariant * variant,
+                        gpointer user_data)
+{
+  if (g_strcmp0 (property, MENU_SWITCH_USER) != 0) {
+    return;
+  }
 	
-	GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(DBUSMENU_GTKCLIENT(user_data), item);
-	gchar * finalstring = NULL;
-	gboolean set_ellipsize = FALSE;
-	gboolean no_name_in_lang = FALSE;
-
-	/* TRANSLATORS: Translate the '1' below into anything other than
-	   '1' if "Switch From %s..." doesn't make sense in your language.
-	   Instead, the string "Switch User..." will be used. */
-	const gchar * translate = C_("session_menu:switchfrom", "1");
-	if (g_strcmp0(translate, "1") != 0) {
-		no_name_in_lang = TRUE;
-	}
-
-	/* If there's a NULL string of some type, then we want to
-	   go back to our old 'Switch User' which isn't great but
-	   eh, this error condition should never happen. */
-	if (variant == NULL || g_variant_get_string(variant, NULL) == NULL || g_variant_get_string(variant, NULL)[0] == '\0' || no_name_in_lang) {
-		finalstring = _("Switch User...");
-		set_ellipsize = FALSE;
-	}
-
-	if (finalstring == NULL) {
-		const gchar * username = g_variant_get_string(variant, NULL);
-		GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(gmi));
-
-		PangoLayout * layout = pango_layout_new(gtk_widget_get_pango_context(GTK_WIDGET(gmi)));
-		pango_layout_set_text(layout, username, -1);
-		pango_layout_set_font_description(layout, style->font_desc);
-
-		gint width;
-		pango_layout_get_pixel_size(layout, &width, NULL);
-		g_object_unref(layout);
-		g_debug("Username width %dpx", width);
-
-		gint point = pango_font_description_get_size(style->font_desc);
-		g_debug("Font size %f pt", (gfloat)point / PANGO_SCALE);
-
-		gdouble dpi = gdk_screen_get_resolution(gdk_screen_get_default());
-		g_debug("Screen DPI %f", dpi);
-
-		gdouble pixels_per_em = ((point * dpi) / 72.0f) / PANGO_SCALE;
-		gdouble ems = width / pixels_per_em;
-		g_debug("Username width %fem", ems);
-
-		/* TODO: We need some way to remove the elipsis from appearing
-		         twice in the label.  Not sure how to do that yet. */
-		finalstring = g_strdup_printf(_("Switch From %s..."), username);
-		if (ems >= 20.0f) {
-			set_ellipsize = TRUE;
-		} else {
-			set_ellipsize = FALSE;
-		}
-	}
-
-	gtk_menu_item_set_label(gmi, finalstring);
-
-	GtkLabel * label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(gmi)));
-	if (label != NULL) {
-		if (set_ellipsize) {
-			gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
-		} else {
-			gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE);
-		}
-	}
+  GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(DBUSMENU_GTKCLIENT(user_data), item);
+  gchar * finalstring = NULL;
+  gboolean set_ellipsize = FALSE;
+  gboolean no_name_in_lang = FALSE;
+
+  const gchar * translate = C_("session_menu:switchfrom", "1");
+  if (g_strcmp0(translate, "1") != 0) {
+    no_name_in_lang = TRUE;
+  }
+
+  if (variant == NULL || g_variant_get_string(variant, NULL) == NULL ||
+      g_variant_get_string(variant, NULL)[0] == '\0' || no_name_in_lang) {
+    finalstring = _("Switch User...");
+    set_ellipsize = FALSE;
+  }
+
+  if (finalstring == NULL) {
+    const gchar * username = g_variant_get_string(variant, NULL);
+    GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(gmi));
+
+    PangoLayout * layout = pango_layout_new(gtk_widget_get_pango_context(GTK_WIDGET(gmi)));
+    pango_layout_set_text (layout, username, -1);
+    pango_layout_set_font_description(layout, style->font_desc);
+
+    gint width;
+    pango_layout_get_pixel_size(layout, &width, NULL);
+    g_object_unref(layout);
+    g_debug("Username width %dpx", width);
+
+    gint point = pango_font_description_get_size(style->font_desc);
+    g_debug("Font size %f pt", (gfloat)point / PANGO_SCALE);
+
+    gdouble dpi = gdk_screen_get_resolution(gdk_screen_get_default());
+    g_debug("Screen DPI %f", dpi);
+
+    gdouble pixels_per_em = ((point * dpi) / 72.0f) / PANGO_SCALE;
+    gdouble ems = width / pixels_per_em;
+    g_debug("Username width %fem", ems);
+
+    finalstring = g_strdup_printf(_("Switch From %s..."), username);
+    if (ems >= 20.0f) {
+      set_ellipsize = TRUE;
+    } else {
+      set_ellipsize = FALSE;
+    }
+    
+  }
+  gtk_menu_item_set_label(gmi, finalstring);
+
+  GtkLabel * label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(gmi)));
+  if (label != NULL) {
+    if (set_ellipsize) {
+      gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
+    } else {
+      gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE);
+    }
+  }
 
 	return;
 }
 
 static const gchar * dbusmenu_item_data = "dbusmenu-item";
 
-/* IF the label or icon changes we need to grab that and update
-   the menu item */
 static void
-restart_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data)
+restart_property_change (DbusmenuMenuitem * item,
+                         const gchar * property,
+                         GVariant * variant,
+                         gpointer user_data)
 {
 	DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data);
 	GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(client, item);
@@ -482,14 +603,14 @@
 		}
 		g_object_unref(G_OBJECT(gicon));
 	}
-
 	return;
 }
 
-/* Builds the restart item which is a more traditional GTK image
-   menu item that puts the graphic into the gutter. */
 static gboolean
-build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
+build_restart_item (DbusmenuMenuitem * newitem,
+                    DbusmenuMenuitem * parent,
+                    DbusmenuClient * client,
+                    gpointer user_data)
 {
 	GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_image_menu_item_new());
 	if (gmi == NULL) {
@@ -500,7 +621,6 @@
 
 	g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(restart_property_change), client);
 
-	/* Grab the inital variants and put them into the item */
 	GVariant * variant;
 	variant = dbusmenu_menuitem_property_get_variant(newitem, RESTART_ITEM_LABEL);
 	if (variant != NULL) {
@@ -515,36 +635,63 @@
 	return TRUE;
 }
 
-
-/* Callback for when the style changes so we can reevaluate the
-   size of the user name with the potentially new font. */
 static void
-switch_style_set (GtkWidget * widget, GtkStyle * prev_style, gpointer user_data)
+switch_style_set (GtkWidget * widget,
+                  GtkStyle * prev_style,
+                  gpointer user_data)
 {
 	DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data);
-	DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(g_object_get_data(G_OBJECT(widget), dbusmenu_item_data));
+	DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(g_object_get_data(G_OBJECT(widget),
+                                                              dbusmenu_item_data));
 
-	switch_property_change(mi, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_variant(mi, MENU_SWITCH_USER), client);
+	switch_property_change (mi,
+                          MENU_SWITCH_USER,
+                          dbusmenu_menuitem_property_get_variant(mi, MENU_SWITCH_USER),
+                          client);
 	return;
 }
 
-/* This function checks to see if the user name is short enough
-   to not need ellipsing itself, or if, it will get ellipsed by
-   the standard label processor. */
 static gboolean
-build_menu_switch (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
+build_menu_switch (DbusmenuMenuitem * newitem,
+                   DbusmenuMenuitem * parent,
+                   DbusmenuClient * client,
+                   gpointer user_data)
 {
 	GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
 	if (gmi == NULL) {
 		return FALSE;
 	}
-	g_object_set_data(G_OBJECT(gmi), dbusmenu_item_data, newitem);
+  	
+  g_object_set_data(G_OBJECT(gmi), dbusmenu_item_data, newitem);
 
 	dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
 
-	g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(switch_property_change), client);
-	g_signal_connect(G_OBJECT(gmi), "style-set", G_CALLBACK(switch_style_set), client);
-	switch_property_change(newitem, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_variant(newitem, MENU_SWITCH_USER), client);
+	g_signal_connect (G_OBJECT(newitem),
+                    DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED,
+                    G_CALLBACK(switch_property_change),
+                    client);
+	g_signal_connect (G_OBJECT(gmi),
+                    "style-set",
+                    G_CALLBACK(switch_style_set),
+                    client);
+                    
+	switch_property_change (newitem,
+                          MENU_SWITCH_USER,
+                          dbusmenu_menuitem_property_get_variant(newitem, MENU_SWITCH_USER), client);
+  	
+  return TRUE;
+}
 
-	return TRUE;
+static void
+indicator_session_update_users_label (IndicatorSession* self, 
+                                      const gchar* name)
+{
+  g_debug ("update users label");
+  
+  if (name == NULL){
+    gtk_widget_hide(GTK_WIDGET(self->users.label));
+    return;
+  }  
+  gtk_label_set_text (self->users.label, g_strdup(name));
+  gtk_widget_show(GTK_WIDGET(self->users.label));
 }

=== modified file 'src/session-dbus.c'
--- src/session-dbus.c	2011-04-13 14:17:11 +0000
+++ src/session-dbus.c	2011-07-14 15:41:23 +0000
@@ -5,6 +5,7 @@
 
 Authors:
     Ted Gould <ted@xxxxxxxxxxxxx>
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
 
 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 
@@ -28,7 +29,7 @@
 #include "session-dbus.h"
 #include "dbus-shared-names.h"
 
-static GVariant * get_icon (SessionDbus * service);
+static GVariant * get_users_real_name (SessionDbus * service);
 static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data);
 static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data);
 
@@ -37,6 +38,7 @@
 typedef struct _SessionDbusPrivate SessionDbusPrivate;
 struct _SessionDbusPrivate {
 	gchar * name;
+  gboolean user_menu_is_visible;
 	GDBusConnection * bus;
 	GCancellable * bus_cancel;
 	guint dbus_registration;
@@ -98,10 +100,11 @@
 {
 	SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(self);
 
-	priv->name = g_strdup(ICON_DEFAULT);
+	priv->name = NULL;
 	priv->bus = NULL;
 	priv->bus_cancel = NULL;
 	priv->dbus_registration = 0;
+  priv->user_menu_is_visible = FALSE;
 
 	priv->bus_cancel = g_cancellable_new();
 	g_bus_get(G_BUS_TYPE_SESSION,
@@ -160,15 +163,20 @@
                  const gchar * method, GVariant * params,
                  GDBusMethodInvocation * invocation, gpointer user_data)
 {
-	SessionDbus * service = SESSION_DBUS(user_data);
+	SessionDbus * service = SESSION_DBUS (user_data);
+	SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE (service);
+
 	GVariant * retval = NULL;
 
-	if (g_strcmp0(method, "GetIcon") == 0) {
-		retval = get_icon(service);
-	} else {
-		g_warning("Calling method '%s' on the indicator service and it's unknown", method);
-	}
-
+	if (g_strcmp0(method, "GetUserRealName") == 0) {
+		retval = get_users_real_name (service);
+	}
+  else if (g_strcmp0 (method, "GetUserMenuVisibility") == 0){
+    retval =  g_variant_new ("(b)", priv->user_menu_is_visible);
+  }
+  else {
+    g_warning("Calling method '%s' on the indicator service and it's unknown", method);
+	}
 	g_dbus_method_invocation_return_value(invocation, retval);
 	return;
 }
@@ -214,10 +222,10 @@
 }
 
 static GVariant *
-get_icon (SessionDbus * service)
+get_users_real_name (SessionDbus * service)
 {
 	SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(service);
-	return g_variant_new("(s)", priv->name);
+	return g_variant_new ("(s)", priv->name);
 }
 
 SessionDbus *
@@ -229,29 +237,59 @@
 void
 session_dbus_set_name (SessionDbus * session, const gchar * name)
 {
+}
+
+void
+session_dbus_set_users_real_name (SessionDbus * session, const gchar * name)
+{
 	SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session);
 	GError * error = NULL;
 	if (priv->name != NULL) {
 		g_free(priv->name);
 		priv->name = NULL;
 	}
+    
 	priv->name = g_strdup(name);
 
 	if (priv->bus != NULL) {
 		g_dbus_connection_emit_signal (priv->bus,
-			                       NULL,
-			                       INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
-			                       INDICATOR_SESSION_SERVICE_DBUS_IFACE,
-			                       "IconUpdated",
-			                       g_variant_new ("(s)", priv->name, NULL),
-			                       &error);
+                                   NULL,
+                                   INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
+                                   INDICATOR_SESSION_SERVICE_DBUS_IFACE,
+                                   "UserRealNameUpdated",
+                                   g_variant_new ("(s)", priv->name, NULL),
+                                   &error);
 
 		if (error != NULL) {
-			g_warning("Unable to send IconUpdated signal: %s", error->message);
+			g_warning("Unable to send UserRealNameUpdated signal: %s", error->message);
 			g_error_free(error);
 			return;
 		}
 	}
-
 	return;
 }
+
+void 
+session_dbus_set_user_menu_visibility (SessionDbus* session,
+                                       gboolean visible)
+{
+	SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session);
+	GError * error = NULL;
+    
+	priv->user_menu_is_visible = visible;
+
+	if (priv->bus != NULL) {
+		g_dbus_connection_emit_signal (priv->bus,
+                                   NULL,
+                                   INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
+                                   INDICATOR_SESSION_SERVICE_DBUS_IFACE,
+                                   "UserMenuIsVisible",
+                                   g_variant_new ("(b)", priv->user_menu_is_visible),
+                                   &error);
+
+		if (error != NULL) {
+			g_warning("Unable to send UserMenuIsVisible signal: %s", error->message);
+			g_error_free(error);
+		}
+	}  
+}

=== modified file 'src/session-dbus.h'
--- src/session-dbus.h	2010-03-12 22:10:57 +0000
+++ src/session-dbus.h	2011-07-14 15:41:23 +0000
@@ -48,7 +48,9 @@
 
 GType session_dbus_get_type (void);
 SessionDbus * session_dbus_new (void);
-void  session_dbus_set_name (SessionDbus * session, const gchar * name);
+void session_dbus_set_name (SessionDbus * session, const gchar * name);
+void session_dbus_set_users_real_name (SessionDbus * session, const gchar * name);
+void session_dbus_set_user_menu_visibility (SessionDbus* session, gboolean visible);
 
 G_END_DECLS
 

=== modified file 'src/session-dbus.xml'
--- src/session-dbus.xml	2011-01-14 03:07:18 +0000
+++ src/session-dbus.xml	2011-07-14 15:41:23 +0000
@@ -2,14 +2,17 @@
 <node name="/com/canonical/indicator/session/service">
   <interface name="com.canonical.indicator.session.service">
 
-    <!-- Icon -->
-    <method name="GetIcon">
+    <method name="GetUserRealName">
       <arg name="name" direction="out" type="s"/>
     </method>
-
-    <signal name="IconUpdated">
+    <method name="GetUserMenuVisibility">
+      <arg name="update" direction="out" type="b"/>
+    </method>
+    <signal name="UserRealNameUpdated">
       <arg name="name" type="s"/>
     </signal>
-
+    <signal name="UserMenuIsVisible">
+      <arg name="update" type="b"/>
+    </signal>
   </interface>
 </node>

=== modified file 'src/session-service.c'
--- src/session-service.c	2011-07-05 06:10:58 +0000
+++ src/session-service.c	2011-07-14 15:41:23 +0000
@@ -8,6 +8,7 @@
     Ted Gould <ted@xxxxxxxxxxxxx>
     Christoph Korn <c_korn@xxxxxx>
     Cody Russell <crussell@xxxxxxxxxxxxx>
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
 
 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 
@@ -76,7 +77,9 @@
 static DbusmenuMenuitem  *lock_menuitem = NULL;
 static DbusmenuMenuitem  *switch_menuitem = NULL;
 
-static DbusmenuMenuitem * root_menuitem = NULL;
+static DbusmenuMenuitem * session_root_menuitem = NULL;
+static DbusmenuMenuitem * users_root_menuitem = NULL;
+
 static GMainLoop * mainloop = NULL;
 static DBusGProxy * up_main_proxy = NULL;
 static DBusGProxy * up_prop_proxy = NULL;
@@ -97,7 +100,9 @@
 
 static GConfClient * gconf_client = NULL;
 
-static void rebuild_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
+static void rebuild_session_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
+static void rebuild_user_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
+static void activate_online_accounts (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data);
 
 static void
 lockdown_changed (GConfClient *client,
@@ -113,7 +118,7 @@
 	}
 
 	if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) {
-		rebuild_items(root_menuitem, dbus_interface);
+		rebuild_session_items(session_root_menuitem, dbus_interface);
 	}
 
 	return;
@@ -138,7 +143,6 @@
 			dbusmenu_menuitem_property_set_shortcut_string(lock_menuitem, gconf_value_get_string(value));
 		}
 	}
-
 	return;
 }
 
@@ -156,7 +160,7 @@
 		gconf_client_add_dir(gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
 		gconf_client_notify_add(gconf_client, KEYBINDING_DIR, keybinding_changed, NULL, NULL, NULL);
 	}
-	return;
+ 	return;
 }
 
 /* Check to see if the lockdown key is protecting from
@@ -224,7 +228,7 @@
 	gboolean local_can_suspend = g_value_get_boolean(&candoit);
 	if (local_can_suspend != can_suspend) {
 		can_suspend = local_can_suspend;
-		rebuild_items(root_menuitem, dbus_interface);
+		rebuild_session_items(session_root_menuitem, dbus_interface);
 	}
 
 	return;
@@ -249,7 +253,7 @@
 	gboolean local_can_hibernate = g_value_get_boolean(&candoit);
 	if (local_can_hibernate != can_hibernate) {
 		can_hibernate = local_can_hibernate;
-		rebuild_items(root_menuitem, dbus_interface);
+		rebuild_session_items(session_root_menuitem, dbus_interface);
 	}
 
 	return;
@@ -310,7 +314,7 @@
 
 	if (OUT_allowed != *can_do) {
 		*can_do = OUT_allowed;
-		rebuild_items (root_menuitem, dbus_interface);
+		rebuild_session_items (session_root_menuitem, dbus_interface);
 	}
 }
 
@@ -387,32 +391,6 @@
 	return;
 }
 
-/* Checks to see if we should show the guest session item */
-static gboolean
-check_guest_session (void)
-{
-	if (geteuid() < 500) {
-		/* System users shouldn't have guest account shown.  Mosly
-		   this would be the case of the guest user itself. */
-		return FALSE;
-	}
-	// FIXME: Ask DisplayManager
-
-	return TRUE;
-}
-
-/* Called when someone clicks on the guest session item. */
-static void
-activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
-{
-	lock_if_possible();
-
-	if (!users_service_dbus_activate_guest_session(USERS_SERVICE_DBUS(user_data)))
-		g_warning("Unable to activate guest session");
-
-	return;
-}
-
 /* Checks to see if we can create sessions */
 static gboolean
 check_new_session (void)
@@ -463,49 +441,16 @@
   return retval;
 }
 
-/* Take a desktop file and execute it */
-static void
-desktop_activate_cb (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
-{
-	GAppInfo * appinfo = G_APP_INFO(data);
-	g_return_if_fail(appinfo != NULL);
-	g_app_info_launch(appinfo, NULL, NULL, NULL);
-	return;
-}
-
-/* Look at the GAppInfo structures and sort based on
-   the application names */
-static gint
-sort_app_infos (gconstpointer a, gconstpointer b)
-{
-	GAppInfo * appa = G_APP_INFO(a);
-	GAppInfo * appb = G_APP_INFO(b);
-
-	const gchar * namea = NULL;
-	const gchar * nameb = NULL;
-
-	if (appa != NULL) {
-		namea = g_app_info_get_name(appa);
-	}
-
-	if (appb != NULL) {
-		nameb = g_app_info_get_name(appb);
-	}
-
-	return g_strcmp0(namea, nameb);
-}
-
 /* Builds up the menu for us */
-static void
-rebuild_items (DbusmenuMenuitem *root,
-               UsersServiceDbus *service)
+static void 
+rebuild_user_items (DbusmenuMenuitem *root,
+                    UsersServiceDbus *service)
 {
   DbusmenuMenuitem *mi = NULL;
-  DbusmenuMenuitem * guest_mi = NULL;
+  DbusmenuMenuitem *guest_mi = NULL;
   GList *u;
   UserData *user;
   gboolean can_activate;
-  gboolean can_lockscreen;
   GList *children;
 
   /* Make sure we have a valid GConf client, and build one
@@ -515,17 +460,163 @@
   /* Check to see which menu items we're allowed to have */
   can_activate = users_service_dbus_can_activate_session (service) &&
       !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_USER, NULL);
-  can_lockscreen = !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL);
 
   /* Remove the old menu items if that makes sense */
   children = dbusmenu_menuitem_take_children (root);
   g_list_foreach (children, (GFunc)g_object_unref, NULL);
   g_list_free (children);
 
+  /* Set to NULL just incase we don't end up building one */
+  users_service_dbus_set_guest_item(service, NULL);
+
+  /* Build all of the user switching items */
+  if (can_activate == TRUE)
+  {
+    if (check_new_session ()){
+      switch_menuitem = dbusmenu_menuitem_new ();
+      dbusmenu_menuitem_property_set (switch_menuitem,
+                                      DBUSMENU_MENUITEM_PROP_TYPE,
+                                      MENU_SWITCH_TYPE);
+      dbusmenu_menuitem_property_set (switch_menuitem,
+                                      MENU_SWITCH_USER,
+                                      g_get_user_name());
+      dbusmenu_menuitem_child_append (root, switch_menuitem);
+      g_signal_connect (G_OBJECT (switch_menuitem),
+                        DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                        G_CALLBACK (activate_new_session),
+                        service);
+    }
+
+    GList * users = NULL;
+    users = users_service_dbus_get_user_list (service);
+    guint user_count = g_list_length(users);
+    // g_debug ("USER COUNT = %i", user_count);
+    // We only want to show this menu when we have more than one registered 
+    // user
+    session_dbus_set_user_menu_visibility (session_dbus, user_count > 1);
+
+    if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
+      users = g_list_sort (users, (GCompareFunc)compare_users_by_username);
+    }
+
+    for (u = users; u != NULL; u = g_list_next (u)) {
+      user = u->data;
+      user->service = service;
+
+      g_debug ("%i %s", (gint)user->uid, user->user_name);
+
+      if (g_strcmp0(user->user_name, "guest") == 0) {
+        /* Check to see if the guest has sessions and so therefore should
+           get a check mark. */
+        if (user->sessions != NULL) {
+          dbusmenu_menuitem_property_set_bool (guest_mi,
+                                               USER_ITEM_PROP_LOGGED_IN,
+                                               TRUE);
+        }
+        /* If we're showing user accounts, keep going through the list */
+        if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
+          continue;
+        }
+        /* If not, we can stop here */
+        break;
+      }
+
+      if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
+        mi = dbusmenu_menuitem_new ();
+        dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
+        if (user->real_name_conflict) {
+          gchar * conflictedname = g_strdup_printf("%s (%s)", user->real_name, user->user_name);
+          dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, conflictedname);
+          g_free(conflictedname);
+        } else {
+          dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, user->real_name);
+        }
+        dbusmenu_menuitem_property_set_bool (mi,
+                                             USER_ITEM_PROP_LOGGED_IN,
+                                             user->sessions != NULL);
+        if (user->icon_file != NULL && user->icon_file[0] != '\0') {
+          dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, user->icon_file);
+        } else {
+          dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, USER_ITEM_ICON_DEFAULT);
+        }
+        
+        gboolean logged_in = g_strcmp0 (user->user_name, g_get_user_name()) == 0;       
+        dbusmenu_menuitem_property_set_bool (mi,
+                                             USER_ITEM_PROP_IS_CURRENT_USER,
+                                             logged_in);          
+        if (logged_in == TRUE){
+          g_debug ("about to set the users real name to %s for user %s",
+                    user->real_name, user->user_name);
+          session_dbus_set_users_real_name (session_dbus, user->real_name);
+        }
+        
+        dbusmenu_menuitem_child_append (root, mi);
+        g_signal_connect (G_OBJECT (mi),
+                          DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                          G_CALLBACK (activate_user_session),
+                          user);
+        user->menuitem = mi;
+      }
+    }
+    g_list_free(users);
+  }
+  // Add the online accounts and separator
+  DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
+  dbusmenu_menuitem_property_set (separator1,
+                                  DBUSMENU_MENUITEM_PROP_TYPE,
+                                  DBUSMENU_CLIENT_TYPES_SEPARATOR);
+  dbusmenu_menuitem_child_append (root, separator1);
+  DbusmenuMenuitem * online_accounts_item = dbusmenu_menuitem_new();
+  dbusmenu_menuitem_property_set (online_accounts_item,
+                                  DBUSMENU_MENUITEM_PROP_TYPE,
+                                  DBUSMENU_CLIENT_TYPES_DEFAULT);
+  dbusmenu_menuitem_property_set (online_accounts_item,
+                                  DBUSMENU_MENUITEM_PROP_LABEL,
+                                  _("Online Accounts..."));
+
+  g_signal_connect (G_OBJECT (online_accounts_item),
+                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                    G_CALLBACK (activate_online_accounts),
+                    NULL);
+                                  
+  dbusmenu_menuitem_child_append (root, online_accounts_item);    
+}
+
+// TODO
+// Wait until dialog is complete to find out name to pass
+// to the control centre.
+static void
+activate_online_accounts (DbusmenuMenuitem *mi,
+                          guint timestamp,
+                          gpointer user_data)
+{
+  GError * error = NULL;
+  if (!g_spawn_command_line_async("gnome-control-center online-accounts", &error))
+  {
+    g_warning("Unable to show control centre: %s", error->message);
+    g_error_free(error);
+  }
+}
+
+static void
+rebuild_session_items (DbusmenuMenuitem *root,
+                       UsersServiceDbus *service)
+{
+  gboolean can_lockscreen;
+
+  /* Make sure we have a valid GConf client, and build one
+     if needed */
+  ensure_gconf_client ();
+
+  can_lockscreen = !gconf_client_get_bool ( gconf_client,
+                                            LOCKDOWN_KEY_SCREENSAVER,
+                                            NULL);
   /* Lock screen item */
   if (can_lockscreen) {
 	lock_menuitem = dbusmenu_menuitem_new();
-	dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
+	dbusmenu_menuitem_property_set (lock_menuitem,
+                                  DBUSMENU_MENUITEM_PROP_LABEL,
+                                  _("Lock Screen"));
 
 	gchar * shortcut = gconf_client_get_string(gconf_client, KEY_LOCK_SCREEN, NULL);
 	if (shortcut != NULL) {
@@ -536,154 +627,93 @@
 		g_debug("Unable to get lock screen shortcut.");
 	}
 
-	g_signal_connect(G_OBJECT(lock_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL);
+	g_signal_connect (G_OBJECT(lock_menuitem),
+                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                    G_CALLBACK(lock_screen), NULL);
 	dbusmenu_menuitem_child_append(root, lock_menuitem);
   }
 
-  /* Set to NULL just incase we don't end up building one */
-  users_service_dbus_set_guest_item(service, NULL);
-
-  /* Build all of the user switching items */
-  if (can_activate == TRUE)
-    {
-		if (can_lockscreen) {
-			DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
-			dbusmenu_menuitem_property_set(separator1, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-			dbusmenu_menuitem_child_append(root, separator1);
-		}
-
-      if (check_guest_session ())
-        {
-          guest_mi = dbusmenu_menuitem_new ();
-		  dbusmenu_menuitem_property_set (guest_mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
-          dbusmenu_menuitem_property_set (guest_mi, USER_ITEM_PROP_NAME, _("Guest Session"));
-          dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, FALSE);
-          dbusmenu_menuitem_child_append (root, guest_mi);
-          g_signal_connect (G_OBJECT (guest_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_guest_session), service);
-          users_service_dbus_set_guest_item(service, guest_mi);
-        }
-
-      if (check_new_session ())
-        {
-
-          switch_menuitem = dbusmenu_menuitem_new ();
-		  dbusmenu_menuitem_property_set (switch_menuitem, DBUSMENU_MENUITEM_PROP_TYPE, MENU_SWITCH_TYPE);
-		  dbusmenu_menuitem_property_set (switch_menuitem, MENU_SWITCH_USER, g_get_user_name());
-          dbusmenu_menuitem_child_append (root, switch_menuitem);
-          g_signal_connect (G_OBJECT (switch_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_new_session), service);
-        }
-
-		GList * users = NULL;
-		users = users_service_dbus_get_user_list (service);
-		guint user_count = g_list_length(users);
-
-		if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
-			users = g_list_sort (users, (GCompareFunc)compare_users_by_username);
-		}
-
-		for (u = users; u != NULL; u = g_list_next (u)) {
-			user = u->data;
-			user->service = service;
-
-			if (user->uid == getuid()) {
-				/* Hide me from the list */
-				continue;
-			}
-          g_debug ("%li %s", user->uid, user->user_name);
-
-			if (g_strcmp0(user->user_name, "guest") == 0) {
-				/* Check to see if the guest has sessions and so therefore should
-				   get a check mark. */
-				if (user->sessions != NULL) {
-					dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, TRUE);
-				}
-				/* If we're showing user accounts, keep going through the list */
-				if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
-					continue;
-				}
-				/* If not, we can stop here */
-				break;
-			}
-
-			if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
-				mi = dbusmenu_menuitem_new ();
-				dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
-				if (user->real_name_conflict) {
-					gchar * conflictedname = g_strdup_printf("%s (%s)", user->real_name, user->user_name);
-					dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, conflictedname);
-					g_free(conflictedname);
-				} else {
-					dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, user->real_name);
-				}
-				dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_LOGGED_IN, user->sessions != NULL);
-				if (user->icon_file != NULL && user->icon_file[0] != '\0') {
-					dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, user->icon_file);
-				} else {
-					dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, USER_ITEM_ICON_DEFAULT);
-				}
-				dbusmenu_menuitem_child_append (root, mi);
-				g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_user_session), user);
-				user->menuitem = mi;
-			}
-		}
-
-		g_list_free(users);
-	}
-
-	/* If there were a bunch of items before us, we need a
-	   separator. */
-	if (can_lockscreen || can_activate) {
-		DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
-		dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-		dbusmenu_menuitem_child_append(root, separator);
-	}
-
 	/* Start going through the session based items. */
 
 	logout_mi = dbusmenu_menuitem_new();
 	if (supress_confirmations()) {
-		dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out"));
+		dbusmenu_menuitem_property_set (logout_mi,
+                                    DBUSMENU_MENUITEM_PROP_LABEL,
+                                    _("Log Out"));
 	} else {
-		dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out\342\200\246"));
+		dbusmenu_menuitem_property_set (logout_mi,
+                                    DBUSMENU_MENUITEM_PROP_LABEL,
+                                    _("Log Out\342\200\246"));
 	}
-	dbusmenu_menuitem_property_set_bool(logout_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_logout());
+	dbusmenu_menuitem_property_set_bool (logout_mi,
+                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
+                                       show_logout());
 	dbusmenu_menuitem_child_append(root, logout_mi);
-	g_signal_connect(G_OBJECT(logout_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "logout");
+	g_signal_connect( G_OBJECT(logout_mi),
+                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                    G_CALLBACK(show_dialog), "logout");
 
 	if (can_suspend && allow_suspend) {
 		suspend_mi = dbusmenu_menuitem_new();
-		dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Suspend"));
-		dbusmenu_menuitem_child_append(root, suspend_mi);
-		g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Suspend");
+		dbusmenu_menuitem_property_set (suspend_mi,
+                                    DBUSMENU_MENUITEM_PROP_LABEL,
+                                    _("Suspend"));
+		dbusmenu_menuitem_child_append (root, suspend_mi);
+		g_signal_connect( G_OBJECT(suspend_mi),
+                      DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                      G_CALLBACK(machine_sleep),
+                      "Suspend");
 	}
 
 	if (can_hibernate && allow_hibernate) {
 		hibernate_mi = dbusmenu_menuitem_new();
-		dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Hibernate"));
+		dbusmenu_menuitem_property_set (hibernate_mi,
+                                    DBUSMENU_MENUITEM_PROP_LABEL,
+                                    _("Hibernate"));
 		dbusmenu_menuitem_child_append(root, hibernate_mi);
-		g_signal_connect(G_OBJECT(hibernate_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Hibernate");
+		g_signal_connect (G_OBJECT(hibernate_mi),
+                      DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                      G_CALLBACK(machine_sleep), "Hibernate");
 	}
 
 	restart_mi = dbusmenu_menuitem_new();
-	dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_TYPE, RESTART_ITEM_TYPE);
+	dbusmenu_menuitem_property_set (restart_mi,
+                                  DBUSMENU_MENUITEM_PROP_TYPE,
+                                  RESTART_ITEM_TYPE);
 	if (supress_confirmations()) {
-		dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
+		dbusmenu_menuitem_property_set (restart_mi,
+                                    RESTART_ITEM_LABEL,
+                                    _("Restart"));
 	} else {
-		dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246"));
+		dbusmenu_menuitem_property_set (restart_mi,
+                                    RESTART_ITEM_LABEL,
+                                    _("Restart\342\200\246"));
 	}
-	dbusmenu_menuitem_property_set_bool(restart_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_restart());
+	dbusmenu_menuitem_property_set_bool (restart_mi,
+                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
+                                       show_restart());
 	dbusmenu_menuitem_child_append(root, restart_mi);
-	g_signal_connect(G_OBJECT(restart_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "restart");
+	g_signal_connect (G_OBJECT(restart_mi),
+                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                    G_CALLBACK(show_dialog), "restart");
 
 	shutdown_mi = dbusmenu_menuitem_new();
 	if (supress_confirmations()) {
-		dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down"));
+		dbusmenu_menuitem_property_set (shutdown_mi,
+                                    DBUSMENU_MENUITEM_PROP_LABEL,
+                                    _("Shut Down"));
 	} else {
-		dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down\342\200\246"));
+		dbusmenu_menuitem_property_set (shutdown_mi,
+                                    DBUSMENU_MENUITEM_PROP_LABEL,
+                                    _("Shut Down\342\200\246"));
 	}
-	dbusmenu_menuitem_property_set_bool(shutdown_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_shutdown());
-	dbusmenu_menuitem_child_append(root, shutdown_mi);
-	g_signal_connect(G_OBJECT(shutdown_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "shutdown");
+	dbusmenu_menuitem_property_set_bool (shutdown_mi,
+                                       DBUSMENU_MENUITEM_PROP_VISIBLE,
+                                       show_shutdown());
+	dbusmenu_menuitem_child_append (root, shutdown_mi);
+	g_signal_connect (G_OBJECT(shutdown_mi),
+                    DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+                    G_CALLBACK(show_dialog), "shutdown");
 
 	RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = g_new0 (RestartShutdownLogoutMenuItems, 1);
 	restart_shutdown_logout_mi->logout_mi = logout_mi;
@@ -692,61 +722,6 @@
 
 	update_menu_entries(restart_shutdown_logout_mi);
 
-	/* now add extra launchers */
-	GDir *extra_launchers_dir;
-	extra_launchers_dir = g_dir_open (EXTRA_LAUNCHER_DIR, 0, NULL);
-	if (extra_launchers_dir != NULL) {
-		GList * launchers = NULL;
-
-		/* Find all the desktop files we want to use */
-		for (;;) {
-			const gchar *extra_launcher_file;
-
-			extra_launcher_file = g_dir_read_name (extra_launchers_dir);
-			if (extra_launcher_file == NULL)
-				break;
-			if (!g_str_has_suffix (extra_launcher_file, ".desktop"))
-				continue;
-
-			gchar *full_path = g_build_filename (EXTRA_LAUNCHER_DIR, extra_launcher_file, NULL);
-			GAppInfo * appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename (full_path));
-			g_free (full_path);
-
-			launchers = g_list_prepend(launchers, appinfo);
-		}
-		g_dir_close(extra_launchers_dir);
-
-		/* Sort the desktop files based on their names */
-		launchers = g_list_sort(launchers, sort_app_infos);
-
-		/* Turn each one into a separate menu item */
-		GList * launcher = NULL;
-		gboolean sepadded = FALSE;
-		for (launcher = launchers; launcher != NULL; launcher = g_list_next(launcher)) {
-			GAppInfo * appinfo = G_APP_INFO(launcher->data);
-
-			/* Make sure we have a separator */
-			if (!sepadded) {
-				DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
-				dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
-				dbusmenu_menuitem_child_append(root, separator);
-				g_object_unref(separator);
-				sepadded = TRUE;
-			}
-
-			/* Build the item */
-			DbusmenuMenuitem * desktop_mi = dbusmenu_menuitem_new();
-			dbusmenu_menuitem_property_set(desktop_mi, DBUSMENU_MENUITEM_PROP_LABEL, g_app_info_get_name(appinfo));
-			g_signal_connect(G_OBJECT(desktop_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(desktop_activate_cb), appinfo);
-			g_object_weak_ref(G_OBJECT(desktop_mi), (GWeakNotify)g_object_unref, appinfo);
-
-			/* Put into the menu */
-			dbusmenu_menuitem_child_append(root, desktop_mi);
-		}
-
-		g_list_free(launchers);
-	}
-
 	return;
 }
 
@@ -758,7 +733,7 @@
              gpointer          user_data)
 {
 	DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data;
-	rebuild_items (root, service);
+	rebuild_user_items (root, service);
 	return;
 }
 
@@ -802,7 +777,6 @@
 			session_dbus_set_name(session_dbus, ICON_DEFAULT);
 		}
 	}
-
 	return;
 }
 
@@ -826,7 +800,7 @@
 int
 main (int argc, char ** argv)
 {
-    g_type_init();
+  g_type_init();
 
 	/* Setting up i18n and gettext.  Apparently, we need
 	   all of these. */
@@ -834,42 +808,47 @@
 	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
 	textdomain (GETTEXT_PACKAGE);
 
-	IndicatorService * service = indicator_service_new_version(INDICATOR_SESSION_DBUS_NAME,
-	                                                           INDICATOR_SESSION_DBUS_VERSION);
+	IndicatorService * service = indicator_service_new_version (INDICATOR_SESSION_DBUS_NAME,
+      		                                                    INDICATOR_SESSION_DBUS_VERSION);
 	g_signal_connect(G_OBJECT(service),
-	                 INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
-	                 G_CALLBACK(service_shutdown), NULL);
+                   INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
+                   G_CALLBACK(service_shutdown), NULL);
 
 	session_dbus = session_dbus_new();
 
 	g_idle_add(lock_screen_setup, NULL);
 
-    root_menuitem = dbusmenu_menuitem_new();
-	g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem));
-
-    dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL);
-
-    rebuild_items (root_menuitem, dbus_interface);
-
-    g_signal_connect (G_OBJECT (dbus_interface),
-                      "user-added",
-                      G_CALLBACK (user_change),
-                      root_menuitem);
-    g_signal_connect (G_OBJECT (dbus_interface),
-                      "user-deleted",
-                      G_CALLBACK (user_change),
-                      root_menuitem);
-
-	setup_restart_watch();
+  session_root_menuitem = dbusmenu_menuitem_new();
+	g_debug("Session Root ID: %d", dbusmenu_menuitem_get_id(session_root_menuitem));
+
+  dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL);
+
+  rebuild_session_items (session_root_menuitem, dbus_interface);
+
+  DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);
+  dbusmenu_server_set_root(server, session_root_menuitem);
+    
+  users_root_menuitem = dbusmenu_menuitem_new();
+  rebuild_user_items (users_root_menuitem, dbus_interface);
+  g_signal_connect (G_OBJECT (dbus_interface),
+                    "user-added",
+                    G_CALLBACK (user_change),
+                    users_root_menuitem);
+  g_signal_connect (G_OBJECT (dbus_interface),
+                    "user-removed",
+                    G_CALLBACK (user_change),
+                    users_root_menuitem);
+  
+  setup_restart_watch();
 
 	setup_up();
 
-    DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);
-    dbusmenu_server_set_root(server, root_menuitem);
-
-    mainloop = g_main_loop_new(NULL, FALSE);
-    g_main_loop_run(mainloop);
-
-    return 0;
+  DbusmenuServer * users_server = dbusmenu_server_new (INDICATOR_USERS_DBUS_OBJECT);
+  dbusmenu_server_set_root (users_server, users_root_menuitem);
+
+  mainloop = g_main_loop_new(NULL, FALSE);
+  g_main_loop_run(mainloop);
+  
+  return 0;
 }
 

=== added file 'src/user-widget.c'
--- src/user-widget.c	1970-01-01 00:00:00 +0000
+++ src/user-widget.c	2011-07-14 15:41:23 +0000
@@ -0,0 +1,341 @@
+/*
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
+
+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/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <libindicator/indicator-image-helper.h>
+#include "user-widget.h"
+#include "dbus-shared-names.h"
+
+
+typedef struct _UserWidgetPrivate UserWidgetPrivate;
+
+struct _UserWidgetPrivate
+{
+  DbusmenuMenuitem* twin_item;
+  GtkWidget* user_image;
+  GtkWidget* user_name;
+  GtkWidget* container;
+  GtkWidget* tick_icon;
+  gboolean logged_in;
+  gboolean sessions_active;
+};
+
+#define USER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USER_WIDGET_TYPE, UserWidgetPrivate))
+
+/* Prototypes */
+static void user_widget_class_init    (UserWidgetClass *klass);
+static void user_widget_init          (UserWidget *self);
+static void user_widget_dispose       (GObject *object);
+static void user_widget_finalize      (GObject *object);
+
+static void user_widget_set_twin_item (UserWidget* self,
+                                       DbusmenuMenuitem* twin_item);
+// keyevent consumers
+static gboolean user_widget_button_release_event (GtkWidget *menuitem, 
+                                                  GdkEventButton *event);
+// Dbusmenuitem properties update callback
+static void user_widget_property_update (DbusmenuMenuitem* item,
+                                         gchar* property, 
+                                         GVariant* value,
+                                         gpointer userdata);
+#if GTK_CHECK_VERSION(3, 0, 0)
+static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *image,
+                                                         cairo_t* cr,
+                                                         gpointer user_data);
+#else
+static gboolean user_widget_primitive_draw_cb (GtkWidget *image,
+                                                   GdkEventExpose *event,
+                                                   gpointer user_data);
+#endif
+
+G_DEFINE_TYPE (UserWidget, user_widget, GTK_TYPE_MENU_ITEM);
+
+static void
+user_widget_class_init (UserWidgetClass *klass)
+{
+  GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass    *widget_class = GTK_WIDGET_CLASS (klass);
+
+  widget_class->button_release_event = user_widget_button_release_event;
+  
+  g_type_class_add_private (klass, sizeof (UserWidgetPrivate));
+
+  gobject_class->dispose = user_widget_dispose;
+  gobject_class->finalize = user_widget_finalize;
+}
+
+static void
+user_widget_init (UserWidget *self)
+{
+  UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(self);
+  
+	gint padding = 0;
+	gtk_widget_style_get (GTK_WIDGET(self),
+                        "horizontal-padding",
+                        &padding,
+                        NULL);
+  
+  priv->user_image = NULL;
+  priv->user_name  = NULL;
+  priv->logged_in = FALSE;
+  priv->sessions_active = FALSE;
+  priv->container = NULL;
+  priv->tick_icon = NULL;
+  
+  // Create the UI elements.  
+  priv->user_image = gtk_image_new ();
+  
+  // Just for now set the image to the default avator image
+  GdkPixbuf* pixbuf  = NULL; 
+  GError* error = NULL;
+  pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+                                     "avatar-default",
+                                     32,
+                                     GTK_ICON_LOOKUP_FORCE_SIZE,
+                                     &error);
+  
+  if (pixbuf == NULL || error != NULL) {
+    g_warning ("Could not load the default avatar image for some reason");
+  }
+  else{
+    gtk_image_set_from_pixbuf (GTK_IMAGE(priv->user_image), pixbuf);
+    g_object_unref (pixbuf);
+  }
+
+  priv->user_name = gtk_label_new ("");
+  priv->container = gtk_hbox_new (FALSE, 0);
+  // TODO: 
+  // Delete tick icon and draw primitively.
+	priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in",
+                                                   GTK_ICON_SIZE_MENU);
+ 	gtk_misc_set_alignment(GTK_MISC(priv->tick_icon), 1.0, 0.5);
+  
+  // Pack it together
+  gtk_box_pack_start (GTK_BOX (priv->container),
+                      priv->user_image,
+                      FALSE,
+                      FALSE,
+                      0);   
+  gtk_box_pack_start (GTK_BOX (priv->container),
+                      priv->user_name,
+                      FALSE,
+                      FALSE,
+                      3);                       
+	gtk_box_pack_start (GTK_BOX(priv->container),
+                      priv->tick_icon,
+                      FALSE,
+                      FALSE, 5);
+  
+  gtk_widget_show_all (priv->container);
+  gtk_container_add (GTK_CONTAINER (self), priv->container);  
+  
+  // Fetch the drawing context.
+  #if GTK_CHECK_VERSION(3, 0, 0) 
+  g_signal_connect_after (GTK_WIDGET(self), "draw", 
+                          G_CALLBACK(user_widget_primitive_draw_cb_gtk_3),
+                          GTK_WIDGET(self));
+  #else
+  g_signal_connect_after (GTK_WIDGET(self), "expose-event", 
+                          G_CALLBACK(user_widget_primitive_draw_cb),
+                          GTK_WIDGET(self));  
+  #endif  
+}
+
+static void
+user_widget_dispose (GObject *object)
+{
+  //UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(USER_WIDGET(object)); 
+
+  G_OBJECT_CLASS (user_widget_parent_class)->dispose (object);
+}
+
+// TODO tidy up image and name
+static void
+user_widget_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (user_widget_parent_class)->finalize (object);
+}
+
+/**
+ * We override the expose method to enable primitive drawing of the 
+ * empty album art image and rounded rectangles on the album art.
+ */
+
+#if GTK_CHECK_VERSION(3, 0, 0)  
+
+// Draw the radio dot and/or green check mark
+// TODO handle drawing of green check mark
+static gboolean
+user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget,
+                                     cairo_t* cr,
+                                     gpointer user_data)
+{
+	
+  g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE);
+  UserWidget* meta = USER_WIDGET(user_data);
+  UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta);  
+
+  // Draw dot only when user is the current user.
+  if (!dbusmenu_menuitem_property_get_bool (priv->twin_item,
+                                            USER_ITEM_PROP_IS_CURRENT_USER)){
+    return FALSE;                                           
+  }
+  
+  GtkStyle *style;
+  gdouble x, y;
+  gdouble offset = 15.0;
+  
+  style = gtk_widget_get_style (widget);
+  
+  GtkAllocation allocation;
+  gtk_widget_get_allocation (widget, &allocation);
+  x = allocation.x + 13;        
+  y = offset;
+  
+  cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI);;
+  
+  cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
+                            style->fg[gtk_widget_get_state(widget)].green/65535.0,
+                            style->fg[gtk_widget_get_state(widget)].blue/65535.0);
+  cairo_fill (cr);                                             
+
+  return FALSE;  
+}
+
+// GTK 2 Expose handler
+#else
+
+// Draw the triangle if the player is running ...
+static gboolean
+user_widget_primitive_draw_cb (GtkWidget *widget,
+                               GdkEventExpose *event,
+                               gpointer user_data)
+{
+  /*
+  g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE);
+  UserWidget* meta = USER_WIDGET(user_data);
+  UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta);  
+
+  GtkStyle *style;
+  cairo_t *cr;
+  int x, y, arrow_width, arrow_height;               
+
+  gint offset = 3;
+  arrow_width = 5; 
+  arrow_height = 9;
+  
+  style = gtk_widget_get_style (widget);
+
+  cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));  
+  
+  GtkAllocation allocation;
+  gtk_widget_get_allocation (widget, &allocation);
+  x = allocation.x;
+  y = allocation.y;
+    
+  // Draw player icon  
+  if (priv->icon_buf != NULL){  
+    gdk_cairo_set_source_pixbuf (cr,
+                                 priv->icon_buf,
+                                 x + arrow_width + 1,
+                                 y + offset);
+    cairo_paint (cr);
+  }
+    
+  // Draw triangle but only if the player is running.
+  if (dbusmenu_menuitem_property_get_bool (priv->twin_item,
+                                             DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING)){
+    y += (double)arrow_height/2.0 + offset;
+    cairo_set_line_width (cr, 1.0);
+
+    cairo_move_to (cr, x, y);
+    cairo_line_to (cr, x, y + arrow_height);
+    cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0);
+    cairo_close_path (cr);
+    cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
+                              style->fg[gtk_widget_get_state(widget)].green/65535.0,
+                              style->fg[gtk_widget_get_state(widget)].blue/65535.0);
+    cairo_fill (cr);                                             
+  }
+  
+  cairo_destroy (cr);*/
+  return FALSE;  
+}
+#endif
+
+
+/* Suppress/consume keyevents */
+static gboolean
+user_widget_button_release_event (GtkWidget *menuitem, 
+                                      GdkEventButton *event)
+{
+  return FALSE;
+}
+
+static void 
+user_widget_property_update (DbusmenuMenuitem* item, gchar* property, 
+                             GVariant* value, gpointer userdata)
+{
+  g_return_if_fail (IS_USER_WIDGET (userdata)); 
+  //gtk_widget_queue_redraw (GTK_WIDGET(userdata));
+}
+
+
+static void
+user_widget_set_twin_item (UserWidget* self,
+                           DbusmenuMenuitem* twin_item)
+{
+  UserWidgetPrivate* priv = USER_WIDGET_GET_PRIVATE(self);
+  priv->twin_item = twin_item;
+  g_signal_connect( G_OBJECT(priv->twin_item), "property-changed", 
+                    G_CALLBACK(user_widget_property_update), self);
+ 
+  const gchar * icon_name = dbusmenu_menuitem_property_get (twin_item,
+                                                            USER_ITEM_PROP_ICON);
+  gtk_label_set_label (GTK_LABEL (priv->user_name),
+                       dbusmenu_menuitem_property_get (twin_item, USER_ITEM_PROP_NAME));
+
+	//if (dbusmenu_menuitem_property_get_bool (twin_item, USER_ITEM_PROP_LOGGED_IN)) {
+	//	gtk_widget_show(priv->tick_icon);
+	//} else {
+  gtk_widget_show(priv->tick_icon);
+	//}
+
+	g_debug("Using user icon for '%s' from file: %s",
+          dbusmenu_menuitem_property_get(twin_item, USER_ITEM_PROP_NAME), icon_name);
+
+}
+
+ /**
+ * transport_new:
+ * @returns: a new #UserWidget.
+ **/
+GtkWidget* 
+user_widget_new(DbusmenuMenuitem *item)
+{
+  GtkWidget* widget =  g_object_new(USER_WIDGET_TYPE, NULL);
+  user_widget_set_twin_item ( USER_WIDGET(widget), item );
+  return widget;                  
+}

=== added file 'src/user-widget.h'
--- src/user-widget.h	1970-01-01 00:00:00 +0000
+++ src/user-widget.h	2011-07-14 15:41:23 +0000
@@ -0,0 +1,54 @@
+/*
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
+
+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/>.
+*/
+#ifndef __USER_WIDGET_H__
+#define __USER_WIDGET_H__
+
+#include <gtk/gtk.h>
+#if GTK_CHECK_VERSION(3, 0, 0)
+#include <libdbusmenu-gtk3/menuitem.h>
+#else
+#include <libdbusmenu-gtk/menuitem.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define USER_WIDGET_TYPE            (user_widget_get_type ())
+#define USER_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), USER_WIDGET_TYPE, UserWidget))
+#define USER_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), USER_WIDGET_TYPE, UserWidgetClass))
+#define IS_USER_WIDGET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), USER_WIDGET_TYPE))
+#define IS_USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), USER_WIDGET_TYPE))
+#define USER_WIDGET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), USER_WIDGET_TYPE, UserWidgetClass))
+
+typedef struct _UserWidget      UserWidget;
+typedef struct _UserWidgetClass UserWidgetClass;
+
+struct _UserWidgetClass {
+  GtkMenuItemClass parent_class;
+};
+
+struct _UserWidget {
+  GtkMenuItem parent;
+};
+
+GType user_widget_get_type (void);
+GtkWidget* user_widget_new(DbusmenuMenuitem *twin_item);
+
+G_END_DECLS
+
+#endif


Follow ups