changeset 14327:39bd60b73032

[gaim-migrate @ 17022] Add a new notification method, this method keeps the unseen message count in an X property (_GAIM_UNSEEN_COUNT) which allow for some nifty things. Also, some whitespace, etc. nitpicks I noticed while going over this. committer: Tailor Script <tailor@pidgin.im>
author Etan Reisner <pidgin@unreliablesource.net>
date Thu, 24 Aug 2006 20:05:56 +0000
parents f74c19f2da30
children 2ce396e60cea
files gtk/plugins/notify.c
diffstat 1 files changed, 89 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/gtk/plugins/notify.c	Thu Aug 24 19:55:43 2006 +0000
+++ b/gtk/plugins/notify.c	Thu Aug 24 20:05:56 2006 +0000
@@ -105,29 +105,36 @@
 #define NOTIFY_PLUGIN_ID "gtk-x11-notify"
 
 static GaimPlugin *my_plugin = NULL;
+static GdkAtom _Cardinal = GDK_NONE;
+static GdkAtom _GaimUnseenCount = GDK_NONE;
 
 /* notification set/unset */
 static int notify(GaimConversation *conv, gboolean increment);
 static void notify_win(GaimGtkWindow *gaimwin);
 static void unnotify(GaimConversation *conv, gboolean reset);
-static int unnotify_cb(GtkWidget *widget, gpointer data, GaimConversation *conv);
+static int unnotify_cb(GtkWidget *widget, gpointer data,
+                       GaimConversation *conv);
 
 /* gtk widget callbacks for prefs panel */
 static void type_toggle_cb(GtkWidget *widget, gpointer data);
 static void method_toggle_cb(GtkWidget *widget, gpointer data);
 static void notify_toggle_cb(GtkWidget *widget, gpointer data);
-static gboolean options_entry_cb(GtkWidget *widget, GdkEventFocus *event, gpointer data);
+static gboolean options_entry_cb(GtkWidget *widget, GdkEventFocus *event,
+                                 gpointer data);
 static void apply_method(void);
 static void apply_notify(void);
 
 /* string function */
 static void handle_string(GaimGtkWindow *gaimwin);
 
-/* count function */
-static void handle_count(GaimGtkWindow *gaimwin);
+/* count_title function */
+static void handle_count_title(GaimGtkWindow *gaimwin);
+
+/* count_xprop function */
+static void handle_count_xprop(GaimGtkWindow *gaimwin);
 
 /* urgent function */
-static void handle_urgent(GaimGtkWindow *gaimwin, gboolean add);
+static void handle_urgent(GaimGtkWindow *gaimwin, gboolean set);
 
 /* raise function */
 static void handle_raise(GaimGtkWindow *gaimwin);
@@ -135,10 +142,10 @@
 /****************************************/
 /* Begin doing stuff below this line... */
 /****************************************/
