27 February 2008

Water ripple as demands_attention indicator

I came across an interesting effect for Pidgin (or anything else, really). It requires Compiz; specifically, it requires the Water Effect plugin. I'm also pretty sure it requires GNOME. It turns out compiz has a fantastic dbus interface, you can pretty much get, set or trigger anything using it (more info). You can use any language with dbus bindings, but I prefer shell scripting when I can, so I use the included dbus-send program. To trigger the water effect, the command is:

dbus-send --type=method_call --dest=org.freedesktop.compiz /org/freedesktop/compiz/water/allscreens/point org.freedesktop.compiz.activate string:'root' int32:`xwininfo -root | grep id: | awk '{ print $4 }'`


The backtick expression pulls the root window's ID, which all the compiz activation commands require. That command shows a water ripple in the middle of the screen. My goal was to make the Pidgin icon ripple when I got a new message, which I'd noticed in a youtube video once and liked. I found code that uses xwininfo to figure out the location of a gnome panel icon, and combined it with the dbus call to make the ripple effect around a panel icon:

#!/bin/bash
#WINFO=`xwininfo -root -tree | egrep ' (1[2-9]|2[0-4])x(1[2-9]|2[0-4])\+0\+0' | grep "$1" | cut -d ')' -f 2-`
#This WINFO is faster to calculate, but depends on the icon being in the top panel
WINFO=`xwininfo -root -tree -name "Top Expanded Edge Panel"| grep "$1" | cut -d ')' -f 2-`
WIW=`echo $WINFO | cut -d 'x' -f 1`
WIH=`echo $WINFO | cut -d 'x' -f 2 | cut -d '+' -f 1`
WIX=`echo $WINFO | cut -d '+' -f 4`
WIY=`echo $WINFO | cut -d '+' -f 5`
let WAX=WIX+WIW/2
let WAY=WIY+WIH/2

dbus-send --type=method_call --dest=org.freedesktop.compiz /org/freedesktop/compiz/water/allscreens/point org.freedesktop.compiz.activate string:'root' int32:`xwininfo -root | grep id: | awk '{ print $4 }'` string:'amplitude' double:.1 string:'x' int32:$WAX string:'y' int32:$WAY


All that's left is to call the script when a message comes in. The accepted way I found was to change Pidgin's sound settings, but I'd prefer to leave them the way they are. Instead, I wrote a Pidgin plugin (in Perl, because C makes me sad) that waits for the received-im-msg signal and calls the shell script:

use Purple;

%PLUGIN_INFO = (
perl_api_version => 2,
name => "Icon Ripple",
version => "2.0.0",
summary => "Shows water ripples around the Pidgin icon",
description => "Shows water ripples (powered by the Compiz Water Effect plugin) around the Pidgin icon when a message is received",
author => "Michael Mrozek <sysop073\@gmail.com>",
url => "http://pidgin.im",
load => "plugin_load"
);

sub plugin_init {return %PLUGIN_INFO;}

sub plugin_load {
my $plugin = shift;
Purple::Signal::connect(Purple::Conversations::get_handle(), "received-im-msg", $plugin, \&signal_msgin, "");
}

sub signal_msgin { #(account, sender, message, conv, flags)
system("/home/mrozekma/scripts/waterping","Pidgin");
}


This has a side-effect that some may not like of showing the ripple on every received message, not just ones when the window is demanding attention. There's probably a way to change this in the plugin, but I prefer it that way so I haven't explored it.

EDIT: I forgot that I took a screenshot of the ripple effect before I wrote this article, and never included it. It's not very good, but you can see the effect at least:

No comments: