From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
Subject: Implement conditional support for libappindicator

To get better integration with Unity (and actually have nm-applet show up at
all with Unity / compiz), implement drawing the applet using libappindicator.

To play well with others, this patch actually implements libappindicator
conditionally to running configure with --enable-indicator.

=== modified file 'configure.ac'
---
 configure.ac                  |    8 
 src/Makefile.am               |    2 
 src/applet-device-bt.c        |   13 -
 src/applet-device-cdma.c      |   52 ++++
 src/applet-device-gsm.c       |   56 ++++-
 src/applet-device-wifi.c      |  327 +++++++++++++++++++++++++++++-
 src/applet-device-wimax.c     |   42 +++
 src/applet-device-wired.c     |   13 -
 src/applet.c                  |  450 +++++++++++++++++++++++++++++++++++-------
 src/applet.h                  |   19 +
 src/gconf-helpers/Makefile.am |    2 
 src/mb-menu-item.c            |    3 
 src/mobile-helpers.c          |  135 ++++++++++++
 src/mobile-helpers.h          |   11 +
 14 files changed, 1020 insertions(+), 113 deletions(-)

Index: network-manager-applet-0.9.4.1/configure.ac
===================================================================
--- network-manager-applet-0.9.4.1.orig/configure.ac	2012-03-23 15:55:33.000000000 -0700
+++ network-manager-applet-0.9.4.1/configure.ac	2012-11-21 16:19:09.071734640 -0800
@@ -170,6 +170,14 @@
 		;;
 esac
 
+AC_ARG_ENABLE([indicator],
+[  --enable-appindicator  Enables using libappindicator to draw the applet
+                          on the screen, instead of the standard status icons.],
+[
+	PKG_CHECK_MODULES(APPINDICATOR, appindicator3-0.1)
+	AC_DEFINE([ENABLE_INDICATOR], 1, [Enable using libappindicator])
+])
+
 AM_CONDITIONAL(HAVE_GBT, test x"$have_gbt" = "xyes")
 
 AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
Index: network-manager-applet-0.9.4.1/src/Makefile.am
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/Makefile.am	2012-03-13 16:03:59.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/Makefile.am	2012-11-21 16:19:09.071734640 -0800
@@ -8,6 +8,7 @@
 	$(GCONF_CFLAGS) \
 	$(GNOME_KEYRING_CFLAGS) \
 	$(NOTIFY_CFLAGS) \
+	$(APPINDICATOR_CFLAGS) \
 	-DICONDIR=\""$(datadir)/icons"\"						\
 	-DUIDIR=\""$(uidir)"\"							\
 	-DBINDIR=\""$(bindir)"\"								\
@@ -68,6 +69,7 @@
 	$(GCONF_LIBS) \
 	$(GNOME_KEYRING_LIBS) \
 	$(NOTIFY_LIBS) \
+	$(APPINDICATOR_LIBS) \
 	${top_builddir}/src/marshallers/libmarshallers.la \
 	${top_builddir}/src/utils/libutils.la \
 	${top_builddir}/src/gconf-helpers/libgconf-helpers.la \
Index: network-manager-applet-0.9.4.1/src/applet-device-bt.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet-device-bt.c	2012-03-19 11:39:48.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/applet-device-bt.c	2012-11-21 16:19:09.071734640 -0800
@@ -154,7 +154,9 @@
 
 	item = applet_menu_item_create_device_item_helper (device, applet, text);
 
+#ifndef ENABLE_INDICATOR
 	gtk_widget_set_sensitive (item, FALSE);
+#endif
 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 	gtk_widget_show (item);
 
@@ -209,15 +211,16 @@
 	}
 }
 
-static GdkPixbuf *
+static void
 bt_get_icon (NMDevice *device,
              NMDeviceState state,
              NMConnection *connection,
+             GdkPixbuf **out_pixbuf,
+             char **out_indicator_icon,
              char **tip,
              NMApplet *applet)
 {
 	NMSettingConnection *s_con;
-	GdkPixbuf *pixbuf = NULL;
 	const char *id;
 
 	id = nm_device_get_iface (NM_DEVICE (device));
@@ -240,14 +243,16 @@
 		*tip = g_strdup_printf (_("Requesting a network address for '%s'..."), id);
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
-		pixbuf = nma_icon_check_and_load ("nm-device-wwan", &applet->wwan_icon, applet);
+		*out_indicator_icon = g_strdup_printf ("nm-device-wwan");
+		*out_pixbuf = nma_icon_check_and_load ("nm-device-wwan", &applet->wwan_icon, applet);
 		*tip = g_strdup_printf (_("Mobile broadband connection '%s' active"), id);
 		break;
 	default:
 		break;
 	}
 
-	return pixbuf ? g_object_ref (pixbuf) : NULL;
+	if (out_pixbuf && *out_pixbuf)
+		g_object_ref (*out_pixbuf);
 }
 
 typedef struct {
Index: network-manager-applet-0.9.4.1/src/applet-device-cdma.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet-device-cdma.c	2012-03-19 07:53:53.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/applet-device-cdma.c	2012-11-21 16:19:09.071734640 -0800
@@ -327,6 +327,9 @@
 	char *text;
 	GtkWidget *item;
 	GSList *connections, *all, *iter;
+#ifdef ENABLE_INDICATOR
+	GtkWidget *signal_icon;
+#endif
 
 	info = g_object_get_data (G_OBJECT (device), "devinfo");
 
@@ -348,7 +351,9 @@
 	}
 
 	item = applet_menu_item_create_device_item_helper (device, applet, text);
+#ifndef ENABLE_INDICATOR
 	gtk_widget_set_sensitive (item, FALSE);
+#endif
 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 	gtk_widget_show (item);
 	g_free (text);
@@ -360,6 +365,7 @@
 		s_con = nm_connection_get_setting_connection (active);
 		g_assert (s_con);
 
+#ifndef ENABLE_INDICATOR
 		item = nm_mb_menu_item_new (nm_setting_connection_get_id (s_con),
 		                            info->quality_valid ? info->quality : 0,
 		                            info->provider_name,
@@ -368,6 +374,21 @@
 		                            cdma_state_to_mb_state (info),
 		                            info->modem_enabled,
 		                            applet);
+#else
+                text = mobile_helper_get_connection_label (nm_setting_connection_get_id (s_con),
+                                                           info->provider_name,
+                                                           cdma_act_to_mb_act (info),
+                                                           cdma_state_to_mb_state (info));
+                item = gtk_image_menu_item_new_with_label (text);
+                g_free (text);
+                text = mobile_helper_get_quality_icon (info->quality_valid ?
+                                                       info->quality : 0,
+                                                       applet);
+                signal_icon = gtk_image_new_from_icon_name (text, GTK_ICON_SIZE_LARGE_TOOLBAR);
+                g_free (text);
+                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), signal_icon);
+                gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+#endif
 		gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
 		add_connection_item (device, active, item, menu, applet);
 	}
@@ -381,6 +402,7 @@
 		}
 	} else {
 		/* Otherwise show idle registration state or disabled */
+#ifndef ENABLE_INDICATOR
 		item = nm_mb_menu_item_new (NULL,
 		                            info->quality_valid ? info->quality : 0,
 		                            info->provider_name,
@@ -389,6 +411,21 @@
 		                            cdma_state_to_mb_state (info),
 		                            info->modem_enabled,
 		                            applet);
+#else
+                text = mobile_helper_get_connection_label (NULL,
+                                                            info->provider_name,
+                                                            cdma_act_to_mb_act (info),
+                                                            cdma_state_to_mb_state (info));
+                item = gtk_image_menu_item_new_with_label (text);
+                g_free (text);
+                text = mobile_helper_get_quality_icon (info->quality_valid ?
+                                                       info->quality : 0,
+                                                       applet);
+                signal_icon = gtk_image_new_from_icon_name (text, GTK_ICON_SIZE_LARGE_TOOLBAR);
+                g_free (text);
+                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), signal_icon);
+                gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+#endif
 		gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 	}
@@ -454,15 +491,16 @@
 	check_start_polling (info);
 }
 
-static GdkPixbuf *
+static void
 cdma_get_icon (NMDevice *device,
                NMDeviceState state,
                NMConnection *connection,
+               GdkPixbuf **out_pixbuf,
+               char **out_indicator_icon,
                char **tip,
                NMApplet *applet)
 {
 	NMSettingConnection *s_con;
-	GdkPixbuf *pixbuf = NULL;
 	const char *id;
 	CdmaDeviceInfo *info;
 	gboolean mb_state;
@@ -491,11 +529,14 @@
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
 		mb_state = cdma_state_to_mb_state (info);
-		pixbuf = mobile_helper_get_status_pixbuf (info->quality,
+		*out_pixbuf = mobile_helper_get_status_pixbuf (info->quality,
 		                                          info->quality_valid,
 		                                          mb_state,
 		                                          cdma_act_to_mb_act (info),
 		                                          applet);
+		*out_indicator_icon = mobile_helper_get_quality_icon (info->quality_valid ?
+									info->quality : 0,
+									applet);
 
 		if ((mb_state != MB_STATE_UNKNOWN) && info->quality_valid) {
 			gboolean roaming = (mb_state == MB_STATE_ROAMING);
@@ -510,8 +551,6 @@
 	default:
 		break;
 	}
-
-	return pixbuf;
 }
 
 typedef struct {
@@ -877,6 +916,9 @@
 	update_registration_state (info, cdma1x_state, evdo_state);
 	info->skip_reg_poll = TRUE;
 	applet_schedule_update_icon (info->applet);
+#ifdef ENABLE_INDICATOR
+	applet_schedule_update_menu (info->applet);
+#endif /* ENABLE_INDICATOR */
 }
 
 static void
Index: network-manager-applet-0.9.4.1/src/applet-device-gsm.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet-device-gsm.c	2012-11-21 16:19:08.943734000 -0800
+++ network-manager-applet-0.9.4.1/src/applet-device-gsm.c	2012-11-21 16:19:09.071734640 -0800
@@ -42,6 +42,7 @@
 #include "applet-device-gsm.h"
 #include "utils.h"
 #include "nm-mobile-wizard.h"
+#include "mobile-helpers.h"
 #include "applet-dialogs.h"
 #include "mb-menu-item.h"
 #include "nma-marshal.h"
@@ -374,6 +375,9 @@
 	char *text;
 	GtkWidget *item;
 	GSList *connections, *all, *iter;
+#ifdef ENABLE_INDICATOR
+	GtkWidget *signal_icon;
+#endif
 
 	info = g_object_get_data (G_OBJECT (device), "devinfo");
 
@@ -395,7 +399,9 @@
 	}
 
 	item = applet_menu_item_create_device_item_helper (device, applet, text);
+#ifndef ENABLE_INDICATOR
 	gtk_widget_set_sensitive (item, FALSE);
