src/notification.c (-set_scaled_pixbuf, +zenity_notification_icon_update,

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.
This commit is contained in:
Lucas Rocha 2006-07-28 21:25:11 +00:00 committed by Lucas Almeida Rocha
parent e46814b46a
commit d373b3f3ce
8 changed files with 183 additions and 730 deletions

View File

@ -1,3 +1,21 @@
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

View File

@ -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])

View File

@ -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 \
scale.c \
fileselection.c \
entry.c \
text.c \
progress.c \
scale.c \
text.c \
tree.c \
eggtrayicon.h \
eggtrayicon.c \
notification.c \
about.c \
util.c \
util.h \
util.c
zenity.h
zenity_CPPFLAGS = \
-I$(includedir) \

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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,95 +34,65 @@
#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;
GdkPixbuf *pixbuf;
GError *error = NULL;
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;
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);
}
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;
gtk_status_icon_set_from_pixbuf (status_icon, pixbuf);
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);
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;
}
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 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
@ -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;
if (!g_ascii_strcasecmp (command, "icon")) {
icon_stock = zenity_util_stock_from_filename (value);
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);
g_free (icon_file);
icon_file = g_strdup (value);
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 (!strcmp (command, "message")) {
} else if (!g_ascii_strcasecmp (command, "message")) {
#ifdef HAVE_LIBNOTIFY
/* display a notification bubble */
if (notify_is_initted ()) {
if (!g_utf8_validate (value, -1, NULL)) {
g_warning ("Invalid UTF-8 in input!");
} else if (notify_is_initted ()) {
GError *error = NULL;
NotifyNotification *n;
GdkPixbuf *icon;
NotifyNotification *notif;
const gchar *icon = NULL;
gchar *freeme = NULL;
gchar *message;
n = notify_notification_new (g_strcompress (value), NULL, NULL,
GTK_WIDGET (tray_icon));
message = g_strcompress (value);
icon = gtk_image_get_pixbuf (GTK_IMAGE (icon_image));
if (icon_stock) {
icon = icon_stock;
} else if (icon_file) {
icon = freeme = g_filename_to_uri (icon_file, NULL, NULL);
}
notify_notification_set_icon_from_pixbuf (n, icon);
notif = notify_notification_new_with_status_icon (message, NULL /* summary */,
icon, status_icon);
g_free (message);
g_free (freeme);
notify_notification_show (n, &error);
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 if (!g_ascii_strcasecmp (command, "tooltip")) {
if (g_utf8_validate (value, -1, NULL)) {
gtk_status_icon_set_tooltip (status_icon, value);
} else {
gtk_widget_show (GTK_WIDGET (tray_icon));
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);
icon_file = g_strdup (data->window_icon);
icon_stock = zenity_util_stock_from_filename (data->window_icon);
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, "destroy",
G_CALLBACK (zenity_notification_icon_destroy_callback), data);
g_signal_connect (tray_icon, "expose_event",
G_CALLBACK (zenity_notification_icon_expose_callback), data);
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);
/* 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 ())
if (!notify_is_initted ()) {
notify_init (_("Zenity notification"));
}
#endif
gtk_widget_show_all (GTK_WIDGET (tray_icon));
if (notification_data->listen) {
zenity_notification_listen_on_stdin (data);
} else {
/* 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);
}
/* 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);
}

View File

@ -145,18 +145,32 @@ zenity_util_fill_file_buffer (GtkTextBuffer *buffer, const gchar *filename)
return TRUE;
}
GdkPixbuf *
zenity_util_pixbuf_new_from_file (GtkWidget *widget, gchar *filename)
const gchar *
zenity_util_stock_from_filename (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
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, const gchar *filename)
{
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);
}

View File

@ -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);