]> git.0d.be Git - empathy.git/blob - src/empathy-status-icon.c
Merge remote branch 'vminko/fix-573283'
[empathy.git] / src / empathy-status-icon.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007-2008 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * Authors: Xavier Claessens <xclaesse@gmail.com>
20  */
21
22 #include <config.h>
23
24 #include <string.h>
25
26 #include <glib.h>
27
28 #include <gtk/gtk.h>
29 #include <gdk/gdkkeysyms.h>
30 #include <glib/gi18n.h>
31
32 #include <libnotify/notification.h>
33 #include <libnotify/notify.h>
34
35 #include <telepathy-glib/account-manager.h>
36 #include <telepathy-glib/util.h>
37
38 #include <libempathy/empathy-gsettings.h>
39 #include <libempathy/empathy-utils.h>
40
41 #include <libempathy-gtk/empathy-presence-chooser.h>
42 #include <libempathy-gtk/empathy-ui-utils.h>
43 #include <libempathy-gtk/empathy-images.h>
44 #include <libempathy-gtk/empathy-new-message-dialog.h>
45 #include <libempathy-gtk/empathy-new-call-dialog.h>
46 #include <libempathy-gtk/empathy-notify-manager.h>
47
48 #include "empathy-accounts-dialog.h"
49 #include "empathy-status-icon.h"
50 #include "empathy-preferences.h"
51 #include "empathy-event-manager.h"
52
53 #define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
54 #include <libempathy/empathy-debug.h>
55
56 /* Number of ms to wait when blinking */
57 #define BLINK_TIMEOUT 500
58
59 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyStatusIcon)
60 typedef struct {
61         GtkStatusIcon       *icon;
62         TpAccountManager    *account_manager;
63         EmpathyNotifyManager *notify_mgr;
64         gboolean             showing_event_icon;
65         guint                blink_timeout;
66         EmpathyEventManager *event_manager;
67         EmpathyEvent        *event;
68         NotifyNotification  *notification;
69         GSettings           *gsettings_ui;
70
71         GtkWindow           *window;
72         GtkUIManager        *ui_manager;
73         GtkWidget           *popup_menu;
74         GtkAction           *show_window_item;
75         GtkAction           *new_message_item;
76         GtkAction           *status_item;
77 } EmpathyStatusIconPriv;
78
79 G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT);
80
81 static void
82 status_icon_notification_closed_cb (NotifyNotification *notification,
83                                     EmpathyStatusIcon  *icon)
84 {
85         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
86
87         g_object_unref (notification);
88
89         if (priv->notification == notification) {
90                 priv->notification = NULL;
91         }
92
93         if (!priv->event) {
94                 return;
95         }
96
97         /* inhibit other updates for this event */
98         empathy_event_inhibit_updates (priv->event);
99 }
100
101 static void
102 notification_close_helper (EmpathyStatusIconPriv *priv)
103 {
104         if (priv->notification != NULL) {
105                 notify_notification_close (priv->notification, NULL);
106                 priv->notification = NULL;
107         }
108 }
109
110 static void
111 notification_approve_cb (NotifyNotification *notification,
112                         gchar              *action,
113                         EmpathyStatusIcon  *icon)
114 {
115         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
116
117         if (priv->event)
118                 empathy_event_approve (priv->event);
119 }
120
121 static void
122 notification_decline_cb (NotifyNotification *notification,
123                         gchar              *action,
124                         EmpathyStatusIcon  *icon)
125 {
126         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
127
128         if (priv->event)
129                 empathy_event_decline (priv->event);
130 }
131
132 static void
133 add_notification_actions (EmpathyStatusIcon *self,
134                           NotifyNotification *notification)
135 {
136         EmpathyStatusIconPriv *priv = GET_PRIV (self);
137
138         switch (priv->event->type) {
139                 case EMPATHY_EVENT_TYPE_CHAT:
140                         notify_notification_add_action (notification,
141                                 "respond", _("Respond"), (NotifyActionCallback) notification_approve_cb,
142                                         self, NULL);
143                         break;
144
145                 case EMPATHY_EVENT_TYPE_VOIP:
146                         notify_notification_add_action (notification,
147                                 "reject", _("Reject"), (NotifyActionCallback) notification_decline_cb,
148                                         self, NULL);
149
150                         notify_notification_add_action (notification,
151                                 "answer", _("Answer"), (NotifyActionCallback) notification_approve_cb,
152                                         self, NULL);
153                         break;
154
155                 case EMPATHY_EVENT_TYPE_TRANSFER:
156                 case EMPATHY_EVENT_TYPE_INVITATION:
157                         notify_notification_add_action (notification,
158                                 "decline", _("Decline"), (NotifyActionCallback) notification_decline_cb,
159                                         self, NULL);
160
161                         notify_notification_add_action (notification,
162                                 "accept", _("Accept"), (NotifyActionCallback) notification_approve_cb,
163                                         self, NULL);
164                         break;
165
166                 default:
167                         break;
168         }
169 }
170
171 static void
172 status_icon_update_notification (EmpathyStatusIcon *icon)
173 {
174         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
175         GdkPixbuf *pixbuf = NULL;
176
177         if (!empathy_notify_manager_notification_is_enabled (priv->notify_mgr)) {
178                 /* always close the notification if this happens */
179                 notification_close_helper (priv);
180                 return;
181         }
182
183         if (priv->event) {
184                 gchar *message_esc = NULL;
185                 gboolean has_x_canonical_append;
186                 NotifyNotification *notification = priv->notification;
187
188                 if (priv->event->message != NULL)
189                         message_esc = g_markup_escape_text (priv->event->message, -1);
190
191                 has_x_canonical_append =
192                                 empathy_notify_manager_has_capability (priv->notify_mgr,
193                                         EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND);
194
195                 if (notification != NULL && ! has_x_canonical_append) {
196                         /* if the notification server supports x-canonical-append, it is
197                            better to not use notify_notification_update to avoid
198                            overwriting the current notification message */
199                         notify_notification_update (notification,
200                                                     priv->event->header, message_esc,
201                                                     NULL);
202                 } else {
203                         /* if the notification server supports x-canonical-append,
204                            the hint will be added, so that the message from the
205                            just created notification will be automatically appended
206                            to an existing notification with the same title.
207                            In this way the previous message will not be lost: the new
208                            message will appear below it, in the same notification */
209                         notification = notify_notification_new
210                                 (priv->event->header, message_esc, NULL);
211
212                         if (priv->notification == NULL) {
213                                 priv->notification = notification;
214                         }
215
216                         notify_notification_set_timeout (notification,
217                                                          NOTIFY_EXPIRES_DEFAULT);
218
219                         if (has_x_canonical_append) {
220                                 notify_notification_set_hint_string (notification,
221                                         EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND, "");
222                         }
223
224                         if (empathy_notify_manager_has_capability (priv->notify_mgr,
225                                    EMPATHY_NOTIFY_MANAGER_CAP_ACTIONS))
226                                 add_notification_actions (icon, notification);
227
228                         g_signal_connect (notification, "closed",
229                                           G_CALLBACK (status_icon_notification_closed_cb), icon);
230                 }
231
232                 pixbuf = empathy_notify_manager_get_pixbuf_for_notification (
233                                                                    priv->notify_mgr, priv->event->contact,
234                                                                    priv->event->icon_name);
235
236                 if (pixbuf != NULL) {
237                         notify_notification_set_icon_from_pixbuf (notification, pixbuf);
238                         g_object_unref (pixbuf);
239                 }
240
241                 notify_notification_show (notification, NULL);
242
243                 g_free (message_esc);
244         } else {
245                 notification_close_helper (priv);
246         }
247 }
248
249 static void
250 status_icon_update_tooltip (EmpathyStatusIcon *icon)
251 {
252         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
253
254         if (priv->event) {
255                 gchar *tooltip = NULL;
256
257                 if (priv->event->message != NULL)
258                                 tooltip = g_markup_printf_escaped ("<i>%s</i>\n%s",
259                                                                    priv->event->header,
260                                                                    priv->event->message);
261                 else
262                                 tooltip = g_markup_printf_escaped ("<i>%s</i>",
263                                                                    priv->event->header);
264                 gtk_status_icon_set_tooltip_markup (priv->icon, tooltip);
265                 g_free (tooltip);
266         } else {
267                 TpConnectionPresenceType type;
268                 gchar *msg;
269
270                 type = tp_account_manager_get_most_available_presence (
271                         priv->account_manager, NULL, &msg);
272
273                 if (!EMP_STR_EMPTY (msg)) {
274                         gtk_status_icon_set_tooltip_text (priv->icon, msg);
275                 }
276                 else {
277                         gtk_status_icon_set_tooltip_text (priv->icon,
278                                                 empathy_presence_get_default_message (type));
279                 }
280
281                 g_free (msg);
282         }
283 }
284
285 static void
286 status_icon_update_icon (EmpathyStatusIcon *icon)
287 {
288         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
289         const gchar           *icon_name;
290
291         if (priv->event && priv->showing_event_icon) {
292                 icon_name = priv->event->icon_name;
293         } else {
294                 TpConnectionPresenceType state;
295
296                 state = tp_account_manager_get_most_available_presence (
297                         priv->account_manager, NULL, NULL);
298
299                 /* An unset presence type here doesn't make sense. Force it
300                  * to be offline. */
301                 if (state == TP_CONNECTION_PRESENCE_TYPE_UNSET) {
302                         state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE;
303                 }
304
305                 icon_name = empathy_icon_name_for_presence (state);
306         }
307
308         if (icon_name != NULL)
309                 gtk_status_icon_set_from_icon_name (priv->icon, icon_name);
310 }
311
312 static gboolean
313 status_icon_blink_timeout_cb (EmpathyStatusIcon *icon)
314 {
315         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
316
317         priv->showing_event_icon = !priv->showing_event_icon;
318         status_icon_update_icon (icon);
319
320         return TRUE;
321 }
322 static void
323 status_icon_event_added_cb (EmpathyEventManager *manager,
324                             EmpathyEvent        *event,
325                             EmpathyStatusIcon   *icon)
326 {
327         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
328
329         if (priv->event) {
330                 return;
331         }
332
333         DEBUG ("New event %p", event);
334
335         priv->event = event;
336         if (event->must_ack) {
337                 priv->showing_event_icon = TRUE;
338                 status_icon_update_icon (icon);
339                 status_icon_update_tooltip (icon);
340         }
341         status_icon_update_notification (icon);
342
343         if (!priv->blink_timeout && priv->showing_event_icon) {
344                 priv->blink_timeout = g_timeout_add (BLINK_TIMEOUT,
345                                                      (GSourceFunc) status_icon_blink_timeout_cb,
346                                                      icon);
347         }
348 }
349
350 static void
351 status_icon_event_removed_cb (EmpathyEventManager *manager,
352                               EmpathyEvent        *event,
353                               EmpathyStatusIcon   *icon)
354 {
355         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
356
357         if (event != priv->event) {
358                 return;
359         }
360
361         priv->event = empathy_event_manager_get_top_event (priv->event_manager);
362
363         status_icon_update_tooltip (icon);
364         status_icon_update_icon (icon);
365
366         /* update notification anyway, as it's safe and we might have been
367          * changed presence in the meanwhile
368          */
369         status_icon_update_notification (icon);
370
371         if (!priv->event && priv->blink_timeout) {
372                 g_source_remove (priv->blink_timeout);
373                 priv->blink_timeout = 0;
374         }
375 }
376
377 static void
378 status_icon_event_updated_cb (EmpathyEventManager *manager,
379                               EmpathyEvent        *event,
380                               EmpathyStatusIcon   *icon)
381 {
382         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
383
384         if (event != priv->event) {
385                 return;
386         }
387
388         if (empathy_notify_manager_notification_is_enabled (priv->notify_mgr)) {
389                 status_icon_update_notification (icon);
390         }
391
392         status_icon_update_tooltip (icon);
393 }
394
395 static void
396 status_icon_set_visibility (EmpathyStatusIcon *icon,
397                             gboolean           visible,
398                             gboolean           store)
399 {
400         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
401
402         if (store) {
403                 g_settings_set_boolean (priv->gsettings_ui,
404                                         EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
405                                         !visible);
406         }
407
408         if (!visible) {
409                 empathy_window_iconify (priv->window, priv->icon);
410         } else {
411                 empathy_window_present (GTK_WINDOW (priv->window));
412         }
413 }
414
415 static void
416 status_icon_notify_visibility_cb (GSettings   *gsettings,
417                                   const gchar *key,
418                                   gpointer     user_data)
419 {
420         EmpathyStatusIcon *icon = user_data;
421         gboolean           hidden = FALSE;
422
423         hidden = g_settings_get_boolean (gsettings, key);
424         status_icon_set_visibility (icon, !hidden, FALSE);
425 }
426
427 static void
428 status_icon_toggle_visibility (EmpathyStatusIcon *icon)
429 {
430         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
431         gboolean               visible;
432
433         visible = gtk_window_is_active (priv->window);
434         status_icon_set_visibility (icon, !visible, TRUE);
435 }
436
437 static void
438 status_icon_presence_changed_cb (EmpathyStatusIcon *icon)
439 {
440         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
441
442         status_icon_update_icon (icon);
443         status_icon_update_tooltip (icon);
444
445         if (!empathy_notify_manager_notification_is_enabled (priv->notify_mgr)) {
446                 /* dismiss the outstanding notification if present */
447
448                 if (priv->notification) {
449                         notify_notification_close (priv->notification, NULL);
450                         priv->notification = NULL;
451                 }
452         }
453 }
454
455 static gboolean
456 status_icon_delete_event_cb (GtkWidget         *widget,
457                              GdkEvent          *event,
458                              EmpathyStatusIcon *icon)
459 {
460         status_icon_set_visibility (icon, FALSE, TRUE);
461         return TRUE;
462 }
463
464 static gboolean
465 status_icon_key_press_event_cb  (GtkWidget *window,
466                                  GdkEventKey *event,
467                                  EmpathyStatusIcon *icon)
468 {
469         if (event->keyval == GDK_KEY_Escape) {
470                 status_icon_set_visibility (icon, FALSE, TRUE);
471         }
472         return FALSE;
473 }
474
475 static void
476 status_icon_activate_cb (GtkStatusIcon     *status_icon,
477                          EmpathyStatusIcon *icon)
478 {
479         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
480
481         DEBUG ("%s", priv->event ? "event" : "toggle");
482
483         if (priv->event) {
484                 empathy_event_activate (priv->event);
485         } else {
486                 status_icon_toggle_visibility (icon);
487         }
488 }
489
490 static void
491 status_icon_show_hide_window_cb (GtkToggleAction   *action,
492                                  EmpathyStatusIcon *icon)
493 {
494         gboolean visible;
495
496         visible = gtk_toggle_action_get_active (action);
497         status_icon_set_visibility (icon, visible, TRUE);
498 }
499
500 static void
501 status_icon_new_message_cb (GtkAction         *action,
502                             EmpathyStatusIcon *icon)
503 {
504         empathy_new_message_dialog_show (NULL);
505 }
506
507 static void
508 status_icon_new_call_cb (GtkAction         *action,
509                             EmpathyStatusIcon *icon)
510 {
511         empathy_new_call_dialog_show (NULL);
512 }
513
514 static void
515 status_icon_quit_cb (GtkAction         *action,
516                      EmpathyStatusIcon *icon)
517 {
518         gtk_main_quit ();
519 }
520
521 static void
522 status_icon_popup_menu_cb (GtkStatusIcon     *status_icon,
523                            guint              button,
524                            guint              activate_time,
525                            EmpathyStatusIcon *icon)
526 {
527         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
528         GtkWidget             *menu_item;
529         GtkWidget             *submenu;
530         gboolean               show;
531
532         show = empathy_window_get_is_visible (GTK_WINDOW (priv->window));
533
534         g_signal_handlers_block_by_func (priv->show_window_item,
535                                          status_icon_show_hide_window_cb,
536                                          icon);
537         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_window_item),
538                                       show);
539         g_signal_handlers_unblock_by_func (priv->show_window_item,
540                                            status_icon_show_hide_window_cb,
541                                            icon);
542
543         menu_item = gtk_ui_manager_get_widget (priv->ui_manager, "/menu/status");
544         submenu = empathy_presence_chooser_create_menu ();
545         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), submenu);
546
547         gtk_menu_popup (GTK_MENU (priv->popup_menu),
548                         NULL, NULL,
549                         gtk_status_icon_position_menu,
550                         priv->icon,
551                         button,
552                         activate_time);
553 }
554
555 static void
556 status_icon_create_menu (EmpathyStatusIcon *icon)
557 {
558         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
559         GtkBuilder            *gui;
560         gchar                 *filename;
561
562         filename = empathy_file_lookup ("empathy-status-icon.ui", "src");
563         gui = empathy_builder_get_file (filename,
564                                         "ui_manager", &priv->ui_manager,
565                                         "menu", &priv->popup_menu,
566                                         "show_list", &priv->show_window_item,
567                                         "new_message", &priv->new_message_item,
568                                         "status", &priv->status_item,
569                                        NULL);
570         g_free (filename);
571
572         empathy_builder_connect (gui, icon,
573                               "show_list", "toggled", status_icon_show_hide_window_cb,
574                               "new_message", "activate", status_icon_new_message_cb,
575                               "new_call", "activate", status_icon_new_call_cb,
576                               "quit", "activate", status_icon_quit_cb,
577                               NULL);
578
579         g_object_ref (priv->ui_manager);
580         g_object_unref (gui);
581 }
582
583 static void
584 status_icon_status_changed_cb (TpAccount *account,
585                                TpConnectionStatus current,
586                                TpConnectionStatus previous,
587                                TpConnectionStatusReason reason,
588                                gchar *dbus_error_name,
589                                GHashTable *details,
590                                EmpathyStatusIcon *icon)
591 {
592         EmpathyStatusIconPriv *priv = GET_PRIV (icon);
593
594         gtk_action_set_sensitive (priv->new_message_item,
595                                   empathy_account_manager_get_accounts_connected (NULL));
596 }
597
598 static void
599 status_icon_finalize (GObject *object)
600 {
601         EmpathyStatusIconPriv *priv = GET_PRIV (object);
602
603         if (priv->blink_timeout) {
604                 g_source_remove (priv->blink_timeout);
605         }
606
607         if (priv->notification) {
608                 notify_notification_close (priv->notification, NULL);
609                 g_object_unref (priv->notification);
610                 priv->notification = NULL;
611         }
612
613         g_object_unref (priv->icon);
614         g_object_unref (priv->account_manager);
615         g_object_unref (priv->event_manager);
616         g_object_unref (priv->ui_manager);
617         g_object_unref (priv->notify_mgr);
618         g_object_unref (priv->gsettings_ui);
619         g_object_unref (priv->window);
620 }
621
622 static void
623 empathy_status_icon_class_init (EmpathyStatusIconClass *klass)
624 {
625         GObjectClass *object_class = G_OBJECT_CLASS (klass);
626
627         object_class->finalize = status_icon_finalize;
628
629         g_type_class_add_private (object_class, sizeof (EmpathyStatusIconPriv));
630 }
631
632 static void
633 account_manager_prepared_cb (GObject *source_object,
634                              GAsyncResult *result,
635                              gpointer user_data)
636 {
637         GList *list, *l;
638         TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
639         EmpathyStatusIcon *icon = user_data;
640         GError *error = NULL;
641
642         if (!tp_account_manager_prepare_finish (account_manager, result, &error)) {
643                 DEBUG ("Failed to prepare account manager: %s", error->message);
644                 g_error_free (error);
645                 return;
646         }
647
648         list = tp_account_manager_get_valid_accounts (account_manager);
649         for (l = list; l != NULL; l = l->next) {
650                 tp_g_signal_connect_object (l->data, "status-changed",
651                                              G_CALLBACK (status_icon_status_changed_cb),
652                                              icon, 0);
653         }
654         g_list_free (list);
655
656         status_icon_presence_changed_cb (icon);
657 }
658
659 static void
660 empathy_status_icon_init (EmpathyStatusIcon *icon)
661 {
662         EmpathyStatusIconPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (icon,
663                 EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconPriv);
664
665         icon->priv = priv;
666         priv->icon = gtk_status_icon_new ();
667         priv->account_manager = tp_account_manager_dup ();
668         priv->event_manager = empathy_event_manager_dup_singleton ();
669
670         tp_account_manager_prepare_async (priv->account_manager, NULL,
671             account_manager_prepared_cb, icon);
672
673         /* make icon listen and respond to MAIN_WINDOW_HIDDEN changes */
674         priv->gsettings_ui = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
675         g_signal_connect (priv->gsettings_ui,
676                           "changed::" EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
677                           G_CALLBACK (status_icon_notify_visibility_cb),
678                           icon);
679
680         status_icon_create_menu (icon);
681
682         g_signal_connect_swapped (priv->account_manager,
683                                   "most-available-presence-changed",
684                                   G_CALLBACK (status_icon_presence_changed_cb),
685                                   icon);
686         g_signal_connect (priv->event_manager, "event-added",
687                           G_CALLBACK (status_icon_event_added_cb),
688                           icon);
689         g_signal_connect (priv->event_manager, "event-removed",
690                           G_CALLBACK (status_icon_event_removed_cb),
691                           icon);
692         g_signal_connect (priv->event_manager, "event-updated",
693                           G_CALLBACK (status_icon_event_updated_cb),
694                           icon);
695         g_signal_connect (priv->icon, "activate",
696                           G_CALLBACK (status_icon_activate_cb),
697                           icon);
698         g_signal_connect (priv->icon, "popup-menu",
699                           G_CALLBACK (status_icon_popup_menu_cb),
700                           icon);
701
702         priv->notification = NULL;
703         priv->notify_mgr = empathy_notify_manager_dup_singleton ();
704 }
705
706 EmpathyStatusIcon *
707 empathy_status_icon_new (GtkWindow *window, gboolean hide_contact_list)
708 {
709         EmpathyStatusIconPriv *priv;
710         EmpathyStatusIcon     *icon;
711         gboolean               should_hide;
712
713         g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
714
715         icon = g_object_new (EMPATHY_TYPE_STATUS_ICON, NULL);
716         priv = GET_PRIV (icon);
717
718         priv->window = g_object_ref (window);
719
720         g_signal_connect_after (priv->window, "key-press-event",
721                           G_CALLBACK (status_icon_key_press_event_cb),
722                           icon);
723
724         g_signal_connect (priv->window, "delete-event",
725                           G_CALLBACK (status_icon_delete_event_cb),
726                           icon);
727
728         if (!hide_contact_list) {
729                 should_hide = g_settings_get_boolean (priv->gsettings_ui,
730                         EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN);
731         } else {
732                 should_hide = TRUE;
733         }
734
735         status_icon_set_visibility (icon, !should_hide, FALSE);
736
737         return icon;
738 }
739