+#endif
 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 	gtk_widget_show (item);
 	g_free (text);
@@ -407,6 +413,7 @@
 		s_con = nm_connection_get_setting_connection (active);
 		g_assert (s_con);
 
+#ifndef ENABLE_INDICATOR
 		item = nm_mb_menu_item_new (nm_setting_connection_get_id (s_con),
 		                            info->quality_valid ? info->quality : 0,
 		                            info->op_name,
@@ -415,6 +422,21 @@
 		                            gsm_state_to_mb_state (info),
 		                            info->modem_enabled,
 		                            applet);
+#else
+                text = mobile_helper_get_connection_label (nm_setting_connection_get_id (s_con),
+                                                           info->op_name,
+                                                           gsm_act_to_mb_act (info),
+                                                           gsm_state_to_mb_state (info));
+                item = gtk_image_menu_item_new_with_label (text);
+                g_free (text);
+                text = mobile_helper_get_quality_icon (info->quality_valid ?
+                                                       info->quality : 0,
+                                                       applet);
+                signal_icon = gtk_image_new_from_icon_name (text, GTK_ICON_SIZE_LARGE_TOOLBAR);
+                g_free (text);
+                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), signal_icon);
+                gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+#endif
 		gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
 		add_connection_item (device, active, item, menu, applet);
 	}
@@ -428,6 +450,7 @@
 		}
 	} else {
 		/* Otherwise show idle registration state or disabled */
+#ifndef ENABLE_INDICATOR
 		item = nm_mb_menu_item_new (NULL,
 		                            info->quality_valid ? info->quality : 0,
 		                            info->op_name,
@@ -436,6 +459,23 @@
 		                            gsm_state_to_mb_state (info),
 		                            info->modem_enabled,
 		                            applet);
+#else
+                text = mobile_helper_get_connection_label (NULL,
+                                                           info->op_name,
+                                                           gsm_act_to_mb_act (info),
+                                                           gsm_state_to_mb_state (info));
+                item = gtk_image_menu_item_new_with_label (text);
+                g_free (text);
+                text = mobile_helper_get_quality_icon (info->quality_valid ?
+                                                       info->quality : 0,
+                                                       applet);
+                signal_icon = gtk_image_new_from_icon_name (text, GTK_ICON_SIZE_LARGE_TOOLBAR);
+                g_free (text);
+                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), signal_icon);
+                gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+                gtk_widget_set_sensitive (item, FALSE);
+#endif
+
 		gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 	}
@@ -496,15 +536,16 @@
 	check_start_polling (info);
 }
 
-static GdkPixbuf *
+static void
 gsm_get_icon (NMDevice *device,
               NMDeviceState state,
               NMConnection *connection,
+              GdkPixbuf **out_pixbuf,
+              char **out_indicator_icon,
               char **tip,
               NMApplet *applet)
 {
 	NMSettingConnection *s_con;
-	GdkPixbuf *pixbuf = NULL;
 	const char *id;
 	GsmDeviceInfo *info;
 	guint32 mb_state;
@@ -533,11 +574,14 @@
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
 		mb_state = gsm_state_to_mb_state (info);
-		pixbuf = mobile_helper_get_status_pixbuf (info->quality,
+		*out_pixbuf = mobile_helper_get_status_pixbuf (info->quality,
 		                                          info->quality_valid,
 		                                          mb_state,
 		                                          gsm_act_to_mb_act (info),
 		                                          applet);
+		*out_indicator_icon = mobile_helper_get_quality_icon (info->quality_valid ?
+								info->quality : 0,
+								applet);
 
 		if ((mb_state != MB_STATE_UNKNOWN) && info->quality_valid) {
 			gboolean roaming = (mb_state == MB_STATE_ROAMING);
@@ -552,8 +596,6 @@
 	default:
 		break;
 	}
-
-	return pixbuf;
 }
 
 typedef struct {
@@ -1554,6 +1596,10 @@
 	g_free (info->op_name);
 	info->op_name = parse_op_name (info, op_name, info->op_code);
 	info->skip_reg_poll = TRUE;
+
+#ifdef ENABLE_INDICATOR
+	applet_schedule_update_menu (info->applet);
+#endif /* ENABLE_INDICATOR */
 }
 
 static void
Index: network-manager-applet-0.9.4.1/src/applet-device-wifi.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet-device-wifi.c	2012-11-21 16:19:08.971734142 -0800
+++ network-manager-applet-0.9.4.1/src/applet-device-wifi.c	2012-11-21 16:22:11.308638296 -0800
@@ -31,6 +31,7 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <atk/atk.h>
 
 #include <nm-device.h>
 #include <nm-access-point.h>
@@ -309,6 +310,135 @@
 	return is_ssid_in_list (ssid, blacklisted_ssids);
 }
 
+#ifdef ENABLE_INDICATOR
+static void
+clear_dupes_list (GSList *list)
+{
+	g_slist_foreach (list, (GFunc) g_free, NULL);
+	g_slist_free (list);
+}
+
+static gboolean
+get_ap_is_encrypted (NMAccessPoint *ap)
+{
+        guint32 ap_flags, ap_wpa, ap_rsn;
+
+        ap_flags = nm_access_point_get_flags (ap);
+        ap_wpa = nm_access_point_get_wpa_flags (ap);
+        ap_rsn = nm_access_point_get_rsn_flags (ap);
+
+        if ((ap_flags & NM_802_11_AP_FLAGS_PRIVACY) || ap_wpa || ap_rsn)
+                return TRUE;
+
+	return FALSE;
+}
+
+static void
+ap_menu_item_set_sensitive (GtkWidget *item, NMAccessPoint *ap, guint32 dev_caps)
+{
+	gboolean is_adhoc = FALSE;
+        guint32 ap_flags, ap_wpa, ap_rsn;
+
+        ap_flags = nm_access_point_get_flags (ap);
+        ap_wpa = nm_access_point_get_wpa_flags (ap);
+        ap_rsn = nm_access_point_get_rsn_flags (ap);
+
+	if (nm_access_point_get_mode (ap) == NM_802_11_MODE_ADHOC)
+		is_adhoc = TRUE;
+
+	/* Don't enable the menu item the device can't even connect to the AP */
+	if (   !nm_utils_security_valid (NMU_SEC_NONE, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)
+		&& !nm_utils_security_valid (NMU_SEC_STATIC_WEP, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)
+		&& !nm_utils_security_valid (NMU_SEC_LEAP, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)
+		&& !nm_utils_security_valid (NMU_SEC_DYNAMIC_WEP, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)
+		&& !nm_utils_security_valid (NMU_SEC_WPA_PSK, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)
+		&& !nm_utils_security_valid (NMU_SEC_WPA2_PSK, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)
+		&& !nm_utils_security_valid (NMU_SEC_WPA_ENTERPRISE, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)
+		&& !nm_utils_security_valid (NMU_SEC_WPA2_ENTERPRISE, dev_caps, TRUE, is_adhoc, ap_flags, ap_wpa, ap_rsn)) {
+		gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
+	}
+}
+
+static gchar *
+get_best_icon_name_for_ap (NMAccessPoint *ap, gboolean need_sec, gboolean encrypted)
+{
+	GString *icon_name = NULL;
+	gchar *tmp = NULL;
+	guint32 strength;
+
+	g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL);
+
+	strength = nm_access_point_get_strength (ap);
+	strength = CLAMP (strength, 0, 100);
+
+	icon_name = g_string_new ("");
+	if (strength > 80)
+                icon_name = g_string_assign (icon_name, "nm-signal-100");
+        else if (strength > 55)
+                icon_name = g_string_assign (icon_name, "nm-signal-75");
+        else if (strength > 30)
+                icon_name = g_string_assign (icon_name, "nm-signal-50");
+        else if (strength > 5)
+                icon_name = g_string_assign (icon_name, "nm-signal-25");
+        else
+                icon_name = g_string_assign (icon_name, "nm-signal-00");
+
+        if (nm_access_point_get_mode (ap) == NM_802_11_MODE_ADHOC) {
+                icon_name = g_string_assign (icon_name, "nm-adhoc");
+		goto out;
+	}
+
+	if (need_sec && encrypted)
+		icon_name = g_string_append (icon_name, "-secure");
+
+out:
+	tmp = icon_name->str;
+	g_string_free (icon_name, FALSE);
+
+	return tmp;
+}
+
+static void
+set_menu_item_accessible_desc (NMAccessPoint *ap,
+			       GtkMenuItem *item,
+			       gboolean is_encrypted)
+{
+	guint32 strength;
+	gchar *ssid = NULL;
+	GString *icon_desc = NULL;
+
+	g_return_if_fail (NM_IS_ACCESS_POINT (ap));
+
+	strength = nm_access_point_get_strength (ap);
+	strength = CLAMP (strength, 0, 100);
+
+	ssid = g_strdup (gtk_menu_item_get_label (item));
+
+	if (ssid == NULL)
+		return;
+
+	icon_desc = g_string_new ("");
+	g_string_append_printf (icon_desc, "%s: ", ssid);
+
+	if (nm_access_point_get_mode (ap) == NM_802_11_MODE_ADHOC) {
+		icon_desc = g_string_append (icon_desc, _("ad-hoc"));
+		goto out;
+	}
+
+	g_string_append_printf (icon_desc, "%d%%", strength);
+
+	if (is_encrypted) {
+		icon_desc = g_string_append (icon_desc, ", ");
+		icon_desc = g_string_append (icon_desc, _("secure."));
+	}
+
+out:
+	atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (item)), icon_desc->str);
+	g_free (ssid);
+	g_string_free (icon_desc, TRUE);
+}
+#endif
+
 static void
 clamp_ap_to_bssid (NMAccessPoint *ap, NMSettingWireless *s_wifi)
 {
@@ -517,7 +647,11 @@
 
 struct dup_data {
 	NMDevice *device;
+#ifndef ENABLE_INDICATOR
 	NMNetworkMenuItem *found;
+#else
+	GtkWidget *found;
+#endif
 	char *hash;
 };
 
@@ -533,19 +667,34 @@
 	g_return_if_fail (data);
 	g_return_if_fail (data->hash);
 
+#ifndef ENABLE_INDICATOR
 	if (data->found || !NM_IS_NETWORK_MENU_ITEM (widget))
 		return;
+#else
+	if (data->found || !GTK_IS_IMAGE_MENU_ITEM (widget))
+		return;
+#endif
 
 	device = g_object_get_data (G_OBJECT (widget), "device");
 	if (NM_DEVICE (device) != data->device)
 		return;
 
+#ifndef ENABLE_INDICATOR
 	hash = nm_network_menu_item_get_hash (NM_NETWORK_MENU_ITEM (widget));
 	if (hash && (strcmp (hash, data->hash) == 0))
 		data->found = NM_NETWORK_MENU_ITEM (widget);
+#else
+	hash = g_object_get_data (G_OBJECT (widget), "hash");
+	if (hash && (strcmp (hash, data->hash) == 0))
+		data->found = widget;
+#endif /* ENABLE_INDICATOR */
 }
 
