# Description: use the new application indicator system
# Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gnome-settings-daemon/+bug/497875
# Upstream: https://bugzilla.gnome.org/show_bug.cgi?id=610867
diff --git a/configure.ac b/configure.ac
index 23959e6..24574f6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,6 +52,7 @@
 GIO_REQUIRED_VERSION=2.17.3
 GNOME_DESKTOP_REQUIRED_VERSION=2.26.3
 LIBNOTIFY_REQUIRED_VERSION=0.4.3
+APPINDICATOR_REQUIRED_VERSION=0.0.13
 
 EXTRA_COMPILE_WARNINGS(yes)
 
@@ -105,6 +106,32 @@ fi
 AC_SUBST(LIBNOTIFY_CFLAGS)
 AC_SUBST(LIBNOTIFY_LIBS)
 
+dnl ---------------------------------
+dnl - Application indicator
+dnl ---------------------------------
+
+AC_ARG_ENABLE([appindicator],
+	AS_HELP_STRING([--enable-appindicator[=@<:@no/auto/yes@:>@]],[Build support for application indicators]),
+	[enable_appindicator=$enableval],
+	[enable_appindicator="auto"])
+
+
+if test x$enable_appindicator = xauto ; then
+	PKG_CHECK_EXISTS(appindicator-0.1 >= $APPINDICATOR_REQUIRED_VERSION,
+		[enable_appindicator="yes"],
+		[enable_appindicator="no"])
+fi
+
+if test x$enable_appindicator = xyes ; then
+	PKG_CHECK_MODULES(APPINDICATOR,
+		[appindicator-0.1 >= $APPINDICATOR_REQUIRED_VERSION],
+		[AC_DEFINE(HAVE_APPINDICATOR, 1, [Have AppIndicator])])
+fi
+
+AM_CONDITIONAL(HAVE_APPINDICATOR, test x$enable_appindicator = xyes)
+AC_SUBST(APPINDICATOR_CFLAGS)
+AC_SUBST(APPINDICATOR_LIBS)
+
 dnl ---------------------------------------------------------------------------
 dnl - Check for D-Bus
 dnl ---------------------------------------------------------------------------
@@ -386,6 +413,7 @@ echo "
         dbus-1 system.d dir:      ${DBUS_SYS_DIR}
 
         Libnotify support:        ${have_libnotify}
+	App indicatpr support:    ${enable_appindicator}
         PulseAudio support:       ${have_pulse}
         Profiling support:        ${enable_profiling}
 "
diff --git a/plugins/a11y-keyboard/Makefile.am b/plugins/a11y-keyboard/Makefile.am
index 99bfa90..5770c1f 100644
--- a/plugins/a11y-keyboard/Makefile.am
+++ b/plugins/a11y-keyboard/Makefile.am
@@ -53,6 +53,7 @@ liba11y_keyboard_la_CPPFLAGS = \
 liba11y_keyboard_la_CFLAGS = \
 	$(SETTINGS_PLUGIN_CFLAGS)	\
 	$(LIBNOTIFY_CFLAGS)		\
+	$(APPINDICATOR_CFLAGS)		\
 	$(AM_CFLAGS)
 
 liba11y_keyboard_la_LDFLAGS = 		\
@@ -63,6 +64,7 @@ liba11y_keyboard_la_LIBADD  = 		\
 	$(SETTINGS_PLUGIN_LIBS)		\
 	$(XF86MISC_LIBS)		\
 	$(LIBNOTIFY_LIBS)		\
+	$(APPINDICATOR_LIBS)		\
 	$(NULL)
 
 plugin_in_files = 		\
diff --git a/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c b/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c
index ba19b42..88d2038 100644
--- a/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c
+++ b/plugins/a11y-keyboard/gsd-a11y-keyboard-manager.c
@@ -45,6 +45,10 @@
 #include <libnotify/notify.h>
 #endif /* HAVE_LIBNOTIFY */
 
