Statistics
| Revision:

root / src / trayicon.c @ 2755

History | View | Annotate | Download (11 kB)

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