+#ifndef ENABLE_INDICATOR
 static NMNetworkMenuItem *
+#else
+static GtkImageMenuItem *
+#endif
 create_new_ap_item (NMDeviceWifi *device,
                     NMAccessPoint *ap,
                     struct dup_data *dup_data,
@@ -554,7 +703,16 @@
 {
 	WirelessMenuItemInfo *info;
 	GSList *iter;
+#ifndef ENABLE_INDICATOR
 	NMNetworkMenuItem *item = NULL;
+#else
+	GtkWidget *item = NULL;
+	char *text, *best_icon_name;
+	const char *path;
+	GtkWidget *icon_image;
+	gboolean encrypted, ad_hoc;
+	GSList *dupes;
+#endif /* ENABLE_INDICATOR */
 	GSList *dev_connections = NULL;
 	GSList *ap_connections = NULL;
 	const GByteArray *ssid;
@@ -565,18 +723,51 @@
 	g_slist_free (dev_connections);
 	dev_connections = NULL;
 
+	ssid = nm_access_point_get_ssid (ap);
+	dev_caps = nm_device_wifi_get_capabilities (device);
+
+#ifndef ENABLE_INDICATOR
 	item = NM_NETWORK_MENU_ITEM (nm_network_menu_item_new (dup_data->hash,
 	                                                       !!g_slist_length (ap_connections)));
 	gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
 
-	ssid = nm_access_point_get_ssid (ap);
 	nm_network_menu_item_set_ssid (item, (GByteArray *) ssid);
 
-	dev_caps = nm_device_wifi_get_capabilities (device);
 	nma_icon_check_and_load ("nm-adhoc", &applet->adhoc_icon, applet);
 	nm_network_menu_item_set_detail (item, ap, applet->adhoc_icon, dev_caps);
 	nm_network_menu_item_best_strength (item, nm_access_point_get_strength (ap), applet);
 	nm_network_menu_item_add_dupe (item, ap);
+#else
+	text = nm_utils_ssid_to_utf8 (ssid);
+	if (!text) {
+		// Avoid any cases where the SSID could possibly end up undefined.
+		text = g_strdup ("<unknown>");
+	}
+	item = gtk_image_menu_item_new_with_label (text);
+	g_free (text);
+
+	encrypted = get_ap_is_encrypted (ap);
+	ad_hoc = nm_access_point_get_mode (ap) == NM_802_11_MODE_ADHOC;
+
+	best_icon_name = get_best_icon_name_for_ap (ap, TRUE, encrypted);
+	icon_image = gtk_image_new_from_icon_name (best_icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
+	g_free (best_icon_name);
+
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), icon_image);
+	gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+
+	path = nm_object_get_path (NM_OBJECT (ap));
+	dupes = g_slist_append (dupes, g_strdup (path));
+	g_object_set_data_full (G_OBJECT (item), "dupes", (gpointer) dupes, (GDestroyNotify) clear_dupes_list);
+	g_object_set_data (G_OBJECT (item), "encrypted", (gpointer) encrypted);
+	g_object_set_data (G_OBJECT (item), "ad-hoc", (gpointer) ad_hoc);
+	g_object_set_data (G_OBJECT (item), "hash", (gpointer) dup_data->hash);
+	g_object_set_data (G_OBJECT (item), "has_connections", (gpointer) !!g_slist_length (ap_connections));
+
+	set_menu_item_accessible_desc (ap, GTK_MENU_ITEM (item), encrypted);
+
+	ap_menu_item_set_sensitive (item, ap, dev_caps);
+#endif /* ENABLE_INDICATOR */
 
 	g_object_set_data (G_OBJECT (item), "device", NM_DEVICE (device));
 
@@ -634,7 +825,11 @@
 	return item;
 }
 
+#ifndef ENABLE_INDICATOR
 static NMNetworkMenuItem *
+#else
+static GtkImageMenuItem *
+#endif /* ENABLE_INDICATOR */
 get_menu_item_for_ap (NMDeviceWifi *device,
                       NMAccessPoint *ap,
                       GSList *connections,
@@ -658,14 +853,32 @@
 	 */
 	dup_data.found = NULL;
 	dup_data.hash = g_object_get_data (G_OBJECT (ap), "hash");
+#ifndef ENABLE_INDICATOR
 	g_return_val_if_fail (dup_data.hash != NULL, NULL);
+#else
+	/* heh, not much choice here, otherwise on startup we get tons of errors
+         * because g_return_val_if_fail prints assertion errors.
+         */
+	if (dup_data.hash == NULL)
+		return NULL;
+#endif
 
 	dup_data.device = NM_DEVICE (device);
 	g_slist_foreach (menu_list, find_duplicate, &dup_data);
 
 	if (dup_data.found) {
+#ifndef ENABLE_INDICATOR
 		nm_network_menu_item_best_strength (dup_data.found, nm_access_point_get_strength (ap), applet);
 		nm_network_menu_item_add_dupe (dup_data.found, ap);
+#else
+		GSList *dupes = NULL;
+		const char *path;
+
+		dupes = g_object_steal_data (G_OBJECT (dup_data.found), "dupes");
+		path = nm_object_get_path (NM_OBJECT (ap));
+		dupes = g_slist_prepend (dupes, g_strdup (path));
+		g_object_set_data_full (G_OBJECT (dup_data.found), "dupes", (gpointer) dupes, (GDestroyNotify) clear_dupes_list);
+#endif
 		return NULL;
 	}
 
@@ -675,6 +888,7 @@
 static gint
 sort_by_name (gconstpointer tmpa, gconstpointer tmpb)
 {
+#ifndef ENABLE_INDICATOR
 	NMNetworkMenuItem *a = NM_NETWORK_MENU_ITEM (tmpa);
 	NMNetworkMenuItem *b = NM_NETWORK_MENU_ITEM (tmpb);
 	const char *a_ssid, *b_ssid;
@@ -711,6 +925,44 @@
 		return -1;
 
 	return 0;
+#else
+	GtkImageMenuItem *a = GTK_IMAGE_MENU_ITEM (tmpa);
+	GtkImageMenuItem *b = GTK_IMAGE_MENU_ITEM (tmpb);
+	const char *a_ssid, *b_ssid;
+	gboolean a_adhoc, b_adhoc;
+	int i;
+
+	if (a && !b)
+		return 1;
+	else if (!a && b)
+		return -1;
+	else if (a == b)
+		return 0;
+
+	a_ssid = gtk_menu_item_get_label (GTK_MENU_ITEM (a));
+	b_ssid = gtk_menu_item_get_label (GTK_MENU_ITEM (b));
+
+	if (a_ssid && !b_ssid)
+		return 1;
+	if (b_ssid && !a_ssid)
+		return -1;
+
+	if (a_ssid && b_ssid) {
+		i = g_ascii_strcasecmp (a_ssid, b_ssid);
+		if (i != 0)
+			return i;
+	}
+
+	/* If the names are the same, sort infrastructure APs first */
+	a_adhoc = g_object_get_data (G_OBJECT (a), "ad-hoc");
+	b_adhoc = g_object_get_data (G_OBJECT (b), "ad-hoc");
+	if (a_adhoc && !b_adhoc)
+		return 1;
+	else if (!a_adhoc && b_adhoc)
+		return -1;
+
+	return 0;
+#endif /* ENABLE_INDICATOR */
 }
 
 /* Sort menu items for the top-level menu:
@@ -722,6 +974,7 @@
 static gint
 sort_toplevel (gconstpointer tmpa, gconstpointer tmpb)
 {
+#ifndef ENABLE_INDICATOR
 	NMNetworkMenuItem *a = NM_NETWORK_MENU_ITEM (tmpa);
 	NMNetworkMenuItem *b = NM_NETWORK_MENU_ITEM (tmpb);
 	gboolean a_fave, b_fave;
@@ -756,6 +1009,42 @@
 	 * both are unencrypted) just sort by name.
 	 */
 	return sort_by_name (a, b);
+#else
+	GtkImageMenuItem *a = GTK_IMAGE_MENU_ITEM (tmpa);
+	GtkImageMenuItem *b = GTK_IMAGE_MENU_ITEM (tmpb);
+	gboolean a_fave, b_fave;
+
+	if (a && !b)
+		return 1;
+	else if (!a && b)
+		return -1;
+	else if (a == b)
+		return 0;
+
+	a_fave = g_object_get_data (G_OBJECT (a), "has_connections");
+	b_fave = g_object_get_data (G_OBJECT (b), "has_connections");
+
+	/* Items with a saved connection first */
+	if (a_fave && !b_fave)
+		return -1;
+	else if (!a_fave && b_fave)
+		return 1;
+	else if (!a_fave && !b_fave) {
+		gboolean a_enc = g_object_get_data (G_OBJECT (a), "encrypted");
+		gboolean b_enc = g_object_get_data (G_OBJECT (b), "encrypted");
+
+		/* If neither item has a saved connection, sort by encryption */
+		if (a_enc && !b_enc)
+			return -1;
+		else if (!a_enc && b_enc)
+			return 1;
+	}
+
+	/* For all other cases (both have saved connections, both are encrypted, or
+	 * both are unencrypted) just sort by name.
+	 */
+	return sort_by_name (a, b);
+#endif /* ENABLE_INDICATOR */
 }
 
 static void
@@ -774,7 +1063,11 @@
 	gboolean wireless_enabled = TRUE;
 	gboolean wireless_hw_enabled = TRUE;
 	GSList *menu_items = NULL;  /* All menu items we'll be adding */
+#ifndef ENABLE_INDICATOR
 	NMNetworkMenuItem *item, *active_item = NULL;
+#else
+	GtkImageMenuItem *item, *active_item = NULL;
+#endif /* ENABLE_INDICATOR */
 	GtkWidget *widget;
 
 	wdev = NM_DEVICE_WIFI (device);
@@ -812,7 +1105,9 @@
 		if (active_ap) {
 			active_item = item = get_menu_item_for_ap (wdev, active_ap, connections, NULL, applet);
 			if (item) {
+#ifndef ENABLE_INDICATOR
 				nm_network_menu_item_set_active (item, TRUE);
+#endif
 				menu_items = g_slist_append (menu_items, item);
 
 				gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (item));
@@ -1109,6 +1404,9 @@
 	                  applet);
 	
 	queue_avail_access_point_notification (NM_DEVICE (device));
+#ifdef ENABLE_INDICATOR
+	applet_schedule_update_menu (applet);
+#endif /* ENABLE_INDICATOR */
 }
 
 static void