+#ifdef HAVE_APPINDICATOR
+#include <libappindicator/app-indicator.h>
+#endif
+
 #include "gnome-settings-profile.h"
 #include "gsd-a11y-keyboard-manager.h"
 #include "gsd-a11y-preferences-dialog.h"
@@ -62,7 +66,11 @@ struct GsdA11yKeyboardManagerPrivate
         GtkWidget *stickykeys_alert;
         GtkWidget *slowkeys_alert;
         GtkWidget *preferences_dialog;
+#ifdef HAVE_APPINDICATOR
+	AppIndicator *app_indicator;
+#else
         GtkStatusIcon *status_icon;
+#endif
         XkbDescRec *original_xkb_desc;
 
         guint      gconf_notify;
@@ -435,11 +443,24 @@ maybe_show_status_icon (GsdA11yKeyboardManager *manager)
         show = gconf_client_get_bool (client, CONFIG_ROOT "/enable", NULL);
         g_object_unref (client);
 
+#ifdef HAVE_APPINDICATOR
+        if (!show && manager->priv->app_indicator == NULL)
+                return;
+	
+        gsd_a11y_keyboard_manager_ensure_status_icon (manager);
+	if (show)
+		app_indicator_set_status (manager->priv->app_indicator,
+					  APP_INDICATOR_STATUS_ACTIVE);
+	else
+		app_indicator_set_status (manager->priv->app_indicator,
+					  APP_INDICATOR_STATUS_PASSIVE);
+#else
         if (!show && manager->priv->status_icon == NULL)
                 return;
 
         gsd_a11y_keyboard_manager_ensure_status_icon (manager);
         gtk_status_icon_set_visible (manager->priv->status_icon, show);
+#endif
 }
 
 #ifdef HAVE_LIBNOTIFY
