summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hammond <chipx86@chipx86.com>2006-06-05 00:48:56 +0000
committerChristian Hammond <chipx86@chipx86.com>2006-06-05 00:48:56 +0000
commitd986aaf233e0ccd31239e7157b8f6d0277ade469 (patch)
tree0f36147438fc3a90591dd5d2ed04e761008e5a99
parent51ecbc7a2bf0e1b191d3b8198cff750fe7c64565 (diff)
downloadlibnotify-d986aaf233e0ccd31239e7157b8f6d0277ade469.tar.gz
Patch by chpe to add support for using the new GtkStatusIcon in GTK+ 2.9.x. These functions are #ifdef'd to only be provided in supported versions of GTK. The patch also added support for GObject properties on the NotifyNotification objects. This closes ticket #60.
-rw-r--r--ChangeLog9
-rw-r--r--NEWS7
-rw-r--r--libnotify/notification.c407
-rw-r--r--libnotify/notification.h19
4 files changed, 371 insertions, 71 deletions
diff --git a/ChangeLog b/ChangeLog
index d59a7ea..11b6f82 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Sun Jun 04 17:44:27 PDT 2006 Christian Hammond <chipx86@chipx86.com>
+
+ * libnotify/notification.c:
+ * libnotify/notification.h:
+ - Patch by chpe to add support for using the new GtkStatusIcon in
+ GTK+ 2.9.x. These functions are #ifdef'd to only be provided in
+ supported versions of GTK. The patch also added support for GObject
+ properties on the NotifyNotification objects. This closes ticket #60.
+
Sun Jun 04 16:12:05 PDT 2006 Christian Hammond <chipx86@chipx86.com>
* libnotify/notify.c:
diff --git a/NEWS b/NEWS
index f4a1b7e..a2f8c6a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+version 0.4.1:
+ * Added support for attaching to a GtkStatusIcon. Patch by chpe. (Bug #60)
+ * Added GObject properties to NotifyNotification. Patch by chpe. (Bug #60)
+ * Fixed up libnotify.pc to support dependencies correctly. (Bug #58)
+ * Fixed notify_uninit() to properly set _initted to FALSE after being
+ called. (Bug #56)
+
version 0.4.0 (26-April-2006):
* Patch by M.S. to switch notify-send to use GOption instead of popt,
to add -v, --version, -h, and --hint options, and to rename
diff --git a/libnotify/notification.c b/libnotify/notification.c
index 80b386a..43e5b86 100644
--- a/libnotify/notification.c
+++ b/libnotify/notification.c
@@ -26,10 +26,23 @@
#include <libnotify/notify.h>
#include <libnotify/internal.h>
+#include <gtk/gtkversion.h>
+#if GTK_CHECK_VERSION(2, 9, 2)
+# define HAVE_STATUS_ICON
+# include <gtk/gtkstatusicon.h>
+#endif
+
#define CHECK_DBUS_VERSION(major, minor) \
(DBUS_MAJOR_VER > (major) || \
(DBUS_MAJOR_VER == (major) && DBUS_MINOR_VER >= (minor)))
+#if !defined(G_PARAM_STATIC_NAME) && !defined(G_PARAM_STATIC_NICK) && \
+ !defined(G_PARAM_STATIC_BLURB)
+# define G_PARAM_STATIC_NAME 0
+# define G_PARAM_STATIC_NICK 0
+# define G_PARAM_STATIC_BLURB 0
+#endif
+
static void notify_notification_class_init(NotifyNotificationClass *klass);
static void notify_notification_init(NotifyNotification *sp);
static void notify_notification_finalize(GObject *object);
@@ -69,8 +82,9 @@ struct _NotifyNotificationPrivate
GHashTable *hints;
GtkWidget *attached_widget;
- gint widget_old_x;
- gint widget_old_y;
+#ifdef HAVE_STATUS_ICON
+ GtkStatusIcon *status_icon;
+#endif
gboolean has_nondefault_actions;
gboolean updates_pending;
@@ -83,10 +97,38 @@ enum
LAST_SIGNAL
};
+enum
+{
+ PROP_0,
+ PROP_SUMMARY,
+ PROP_BODY,
+ PROP_ICON_NAME,
+ PROP_ATTACH_WIDGET,
+ PROP_STATUS_ICON
+};
+
+static void notify_notification_set_property(GObject *object, guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void notify_notification_get_property(GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
static guint signals[LAST_SIGNAL] = { 0 };
static GObjectClass *parent_class = NULL;
-G_DEFINE_TYPE(NotifyNotification, notify_notification, G_TYPE_OBJECT);
+G_DEFINE_TYPE(NotifyNotification, notify_notification, G_TYPE_OBJECT)
+
+static GObject *
+notify_notification_constructor(GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object = parent_class->constructor(type, n_construct_properties,
+ construct_params);
+
+ _notify_cache_add_notification(NOTIFY_NOTIFICATION(object));
+
+ return object;
+}
static void
notify_notification_class_init(NotifyNotificationClass *klass)
@@ -95,6 +137,9 @@ notify_notification_class_init(NotifyNotificationClass *klass)
parent_class = g_type_class_peek_parent(klass);
+ object_class->constructor = notify_notification_constructor;
+ object_class->get_property = notify_notification_get_property;
+ object_class->set_property = notify_notification_set_property;
object_class->finalize = notify_notification_finalize;
/* Create signals here: */
@@ -105,6 +150,157 @@ notify_notification_class_init(NotifyNotificationClass *klass)
G_STRUCT_OFFSET(NotifyNotificationClass, closed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ g_object_class_install_property
+ (object_class,
+ PROP_SUMMARY,
+ g_param_spec_string("summary",
+ "Summary",
+ "Summary",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property
+ (object_class,
+ PROP_BODY,
+ g_param_spec_string("body",
+ "Message Body",
+ "Message body",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property
+ (object_class,
+ PROP_ICON_NAME,
+ g_param_spec_string("icon-name",
+ "Icon Name",
+ "Icon name",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property
+ (object_class,
+ PROP_ATTACH_WIDGET,
+ g_param_spec_object("attach-widget",
+ "Attach Widget",
+ "Attach Widget",
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+#ifdef HAVE_STATUS_ICON
+ g_object_class_install_property
+ (object_class,
+ PROP_STATUS_ICON,
+ g_param_spec_object("status-icon",
+ "Status Icon",
+ "Status Icon",
+ GTK_TYPE_STATUS_ICON,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+#endif /* HAVE_STATUS_ICON */
+}
+
+static void
+notify_notification_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NotifyNotification *notification = NOTIFY_NOTIFICATION(object);
+ NotifyNotificationPrivate *priv = notification->priv;
+
+ switch (prop_id)
+ {
+ case PROP_SUMMARY:
+ notify_notification_update(notification, g_value_get_string(value),
+ priv->body, priv->icon_name);
+ break;
+
+ case PROP_BODY:
+ notify_notification_update(notification, priv->summary,
+ g_value_get_string(value),
+ priv->icon_name);
+ break;
+
+ case PROP_ICON_NAME:
+ notify_notification_update(notification, priv->summary,
+ priv->body, g_value_get_string(value));
+ break;
+
+ case PROP_ATTACH_WIDGET:
+ notify_notification_attach_to_widget(notification,
+ g_value_get_object(value));
+ break;
+
+#ifdef HAVE_STATUS_ICON
+ case PROP_STATUS_ICON:
+ notify_notification_attach_to_status_icon(notification,
+ g_value_get_object(value));
+ break;
+#endif
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+notify_notification_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NotifyNotification *notification = NOTIFY_NOTIFICATION(object);
+ NotifyNotificationPrivate *priv = notification->priv;
+
+ switch (prop_id)
+ {
+ case PROP_SUMMARY:
+ g_value_set_string(value, priv->summary);
+ break;
+
+ case PROP_BODY:
+ g_value_set_string(value, priv->body);
+ break;
+
+ case PROP_ICON_NAME:
+ g_value_set_string(value, priv->icon_name);
+ break;
+
+ case PROP_ATTACH_WIDGET:
+ g_value_set_object(value, priv->attached_widget);
+ break;
+
+#ifdef HAVE_STATUS_ICON
+ case PROP_STATUS_ICON:
+ g_value_set_object(value, priv->status_icon);
+ break;
+#endif
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
}
static void
@@ -165,6 +361,12 @@ notify_notification_finalize(GObject *object)
if (priv->attached_widget != NULL)
g_object_unref(G_OBJECT(priv->attached_widget));
+#if HAVE_STATUS_ICON
+ if (priv->status_icon != NULL)
+ g_object_remove_weak_pointer(G_OBJECT(priv->status_icon),
+ (gpointer)&priv->status_icon);
+#endif
+
if (priv->signals_registered)
{
dbus_g_proxy_disconnect_signal(proxy, "NotificationClosed",
@@ -180,61 +382,59 @@ notify_notification_finalize(GObject *object)
G_OBJECT_CLASS(parent_class)->finalize(object);
}
-static gboolean
+static void
_notify_notification_update_applet_hints(NotifyNotification *n)
{
NotifyNotificationPrivate *priv = n->priv;
- gboolean update_pending = FALSE;
+ GdkScreen *screen = NULL;
+ GdkRectangle rect;
+#ifdef HAVE_STATUS_ICON
+ if (priv->status_icon != NULL)
+ {
+ if (!gtk_status_icon_get_geometry(priv->status_icon, &screen,
+ &rect, NULL))
+ {
+ return;
+ }
+ }
+ else
+#endif /* HAVE_STATUS_ICON */
if (priv->attached_widget != NULL)
{
- gint x, y, h, w;
GtkWidget *widget = priv->attached_widget;
GtkRequisition requisition;
+ screen = gtk_widget_get_screen(widget);
gtk_widget_size_request(widget, &requisition);
- w = requisition.width;
- h = requisition.height;
+ rect.width = requisition.width;
+ rect.height = requisition.height;
- gdk_window_get_origin(widget->window, &x, &y);
+ gdk_window_get_origin(widget->window, &rect.x, &rect.y);
if (GTK_WIDGET_NO_WINDOW(widget))
{
- x += widget->allocation.x;
- y += widget->allocation.y;
- }
-
- x += widget->allocation.width / 2;
- y += widget->allocation.height / 2;
-
- if (x != priv->widget_old_x)
- {
- notify_notification_set_hint_int32(n, "x", x);
- priv->widget_old_x = x;
-
- update_pending = TRUE;
+ rect.x += widget->allocation.x;
+ rect.y += widget->allocation.y;
}
- if (y != priv->widget_old_y)
- {
- notify_notification_set_hint_int32(n, "y", y);
- priv->widget_old_y = y;
-
- update_pending = TRUE;
- }
+ rect.x += widget->allocation.width / 2;
+ rect.y += widget->allocation.height / 2;
}
+ else
+ return;
- return update_pending;
+ notify_notification_set_geometry_hints(n, screen, &rect);
}
#if 0
-
-/* This is left here just incase we revisit autoupdating
- One thought would be to check for updates every time the icon
- is redrawn but we still have to deal with the race conditions
- that could occure between the server and the client so we will
- leave this alone for now.
-*/
+/*
+ * This is left here just incase we revisit autoupdating
+ * One thought would be to check for updates every time the icon
+ * is redrawn but we still have to deal with the race conditions
+ * that could occure between the server and the client so we will
+ * leave this alone for now.
+ */
static gboolean
_idle_check_updates(void *user_data)
{
@@ -264,31 +464,33 @@ NotifyNotification *
notify_notification_new(const gchar *summary, const gchar *body,
const gchar *icon, GtkWidget *attach)
{
- NotifyNotification *obj;
-
- g_return_val_if_fail(summary != NULL && *summary != '\0', NULL);
g_return_val_if_fail(attach == NULL || GTK_IS_WIDGET(attach), NULL);
- obj = NOTIFY_NOTIFICATION(g_object_new(NOTIFY_TYPE_NOTIFICATION, NULL));
-
- obj->priv->summary = g_strdup(summary);
-
- if (body != NULL && *body != '\0')
- obj->priv->body = g_strdup(body);
-
- if (icon != NULL && *icon != '\0')
- obj->priv->icon_name = g_strdup(icon);
-
- if (attach != NULL)
- {
- g_object_ref(G_OBJECT(attach));
- obj->priv->attached_widget = attach;
- }
-
- _notify_cache_add_notification(obj);
+ return g_object_new(NOTIFY_TYPE_NOTIFICATION,
+ "summary", summary,
+ "body", body,
+ "icon-name", icon,
+ "attach-widget", attach,
+ NULL);
+}
- return obj;
+#ifdef HAVE_STATUS_ICON
+NotifyNotification *
+notify_notification_new_with_status_icon(const gchar *summary,
+ const gchar *message,
+ const gchar *icon,
+ GtkStatusIcon *status_icon)
+{
+ g_return_val_if_fail(status_icon == NULL || GTK_IS_STATUS_ICON(status_icon), NULL);
+
+ return g_object_new(NOTIFY_TYPE_NOTIFICATION,
+ "summary", summary,
+ "body", message,
+ "icon-name", icon,
+ "status-icon", status_icon,
+ NULL);
}
+#endif /* HAVE_STATUS_ICON */
gboolean
notify_notification_update(NotifyNotification *notification,
@@ -299,17 +501,28 @@ notify_notification_update(NotifyNotification *notification,
g_return_val_if_fail(NOTIFY_IS_NOTIFICATION(notification), FALSE);
g_return_val_if_fail(summary != NULL && *summary != '\0', FALSE);
- g_free(notification->priv->summary);
- g_free(notification->priv->body);
- g_free(notification->priv->icon_name);
-
- notification->priv->summary = g_strdup(summary);
+ if (notification->priv->summary != summary)
+ {
+ g_free(notification->priv->summary);
+ notification->priv->summary = g_strdup(summary);
+ g_object_notify(G_OBJECT(notification), "summary");
+ }
- if (body != NULL && *body != '\0')
- notification->priv->body = g_strdup(body);
+ if (notification->priv->body != body)
+ {
+ g_free(notification->priv->body);
+ notification->priv->body =
+ (body != NULL && *body != '\0' ? g_strdup(body) : NULL);
+ g_object_notify(G_OBJECT(notification), "body");
+ }
- if (icon != NULL && *icon != '\0')
- notification->priv->icon_name = g_strdup(icon);
+ if (notification->priv->icon_name != icon)
+ {
+ g_free(notification->priv->icon_name);
+ notification->priv->icon_name =
+ (icon != NULL && *icon != '\0' ? g_strdup(icon) : NULL);
+ g_object_notify(G_OBJECT(notification), "icon-name");
+ }
notification->priv->updates_pending = TRUE;
@@ -320,14 +533,70 @@ void
notify_notification_attach_to_widget(NotifyNotification *notification,
GtkWidget *attach)
{
- g_return_if_fail(notification != NULL);
g_return_if_fail(NOTIFY_IS_NOTIFICATION(notification));
+ if (notification->priv->attached_widget == attach)
+ return;
+
if (notification->priv->attached_widget != NULL)
g_object_unref(notification->priv->attached_widget);
notification->priv->attached_widget =
(attach != NULL ? g_object_ref(attach) : NULL);
+
+ g_object_notify(G_OBJECT(notification), "attach-widget");
+}
+
+#ifdef HAVE_STATUS_ICON
+void
+notify_notification_attach_to_status_icon(NotifyNotification *notification,
+ GtkStatusIcon *status_icon)
+{
+ g_return_if_fail(NOTIFY_IS_NOTIFICATION(notification));
+ g_return_if_fail(status_icon == NULL || GTK_IS_STATUS_ICON(status_icon));
+
+ if (notification->priv->status_icon == status_icon)
+ return;
+
+ if (priv->status_icon != NULL)
+ {
+ g_object_remove_weak_pointer(G_OBJECT(priv->status_icon),
+ (gpointer)&priv->status_icon);
+ }
+
+ priv->status_icon = status_icon;
+
+ if (priv->status_icon != NULL)
+ {
+ g_object_add_weak_pointer(G_OBJECT(priv->status_icon),
+ (gpointer)&priv->status_icon);
+ }
+
+ g_object_notify(G_OBJECT(notification), "attach-icon");
+}
+#endif /* HAVE_STATUS_ICON */
+
+void
+notify_notification_set_geometry_hints(NotifyNotification *notification,
+ GdkScreen *screen,
+ GdkRectangle *rect)
+{
+ char *display_name;
+
+ g_return_if_fail(notification != NULL);
+ g_return_if_fail(NOTIFY_IS_NOTIFICATION(notification));
+ g_return_if_fail(screen != NULL);
+ g_return_if_fail(GDK_IS_SCREEN(screen));
+ g_return_if_fail(rect != NULL);
+
+ notify_notification_set_hint_int32(notification, "x", rect->x);
+ notify_notification_set_hint_int32(notification, "y", rect->y);
+ notify_notification_set_hint_int32(notification, "width", rect->width);
+ notify_notification_set_hint_int32(notification, "height", rect->height);
+
+ display_name = gdk_screen_make_display_name(screen);
+ notify_notification_set_hint_string(notification, "xdisplay", display_name);
+ g_free(display_name);
}
static void
@@ -405,7 +674,7 @@ notify_notification_show(NotifyNotification *notification, GError **error)
priv->signals_registered = TRUE;
}
- /* If attached to a widget, modify x and y in hints */
+ /* If attached to a widget or status icon, modify x and y in hints */
_notify_notification_update_applet_hints(notification);
action_array = _gslist_to_string_array(priv->actions);
diff --git a/libnotify/notification.h b/libnotify/notification.h
index c7a9965..34b6976 100644
--- a/libnotify/notification.h
+++ b/libnotify/notification.h
@@ -25,6 +25,7 @@
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
+#include <gtk/gtkversion.h>
G_BEGIN_DECLS
@@ -86,6 +87,11 @@ NotifyNotification *notify_notification_new(const gchar *summary,
const gchar *message,
const gchar *icon,
GtkWidget *attach);
+#if GTK_CHECK_VERSION(2, 9, 2)
+NotifyNotification *notify_notification_new_with_status_icon(
+ const gchar *summary, const gchar *message,
+ const gchar *icon, GtkStatusIcon *status_icon);
+#endif
gboolean notify_notification_update(NotifyNotification *notification,
const gchar *summary,
@@ -95,6 +101,15 @@ gboolean notify_notification_update(NotifyNotification *notification,
void notify_notification_attach_to_widget(NotifyNotification* notification,
GtkWidget *attach);
+#if GTK_CHECK_VERSION(2, 9, 2)
+void notify_notification_attach_to_status_icon(NotifyNotification *notification,
+ GtkStatusIcon *status_icon);
+#endif
+
+void notify_notification_set_geometry_hints(NotifyNotification *notification,
+ GdkScreen *screen,
+ GdkRectangle *rect);
+
gboolean notify_notification_show(NotifyNotification *notification,
GError **error);
@@ -107,8 +122,8 @@ void notify_notification_set_category(NotifyNotification *notification,
void notify_notification_set_urgency(NotifyNotification *notification,
NotifyUrgency l);
-void notify_notification_set_icon_from_pixbuf(
- NotifyNotification *notification, GdkPixbuf *icon);
+void notify_notification_set_icon_from_pixbuf(NotifyNotification *notification,
+ GdkPixbuf *icon);
void notify_notification_set_hint_int32(NotifyNotification *notification,
const gchar *key, gint value);