1 /* Notification plugin for Claws Mail
2 * Copyright (C) 2005-2022 Holger Berndt and the Claws Mail Team.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 /* This module is of course inspired by the trayicon plugin which is
19 * shipped with Claws Mail, copyrighted by the Claws Mail Team. */
23 # include "claws-features.h"
27 #include <glib/gi18n.h>
29 #ifdef NOTIFICATION_TRAYICON
31 #include "notification_trayicon.h"
32 #include "notification_prefs.h"
33 #include "notification_core.h"
34 #include "notification_hotkeys.h"
35 #include "notification_pixbuf.h"
36 #include "notification_foldercheck.h"
40 #include "mainwindow.h"
41 #include "prefs_common.h"
42 #include "alertpanel.h"
44 #ifndef USE_ALT_ADDRBOOK
45 #include "addressbook.h"
46 #include "addrindex.h"
48 #include "addressbook-dbus.h"
51 #include "gtk/manage_window.h"
52 #include "common/utils.h"
53 #include "gtk/gtkutils.h"
56 static void notification_trayicon_account_list_reset(const gchar
*,
60 static GdkPixbuf
* notification_trayicon_create(void);
62 static void notification_trayicon_on_popup_menu(GtkStatusIcon
*,guint
,
64 static gboolean
notification_trayicon_on_size_changed(GtkStatusIcon
*,
67 static void trayicon_get_all_cb(GtkAction
*, gpointer
);
68 static void trayicon_get_from_account_cb(GtkAction
*, gpointer
);
69 static void trayicon_compose_cb(GtkAction
*, gpointer
);
70 static void trayicon_compose_acc_cb(GtkMenuItem
*, gpointer
);
71 static void trayicon_addressbook_cb(GtkAction
*, gpointer
);
72 static void trayicon_exit_cb(GtkAction
*,gpointer
);
73 static void trayicon_toggle_offline_cb(GtkAction
*,gpointer
);
75 static void trayicon_toggle_notify_cb(GtkAction
*,gpointer
);
79 #include <libnotify/notify.h>
81 #ifndef NOTIFY_CHECK_VERSION
82 # define NOTIFY_CHECK_VERSION(a,b,c) 0
92 NotifyNotification
*notification
;
94 } NotificationTrayiconPopup
;
96 static NotificationTrayiconPopup popup
;
98 static gboolean
notification_trayicon_popup_add_msg(MsgInfo
*,
99 NotificationFolderType
);
100 static gboolean
notification_trayicon_popup_create(MsgInfo
*,
101 NotificationFolderType
);
102 static void popup_timeout_fun(NotifyNotification
*, gpointer
);
103 static void notification_trayicon_popup_free_func(gpointer
);
104 static void notification_trayicon_popup_default_action_cb(NotifyNotification
*,
106 static gchar
* notification_trayicon_popup_assemble_summary(void);
107 static gchar
* notification_trayicon_popup_assemble_body(MsgInfo
*);
108 static void notification_trayicon_popup_count_msgs(NotificationFolderType
);
110 G_LOCK_DEFINE_STATIC(trayicon_popup
);
114 static GtkStatusIcon
*trayicon
;
115 static gboolean updating_menu
= FALSE
;
116 static GtkWidget
*traymenu_popup
;
117 static GtkWidget
*focused_widget
= NULL
;
119 static GtkActionEntry trayicon_popup_menu_entries
[] = {
120 {"SysTrayiconPopup", NULL
, "SysTrayiconPopup", NULL
, NULL
, NULL
},
121 {"SysTrayiconPopup/GetMail", NULL
, N_("_Get Mail"), NULL
, NULL
, G_CALLBACK(trayicon_get_all_cb
) },
122 {"SysTrayiconPopup/GetMailAcc", NULL
, N_("_Get Mail from account"), NULL
, NULL
, NULL
},
123 {"SysTrayiconPopup/---", NULL
, "---", NULL
, NULL
, NULL
},
124 {"SysTrayiconPopup/Email", NULL
, N_("_Email"), NULL
, NULL
, G_CALLBACK(trayicon_compose_cb
) },
125 {"SysTrayiconPopup/EmailAcc", NULL
, N_("E_mail from account"), NULL
, NULL
, NULL
},
126 {"SysTrayiconPopup/OpenAB", NULL
, N_("Open A_ddressbook"), NULL
, NULL
, G_CALLBACK(trayicon_addressbook_cb
) },
127 {"SysTrayiconPopup/Exit", NULL
, N_("E_xit Claws Mail"), NULL
, NULL
, G_CALLBACK(trayicon_exit_cb
) },
130 static GtkToggleActionEntry trayicon_popup_toggle_menu_entries
[] =
132 {"SysTrayiconPopup/ToggleOffline", NULL
, N_("_Work Offline"), NULL
, NULL
, G_CALLBACK(trayicon_toggle_offline_cb
), FALSE
},
133 #ifdef HAVE_LIBNOTIFY
134 {"SysTrayiconPopup/ShowBubbles", NULL
, N_("Show Trayicon Notifications"), NULL
, NULL
, G_CALLBACK(trayicon_toggle_notify_cb
), FALSE
},
139 void notification_trayicon_msg(MsgInfo
*msginfo
)
141 #ifndef HAVE_LIBNOTIFY
146 NotificationFolderType nftype
;
149 nftype
= F_TYPE_MAIL
;
151 if(!msginfo
|| !notify_config
.trayicon_enabled
||
152 !notify_config
.trayicon_popup_enabled
||
153 !MSG_IS_NEW(msginfo
->flags
))
156 if(notify_config
.trayicon_folder_specific
) {
160 gboolean found
= FALSE
;
162 if(!(msginfo
->folder
))
165 identifier
= folder_item_get_identifier(msginfo
->folder
);
168 notification_register_folder_specific_list
169 (TRAYICON_SPECIFIC_FOLDER_ID_STR
);
170 list
= notification_foldercheck_get_list(id
);
171 for(; (list
!= NULL
) && !found
; list
= g_slist_next(list
)) {
172 gchar
*list_identifier
;
173 FolderItem
*list_item
= (FolderItem
*) list
->data
;
175 list_identifier
= folder_item_get_identifier(list_item
);
176 if(!g_strcmp0(list_identifier
, identifier
))
179 g_free(list_identifier
);
185 } /* folder specific */
187 ftype
= msginfo
->folder
->folder
->klass
->type
;
189 G_LOCK(trayicon_popup
);
190 /* Check out which type to notify about */
196 nftype
= F_TYPE_MAIL
;
199 nftype
= F_TYPE_NEWS
;
202 if((uistr
= msginfo
->folder
->folder
->klass
->uistr
) == NULL
) {
203 G_UNLOCK(trayicon_popup
);
206 else if(!strcmp(uistr
, "vCalendar"))
207 nftype
= F_TYPE_CALENDAR
;
208 else if(!strcmp(uistr
, "RSSyl"))
211 debug_print("Notification Plugin: Unknown folder type %d\n",ftype
);
212 G_UNLOCK(trayicon_popup
);
217 debug_print("Notification Plugin: Unknown folder type %d\n",ftype
);
218 G_UNLOCK(trayicon_popup
);
223 notification_trayicon_popup_add_msg(msginfo
, nftype
);
225 G_UNLOCK(trayicon_popup
);
227 #endif /* HAVE_LIBNOTIFY */
230 void notification_trayicon_destroy(void)
233 gtk_status_icon_set_visible(trayicon
, FALSE
);
234 g_object_unref(trayicon
);
239 void notification_update_trayicon()
242 static GdkPixbuf
*old_icon
= NULL
;
245 NotificationMsgCount count
;
248 if(!notify_config
.trayicon_enabled
)
251 if(notify_config
.trayicon_folder_specific
) {
254 notification_register_folder_specific_list
255 (TRAYICON_SPECIFIC_FOLDER_ID_STR
);
256 list
= notification_foldercheck_get_list(id
);
261 notification_core_get_msg_count(list
, &count
);
265 #ifdef NOTIFICATION_HOTKEYS
266 notification_hotkeys_update_bindings();
269 old_icon
= notification_trayicon_create();
271 debug_print("Notification plugin: Could not create trayicon\n");
277 buf
= g_strdup_printf(_("New %d, Unread: %d, Total: %d"),
278 count
.new_msgs
, count
.unread_msgs
,
280 gtk_status_icon_set_tooltip_text(trayicon
, buf
);
285 (prefs_common_get_prefs()->work_offline
) ? (offset
= 1) : (offset
= 0);
287 if((count
.new_msgs
> 0) && (count
.unreadmarked_msgs
> 0))
289 notification_pixbuf_get(NOTIFICATION_TRAYICON_NEWMARKEDMAIL
+offset
);
290 else if(count
.new_msgs
> 0)
292 notification_pixbuf_get(NOTIFICATION_TRAYICON_NEWMAIL
+offset
);
293 else if(count
.unreadmarked_msgs
> 0)
295 notification_pixbuf_get(NOTIFICATION_TRAYICON_UNREADMARKEDMAIL
+offset
);
296 else if(count
.unread_msgs
> 0)
298 notification_pixbuf_get(NOTIFICATION_TRAYICON_UNREADMAIL
+offset
);
301 notification_pixbuf_get(NOTIFICATION_TRAYICON_NOMAIL
+offset
);
303 if(new_icon
!= old_icon
) {
304 gtk_status_icon_set_from_pixbuf(trayicon
, new_icon
);
309 gboolean
notification_trayicon_main_window_close(gpointer source
, gpointer data
)
311 if(!notify_config
.trayicon_enabled
)
315 gboolean
*close_allowed
= (gboolean
*)source
;
317 if(notify_config
.trayicon_close_to_tray
) {
318 MainWindow
*mainwin
= mainwindow_get_mainwindow();
320 *close_allowed
= FALSE
;
321 if(mainwin
&& gtk_widget_get_visible(GTK_WIDGET(mainwin
->window
))) {
322 focused_widget
= gtk_window_get_focus(GTK_WINDOW(mainwin
->window
));
323 main_window_hide(mainwin
);
330 gboolean
notification_trayicon_main_window_got_iconified(gpointer source
,
333 MainWindow
*mainwin
= mainwindow_get_mainwindow();
335 if(!notify_config
.trayicon_enabled
)
338 if(notify_config
.trayicon_hide_when_iconified
&&
339 mainwin
&& gtk_widget_get_visible(GTK_WIDGET(mainwin
->window
))
340 && !gtk_window_get_skip_taskbar_hint(GTK_WINDOW(mainwin
->window
))) {
341 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mainwin
->window
), TRUE
);
346 static void notification_trayicon_account_list_reset(const gchar
*menuname
,
351 GtkWidget
*menu
, *submenu
;
353 PrefsAccount
*ac_prefs
;
355 GList
*account_list
= account_get_list();
357 menu
= gtk_ui_manager_get_widget(gtkut_ui_manager(), menuname
);
358 gtk_widget_show(menu
);
360 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu
), NULL
);
361 submenu
= gtk_menu_new();
363 for(cur_ac
= account_list
; cur_ac
!= NULL
; cur_ac
= cur_ac
->next
) {
364 ac_prefs
= (PrefsAccount
*)cur_ac
->data
;
366 /* accounts list for receiving: skip SMTP-only accounts */
367 if (receive
&& ac_prefs
->protocol
== A_NONE
)
370 menuitem
= gtk_menu_item_new_with_label
371 (ac_prefs
->account_name
? ac_prefs
->account_name
373 gtk_widget_show(menuitem
);
374 gtk_menu_shell_append(GTK_MENU_SHELL(submenu
), menuitem
);
375 g_signal_connect(G_OBJECT(menuitem
), "activate",
376 G_CALLBACK(callback
),
379 gtk_widget_show(submenu
);
380 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu
), submenu
);
383 gboolean
notification_trayicon_account_list_changed(gpointer source
,
386 if (notify_config
.trayicon_enabled
) {
387 notification_trayicon_account_list_reset("/Menus/SysTrayiconPopup/GetMailAcc",
388 (gpointer
)trayicon_get_from_account_cb
, TRUE
);
389 notification_trayicon_account_list_reset("/Menus/SysTrayiconPopup/EmailAcc",
390 (gpointer
)trayicon_compose_acc_cb
, FALSE
);
395 static GdkPixbuf
* notification_trayicon_create(void)
397 GdkPixbuf
*trayicon_nomail
;
398 GtkActionGroup
*action_group
;
400 trayicon_nomail
= notification_pixbuf_get(NOTIFICATION_TRAYICON_NOMAIL
);
402 notification_trayicon_destroy();
404 trayicon
= gtk_status_icon_new_from_pixbuf(trayicon_nomail
);
406 g_signal_connect(G_OBJECT(trayicon
), "activate",
407 G_CALLBACK(notification_trayicon_on_activate
), NULL
);
408 g_signal_connect(G_OBJECT(trayicon
), "popup-menu",
409 G_CALLBACK(notification_trayicon_on_popup_menu
), NULL
);
410 g_signal_connect(G_OBJECT(trayicon
), "size-changed",
411 G_CALLBACK(notification_trayicon_on_size_changed
), NULL
);
414 action_group
= cm_menu_create_action_group("SysTrayiconPopup", trayicon_popup_menu_entries
,
415 G_N_ELEMENTS(trayicon_popup_menu_entries
), NULL
);
416 gtk_action_group_add_toggle_actions(action_group
, trayicon_popup_toggle_menu_entries
,
417 G_N_ELEMENTS(trayicon_popup_toggle_menu_entries
), NULL
);
419 MENUITEM_ADDUI("/Menus", "SysTrayiconPopup", "SysTrayiconPopup", GTK_UI_MANAGER_MENU
)
420 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "GetMail", "SysTrayiconPopup/GetMail", GTK_UI_MANAGER_MENUITEM
)
421 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "GetMailAcc", "SysTrayiconPopup/GetMailAcc", GTK_UI_MANAGER_MENU
)
422 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator1", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR
)
423 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Email", "SysTrayiconPopup/Email", GTK_UI_MANAGER_MENUITEM
)
424 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "EmailAcc", "SysTrayiconPopup/EmailAcc", GTK_UI_MANAGER_MENU
)
425 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator2", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR
)
426 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "OpenAB", "SysTrayiconPopup/OpenAB", GTK_UI_MANAGER_MENUITEM
)
427 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator3", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR
)
428 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "ToggleOffline", "SysTrayiconPopup/ToggleOffline", GTK_UI_MANAGER_MENUITEM
)
429 #ifdef HAVE_LIBNOTIFY
430 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "ShowBubbles", "SysTrayiconPopup/ShowBubbles", GTK_UI_MANAGER_MENUITEM
)
432 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Separator4", "SysTrayiconPopup/---", GTK_UI_MANAGER_SEPARATOR
)
433 MENUITEM_ADDUI("/Menus/SysTrayiconPopup", "Exit", "SysTrayiconPopup/Exit", GTK_UI_MANAGER_MENUITEM
)
435 traymenu_popup
= gtk_menu_item_get_submenu(GTK_MENU_ITEM(
436 gtk_ui_manager_get_widget(gtkut_ui_manager(), "/Menus/SysTrayiconPopup")));
439 return trayicon_nomail
;
442 void notification_trayicon_on_activate(GtkStatusIcon
*status_icon
, gpointer user_data
)
444 MainWindow
*mainwin
= mainwindow_get_mainwindow();
446 if(mainwin
&& gtk_widget_get_visible(GTK_WIDGET(mainwin
->window
)) == TRUE
)
447 focused_widget
= gtk_window_get_focus(GTK_WINDOW(mainwin
->window
));
449 notification_toggle_hide_show_window();
451 if(mainwin
&& gtk_widget_get_visible(GTK_WIDGET(mainwin
->window
)) == TRUE
)
452 gtk_window_set_focus(GTK_WINDOW(mainwin
->window
), focused_widget
);
455 static void notification_trayicon_on_popup_menu(GtkStatusIcon
*status_icon
,
456 guint button
, guint activate_time
,
459 MainWindow
*mainwin
= mainwindow_get_mainwindow();
464 /* tell callbacks to skip any event */
465 updating_menu
= TRUE
;
466 /* initialize checkitems according to current states */
467 cm_toggle_menu_set_active("SysTrayiconPopup/ToggleOffline", prefs_common_get_prefs()->work_offline
);
468 #ifdef HAVE_LIBNOTIFY
469 cm_toggle_menu_set_active("SysTrayiconPopup/ShowBubbles", notify_config
.trayicon_popup_enabled
);
471 cm_menu_set_sensitive("SysTrayiconPopup/GetMail", mainwin
->lock_count
== 0);
472 cm_menu_set_sensitive("SysTrayiconPopup/GetMailAcc", mainwin
->lock_count
== 0);
473 cm_menu_set_sensitive("SysTrayiconPopup/Exit", mainwin
->lock_count
== 0);
475 updating_menu
= FALSE
;
477 gtk_menu_popup_at_pointer(GTK_MENU(traymenu_popup
), NULL
);
480 static gboolean
notification_trayicon_on_size_changed(GtkStatusIcon
*icon
,
484 notification_update_msg_counts(NULL
);
488 /* popup menu callbacks */
489 static void trayicon_get_all_cb(GtkAction
*action
, gpointer data
)
491 MainWindow
*mainwin
= mainwindow_get_mainwindow();
492 inc_all_account_mail_cb(mainwin
, 0, NULL
);
495 static void trayicon_get_from_account_cb(GtkAction
*action
, gpointer data
)
497 MainWindow
*mainwin
= mainwindow_get_mainwindow();
498 PrefsAccount
*account
= (PrefsAccount
*)data
;
499 inc_account_mail(mainwin
, account
);
502 static void trayicon_compose_cb(GtkAction
*action
, gpointer data
)
504 MainWindow
*mainwin
= mainwindow_get_mainwindow();
505 compose_mail_cb(mainwin
, 0, NULL
);
508 static void trayicon_compose_acc_cb(GtkMenuItem
*menuitem
, gpointer data
)
510 compose_new((PrefsAccount
*)data
, NULL
, NULL
);
513 static void trayicon_addressbook_cb(GtkAction
*action
, gpointer data
)
515 #ifndef USE_ALT_ADDRBOOK
516 addressbook_open(NULL
);
518 GError
* error
= NULL
;
520 addressbook_dbus_open(FALSE
, &error
);
522 g_warning("%s", error
->message
);
528 static void trayicon_toggle_offline_cb(GtkAction
*action
, gpointer data
)
530 /* toggle offline mode if menu checkitem has been clicked */
532 MainWindow
*mainwin
= mainwindow_get_mainwindow();
533 main_window_toggle_work_offline(mainwin
, !prefs_common_get_prefs()->work_offline
, TRUE
);
537 #ifdef HAVE_LIBNOTIFY
538 static void trayicon_toggle_notify_cb(GtkAction
*action
, gpointer data
)
541 notify_config
.trayicon_popup_enabled
= !notify_config
.trayicon_popup_enabled
;
546 static void app_exit_cb(MainWindow
*mainwin
, guint action
, GtkWidget
*widget
)
548 if(prefs_common_get_prefs()->confirm_on_exit
) {
549 if(alertpanel(_("Exit"), _("Exit Claws Mail?"),
550 NULL
, _("_Cancel"), NULL
, _("_OK"),
551 NULL
, NULL
, ALERTFOCUS_FIRST
) != G_ALERTALTERNATE
) {
554 manage_window_focus_in(mainwin
->window
, NULL
, NULL
);
557 if (prefs_common_get_prefs()->clean_on_exit
) {
558 if (!main_window_empty_trash(mainwin
, prefs_common_get_prefs()->ask_on_clean
, TRUE
))
562 app_will_exit(NULL
, mainwin
);
565 static void trayicon_exit_cb(GtkAction
*action
, gpointer data
)
567 MainWindow
*mainwin
= mainwindow_get_mainwindow();
569 if(mainwin
->lock_count
== 0) {
570 app_exit_cb(mainwin
, 0, NULL
);
574 #ifdef HAVE_LIBNOTIFY
575 static gboolean
notification_trayicon_popup_add_msg(MsgInfo
*msginfo
,
576 NotificationFolderType nftype
)
583 g_return_val_if_fail(msginfo
, FALSE
);
585 if(!popup
.notification
)
586 return notification_trayicon_popup_create(msginfo
,nftype
);
589 notification_trayicon_popup_count_msgs(nftype
);
592 g_free(popup
.msg_path
);
593 popup
.msg_path
= NULL
;
596 summary
= notification_trayicon_popup_assemble_summary();
597 utf8_str
= notification_trayicon_popup_assemble_body(msginfo
);
599 /* make sure we show a logo on many msg arrival */
600 pixbuf
= notification_pixbuf_get(NOTIFICATION_CM_LOGO_64x64
);
602 notify_notification_set_icon_from_pixbuf(popup
.notification
, pixbuf
);
604 retval
= notify_notification_update(popup
.notification
, summary
,
609 debug_print("Notification Plugin: Failed to update notification.\n");
613 notify_notification_set_hint_string(popup
.notification
, "desktop-entry", "claws-mail");
614 if(!notify_notification_show(popup
.notification
, &(popup
.error
))) {
615 debug_print("Notification Plugin: Failed to send updated notification: "
616 "%s\n", popup
.error
->message
);
617 g_clear_error(&(popup
.error
));
621 debug_print("Notification Plugin: Popup successfully modified "
622 "with libnotify.\n");
627 static gboolean
notification_trayicon_popup_create(MsgInfo
*msginfo
,
628 NotificationFolderType nftype
)
630 gchar
*summary
= NULL
;
631 gchar
*utf8_str
= NULL
;
634 gboolean support_actions
= FALSE
;
636 /* init libnotify if necessary */
637 if(!notify_is_initted()) {
638 if(!notify_init("claws-mail")) {
639 debug_print("Notification Plugin: Failed to initialize libnotify. "
640 "No popups will be shown.\n");
646 notification_trayicon_popup_count_msgs(nftype
);
648 summary
= notification_trayicon_popup_assemble_summary();
649 utf8_str
= notification_trayicon_popup_assemble_body(msginfo
);
651 #if NOTIFY_CHECK_VERSION(0, 7, 0)
652 popup
.notification
= notify_notification_new(summary
, utf8_str
, NULL
);
654 popup
.notification
= notify_notification_new(summary
, utf8_str
, NULL
, NULL
);
655 notify_notification_attach_to_status_icon(popup
.notification
, trayicon
);
661 caps
= notify_get_server_caps();
664 for(c
= caps
; c
!= NULL
; c
= c
->next
) {
665 if(strcmp((char*)c
->data
, "actions") == 0 ) {
666 support_actions
= TRUE
;
671 g_list_foreach(caps
, (GFunc
)g_free
, NULL
);
677 notify_notification_add_action(popup
.notification
,
678 "default", _("Present main window"),
679 (NotifyActionCallback
)
680 notification_trayicon_popup_default_action_cb
,
681 GINT_TO_POINTER(nftype
),
682 notification_trayicon_popup_free_func
);
684 if(popup
.notification
== NULL
) {
685 debug_print("Notification Plugin: Failed to create a new notification.\n");
691 #ifndef USE_ALT_ADDRBOOK
692 if(msginfo
&& msginfo
->from
) {
694 icon_path
= addrindex_get_picture_file(msginfo
->from
);
695 if(is_file_exist(icon_path
)) {
696 GError
*error
= NULL
;
699 gdk_pixbuf_get_file_info(icon_path
, &w
, &h
);
700 if((w
> 64) || (h
> 64))
701 pixbuf
= gdk_pixbuf_new_from_file_at_scale(icon_path
,
702 64, 64, TRUE
, &error
);
704 pixbuf
= gdk_pixbuf_new_from_file(icon_path
, &error
);
707 debug_print("Could not load picture file: %s\n",
708 error
? error
->message
: "no details");
713 debug_print("Picture path does not exist: %s\n",icon_path
);
718 pixbuf
= g_object_ref(notification_pixbuf_get(NOTIFICATION_CM_LOGO_64x64
));
721 notify_notification_set_icon_from_pixbuf(popup
.notification
, pixbuf
);
722 g_object_unref(pixbuf
);
724 else /* This is not fatal */
725 debug_print("Notification plugin: Icon could not be loaded.\n");
728 notify_notification_set_timeout(popup
.notification
, notify_config
.trayicon_popup_timeout
);
731 notify_notification_set_category(popup
.notification
, "email.arrived");
733 /* get notified on bubble close */
734 g_signal_connect(G_OBJECT(popup
.notification
), "closed", G_CALLBACK(popup_timeout_fun
), NULL
);
737 notify_notification_set_hint_string(popup
.notification
, "desktop-entry", "claws-mail");
738 if(!notify_notification_show(popup
.notification
, &(popup
.error
))) {
739 debug_print("Notification Plugin: Failed to send notification: %s\n",
740 popup
.error
->message
);
741 g_clear_error(&(popup
.error
));
742 g_object_unref(G_OBJECT(popup
.notification
));
743 popup
.notification
= NULL
;
747 /* Store path to message */
748 if(nftype
== F_TYPE_MAIL
) {
749 if(msginfo
&& msginfo
->folder
) {
751 ident
= folder_item_get_identifier(msginfo
->folder
);
752 popup
.msg_path
= g_strdup_printf("%s%s%u", ident
,G_DIR_SEPARATOR_S
,
757 popup
.msg_path
= NULL
;
760 debug_print("Notification Plugin: Popup created with libnotify.\n");
765 static void popup_timeout_fun(NotifyNotification
*nn
, gpointer data
)
767 G_LOCK(trayicon_popup
);
769 g_object_unref(G_OBJECT(popup
.notification
));
771 popup
.notification
= NULL
;
772 g_clear_error(&(popup
.error
));
777 popup
.num_calendar
= 0;
781 g_free(popup
.msg_path
);
782 popup
.msg_path
= NULL
;
785 G_UNLOCK(trayicon_popup
);
788 static void notification_trayicon_popup_free_func(gpointer data
)
791 g_free(popup
.msg_path
);
792 popup
.msg_path
= NULL
;
795 debug_print("Freed notification data\n");
798 static void notification_trayicon_popup_default_action_cb(NotifyNotification
803 if(strcmp("default", action
))
807 mainwin
= mainwindow_get_mainwindow();
809 NotificationFolderType nftype
;
811 /* Let mainwindow pop up */
812 notification_show_mainwindow(mainwin
);
813 /* If there is only one new mail message, jump to this message */
814 nftype
= (NotificationFolderType
)GPOINTER_TO_INT(user_data
);
815 if((popup
.count
== 1) && (nftype
== F_TYPE_MAIL
)) {
817 G_LOCK(trayicon_popup
);
818 select_str
= g_strdup(popup
.msg_path
);
819 G_UNLOCK(trayicon_popup
);
820 debug_print("Notification plugin: Select message %s\n", select_str
);
821 mainwindow_jump_to(select_str
, FALSE
);
827 static void notification_trayicon_popup_count_msgs(NotificationFolderType nftype
)
836 case F_TYPE_CALENDAR
:
837 popup
.num_calendar
++;
843 debug_print("Notification plugin: Unknown folder type\n");
849 /* The returned value has to be freed by the caller */
850 static gchar
* notification_trayicon_popup_assemble_summary(void)
852 gchar
*summary
= NULL
;
854 if(popup
.count
== 1) {
856 summary
= g_strdup(_("New mail message"));
857 else if(popup
.num_news
)
858 summary
= g_strdup(_("New news post"));
859 else if(popup
.num_calendar
)
860 summary
= g_strdup(_("New calendar message"));
862 summary
= g_strdup(_("New article in RSS feed"));
863 } /* One new message */
865 summary
= g_strdup(_("New messages arrived"));
866 } /* Many new messages */
871 /* The returned value has to be freed by the caller */
872 static gchar
* notification_trayicon_popup_assemble_body(MsgInfo
*msginfo
)
876 if(popup
.count
== 1) {
877 if(popup
.num_mail
|| popup
.num_news
) {
881 gchar
*foldname
= NULL
;
883 from
= notification_libnotify_sanitize_str(msginfo
->from
?
886 subj
= notification_libnotify_sanitize_str(msginfo
->subject
?
889 if (notify_config
.trayicon_display_folder_name
) {
890 foldname
= notification_libnotify_sanitize_str(msginfo
->folder
->path
);
891 text
= g_strconcat(from
,"\n\n", subj
, "\n\n", foldname
, NULL
);
894 text
= g_strconcat(from
, "\n\n",subj
, NULL
);
897 /* Make sure text is valid UTF8 */
898 utf8_str
= notification_validate_utf8_str(text
);
903 if(foldname
) g_free(foldname
);
905 else if(popup
.num_calendar
) {
906 utf8_str
= g_strdup(_("A new calendar message arrived"));
909 utf8_str
= g_strdup(_("A new article in a RSS feed arrived"));
916 gboolean str_empty
= TRUE
;
918 utf8_str
= g_strdup("");
921 msg
= g_strdup_printf(ngettext("%d new mail message arrived",
922 "%d new mail messages arrived",
925 tmp
= g_strdup_printf("%s%s%s",utf8_str
,"",msg
);
932 msg
= g_strdup_printf(ngettext("%d new news post arrived",
933 "%d new news posts arrived",
936 tmp
= g_strdup_printf("%s%s%s",utf8_str
,str_empty
?"":"\n",msg
);
942 if(popup
.num_calendar
) {
943 msg
= g_strdup_printf(ngettext("%d new calendar message arrived",
944 "%d new calendar messages arrived",
947 tmp
= g_strdup_printf("%s%s%s",utf8_str
,str_empty
?"":"\n",msg
);
954 msg
= g_strdup_printf(ngettext("%d new article in RSS feeds arrived",
955 "%d new articles in RSS feeds arrived",
958 tmp
= g_strdup_printf("%s%s%s",utf8_str
,str_empty
?"":"\n",msg
);
964 } /* Many messages */
969 #endif /* HAVE_LIBNOTIFY */
971 gboolean
notification_trayicon_is_available(void)
973 gboolean is_available
;
974 is_available
= FALSE
;
977 if(gtk_status_icon_is_embedded(trayicon
) &&
978 gtk_status_icon_get_visible(trayicon
))
985 #endif /* NOTIFICATION_TRAYICON */