@@ -1126,6 +1424,9 @@
 	if (old == ap) {
 		g_object_set_data (G_OBJECT (device), ACTIVE_AP_TAG, NULL);
 		applet_schedule_update_icon (applet);
+#ifdef ENABLE_INDICATOR
+		applet_schedule_update_menu (applet);
+#endif /* ENABLE_INDICATOR */
 	}
 }
 
@@ -1272,16 +1573,17 @@
 	g_free (esc_ssid);
 }
 
-static GdkPixbuf *
+static void
 wireless_get_icon (NMDevice *device,
                    NMDeviceState state,
                    NMConnection *connection,
+                   GdkPixbuf **out_pixbuf,
+                   char **out_indicator_icon,
                    char **tip,
                    NMApplet *applet)
 {
 	NMSettingConnection *s_con;
 	NMAccessPoint *ap;
-	GdkPixbuf *pixbuf = NULL;
 	const char *id;
 	char *ssid = NULL;
 
@@ -1314,22 +1616,25 @@
 			strength = CLAMP (strength, 0, 100);
 
 			if (strength > 80)
-				pixbuf = nma_icon_check_and_load ("nm-signal-100", &applet->wireless_100_icon, applet);
+				*out_pixbuf = nma_icon_check_and_load ("nm-signal-100", &applet->wireless_100_icon, applet);
 			else if (strength > 55)
-				pixbuf = nma_icon_check_and_load ("nm-signal-75", &applet->wireless_75_icon, applet);
+				*out_pixbuf = nma_icon_check_and_load ("nm-signal-75", &applet->wireless_75_icon, applet);
 			else if (strength > 30)
-				pixbuf = nma_icon_check_and_load ("nm-signal-50", &applet->wireless_50_icon, applet);
+				*out_pixbuf = nma_icon_check_and_load ("nm-signal-50", &applet->wireless_50_icon, applet);
 			else if (strength > 5)
-				pixbuf = nma_icon_check_and_load ("nm-signal-25", &applet->wireless_25_icon, applet);
+				*out_pixbuf = nma_icon_check_and_load ("nm-signal-25", &applet->wireless_25_icon, applet);
 			else
-				pixbuf = nma_icon_check_and_load ("nm-signal-00", &applet->wireless_00_icon, applet);
+				*out_pixbuf = nma_icon_check_and_load ("nm-signal-00", &applet->wireless_00_icon, applet);
+
+			*out_indicator_icon = get_best_icon_name_for_ap (ap, FALSE, FALSE);
 
 			ssid = get_ssid_utf8 (ap);
 			*tip = g_strdup_printf (_("Wireless network connection '%s' active: %s (%d%%)"),
 			                        id, ssid, strength);
 			g_free (ssid);
 		} else {
-			pixbuf = nma_icon_check_and_load ("nm-signal-00", &applet->wireless_00_icon, applet);
+			*out_indicator_icon = g_strdup_printf ("nm-signal-00");
+			*out_pixbuf = nma_icon_check_and_load ("nm-signal-00", &applet->wireless_00_icon, applet);
 			*tip = g_strdup_printf (_("Wireless network connection '%s' active"), id);
 		}
 		break;
@@ -1337,7 +1642,8 @@
 		break;
 	}
 
-	return pixbuf ? g_object_ref (pixbuf) : NULL;
+	if (out_pixbuf && *out_pixbuf)
+		g_object_ref (*out_pixbuf);
 }
 
 static gboolean
Index: network-manager-applet-0.9.4.1/src/applet-device-wired.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet-device-wired.c	2012-11-21 16:19:08.943734000 -0800
+++ network-manager-applet-0.9.4.1/src/applet-device-wired.c	2012-11-21 16:19:09.079734683 -0800
@@ -221,7 +221,9 @@
  	if (nm_device_get_capabilities (device) & NM_DEVICE_CAP_CARRIER_DETECT)
 		carrier = nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (device));
 
+#ifndef ENABLE_INDICATOR
 	gtk_widget_set_sensitive (item, FALSE);
+#endif
 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 	gtk_widget_show (item);
 
@@ -274,15 +276,16 @@
 	}
 }
 
-static GdkPixbuf *
+static void
 wired_get_icon (NMDevice *device,
                 NMDeviceState state,
                 NMConnection *connection,
+                GdkPixbuf **out_pixbuf,
+                char **out_indicator_icon,
                 char **tip,
                 NMApplet *applet)
 {
 	NMSettingConnection *s_con;
-	GdkPixbuf *pixbuf = NULL;
 	const char *id;
 
 	id = nm_device_get_iface (NM_DEVICE (device));
@@ -305,14 +308,16 @@
 		*tip = g_strdup_printf (_("Requesting a wired network address for '%s'..."), id);
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
-		pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->wired_icon, applet);
+		*out_indicator_icon = g_strdup_printf ("nm-device-wired");
+		*out_pixbuf = nma_icon_check_and_load (*out_indicator_icon, &applet->wired_icon, applet);
 		*tip = g_strdup_printf (_("Wired network connection '%s' active"), id);
 		break;
 	default:
 		break;
 	}
 
-	return pixbuf ? g_object_ref (pixbuf) : NULL;
+	if (out_pixbuf && *out_pixbuf)
+		g_object_ref (*out_pixbuf);
 }
 
 /* PPPoE */
Index: network-manager-applet-0.9.4.1/src/applet.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet.c	2012-11-21 16:19:09.047734521 -0800
+++ network-manager-applet-0.9.4.1/src/applet.c	2012-11-21 16:19:33.259854586 -0800
@@ -499,6 +499,8 @@
                      GError *error,
                      gpointer user_data)
 {
+	NMApplet *applet = NM_APPLET (user_data);
+
 	if (error) {
 		const char *text = _("Failed to add/activate connection");
 		char *err_text = g_strdup_printf ("(%d) %s", error->code,
@@ -509,7 +511,8 @@
 		g_free (err_text);
 	}
 
-	applet_schedule_update_icon (NM_APPLET (user_data));
+	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
 }
 
 static void
@@ -543,6 +546,8 @@
 static void
 disconnect_cb (NMDevice *device, GError *error, gpointer user_data)
 {
+	NMApplet *applet = NM_APPLET (user_data);
+
 	if (error) {
 		const char *text = _("Device disconnect failed");
 		char *err_text = g_strdup_printf ("(%d) %s", error->code,
@@ -552,6 +557,9 @@
 		utils_show_error_dialog (_("Disconnect failure"), text, err_text, FALSE, NULL);
 		g_free (err_text);
 	}
+
+	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
 }
 
 void
@@ -560,7 +568,7 @@
 {
 	g_return_if_fail (NM_IS_DEVICE (device));
 
-	nm_device_disconnect (device, disconnect_cb, NULL);
+	nm_device_disconnect (device, disconnect_cb, applet);
 }
 
 static void
@@ -633,13 +641,15 @@
                                                const gchar* label,
                                                int pos)
 {
-	GtkWidget *menu_item = gtk_image_menu_item_new ();
+	GtkWidget *menu_item = NULL;
+#ifndef ENABLE_INDICATOR
 #if GTK_CHECK_VERSION(3,1,6)
         GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 #else
 	GtkWidget *box = gtk_hbox_new (FALSE, 0);
 #endif
 	GtkWidget *xlabel = NULL;
+	menu_item = gtk_image_menu_item_new ();
 
 	if (label) {
 		xlabel = gtk_label_new (NULL);
@@ -663,6 +673,9 @@
 	              "child", box,
 	              "sensitive", FALSE,
 	              NULL);
+#else
+	menu_item = gtk_separator_menu_item_new ();
+#endif
 	if (pos < 0)
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 	else
@@ -677,10 +690,13 @@
 {
 	GtkWidget *item;
 	NMSettingConnection *s_con;
+#ifndef ENABLE_INDICATOR
 	char *markup;
 	GtkWidget *label;
+#endif /* ENABLE_INDICATOR */
 
 	s_con = nm_connection_get_setting_connection (connection);
+#ifndef ENABLE_INDICATOR
 	item = gtk_image_menu_item_new_with_label ("");
 	if (add_active && (active == connection)) {
 		/* Pure evil */
@@ -693,9 +709,13 @@
 		gtk_menu_item_set_label (GTK_MENU_ITEM (item), nm_setting_connection_get_id (s_con));
 
 	gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+#else
+	item = gtk_menu_item_new_with_label (nm_setting_connection_get_id (s_con));
+#endif /* ENABLE_INDICATOR */
 	return item;
 }
 
+#ifndef ENABLE_INDICATOR
 #define TITLE_TEXT_R ((double) 0x5e / 255.0 )
 #define TITLE_TEXT_G ((double) 0x5e / 255.0 )
 #define TITLE_TEXT_B ((double) 0x5e / 255.0 )
@@ -800,6 +820,8 @@
 }
 #endif
 
+#endif /* ENABLE_INDICATOR */
+
 GtkWidget *
 applet_menu_item_create_device_item_helper (NMDevice *device,
                                             NMApplet *applet,
@@ -809,11 +831,13 @@
 
 	item = gtk_menu_item_new_with_mnemonic (text);
 	gtk_widget_set_sensitive (item, FALSE);
+#ifndef ENABLE_INDICATOR
 #if GTK_CHECK_VERSION(2,90,7)
 	g_signal_connect (item, "draw", G_CALLBACK (menu_title_item_draw), NULL);
 #else
 	g_signal_connect (item, "expose-event", G_CALLBACK (menu_title_item_expose), NULL);
 #endif
+#endif /* ENABLE_INDICATOR */
 	return item;
 }
 
@@ -860,7 +884,12 @@
 	g_return_if_fail (summary != NULL);
 	g_return_if_fail (message != NULL);
 
+#ifndef ENABLE_INDICATOR
 	if (!gtk_status_icon_is_embedded (applet->status_icon))
+#else
+	if (!gtk_status_icon_is_embedded (applet->status_icon) &&
+	    app_indicator_get_status (applet->app_indicator) == APP_INDICATOR_STATUS_PASSIVE)
+#endif /* ENABLE_INDICATOR */
 		return;
 
 	escaped = utils_escape_notify_message (message);
@@ -1144,6 +1173,7 @@
 		clear_animation_timeout (applet);
 
 	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
 }
 
 static const char *
@@ -1199,10 +1229,13 @@
 	}
 
 	applet_schedule_update_icon (info->applet);
+	applet_schedule_update_menu (info->applet);
 	g_free (info->vpn_name);
 	g_free (info);
 }
 
+static void nma_menu_disconnect_vpn_item_activate (GtkMenuItem *item, gpointer user_data);
+
 static void
 nma_menu_vpn_item_clicked (GtkMenuItem *item, gpointer user_data)
 {
@@ -1225,9 +1258,14 @@
 		return;
 	}
 
