+2003-03-22 [christoph] 0.8.11claws39
+
+ * src/imap.c
+ * src/common/session.[ch]
+ Init session data to make sure we don't have invalid pointers
+ for read_ch and write_ch when new multi process sessions are
+ not used
+
+ * src/main.c
+ * src/common/plugin.c
+ * src/common/sylpheed.c
+ * src/plugins/demo/demo.c
+ * src/plugins/dillo_viewer/dillo_viewer.c
+ * src/plugins/mathml_viewer/mathml_viewer.c
+ * src/plugins/spamassassin/spamassassin.c
+ * src/plugins/spamassassin/spamassassin_gtk.c
+ add plugin types to allow loading plugins at different times
+ (and maybe for different frontends), because it's not good to
+ load GTK-Plugins gefore gtk_init was called
+
+ * configure.ac
+ * src/plugins/Makefile.am
+ * src/plugins/trayicon/.cvsignore ** NEW **
+ * src/plugins/trayicon/Makefile.am ** NEW **
+ * src/plugins/trayicon/eggtrayicon.c ** NEW **
+ * src/plugins/trayicon/eggtrayicon.h ** NEW **
+ * src/plugins/trayicon/gnome-mail.xpm ** NEW **
+ * src/plugins/trayicon/gnome-nomail.xpm ** NEW **
+ * src/plugins/trayicon/trayicon.c ** NEW **
+ New Trayicon plugin that shows an icon in a systray that uses
+ XEMBED protocol like Gnome's systray. Icon shows if there
+ are new mails and a tooltip shows information about new,
+ unread and total messages.
+
2003-03-22 [paul] 0.8.11claws38
* src/common/smtp.c
MICRO_VERSION=11
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=claws38
+EXTRA_VERSION=claws39
VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
dnl set $target
PLUGINS="dillo $PLUGINS"
fi
+AC_ARG_ENABLE(trayicon-plugin,
+ [ --enable-trayicon-plugin System Tray Icon [default=no]],
+ [ac_cv_enable_trayicon_plugin=$enableval], [ac_cv_enable_trayicon_plugin=no])
+AM_CONDITIONAL(BUILD_TRAYICON_PLUGIN, test x"$ac_cv_enable_trayicon_plugin" = xyes)
+if test x"$ac_cv_enable_trayicon_plugin" = xyes; then
+ PLUGINS="trayicon $PLUGINS"
+fi
dnl ****************************
dnl ** Final configure output **
src/plugins/spamassassin/Makefile
src/plugins/mathml_viewer/Makefile
src/plugins/dillo_viewer/Makefile
+src/plugins/trayicon/Makefile
faq/Makefile
faq/de/Makefile
faq/en/Makefile
GModule *module;
gchar *(*name) ();
gchar *(*desc) ();
+ gchar *(*type) ();
};
/**
* List of all loaded plugins
*/
GSList *plugins = NULL;
+GSList *plugin_types = NULL;
+
+static gint list_find_by_string(gconstpointer data, gconstpointer str)
+{
+ return strcmp((gchar *)data, (gchar *)str) ? TRUE : FALSE;
+}
void plugin_save_list()
{
- gchar *rcpath;
+ gchar *rcpath, *block;
PrefFile *pfile;
- GSList *cur;
+ GSList *type_cur, *plugin_cur;
Plugin *plugin;
- rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
- if ((pfile = prefs_write_open(rcpath)) == NULL ||
- (prefs_set_block_label(pfile, "Plugins") < 0)) {
- g_warning("failed to write plugin list\n");
- g_free(rcpath);
- return;
- }
-
- for (cur = plugins; cur != NULL; cur = g_slist_next(cur)) {
- plugin = (Plugin *)cur->data;
+ for (type_cur = plugin_types; type_cur != NULL; type_cur = g_slist_next(type_cur)) {
+ rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
+ block = g_strconcat("Plugins_", type_cur->data, NULL);
+ if ((pfile = prefs_write_open(rcpath)) == NULL ||
+ (prefs_set_block_label(pfile, block) < 0)) {
+ g_warning("failed to write plugin list\n");
+ g_free(rcpath);
+ return;
+ }
+ g_free(block);
+
+ for (plugin_cur = plugins; plugin_cur != NULL; plugin_cur = g_slist_next(plugin_cur)) {
+ plugin = (Plugin *) plugin_cur->data;
- fprintf(pfile->fp, "%s\n", plugin->filename);
- }
- fprintf(pfile->fp, "\n");
+ if (!strcmp(plugin->type(), type_cur->data))
+ fprintf(pfile->fp, "%s\n", plugin->filename);
+ }
+ fprintf(pfile->fp, "\n");
- if (prefs_file_close(pfile) < 0)
- g_warning("failed to write plugin list\n");
+ if (prefs_file_close(pfile) < 0)
+ g_warning("failed to write plugin list\n");
- g_free(rcpath);
+ g_free(rcpath);
+ }
}
/**
{
Plugin *plugin;
gint (*plugin_init) (gchar **error);
- gchar *plugin_name, *plugin_desc;
+ gchar *plugin_name, *plugin_desc, *plugin_type;
gint ok;
g_return_val_if_fail(filename != NULL, -1);
if (!g_module_symbol(plugin->module, "plugin_name", (gpointer *)&plugin_name) ||
!g_module_symbol(plugin->module, "plugin_desc", (gpointer *)&plugin_desc) ||
+ !g_module_symbol(plugin->module, "plugin_type", (gpointer *)&plugin_type) ||
!g_module_symbol(plugin->module, "plugin_init", (gpointer *)&plugin_init)) {
*error = g_strdup(g_module_error());
g_module_close(plugin->module);
plugin->name = plugin_name;
plugin->desc = plugin_desc;
+ plugin->type = plugin_type;
plugin->filename = g_strdup(filename);
plugins = g_slist_append(plugins, plugin);
g_free(plugin);
}
-void plugin_load_all()
+void plugin_load_all(gchar *type)
{
gchar *rcpath;
gchar buf[BUFFSIZE];
PrefFile *pfile;
- gchar *error;
+ gchar *error, *block;
+
+ plugin_types = g_slist_append(plugin_types, g_strdup(type));
rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
+ block = g_strconcat("Plugins_", type, NULL);
if ((pfile = prefs_read_open(rcpath)) == NULL ||
- (prefs_set_block_label(pfile, "Plugins") < 0)) {
+ (prefs_set_block_label(pfile, block) < 0)) {
g_free(rcpath);
return;
}
+ g_free(block);
while (fgets(buf, sizeof(buf), pfile->fp) != NULL) {
if (buf[0] == '[')
g_free(rcpath);
}
-void plugin_unload_all()
+void plugin_unload_all(gchar *type)
{
GSList *list, *cur;
for(cur = list; cur != NULL; cur = g_slist_next(cur)) {
Plugin *plugin = (Plugin *) cur->data;
- plugin_unload(plugin);
+ if (!strcmp(type, plugin->type()))
+ plugin_unload(plugin);
}
g_slist_free(list);
+
+ cur = g_slist_find_custom(plugin_types, type, list_find_by_string);
+ if (cur) {
+ g_free(cur->data);
+ g_slist_remove(plugin_types, cur);
+ }
}
GSList *plugin_get_list()
gboolean session_child_input (Session *session);
+void session_init(Session *session)
+{
+ session->type = 0;
+ session->sock = NULL;
+
+ session->server = NULL;
+ session->port = 0;
+ session->state = SESSION_READY;
+ session->last_access_time = time(NULL);
+ session->data = NULL;
+
+ session->read_ch = NULL;
+ session->write_ch = NULL;
+}
+
gint session_connect(Session *session, const gchar *server, gushort port)
{
pid_t pid;
gpointer send_data_notify_data;
};
+void session_init (Session *session);
gint session_connect (Session *session,
const gchar *server,
gushort port);
ssl_init();
#endif
- plugin_load_all();
+ plugin_load_all("Common");
sylpheed_initialized = TRUE;
void sylpheed_done()
{
- plugin_unload_all();
+ plugin_unload_all("Common");
#if USE_OPENSSL
ssl_done();
(is_preauth) ? "pre" : "un");
session = g_new(IMAPSession, 1);
+ session_init(SESSION(session));
SESSION(session)->type = SESSION_IMAP;
SESSION(session)->server = g_strdup(account->recv_server);
SESSION(session)->sock = imap_sock;
- SESSION(session)->last_access_time = time(NULL);
- SESSION(session)->data = NULL;
SESSION(session)->destroy = imap_session_destroy;
#include "gtkutils.h"
#include "log.h"
#include "prefs_toolbar.h"
+#include "plugin.h"
#if USE_GPGME
# include "rfc2015.h"
main_window_toggle_work_offline(mainwin, FALSE);
prefs_toolbar_init();
+
+ plugin_load_all("GTK");
static_mainwindow = mainwin;
gtk_main();
+ plugin_unload_all("GTK");
+
prefs_toolbar_done();
addressbook_destroy();
dillo_viewer_dir = dillo_viewer
endif
+if BUILD_TRAYICON_PLUGIN
+trayicon_dir = trayicon
+endif
-SUBDIRS = $(demo_dir) $(spamassasssin_dir) $(mathml_viewer_dir) \
- $(dillo_viewer_dir)
-
+SUBDIRS = $(demo_dir) \
+ $(spamassasssin_dir) \
+ $(mathml_viewer_dir) \
+ $(dillo_viewer_dir) \
+ $(trayicon_dir)
"\n\n"
"It is not really usefull";
}
+
+const gchar *plugin_type()
+{
+ return "Common";
+}
return "This plugin renders HTML mail using the Dillo "
"web browser.";
}
+
+const gchar *plugin_type()
+{
+ return "GTK";
+}
{
return "";
}
+
+const gchar *plugin_type()
+{
+ return "GTK";
+}
"a User Interface plugin too, otherwise you will have to "
"manually write the plugin configuration.\n";
}
+
+const gchar *plugin_type()
+{
+ return "Common";
+}
"(default: Yes) and select the folder where spam mail will be "
"saved.\n";
}
+
+const gchar *plugin_type()
+{
+ return "GTK";
+}
--- /dev/null
+.deps
+.libs
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
--- /dev/null
+plugindir = $(pkglibdir)/plugins
+
+plugin_LTLIBRARIES = trayicon.la
+
+trayicon_la_SOURCES = \
+ trayicon.c \
+ eggtrayicon.c eggtrayicon.h
+
+trayicon_la_LDFLAGS = \
+ -avoid-version -module \
+ $(GTK_LIBS)
+
+INCLUDES = \
+ -I../../ \
+ -I../../common \
+ -I../../gtk
+
+CPPFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(GTK_CFLAGS) \
+ $(ASPELL_CFLAGS)
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.c
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <gdk/gdkx.h>
+#include "eggtrayicon.h"
+
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+static GtkPlugClass *parent_class = NULL;
+
+static void egg_tray_icon_init (EggTrayIcon *icon);
+static void egg_tray_icon_class_init (EggTrayIconClass *klass);
+
+static void egg_tray_icon_unrealize (GtkWidget *widget);
+
+static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
+
+Window gtk_plug_get_id(GtkPlug *widget)
+{
+ return (guint32) GDK_WINDOW_XWINDOW(GTK_WIDGET(widget)->window);
+}
+
+GtkType
+egg_tray_icon_get_type (void)
+{
+ static GtkType our_type = 0;
+
+ if (our_type == 0)
+ {
+ GtkTypeInfo our_info =
+ {
+ "EggTrayIcon",
+ sizeof (EggTrayIcon),
+ sizeof (EggTrayIconClass),
+ (GtkClassInitFunc) egg_tray_icon_class_init,
+ (GtkObjectInitFunc) egg_tray_icon_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0, /* n_preallocs */
+ };
+
+ our_type = gtk_type_unique (gtk_plug_get_type(), &our_info);
+ }
+
+ return our_type;
+}
+
+static void
+egg_tray_icon_init (EggTrayIcon *icon)
+{
+ icon->stamp = 1;
+
+ gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
+}
+
+static void
+egg_tray_icon_class_init (EggTrayIconClass *klass)
+{
+ GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
+ parent_class = gtk_type_class(gtk_plug_get_type());
+
+ widget_class->unrealize = egg_tray_icon_unrealize;
+}
+
+static GdkFilterReturn
+egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
+{
+ EggTrayIcon *icon = user_data;
+ XEvent *xev = (XEvent *)xevent;
+
+ if (xev->xany.type == ClientMessage &&
+ xev->xclient.message_type == icon->manager_atom &&
+ xev->xclient.data.l[1] == icon->selection_atom)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ else if (xev->xany.window == icon->manager_window)
+ {
+ if (xev->xany.type == DestroyNotify)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+egg_tray_icon_unrealize (GtkWidget *widget)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+ GdkWindow *root_window;
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+#if HAVE_GTK_MULTIHEAD
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
+ icon->manager_window);
+#else
+ gdkwin = gdk_window_lookup (icon->manager_window);
+#endif
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+#if HAVE_GTK_MULTIHEAD
+ root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+#else
+ root_window = gdk_window_lookup (GDK_ROOT_WINDOW());
+#endif
+
+ gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+egg_tray_icon_send_manager_message (EggTrayIcon *icon,
+ long message,
+ Window window,
+ long data1,
+ long data2,
+ long data3)
+{
+ XClientMessageEvent ev;
+ Display *display;
+
+ ev.type = ClientMessage;
+ ev.window = window;
+ ev.message_type = icon->system_tray_opcode_atom;
+ ev.format = 32;
+ ev.data.l[0] = gdk_time_get(); /* gdk_x11_get_server_time (GTK_WIDGET (icon)->window); */
+ ev.data.l[1] = message;
+ ev.data.l[2] = data1;
+ ev.data.l[3] = data2;
+ ev.data.l[4] = data3;
+
+#if HAVE_GTK_MULTIHEAD
+ display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+#else
+ display = gdk_display;
+#endif
+
+ gdk_error_trap_push ();
+ XSendEvent (display,
+ icon->manager_window, False, NoEventMask, (XEvent *)&ev);
+ XSync (display, False);
+ gdk_error_trap_pop ();
+}
+
+static void
+egg_tray_icon_send_dock_request (EggTrayIcon *icon)
+{
+ egg_tray_icon_send_manager_message (icon,
+ SYSTEM_TRAY_REQUEST_DOCK,
+ icon->manager_window,
+ gtk_plug_get_id (GTK_PLUG (icon)),
+ 0, 0);
+}
+
+static void
+egg_tray_icon_update_manager_window (EggTrayIcon *icon)
+{
+ Display *xdisplay;
+
+#if HAVE_GTK_MULTIHEAD
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+#else
+ xdisplay = gdk_display;
+#endif
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+#if HAVE_GTK_MULTIHEAD
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+#else
+ gdkwin = gdk_window_lookup (icon->manager_window);
+#endif
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+ XGrabServer (xdisplay);
+
+ icon->manager_window = XGetSelectionOwner (xdisplay,
+ icon->selection_atom);
+
+ if (icon->manager_window != None)
+ XSelectInput (xdisplay,
+ icon->manager_window, StructureNotifyMask);
+
+ XUngrabServer (xdisplay);
+ XFlush (xdisplay);
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+#if HAVE_GTK_MULTIHEAD
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+#else
+ gdkwin = gdk_window_lookup (icon->manager_window);
+#endif
+
+ gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+
+ /* Send a request that we'd like to dock */
+ egg_tray_icon_send_dock_request (icon);
+ }
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
+{
+ EggTrayIcon *icon;
+ char buffer[256];
+ GdkWindow *root_window;
+
+ g_return_val_if_fail (xscreen != NULL, NULL);
+
+ icon = gtk_type_new (EGG_TYPE_TRAY_ICON);
+ gtk_window_set_title (GTK_WINDOW (icon), name);
+
+#if HAVE_GTK_MULTIHEAD
+ /* FIXME: this code does not compile, screen is undefined. Now try
+ * getting the GdkScreen from xscreen (:. Dunno how to solve this
+ * (there is prolly some easy way I cant think of right now)
+ */
+ gtk_plug_construct_for_display (GTK_PLUG (icon),
+ gdk_screen_get_display (screen), 0);
+#else
+ gtk_plug_construct (GTK_PLUG (icon), 0);
+#endif
+
+ gtk_widget_set_events(GTK_WIDGET(icon), GDK_ALL_EVENTS_MASK);
+ gtk_widget_realize (GTK_WIDGET (icon));
+
+ /* Now see if there's a manager window around */
+ g_snprintf (buffer, sizeof (buffer),
+ "_NET_SYSTEM_TRAY_S%d",
+ XScreenNumberOfScreen (xscreen));
+
+ icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen),
+ buffer, False);
+
+ icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen),
+ "MANAGER", False);
+
+ icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen),
+ "_NET_SYSTEM_TRAY_OPCODE", False);
+
+ egg_tray_icon_update_manager_window (icon);
+
+#if HAVE_GTK_MULTIHEAD
+ root_window = gdk_screen_get_root_window (gtk_widget_get_screen (screen));
+#else
+ root_window = gdk_window_lookup (GDK_ROOT_WINDOW ());
+#endif
+
+ /* Add a root window filter so that we get changes on MANAGER */
+ gdk_window_add_filter (root_window,
+ egg_tray_icon_manager_filter, icon);
+
+ return icon;
+}
+
+#if HAVE_GTK_MULTIHEAD
+EggTrayIcon *
+egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
+{
+ EggTrayIcon *icon;
+ char buffer[256];
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name);
+}
+#endif
+
+EggTrayIcon*
+egg_tray_icon_new (const gchar *name)
+{
+ return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_display), name);
+}
+
+guint
+egg_tray_icon_send_message (EggTrayIcon *icon,
+ gint timeout,
+ const gchar *message,
+ gint len)
+{
+ guint stamp;
+
+ g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
+ g_return_val_if_fail (timeout >= 0, 0);
+ g_return_val_if_fail (message != NULL, 0);
+
+ if (icon->manager_window == None)
+ return 0;
+
+ if (len < 0)
+ len = strlen (message);
+
+ stamp = icon->stamp++;
+
+ /* Get ready to send the message */
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ timeout, len, stamp);
+
+ /* Now to send the actual message */
+ gdk_error_trap_push ();
+ while (len > 0)
+ {
+ XClientMessageEvent ev;
+ Display *xdisplay;
+
+#if HAVE_GTK_MULTIHEAD
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+#else
+ xdisplay = gdk_display;
+#endif
+
+ ev.type = ClientMessage;
+ ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
+ ev.format = 8;
+ ev.message_type = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
+ if (len > 20)
+ {
+ memcpy (&ev.data, message, 20);
+ len -= 20;
+ message += 20;
+ }
+ else
+ {
+ memcpy (&ev.data, message, len);
+ len = 0;
+ }
+
+ XSendEvent (xdisplay,
+ icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
+ XSync (xdisplay, False);
+ }
+ gdk_error_trap_pop ();
+
+ return stamp;
+}
+
+void
+egg_tray_icon_cancel_message (EggTrayIcon *icon,
+ guint id)
+{
+ g_return_if_fail (EGG_IS_TRAY_ICON (icon));
+ g_return_if_fail (id > 0);
+
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ id, 0, 0);
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.h
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_TRAY_ICON_H__
+#define __EGG_TRAY_ICON_H__
+
+#include <gtk/gtk.h>
+#include <gtk/gtkplug.h>
+#include <gdk/gdkx.h>
+
+#define EGG_TYPE_TRAY_ICON (egg_tray_icon_get_type ())
+#define EGG_TRAY_ICON(obj) (GTK_CHECK_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon))
+#define EGG_TRAY_ICON_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+#define EGG_IS_TRAY_ICON(obj) (GTK_CHECK_TYPE ((obj), EGG_TYPE_TRAY_ICON))
+#define EGG_IS_TRAY_ICON_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON))
+/*
+#define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+*/
+
+typedef struct _EggTrayIcon EggTrayIcon;
+typedef struct _EggTrayIconClass EggTrayIconClass;
+
+struct _EggTrayIcon
+{
+ GtkPlug parent_instance;
+
+ guint stamp;
+
+ Atom selection_atom;
+ Atom manager_atom;
+ Atom system_tray_opcode_atom;
+ Window manager_window;
+};
+
+struct _EggTrayIconClass
+{
+ GtkPlugClass parent_class;
+};
+
+GtkType egg_tray_icon_get_type (void);
+
+#if EGG_TRAY_ENABLE_MULTIHEAD
+EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen *screen,
+ const gchar *name);
+#endif
+
+EggTrayIcon *egg_tray_icon_new (const gchar *name);
+
+guint egg_tray_icon_send_message (EggTrayIcon *icon,
+ gint timeout,
+ const char *message,
+ gint len);
+void egg_tray_icon_cancel_message (EggTrayIcon *icon,
+ guint id);
+
+
+
+#endif /* __EGG_TRAY_ICON_H__ */
--- /dev/null
+/* XPM */
+static char * mail_xpm[] = {
+"28 16 7 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+"@ c #CCCCCC",
+"# c #00FFFF",
+"$ c #0000FF",
+"% c #999999",
+"............................",
+".++++++++++++++++++++++++++.",
+".+++++++++++++@@+++@@+###$+.",
+".+%....%+++++@++@@@++@###$+.",
+".++++++++++++@++@++@@+###$+.",
+".+%....%++++++@@+@@++@$$$$+.",
+".++++++++++++++++++++++++++.",
+".++++++++..........++++++++.",
+".++++++++++++++++++++++++++.",
+".++++++++........++++++++++.",
+".++++++++++++++++++++++++++.",
+".++++++++...........+++++++.",
+".++++++++++++++++++++++++++.",
+".++++++++++++++++++++++++++.",
+".++++++++++++++++++++++++++.",
+"............................"};
--- /dev/null
+/* XPM */
+static char * nomail_xpm[] = {
+"28 16 4 1",
+" c None",
+". c #999999",
+"+ c #FFFFFF",
+"@ c #CCCCCC",
+"............................",
+".++++++++++++++++++++++++++.",
+".+@@@@@@@@@@@@@@@@@@@@@@@.@.",
+".+......@@@@@@@@@@@@@@@@@.+.",
+".+@++++++@@@@@@@@@@@@@@@@.+.",
+".+......@@@@@@@@@@@@@@....+.",
+".+@++++++@@@@@@@@@@@@@@++++.",
+".+@@@@@@@..........@@@@@@@@.",
+".+@@@@@@@@++++++++++@@@@@@@.",
+".+@@@@@@@........@@@@@@@@@@.",
+".+@@@@@@@@++++++++@@@@@@@@@.",
+".+@@@@@@@...........@@@@@@@.",
+".+@@@@@@@@+++++++++++@@@@@@.",
+".+@@@@@@@@@@@@@@@@@@@@@@@@@.",
+".+@@@@@@@@@@@@@@@@@@@@@@@@@.",
+"............................"};
--- /dev/null
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2003 Hiroyuki Yamamoto and the Sylpheed-Claws Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "plugin.h"
+#include "hooks.h"
+#include "folder.h"
+#include "mainwindow.h"
+
+#include "eggtrayicon.h"
+#include "gnome-mail.xpm"
+#include "gnome-nomail.xpm"
+
+static gint hook_id;
+
+static GdkPixmap *mail_pixmap;
+static GdkPixmap *mail_bitmap;
+static GdkPixmap *nomail_pixmap;
+static GdkPixmap *nomail_bitmap;
+
+static EggTrayIcon *trayicon;
+static GtkWidget *eventbox;
+static GtkWidget *image;
+static GtkTooltips *tooltips;
+
+typedef enum
+{
+ TRAYICON_NEW,
+ TRAYICON_UNREAD,
+ TRAYICON_UNREADMARKED,
+ TRAYICON_NOTHING,
+} TrayIconType;
+
+static gboolean mainwin_hidden = FALSE;
+
+static gboolean click_cb(GtkWidget * widget,
+ GdkEventButton * event, gpointer user_data)
+{
+/*
+ MainWindow *mainwin;
+
+ mainwin = mainwindow_get_mainwindow();
+ if (mainwin_hidden) {
+ gtk_widget_show(mainwin->window);
+ mainwin_hidden = FALSE;
+ } else {
+ gtk_widget_hide(mainwin->window);
+ mainwin_hidden = TRUE;
+ }
+*/
+ return TRUE;
+}
+
+static void set_trayicon_pixmap(TrayIconType icontype)
+{
+ GdkPixmap *pixmap = NULL;
+ GdkBitmap *bitmap = NULL;
+
+ switch(icontype) {
+ case TRAYICON_NEW:
+ pixmap = mail_pixmap;
+ bitmap = mail_bitmap;
+ break;
+ default:
+ pixmap = nomail_pixmap;
+ bitmap = nomail_bitmap;
+ break;
+ }
+
+ gtk_pixmap_set(GTK_PIXMAP(image), pixmap, bitmap);
+}
+
+static gboolean folder_item_update_hook(gpointer source, gpointer data)
+{
+ gint new, unread, unreadmarked, total;
+ gchar *buf;
+
+ folder_count_total_msgs(&new, &unread, &unreadmarked, &total);
+ buf = g_strdup_printf("New %d, Unread: %d, Total: %d", new, unread, total);
+
+ gtk_tooltips_set_tip(tooltips, eventbox, buf, "");
+ g_free(buf);
+
+ set_trayicon_pixmap(new > 0 ? TRAYICON_NEW : TRAYICON_NOTHING);
+
+ return FALSE;
+}
+
+int plugin_init(gchar **error)
+{
+ hook_id = hooks_register_hook (FOLDER_ITEM_UPDATE_HOOKLIST, folder_item_update_hook, NULL);
+ if (hook_id == -1) {
+ *error = g_strdup("Failed to register folder item update hook");
+ return -1;
+ }
+
+ trayicon = egg_tray_icon_new("Sylpheed-Claws");
+ gtk_container_set_border_width(GTK_CONTAINER(trayicon), 0);
+
+ nomail_pixmap = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(trayicon)->window, &nomail_bitmap, NULL, nomail_xpm);
+ mail_pixmap = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(trayicon)->window, &mail_bitmap, NULL, mail_xpm);
+
+ eventbox = gtk_event_box_new();
+ gtk_container_set_border_width(eventbox, 0);
+ gtk_container_add(GTK_CONTAINER(trayicon), GTK_WIDGET(eventbox));
+
+ image = gtk_pixmap_new (nomail_pixmap, nomail_bitmap);
+ gtk_container_add(GTK_CONTAINER(eventbox), GTK_WIDGET(image));
+
+ gtk_signal_connect(GTK_OBJECT(eventbox), "button-press-event", GTK_SIGNAL_FUNC(click_cb), NULL);
+
+ tooltips = gtk_tooltips_new();
+ gtk_tooltips_set_delay(tooltips, 1000);
+ gtk_tooltips_enable(tooltips);
+
+ gtk_widget_show_all(GTK_WIDGET(trayicon));
+
+ return 0;
+}
+
+void plugin_done()
+{
+ gtk_widget_destroy(GTK_WIDGET(trayicon));
+ hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, hook_id);
+}
+
+const gchar *plugin_name()
+{
+ return "Trayicon";
+}
+
+const gchar *plugin_desc()
+{
+ return "";
+}
+
+const gchar *plugin_type()
+{
+ return "GTK";
+}