@@ -521,9 +542,11 @@ ax_slowkeys_warning_post_bubble (GsdA11yKeyboardManager *manager,
         message = _("You just held down the Shift key for 8 seconds.  This is the shortcut "
                     "for the Slow Keys feature, which affects the way your keyboard works.");
 
+#ifndef HAVE_APPINDICATOR
         if (manager->priv->status_icon == NULL || ! gtk_status_icon_is_embedded (manager->priv->status_icon)) {
                 return FALSE;
         }
+#endif
 
         if (manager->priv->slowkeys_alert != NULL) {
                 gtk_widget_destroy (manager->priv->slowkeys_alert);
@@ -538,7 +561,9 @@ ax_slowkeys_warning_post_bubble (GsdA11yKeyboardManager *manager,
                                                                message,
                                                                "preferences-desktop-accessibility",
                                                                NULL);
+#ifndef HAVE_APPINDICATOR
         notify_notification_attach_to_status_icon (manager->priv->notification, manager->priv->status_icon);
+#endif
         notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000);
 
         notify_notification_add_action (manager->priv->notification,
@@ -660,9 +685,11 @@ ax_stickykeys_warning_post_bubble (GsdA11yKeyboardManager *manager,
                 _("You just pressed two keys at once, or pressed the Shift key 5 times in a row.  "
                   "This turns off the Sticky Keys feature, which affects the way your keyboard works.");
 
+#ifndef HAVE_APPINDICATOR
         if (manager->priv->status_icon == NULL || ! gtk_status_icon_is_embedded (manager->priv->status_icon)) {
                 return FALSE;
         }
+#endif
 
         if (manager->priv->slowkeys_alert != NULL) {
                 gtk_widget_destroy (manager->priv->slowkeys_alert);
@@ -677,7 +704,9 @@ ax_stickykeys_warning_post_bubble (GsdA11yKeyboardManager *manager,
                                                                message,
                                                                "preferences-desktop-accessibility",
                                                                NULL);
+#ifndef HAVE_APPINDICATOR
         notify_notification_attach_to_status_icon (manager->priv->notification, manager->priv->status_icon);
+#endif
         notify_notification_set_timeout (manager->priv->notification, NOTIFICATION_TIMEOUT * 1000);
 
         notify_notification_add_action (manager->priv->notification,
@@ -1072,8 +1101,14 @@ gsd_a11y_keyboard_manager_stop (GsdA11yKeyboardManager *manager)
 
         g_debug ("Stopping a11y_keyboard manager");
 
+#ifdef HAVE_APPINDICATOR
+	if (p->app_indicator)
+		app_indicator_set_status (p->app_indicator,
+					  APP_INDICATOR_STATUS_PASSIVE);
+#else
         if (p->status_icon)
                 gtk_status_icon_set_visible (p->status_icon, FALSE);
+#endif
 
         if (p->gconf_notify != 0) {
                 GConfClient *client = gconf_client_get_default ();
@@ -1190,8 +1225,13 @@ on_preferences_dialog_response (GtkDialog              *dialog,
 }
 
 static void
+#ifdef HAVE_APPINDICATOR
+on_status_icon_activate (GtkMenuItem            *item,
+                         GsdA11yKeyboardManager *manager)
+#else
 on_status_icon_activate (GtkStatusIcon          *status_icon,
                          GsdA11yKeyboardManager *manager)
+#endif
 {
         if (manager->priv->preferences_dialog == NULL) {
                 manager->priv->preferences_dialog = gsd_a11y_preferences_dialog_new ();
@@ -1215,6 +1255,26 @@ gsd_a11y_keyboard_manager_ensure_status_icon (GsdA11yKeyboardManager *manager)
 {
         gnome_settings_profile_start (NULL);
 
+#ifdef HAVE_APPINDICATOR
+	if (!manager->priv->app_indicator) {
+		GtkWidget *menu = gtk_menu_new ();
+		GtkWidget *item = gtk_menu_item_new_with_label (_("Universal Access Preferences"));
+
+		g_signal_connect (item,
+				  "activate",
+				  G_CALLBACK (on_status_icon_activate),
+				  manager);
+
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+		gtk_widget_show_all (menu);
+
+		manager->priv->app_indicator = app_indicator_new ("gsd-a11y-keyboard",
+								  "preferences-desktop-accessibility",
+								  APP_INDICATOR_CATEGORY_OTHER);
+		app_indicator_set_menu (manager->priv->app_indicator,
+					GTK_MENU (menu));
+	}
+#else
         if (!manager->priv->status_icon) {
 
                 manager->priv->status_icon = gtk_status_icon_new_from_icon_name ("preferences-desktop-accessibility");
@@ -1223,6 +1283,7 @@ gsd_a11y_keyboard_manager_ensure_status_icon (GsdA11yKeyboardManager *manager)
                                   G_CALLBACK (on_status_icon_activate),
                                   manager);
         }
+#endif
 
         gnome_settings_profile_end (NULL);
 }
diff --git a/plugins/xrandr/Makefile.am b/plugins/xrandr/Makefile.am
index c5d660d..d2dd91f 100644
--- a/plugins/xrandr/Makefile.am
+++ b/plugins/xrandr/Makefile.am
@@ -54,6 +54,7 @@ libxrandr_la_CPPFLAGS =						\
 libxrandr_la_CFLAGS =			\
 	$(SETTINGS_PLUGIN_CFLAGS)	\
 	$(LIBNOTIFY_CFLAGS)		\
+	$(APPINDICATOR_CFLAGS)		\
 	$(AM_CFLAGS)
 
 libxrandr_la_LDFLAGS = 			\
@@ -61,7 +62,8 @@ libxrandr_la_LDFLAGS = 			\
 
 libxrandr_la_LIBADD  =			\
 	$(SETTINGS_PLUGIN_LIBS)		\
-	$(LIBNOTIFY_LIBS)
+	$(LIBNOTIFY_LIBS)		\
+	$(APPINDICATOR_LIBS)
 
 plugin_in_files =			\
 	xrandr.gnome-settings-plugin.in
diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index e78eb6b..0db025b 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -49,6 +49,10 @@
 #include <libnotify/notify.h>
 #endif
 
+#ifdef HAVE_APPINDICATOR
+#include <libappindicator/app-indicator.h>
+#endif
+
 #include "gnome-settings-profile.h"
 #include "gsd-xrandr-manager.h"
 
@@ -93,7 +97,11 @@ struct GsdXrandrManagerPrivate
         GnomeRRScreen *rw_screen;
         gboolean running;
 
+#ifdef HAVE_APPINDICATOR
+        AppIndicator *app_indicator;
+#else
         GtkStatusIcon *status_icon;
+#endif
         GtkWidget *popup_menu;
         GnomeRRConfig *configuration;
         GnomeRRLabeler *labeler;
@@ -908,17 +916,21 @@ static void
 error_message (GsdXrandrManager *mgr, const char *primary_text, GError *error_to_display, const char *secondary_text)
 {
 #ifdef HAVE_LIBNOTIFY
+#ifndef HAVE_APPINDICATOR
         GsdXrandrManagerPrivate *priv = mgr->priv;
+#endif
         NotifyNotification *notification;
 
         g_assert (error_to_display == NULL || secondary_text == NULL);
 
+#ifndef HAVE_APPINDICATOR
         if (priv->status_icon)
                 notification = notify_notification_new_with_status_icon (primary_text,
                                                                          error_to_display ? error_to_display->message : secondary_text,
                                                                          GSD_XRANDR_ICON_NAME,
                                                                          priv->status_icon);
         else
+#endif
                 notification = notify_notification_new (primary_text,
                                                         error_to_display ? error_to_display->message : secondary_text,
                                                         GSD_XRANDR_ICON_NAME,
@@ -1150,6 +1162,11 @@ refresh_tray_icon_menu_if_active (GsdXrandrManager *manager, guint32 timestamp)
                 gtk_menu_shell_cancel (GTK_MENU_SHELL (priv->popup_menu)); /* status_icon_popup_menu_selection_done_cb() will free everything */
                 status_icon_popup_menu (manager, 0, timestamp);
         }
+#if 0
+        else {
+                status_icon_popup_menu (manager, 0, GDK_CURRENT_TIME);
+        }
+#endif
 }
 
 static void
@@ -1464,6 +1481,8 @@ status_icon_popup_menu_selection_done_cb (GtkMenuShell *menu_shell, gpointer dat
         priv->configuration = NULL;
 }
 
+#ifndef HAVE_APPINDICATOR
+
 #define OUTPUT_TITLE_ITEM_BORDER 2
 #define OUTPUT_TITLE_ITEM_PADDING 4
 
@@ -1539,6 +1558,8 @@ output_title_label_after_expose_event_cb (GtkWidget *widget, GdkEventExpose *eve
         return FALSE;
 }
 
+#endif
+
 static void
 title_item_size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation, gpointer data)
 {
@@ -1596,6 +1617,7 @@ make_menu_item_for_output_title (GsdXrandrManager *manager, GnomeOutputInfo *out
         gtk_label_set_markup (GTK_LABEL (label), str);
         g_free (str);
 
+#ifndef HAVE_APPINDICATOR
 	/* Make the label explicitly black.  We don't want it to follow the
 	 * theme's colors, since the label is always shown against a light
 	 * pastel background.  See bgo#556050
@@ -1607,6 +1629,7 @@ make_menu_item_for_output_title (GsdXrandrManager *manager, GnomeOutputInfo *out
         gtk_misc_set_padding (GTK_MISC (label),
                               OUTPUT_TITLE_ITEM_BORDER + OUTPUT_TITLE_ITEM_PADDING,
                               OUTPUT_TITLE_ITEM_BORDER + OUTPUT_TITLE_ITEM_PADDING);
+#endif
 
         gtk_container_add (GTK_CONTAINER (item), label);
 
@@ -1614,10 +1637,12 @@ make_menu_item_for_output_title (GsdXrandrManager *manager, GnomeOutputInfo *out
          * to its expose-event signal.  See the comment in *** to see why need to connect
          * to the label both 'before' and 'after'.
          */
+#ifndef HAVE_APPINDICATOR
         g_signal_connect (label, "expose-event",
                           G_CALLBACK (output_title_label_expose_event_cb), manager);
         g_signal_connect_after (label, "expose-event",
                                 G_CALLBACK (output_title_label_after_expose_event_cb), manager);
+#endif
 
         g_object_set_data (G_OBJECT (label), "output", output);
 
@@ -1856,6 +1881,13 @@ status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timesta
         struct GsdXrandrManagerPrivate *priv = manager->priv;
         GtkWidget *item;
 
+#ifdef HAVE_APPINDICATOR
+	if (!priv->configuration)
+		priv->configuration = gnome_rr_config_new_current (priv->rw_screen);
+
+	if (priv->popup_menu)
+		gtk_widget_destroy (priv->popup_menu);
+#else
         g_assert (priv->configuration == NULL);
         priv->configuration = gnome_rr_config_new_current (priv->rw_screen);
 
@@ -1863,6 +1895,7 @@ status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timesta
         priv->labeler = gnome_rr_labeler_new (priv->configuration);
 
         g_assert (priv->popup_menu == NULL);
+#endif
         priv->popup_menu = gtk_menu_new ();
 
         add_menu_items_for_outputs (manager);
@@ -1877,14 +1910,20 @@ status_icon_popup_menu (GsdXrandrManager *manager, guint button, guint32 timesta
         gtk_widget_show (item);
         gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), item);
 
+#ifdef HAVE_APPINDICATOR
+        app_indicator_set_menu (priv->app_indicator,
+                                GTK_MENU (priv->popup_menu));
+#else
         g_signal_connect (priv->popup_menu, "selection-done",
                           G_CALLBACK (status_icon_popup_menu_selection_done_cb), manager);
 
         gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL,
                         gtk_status_icon_position_menu,
                         priv->status_icon, button, timestamp);
+#endif
 }
 
+#ifndef HAVE_APPINDICATOR
 static void
 status_icon_activate_cb (GtkStatusIcon *status_icon, gpointer data)
 {
@@ -1901,12 +1940,23 @@ status_icon_popup_menu_cb (GtkStatusIcon *status_icon, guint button, guint32 tim
 
         status_icon_popup_menu (manager, button, timestamp);
 }
+#endif
 
 static void
 status_icon_start (GsdXrandrManager *manager)
 {
         struct GsdXrandrManagerPrivate *priv = manager->priv;
 
+#ifdef HAVE_APPINDICATOR
+        if (!priv->app_indicator) {
+                priv->app_indicator = app_indicator_new ("gsd-xrandr",
+                                                         GSD_XRANDR_ICON_NAME,
+                                                         APP_INDICATOR_CATEGORY_HARDWARE);
+                app_indicator_set_status (priv->app_indicator,
+                                          APP_INDICATOR_STATUS_ACTIVE);
+		status_icon_popup_menu (manager, 0, 0);
+        }
+#else
         /* Ideally, we should detect if we are on a tablet and only display
          * the icon in that case.
          */
@@ -1919,6 +1969,7 @@ status_icon_start (GsdXrandrManager *manager)
                 g_signal_connect (priv->status_icon, "popup-menu",
                                   G_CALLBACK (status_icon_popup_menu_cb), manager);
         }
+#endif
 }
 
 static void
@@ -1926,6 +1977,14 @@ status_icon_stop (GsdXrandrManager *manager)
 {
         struct GsdXrandrManagerPrivate *priv = manager->priv;
 
+#ifdef HAVE_APPINDICATOR
+        if (priv->app_indicator) {
+                app_indicator_set_status (priv->app_indicator,
+                                          APP_INDICATOR_STATUS_PASSIVE);
+                g_object_unref (priv->app_indicator);
+                priv->app_indicator  = NULL;
+        }
+#else
         if (priv->status_icon) {
                 g_signal_handlers_disconnect_by_func (
                         priv->status_icon, G_CALLBACK (status_icon_activate_cb), manager);
@@ -1938,6 +1997,7 @@ status_icon_stop (GsdXrandrManager *manager)
                 g_object_unref (priv->status_icon);
                 priv->status_icon = NULL;
         }
+#endif
 }
 
 static void