-	if (applet_get_active_for_connection (applet, connection))
+	if (applet_get_active_for_connection (applet, connection)) {
+#ifndef ENABLE_INDICATOR
 		/* Connection already active; do nothing */
+#else
+		nma_menu_disconnect_vpn_item_activate (item, applet);
+#endif /* ENABLE_INDICATOR */
 		return;
+	}
 
 	s_con = nm_connection_get_setting_connection (connection);
 	info = g_malloc0 (sizeof (VPNActivateInfo));
@@ -1620,6 +1658,8 @@
 		dclass = get_device_class (device, applet);
 		if (dclass)
 			dclass->add_menu_item (device, n_devices, active, menu, applet);
+
+		nma_menu_add_separator_item (menu);
 	}
 
  out:
@@ -1677,8 +1717,6 @@
 	GSList *list, *iter;
 	int num_vpn_active = 0;
 
-	nma_menu_add_separator_item (menu);
-
 	vpn_menu = GTK_MENU (gtk_menu_new ());
 
 	item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_VPN Connections")));
@@ -1697,13 +1735,20 @@
 		NMConnection *connection = NM_CONNECTION (iter->data);
 		NMActiveConnection *active;
 		const char *name;
+#ifndef ENABLE_INDICATOR
 		GtkWidget *image;
+#endif /* ENABLE_INDICATOR */
 		NMState state;
 
 		name = get_connection_id (connection);
 
+#ifndef ENABLE_INDICATOR
 		item = GTK_MENU_ITEM (gtk_image_menu_item_new_with_label (name));
 		gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item), TRUE);
+#else
+		item = GTK_MENU_ITEM (gtk_check_menu_item_new_with_label (name));
+		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(item), FALSE);
+#endif /* ENABLE_INDICATOR */
 
 		/* If no VPN connections are active, draw all menu items enabled. If
 		 * >= 1 VPN connections are active, only the active VPN menu item is
@@ -1722,8 +1767,12 @@
 			gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
 
 		if (active) {
+#ifndef ENABLE_INDICATOR
 			image = gtk_image_new_from_stock (GTK_STOCK_CONNECT, GTK_ICON_SIZE_MENU);
 			gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+#else
+			gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(item), TRUE);
+#endif /* ENABLE_INDICATOR */
 		}
 
 		g_object_set_data_full (G_OBJECT (item), "connection", 
@@ -1797,6 +1846,7 @@
 }
 
 
+#ifndef ENABLE_INDICATOR
 static void
 nma_set_notifications_enabled_cb (GtkWidget *widget, NMApplet *applet)
 {
@@ -1823,6 +1873,7 @@
 	                       !state,
 	                       NULL);
 }
+#endif /* ENABLE_INDICATOR */
 
 /*
  * nma_menu_show_cb
@@ -1911,7 +1962,9 @@
 	gboolean wireless_hw_enabled;
 	gboolean wwan_hw_enabled;
 	gboolean wimax_hw_enabled;
+#ifndef ENABLE_INDICATOR
 	gboolean notifications_enabled = TRUE;
+#endif /* ENABLE_INDICATOR */
 	gboolean sensitive = FALSE;
 
 	state = nm_client_get_state (applet->nm_client);
@@ -1971,6 +2024,7 @@
 	gtk_widget_set_sensitive (GTK_WIDGET (applet->wimax_enabled_item),
 	                          wimax_hw_enabled && is_permission_yes (applet, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX));
 
+#ifndef ENABLE_INDICATOR
 	/* Enabled notifications */
 	g_signal_handler_block (G_OBJECT (applet->notifications_enabled_item),
 	                        applet->notifications_enabled_toggled_id);
@@ -1982,6 +2036,7 @@
 	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (applet->notifications_enabled_item), notifications_enabled);
 	g_signal_handler_unblock (G_OBJECT (applet->notifications_enabled_item),
 	                          applet->notifications_enabled_toggled_id);
+#endif /* ENABLE_INDICATOR */
 
 	/* Don't show wifi-specific stuff if wireless is off */
 	if (state != NM_STATE_ASLEEP) {
@@ -2054,16 +2109,20 @@
  * Generate the contextual popup menu.
  *
  */
-static GtkWidget *nma_context_menu_create (NMApplet *applet)
+static GtkWidget *nma_context_menu_create (NMApplet *applet, GtkMenuShell *menu)
 {
+#ifndef ENABLE_INDICATOR
 	GtkMenuShell *menu;
 	GtkWidget *menu_item;
+#endif
 	GtkWidget *image;
 	guint id;
 
 	g_return_val_if_fail (applet != NULL, NULL);
 
+#ifndef ENABLE_INDICATOR
 	menu = GTK_MENU_SHELL (gtk_menu_new ());
+#endif
 
 	/* 'Enable Networking' item */
 	applet->networking_enabled_item = gtk_check_menu_item_new_with_mnemonic (_("Enable _Networking"));
@@ -2103,6 +2162,7 @@
 
 	nma_menu_add_separator_item (GTK_WIDGET (menu));
 
+#ifndef ENABLE_INDICATOR
 	/* Toggle notifications item */
 	applet->notifications_enabled_item = gtk_check_menu_item_new_with_mnemonic (_("Enable N_otifications"));
 	id = g_signal_connect (applet->notifications_enabled_item,
@@ -2113,6 +2173,7 @@
 	gtk_menu_shell_append (menu, applet->notifications_enabled_item);
 
 	nma_menu_add_separator_item (GTK_WIDGET (menu));
+#endif /* ENABLE_INDICATOR */
 
 	/* 'Connection Information' item */
 	applet->info_menu_item = gtk_image_menu_item_new_with_mnemonic (_("Connection _Information"));
@@ -2134,6 +2195,7 @@
 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->connections_menu_item), image);
 	gtk_menu_shell_append (menu, applet->connections_menu_item);
 
+#ifndef ENABLE_INDICATOR
 	/* Separator */
 	nma_menu_add_separator_item (GTK_WIDGET (menu));
 
@@ -2153,25 +2215,112 @@
 	image = gtk_image_new_from_stock (GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU);
 	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image);
 	gtk_menu_shell_append (menu, menu_item);
+#endif /* ENABLE_INDICATOR */
 
 	gtk_widget_show_all (GTK_WIDGET (menu));
 
 	return GTK_WIDGET (menu);
 }
 
+#ifdef ENABLE_INDICATOR
+static void
+indicator_update_menu (NMApplet *applet)
+{
+	if (!applet->in_fallback) {
+		if (applet->menu)
+			g_object_unref (applet->menu);
+
+		applet->menu = gtk_menu_new ();
+		g_object_ref_sink (G_OBJECT (applet->menu));
+		nma_menu_show_cb (applet->menu, applet);
+		nma_menu_add_separator_item (applet->menu);
+		applet->menu = nma_context_menu_create (applet, GTK_MENU_SHELL(applet->menu));
+
+		app_indicator_set_menu (applet->app_indicator, GTK_MENU (applet->menu));
+
+		nma_context_menu_update (applet);
+	}
+
+	applet->update_menu_id = 0;
+}
+
+static gboolean
+applet_update_indicator_menu (gpointer user_data)
+{
+	NMApplet *applet = NM_APPLET (user_data);
+
+	indicator_update_menu (applet);
+
+	return FALSE;
+}
+
+void
+applet_schedule_update_menu (NMApplet *applet)
+{
+	if (!applet->update_menu_id)
+		applet->update_menu_id = g_idle_add (applet_update_indicator_menu, applet);
+}
+
+static void
+new_connection_cb (NMRemoteSettings *settings, NMRemoteConnection *connection, gpointer user_data)
+{
+	NMApplet *applet = NM_APPLET (user_data);
+
+	//if (nm_connection_is_type (NM_CONNECTION (connection), NM_SETTING_VPN_SETTING_NAME))
+		applet_schedule_update_menu (applet);
+}
+#endif /* ENABLE_INDICATOR */
+
 
 /*****************************************************************************/
 
 static void
-foo_set_icon (NMApplet *applet, GdkPixbuf *pixbuf, guint32 layer)
+foo_set_icon (NMApplet *applet, guint32 layer, GdkPixbuf *pixbuf, char *icon_name, char *new_tip)
 {
+	GString *tip = NULL;
 	int i;
 
-	if (layer > ICON_LAYER_MAX) {
-		g_warning ("Tried to icon to invalid layer %d", layer);
-		return;
+	switch (layer) {
+		case ICON_LAYER_LINK:
+			if (new_tip == NULL)
+				new_tip = g_strdup (_("No network connection"));
+			tip = g_string_new (new_tip);
+			break;
+		case ICON_LAYER_VPN:
+			tip = g_string_new (applet->tip);
+
+			if (new_tip)
+				g_string_append_printf (tip, "%s%s", tip->len ? "\n" : "", new_tip);
+			break;
+		default:
+			tip = g_string_new ("");
+			if (layer > ICON_LAYER_MAX) {
+				g_string_free (tip, TRUE);
+				g_warning ("Tried to icon to invalid layer %d", layer);
+				return;
+			}
+			break;
 	}
 
+	if (tip->len) {
+		g_free (applet->tip);
+		applet->tip = tip->str;
+	}
+
+	g_free (new_tip);
+	g_string_free (tip, FALSE);
+
+#ifdef ENABLE_INDICATOR
+	if (icon_name == NULL && layer == ICON_LAYER_LINK) {
+		icon_name = g_strdup ("nm-no-connection");
+	}
+
+	if (icon_name != NULL &&
+	    g_strcmp0 (app_indicator_get_icon (applet->app_indicator), icon_name) != 0) {
+		app_indicator_set_icon_full (applet->app_indicator, icon_name, applet->tip);
+	}
+#endif /* ENABLE_INDICATOR */
+
 	/* Ignore setting of the same icon as is already displayed */
 	if (applet->icon_layers[layer] == pixbuf)
 		return;
@@ -2205,8 +2354,13 @@
 
 	gtk_status_icon_set_from_pixbuf (applet->status_icon, pixbuf);
 	g_object_unref (pixbuf);
-}
+#if GTK_CHECK_VERSION(2, 15, 0)
+	gtk_status_icon_set_tooltip_text (applet->status_icon, applet->tip);
+#else
+	gtk_status_icon_set_tooltip (applet->status_icon, applet->tip);
+#endif
 
+}
 
 NMRemoteConnection *
 applet_get_exported_connection_for_device (NMDevice *device, NMApplet *applet)
@@ -2393,6 +2547,7 @@
 	applet_common_device_state_changed (device, new_state, old_state, reason, applet);
 
 	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
 }
 
 static void
@@ -2448,8 +2603,20 @@
 	}
 
 	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
 }
 
+#ifdef ENABLE_INDICATOR
+static void
+foo_device_removed_cb (NMClient *client, NMDevice *device, gpointer user_data)
+{
+	NMApplet *applet = NM_APPLET (user_data);
+
+	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
+}
+#endif
+
 static void
 foo_manager_running_cb (NMClient *client,
                         GParamSpec *pspec,
@@ -2465,6 +2632,7 @@
 	}
 
 	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
 }
 
 #define VPN_STATE_ID_TAG "vpn-state-id"
@@ -2494,6 +2662,7 @@
 	}
 
 	applet_schedule_update_icon (applet);
+	applet_schedule_update_menu (applet);
 }
 
 static void
@@ -2526,6 +2695,9 @@
 	return FALSE;
 }
 
+static gboolean setup_widgets (NMApplet *applet);
+static void nma_icons_init (NMApplet *applet);
+
 static void
 foo_client_setup (NMApplet *applet)
 {
@@ -2542,6 +2714,11 @@
 	g_signal_connect (applet->nm_client, "device-added",
 	                  G_CALLBACK (foo_device_added_cb),
 	                  applet);
+#ifdef ENABLE_INDICATOR
+	g_signal_connect (applet->nm_client, "device-removed",
+	                  G_CALLBACK (foo_device_removed_cb),
+	                  applet);
+#endif /* ENABLE_INDICATOR */
 	g_signal_connect (applet->nm_client, "notify::manager-running",
 	                  G_CALLBACK (foo_manager_running_cb),
 	                  applet);
@@ -2561,10 +2738,12 @@
 	applet_schedule_update_icon (applet);
 }
 
-static GdkPixbuf *
-applet_common_get_device_icon (NMDeviceState state, NMApplet *applet)
+static void
+applet_common_get_device_icon (NMDeviceState state,
+				GdkPixbuf **out_pixbuf,
+				char **out_indicator_icon,
+				NMApplet *applet)
 {
-	GdkPixbuf *pixbuf = NULL;
 	int stage = -1;
 
 	switch (state) {
@@ -2583,25 +2762,32 @@
 	}
 
 	if (stage >= 0) {
-		int i, j;
-
-		for (i = 0; i < NUM_CONNECTING_STAGES; i++) {
-			for (j = 0; j < NUM_CONNECTING_FRAMES; j++) {
-				char *name;
-
-				name = g_strdup_printf ("nm-stage%02d-connecting%02d", i+1, j+1);
-				nma_icon_check_and_load (name, &applet->network_connecting_icons[i][j], applet);
-				g_free (name);
+		/* Don't overwrite pixbufs or names given by specific device classes */
+		if (out_pixbuf && !*out_pixbuf) {
+			int i, j;
+			for (i = 0; i < NUM_CONNECTING_STAGES; i++) {
+				for (j = 0; j < NUM_CONNECTING_FRAMES; j++) {
+					char *name;
+
+					name = g_strdup_printf ("nm-stage%02d-connecting%02d", i+1, j+1);
+					nma_icon_check_and_load (name, &applet->network_connecting_icons[i][j], applet);
+					g_free (name);
+				}
 			}
+			*out_pixbuf = applet->network_connecting_icons[stage][applet->animation_step];
+			if (out_pixbuf && *out_pixbuf)
+				g_object_ref (*out_pixbuf);
+		}
+		if (out_indicator_icon && !*out_indicator_icon) {
+			*out_indicator_icon = g_strdup_printf ("nm-stage%02d-connecting%02d",
+								stage + 1,
+								applet->animation_step + 1);
 		}
 
-		pixbuf = applet->network_connecting_icons[stage][applet->animation_step];
 		applet->animation_step++;
 		if (applet->animation_step >= NUM_CONNECTING_FRAMES)
 			applet->animation_step = 0;
 	}
-
-	return pixbuf;
 }
 
 static char *
@@ -2640,12 +2826,14 @@
 	return tip;
 }
 
-static GdkPixbuf *
-applet_get_device_icon_for_state (NMApplet *applet, char **tip)
+static void
+applet_get_device_icon_for_state (NMApplet *applet,
+                                  GdkPixbuf **out_pixbuf,
+                                  char **out_indicator_icon,
+                                  char **out_tip)
 {
 	NMActiveConnection *active;
 	NMDevice *device = NULL;
-	GdkPixbuf *pixbuf = NULL;
 	NMDeviceState state = NM_DEVICE_STATE_UNKNOWN;
 	NMADeviceClass *dclass;
 
@@ -2670,19 +2858,13 @@
 
 		connection = applet_find_active_connection_for_device (device, applet, NULL);
 		/* device class returns a referenced pixbuf */
-		pixbuf = dclass->get_icon (device, state, connection, tip, applet);
-		if (!*tip)
-			*tip = get_tip_for_device_state (device, state, connection);
+		dclass->get_icon (device, state, connection, out_pixbuf, out_indicator_icon, out_tip, applet);
+		if (out_tip && !*out_tip)
+			*out_tip = get_tip_for_device_state (device, state, connection);
 	}
 
 out:
-	if (!pixbuf) {
-		pixbuf = applet_common_get_device_icon (state, applet);
-		/* reference the pixbuf to match the device class' get_icon() function behavior */
-		if (pixbuf)
-			g_object_ref (pixbuf);
-	}
-	return pixbuf;
+	applet_common_get_device_icon (state, out_pixbuf, out_indicator_icon, applet);
 }
 
 static char *
@@ -2738,7 +2920,7 @@
 	NMApplet *applet = NM_APPLET (user_data);
 	GdkPixbuf *pixbuf = NULL;
 	NMState state;
-	char *dev_tip = NULL, *vpn_tip = NULL;
+	char *dev_tip = NULL, *vpn_tip = NULL, *icon_name = NULL;
 	NMVPNConnectionState vpn_state = NM_VPN_SERVICE_STATE_UNKNOWN;
 	gboolean nm_running;
 	NMActiveConnection *active_vpn = NULL;
@@ -2753,36 +2935,53 @@
 	if (!nm_running)
 		state = NM_STATE_UNKNOWN;
 
+#ifdef ENABLE_INDICATOR
+	if (nm_running)
+		app_indicator_set_status (applet->app_indicator, APP_INDICATOR_STATUS_ACTIVE);
+	else
+		app_indicator_set_status (applet->app_indicator, APP_INDICATOR_STATUS_PASSIVE);
+#endif
+
 	switch (state) {
 	case NM_STATE_UNKNOWN:
 	case NM_STATE_ASLEEP:
-		pixbuf = nma_icon_check_and_load ("nm-no-connection", &applet->no_connection_icon, applet);
+		icon_name = g_strdup ("nm-no-connection");
+		pixbuf = nma_icon_check_and_load (icon_name, &applet->no_connection_icon, applet);
 		g_object_ref (pixbuf);
 		dev_tip = g_strdup (_("Networking disabled"));
 		break;
 	case NM_STATE_DISCONNECTED:
-		pixbuf = nma_icon_check_and_load ("nm-no-connection", &applet->no_connection_icon, applet);
+		icon_name = g_strdup ("nm-no-connection");
+		pixbuf = nma_icon_check_and_load (icon_name, &applet->no_connection_icon, applet);
 		g_object_ref (pixbuf);
 		dev_tip = g_strdup (_("No network connection"));
 		break;
 	default:
-		pixbuf = applet_get_device_icon_for_state (applet, &dev_tip);
+		applet_get_device_icon_for_state (applet, &pixbuf, &icon_name, &dev_tip);
 		break;
 	}
 
-	foo_set_icon (applet, pixbuf, ICON_LAYER_LINK);
+	foo_set_icon (applet, ICON_LAYER_LINK, pixbuf, icon_name, dev_tip);
 	if (pixbuf)
 		g_object_unref (pixbuf);
+	if (icon_name)
+		g_free (icon_name);
 
 	/* VPN state next */
 	pixbuf = NULL;
+	icon_name = NULL;
 	active_vpn = applet_get_first_active_vpn_connection (applet, &vpn_state);
 	if (active_vpn) {
 		int i;
 
 		switch (vpn_state) {
 		case NM_VPN_CONNECTION_STATE_ACTIVATED:
-			pixbuf = nma_icon_check_and_load ("nm-vpn-active-lock", &applet->vpn_lock_icon, applet);
+#ifndef ENABLE_INDICATOR
+			icon_name = g_strdup_printf ("nm-vpn-active-lock");
+#else
+			icon_name = g_strdup_printf ("%s-secure", app_indicator_get_icon (applet->app_indicator));
+#endif /* ENABLE_INDICATOR */
+			pixbuf = nma_icon_check_and_load (icon_name, &applet->vpn_lock_icon, applet);
 			break;
 		case NM_VPN_CONNECTION_STATE_PREPARE:
 		case NM_VPN_CONNECTION_STATE_NEED_AUTH:
@@ -2797,6 +2996,9 @@
 			}
 
 			pixbuf = applet->vpn_connecting_icons[applet->animation_step];
+#ifdef ENABLE_INDICATOR
+			icon_name = g_strdup_printf ("nm-vpn-connecting%02d", applet->animation_step+1);
+#endif
 			applet->animation_step++;
 			if (applet->animation_step >= NUM_VPN_CONNECTING_FRAMES)
 				applet->animation_step = 0;
@@ -2807,28 +3009,9 @@
 
 		vpn_tip = get_tip_for_vpn (active_vpn, vpn_state, applet);
 	}
-	foo_set_icon (applet, pixbuf, ICON_LAYER_VPN);
-
-	g_free (applet->tip);
-	applet->tip = NULL;
-
-	if (dev_tip || vpn_tip) {
-		GString *tip;
-
-		tip = g_string_new (dev_tip);
-
-		if (vpn_tip)
-			g_string_append_printf (tip, "%s%s", tip->len ? "\n" : "", vpn_tip);
-
-		if (tip->len)
-			applet->tip = tip->str;
-
-		g_free (vpn_tip);
-		g_free (dev_tip);
-		g_string_free (tip, FALSE);
-	}
-
-	gtk_status_icon_set_tooltip_text (applet->status_icon, applet->tip);
+	foo_set_icon (applet, ICON_LAYER_VPN, pixbuf, icon_name, vpn_tip);
+	if (icon_name)
+		g_free (icon_name);
 
 	return FALSE;
 }
@@ -3311,18 +3494,95 @@
 	 * of the notification. 
 	 */
 
+	/* Kill the old menu */
+	if (applet->context_menu)
+		g_object_unref (applet->context_menu);
+
+	/* And make a fresh new one */
+	applet->context_menu = gtk_menu_new ();
+	g_object_ref_sink (G_OBJECT (applet->context_menu));
+	applet->context_menu = nma_context_menu_create (applet, GTK_MENU_SHELL (applet->context_menu));
 	nma_context_menu_update (applet);
 	gtk_menu_popup (GTK_MENU (applet->context_menu), NULL, NULL,
 			gtk_status_icon_position_menu, icon,
 			button, activate_time);
 }
 