-static int
+static guint
 count_messages(GaimGtkWindow *gaimwin)
 {
-	gint count = 0;
+	guint count = 0;
 	GList *convs = NULL, *l;
 
 	for (convs = gaimwin->gtkconvs; convs != NULL; convs = convs->next) {
@@ -154,9 +161,9 @@
 static int
 notify(GaimConversation *conv, gboolean increment)
 {
-	GaimGtkWindow *gaimwin = NULL;
 	gint count;
 	gboolean has_focus;
+	GaimGtkWindow *gaimwin = NULL;
 
 	if (conv == NULL)
 		return 0;
@@ -197,7 +204,9 @@
 		return;
 
 	if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_count"))
-		handle_count(gaimwin);
+		handle_count_title(gaimwin);
+	if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_count_xprop"))
+		handle_count_xprop(gaimwin);
 	if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_string"))
 		handle_string(gaimwin);
 	if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_urgent"))
@@ -221,11 +230,15 @@
 	gaim_conversation_autoset_title(active_conv);
 
 	if (reset) {
-		/* Only need to actually remove the urgent hinting here, since removing it
-		 * just to have it readded in re-notify is an unnecessary couple extra RTs
-		 * to the server */
+		/* Only need to actually remove the urgent hinting here, since
+		 * removing it just to have it readded in re-notify is an
+		 * unnecessary couple extra RTs to the server */
 		handle_urgent(gaimwin, FALSE);
 		gaim_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
+		/* Same logic as for the urgent hint, xprops are also a RT.
+		 * This needs to go here so that it gets the updated message
+		 * count. */
+		handle_count_xprop(gaimwin);
 	}
 
 	return;
@@ -242,7 +255,7 @@
 
 static gboolean
 message_displayed_cb(GaimAccount *account, const char *who, char *message,
-				GaimConversation *conv, GaimMessageFlags flags)
+                     GaimConversation *conv, GaimMessageFlags flags)
 {
 	if ((gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT &&
 	     gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_chat_nick") &&
@@ -256,7 +269,8 @@
 }
 
 static void
-im_sent_im(GaimAccount *account, const char *receiver, const char *message) {
+im_sent_im(GaimAccount *account, const char *receiver, const char *message)
+{
 	GaimConversation *conv = NULL;
 
 	if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_send")) {
@@ -293,9 +307,9 @@
 	gtkwin  = gtkconv->win;
 
 	if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_focus")) {
-		/* TODO should really find a way to make this work no matter where the
-		 * focus is inside the conv window, without having to bind to
-		 * focus-in-event on the g(d|t)kwindow */
+		/* TODO should really find a way to make this work no matter
+		 * where the focus is inside the conv window, without having
+		 * to bind to focus-in-event on the g(d|t)kwindow */
 		/* try setting the signal on the focus-in-event for
 		 * gtkwin->notebook->container? */
 		id = g_signal_connect(G_OBJECT(gtkconv->entry), "focus-in-event",
@@ -308,8 +322,8 @@
 	}
 
 	if (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_click")) {
-		/* TODO similarly should really find a way to allow for clicking in other
-		 * places of the window */
+		/* TODO similarly should really find a way to allow for
+		 * clicking in other places of the window */
 		id = g_signal_connect(G_OBJECT(gtkconv->entry), "button-press-event",
 		                      G_CALLBACK(unnotify_cb), conv);
 		entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id));
@@ -362,10 +376,11 @@
 static void
 conv_created(GaimConversation *conv)
 {
-	gaim_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0));
+	gaim_conversation_set_data(conv, "notify-message-count",
+	                           GINT_TO_POINTER(0));
 
-	/* always attach the signals, notify() will take care of conversation type
-	 * checking */
+	/* always attach the signals, notify() will take care of conversation
+	 * type checking */
 	attach_signals(conv);
 }
 
@@ -484,7 +499,7 @@
 }
 
 static void
-handle_count(GaimGtkWindow *gaimwin)
+handle_count_title(GaimGtkWindow *gaimwin)
 {
 	GtkWindow *window;
 	char newtitle[256];
@@ -500,7 +515,34 @@
 }
 
 static void
-handle_urgent(GaimGtkWindow *win, gboolean add)
+handle_count_xprop(GaimGtkWindow *gaimwin)
+{
+#ifndef _WIN32
+	guint count;
+	GtkWidget *window;
+	GdkWindow *gdkwin;
+
+	window = gaimwin->window;
+	g_return_if_fail(window != NULL);
+
+	if (_GaimUnseenCount == GDK_NONE) {
+		_GaimUnseenCount = gdk_atom_intern("_GAIM_UNSEEN_COUNT", FALSE);
+	}
+
+	if (_Cardinal == GDK_NONE) {
+		_Cardinal = gdk_atom_intern("CARDINAL", FALSE);
+	}
+
+	count = count_messages(gaimwin);
+	gdkwin = window->window;
+
+	gdk_property_change(gdkwin, _GaimUnseenCount, _Cardinal, 32,
+	                    GDK_PROP_MODE_REPLACE, (guchar *) &count, 1);
+#endif
+}
+
+static void
+handle_urgent(GaimGtkWindow *win, gboolean set)
 {
 #ifndef _WIN32
 	XWMHints *hints;
@@ -514,7 +556,7 @@
 	if(!hints)
 		hints = XAllocWMHints();
 
-	if (add)
+	if (set)
 		hints->flags |= XUrgencyHint;
 	else
 		hints->flags &= ~XUrgencyHint;
@@ -536,7 +578,8 @@
 	gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 	gchar pref[256];
 
-	g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s", (char *)data);
+	g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s",
+	           (char *)data);
 
 	gaim_prefs_set_bool(pref, on);
 }
@@ -547,7 +590,8 @@
 	gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 	gchar pref[256];
 
-	g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s", (char *)data);
+	g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s",
+	           (char *)data);
 
 	gaim_prefs_set_bool(pref, on);
 
