summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/about.c4
-rw-r--r--src/calendar.c5
-rw-r--r--src/eggtrayicon.c468
-rw-r--r--src/eggtrayicon.h77
-rw-r--r--src/entry.c5
-rw-r--r--src/fileselection.c5
-rw-r--r--src/main.c67
-rw-r--r--src/msg.c36
-rw-r--r--src/notification.c129
-rw-r--r--src/progress.c5
-rw-r--r--src/text.c5
-rw-r--r--src/tree.c5
-rw-r--r--src/util.c73
-rw-r--r--src/util.h10
-rw-r--r--src/zenity.h6
16 files changed, 814 insertions, 89 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c5c9fcda..310cb560 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,6 +12,9 @@ zenity_SOURCES = \
text.c \
progress.c \
tree.c \
+ notification.c \
+ eggtrayicon.c \
+ eggtrayicon.h \
about.c \
util.h \
util.c
diff --git a/src/about.c b/src/about.c
index 60cb5704..d6fc9083 100644
--- a/src/about.c
+++ b/src/about.c
@@ -300,7 +300,7 @@ zenity_create_boutique (void)
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- zenity_util_set_window_icon (window, ZENITY_IMAGE_FULLPATH ("zenity.png"));
+ zenity_util_set_window_icon (window, NULL, ZENITY_IMAGE_FULLPATH ("zenity.png"));
canvas = zenity_create_monk ();
gtk_container_add (GTK_CONTAINER (window), canvas);
@@ -383,7 +383,7 @@ zenity_about (ZenityData *data)
g_signal_connect (G_OBJECT (dialog), "key_press_event",
G_CALLBACK (zenity_zen_wisdom), glade_dialog);
- zenity_util_set_window_icon (dialog, ZENITY_IMAGE_FULLPATH ("zenity.png"));
+ zenity_util_set_window_icon (dialog, NULL, ZENITY_IMAGE_FULLPATH ("zenity.png"));
image = glade_xml_get_widget (glade_dialog, "zenity_about_image");
diff --git a/src/calendar.c b/src/calendar.c
index 5936aef2..9da633e8 100644
--- a/src/calendar.c
+++ b/src/calendar.c
@@ -58,10 +58,7 @@ zenity_calendar (ZenityData *data, ZenityCalendarData *cal_data)
if (data->dialog_title)
gtk_window_set_title (GTK_WINDOW (dialog), data->dialog_title);
- if (data->window_icon)
- zenity_util_set_window_icon (dialog, data->window_icon);
- else
- zenity_util_set_window_icon (dialog, ZENITY_IMAGE_FULLPATH ("zenity-calendar.png"));
+ zenity_util_set_window_icon (dialog, data->window_icon, ZENITY_IMAGE_FULLPATH ("zenity-calendar.png"));
if (data->width > -1 || data->height > -1)
gtk_window_set_default_size (GTK_WINDOW (dialog), data->width, data->height);
diff --git a/src/eggtrayicon.c b/src/eggtrayicon.c
new file mode 100644
index 00000000..c4aa3e6e
--- /dev/null
+++ b/src/eggtrayicon.c
@@ -0,0 +1,468 @@
+/* -*- 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 <config.h>
+#include <string.h>
+#include <libintl.h>
+
+#include "eggtrayicon.h"
+
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+#ifndef EGG_COMPILATION
+#ifndef _
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+#endif
+#else
+#define _(x) x
+#define N_(x) x
+#endif
+
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+#define SYSTEM_TRAY_ORIENTATION_HORZ 0
+#define SYSTEM_TRAY_ORIENTATION_VERT 1
+
+enum {
+ PROP_0,
+ PROP_ORIENTATION
+};
+
+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_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void egg_tray_icon_realize (GtkWidget *widget);
+static void egg_tray_icon_unrealize (GtkWidget *widget);
+
+static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
+
+GType
+egg_tray_icon_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EggTrayIconClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_tray_icon_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EggTrayIcon),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_tray_icon_init
+ };
+
+ our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
+ }
+
+ return our_type;
+}
+
+static void
+egg_tray_icon_init (EggTrayIcon *icon)
+{
+ icon->stamp = 1;
+ icon->orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
+}
+
+static void
+egg_tray_icon_class_init (EggTrayIconClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *)klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = egg_tray_icon_get_property;
+
+ widget_class->realize = egg_tray_icon_realize;
+ widget_class->unrealize = egg_tray_icon_unrealize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation",
+ _("Orientation"),
+ _("The orientation of the tray."),
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_HORIZONTAL,
+ G_PARAM_READABLE));
+}
+
+static void
+egg_tray_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, icon->orientation);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
+{
+ Display *xdisplay;
+ Atom type;
+ int format;
+ union {
+ gulong *prop;
+ guchar *prop_ch;
+ } prop = { NULL };
+ gulong nitems;
+ gulong bytes_after;
+ int error, result;
+
+ g_assert (icon->manager_window != None);
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ gdk_error_trap_push ();
+ type = None;
+ result = XGetWindowProperty (xdisplay,
+ icon->manager_window,
+ icon->orientation_atom,
+ 0, G_MAXLONG, FALSE,
+ XA_CARDINAL,
+ &type, &format, &nitems,
+ &bytes_after, &(prop.prop_ch));
+ error = gdk_error_trap_pop ();
+
+ if (error || result != Success)
+ return;
+
+ if (type == XA_CARDINAL)
+ {
+ GtkOrientation orientation;
+
+ orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
+ GTK_ORIENTATION_HORIZONTAL :
+ GTK_ORIENTATION_VERTICAL;
+
+ if (icon->orientation != orientation)
+ {
+ icon->orientation = orientation;
+
+ g_object_notify (G_OBJECT (icon), "orientation");
+ }
+ }
+
+ if (prop.prop)
+ XFree (prop.prop);
+}
+
+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 == PropertyNotify &&
+ xev->xproperty.atom == icon->orientation_atom)
+ {
+ egg_tray_icon_get_orientation_property (icon);
+ }
+ 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;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
+ icon->manager_window);
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+ root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+
+ 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_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;
+
+ display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ 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;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+
+ 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|PropertyChangeMask);
+
+ XUngrabServer (xdisplay);
+ XFlush (xdisplay);
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+
+ 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);
+
+ egg_tray_icon_get_orientation_property (icon);
+ }
+}
+
+static void
+egg_tray_icon_realize (GtkWidget *widget)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+ GdkScreen *screen;
+ GdkDisplay *display;
+ Display *xdisplay;
+ char buffer[256];
+ GdkWindow *root_window;
+
+ if (GTK_WIDGET_CLASS (parent_class)->realize)
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+ screen = gtk_widget_get_screen (widget);
+ display = gdk_screen_get_display (screen);
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+
+ /* Now see if there's a manager window around */
+ g_snprintf (buffer, sizeof (buffer),
+ "_NET_SYSTEM_TRAY_S%d",
+ gdk_screen_get_number (screen));
+
+ icon->selection_atom = XInternAtom (xdisplay, buffer, False);
+
+ icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
+
+ icon->system_tray_opcode_atom = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_OPCODE",
+ False);
+
+ icon->orientation_atom = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_ORIENTATION",
+ False);
+
+ egg_tray_icon_update_manager_window (icon);
+
+ root_window = gdk_screen_get_root_window (screen);
+
+ /* Add a root window filter so that we get changes on MANAGER */
+ gdk_window_add_filter (root_window,
+ egg_tray_icon_manager_filter, icon);
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
+}
+
+EggTrayIcon*
+egg_tray_icon_new (const gchar *name)
+{
+ return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
+}
+
+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;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ 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);
+}
+
+GtkOrientation
+egg_tray_icon_get_orientation (EggTrayIcon *icon)
+{
+ g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
+
+ return icon->orientation;
+}
diff --git a/src/eggtrayicon.h b/src/eggtrayicon.h
new file mode 100644
index 00000000..007f4c18
--- /dev/null
+++ b/src/eggtrayicon.h
@@ -0,0 +1,77 @@
+/* -*- 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/gtkplug.h>
+#include <gdk/gdkx.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TRAY_ICON (egg_tray_icon_get_type ())
+#define EGG_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon))
+#define EGG_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+#define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON))
+#define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_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;
+ Atom orientation_atom;
+ Window manager_window;
+
+ GtkOrientation orientation;
+};
+
+struct _EggTrayIconClass
+{
+ GtkPlugClass parent_class;
+};
+
+GType egg_tray_icon_get_type (void);
+
+EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen *screen,
+ const gchar *name);
+
+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);
+
+GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon);
+
+G_END_DECLS
+
+#endif /* __EGG_TRAY_ICON_H__ */
diff --git a/src/entry.c b/src/entry.c
index 4d242160..46672f82 100644
--- a/src/entry.c
+++ b/src/entry.c
@@ -54,10 +54,7 @@ zenity_entry (ZenityData *data, ZenityEntryData *entry_data)
if (data->dialog_title)
gtk_window_set_title (GTK_WINDOW (dialog), data->dialog_title);
- if (data->window_icon)
- zenity_util_set_window_icon (dialog, data->window_icon);
- else
- zenity_util_set_window_icon (dialog, ZENITY_IMAGE_FULLPATH ("zenity-entry.png"));
+ zenity_util_set_window_icon (dialog, data->window_icon, ZENITY_IMAGE_FULLPATH ("zenity-entry.png"));
if (data->width > -1 || data->height > -1)
gtk_window_set_default_size (GTK_WINDOW (dialog), data->width, data->height);
diff --git a/src/fileselection.c b/src/fileselection.c
index fdd40fdd..4d50fb76 100644
--- a/src/fileselection.c
+++ b/src/fileselection.c
@@ -60,10 +60,7 @@ void zenity_fileselection (ZenityData *data, ZenityFileData *file_data)
if (data->dialog_title)
gtk_window_set_title (GTK_WINDOW (dialog), data->dialog_title);
- if (data->window_icon)
- zenity_util_set_window_icon (dialog, data->window_icon);
- else
- zenity_util_set_window_icon (dialog, ZENITY_IMAGE_FULLPATH ("zenity-file.png"));
+ zenity_util_set_window_icon (dialog, data->window_icon, ZENITY_IMAGE_FULLPATH ("zenity-file.png"));
if (file_data->uri) {
dir = g_path_get_dirname (file_data->uri);
diff --git a/src/main.c b/src/main.c
index 09b1519c..4d8c6079 100644
--- a/src/main.c
+++ b/src/main.c
@@ -42,6 +42,7 @@ typedef enum {
MODE_TEXTINFO,
MODE_WARNING,
MODE_INFO,
+ MODE_NOTIFICATION,
MODE_ABOUT,
MODE_LAST
} ZenityDialogMode;
@@ -64,6 +65,7 @@ typedef struct {
ZenityProgressData *progress_data;
ZenityTextData *text_data;
ZenityTreeData *tree_data;
+ ZenityNotificationData *notification_data;
} ZenityParsingOptions;
enum {
@@ -79,6 +81,7 @@ enum {
OPTION_TEXTINFO,
OPTION_TEXTEDIT,
OPTION_WARNING,
+ OPTION_NOTIFICATION,
OPTION_TITLE,
OPTION_ICON,
OPTION_WIDTH,
@@ -110,6 +113,8 @@ enum {
OPTION_PRINTCOLUMN,
OPTION_QUESTIONTEXT,
OPTION_WARNINGTEXT,
+ OPTION_NOTIFICATIONICON,
+ OPTION_NOTIFICATIONTEXT,
OPTION_ABOUT,
OPTION_VERSION,
OPTION_LAST,
@@ -186,6 +191,15 @@ struct poptOption options[] = {
NULL
},
{
+ "notification",
+ '\0',
+ POPT_ARG_NONE,
+ NULL,
+ OPTION_NOTIFICATION,
+ N_("Display notification"),
+ NULL
+ },
+ {
"progress",
'\0',
POPT_ARG_NONE,
@@ -548,6 +562,28 @@ struct poptOption list_options[] = {
POPT_TABLEEND
};
+struct poptOption notification_options[] = {
+ {
+ NULL,
+ '\0',
+ POPT_ARG_CALLBACK | POPT_CBFLAG_POST,
+ zenity_parse_options_callback,
+ 0,
+ NULL,
+ NULL
+ },
+ {
+ "text",
+ '\0',
+ POPT_ARG_STRING,
+ NULL,
+ OPTION_NOTIFICATIONTEXT,
+ N_("Set the notification text"),
+ NULL
+ },
+ POPT_TABLEEND
+};
+
struct poptOption progress_options[] = {
{
NULL,
@@ -900,6 +936,15 @@ struct poptOption application_options[] = {
NULL,
'\0',
POPT_ARG_INCLUDE_TABLE,
+ notification_options,
+ 0,
+ N_("Notication options"),
+ NULL
+ },
+ {
+ NULL,
+ '\0',
+ POPT_ARG_INCLUDE_TABLE,
progress_options,
0,
N_("Progress options"),
@@ -979,6 +1024,7 @@ zenity_init_parsing_options (void) {
results->progress_data = g_new0 (ZenityProgressData, 1);
results->text_data = g_new0 (ZenityTextData, 1);
results->tree_data = g_new0 (ZenityTreeData, 1);
+ results->notification_data = g_new0 (ZenityNotificationData, 1);
/* Give some sensible defaults */
results->data->width = -1;
@@ -1056,6 +1102,10 @@ zenity_free_parsing_options (void) {
if (results->tree_data->print_column)
g_free (results->tree_data->print_column);
break;
+ case MODE_NOTIFICATION:
+ if (results->notification_data->notification_text)
+ g_free (results->notification_data->notification_text);
+ break;
default:
break;
}
@@ -1125,6 +1175,9 @@ main (gint argc, gchar **argv) {
results->tree_data->data = poptGetArgs (ctx);
zenity_tree (results->data, results->tree_data);
break;
+ case MODE_NOTIFICATION:
+ zenity_notification (results->data, results->notification_data);
+ break;
case MODE_PROGRESS:
zenity_progress (results->data, results->progress_data);
break;
@@ -1229,6 +1282,12 @@ zenity_parse_options_callback (poptContext ctx,
results->mode = MODE_LIST;
break;
+ case OPTION_NOTIFICATION:
+ if (results->mode != MODE_LAST)
+ zenity_error (NULL, ERROR_DIALOG);
+
+ results->mode = MODE_NOTIFICATION;
+ break;
case OPTION_PROGRESS:
if (results->mode != MODE_LAST)
zenity_error (NULL, ERROR_DIALOG);
@@ -1286,13 +1345,13 @@ zenity_parse_options_callback (poptContext ctx,
case OPTION_PROGRESSTEXT:
case OPTION_LISTTEXT:
case OPTION_WARNINGTEXT:
-
+ case OPTION_NOTIFICATIONTEXT:
/* FIXME: This is an ugly hack because of the way the poptOptions are
* ordered above. When you try and use an --option more than once
* parse_options_callback gets called for each option. Suckage
*/
- if (parse_option_text > 7)
+ if (parse_option_text > 8)
zenity_error ("--text", ERROR_DUPLICATE);
switch (results->mode) {
@@ -1319,6 +1378,10 @@ zenity_parse_options_callback (poptContext ctx,
results->tree_data->dialog_text = g_locale_to_utf8 (g_strcompress (arg),
-1, NULL, NULL, NULL);
break;
+ case MODE_NOTIFICATION:
+ results->notification_data->notification_text = g_locale_to_utf8 (g_strcompress (arg),
+ -1, NULL, NULL, NULL);
+ break;
default:
zenity_error ("--text", ERROR_SUPPORT);
}
diff --git a/src/msg.c b/src/msg.c
index 27284472..ffb2e531 100644
--- a/src/msg.c
+++ b/src/msg.c
@@ -83,29 +83,25 @@ zenity_msg (ZenityData *data, ZenityMsgData *msg_data)
if (data->dialog_title)
gtk_window_set_title (GTK_WINDOW (dialog), data->dialog_title);
- if (data->window_icon)
- zenity_util_set_window_icon (dialog, data->window_icon);
- else {
- switch (msg_data->mode) {
- case ZENITY_MSG_WARNING:
- zenity_util_set_window_icon_from_stock (dialog, GTK_STOCK_DIALOG_WARNING);
- break;
-
- case ZENITY_MSG_QUESTION:
- zenity_util_set_window_icon_from_stock (dialog, GTK_STOCK_DIALOG_QUESTION);
- break;
+ switch (msg_data->mode) {
+ case ZENITY_MSG_WARNING:
+ zenity_util_set_window_icon_from_stock (dialog, data->window_icon, GTK_STOCK_DIALOG_WARNING);
+ break;
+
+ case ZENITY_MSG_QUESTION:
+ zenity_util_set_window_icon_from_stock (dialog, data->window_icon, GTK_STOCK_DIALOG_QUESTION);
+ break;
- case ZENITY_MSG_ERROR:
- zenity_util_set_window_icon_from_stock (dialog, GTK_STOCK_DIALOG_ERROR);
- break;
+ case ZENITY_MSG_ERROR:
+ zenity_util_set_window_icon_from_stock (dialog, data->window_icon, GTK_STOCK_DIALOG_ERROR);
+ break;
- case ZENITY_MSG_INFO:
- zenity_util_set_window_icon_from_stock (dialog, GTK_STOCK_DIALOG_INFO);
- break;
+ case ZENITY_MSG_INFO:
+ zenity_util_set_window_icon_from_stock (dialog, data->window_icon, GTK_STOCK_DIALOG_INFO);
+ break;
- default:
- break;
- }
+ default:
+ break;
}
if (data->width > -1 || data->height > -1)
diff --git a/src/notification.c b/src/notification.c
new file mode 100644
index 00000000..42f72c5b
--- /dev/null
+++ b/src/notification.c
@@ -0,0 +1,129 @@
+/*
+ * notification.c
+ *
+ * Copyright (C) 2002 Sun Microsystems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ *
+ * Authors: Glynn Foster <glynn.foster@sun.com>
+ */
+
+#include <glade/glade.h>
+#include <time.h>
+#include "zenity.h"
+#include "eggtrayicon.h"
+#include "util.h"
+
+EggTrayIcon *tray_icon;
+
+static gboolean
+zenity_notification_icon_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ ZenityData *zen_data;
+
+ zen_data = data;
+
+ zen_data->exit_code = zenity_util_return_exit_code (ZENITY_OK);
+ gtk_main_quit ();
+}
+
+static gboolean
+zenity_notification_icon_expose_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ if (GTK_WIDGET_HAS_FOCUS (widget)) {
+ gint focus_width, focus_pad;
+ gint x, y, width, height;
+
+ gtk_widget_style_get (widget,
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ NULL);
+ x = widget->allocation.x + focus_pad;
+ y = widget->allocation.y + focus_pad;
+ width = widget->allocation.width - 2 * focus_pad;
+ height = widget->allocation.height - 2 * focus_pad;
+
+ gtk_paint_focus (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget),
+ &event->area, widget, "button",
+ x, y, width, height);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+zenity_notification_icon_destroy_callback (GtkWidget *widget, gpointer data)
+{
+ ZenityData *zen_data;
+
+ zen_data = data;
+ gtk_widget_destroy (GTK_WIDGET (tray_icon));
+
+ zen_data->exit_code = zenity_util_return_exit_code (ZENITY_ESC);
+ gtk_main_quit ();
+}
+
+void
+zenity_notification (ZenityData *data, ZenityNotificationData *notification_data)
+{
+ GtkWidget *icon_image;
+ GtkWidget *icon_event_box;
+ GtkTooltips *tooltips;
+ GdkPixbuf *pixbuf = NULL;
+
+ tray_icon = egg_tray_icon_new (_("Zenity notification"));
+ tooltips = gtk_tooltips_new ();
+
+ if (data->window_icon != NULL)
+ pixbuf = zenity_util_pixbuf_new_from_file (GTK_WIDGET (tray_icon), data->window_icon);
+ else
+ pixbuf = gdk_pixbuf_new_from_file (ZENITY_IMAGE_FULLPATH ("zenity-notification.png"), NULL);
+
+ icon_event_box = gtk_event_box_new ();
+
+ if (pixbuf) {
+ icon_image = gtk_image_new_from_pixbuf (pixbuf);
+ gdk_pixbuf_unref (pixbuf);
+ } else {
+ g_warning ("Could not load notification icon : %s", ZENITY_IMAGE_FULLPATH ("zenity-notification.png"));
+ return;
+ }
+
+ gtk_container_add (GTK_CONTAINER (icon_event_box), icon_image);
+
+ if (notification_data->notification_text)
+ gtk_tooltips_set_tip (tooltips, icon_event_box, notification_data->notification_text, notification_data->notification_text);
+ else
+ gtk_tooltips_set_tip (tooltips, icon_event_box, _("Zenity notification"), _("Zenity notification"));
+
+ gtk_widget_add_events (GTK_WIDGET (tray_icon), GDK_BUTTON_PRESS_MASK | GDK_FOCUS_CHANGE_MASK);
+ gtk_container_add (GTK_CONTAINER (tray_icon), icon_event_box);
+
+ g_signal_connect (tray_icon, "button_press_event",
+ G_CALLBACK (zenity_notification_icon_press_callback), data);
+
+ g_signal_connect (tray_icon, "destroy",
+ G_CALLBACK (zenity_notification_icon_destroy_callback), data);
+
+ g_signal_connect (tray_icon, "expose_event",
+ G_CALLBACK (zenity_notification_icon_expose_callback), data);
+
+ gtk_widget_show_all (GTK_WIDGET (tray_icon));
+
+ /* Does nothing at the moment */
+ gtk_main ();
+}
diff --git a/src/progress.c b/src/progress.c
index 373c5b82..ed727cae 100644
--- a/src/progress.c
+++ b/src/progress.c
@@ -191,10 +191,7 @@ zenity_progress (ZenityData *data, ZenityProgressData *progress_data)
if (data->dialog_title)
gtk_window_set_title (GTK_WINDOW (dialog), data->dialog_title);
- if (data->window_icon)
- zenity_util_set_window_icon (dialog, data->window_icon);
- else
- zenity_util_set_window_icon (dialog, ZENITY_IMAGE_FULLPATH ("zenity-progress.png"));
+ zenity_util_set_window_icon (dialog, data->window_icon, ZENITY_IMAGE_FULLPATH ("zenity-progress.png"));
if (data->width > -1 || data->height > -1)
gtk_window_set_default_size (GTK_WINDOW (dialog), data->width, data->height);
diff --git a/src/text.c b/src/text.c
index b70bed0a..acd17394 100644
--- a/src/text.c
+++ b/src/text.c
@@ -128,10 +128,7 @@ zenity_text (ZenityData *data, ZenityTextData *text_data)
if (data->dialog_title)
gtk_window_set_title (GTK_WINDOW (dialog), data->dialog_title);
- if (data->window_icon)
- zenity_util_set_window_icon (dialog, data->window_icon);
- else
- zenity_util_set_window_icon (dialog, ZENITY_IMAGE_FULLPATH ("zenity-text.png"));
+ zenity_util_set_window_icon (dialog, data->window_icon, ZENITY_IMAGE_FULLPATH ("zenity-text.png"));
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
diff --git a/src/tree.c b/src/tree.c
index fed58e2a..436f632f 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -320,10 +320,7 @@ zenity_tree (ZenityData *data, ZenityTreeData *tree_data)
if (tree_data->dialog_text)
gtk_label_set_text (GTK_LABEL (text), tree_data->dialog_text);
- if (data->window_icon)
- zenity_util_set_window_icon (dialog, data->window_icon);
- else
- zenity_util_set_window_icon (dialog, ZENITY_IMAGE_FULLPATH ("zenity-list.png"));
+ zenity_util_set_window_icon (dialog, data->window_icon, ZENITY_IMAGE_FULLPATH ("zenity-list.png"));
if (data->width > -1 || data->height > -1)
gtk_window_set_default_size (GTK_WINDOW (dialog), data->width, data->height);
diff --git a/src/util.c b/src/util.c
index 3364e306..b839d424 100644
--- a/src/util.c
+++ b/src/util.c
@@ -143,56 +143,53 @@ zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename)
return TRUE;
}
-static GList *
-zenity_util_list_from_char_array (const char **s)
+GdkPixbuf *
+zenity_util_pixbuf_new_from_file (GtkWidget *widget, gchar *filename)
{
- GList *list = NULL;
- gint i;
-
- for (i = 0; s[i]; i++) {
- GdkPixbuf *pixbuf;
-
- pixbuf = gdk_pixbuf_new_from_file (s[i], NULL);
- if (pixbuf)
- list = g_list_prepend (list, pixbuf);
- }
-
- return list;
-}
-
-static void
-zenity_util_free_list (GList *list)
-{
- g_list_foreach (list, (GFunc) g_object_unref, NULL);
- g_list_free (list);
+ if (!strcmp (g_strdown (filename), "warning"))
+ return gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON, NULL);
+ if (!strcmp (g_strdown (filename), "info"))
+ return gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON, NULL);
+ if (!strcmp (g_strdown (filename), "question"))
+ return gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_BUTTON, NULL);
+ if (!strcmp (g_strdown (filename), "error"))
+ return gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_BUTTON, NULL);
+ else
+ return gdk_pixbuf_new_from_file (filename, NULL);
}
void
-zenity_util_set_window_icon (GtkWidget *widget, const gchar *filename)
+zenity_util_set_window_icon (GtkWidget *widget, const gchar *filename, const gchar *default_file)
{
- const gchar *filenames[2] = { NULL};
- GList *list;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_WINDOW (widget));
+ GdkPixbuf *pixbuf;
- if (filename == NULL)
- return;
+ if (filename != NULL)
+ pixbuf = zenity_util_pixbuf_new_from_file (widget, (gchar *) filename);
+ else
+ pixbuf = gdk_pixbuf_new_from_file (default_file, NULL);
- filenames[0] = filename;
- list = zenity_util_list_from_char_array (filenames);
- gtk_window_set_icon_list (GTK_WINDOW (widget), list);
- zenity_util_free_list (list);
+ if (pixbuf != NULL) {
+ gtk_window_set_icon (GTK_WINDOW (widget), pixbuf);
+ g_object_unref (pixbuf);
+ }
}
void
-zenity_util_set_window_icon_from_stock (GtkWidget *widget, const gchar *stock_id)
+zenity_util_set_window_icon_from_stock (GtkWidget *widget, const gchar *filename, const gchar *default_stock_id)
{
GdkPixbuf *pixbuf;
-
- pixbuf = gtk_widget_render_icon (widget, stock_id, (GtkIconSize) -1, NULL);
- gtk_window_set_icon (GTK_WINDOW (widget), pixbuf);
- g_object_unref (pixbuf);
+
+ if (filename != NULL) {
+ pixbuf = zenity_util_pixbuf_new_from_file (widget, (gchar *) filename);
+ }
+ else {
+ pixbuf = gtk_widget_render_icon (widget, default_stock_id, GTK_ICON_SIZE_BUTTON, NULL);
+ }
+
+ if (pixbuf != NULL) {
+ gtk_window_set_icon (GTK_WINDOW (widget), pixbuf);
+ g_object_unref (pixbuf);
+ }
}
void
diff --git a/src/util.h b/src/util.h
index 69ec9122..4e3c2142 100644
--- a/src/util.h
+++ b/src/util.h
@@ -15,10 +15,14 @@ GladeXML* zenity_util_load_glade_file (const gchar *widge
gchar * zenity_util_strip_newline (gchar *string);
gboolean zenity_util_fill_file_buffer (GtkTextBuffer *buffer,
const gchar *filename);
-void zenity_util_set_window_icon (GtkWidget *widget,
- const gchar *filename);
+void zenity_util_set_window_icon (GtkWidget *widget,
+ const gchar *filename,
+ const gchar *default_file);
void zenity_util_set_window_icon_from_stock (GtkWidget *widget,
- const gchar *stock_id);
+ const gchar *filename,
+ const gchar *default_stock_id);
+GdkPixbuf * zenity_util_pixbuf_new_from_file (GtkWidget *widget,
+ gchar *filename);
void zenity_util_show_help (GError **error);
gint zenity_util_return_exit_code (ZenityExitCode value);
void zenity_util_show_dialog (GtkWidget *widget);
diff --git a/src/zenity.h b/src/zenity.h
index d9aff43f..3d4eeeac 100644
--- a/src/zenity.h
+++ b/src/zenity.h
@@ -98,6 +98,10 @@ typedef struct {
const gchar **data;
} ZenityTreeData;
+typedef struct {
+ gchar *notification_text;
+} ZenityNotificationData;
+
void zenity_calendar (ZenityData *data,
ZenityCalendarData *calendar_data);
void zenity_msg (ZenityData *data,
@@ -112,6 +116,8 @@ void zenity_text (ZenityData *data,
ZenityTextData *text_data);
void zenity_tree (ZenityData *data,
ZenityTreeData *tree_data);
+void zenity_notification (ZenityData *data,
+ ZenityNotificationData *notification_data);
void zenity_about (ZenityData *data);
G_END_DECLS
bgstack15