+#ifdef ENABLE_INDICATOR
+static GtkStatusIcon *
+indicator_fallback (AppIndicator *indicator)
+{
+	NMApplet *applet;
+
+	applet = NM_APPLET(g_object_get_data (G_OBJECT (indicator), "applet"));
+	g_return_val_if_fail (NM_IS_APPLET (applet), NULL);
+	g_return_val_if_fail (applet->status_icon, NULL);
+
+	g_message ("using fallback from indicator to GtkStatusIcon");
+	gtk_status_icon_set_visible (applet->status_icon, TRUE);
+
+	applet->in_fallback = TRUE;
+
+	return applet->status_icon;
+}
+
+static void
+indicator_unfallback (AppIndicator *indicator, GtkStatusIcon *status_icon)
+{
+	NMApplet *applet;
+
+	applet = NM_APPLET(g_object_get_data (G_OBJECT (indicator), "applet"));
+	g_return_if_fail (NM_IS_APPLET (applet));
+	g_return_if_fail (applet->status_icon);
+
+	g_message ("moving back from GtkStatusIcon to indicator");
+	gtk_status_icon_set_visible (applet->status_icon, FALSE);
+
+	applet->in_fallback = FALSE;
+}
+
 static gboolean
-setup_widgets (NMApplet *applet)
+setup_indicator_menu (NMApplet *applet)
+{
+	g_return_val_if_fail (NM_IS_APPLET (applet), FALSE);
+
+	applet->in_fallback = FALSE;
+
+	applet->app_indicator = app_indicator_new
+				("nm-applet", "nm-no-connection",
+				 APP_INDICATOR_CATEGORY_SYSTEM_SERVICES);
+
+	app_indicator_set_title(applet->app_indicator, _("Network"));
+
+	g_object_set_data (G_OBJECT (applet->app_indicator), "applet", (gpointer) applet);
+
+	APP_INDICATOR_GET_CLASS(applet->app_indicator)->fallback = indicator_fallback;
+	APP_INDICATOR_GET_CLASS(applet->app_indicator)->unfallback = indicator_unfallback;
+
+	applet->menu = gtk_menu_new ();
+
+	g_object_ref_sink (G_OBJECT (applet->menu));
+
+	applet->menu = nma_context_menu_create (applet, GTK_MENU_SHELL(applet->menu));
+	nma_context_menu_update(applet);
+
+	app_indicator_set_menu(applet->app_indicator, GTK_MENU(applet->menu));
+
+	return TRUE;
+}
+#endif /* ENABLE_INDICATOR */
+
+static gboolean
+setup_statusicon_menu (NMApplet *applet)
 {
 	g_return_val_if_fail (NM_IS_APPLET (applet), FALSE);
 
 	applet->status_icon = gtk_status_icon_new ();
+
+#ifdef ENABLE_INDICATOR
+	gtk_status_icon_set_visible (applet->status_icon, FALSE);
+#endif
+
 	if (!applet->status_icon)
 		return FALSE;
 	if (shell_debug)
@@ -3337,11 +3597,34 @@
 	g_signal_connect (applet->status_icon, "popup-menu",
 			  G_CALLBACK (status_icon_popup_menu_cb), applet);
 
-	applet->context_menu = nma_context_menu_create (applet);
-	if (!applet->context_menu)
-		return FALSE;
+	applet->context_menu = gtk_menu_new ();
+	applet->context_menu = nma_context_menu_create (applet, GTK_MENU_SHELL (applet->context_menu));
+	g_object_ref_sink (G_OBJECT (applet->context_menu));
+ 	if (!applet->context_menu)
+ 		return FALSE;
 
-	return TRUE;
+ 	return TRUE;
+}
+
+static gboolean
+setup_widgets (NMApplet *applet)
+{
+	gboolean success = FALSE;
+	gboolean indicator_success = FALSE;
+
+	g_return_val_if_fail (NM_IS_APPLET (applet), FALSE);
+
+	success = setup_statusicon_menu (applet);
+
+#ifdef ENABLE_INDICATOR
+	indicator_success = setup_indicator_menu (applet);
+#endif
+
+#ifndef ENABLE_INDICATOR
+	return success;
+#else
+	return success || indicator_success;
+#endif
 }
 
 static void
@@ -3537,6 +3820,8 @@
 	                      GCONF_CLIENT_PRELOAD_ONELEVEL,
 	                      NULL);
 
+	foo_client_setup (applet);
+
 	/* Load pixmaps and create applet widgets */
 	if (!setup_widgets (applet))
 		goto error;
@@ -3555,6 +3840,13 @@
 	/* Move user connections to the system */
 	nm_gconf_move_connections_to_system (import_cb, applet);
 
+#ifdef ENABLE_INDICATOR
+	/* Watch for new connections */
+	g_signal_connect (applet->settings, "new-connection",
+	                  G_CALLBACK (new_connection_cb),
+	                  applet);
+#endif /* ENABLE_INDICATOR */
+
 	applet->agent = applet_agent_new ();
 	g_assert (applet->agent);
 	g_signal_connect (applet->agent, APPLET_AGENT_GET_SECRETS,
@@ -3583,8 +3875,6 @@
 	applet->wimax_class = applet_device_wimax_get_class (applet);
 	g_assert (applet->wimax_class);
 
-	foo_client_setup (applet);
-
 	/* Track embedding to help debug issues where user has removed the
 	 * notification area applet from the panel, and thus nm-applet too.
 	 */
@@ -3630,6 +3920,11 @@
 	if (applet->update_icon_id)
 		g_source_remove (applet->update_icon_id);
 
+#ifdef ENABLE_INDICATOR
+	if (applet->update_menu_id)
+		g_source_remove (applet->update_menu_id);
+#endif /* ENABLE_INDICATOR */
+
 	if (applet->menu)
 		g_object_unref (applet->menu);
 	nma_icons_free (applet);
@@ -3657,6 +3952,11 @@
 	if (applet->status_icon)
 		g_object_unref (applet->status_icon);
 
+#ifdef ENABLE_INDICATOR
+	if (applet->app_indicator)
+		g_object_unref (applet->app_indicator);
+#endif
+
 	if (applet->nm_client)
 		g_object_unref (applet->nm_client);
 
Index: network-manager-applet-0.9.4.1/src/applet.h
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet.h	2012-11-21 16:19:08.971734142 -0800
+++ network-manager-applet-0.9.4.1/src/applet.h	2012-11-21 16:19:33.239854478 -0800
@@ -38,6 +38,10 @@
 
 #include <libnotify/notify.h>
 
+#if ENABLE_INDICATOR
+#include <libappindicator/app-indicator.h>
+#endif
+
 #include <nm-connection.h>
 #include <nm-client.h>
 #include <nm-access-point.h>
@@ -148,6 +152,11 @@
 	guint			animation_id;
 
 	/* Direct UI elements */
+#if ENABLE_INDICATOR
+	AppIndicator *	app_indicator;
+	guint		update_menu_id;
+	gboolean	in_fallback;
+#endif
 	GtkStatusIcon * status_icon;
 	int             icon_size;
 
@@ -234,13 +243,15 @@
 	                                        NMDeviceStateReason reason,
 	                                        NMApplet *applet);
 
-	/* Device class is expected to return a *referenced* pixbuf, which will
+	/* Device class is expected to pass a *referenced* pixbuf, which will
 	 * be unrefed by the icon code.  This allows the device class to create
 	 * a composited pixbuf if necessary and pass the reference to the caller.
 	 */
