diff --git a/src/empathy-misc.c b/src/empathy-misc.c index a1a0847..94f43ea 100644 --- a/src/empathy-misc.c +++ b/src/empathy-misc.c @@ -26,6 +26,117 @@ #include #include #include +#include + +#define ACTIONS "actions" +#define BODY "body" +#define BODY_HYPERLINKS "body-hyperlinks" +#define BODY_IMAGES "body-images" +#define BODY_MARKUP "body-markup" +#define ICON_MULTI "icon-multi" +#define ICON_STATIC "icon-static" +#define SOUND "sound" +#define IMAGE_SVG "image/svg+xml" +#define SYNCHRONOUS "x-canonical-synchronous" +#define APPEND "x-canonical-append" +#define LAYOUT_ICON_ONLY "x-canonical-icon-only" + +static gboolean g_capabilities[CAP_MAX] = { + FALSE, /* array init */ + FALSE, /* actions */ + FALSE, /* body */ + FALSE, /* body-hyperlinks */ + FALSE, /* body-imges */ + FALSE, /* body-markup */ + FALSE, /* icon-multi */ + FALSE, /* icon-static */ + FALSE, /* sound */ + FALSE, /* image/svg+xml */ + FALSE, /* synchronous-hint */ + FALSE, /* append-hint */ + FALSE /* icon-only-hint */ +}; + +static int have_notify_osd = -1; + +static void +set_cap (gpointer data, + gpointer user_data) +{ + /* test for "actions" */ + if (!g_strcmp0 (ACTIONS, (gchar*) data)) { + g_capabilities[CAP_ACTIONS] = TRUE; + } + + /* test for "body" */ + if (!g_strcmp0 (BODY, (gchar*) data)) { + g_capabilities[CAP_BODY] = TRUE; + } + + /* test for "body-hyperlinks" */ + if (!g_strcmp0 (BODY_HYPERLINKS, (gchar*) data)) { + g_capabilities[CAP_BODY_HYPERLINKS] = TRUE; + } + + /* test for "body-images" */ + if (!g_strcmp0 (BODY_IMAGES, (gchar*) data)) { + g_capabilities[CAP_BODY_IMAGES] = TRUE; + } + + /* test for "body-markup" */ + if (!g_strcmp0 (BODY_MARKUP, (gchar*) data)) { + g_capabilities[CAP_BODY_MARKUP] = TRUE; + } + + /* test for "icon-multi" */ + if (!g_strcmp0 (ICON_MULTI, (gchar*) data)) { + g_capabilities[CAP_ICON_MULTI] = TRUE; + } + + /* test for "icon-static" */ + if (!g_strcmp0 (ICON_STATIC, (gchar*) data)) { + g_capabilities[CAP_ICON_STATIC] = TRUE; + } + + /* test for "sound" */ + if (!g_strcmp0 (SOUND, (gchar*) data)) { + g_capabilities[CAP_SOUND] = TRUE; + } + + /* test for "image/svg+xml" */ + if (!g_strcmp0 (IMAGE_SVG, (gchar*) data)) { + g_capabilities[CAP_IMAGE_SVG] = TRUE; + } + + /* test for "canonical-private-1" */ + if (!g_strcmp0 (SYNCHRONOUS, (gchar*) data)) { + g_capabilities[CAP_SYNCHRONOUS] = TRUE; + } + + /* test for "canonical-private-2" */ + if (!g_strcmp0 (APPEND, (gchar*) data)) { + g_capabilities[CAP_APPEND] = TRUE; + } + + /* test for "canonical-private-3" */ + if (!g_strcmp0 (LAYOUT_ICON_ONLY, (gchar*) data)) { + g_capabilities[CAP_LAYOUT_ICON_ONLY] = TRUE; + } +} + +static void +init_caps (void) +{ + GList* caps_list; + + caps_list = notify_get_server_caps (); + if (caps_list) + { + g_list_foreach (caps_list, set_cap, NULL); + g_list_foreach (caps_list, (GFunc) g_free, NULL); + g_list_free (caps_list); + } +} /* public methods */ @@ -34,17 +145,44 @@ empathy_misc_get_pixbuf_for_notification (EmpathyContact *contact, const char *icon_name) { GdkPixbuf *pixbuf = NULL; + gint size; + gchar *server_name = NULL; + + if (have_notify_osd == -1) { + notify_get_server_info (&server_name, NULL, NULL, NULL); + if (!g_strcmp0 ("notify-osd", server_name)) { + have_notify_osd = TRUE; + } + else { + have_notify_osd = FALSE; + } + } + + if (have_notify_osd) { + size = 128; + + /* change the default new message icon with + the one shipped by notify-osd */ + if (!g_strcmp0 (icon_name, "im-message-new")) { + icon_name = "notification-message-im"; + } + } + else { + size = 48; + } if (contact != NULL) { pixbuf = empathy_pixbuf_avatar_from_contact_scaled (contact, - 48, 48); + size, size); } if (!pixbuf) { pixbuf = empathy_pixbuf_from_icon_name_sized - (icon_name, 48); + (icon_name, size); } + g_free (server_name); + return pixbuf; } @@ -75,3 +213,11 @@ empathy_notification_is_enabled (void) return TRUE; } +gboolean +empathy_notification_supports (EmpathyNotificationCapability cap) +{ + if (!g_capabilities[0]) { + init_caps (); + } + return g_capabilities[cap]; +} \ No newline at end of file diff --git a/src/empathy-misc.h b/src/empathy-misc.h index b3fe8fd..e67d87b 100644 --- a/src/empathy-misc.h +++ b/src/empathy-misc.h @@ -40,7 +40,24 @@ typedef enum { EMPATHY_NOTIFICATION_CLOSED_RESERVED = 4 } EmpathyNotificationClosedReason; +typedef enum { + CAP_ACTIONS = 1, + CAP_BODY, + CAP_BODY_HYPERLINKS, + CAP_BODY_IMAGES, + CAP_BODY_MARKUP, + CAP_ICON_MULTI, + CAP_ICON_STATIC, + CAP_SOUND, + CAP_IMAGE_SVG, + CAP_SYNCHRONOUS, + CAP_APPEND, + CAP_LAYOUT_ICON_ONLY, + CAP_MAX +} EmpathyNotificationCapability; + gboolean empathy_notification_is_enabled (void); +gboolean empathy_notification_supports (EmpathyNotificationCapability cap); GdkPixbuf * empathy_misc_get_pixbuf_for_notification (EmpathyContact *contact, const char *icon_name); diff --git a/src/empathy-status-icon.c b/src/empathy-status-icon.c index f6c63c5..ee09f9c 100644 --- a/src/empathy-status-icon.c +++ b/src/empathy-status-icon.c @@ -89,15 +89,20 @@ status_icon_notification_closed_cb (NotifyNotification *notification, #ifdef notify_notification_get_closed_reason reason = notify_notification_get_closed_reason (notification); #endif - if (priv->notification) { - g_object_unref (priv->notification); - priv->notification = NULL; - } + + g_object_unref (notification); if (!priv->event) { return; } + /* there's another pending notification caused by an append */ + if (notification != priv->notification) { + return; + } + + priv->notification = NULL; + /* the notification has been closed by the user, see the * DesktopNotification spec. */ @@ -139,20 +144,32 @@ status_icon_update_notification (EmpathyStatusIcon *icon) pixbuf = empathy_misc_get_pixbuf_for_notification (priv->event->contact, priv->event->icon_name); - if (priv->notification) { + /* replace only if append is not supported + and if having a previous notification */ + if (!empathy_notification_supports (CAP_APPEND) && + priv->notification != NULL) { notify_notification_update (priv->notification, priv->event->header, priv->event->message, NULL); } else { priv->notification = notify_notification_new_with_status_icon (priv->event->header, priv->event->message, NULL, priv->icon); + + /* set the append hint if it is supported */ + if (empathy_notification_supports (CAP_APPEND)) { + notify_notification_set_hint_string (priv->notification, + "x-canonical-append", + "allowed"); + } + + /* set the expires timeout */ notify_notification_set_timeout (priv->notification, NOTIFY_EXPIRES_DEFAULT); g_signal_connect (priv->notification, "closed", G_CALLBACK (status_icon_notification_closed_cb), icon); - } + } /* if icon doesn't exist libnotify will crash */ if (pixbuf != NULL) notify_notification_set_icon_from_pixbuf (priv->notification,