29
29
#include <gdk/gdkkeysyms.h>
30
30
#include <glib/gi18n.h>
32
#include <libnotify/notify.h>
33
#include <libnotify/notification.h>
34
#include <libnotify/notify.h>
36
32
#include <telepathy-glib/account-manager.h>
37
33
#include <telepathy-glib/util.h>
38
#include <telepathy-yell/telepathy-yell.h>
40
35
#include <libempathy/empathy-gsettings.h>
41
36
#include <libempathy/empathy-utils.h>
42
#include <libempathy/empathy-tp-streamed-media.h>
44
38
#include <libempathy-gtk/empathy-presence-chooser.h>
45
39
#include <libempathy-gtk/empathy-ui-utils.h>
46
40
#include <libempathy-gtk/empathy-images.h>
47
41
#include <libempathy-gtk/empathy-new-message-dialog.h>
48
42
#include <libempathy-gtk/empathy-new-call-dialog.h>
49
#include <libempathy-gtk/empathy-notify-manager.h>
51
44
#include "empathy-accounts-dialog.h"
52
45
#include "empathy-status-icon.h"
53
46
#include "empathy-preferences.h"
54
47
#include "empathy-event-manager.h"
56
#ifdef HAVE_LIBINDICATE
57
#include "empathy-indicator-manager.h"
58
#include <libindicate/server.h>
59
#include <libindicate/interests.h>
62
49
#define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
63
50
#include <libempathy/empathy-debug.h>
83
68
GtkAction *show_window_item;
84
69
GtkAction *new_message_item;
85
70
GtkAction *status_item;
86
#ifdef HAVE_LIBINDICATE
87
EmpathyIndicatorManager *indicator_manager;
88
IndicateServer *indicate_server;
90
71
} EmpathyStatusIconPriv;
92
73
G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT);
95
status_icon_notification_closed_cb (NotifyNotification *notification,
96
EmpathyStatusIcon *icon)
98
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
100
g_object_unref (notification);
102
if (priv->notification == notification) {
103
priv->notification = NULL;
110
/* inhibit other updates for this event */
111
empathy_event_inhibit_updates (priv->event);
115
notification_close_helper (EmpathyStatusIconPriv *priv)
117
if (priv->notification != NULL) {
118
notify_notification_close (priv->notification, NULL);
119
priv->notification = NULL;
124
notification_approve_no_video_cb (NotifyNotification *notification,
126
EmpathyStatusIcon *icon)
128
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
131
tpy_call_channel_send_video (
132
TPY_CALL_CHANNEL (priv->event->handler_instance),
134
empathy_event_approve (priv->event);
139
notification_approve_cb (NotifyNotification *notification,
141
EmpathyStatusIcon *icon)
143
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
146
empathy_event_approve (priv->event);
150
notification_decline_cb (NotifyNotification *notification,
152
EmpathyStatusIcon *icon)
154
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
157
empathy_event_decline (priv->event);
161
add_notification_actions (EmpathyStatusIcon *self,
162
NotifyNotification *notification)
164
EmpathyStatusIconPriv *priv = GET_PRIV (self);
167
switch (priv->event->type) {
168
case EMPATHY_EVENT_TYPE_CHAT:
169
notify_notification_add_action (notification,
170
"respond", _("Respond"), (NotifyActionCallback) notification_approve_cb,
174
case EMPATHY_EVENT_TYPE_VOIP:
175
case EMPATHY_EVENT_TYPE_CALL:
176
if (priv->event->type == EMPATHY_EVENT_TYPE_VOIP)
177
video = empathy_tp_streamed_media_has_initial_video (
178
EMPATHY_TP_STREAMED_MEDIA (priv->event->handler_instance));
180
video = tpy_call_channel_has_initial_video (
181
TPY_CALL_CHANNEL (priv->event->handler_instance));
183
notify_notification_add_action (notification,
184
"reject", _("Reject"), (NotifyActionCallback) notification_decline_cb,
188
if (video && priv->event->type == EMPATHY_EVENT_TYPE_CALL)
189
notify_notification_add_action (notification,
190
"answer-no-video", _("Answer"), (NotifyActionCallback)
191
notification_approve_no_video_cb,
194
notify_notification_add_action (notification,
195
"answer", video ? _("Answer with video") : _("Answer"),
196
(NotifyActionCallback) notification_approve_cb,
200
case EMPATHY_EVENT_TYPE_TRANSFER:
201
case EMPATHY_EVENT_TYPE_INVITATION:
202
notify_notification_add_action (notification,
203
"decline", _("Decline"), (NotifyActionCallback) notification_decline_cb,
206
notify_notification_add_action (notification,
207
"accept", _("Accept"), (NotifyActionCallback) notification_approve_cb,
217
status_icon_update_notification (EmpathyStatusIcon *icon)
219
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
220
GdkPixbuf *pixbuf = NULL;
222
if (!empathy_notify_manager_notification_is_enabled (priv->notify_mgr)) {
223
/* always close the notification if this happens */
224
notification_close_helper (priv);
229
if (priv->event->type == EMPATHY_EVENT_TYPE_VOIP
230
|| priv->event->type == EMPATHY_EVENT_TYPE_CALL
231
|| priv->event->type == EMPATHY_EVENT_TYPE_TRANSFER) {
232
empathy_event_activate (priv->event);
235
gchar *message_esc = NULL;
236
gboolean has_x_canonical_append;
237
NotifyNotification *notification = priv->notification;
239
if (priv->event->message != NULL)
240
message_esc = g_markup_escape_text (priv->event->message, -1);
242
has_x_canonical_append =
243
empathy_notify_manager_has_capability (priv->notify_mgr,
244
EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND);
246
if (notification != NULL && ! has_x_canonical_append) {
247
/* if the notification server supports x-canonical-append, it is
248
better to not use notify_notification_update to avoid
249
overwriting the current notification message */
250
notify_notification_update (notification,
251
priv->event->header, message_esc,
254
/* if the notification server supports x-canonical-append,
255
the hint will be added, so that the message from the
256
just created notification will be automatically appended
257
to an existing notification with the same title.
258
In this way the previous message will not be lost: the new
259
message will appear below it, in the same notification */
260
notification = notify_notification_new
261
(priv->event->header, message_esc, NULL);
263
if (priv->notification == NULL) {
264
priv->notification = notification;
267
notify_notification_set_timeout (notification,
268
NOTIFY_EXPIRES_DEFAULT);
270
if (has_x_canonical_append) {
271
notify_notification_set_hint_string (notification,
272
EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND, "");
275
if (empathy_notify_manager_has_capability (priv->notify_mgr,
276
EMPATHY_NOTIFY_MANAGER_CAP_ACTIONS))
277
add_notification_actions (icon, notification);
279
g_signal_connect (notification, "closed",
280
G_CALLBACK (status_icon_notification_closed_cb), icon);
283
pixbuf = empathy_notify_manager_get_pixbuf_for_notification (
284
priv->notify_mgr, priv->event->contact,
285
priv->event->icon_name);
287
if (pixbuf != NULL) {
288
notify_notification_set_icon_from_pixbuf (notification, pixbuf);
289
g_object_unref (pixbuf);
292
notify_notification_show (notification, NULL);
294
g_free (message_esc);
296
notification_close_helper (priv);
301
76
status_icon_update_tooltip (EmpathyStatusIcon *icon)
303
78
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
474
227
empathy_window_present (GTK_WINDOW (priv->window));
477
#ifdef HAVE_LIBINDICATE
479
empathy_status_icon_set_visible (gboolean show_icon, EmpathyStatusIcon *icon)
481
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
482
gtk_status_icon_set_visible (priv->icon, show_icon);
486
empathy_indicator_interest_status_icon (gboolean icon_visibility,
487
EmpathyStatusIcon *icon)
489
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
490
EmpathyIndicatorManager *manager;
491
gboolean use_libindicate;
493
manager = empathy_indicator_manager_dup_singleton();
494
use_libindicate = g_settings_get_boolean (priv->gsettings_ui,
495
EMPATHY_PREFS_UI_USE_LIBINDICATE);
497
if (use_libindicate && !icon_visibility) {
498
empathy_indicator_manager_set_server_visible (manager, TRUE);
499
/* Hide the status icon so there are not two ways to access
502
DEBUG ("Hiding the icon, we are shown in the indicator");
503
empathy_status_icon_set_visible (FALSE, icon);
505
empathy_indicator_manager_set_server_visible (manager,
507
DEBUG ("Show the icon, we are not shown in the indicator");
508
empathy_status_icon_set_visible (TRUE, icon);
513
empathy_indicator_interest_added (IndicateServer * server,
514
IndicateInterests interest, EmpathyStatusIcon *icon)
516
if (interest != INDICATE_INTEREST_SERVER_SIGNAL) {
519
DEBUG ("Indicator received interest-added signal");
520
empathy_indicator_interest_status_icon(FALSE, icon);
524
empathy_indicator_interest_removed (IndicateServer * server,
525
IndicateInterests interest, EmpathyStatusIcon *icon)
527
if (interest != INDICATE_INTEREST_SERVER_SIGNAL) {
531
DEBUG ("Indicator received interest-removed signal");
532
empathy_indicator_interest_status_icon(TRUE, icon);
536
status_icon_set_use_libindicate (EmpathyStatusIcon *icon,
537
gboolean use_libindicate)
539
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
541
if (use_libindicate) {
542
empathy_indicator_manager_set_server_visible (priv->indicator_manager, TRUE);
544
empathy_indicator_manager_set_server_visible (priv->indicator_manager, FALSE);
545
empathy_status_icon_set_visible(TRUE, icon);
550
status_icon_notify_libindicate_cb (GSettings *gsettings,
554
EmpathyStatusIcon *icon = user_data;
555
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
556
gboolean use_libindicate;
558
use_libindicate = g_settings_get_boolean (priv->gsettings_ui,
559
EMPATHY_PREFS_UI_USE_LIBINDICATE);
560
status_icon_set_use_libindicate (icon, use_libindicate);
565
232
status_icon_notify_visibility_cb (GSettings *gsettings,
579
246
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
580
247
gboolean visible;
583
249
visible = gtk_window_is_active (priv->window);
584
#ifdef HAVE_LIBINDICATE
585
gboolean use_libindicate;
586
use_libindicate = g_settings_get_boolean (priv->gsettings_ui,
587
EMPATHY_PREFS_UI_USE_LIBINDICATE);
588
if (use_libindicate) {
589
/* If indicators are used then we may very well not be active
590
* when toggled, as they are usually windows themselves. This
591
* makes it damn hard to toggle, so we just look at whether
594
visible = GTK_WIDGET_VISIBLE (priv->window);
595
status_icon_set_visibility (icon, TRUE, TRUE);
600
250
status_icon_set_visibility (icon, !visible, TRUE);
603
#ifdef HAVE_LIBINDICATE
605
indicate_server_activate_cb (EmpathyIndicatorManager *manager,
606
guint timestamp, EmpathyStatusIcon *icon)
608
status_icon_toggle_visibility (icon);
613
254
status_icon_presence_changed_cb (EmpathyStatusIcon *icon)
615
EmpathyStatusIconPriv *priv = GET_PRIV (icon);
617
256
status_icon_update_icon (icon);
618
257
status_icon_update_tooltip (icon);
620
if (!empathy_notify_manager_notification_is_enabled (priv->notify_mgr)) {
621
/* dismiss the outstanding notification if present */
623
if (priv->notification) {
624
notify_notification_close (priv->notification, NULL);
625
priv->notification = NULL;