-	GdkPixbuf *    (*get_icon)             (NMDevice *device,
+	void           (*get_icon)             (NMDevice *device,
 	                                        NMDeviceState state,
 	                                        NMConnection *connection,
+	                                        GdkPixbuf **out_pixbuf,
+	                                        char **out_indicator_icon,
 	                                        char **tip,
 	                                        NMApplet *applet);
 
@@ -255,6 +266,10 @@
 
 void applet_schedule_update_icon (NMApplet *applet);
 
+#if ENABLE_INDICATOR
+void applet_schedule_update_menu (NMApplet *applet);
+#endif /* ENABLE_INDICATOR */
+
 NMRemoteSettings *applet_get_settings (NMApplet *applet);
 
 GSList *applet_get_all_connections (NMApplet *applet);
Index: network-manager-applet-0.9.4.1/src/mobile-helpers.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/mobile-helpers.c	2012-03-19 11:41:12.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/mobile-helpers.c	2012-11-21 16:19:09.079734683 -0800
@@ -21,6 +21,7 @@
  */
 
 #include "mobile-helpers.h"
+#include <glib/gi18n.h>
 
 GdkPixbuf *
 mobile_helper_get_status_pixbuf (guint32 quality,
@@ -35,7 +36,11 @@
 
 	if (!quality_valid)
 		quality = 0;
+#ifndef ENABLE_INDICATOR
 	qual_pixbuf = mobile_helper_get_quality_icon (quality, applet);
+#else
+	qual_pixbuf = wwan_pixbuf;
+#endif
 
 	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
 	                         TRUE,
@@ -83,9 +88,14 @@
 	return pixbuf;
 }
 
+#ifndef ENABLE_INDICATOR
 GdkPixbuf *
+#else
+char *
+#endif
 mobile_helper_get_quality_icon (guint32 quality, NMApplet *applet)
 {
+#ifndef ENABLE_INDICATOR
 	if (quality > 80)
 		return nma_icon_check_and_load ("nm-signal-100", &applet->wireless_100_icon, applet);
 	else if (quality > 55)
@@ -96,7 +106,132 @@
 		return nma_icon_check_and_load ("nm-signal-25", &applet->wireless_25_icon, applet);
 
 	return nma_icon_check_and_load ("nm-signal-00", &applet->wireless_00_icon, applet);
+#else
+	char *icon_name;
+
+	if (quality > 80)
+		icon_name = g_strdup_printf ("gsm-3g-full");
+	else if (quality > 55)
+		icon_name = g_strdup_printf ("gsm-3g-high");
+	else if (quality > 30)
+		icon_name = g_strdup_printf ("gsm-3g-medium");
+	else if (quality > 5)
+		icon_name = g_strdup_printf ("gsm-3g-low");
+	else
+		icon_name = g_strdup_printf ("gsm-3g-none");
+
+	return icon_name;
+#endif
+}
+
+#ifdef ENABLE_INDICATOR
+static const char *
+get_tech_name (guint32 tech)
+{
+        switch (tech) {
+        case MB_TECH_1XRTT:
+                return _("CDMA");
+        case MB_TECH_EVDO_REV0:
+        case MB_TECH_EVDO_REVA:
+                return _("EVDO");
+        case MB_TECH_GSM:
+                return _("GSM");
+        case MB_TECH_GPRS:
+                return _("GPRS");
+        case MB_TECH_EDGE:
+                return _("EDGE");
+        case MB_TECH_UMTS:
+                return _("UMTS");
+        case MB_TECH_HSDPA:
+                return _("HSDPA");
+        case MB_TECH_HSUPA:
+                return _("HSUPA");
+        case MB_TECH_HSPA:
+                return _("HSPA");
+        default:
+                break;
+        }
+        return NULL;
+}
+
+char *
+mobile_helper_get_connection_label (const char *connection_name,
+				    const char *provider,
+				    guint32 technology,
+				    guint32 state)
+{
+	const char *tech_name;
+	char *desc_string;
+
+        /* Construct the description string */
+        tech_name = get_tech_name (technology);
+        switch (state) {
+        default:
+        case MB_STATE_UNKNOWN:
+                desc_string = g_strdup (_("not enabled"));
+                break;
+        case MB_STATE_IDLE:
+                if (connection_name)
+                        desc_string = g_strdup (connection_name);
+                else
+                        desc_string = g_strdup (_("not registered"));
+                break;
+        case MB_STATE_HOME:
+                if (connection_name) {
+                        if (provider && tech_name)
+                                desc_string = g_strdup_printf ("%s (%s %s)", connection_name, provider, tech_name);
+                        else if (provider || tech_name)
+                                desc_string = g_strdup_printf ("%s (%s)", connection_name, provider ? provider : tech_name);
+                        else
+                                desc_string = g_strdup_printf ("%s", connection_name);
+                } else {
+                        if (provider) {
+                                if (tech_name)
+                                        desc_string = g_strdup_printf ("%s %s", provider, tech_name);
+                                else
+                                        desc_string = g_strdup_printf ("%s", provider);
+                        } else {
+                                if (tech_name)
+                                        desc_string = g_strdup_printf (_("Home network (%s)"), tech_name);
+                                else
+                                        desc_string = g_strdup_printf (_("Home network"));
+                        }
+                }
+                break;
+        case MB_STATE_SEARCHING:
+                if (connection_name)
+                        desc_string = g_strdup (connection_name);
+                else
+                        desc_string = g_strdup (_("searching"));
+                break;
+        case MB_STATE_DENIED:
+                desc_string = g_strdup (_("registration denied"));
+                break;
+        case MB_STATE_ROAMING:
+                if (connection_name) {
+                        if (tech_name)
+                                desc_string = g_strdup_printf (_("%s (%s roaming)"), connection_name, tech_name);
+                        else
+                                desc_string = g_strdup_printf (_("%s (roaming)"), connection_name);
+                } else {
+                        if (provider) {
+                                if (tech_name)
+                                        desc_string = g_strdup_printf (_("%s (%s roaming)"), provider, tech_name);
+                                else
+                                        desc_string = g_strdup_printf (_("%s (roaming)"), provider);
+                        } else {
+                                if (tech_name)
+                                        desc_string = g_strdup_printf (_("Roaming network (%s)"), tech_name);
+                                else
+                                        desc_string = g_strdup_printf (_("Roaming network"));
+                        }
+                }
+                break;
+        }
+
+	return desc_string;
 }
+#endif
 
 GdkPixbuf *
 mobile_helper_get_tech_icon (guint32 tech, NMApplet *applet)
Index: network-manager-applet-0.9.4.1/src/mobile-helpers.h
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/mobile-helpers.h	2012-03-13 16:04:00.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/mobile-helpers.h	2012-11-21 16:19:09.079734683 -0800
@@ -56,9 +56,20 @@
                                             guint32 access_tech,
                                             NMApplet *applet);
 
+#ifndef ENABLE_INDICATOR
 GdkPixbuf *mobile_helper_get_quality_icon (guint32 quality, NMApplet *applet);
+#else
+char *mobile_helper_get_quality_icon (guint32 quality, NMApplet *applet);
+#endif
 
 GdkPixbuf *mobile_helper_get_tech_icon (guint32 tech, NMApplet *applet);
 
+#ifdef ENABLE_INDICATOR
+char *mobile_helper_get_connection_label (const char *connection_name,
+					  const char *provider,
+					  guint32 technology,
+					  guint32 state);
+#endif
+
 #endif  /* APPLET_MOBILE_HELPERS_H */
 
Index: network-manager-applet-0.9.4.1/src/mb-menu-item.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/mb-menu-item.c	2012-03-20 13:32:44.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/mb-menu-item.c	2012-11-21 16:19:09.079734683 -0800
@@ -180,11 +180,14 @@
 		gtk_label_set_text (GTK_LABEL (priv->desc), priv->desc_string);
 	}
 
+/* Disabling this for indicators only because it won't build otherwise. */
+#ifndef ENABLE_INDICATOR
 	/* And the strength icon, if we have strength information at all */
 	if (enabled && strength) {
 		gtk_image_set_from_pixbuf (GTK_IMAGE (priv->strength),
 		                           mobile_helper_get_quality_icon (strength, applet));
 	}
+#endif
 
 	return GTK_WIDGET (item);
 }
Index: network-manager-applet-0.9.4.1/src/gconf-helpers/Makefile.am
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/gconf-helpers/Makefile.am	2012-03-13 16:03:59.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/gconf-helpers/Makefile.am	2012-11-21 16:19:09.083734694 -0800
@@ -16,6 +16,7 @@
 	-I$(top_srcdir)/src/utils \
 	$(GTK_CFLAGS) \
 	$(NMA_CFLAGS) \
+	$(APPINDICATOR_CFLAGS) \
 	$(GCONF_CFLAGS) \
 	$(GNOME_KEYRING_CFLAGS) \
 	$(DISABLE_DEPRECATED)
@@ -23,6 +24,7 @@
 libgconf_helpers_la_LIBADD = \
 	$(GTK_LIBS) \
 	$(NMA_LIBS) \
+	$(APPINDICATOR_LIBS) \
 	$(GCONF_LIBS) \
 	$(GNOME_KEYRING_LIBS)
 
Index: network-manager-applet-0.9.4.1/src/applet-device-wimax.c
===================================================================
--- network-manager-applet-0.9.4.1.orig/src/applet-device-wimax.c	2012-03-19 07:53:53.000000000 -0700
+++ network-manager-applet-0.9.4.1/src/applet-device-wimax.c	2012-11-21 16:19:09.083734694 -0800
@@ -36,6 +36,7 @@
 #include "applet.h"
 #include "applet-device-wimax.h"
 #include "utils.h"
+#include "mobile-helpers.h"
 #include "applet-dialogs.h"
 #include "nma-marshal.h"
 #include "mb-menu-item.h"
@@ -141,9 +142,14 @@
 {
 	GtkWidget *item;
 	WimaxMenuItemInfo *info;
+#ifdef ENABLE_INDICATOR
+	char *text = NULL;
+	GtkWidget *signal_icon = NULL;
+#endif
 
 	g_return_val_if_fail (nsp != NULL, NULL);
 
+#ifndef ENABLE_INDICATOR
 	item = nm_mb_menu_item_new (nm_wimax_nsp_get_name (nsp),
 		                        nm_wimax_nsp_get_signal_quality (nsp),
 		                        NULL,
@@ -152,6 +158,16 @@
 		                        nsp_type_to_mb_state (nm_wimax_nsp_get_network_type (nsp)),
 		                        TRUE,
 		                        applet);
+#else
+	text = g_strdup (nm_wimax_nsp_get_name (nsp));
+	item = gtk_image_menu_item_new_with_label (text);
+	g_free (text);
+	text = mobile_helper_get_quality_icon (nm_wimax_nsp_get_signal_quality (nsp), applet);
+	signal_icon = gtk_image_new_from_icon_name (text, GTK_ICON_SIZE_LARGE_TOOLBAR);
+	g_free (text);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), signal_icon);
+	gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+#endif /* ENABLE_INDICATOR */
 	gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
 
 	info = g_slice_new0 (WimaxMenuItemInfo);
@@ -305,7 +321,12 @@
 static void
 nsp_quality_changed (NMWimaxNsp *nsp, GParamSpec *pspec, gpointer user_data)
 {
-	applet_schedule_update_icon (NM_APPLET (user_data));
+	NMApplet *applet = NM_APPLET (user_data);
+
+	applet_schedule_update_icon (applet);
+#ifdef ENABLE_INDICATOR
+	applet_schedule_update_menu (applet);
+#endif /* ENABLE_INDICATOR */
 }
 
 static NMWimaxNsp *
@@ -367,8 +388,12 @@
 	if (!s_wimax)
 		return;
 
-	if (g_strcmp0 (nm_wimax_nsp_get_name (new), nm_setting_wimax_get_network_name (s_wimax)) != 0)
+	if (g_strcmp0 (nm_wimax_nsp_get_name (new), nm_setting_wimax_get_network_name (s_wimax)) != 0) {
 		applet_schedule_update_icon (applet);
+#ifdef ENABLE_INDICATOR
+		applet_schedule_update_menu (applet);
+#endif /* ENABLE_INDICATOR */
+	}
 }
 
 static void
@@ -384,6 +409,9 @@
 	if (old == nsp) {
 		g_object_set_data (G_OBJECT (device), ACTIVE_NSP_TAG, NULL);
 		applet_schedule_update_icon (applet);
+#ifdef ENABLE_INDICATOR
+		applet_schedule_update_menu (applet);
+#endif /* ENABLE_INDICATOR */
 	}
 }
 
@@ -432,15 +460,16 @@
 	}
 }
 
-static GdkPixbuf *
+static void
 wimax_get_icon (NMDevice *device,
                 NMDeviceState state,
                 NMConnection *connection,
+		GdkPixbuf **out_pixbuf,
+		char **out_indicator_icon,
                 char **tip,
                 NMApplet *applet)
 {
 	NMSettingConnection *s_con;
-	GdkPixbuf *pixbuf = NULL;
 	const char *id;
 	NMWimaxNsp *nsp;
 	guint32 quality = 0;
@@ -474,7 +503,7 @@
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
 		roaming = (nsp_type == NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER);
-		pixbuf = mobile_helper_get_status_pixbuf (quality,
+		*out_pixbuf = mobile_helper_get_status_pixbuf (quality,
 		                                          TRUE,
 		                                          nsp_type_to_mb_state (nsp_type),
 		                                          MB_TECH_WIMAX,
@@ -483,12 +512,11 @@
 		                        id, quality,
 		                        roaming ? ", " : "",
 		                        roaming ? _("roaming") : "");
+		*out_indicator_icon = mobile_helper_get_quality_icon (quality, applet);
 		break;
 	default:
 		break;
 	}
-
-	return pixbuf;
 }
 
 static gboolean
