summaryrefslogtreecommitdiff
path: root/src/trayicon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/trayicon.c')
-rw-r--r--src/trayicon.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/src/trayicon.c b/src/trayicon.c
new file mode 100644
index 0000000..ef56dc1
--- /dev/null
+++ b/src/trayicon.c
@@ -0,0 +1,434 @@
1/*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2014 Hiroyuki Yamamoto
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21# include "config.h"
22#endif
23
24#include <glib.h>
25#include <glib/gi18n.h>
26#include <gtk/gtkwindow.h>
27#include <gtk/gtkeventbox.h>
28#include <gtk/gtktooltips.h>
29#include <gtk/gtkimage.h>
30#include <gtk/gtkmenu.h>
31#include <gtk/gtkmenuitem.h>
32#include <gtk/gtkversion.h>
33
34#include "eggtrayicon.h"
35#include "trayicon.h"
36#include "mainwindow.h"
37#include "utils.h"
38#include "gtkutils.h"
39#include "stock_pixmap.h"
40#include "menu.h"
41#include "main.h"
42#include "inc.h"
43#include "compose.h"
44#include "prefs_common.h"
45
46#if GTK_CHECK_VERSION(2, 10, 0) || defined(GDK_WINDOWING_X11)
47
48#if GTK_CHECK_VERSION(2, 10, 0)
49#include <gtk/gtkstatusicon.h>
50#endif
51
52#ifdef G_OS_WIN32
53#define TRAYICON_IMAGE STOCK_PIXMAP_SYLPHEED_SMALL
54#define TRAYICON_NEW_IMAGE STOCK_PIXMAP_SYLPHEED_NEWMAIL_SMALL
55#else
56#define TRAYICON_IMAGE STOCK_PIXMAP_SYLPHEED
57#define TRAYICON_NEW_IMAGE STOCK_PIXMAP_SYLPHEED_NEWMAIL
58#endif
59
60#define TRAYICON_NOTIFY_PERIOD 10000
61
62static TrayIcon trayicon;
63static GtkWidget *trayicon_menu;
64static gboolean on_notify = FALSE;
65static gboolean default_tooltip = FALSE;
66
67#if GTK_CHECK_VERSION(2, 10, 0)
68
69static void trayicon_activated (GtkStatusIcon *status_icon,
70 gpointer data);
71static void trayicon_popup_menu_cb (GtkStatusIcon *status_icon,
72 guint button,
73 guint activate_time,
74 gpointer data);
75
76#else
77
78static GtkWidget *trayicon_img;
79static GtkWidget *eventbox;
80static GtkTooltips *trayicon_tip;
81
82static void trayicon_button_pressed (GtkWidget *widget,
83 GdkEventButton *event,
84 gpointer data);
85static void trayicon_destroy_cb (GtkWidget *widget,
86 gpointer data);
87
88#endif
89
90static void trayicon_present (GtkWidget *widget,
91 gpointer data);
92static void trayicon_inc (GtkWidget *widget,
93 gpointer data);
94static void trayicon_inc_all (GtkWidget *widget,
95 gpointer data);
96static void trayicon_send (GtkWidget *widget,
97 gpointer data);
98static void trayicon_compose (GtkWidget *widget,
99 gpointer data);
100static void trayicon_app_exit (GtkWidget *widget,
101 gpointer data);
102
103TrayIcon *trayicon_create(MainWindow *mainwin)
104{
105 GtkWidget *menuitem;
106
107#if GTK_CHECK_VERSION(2, 10, 0)
108 GdkPixbuf *pixbuf;
109
110 stock_pixbuf_gdk(NULL, TRAYICON_IMAGE, &pixbuf);
111 trayicon.status_icon = gtk_status_icon_new_from_pixbuf(pixbuf);
112
113 g_signal_connect(G_OBJECT(trayicon.status_icon), "activate",
114 G_CALLBACK(trayicon_activated), mainwin);
115 g_signal_connect(G_OBJECT(trayicon.status_icon), "popup-menu",
116 G_CALLBACK(trayicon_popup_menu_cb), mainwin);
117#else
118 trayicon.widget = GTK_WIDGET(egg_tray_icon_new("Sylpheed"));
119 g_signal_connect(G_OBJECT(trayicon.widget), "destroy",
120 G_CALLBACK(trayicon_destroy_cb), mainwin);
121
122 eventbox = gtk_event_box_new();
123 gtk_widget_show(eventbox);
124 gtk_container_add(GTK_CONTAINER(trayicon.widget), eventbox);
125 g_signal_connect(G_OBJECT(eventbox), "button_press_event",
126 G_CALLBACK(trayicon_button_pressed), mainwin);
127 trayicon_img = stock_pixbuf_widget_scale(NULL, TRAYICON_IMAGE, 24, 24);
128 gtk_widget_show(trayicon_img);
129 gtk_container_add(GTK_CONTAINER(eventbox), trayicon_img);
130
131 trayicon_tip = gtk_tooltips_new();
132#endif
133 on_notify = FALSE;
134 default_tooltip = FALSE;
135 trayicon_set_tooltip(NULL);
136
137 if (!trayicon_menu) {
138 trayicon_menu = gtk_menu_new();
139 gtk_widget_show(trayicon_menu);
140 MENUITEM_ADD_WITH_MNEMONIC(trayicon_menu, menuitem,
141 _("_Display Sylpheed"), 0);
142 g_signal_connect(G_OBJECT(menuitem), "activate",
143 G_CALLBACK(trayicon_present), mainwin);
144 MENUITEM_ADD(trayicon_menu, menuitem, NULL, 0);
145 MENUITEM_ADD_WITH_MNEMONIC(trayicon_menu, menuitem,
146 _("Get from _current account"), 0);
147 g_signal_connect(G_OBJECT(menuitem), "activate",
148 G_CALLBACK(trayicon_inc), mainwin);
149 MENUITEM_ADD_WITH_MNEMONIC(trayicon_menu, menuitem,
150 _("Get from _all accounts"), 0);
151 g_signal_connect(G_OBJECT(menuitem), "activate",
152 G_CALLBACK(trayicon_inc_all), mainwin);
153 MENUITEM_ADD_WITH_MNEMONIC(trayicon_menu, menuitem,
154 _("_Send queued messages"), 0);
155 g_signal_connect(G_OBJECT(menuitem), "activate",
156 G_CALLBACK(trayicon_send), mainwin);
157
158 MENUITEM_ADD(trayicon_menu, menuitem, NULL, 0);
159 MENUITEM_ADD_WITH_MNEMONIC(trayicon_menu, menuitem,
160 _("Compose _new message"), 0);
161 g_signal_connect(G_OBJECT(menuitem), "activate",
162 G_CALLBACK(trayicon_compose), mainwin);
163
164 MENUITEM_ADD(trayicon_menu, menuitem, NULL, 0);
165 MENUITEM_ADD_WITH_MNEMONIC(trayicon_menu, menuitem,
166 _("E_xit"), 0);
167 g_signal_connect(G_OBJECT(menuitem), "activate",
168 G_CALLBACK(trayicon_app_exit), mainwin);
169 }
170
171 return &trayicon;
172}
173
174#if GTK_CHECK_VERSION(2, 10, 0)
175
176void trayicon_show(TrayIcon *tray_icon)
177{
178 gtk_status_icon_set_visible(tray_icon->status_icon, TRUE);
179};
180
181void trayicon_hide(TrayIcon *tray_icon)
182{
183 gtk_status_icon_set_visible(tray_icon->status_icon, FALSE);
184}
185
186void trayicon_destroy(TrayIcon *tray_icon)
187{
188 g_object_unref(tray_icon->status_icon);
189 tray_icon->status_icon = NULL;
190}
191
192void trayicon_set_tooltip(const gchar *text)
193{
194 if (text) {
195 default_tooltip = FALSE;
196 gtk_status_icon_set_tooltip(trayicon.status_icon, text);
197 } else if (!default_tooltip) {
198 default_tooltip = TRUE;
199 gtk_status_icon_set_tooltip(trayicon.status_icon,
200 _("Sylpheed"));
201 }
202}
203
204static guint notify_tag = 0;
205
206gboolean notify_timeout_cb(gpointer data)
207{
208 gdk_threads_enter();
209 gtk_status_icon_set_blinking(trayicon.status_icon, FALSE);
210 notify_tag = 0;
211 gdk_threads_leave();
212
213 return FALSE;
214}
215
216void trayicon_set_notify(gboolean enabled)
217{
218 if (enabled && !on_notify) {
219 trayicon_set_stock_icon(TRAYICON_NEW_IMAGE);
220 on_notify = TRUE;
221 } else if (!enabled && on_notify) {
222 trayicon_set_stock_icon(TRAYICON_IMAGE);
223 on_notify = FALSE;
224 }
225
226 if (enabled && notify_tag == 0) {
227 gtk_status_icon_set_blinking(trayicon.status_icon, enabled);
228 notify_tag = g_timeout_add(TRAYICON_NOTIFY_PERIOD, notify_timeout_cb, NULL);
229 } else if (!enabled && notify_tag > 0) {
230 g_source_remove(notify_tag);
231 notify_timeout_cb(NULL);
232 }
233}
234
235void trayicon_set_stock_icon(StockPixmap icon)
236{
237 GdkPixbuf *pixbuf;
238
239 stock_pixbuf_gdk(NULL, icon, &pixbuf);
240 gtk_status_icon_set_from_pixbuf(trayicon.status_icon, pixbuf);
241}
242
243static void trayicon_activated(GtkStatusIcon *status_icon, gpointer data)
244{
245 MainWindow *mainwin = (MainWindow *)data;
246
247#ifdef G_OS_WIN32
248 if (prefs_common.toggle_window_on_trayicon_click &&
249 !mainwin->window_hidden && !mainwin->window_obscured)
250 gtk_window_iconify(GTK_WINDOW(mainwin->window));
251 else
252 main_window_popup(mainwin);
253#else
254 if (prefs_common.toggle_window_on_trayicon_click &&
255 gtk_window_is_active(GTK_WINDOW(mainwin->window)))
256 gtk_window_iconify(GTK_WINDOW(mainwin->window));
257 else
258 main_window_popup(mainwin);
259#endif
260}
261
262static void trayicon_popup_menu_cb(GtkStatusIcon *status_icon, guint button,
263 guint activate_time, gpointer data)
264{
265 gtk_menu_popup(GTK_MENU(trayicon_menu), NULL, NULL, NULL, NULL,
266 button, activate_time);
267}
268
269#else /* GTK_CHECK_VERSION(2, 10, 0) */
270
271void trayicon_show(TrayIcon *tray_icon)
272{
273 gtk_widget_show(tray_icon->widget);
274};
275
276void trayicon_hide(TrayIcon *tray_icon)
277{
278 gtk_widget_destroy(tray_icon->widget);
279 tray_icon->widget = NULL;
280}
281
282void trayicon_destroy(TrayIcon *tray_icon)
283{
284 g_signal_handlers_disconnect_by_func(G_OBJECT(tray_icon->widget),
285 G_CALLBACK(trayicon_destroy_cb),
286 main_window_get());
287 gtk_widget_destroy(tray_icon->widget);
288 tray_icon->widget = NULL;
289}
290
291void trayicon_set_tooltip(const gchar *text)
292{
293 if (text) {
294 default_tooltip = FALSE;
295 gtk_tooltips_set_tip(trayicon_tip, trayicon.widget, text,
296 NULL);
297 } else if (!default_tooltip) {
298 default_tooltip = TRUE;
299 gtk_tooltips_set_tip(trayicon_tip, trayicon.widget,
300 _("Sylpheed"), NULL);
301 }
302}
303
304void trayicon_set_notify(gboolean enabled)
305{
306 if (enabled && !on_notify) {
307 trayicon_set_stock_icon(TRAYICON_NEW_IMAGE);
308 on_notify = TRUE;
309 } else if (!enabled && on_notify) {
310 trayicon_set_stock_icon(TRAYICON_IMAGE);
311 on_notify = FALSE;
312 }
313}
314
315void trayicon_set_stock_icon(StockPixmap icon)
316{
317 GdkPixbuf *pixbuf;
318 GdkPixbuf *scaled_pixbuf;
319
320 stock_pixbuf_gdk(NULL, icon, &pixbuf);
321 scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, 24, 24,
322 GDK_INTERP_HYPER);
323 gtk_image_set_from_pixbuf(GTK_IMAGE(trayicon_img), scaled_pixbuf);
324 g_object_unref(scaled_pixbuf);
325}
326
327static void trayicon_button_pressed(GtkWidget *widget, GdkEventButton *event,
328 gpointer data)
329{
330 MainWindow *mainwin = (MainWindow *)data;
331
332 if (!event)
333 return;
334
335 if (event->button == 1) {
336 if (prefs_common.toggle_window_on_trayicon_click &&
337 gtk_window_is_active(GTK_WINDOW(mainwin->window)))
338 gtk_window_iconify(GTK_WINDOW(mainwin->window));
339 else
340 main_window_popup(mainwin);
341 } else if (event->button == 3) {
342 gtk_menu_popup(GTK_MENU(trayicon_menu), NULL, NULL, NULL, NULL,
343 event->button, event->time);
344 }
345}
346
347static gboolean trayicon_restore(gpointer data)
348{
349 MainWindow *mainwin = (MainWindow *)data;
350
351 gdk_threads_enter();
352 mainwin->tray_icon = trayicon_create(mainwin);
353 gdk_threads_leave();
354 return FALSE;
355}
356
357static void trayicon_destroy_cb(GtkWidget *widget, gpointer data)
358{
359 g_idle_add(trayicon_restore, data);
360}
361
362#endif /* GTK_CHECK_VERSION(2, 10, 0) */
363
364static void trayicon_present(GtkWidget *widget, gpointer data)
365{
366 MainWindow *mainwin = (MainWindow *)data;
367
368 main_window_popup(mainwin);
369}
370
371static void trayicon_inc(GtkWidget *widget, gpointer data)
372{
373 if (!inc_is_active() && !gtkut_window_modal_exist())
374 inc_mail((MainWindow *)data);
375}
376
377static void trayicon_inc_all(GtkWidget *widget, gpointer data)
378{
379 if (!inc_is_active() && !gtkut_window_modal_exist())
380 inc_all_account_mail((MainWindow *)data, FALSE);
381}
382
383static void trayicon_send(GtkWidget *widget, gpointer data)
384{
385 if (!gtkut_window_modal_exist())
386 main_window_send_queue((MainWindow *)data);
387}
388
389static void trayicon_compose(GtkWidget *widget, gpointer data)
390{
391 if (!gtkut_window_modal_exist())
392 compose_new(NULL, NULL, NULL, NULL);
393}
394
395static void trayicon_app_exit(GtkWidget *widget, gpointer data)
396{
397 MainWindow *mainwin = (MainWindow *)data;
398
399 if (mainwin->lock_count == 0 && !gtkut_window_modal_exist())
400 app_will_exit(FALSE);
401}
402
403#else /* GTK_CHECK_VERSION(2, 10, 0) || defined(GDK_WINDOWING_X11) */
404
405TrayIcon *trayicon_create(MainWindow *mainwin)
406{
407 return NULL;
408}
409
410void trayicon_show(TrayIcon *tray_icon)
411{
412}
413
414void trayicon_hide(TrayIcon *tray_icon)
415{
416}
417
418void trayicon_destroy(TrayIcon *tray_icon)
419{
420}
421
422void trayicon_set_tooltip(const gchar *text)
423{
424}
425
426void trayicon_set_notify(gboolean enabled)
427{
428}
429
430void trayicon_set_stock_icon(StockPixmap icon)
431{
432}
433
434#endif /* GTK_CHECK_VERSION(2, 10, 0) || defined(GDK_WINDOWING_X11) */