summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--configure.in4
-rw-r--r--src/Makefile.am20
-rw-r--r--src/eggtrayicon.c468
-rw-r--r--src/eggtrayicon.h77
-rw-r--r--src/notification.c287
-rw-r--r--src/util.c36
-rw-r--r--src/util.h3
8 files changed, 183 insertions, 730 deletions
diff --git a/ChangeLog b/ChangeLog
index c25ac14..2c6b0af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
2006-07-27 Lucas Rocha <lucasr@gnome.org>
+ * src/notification.c (-set_scaled_pixbuf,
+ +zenity_notification_icon_update,
+ -zenity_notification_icon_press_callback,
+ +zenity_notification_icon_size_changed_cb,
+ -zenity_notification_icon_expose_callback,
+ -zenity_notification_icon_destroy_callback,
+ +zenity_notification_icon_activate_cb,
+ zenity_notification_handle_stdin, zenity_notification),
+ src/util.[ch] (+zenity_util_stock_from_filename,
+ zenity_util_pixbuf_new_from_file), Makefile.am, configure.in:
+
+ Migration to gtk_status_icon (Fixes bug #341451). Patch from
+ Christian Persch <chpe@gnome.org>.
+
+ * src/eggtrayicon.[ch]: removed.
+
+2006-07-27 Lucas Rocha <lucasr@gnome.org>
+
* src/text.c (zenity_text_handle_stdin): correctly stdin input for
text info dialog (Fixes bug #336736).
diff --git a/configure.in b/configure.in
index 87c243d..4acf5b7 100644
--- a/configure.in
+++ b/configure.in
@@ -16,7 +16,7 @@ IT_PROG_INTLTOOL([0.34.90])
AC_PROG_CC
-GTK_REQUIRED=2.9.0
+GTK_REQUIRED=2.9.2
PKG_CHECK_MODULES([ZENITY],[gtk+-2.0 >= $GTK_REQUIRED libglade-2.0 libgnomecanvas-2.0 glib-2.0])
AC_SUBST([ZENITY_CFLAGS])
@@ -32,7 +32,7 @@ AC_PATH_PROG([PERL],[perl],)
# libnotify check
# *******************************
-LIBNOTIFY_REQUIRED=0.3.2
+LIBNOTIFY_REQUIRED=0.4.1
PKG_CHECK_MODULES([LIBNOTIFY],[libnotify >= $LIBNOTIFY_REQUIRED],
[HAVE_LIBNOTIFY="yes"],[HAVE_LIBNOTIFY="no"])
AC_SUBST([LIBNOTIFY_CFLAGS])
diff --git a/src/Makefile.am b/src/Makefile.am
index 192dc3b..e70a51b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,24 +3,22 @@ bin_PROGRAMS = zenity
bin_SCRIPTS = gdialog
zenity_SOURCES = \
+ about.c \
+ calendar.c \
+ entry.c \
+ fileselection.c \
main.c \
+ msg.c \
+ notification.c \
option.c \
option.h \
- zenity.h \
- calendar.c \
- msg.c \
+ progress.c \
scale.c \
- fileselection.c \
- entry.c \
text.c \
- progress.c \
tree.c \
- eggtrayicon.h \
- eggtrayicon.c \
- notification.c \
- about.c \
+ util.c \
util.h \
- util.c
+ zenity.h
zenity_CPPFLAGS = \
-I$(includedir) \
diff --git a/src/eggtrayicon.c b/src/eggtrayicon.c
deleted file mode 100644
index 1e6d5bd..0000000
--- a/src/eggtrayicon.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/* -*- 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., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, 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
deleted file mode 100644
index 007f4c1..0000000
--- a/src/eggtrayicon.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- 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/notification.c b/src/notification.c
index 6d5f8dd..222fbc8 100644
--- a/src/notification.c
+++ b/src/notification.c
@@ -2,6 +2,7 @@
* notification.c
*
* Copyright (C) 2002 Sun Microsystems, Inc.
+ * Copyright (C) 2006 Christian Persch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -23,6 +24,7 @@
#include <config.h>
+#include <gtk/gtk.h>
#include <glade/glade.h>
#include <time.h>
#include <string.h>
@@ -32,101 +34,71 @@
#endif
#include "zenity.h"
-#include "eggtrayicon.h"
#include "util.h"
-static EggTrayIcon *tray_icon;
-static GtkWidget *icon_image;
-static GtkWidget *icon_event_box;
-static GtkTooltips *tooltips;
-
+static GtkStatusIcon *status_icon;
+static gchar *icon_file;
+static const gchar *icon_stock;
+static gint icon_size;
static void
-set_scaled_pixbuf (GtkImage *image, GdkPixbuf *pixbuf, GtkIconSize icon_size)
+zenity_notification_icon_update (void)
{
- GdkScreen *screen;
- GtkSettings *settings;
- int width, height, desired_width, desired_height;
- GdkPixbuf *new_pixbuf;
-
- screen = gtk_widget_get_screen (GTK_WIDGET (image));
- settings = gtk_settings_get_for_screen (screen);
- if (!gtk_icon_size_lookup_for_settings (settings, icon_size,
- &desired_width, &desired_height))
- return;
-
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- if (height > desired_height || width > desired_width) {
- if (width * desired_height / height > desired_width)
- desired_height = height * desired_width / width;
- else
- desired_width = width * desired_height / height;
-
- new_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
- desired_width,
- desired_height,
- GDK_INTERP_BILINEAR);
- gtk_image_set_from_pixbuf (image, new_pixbuf);
- g_object_unref (new_pixbuf);
- } else {
- gtk_image_set_from_pixbuf (image, pixbuf);
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
+
+ pixbuf = gdk_pixbuf_new_from_file_at_scale (icon_file, icon_size, icon_size, TRUE, &error);
+ if (error) {
+ g_warning ("Could not load notification icon '%s': %s",
+ icon_file, error->message);
+ g_clear_error (&error);
+ }
+ if (!pixbuf) {
+ pixbuf = gdk_pixbuf_new_from_file_at_scale (ZENITY_IMAGE_FULLPATH ("zenity-notification.png"),
+ icon_size, icon_size, TRUE, NULL);
+ }
+
+ gtk_status_icon_set_from_pixbuf (status_icon, pixbuf);
+
+ if (pixbuf) {
+ g_object_unref (pixbuf);
}
}
static gboolean
-zenity_notification_icon_press_callback (GtkWidget *widget, GdkEventButton *event, gpointer data)
+zenity_notification_icon_size_changed_cb (GtkStatusIcon *icon,
+ gint size,
+ gpointer user_data)
{
- ZenityData *zen_data;
+ icon_size = size;
- zen_data = data;
+ /* If we're displaying not a stock icon but a custom pixbuf,
+ * we need to update the icon for the new size.
+ */
+ if (!icon_stock) {
+ zenity_notification_icon_update ();
- zen_data->exit_code = zenity_util_return_exit_code (ZENITY_OK);
- gtk_main_quit ();
- return TRUE;
-}
+ return TRUE;
+ }
-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;
+ return FALSE;
}
-static void
-zenity_notification_icon_destroy_callback (GtkWidget *widget, gpointer data)
+static gboolean
+zenity_notification_icon_activate_cb (GtkWidget *widget,
+ ZenityData *data)
{
- ZenityData *zen_data;
+ data->exit_code = zenity_util_return_exit_code (ZENITY_OK);
- zen_data = data;
- gtk_widget_destroy (GTK_WIDGET (tray_icon));
-
- zen_data->exit_code = zenity_util_return_exit_code (ZENITY_ESC);
gtk_main_quit ();
+
+ return TRUE;
}
static gboolean
-zenity_notification_handle_stdin (GIOChannel *channel,
+zenity_notification_handle_stdin (GIOChannel *channel,
GIOCondition condition,
- gpointer user_data)
+ gpointer user_data)
{
ZenityData *zen_data;
@@ -137,7 +109,7 @@ zenity_notification_handle_stdin (GIOChannel *channel,
GError *error = NULL;
string = g_string_new (NULL);
- while (channel->is_readable != TRUE)
+ while (channel->is_readable == FALSE)
;
do {
gint status;
@@ -167,60 +139,72 @@ zenity_notification_handle_stdin (GIOChannel *channel,
continue;
}
/* split off the command and value */
- command = g_strndup (string->str, colon - string->str);
- command = g_strstrip (command);
- g_strdown (command);
+ command = g_strstrip (g_strndup (string->str, colon - string->str));
value = colon + 1;
while (*value && g_ascii_isspace (*value)) value++;
- if (!strcmp (command, "icon")) {
- GdkPixbuf *pixbuf;
-
- pixbuf = zenity_util_pixbuf_new_from_file (GTK_WIDGET (tray_icon),
- value);
- if (pixbuf != NULL) {
- set_scaled_pixbuf (GTK_IMAGE (icon_image), pixbuf,
- GTK_ICON_SIZE_BUTTON);
- gdk_pixbuf_unref (pixbuf);
- } else {
- g_warning ("Could not load notification icon : %s", value);
- }
- } else if (!strcmp (command, "message")) {
-#ifdef HAVE_LIBNOTIFY
- /* display a notification bubble */
- if (notify_is_initted ()) {
- GError *error = NULL;
- NotifyNotification *n;
- GdkPixbuf *icon;
-
- n = notify_notification_new (g_strcompress (value), NULL, NULL,
- GTK_WIDGET (tray_icon));
+ if (!g_ascii_strcasecmp (command, "icon")) {
+ icon_stock = zenity_util_stock_from_filename (value);
- icon = gtk_image_get_pixbuf (GTK_IMAGE (icon_image));
+ g_free (icon_file);
+ icon_file = g_strdup (value);
- notify_notification_set_icon_from_pixbuf (n, icon);
-
- notify_notification_show (n, &error);
+ if (icon_stock) {
+ gtk_status_icon_set_from_stock (status_icon, icon_stock);
+ } else if (gtk_status_icon_get_visible (status_icon) &&
+ gtk_status_icon_is_embedded (status_icon)) {
+ zenity_notification_icon_update ();
+ }
+ } else if (!g_ascii_strcasecmp (command, "message")) {
+#ifdef HAVE_LIBNOTIFY
+ /* display a notification bubble */
+ if (!g_utf8_validate (value, -1, NULL)) {
+ g_warning ("Invalid UTF-8 in input!");
+ } else if (notify_is_initted ()) {
+ GError *error = NULL;
+ NotifyNotification *notif;
+ const gchar *icon = NULL;
+ gchar *freeme = NULL;
+ gchar *message;
+
+ message = g_strcompress (value);
+
+ if (icon_stock) {
+ icon = icon_stock;
+ } else if (icon_file) {
+ icon = freeme = g_filename_to_uri (icon_file, NULL, NULL);
+ }
+
+ notif = notify_notification_new_with_status_icon (message, NULL /* summary */,
+ icon, status_icon);
+ g_free (message);
+ g_free (freeme);
+
+ notify_notification_show (notif, &error);
if (error) {
- g_warning (error->message);
+ g_warning ("Error showing notification: %s", error->message);
g_error_free (error);
}
- g_object_unref (G_OBJECT (n));
+ g_object_unref (notif);
} else {
#else
{ /* this brace is for balance */
#endif
g_warning ("Notification framework not available");
}
- } else if (!strcmp (command, "tooltip")) {
- gtk_tooltips_set_tip (tooltips, icon_event_box, value, value);
- } else if (!strcmp (command, "visible")) {
- if (!strcasecmp (value, "false")) {
- gtk_widget_hide (GTK_WIDGET (tray_icon));
- } else {
- gtk_widget_show (GTK_WIDGET (tray_icon));
+ } else if (!g_ascii_strcasecmp (command, "tooltip")) {
+ if (g_utf8_validate (value, -1, NULL)) {
+ gtk_status_icon_set_tooltip (status_icon, value);
+ } else {
+ g_warning ("Invalid UTF-8 in input!");
+ }
+ } else if (!g_ascii_strcasecmp (command, "visible")) {
+ if (!g_ascii_strcasecmp (value, "false")) {
+ gtk_status_icon_set_visible (status_icon, FALSE);
+ } else {
+ gtk_status_icon_set_visible (status_icon, TRUE);
}
} else {
g_warning ("Unknown command '%s'", command);
@@ -256,64 +240,47 @@ zenity_notification_listen_on_stdin (ZenityData *data)
void
zenity_notification (ZenityData *data, ZenityNotificationData *notification_data)
{
- GdkPixbuf *pixbuf = NULL;
+ status_icon = gtk_status_icon_new ();
+ g_signal_connect (status_icon, "size-changed",
+ G_CALLBACK (zenity_notification_icon_size_changed_cb), data);
- 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 ();
- icon_image = gtk_image_new ();
-
- if (pixbuf) {
- set_scaled_pixbuf (GTK_IMAGE (icon_image), pixbuf,
- GTK_ICON_SIZE_BUTTON);
- gdk_pixbuf_unref (pixbuf);
+ if (notification_data->notification_text) {
+ gtk_status_icon_set_tooltip (status_icon, notification_data->notification_text);
} else {
- if (data->window_icon != NULL) {
- g_warning ("Could not load notification icon : %s", data->window_icon);
- }
- else
- g_warning ("Could not load notification icon : %s", ZENITY_IMAGE_FULLPATH ("zenity-notification.png"));
- return;
+ gtk_status_icon_set_tooltip (status_icon, _("Zenity notification"));
}
- 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);
+ icon_file = g_strdup (data->window_icon);
+ icon_stock = zenity_util_stock_from_filename (data->window_icon);
- 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);
+ /* Only set the stock icon here; if we're going to display a
+ * custom pixbuf we wait for the size-changed signal to load
+ * it at the right size.
+ */
+ if (icon_stock) {
+ gtk_status_icon_set_from_stock (status_icon, icon_stock);
+ }
+#ifdef HAVE_LIBNOTIFY
+ /* create the notification widget */
+ if (!notify_is_initted ()) {
+ notify_init (_("Zenity notification"));
+ }
+#endif
+
if (notification_data->listen) {
zenity_notification_listen_on_stdin (data);
} else {
- /* if we aren't listening for changes, then close on button_press */
- g_signal_connect (tray_icon, "button_press_event",
- G_CALLBACK (zenity_notification_icon_press_callback), data);
+ /* if we aren't listening for changes, then close on activate (left-click) */
+ g_signal_connect (status_icon, "activate",
+ G_CALLBACK (zenity_notification_icon_activate_cb), data);
}
-#ifdef HAVE_LIBNOTIFY
- /* create the notification widget */
- if (!notify_is_initted ())
- notify_init (_("Zenity notification"));
-#endif
-
- gtk_widget_show_all (GTK_WIDGET (tray_icon));
-
- /* Does nothing at the moment */
+ /* Show icon and wait */
+ gtk_status_icon_set_visible (status_icon, TRUE);
gtk_main ();
+
+ /* Cleanup */
+ g_object_unref (status_icon);
+ g_free (icon_file);
}
diff --git a/src/util.c b/src/util.c
index 4fc7f8d..41c7c55 100644
--- a/src/util.c
+++ b/src/util.c
@@ -145,19 +145,33 @@ zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename)
return TRUE;
}
+const gchar *
+zenity_util_stock_from_filename (const gchar *filename)
+{
+ if (!filename || !filename[0])
+ return GTK_STOCK_DIALOG_WARNING; /* default */
+
+ if (!g_ascii_strcasecmp (filename, "warning"))
+ return GTK_STOCK_DIALOG_WARNING;
+ if (!g_ascii_strcasecmp (filename, "info"))
+ return GTK_STOCK_DIALOG_INFO;
+ if (!g_ascii_strcasecmp (filename, "question"))
+ return GTK_STOCK_DIALOG_QUESTION;
+ if (!g_ascii_strcasecmp (filename, "error"))
+ return GTK_STOCK_DIALOG_ERROR;
+ return NULL;
+}
+
GdkPixbuf *
-zenity_util_pixbuf_new_from_file (GtkWidget *widget, gchar *filename)
+zenity_util_pixbuf_new_from_file (GtkWidget *widget, const gchar *filename)
{
- if (!strcasecmp (filename, "warning"))
- return gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON, NULL);
- if (!strcasecmp (filename, "info"))
- return gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON, NULL);
- if (!strcasecmp (filename, "question"))
- return gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_BUTTON, NULL);
- if (!strcasecmp (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);
+ const gchar *stock;
+
+ stock = zenity_util_stock_from_filename (filename);
+ if (stock)
+ return gtk_widget_render_icon (widget, stock, GTK_ICON_SIZE_BUTTON, NULL);
+
+ return gdk_pixbuf_new_from_file (filename, NULL);
}
void
diff --git a/src/util.h b/src/util.h
index cbf96ab..7535275 100644
--- a/src/util.h
+++ b/src/util.h
@@ -15,6 +15,7 @@ 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);
+const gchar * zenity_util_stock_from_filename (const gchar *filename);
void zenity_util_set_window_icon (GtkWidget *widget,
const gchar *filename,
const gchar *default_file);
@@ -22,7 +23,7 @@ void zenity_util_set_window_icon_from_stock (GtkWidget *widge
const gchar *filename,
const gchar *default_stock_id);
GdkPixbuf * zenity_util_pixbuf_new_from_file (GtkWidget *widget,
- gchar *filename);
+ const gchar *filename);
void zenity_util_show_help (GError **error);
gint zenity_util_return_exit_code (ZenityExitCode value);
void zenity_util_show_dialog (GtkWidget *widget);