@@ -567,7 +611,8 @@
 	gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 	gchar pref[256];
 
-	g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s", (char *)data);
+	g_snprintf(pref, sizeof(pref), "/plugins/gtk/X11/notify/%s",
+	           (char *)data);
 
 	gaim_prefs_set_bool(pref, on);
 
@@ -581,7 +626,8 @@
 		return FALSE;
 
 	if (!strcmp(data, "method_string")) {
-		gaim_prefs_set_string("/plugins/gtk/X11/notify/title_string", gtk_entry_get_text(GTK_ENTRY(widget)));
+		gaim_prefs_set_string("/plugins/gtk/X11/notify/title_string",
+		                      gtk_entry_get_text(GTK_ENTRY(widget)));
 	}
 
 	apply_method();
@@ -590,11 +636,13 @@
 }
 
 static void
-apply_method() {
+apply_method()
+{
 	GList *convs;
 	GaimGtkWindow *gaimwin = NULL;
 
-	for (convs = gaim_get_conversations(); convs != NULL; convs = convs->next) {
+	for (convs = gaim_get_conversations(); convs != NULL;
+	     convs = convs->next) {
 		GaimConversation *conv = (GaimConversation *)convs->data;
 
 		/* remove notifications */
@@ -706,6 +754,14 @@
 	                 G_CALLBACK(method_toggle_cb), "method_count");
 
 #ifndef _WIN32
+	/* Count xprop method button */
+	toggle = gtk_check_button_new_with_mnemonic(_("Insert count of new message into _X property"));
+	gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
+	                             gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_count_xprop"));
+	g_signal_connect(G_OBJECT(toggle), "toggled",
+	                 G_CALLBACK(method_toggle_cb), "method_count_xprop");
+
 	/* Urgent method button */
 	toggle = gtk_check_button_new_with_mnemonic(_("Set window manager \"_URGENT\" hint"));
 	gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
@@ -856,8 +912,8 @@
 	N_("Provides a variety of ways of notifying you of unread messages."),
 	                                                  /**  description    */
 	N_("Provides a variety of ways of notifying you of unread messages."),
+	                                                  /**< author         */
 	"Etan Reisner <deryni@eden.rutgers.edu>\n\t\t\tBrian Tarricone <bjt23@cornell.edu>",
-	                                                  /**< author         */
 	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
@@ -885,6 +941,7 @@
 	gaim_prefs_add_string("/plugins/gtk/X11/notify/title_string", "(*)");
 	gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_urgent", FALSE);
 	gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_count", FALSE);
+	gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_count_xprop", FALSE);
 	gaim_prefs_add_bool("/plugins/gtk/X11/notify/method_raise", FALSE);
 	gaim_prefs_add_bool("/plugins/gtk/X11/notify/notify_focus", FALSE);
 	gaim_prefs_add_bool("/plugins/gtk/X11/notify/notify_click", FALSE);