diff options
Diffstat (limited to 'debian/patches/20_libindicate.patch')
-rw-r--r-- | debian/patches/20_libindicate.patch | 1652 |
1 files changed, 1652 insertions, 0 deletions
diff --git a/debian/patches/20_libindicate.patch b/debian/patches/20_libindicate.patch new file mode 100644 index 000000000..ff78d8bf8 --- /dev/null +++ b/debian/patches/20_libindicate.patch @@ -0,0 +1,1652 @@ +=== modified file 'configure.ac' +--- a/configure.ac ++++ b/configure.ac +@@ -56,6 +56,8 @@ + NETWORK_MANAGER_REQUIRED=0.7.0 + WEBKIT_REQUIRED=1.1.15 + GNOME_CONTROL_CENTER_GTK3_REQUIRED=2.31.4 ++INDICATE_REQUIRED=0.4.91 ++INDICATE_GTK_REQUIRED=0.4.91 + + # telepathy-yell + prev_top_build_prefix=$ac_top_build_prefix +@@ -480,6 +482,34 @@ + AC_SUBST(MEEGO_LIBS) + + # ----------------------------------------------------------- ++# libindicate ++# ----------------------------------------------------------- ++AC_ARG_ENABLE(libindicate, ++ AS_HELP_STRING([--enable-libindicate=@<:@no/yes/auto@:>@], ++ [build libindicate support]), , ++ enable_libindicate=auto) ++ ++if test "x$enable_libindicate" != "xno"; then ++ PKG_CHECK_MODULES(INDICATE, ++ [ ++ indicate-0.5 >= $INDICATE_REQUIRED, ++ indicate-gtk-0.5 >= $INDICATE_GTK_REQUIRED ++ ], have_libindicate="yes", have_libindicate="no") ++ ++ if test "x$have_libindicate" = "xyes"; then ++ AC_DEFINE(HAVE_LIBINDICATE, 1, [Define if you have libindicate]) ++ fi ++else ++ have_libindicate=no ++fi ++ ++if test "x$enable_libindicate" = "xyes" -a "x$have_libindicate" != "xyes"; then ++ AC_MSG_ERROR([Couldn't find libindicate.]) ++fi ++ ++AM_CONDITIONAL(HAVE_LIBINDICATE, test "x$have_libindicate" = "xyes") ++ ++# ----------------------------------------------------------- + # nautilus-sendto + # ----------------------------------------------------------- + AC_ARG_ENABLE(nautilus-sendto, +@@ -581,6 +611,7 @@ + CA Cert Path................: ${GTLS_SYSTEM_CA_FILE} + + Features: ++ Message indicator support (libindicate): ${have_libindicate} + Spell checking (enchant)....: ${have_enchant} + Display maps (libchamplain).: ${have_libchamplain} + Location awareness (Geoclue): ${have_geoclue} +--- a/data/org.gnome.Empathy.gschema.xml.in ++++ b/data/org.gnome.Empathy.gschema.xml.in +@@ -86,6 +86,11 @@ + <_summary>The position for the chat window side pane</_summary> + <_description>The stored position (in pixels) of the chat window side pane.</_description> + </key> ++ <key name="use-libindicate" type="b"> ++ <default>true</default> ++ <summary>Use the messaging indicator</summary> ++ <description>Whether or not to use the messaging indicator, if false the icon in the notification area will be displayed.</description> ++ </key> + </schema> + <schema id="org.gnome.Empathy.contacts" path="/apps/empathy/contacts/"> + <key name="sort-criterium" type="s"> +--- a/libempathy-gtk/empathy-ui-utils.c ++++ b/libempathy-gtk/empathy-ui-utils.c +@@ -1567,25 +1567,36 @@ + Display *dpy; + GdkWindow *gdk_window; + +- gtk_status_icon_get_geometry (status_icon, NULL, &icon_location, NULL); +- gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); +- dpy = gdk_x11_drawable_get_xdisplay (gdk_window); ++ // If the status icon isn't visible (because indicators are used) then ++ // attempting to change the properties of the status icon doesn't work. ++ if (gtk_status_icon_get_visible (status_icon)) { ++ gtk_status_icon_get_geometry (status_icon, NULL, &icon_location, NULL); ++ gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); ++ dpy = gdk_x11_drawable_get_xdisplay (gdk_window); + +- data[0] = icon_location.x; +- data[1] = icon_location.y; +- data[2] = icon_location.width; +- data[3] = icon_location.height; ++ data[0] = icon_location.x; ++ data[1] = icon_location.y; ++ data[2] = icon_location.width; ++ data[3] = icon_location.height; + +- XChangeProperty (dpy, +- GDK_WINDOW_XID (gdk_window), +- gdk_x11_get_xatom_by_name_for_display ( +- gdk_drawable_get_display (gdk_window), +- "_NET_WM_ICON_GEOMETRY"), +- XA_CARDINAL, 32, PropModeReplace, +- (guchar *)&data, 4); ++ XChangeProperty (dpy, ++ GDK_WINDOW_XID (gdk_window), ++ gdk_x11_get_xatom_by_name_for_display ( ++ gdk_drawable_get_display (gdk_window), ++ "_NET_WM_ICON_GEOMETRY"), ++ XA_CARDINAL, 32, PropModeReplace, ++ (guchar *)&data, 4); ++ } + + gtk_window_set_skip_taskbar_hint (window, TRUE); +- gtk_window_iconify (window); ++ // If the status icon isn't present then the WM will probably choose to ++ // iconfy to the taskbar, which doesn't look as good as the taskbar ++ // entry has just been removed. Just hide instead. ++ if (gtk_status_icon_get_visible (status_icon)) { ++ gtk_window_iconify (window); ++ } else { ++ gtk_widget_hide (GTK_WIDGET(window)); ++ } + } + + /* Takes care of moving the window to the current workspace. */ +--- a/libempathy/empathy-gsettings.h ++++ b/libempathy/empathy-gsettings.h +@@ -71,6 +71,7 @@ + #define EMPATHY_PREFS_UI_SHOW_AVATARS "show-avatars" + #define EMPATHY_PREFS_UI_SHOW_PROTOCOLS "show-protocols" + #define EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST "compact-contact-list" ++#define EMPATHY_PREFS_UI_USE_LIBINDICATE "use-libindicate" + #define EMPATHY_PREFS_UI_CHAT_WINDOW_PANED_POS "chat-window-paned-pos" + #define EMPATHY_PREFS_UI_SHOW_OFFLINE "show-offline" + +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -97,6 +97,8 @@ + [type: gettext/glade]src/empathy-ft-manager.ui + src/empathy-import-dialog.c + src/empathy-import-widget.c ++src/empathy-indicator.c ++src/empathy-indicator-manager.c + [type: gettext/glade]src/empathy-import-dialog.ui + src/empathy-import-widget.c + src/empathy-main-window.c +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -8,6 +8,7 @@ + $(ERROR_CFLAGS) \ + -I$(top_srcdir) \ + -DG_LOG_DOMAIN=\"empathy\" \ ++ -DDESKTOPDIR=\"$(datadir)/applications\" \ + -DBIN_DIR=\"$(bindir)\" \ + $(DISABLE_DEPRECATED) \ + $(WARN_CFLAGS) \ +@@ -17,6 +18,7 @@ + AM_CPPFLAGS = \ + $(CPPFLAGS_COMMON) \ + $(LIBNOTIFY_CFLAGS) \ ++ $(INDICATE_CFLAGS) \ + $(UNIQUE_CFLAGS) \ + $(LIBCHAMPLAIN_CFLAGS) \ + $(WEBKIT_CFLAGS) \ +@@ -27,6 +29,7 @@ + $(top_builddir)/libempathy/libempathy.la \ + $(top_builddir)/extensions/libemp-extensions.la \ + $(LIBNOTIFY_LIBS) \ ++ $(INDICATE_LIBS) \ + $(UNIQUE_LIBS) \ + $(EMPATHY_LIBS) \ + $(GTK_LIBS) \ +@@ -200,6 +203,7 @@ + $(LIBNOTIFY_LIBS) \ + $(UNIQUE_LIBS) \ + $(EMPATHY_LIBS) \ ++ $(INDICATE_LIBS) \ + $(LIBCHAMPLAIN_LIBS) \ + $(WEBKIT_LIBS) \ + $(NULL) +@@ -232,6 +236,18 @@ + $(autostart_DATA) \ + $(ui_DATA) + ++if HAVE_LIBINDICATE ++empathy_handwritten_source += \ ++ empathy-indicator-manager.c \ ++ empathy-indicator-manager.h \ ++ empathy-indicator.c empathy-indicator.h ++else ++EXTRA_DIST += \ ++ empathy-indicator-manager.c \ ++ empathy-indicator-manager.h \ ++ empathy-indicator.c empathy-indicator.h ++endif ++ + if HAVE_LIBCHAMPLAIN + empathy_handwritten_source += \ + empathy-map-view.c \ +--- a/src/empathy-chat-window.c ++++ b/src/empathy-chat-window.c +@@ -63,6 +63,11 @@ + #include "empathy-about-dialog.h" + #include "empathy-invite-participant-dialog.h" + ++#ifdef HAVE_LIBINDICATE ++#include "empathy-indicator.h" ++#include "empathy-indicator-manager.h" ++#endif ++ + #define DEBUG_FLAG EMPATHY_DEBUG_CHAT + #include <libempathy/empathy-debug.h> + +@@ -86,7 +91,11 @@ + GtkWidget *dialog; + GtkWidget *notebook; + NotifyNotification *notification; +- ++#ifdef HAVE_LIBINDICATE ++ EmpathyIndicatorManager *indicator_manager; ++ /* EmpathyChat -> EmpathyIndicator for that chat, if any */ ++ GHashTable *indicators; ++#endif + GtkTargetList *contact_targets; + GtkTargetList *file_targets; + +@@ -1278,6 +1287,72 @@ + } + } + ++#ifdef HAVE_LIBINDICATE ++static void ++chat_window_indicator_activate_cb (EmpathyIndicator *indicator, guint timestamp, ++ EmpathyChat *chat) ++{ ++ empathy_chat_window_present_chat (chat, timestamp); ++ empathy_indicator_hide (indicator); ++} ++ ++static void ++chat_window_add_indicator (EmpathyChatWindow *window, ++ EmpathyMessage *message, ++ EmpathyChat *chat) ++{ ++ EmpathyChatWindowPriv *priv = GET_PRIV (window); ++ EmpathyContact *sender; ++ const char *body; ++ gboolean use_libindicate; ++ EmpathyIndicator *indicator = NULL; ++ GSettings *gsettings; ++ ++ gsettings = g_settings_new (EMPATHY_PREFS_UI_SCHEMA); ++ use_libindicate = g_settings_get_boolean (gsettings, EMPATHY_PREFS_UI_USE_LIBINDICATE); ++ g_object_unref (gsettings); ++ ++ if (!use_libindicate) { ++ return; ++ } ++ ++ sender = empathy_message_get_sender (message); ++ body = empathy_message_get_body (message); ++ ++ indicator = g_hash_table_lookup (priv->indicators, chat); ++ if (indicator != NULL) { ++ DEBUG ("indicator exists"); ++ empathy_indicator_update (indicator, body); ++ } else { ++ DEBUG ("indicator doesn't exist yet, creating a new indicator"); ++ indicator = empathy_indicator_manager_create_indicator (priv->indicator_manager, ++ sender, body); ++ g_signal_connect (indicator, "activate", ++ G_CALLBACK (chat_window_indicator_activate_cb), chat); ++ ++ g_hash_table_insert (priv->indicators, chat, indicator); ++ } ++ empathy_indicator_show (indicator); ++} ++ ++static void ++chat_window_remove_indicator (EmpathyChatWindow *window, EmpathyChat *chat) ++{ ++ EmpathyIndicator *indicator = NULL; ++ EmpathyChatWindowPriv *priv = GET_PRIV (window); ++ ++ indicator = g_hash_table_lookup (priv->indicators, chat); ++ ++ if ((indicator) && (indicator != NULL)) { ++ DEBUG ("indicator is %p", indicator); ++ empathy_indicator_hide (indicator); ++ g_hash_table_remove (priv->indicators, chat); ++ } else { ++ DEBUG ("indicator is NULL, nothing to remove"); ++ } ++} ++#endif ++ + static void + chat_window_show_or_update_notification (EmpathyChatWindow *window, + EmpathyMessage *message, +@@ -1454,6 +1529,9 @@ + + empathy_sound_play (GTK_WIDGET (priv->dialog), + EMPATHY_SOUND_MESSAGE_INCOMING); ++#ifdef HAVE_LIBINDICATE ++ chat_window_add_indicator (window, message, chat); ++#endif + + /* Pending messages have already been displayed in the approver, so we don't + * display a notification for those. */ +@@ -1526,6 +1604,10 @@ + empathy_chat_messages_read (chat); + + chat_window_update_chat_tab (chat); ++ ++#ifdef HAVE_LIBINDICATE ++ chat_window_remove_indicator (window, chat); ++#endif + } + + static void +@@ -1642,6 +1724,11 @@ + /* Update the title, since we now mark all unread messages as read. */ + chat_window_update_chat_tab_full (priv->current_chat, FALSE); + ++#ifdef HAVE_LIBINDICATE ++ /* Remove the indicator for the active chat */ ++ chat_window_remove_indicator (window, priv->current_chat); ++#endif ++ + return FALSE; + } + +@@ -1986,6 +2073,11 @@ + g_object_unref (gui); + + priv->chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL); ++#ifdef HAVE_LIBINDICATE ++ priv->indicator_manager = empathy_indicator_manager_dup_singleton (); ++ priv->indicators = g_hash_table_new_full (g_direct_hash, g_direct_equal, ++ NULL, g_object_unref); ++#endif + + priv->notebook = gtk_notebook_new (); + gtk_notebook_set_group (GTK_NOTEBOOK (priv->notebook), "EmpathyChatWindow"); +--- /dev/null ++++ b/src/empathy-indicator-manager.c +@@ -0,0 +1,467 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * Copyright (C) 2009 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ++ * Boston, MA 02110-1301 USA ++ * ++ * Authors: James Westby <james.westby@ubuntu.com> ++ * ++ */ ++ ++#include <config.h> ++ ++#include <gtk/gtk.h> ++ ++#include <libempathy/empathy-contact.h> ++#include <libempathy/empathy-dispatcher.h> ++#include <libempathy/empathy-utils.h> ++ ++#include <libempathy-gtk/empathy-ui-utils.h> ++#include <libempathy-gtk/empathy-notify-manager.h> ++ ++#include <telepathy-glib/util.h> ++ ++#include "empathy-event-manager.h" ++#include "empathy-indicator.h" ++#include "empathy-indicator-manager.h" ++ ++#include <libindicate/server.h> ++#include <libindicate/indicator.h> ++ ++#define DEBUG_FLAG EMPATHY_DEBUG_OTHER ++#include <libempathy/empathy-debug.h> ++ ++#define INDICATOR_LOGIN_TIMEOUT 15 ++#define EMPATHY_DESKTOP_PATH DESKTOPDIR "/empathy.desktop" ++ ++#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndicatorManager) ++ ++enum { ++ SERVER_ACTIVATE, ++ LAST_SIGNAL ++}; ++ ++static guint signals[LAST_SIGNAL]; ++ ++typedef struct { ++ EmpathyEventManager *event_manager; ++ IndicateServer *indicate_server; ++ GSList *indicator_events; ++ GHashTable *login_timeouts; ++} EmpathyIndicatorManagerPriv; ++ ++typedef struct { ++ EmpathyIndicator *indicator; ++ EmpathyEvent *event; ++} IndicatorEvent; ++ ++typedef struct { ++ EmpathyIndicatorManager *manager; ++ EmpathyIndicator *indicator; ++} LoginData; ++ ++G_DEFINE_TYPE (EmpathyIndicatorManager, empathy_indicator_manager, G_TYPE_OBJECT); ++ ++static EmpathyIndicatorManager *manager_singleton = NULL; ++ ++static EmpathyEvent * ++event_copy (EmpathyEvent *event) ++{ ++ EmpathyEvent *ret = g_new0 (EmpathyEvent, 1); ++ ++ ret->contact = g_object_ref (event->contact); ++ ret->icon_name = g_strdup (event->icon_name); ++ ret->header = g_strdup (event->header); ++ ret->message = g_strdup (event->message); ++ ret->must_ack = event->must_ack; ++ ++ return ret; ++} ++ ++static gboolean ++compare_events (EmpathyEvent *ev1, EmpathyEvent *ev2) ++{ ++ return ((g_strcmp0 (ev1->icon_name, ev2->icon_name) == 0) && ++ (g_strcmp0 (ev1->header, ev2->header) == 0) && ++ (ev1->must_ack == ev2->must_ack) && ++ (ev1->contact == ev2->contact)); ++} ++ ++static IndicatorEvent * ++indicator_event_new (EmpathyIndicator *indicator, ++ EmpathyEvent *event) ++{ ++ IndicatorEvent *indicator_event; ++ ++ indicator_event = g_slice_new0 (IndicatorEvent); ++ indicator_event->indicator = g_object_ref (indicator); ++ indicator_event->event = event_copy (event); ++ ++ return indicator_event; ++} ++ ++ ++static void ++indicator_event_free (IndicatorEvent *indicator_event) ++{ ++ g_object_unref (indicator_event->indicator); ++ g_free (indicator_event); ++} ++ ++ ++static void ++indicate_server_activate (IndicateServer *server, guint timestamp, ++ EmpathyIndicatorManager *manager) ++{ ++ g_signal_emit (manager, signals[SERVER_ACTIVATE], 0, timestamp); ++} ++ ++ ++static void ++indicate_show_cb (EmpathyIndicator *indicator, guint timestamp, ++ EmpathyEvent *event) ++{ ++ empathy_event_activate (event); ++} ++ ++ ++static void ++indicator_manager_event_added_cb (EmpathyEventManager *event_manager, ++ EmpathyEvent *event, ++ EmpathyIndicatorManager *manager) ++{ ++ EmpathyIndicator *indicator = NULL; ++ EmpathyIndicatorManagerPriv *priv; ++ IndicatorEvent *indicator_event; ++ ++ priv = GET_PRIV (manager); ++ ++ DEBUG ("Event added"); ++ ++ if (event->contact == NULL) ++ return; ++ ++ indicator = empathy_indicator_new (event->contact, event->message, "im"); ++ if (indicator == NULL) { ++ return; ++ } ++ ++ empathy_indicator_show (indicator); ++ g_signal_connect (G_OBJECT(indicator), "activate", ++ G_CALLBACK (indicate_show_cb), ++ event); ++ indicator_event = indicator_event_new (indicator, event); ++ g_object_unref (indicator); ++ priv->indicator_events = g_slist_prepend (priv->indicator_events, ++ indicator_event); ++} ++ ++static void ++indicator_manager_event_removed_cb (EmpathyEventManager *event_manager, ++ EmpathyEvent *event, ++ EmpathyIndicatorManager *manager) ++{ ++ EmpathyIndicatorManagerPriv *priv; ++ GSList *l; ++ ++ priv = GET_PRIV (manager); ++ ++ DEBUG ("Event removed"); ++ ++ for (l = priv->indicator_events; l; l = l->next) ++ { ++ IndicatorEvent *indicator_event; ++ indicator_event = l->data; ++ ++ if (compare_events (indicator_event->event, event)) { ++ priv->indicator_events = g_slist_remove (priv->indicator_events, ++ indicator_event); ++ empathy_indicator_hide (indicator_event->indicator); ++ return; ++ } ++ } ++} ++ ++ ++static void ++indicator_manager_event_updated_cb (EmpathyEventManager *event_manager, ++ EmpathyEvent *event, ++ EmpathyIndicatorManager *manager) ++{ ++ EmpathyIndicatorManagerPriv *priv; ++ GSList *l; ++ ++ priv = GET_PRIV (manager); ++ ++ for (l = priv->indicator_events; l; l = l->next) ++ { ++ IndicatorEvent *indicator_event; ++ indicator_event = l->data; ++ if (compare_events (indicator_event->event, event)) { ++ empathy_indicator_update (indicator_event->indicator, ++ event->message); ++ return; ++ } ++ } ++} ++ ++ ++/* Remove the login indicator when it times out */ ++static gboolean ++indicate_login_timeout (gpointer data) ++{ ++ LoginData *login_data; ++ EmpathyIndicator *e_indicator; ++ EmpathyIndicatorManager *manager; ++ EmpathyIndicatorManagerPriv *priv; ++ ++ login_data = (LoginData *) data; ++ e_indicator = login_data->indicator; ++ manager = login_data->manager; ++ priv = GET_PRIV (manager); ++ ++ empathy_indicator_hide (e_indicator); ++ g_hash_table_remove (priv->login_timeouts, e_indicator); ++ ++ return FALSE; ++} ++ ++ ++static void ++indicate_login_cb (EmpathyIndicator *e_indicator, guint timestamp, ++ EmpathyIndicatorManager *manager) ++{ ++ EmpathyIndicatorManagerPriv *priv; ++ GSList *events, *l; ++ EmpathyContact *contact; ++ ++ priv = GET_PRIV (manager); ++ ++ empathy_indicator_hide (e_indicator); ++ g_hash_table_remove (priv->login_timeouts, e_indicator); ++ ++ contact = empathy_indicator_get_contact (e_indicator); ++ /* If the contact has an event activate it, otherwise the ++ * default handler of row-activated will be called. */ ++ events = empathy_event_manager_get_events (priv->event_manager); ++ for (l = events; l; l = l->next) { ++ EmpathyEvent *event; ++ ++ event = l->data; ++ if (event->contact == contact) { ++ empathy_event_activate (event); ++ return; ++ } ++ } ++ ++ /* Else start a new conversation */ ++ empathy_dispatcher_chat_with_contact (contact, timestamp); ++} ++ ++ ++EmpathyIndicatorManager * ++empathy_indicator_manager_dup_singleton (void) ++{ ++ return g_object_new (EMPATHY_TYPE_INDICATOR_MANAGER, NULL); ++} ++ ++ ++static void ++indicator_manager_dispose (GObject *object) ++{ ++ EmpathyIndicatorManagerPriv *priv; ++ ++ priv = GET_PRIV (object); ++ ++ if (priv->indicator_events) { ++ g_slist_foreach (priv->indicator_events, (GFunc) indicator_event_free, ++ NULL); ++ g_slist_free (priv->indicator_events); ++ priv->indicator_events = NULL; ++ } ++ if (priv->event_manager) { ++ g_object_unref (priv->event_manager); ++ priv->event_manager = NULL; ++ } ++ if (priv->indicate_server) { ++ g_object_unref (priv->indicate_server); ++ priv->indicate_server = NULL; ++ } ++ if (priv->login_timeouts) { ++ g_hash_table_unref (priv->login_timeouts); ++ priv->login_timeouts = NULL; ++ } ++ ++ G_OBJECT_CLASS (empathy_indicator_manager_parent_class)->dispose (object); ++} ++ ++ ++static GObject * ++indicator_manager_constructor (GType type, ++ guint n_props, ++ GObjectConstructParam *props) ++{ ++ GObject *retval; ++ ++ if (manager_singleton != NULL) { ++ retval = g_object_ref (manager_singleton); ++ } else { ++ retval = G_OBJECT_CLASS (empathy_indicator_manager_parent_class)->constructor ++ (type, n_props, props); ++ ++ manager_singleton = EMPATHY_INDICATOR_MANAGER (retval); ++ g_object_add_weak_pointer (retval, (gpointer) &manager_singleton); ++ } ++ ++ return retval; ++} ++ ++ ++static void ++empathy_indicator_manager_class_init (EmpathyIndicatorManagerClass *klass) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS (klass); ++ object_class->dispose = indicator_manager_dispose; ++ object_class->constructor = indicator_manager_constructor; ++ ++ signals[SERVER_ACTIVATE] = ++ g_signal_new ("server-activate", ++ G_TYPE_FROM_CLASS (klass), ++ G_SIGNAL_RUN_LAST, ++ 0, ++ NULL, NULL, ++ g_cclosure_marshal_VOID__UINT, ++ G_TYPE_NONE, 1, G_TYPE_UINT); ++ ++ g_type_class_add_private (object_class, sizeof (EmpathyIndicatorManagerPriv)); ++} ++ ++ ++static void ++empathy_indicator_manager_init (EmpathyIndicatorManager *manager) ++{ ++ EmpathyIndicatorManagerPriv *priv; ++ ++ priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, ++ EMPATHY_TYPE_INDICATOR_MANAGER, EmpathyIndicatorManagerPriv); ++ manager->priv = priv; ++ ++ priv->event_manager = empathy_event_manager_dup_singleton (); ++ priv->login_timeouts = g_hash_table_new_full (NULL, NULL, ++ (GDestroyNotify) g_object_unref, (GDestroyNotify) g_source_unref); ++ priv->indicate_server = indicate_server_ref_default (); ++ indicate_server_set_type (priv->indicate_server, "message.instant"); ++ indicate_server_set_desktop_file (priv->indicate_server, ++ EMPATHY_DESKTOP_PATH); ++ ++ g_signal_connect (priv->indicate_server, ++ INDICATE_SERVER_SIGNAL_SERVER_DISPLAY, ++ G_CALLBACK (indicate_server_activate), ++ manager); ++ ++ g_signal_connect (priv->event_manager, "event-added", ++ G_CALLBACK (indicator_manager_event_added_cb), ++ manager); ++ g_signal_connect (priv->event_manager, "event-removed", ++ G_CALLBACK (indicator_manager_event_removed_cb), ++ manager); ++ g_signal_connect (priv->event_manager, "event-updated", ++ G_CALLBACK (indicator_manager_event_updated_cb), ++ manager); ++} ++ ++void ++empathy_indicator_manager_set_server_visible (EmpathyIndicatorManager *manager, ++ gboolean visible) ++{ ++ EmpathyIndicatorManagerPriv *priv; ++ ++ priv = GET_PRIV (manager); ++ if (visible) { ++ DEBUG ("Show indicator"); ++ indicate_server_show (priv->indicate_server); ++ } else { ++ DEBUG ("Hide indicator"); ++ indicate_server_hide (priv->indicate_server); ++ } ++} ++ ++ ++EmpathyIndicator * ++empathy_indicator_manager_create_indicator (EmpathyIndicatorManager *manager, ++ EmpathyContact *sender, ++ const gchar *body) ++{ ++ return empathy_indicator_new (sender, body, "im"); ++} ++ ++ ++static LoginData * ++login_data_new (EmpathyIndicator *e_indicator, ++ EmpathyIndicatorManager *manager) ++{ ++ LoginData *login_data; ++ ++ login_data = g_slice_new0 (LoginData); ++ login_data->manager = g_object_ref (manager); ++ login_data->indicator = g_object_ref (e_indicator); ++ ++ return login_data; ++} ++ ++ ++static void ++indicator_destroy_login_data (gpointer data) ++{ ++ LoginData *login_data; ++ ++ login_data = (LoginData *)data; ++ ++ g_object_unref (login_data->manager); ++ g_object_unref (login_data->indicator); ++ g_slice_free (LoginData, login_data); ++} ++ ++ ++/* Add an indicator for someone logging in. This will be displayed for ++ * a short period only. ++ */ ++void ++empathy_indicator_manager_add_login_indicator (EmpathyIndicatorManager *manager, ++ EmpathyContact *contact) ++{ ++ EmpathyIndicatorManagerPriv *priv; ++ GSource *timeout; ++ EmpathyIndicator *e_indicator; ++ LoginData *login_data; ++ ++ priv = GET_PRIV (manager); ++ e_indicator = empathy_indicator_new (contact, NULL, "login"); ++ login_data = login_data_new (e_indicator, manager); ++ ++ timeout = g_timeout_source_new_seconds (INDICATOR_LOGIN_TIMEOUT); ++ g_source_set_callback (timeout, indicate_login_timeout, login_data, ++ indicator_destroy_login_data); ++ g_source_attach (timeout, NULL); ++ ++ g_hash_table_insert (priv->login_timeouts, e_indicator, timeout); ++ ++ g_signal_connect (e_indicator, "activate", ++ G_CALLBACK (indicate_login_cb), manager); ++ empathy_indicator_show (e_indicator); ++} +--- /dev/null ++++ b/src/empathy-indicator-manager.h +@@ -0,0 +1,77 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * Copyright (C) 2009 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ++ * Boston, MA 02110-1301 USA ++ * ++ * Authors: James Westby <james.westby@ubuntu.com> ++ * ++ */ ++ ++#ifndef __EMPATHY_INDICATOR_MANAGER_H__ ++#define __EMPATHY_INDICATOR_MANAGER_H__ ++ ++#include <glib.h> ++ ++#include <libempathy/empathy-contact.h> ++#include "empathy-indicator.h" ++ ++G_BEGIN_DECLS ++ ++#define EMPATHY_TYPE_INDICATOR_MANAGER \ ++ (empathy_indicator_manager_get_type ()) ++#define EMPATHY_INDICATOR_MANAGER(o) \ ++ (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_INDICATOR_MANAGER, \ ++ EmpathyIndicatorManager)) ++#define EMPATHY_INDICATOR_MANAGER_CLASS(k) \ ++ (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_INDICATOR_MANAGER, \ ++ EmpathyIndicatorManagerClass)) ++#define EMPATHY_IS_INDICATOR_MANAGER(o) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_INDICATOR_MANAGER)) ++#define EMPATHY_IS_INDICATOR_MANAGER_CLASS(k) \ ++ (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_INDICATOR_MANAGER)) ++#define EMPATHY_INDICATOR_MANAGER_GET_CLASS(o) \ ++ (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_INDICATOR_MANAGER, \ ++ EmpathyIndicatorManagerClass)) ++ ++typedef struct _EmpathyIndicatorManager EmpathyIndicatorManager; ++typedef struct _EmpathyIndicatorManagerClass EmpathyIndicatorManagerClass; ++ ++struct _EmpathyIndicatorManager { ++ GObject parent; ++ gpointer priv; ++}; ++ ++struct _EmpathyIndicatorManagerClass { ++ GObjectClass parent_class; ++}; ++ ++GType empathy_indicator_manager_get_type (void) G_GNUC_CONST; ++EmpathyIndicatorManager *empathy_indicator_manager_dup_singleton (void); ++void empathy_indicator_manager_set_server_visible ( ++ EmpathyIndicatorManager *manager, ++ gboolean visible); ++EmpathyIndicator *empathy_indicator_manager_create_indicator ( ++ EmpathyIndicatorManager *manager, ++ EmpathyContact *sender, ++ const gchar *body); ++void empathy_indicator_manager_add_login_indicator ( ++ EmpathyIndicatorManager *manager, ++ EmpathyContact *contact); ++ ++G_END_DECLS ++ ++#endif /* __EMPATHY_INDICATOR_MANAGER_H__ */ +--- /dev/null ++++ b/src/empathy-indicator.c +@@ -0,0 +1,325 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * Copyright (C) 2009 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ++ * Boston, MA 02110-1301 USA ++ * ++ * Authors: James Westby <james.westby@ubuntu.com> ++ * ++ */ ++ ++#include <gtk/gtk.h> ++ ++#include <libempathy/empathy-contact.h> ++#include <libempathy/empathy-utils.h> ++ ++#include <libempathy-gtk/empathy-ui-utils.h> ++#include <libempathy-gtk/empathy-notify-manager.h> ++ ++#include "empathy-indicator.h" ++ ++#include <libindicate/indicator.h> ++#include <libindicate-gtk/indicator.h> ++ ++#define DEBUG_FLAG EMPATHY_DEBUG_OTHER ++#include <libempathy/empathy-debug.h> ++ ++#define GET_PRIV(obj) EMPATHY_GET_PRIV ((obj), EmpathyIndicator) ++ ++enum { ++ PROP_0, ++ PROP_CONTACT, ++ PROP_BODY, ++ PROP_SUBTYPE, ++ PROP_VISIBLE ++}; ++ ++enum { ++ ACTIVATE, ++ LAST_SIGNAL ++}; ++ ++static guint signals[LAST_SIGNAL]; ++ ++typedef struct { ++ IndicateIndicator *indicator; ++ EmpathyContact *contact; ++ gchar *body; ++ gchar *subtype; ++} EmpathyIndicatorPriv; ++ ++G_DEFINE_TYPE (EmpathyIndicator, empathy_indicator, G_TYPE_OBJECT) ++ ++ ++static void ++empathy_indicator_dispose (GObject *object) ++{ ++ EmpathyIndicatorPriv *priv; ++ ++ priv = GET_PRIV (object); ++ ++ if (priv->indicator) { ++ g_object_unref (priv->indicator); ++ priv->indicator = NULL; ++ } ++ if (priv->contact) { ++ g_object_unref (priv->contact); ++ priv->contact = NULL; ++ } ++ ++ G_OBJECT_CLASS (empathy_indicator_parent_class)->dispose (object); ++} ++ ++ ++static void ++empathy_indicator_finalize (GObject *object) ++{ ++ EmpathyIndicatorPriv *priv; ++ ++ priv = GET_PRIV (object); ++ ++ g_free (priv->body); ++ g_free (priv->subtype); ++ ++ G_OBJECT_CLASS (empathy_indicator_parent_class)->finalize (object); ++} ++ ++static void ++indicate_show_cb (IndicateIndicator *indicator, guint timestamp, ++ EmpathyIndicator *e_indicator) ++{ ++ g_signal_emit (e_indicator, signals[ACTIVATE], 0, timestamp); ++} ++ ++ ++static IndicateIndicator * ++empathy_indicator_get_indicator (EmpathyIndicator *e_indicator) ++{ ++ EmpathyIndicatorPriv *priv; ++ ++ priv = GET_PRIV (e_indicator); ++ if (priv->indicator) ++ return priv->indicator; ++ ++ priv->indicator = indicate_indicator_new (); ++ g_assert (priv->indicator); ++ g_signal_connect (G_OBJECT (priv->indicator), ++ INDICATE_INDICATOR_SIGNAL_DISPLAY, ++ G_CALLBACK (indicate_show_cb), ++ e_indicator); ++ ++ return priv->indicator; ++} ++ ++ ++static void ++empathy_indicator_set_property (GObject *object, ++ guint param_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ EmpathyIndicator *e_indicator; ++ EmpathyIndicatorPriv *priv; ++ IndicateIndicator *indicator; ++ GTimeVal time; ++ GdkPixbuf *pixbuf_avatar = NULL; ++ ++ e_indicator = EMPATHY_INDICATOR (object); ++ priv = GET_PRIV (e_indicator); ++ ++ indicator = empathy_indicator_get_indicator (e_indicator); ++ ++ switch (param_id) { ++ case PROP_CONTACT: ++ priv->contact = g_object_ref (g_value_get_object (value)); ++ g_assert (priv->contact); ++ indicate_indicator_set_property (indicator, "sender", ++ empathy_contact_get_alias (priv->contact)); ++ /* get the scaled avatar (22,22) until LP bug #433143 is fixed then switch to ++ to letting indicate-messages handle the scaling by setting the size to 0, 0 */ ++ pixbuf_avatar = empathy_pixbuf_avatar_from_contact_scaled (priv->contact, 22, 22); ++ if (pixbuf_avatar != NULL) ++ { ++ indicate_indicator_set_property_icon(indicator, "icon", pixbuf_avatar); ++ g_object_unref(G_OBJECT(pixbuf_avatar)); ++ } ++ break; ++ case PROP_BODY: ++ if (priv->body) ++ g_free (priv->body); ++ priv->body = g_strdup (g_value_get_string (value)); ++ indicate_indicator_set_property (indicator, "body", priv->body); ++ if (priv->body != NULL) { ++ g_get_current_time (&time); ++ indicate_indicator_set_property_time (indicator, "time", &time); ++ } ++ break; ++ case PROP_SUBTYPE: ++ if (priv->subtype) ++ g_free (priv->subtype); ++ priv->subtype = g_strdup (g_value_get_string (value)); ++ indicate_indicator_set_property (indicator, "subtype", priv->subtype); ++ if (g_strcmp0 (priv->subtype, "login") != 0 ) { ++ indicate_indicator_set_property (indicator, "draw-attention", "true"); ++ } ++ break; ++ case PROP_VISIBLE: ++ if (g_value_get_boolean (value)) ++ indicate_indicator_show (indicator); ++ else ++ indicate_indicator_hide (indicator); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; ++ } ++} ++ ++ ++static void ++empathy_indicator_get_property (GObject *object, ++ guint param_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ EmpathyIndicator *e_indicator; ++ EmpathyIndicatorPriv *priv; ++ ++ e_indicator = EMPATHY_INDICATOR (object); ++ priv = GET_PRIV (e_indicator); ++ ++ switch (param_id) { ++ case PROP_CONTACT: ++ g_value_set_object (value, priv->contact); ++ break; ++ case PROP_BODY: ++ g_value_set_string (value, priv->body); ++ break; ++ case PROP_SUBTYPE: ++ g_value_set_string (value, priv->subtype); ++ break; ++ case PROP_VISIBLE: ++ g_value_set_boolean (value, indicate_indicator_is_visible (priv->indicator)); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); ++ break; ++ } ++} ++ ++ ++static void ++empathy_indicator_class_init (EmpathyIndicatorClass *klass) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = empathy_indicator_set_property; ++ object_class->get_property = empathy_indicator_get_property; ++ object_class->dispose = empathy_indicator_dispose; ++ object_class->finalize = empathy_indicator_finalize; ++ ++ g_object_class_install_property (object_class, PROP_CONTACT, ++ g_param_spec_object ("contact", ++ "Contact", ++ "The contact being indicated", ++ EMPATHY_TYPE_CONTACT, ++ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); ++ g_object_class_install_property (object_class, PROP_BODY, ++ g_param_spec_string ("body", ++ "Body", ++ "The text for this contact", ++ NULL, ++ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT))); ++ g_object_class_install_property (object_class, PROP_SUBTYPE, ++ g_param_spec_string ("subtype", ++ "Subtype", ++ "The type of this indicator", ++ NULL, ++ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT))); ++ g_object_class_install_property (object_class, PROP_VISIBLE, ++ g_param_spec_boolean ("visible", ++ "Visible", ++ "The visibility of this indicator", ++ FALSE, ++ G_PARAM_READWRITE)); ++ ++ signals[ACTIVATE] = ++ g_signal_new ("activate", ++ G_TYPE_FROM_CLASS (klass), ++ G_SIGNAL_RUN_LAST, ++ 0, ++ NULL, NULL, ++ g_cclosure_marshal_VOID__UINT, ++ G_TYPE_NONE, 1, G_TYPE_UINT); ++ ++ g_type_class_add_private (object_class, sizeof (EmpathyIndicatorPriv)); ++} ++ ++ ++static void ++empathy_indicator_init (EmpathyIndicator *e_indicator) ++{ ++ e_indicator->priv = G_TYPE_INSTANCE_GET_PRIVATE (e_indicator, ++ EMPATHY_TYPE_INDICATOR, ++ EmpathyIndicatorPriv); ++} ++ ++ ++EmpathyIndicator * ++empathy_indicator_new (EmpathyContact *sender, ++ const gchar *body, ++ const gchar *subtype) ++{ ++ DEBUG ("Creating a new indicator"); ++ return g_object_new (EMPATHY_TYPE_INDICATOR, "contact", sender, "body", body, ++ "subtype", subtype, NULL); ++} ++ ++ ++void ++empathy_indicator_show (EmpathyIndicator *e_indicator) ++{ ++ DEBUG ("Showing indicator %p", e_indicator); ++ g_object_set (e_indicator, "visible", TRUE, NULL); ++} ++ ++ ++void ++empathy_indicator_hide (EmpathyIndicator *e_indicator) ++{ ++ DEBUG ("Hiding indicator %p", e_indicator); ++ g_object_set (e_indicator, "visible", FALSE, NULL); ++} ++ ++ ++void ++empathy_indicator_update (EmpathyIndicator *e_indicator, ++ const gchar *body) ++{ ++ DEBUG ("Updating existing indicator %p", e_indicator); ++ g_object_set (e_indicator, "body", body, NULL); ++} ++ ++ ++EmpathyContact * ++empathy_indicator_get_contact (EmpathyIndicator *e_indicator) ++{ ++ EmpathyContact *contact; ++ g_object_get (e_indicator, "contact", &contact, NULL); ++ return contact; ++} +--- /dev/null ++++ b/src/empathy-indicator.h +@@ -0,0 +1,65 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * Copyright (C) 2009 Canonical Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, ++ * Boston, MA 02110-1301 USA ++ * ++ * Authors: James Westby <james.westby@ubuntu.com> ++ * ++ */ ++ ++#ifndef __EMPATHY_INDICATOR_H__ ++#define __EMPATHY_INDICATOR_H__ ++ ++#include <glib.h> ++ ++#include <libempathy/empathy-contact.h> ++ ++G_BEGIN_DECLS ++ ++#define EMPATHY_TYPE_INDICATOR (empathy_indicator_get_type ()) ++#define EMPATHY_INDICATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_INDICATOR, EmpathyIndicator)) ++#define EMPATHY_INDICATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_INDICATOR, EmpathyIndicatorClass)) ++#define EMPATHY_IS_INDICATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_INDICATOR)) ++#define EMPATHY_IS_INDICATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_INDICATOR)) ++#define EMPATHY_INDICATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_INDICATOR, EmpathyIndicatorClass)) ++ ++typedef struct _EmpathyIndicator EmpathyIndicator; ++typedef struct _EmpathyIndicatorClass EmpathyIndicatorClass; ++ ++struct _EmpathyIndicator { ++ GObject parent; ++ gpointer priv; ++}; ++ ++struct _EmpathyIndicatorClass { ++ GObjectClass parent_class; ++}; ++ ++GType empathy_indicator_get_type (void) G_GNUC_CONST; ++EmpathyIndicator *empathy_indicator_new (EmpathyContact *sender, ++ const gchar *body, ++ const gchar *type); ++void empathy_indicator_show (EmpathyIndicator *e_indicator); ++void empathy_indicator_hide (EmpathyIndicator *e_indicator); ++void empathy_indicator_update (EmpathyIndicator *e_indicator, ++ const gchar *body); ++EmpathyContact *empathy_indicator_get_contact (EmpathyIndicator *e_indicator); ++ ++G_END_DECLS ++ ++ ++#endif /* __EMPATHY-INDICATOR_H__ */ +--- a/src/empathy-main-window.c ++++ b/src/empathy-main-window.c +@@ -82,6 +82,10 @@ + #include "empathy-ft-manager.h" + #include "empathy-migrate-butterfly-logs.h" + ++#ifdef HAVE_LIBINDICATE ++#include "empathy-indicator-manager.h" ++#endif ++ + #define DEBUG_FLAG EMPATHY_DEBUG_OTHER + #include <libempathy/empathy-debug.h> + +@@ -161,6 +165,10 @@ + + /* Actions that are enabled when there are connected accounts */ + GList *actions_connected; ++#ifdef HAVE_LIBINDICATE ++ EmpathyIndicatorManager *indicator_manager; ++ GHashTable *indicator_timeouts; ++#endif + + /* The idle event source to migrate butterfly's logs */ + guint butterfly_log_migration_members_changed_id; +@@ -433,11 +441,23 @@ + EmpathyEvent *event, + EmpathyMainWindow *window) + { ++ EmpathyMainWindowPriv *priv = GET_PRIV (window); ++ + if (event->contact) { + main_window_flash_start (window); + } else if (event->type == EMPATHY_EVENT_TYPE_AUTH) { + main_window_auth_display (window, event); + } ++ ++ #ifdef HAVE_LIBINDICATE ++ if (event->type == EMPATHY_EVENT_TYPE_PRESENCE && ++ tp_connection_presence_type_cmp_availability (empathy_contact_get_presence (event->contact), ++ TP_CONNECTION_PRESENCE_TYPE_OFFLINE) > 0) { ++ empathy_indicator_manager_add_login_indicator (priv->indicator_manager, ++ event->contact); ++ } ++ #endif ++ + } + + static void +@@ -1004,6 +1024,10 @@ + g_object_unref (priv->ui_manager); + g_object_unref (priv->chatroom_manager); + ++#ifdef HAVE_LIBINDICATE ++ g_object_unref (priv->indicator_manager); ++#endif ++ + g_object_unref (priv->gsettings_ui); + g_object_unref (priv->gsettings_contacts); + +@@ -2072,6 +2096,10 @@ + l = l->next; + } + ++#ifdef HAVE_LIBINDICATE ++ priv->indicator_manager = empathy_indicator_manager_dup_singleton (); ++#endif ++ + /* Show offline ? */ + show_offline = g_settings_get_boolean (priv->gsettings_ui, + EMPATHY_PREFS_UI_SHOW_OFFLINE); +--- a/src/empathy-preferences.c ++++ b/src/empathy-preferences.c +@@ -56,6 +56,7 @@ + + GtkWidget *checkbutton_show_smileys; + GtkWidget *checkbutton_show_contacts_in_rooms; ++ GtkWidget *checkbutton_use_libindicate; + GtkWidget *combobox_chat_theme; + GtkWidget *checkbutton_separate_chat_windows; + GtkWidget *checkbutton_events_notif_area; +@@ -235,6 +236,16 @@ + priv->checkbutton_show_smileys, + "active", + G_SETTINGS_BIND_DEFAULT); ++#ifdef HAVE_LIBINDICATE ++ g_settings_bind (priv->gsettings_ui, ++ EMPATHY_PREFS_UI_USE_LIBINDICATE, ++ priv->checkbutton_use_libindicate, ++ "active", ++ G_SETTINGS_BIND_DEFAULT); ++#else ++ gtk_widget_hide (GTK_WIDGET (priv->checkbutton_use_libindicate)); ++#endif ++ + g_settings_bind (priv->gsettings_chat, + EMPATHY_PREFS_CHAT_SHOW_CONTACTS_IN_ROOMS, + priv->checkbutton_show_contacts_in_rooms, +@@ -890,6 +901,7 @@ + "notebook", &priv->notebook, + "checkbutton_show_smileys", &priv->checkbutton_show_smileys, + "checkbutton_show_contacts_in_rooms", &priv->checkbutton_show_contacts_in_rooms, ++ "checkbutton_use_libindicate", &priv->checkbutton_use_libindicate, + "combobox_chat_theme", &priv->combobox_chat_theme, + "checkbutton_separate_chat_windows", &priv->checkbutton_separate_chat_windows, + "checkbutton_events_notif_area", &priv->checkbutton_events_notif_area, +--- a/src/empathy-preferences.ui ++++ b/src/empathy-preferences.ui +@@ -266,6 +266,20 @@ + <property name="position">1</property> + </packing> + </child> ++ <child> ++ <object class="GtkCheckButton" id="checkbutton_use_libindicate"> ++ <property name="label" translatable="yes">Show incoming messages in the messaging menu</property> ++ <property name="visible">True</property> ++ <property name="can_focus">True</property> ++ <property name="receives_default">False</property> ++ <property name="draw_indicator">True</property> ++ </object> ++ <packing> ++ <property name="expand">False</property> ++ <property name="fill">False</property> ++ <property name="position">2</property> ++ </packing> ++ </child> + </object> + <packing> + <property name="position">1</property> +--- a/src/empathy-status-icon.c ++++ b/src/empathy-status-icon.c +@@ -29,6 +29,7 @@ + #include <gdk/gdkkeysyms.h> + #include <glib/gi18n.h> + ++#include <libnotify/notify.h> + #include <libnotify/notification.h> + #include <libnotify/notify.h> + +@@ -52,6 +53,12 @@ + #include "empathy-preferences.h" + #include "empathy-event-manager.h" + ++#ifdef HAVE_LIBINDICATE ++#include "empathy-indicator-manager.h" ++#include <libindicate/server.h> ++#include <libindicate/interests.h> ++#endif ++ + #define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER + #include <libempathy/empathy-debug.h> + +@@ -76,6 +83,10 @@ + GtkAction *show_window_item; + GtkAction *new_message_item; + GtkAction *status_item; ++#ifdef HAVE_LIBINDICATE ++ EmpathyIndicatorManager *indicator_manager; ++ IndicateServer *indicate_server; ++#endif + } EmpathyStatusIconPriv; + + G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT); +@@ -457,6 +468,92 @@ + empathy_window_present (GTK_WINDOW (priv->window)); + } + } ++#ifdef HAVE_LIBINDICATE ++static void ++empathy_status_icon_set_visible (gboolean show_icon, EmpathyStatusIcon *icon) ++{ ++ EmpathyStatusIconPriv *priv = GET_PRIV (icon); ++ gtk_status_icon_set_visible (priv->icon, show_icon); ++} ++ ++static void ++empathy_indicator_interest_status_icon (gboolean icon_visibility, ++ EmpathyStatusIcon *icon) ++{ ++ EmpathyStatusIconPriv *priv = GET_PRIV (icon); ++ EmpathyIndicatorManager *manager; ++ gboolean use_libindicate; ++ ++ manager = empathy_indicator_manager_dup_singleton(); ++ use_libindicate = g_settings_get_boolean (priv->gsettings_ui, ++ EMPATHY_PREFS_UI_USE_LIBINDICATE); ++ ++ if (use_libindicate && !icon_visibility) { ++ empathy_indicator_manager_set_server_visible (manager, TRUE); ++ /* Hide the status icon so there are not two ways to access ++ * empathy. ++ */ ++ DEBUG ("Hiding the icon, we are shown in the indicator"); ++ empathy_status_icon_set_visible (FALSE, icon); ++ } else { ++ empathy_indicator_manager_set_server_visible (manager, ++ FALSE); ++ DEBUG ("Show the icon, we are not shown in the indicator"); ++ empathy_status_icon_set_visible (TRUE, icon); ++ } ++} ++ ++static void ++empathy_indicator_interest_added (IndicateServer * server, ++ IndicateInterests interest, EmpathyStatusIcon *icon) ++{ ++ if (interest != INDICATE_INTEREST_SERVER_SIGNAL) { ++ return; ++ } ++ DEBUG ("Indicator received interest-added signal"); ++ empathy_indicator_interest_status_icon(FALSE, icon); ++} ++ ++static void ++empathy_indicator_interest_removed (IndicateServer * server, ++ IndicateInterests interest, EmpathyStatusIcon *icon) ++{ ++ if (interest != INDICATE_INTEREST_SERVER_SIGNAL) { ++ return; ++ } ++ ++ DEBUG ("Indicator received interest-removed signal"); ++ empathy_indicator_interest_status_icon(TRUE, icon); ++} ++ ++static void ++status_icon_set_use_libindicate (EmpathyStatusIcon *icon, ++ gboolean use_libindicate) ++{ ++ EmpathyStatusIconPriv *priv = GET_PRIV (icon); ++ ++ if (use_libindicate) { ++ empathy_indicator_manager_set_server_visible (priv->indicator_manager, TRUE); ++ } else { ++ empathy_indicator_manager_set_server_visible (priv->indicator_manager, FALSE); ++ empathy_status_icon_set_visible(TRUE, icon); ++ } ++} ++ ++static void ++status_icon_notify_libindicate_cb (GSettings *gsettings, ++ const gchar *key, ++ gpointer user_data) ++{ ++ EmpathyStatusIcon *icon = user_data; ++ EmpathyStatusIconPriv *priv = GET_PRIV (icon); ++ gboolean use_libindicate; ++ ++ use_libindicate = g_settings_get_boolean (priv->gsettings_ui, ++ EMPATHY_PREFS_UI_USE_LIBINDICATE); ++ status_icon_set_use_libindicate (icon, use_libindicate); ++} ++#endif + + static void + status_icon_notify_visibility_cb (GSettings *gsettings, +@@ -476,10 +573,36 @@ + EmpathyStatusIconPriv *priv = GET_PRIV (icon); + gboolean visible; + ++ + visible = gtk_window_is_active (priv->window); ++#ifdef HAVE_LIBINDICATE ++ gboolean use_libindicate; ++ use_libindicate = g_settings_get_boolean (priv->gsettings_ui, ++ EMPATHY_PREFS_UI_USE_LIBINDICATE); ++ if (use_libindicate) { ++ /* If indicators are used then we may very well not be active ++ * when toggled, as they are usually windows themselves. This ++ * makes it damn hard to toggle, so we just look at whether ++ * we are visible. ++ */ ++ visible = GTK_WIDGET_VISIBLE (priv->window); ++ status_icon_set_visibility (icon, TRUE, TRUE); ++ return; ++ } ++#endif ++ + status_icon_set_visibility (icon, !visible, TRUE); + } + ++#ifdef HAVE_LIBINDICATE ++static void ++indicate_server_activate_cb (EmpathyIndicatorManager *manager, ++ guint timestamp, EmpathyStatusIcon *icon) ++{ ++ status_icon_toggle_visibility (icon); ++} ++#endif ++ + static void + status_icon_presence_changed_cb (EmpathyStatusIcon *icon) + { +@@ -663,6 +786,9 @@ + g_object_unref (priv->notify_mgr); + g_object_unref (priv->gsettings_ui); + g_object_unref (priv->window); ++#ifdef HAVE_LIBINDICATE ++ g_object_unref (priv->indicator_manager); ++#endif + } + + static void +@@ -723,6 +849,13 @@ + G_CALLBACK (status_icon_notify_visibility_cb), + icon); + ++#ifdef HAVE_LIBINDICATE ++ g_signal_connect (priv->gsettings_ui, ++ "changed::" EMPATHY_PREFS_UI_USE_LIBINDICATE, ++ G_CALLBACK (status_icon_notify_libindicate_cb), ++ icon); ++#endif ++ + status_icon_create_menu (icon); + + g_signal_connect_swapped (priv->account_manager, +@@ -755,6 +888,9 @@ + EmpathyStatusIconPriv *priv; + EmpathyStatusIcon *icon; + gboolean should_hide; ++#ifdef HAVE_LIBINDICATE ++ gboolean use_libindicate; ++#endif + + g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); + +@@ -762,6 +898,24 @@ + priv = GET_PRIV (icon); + + priv->window = g_object_ref (window); ++#ifdef HAVE_LIBINDICATE ++ priv->indicator_manager = empathy_indicator_manager_dup_singleton (); ++ priv->indicate_server = indicate_server_ref_default (); ++ ++ g_signal_connect (priv->indicator_manager, "server-activate", ++ G_CALLBACK (indicate_server_activate_cb), ++ icon); ++ ++ g_signal_connect (priv->indicate_server, ++ INDICATE_SERVER_SIGNAL_INTEREST_ADDED, ++ G_CALLBACK(empathy_indicator_interest_added), ++ icon); ++ ++ g_signal_connect (priv->indicate_server, ++ INDICATE_SERVER_SIGNAL_INTEREST_REMOVED, ++ G_CALLBACK(empathy_indicator_interest_removed), ++ icon); ++#endif + + g_signal_connect_after (priv->window, "key-press-event", + G_CALLBACK (status_icon_key_press_event_cb), +@@ -778,6 +932,12 @@ + should_hide = TRUE; + } + ++#ifdef HAVE_LIBINDICATE ++ use_libindicate = g_settings_get_boolean (priv->gsettings_ui, ++ EMPATHY_PREFS_UI_USE_LIBINDICATE); ++ status_icon_set_use_libindicate (icon, use_libindicate); ++#endif ++ + status_icon_set_visibility (icon, !should_hide, FALSE); + + return icon; |