summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Untz <vuntz@gnome.org>2009-07-15 16:29:48 +0200
committerVincent Untz <vuntz@gnome.org>2009-07-27 12:26:48 +0200
commit1ca602c3d7163242e00f03e2af02cfc006c3ddd0 (patch)
tree6a1ead0a97cfa09c70f593795d66de05e0763476
parentaed3a2b0e714f8d475129c06e03ef1b78daa6c10 (diff)
downloadlibwnck-1ca602c3d7163242e00f03e2af02cfc006c3ddd0.tar.gz
[urgency] Add the wnck-urgency-monitor utility
This small utility monitors windows that have the urgency hint set, and displays a notification icon for each of them. It's useful for people not using the window list and who don't want to miss something happening in some window.
-rw-r--r--libwnck/Makefile.am10
-rw-r--r--libwnck/wnck-urgency-monitor.c218
2 files changed, 226 insertions, 2 deletions
diff --git a/libwnck/Makefile.am b/libwnck/Makefile.am
index 5fc6a7c..9b6e8a8 100644
--- a/libwnck/Makefile.am
+++ b/libwnck/Makefile.am
@@ -61,6 +61,9 @@ $(libwnck_1_la_OBJECTS): inlinepixbufs.h
wnckprop_SOURCES= \
wnckprop.c
+wnck_urgency_monitor_SOURCES= \
+ wnck-urgency-monitor.c
+
test_wnck_SOURCES= \
test-wnck.c
@@ -74,10 +77,10 @@ test_pager_SOURCES= \
test-pager.c
bin_PROGRAMS= \
- wnckprop
+ wnckprop \
+ wnck-urgency-monitor
noinst_PROGRAMS= \
- wnckprop \
test-pager \
test-wnck \
test-selector \
@@ -94,6 +97,9 @@ libwnck_1_la_LIBADD= \
wnckprop_LDADD= \
@LIBWNCK_LIBS@ ./$(lib_LTLIBRARIES)
+wnck_urgency_monitor_LDADD= \
+ @LIBWNCK_LIBS@ ./$(lib_LTLIBRARIES)
+
test_wnck_LDADD=@LIBWNCK_LIBS@ ./$(lib_LTLIBRARIES)
test_tasklist_LDADD=@LIBWNCK_LIBS@ ./$(lib_LTLIBRARIES)
test_selector_LDADD=@LIBWNCK_LIBS@ ./$(lib_LTLIBRARIES)
diff --git a/libwnck/wnck-urgency-monitor.c b/libwnck/wnck-urgency-monitor.c
new file mode 100644
index 0000000..da88234
--- /dev/null
+++ b/libwnck/wnck-urgency-monitor.c
@@ -0,0 +1,218 @@
+/* vim: set sw=2 et: */
+/*
+ * Copyright (C) 2009 Vincent Untz
+ *
+ * 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.
+ *
+ * Authors:
+ * Vincent Untz <vuntz@gnome.org>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include <libwnck/libwnck.h>
+
+static void
+status_icon_activated (GtkStatusIcon *icon,
+ WnckWindow *window)
+{
+ WnckWorkspace *workspace;
+ guint32 timestamp;
+
+ /* We're in an activate callback, so gtk_get_current_time() works... */
+ timestamp = gtk_get_current_event_time ();
+
+ /* FIXME: THIS IS SICK AND WRONG AND BUGGY. See the end of
+ * http://mail.gnome.org/archives/wm-spec-list/2005-July/msg00032.html
+ * There should only be *one* activate call.
+ */
+ workspace = wnck_window_get_workspace (window);
+ if (workspace)
+ wnck_workspace_activate (workspace, timestamp);
+
+ wnck_window_activate (window, timestamp);
+}
+
+static GtkStatusIcon *
+status_icon_get (WnckWindow *window)
+{
+ return g_object_get_data (G_OBJECT (window), "wnck-urgency-icon");
+}
+
+static void
+status_icon_update (WnckWindow *window)
+{
+ GtkStatusIcon *icon;
+
+ icon = status_icon_get (window);
+
+ if (icon == NULL)
+ {
+ return;
+ }
+
+ if (wnck_window_get_icon_is_fallback (window))
+ {
+ gtk_status_icon_set_from_icon_name (icon, "dialog-information");
+ }
+ else
+ {
+ gtk_status_icon_set_from_pixbuf (icon,
+ wnck_window_get_mini_icon (window));
+ }
+
+ gtk_status_icon_set_tooltip_text (icon, wnck_window_get_name (window));
+}
+
+static void
+status_icon_create (WnckWindow *window)
+{
+ GtkStatusIcon *icon;
+
+ icon = gtk_status_icon_new ();
+ g_object_set_data (G_OBJECT (window), "wnck-urgency-icon", icon);
+
+ g_signal_connect (icon, "activate",
+ G_CALLBACK (status_icon_activated), window);
+
+ status_icon_update (window);
+}
+
+static void
+status_icon_remove (WnckWindow *window)
+{
+ GtkStatusIcon *icon;
+
+ icon = status_icon_get (window);
+ if (icon != NULL)
+ {
+ gtk_status_icon_set_visible (icon, FALSE);
+ g_object_unref (icon);
+ g_object_set_data (G_OBJECT (window), "wnck-urgency-icon", NULL);
+ }
+}
+
+static void
+window_state_changed (WnckWindow *window,
+ WnckWindowState changed_mask,
+ WnckWindowState new_state,
+ gpointer data)
+{
+ GtkStatusIcon *icon;
+
+ if (!
+ (changed_mask &
+ (WNCK_WINDOW_STATE_DEMANDS_ATTENTION |
+ WNCK_WINDOW_STATE_URGENT)))
+ return;
+
+ icon = status_icon_get (window);
+
+ if (wnck_window_or_transient_needs_attention (window))
+ {
+ if (icon == NULL)
+ {
+ status_icon_create (window);
+ }
+ }
+ else
+ {
+ status_icon_remove (window);
+ }
+}
+
+static void
+window_icon_changed (WnckWindow *window,
+ gpointer data)
+{
+ status_icon_update (window);
+}
+
+static void
+window_name_changed (WnckWindow *window,
+ gpointer data)
+{
+ status_icon_update (window);
+}
+
+static void
+connect_to_window (WnckScreen *screen,
+ WnckWindow *window)
+{
+ if (wnck_window_or_transient_needs_attention (window))
+ {
+ status_icon_create (window);
+ }
+
+ g_signal_connect (window, "state_changed",
+ G_CALLBACK (window_state_changed), NULL);
+ g_signal_connect (window, "icon_changed",
+ G_CALLBACK (window_icon_changed), NULL);
+ g_signal_connect (window, "name_changed",
+ G_CALLBACK (window_name_changed), NULL);
+}
+
+static void
+disconnect_from_window (WnckScreen *screen,
+ WnckWindow *window)
+{
+ status_icon_remove (window);
+}
+
+int
+main (int argc, char **argv)
+{
+ GOptionContext *ctxt;
+ GError *error;
+ WnckScreen *screen;
+
+ ctxt = g_option_context_new (NULL);
+ g_option_context_set_summary (ctxt, "Monitor windows with the urgency hint "
+ "set, and display a notification icon "
+ "for each of them.");
+ g_option_context_add_group (ctxt, gtk_get_option_group (TRUE));
+
+ error = NULL;
+ if (!g_option_context_parse (ctxt, &argc, &argv, &error))
+ {
+ g_printerr ("Error while parsing arguments: %s\n", error->message);
+ g_option_context_free (ctxt);
+ g_error_free (error);
+ return 1;
+ }
+
+ g_option_context_free (ctxt);
+ ctxt = NULL;
+
+ gtk_init (&argc, &argv);
+
+ wnck_set_client_type (WNCK_CLIENT_TYPE_PAGER);
+
+ screen = wnck_screen_get_default ();
+ g_signal_connect (screen, "window_opened",
+ G_CALLBACK (connect_to_window), NULL);
+ g_signal_connect (screen, "window_closed",
+ G_CALLBACK (disconnect_from_window), NULL);
+
+ gtk_main ();
+
+ return 0;
+}