Drawing and animating directly to the Desktop with Perl

Posted June 5th, 2009 by kaikokan

A little sidestep from my learning of the Gtk toolkit for Perl GUI programming. I was thinking it would be nice to try some 2D animation on the desktop. Not the most useful thing maybe, but I like to make my learning process as much fun as possible. That keeps me motivated and happy.

Custom windows

It took me a lot of searching on the internet before I found a reasonably easy way to do this. The point is (or seems to be, I'm not an expert) that when I want to draw something to the Desktop with Gtk2 I always need to create a window (A square shaped window). I found out it's pretty easy to set the window decoration to false which provides me with a window consisting of a background alone. What I wanted though was some kind of invisible canvas on which I can draw an animation.

window subclass

After a lot of searching I finally found a way to do this. At first I found a script which does something coming close to my intentions. I believe this script subclasses the Gtk window class and creates a custom window. I must say my level of understanding Perl and Gtk2 is not at all sufficient to fully understand this script. But it provides interesting material for future reference as it is kind a cool to create a application which has it's own specific window which doesn't look like all the other programs.

screenshot:

Get the code here:

http://www.handlewithlinux.com/downloads/code/popup

I don't remember where I found it, it was on some forum. I just hope the original author isn't bothered by me using it here, but I guess if it was top-secret he wouldn't post it on a forum.

Masking the square

It seems to me this custom window is created by using a mask which sets pixels to a transparent color, I tried to use this to make an invisible window which worked. But I could not draw anything visible on that. So the only thing I can do with this is create custom windows (nice enough, but not what I was looking for).

On screen display

So I went on searching on CPAN for some information. And I found something which serves my purpose. It's a perl module called X11::Aosd which is a perl binding to a C library for creating on screen display functionality. It requires a few Linux libraries to be installed as well as a few dependency modules, some of the dev libraries are needed to install X11::Aosd because it gets compiled at installation I believe. So those are probably only needed for installation of the package and not at runtime.

Module installation

This gave me some problems installing the module, as I'm not to experienced with the CPAN shell I had problems installing the module caused by unresolved dependencies.
At first I didn't understand that to install some packages using CPAN you need to have a compiler and make installed. Now I know that some modules are build as a combination of C and perl and they get compiled when I install them. In Debian and Ubuntu there's the build-essential package which provides all the necessary tools. If you want to install the X11::Aosd package I advice you to first install the build-essential package with your package manager. The next thing I did was read the Requirements: http://www.exit1.org/X11-Aosd/#REQUIREMENTS. The first time my install failed because I overlooked the first requirement:

libaosd

This module needs libaosd version 0.2.4 or better installed on your system.

After I installed that and the 3 dev packages by using the the package manager, as well as the required Perl modules. The install of the Aosd package went fine.

Convert Cairo examples

X11::Aosd is a libaosd binding for a Cairo powered on screen display, it says on the site. What this means is that we can draw using the Cairo graphics library and put the graphics directly on the desktop without a visible window. The fun part is we can use images and shapes and there is even a simple routine to redraw stuff. I didn't find any interesting examples though, but I quickly found out it's pretty easy to convert Cairo-perl examples to X11::Aosd examples. Which in turn provides some base for learning.

For instance I took this simple.pl file I found in :/usr/share/doc/libcairo-perl/examples

http://www.handlewithlinux.com/downloads/code/simple

And turned it in to this:

http://www.handlewithlinux.com/downloads/code/simpleAosd

Which shows the same star, only instead of turning it into a image on disk it shows it on the desktop as a transparent image.

Animate it!

So now for some animation I added a Glib control loop and removed the background box to get a truly transparent drawing area. I use the rotate function on the context to rotate the entire image on every redraw. This way it appears as an animated rotation of the 3 stars.

here's the code read the argumentation for a little more explanation:

http://www.handlewithlinux.com/downloads/code/simpleAosdAnimated

More information

There's a lot of information about Cairo at the Cairo site:

http://cairographics.org/documentation/

There are some samples which can easily be converted to Aosd.

For example:

my $xc = 128.0;
my $yc = 128.0;
my $radius = 100.0;
my $angle1 = 45.0 * (M_PI/180.0);
my $angle2 = 180.0 * (M_PI/180.0);

$cr->set_line_width (10.0);
$cr->arc ($xc, $yc, $radius, $angle1, $angle2);
$cr->stroke;

$cr->set_source_rgba (1, 0.2, 0.2, 0.6);
$cr->set_line_width (6.0);

$cr->arc ( $xc, $yc, 10.0, 0, 2*M_PI);
$cr->fill;

$cr->arc ($xc, $yc, $radius, $angle1, $angle1);
$cr->line_to ($xc, $yc);
$cr->arc ($xc, $yc, $radius, $angle2, $angle2);
$cr->line_to ($xc, $yc);
$cr->stroke;

Is the converted version of this sample:

double xc = 128.0;
double yc = 128.0;
double radius = 100.0;
double angle1 = 45.0 * (M_PI/180.0); /* angles are specified */
double angle2 = 180.0 * (M_PI/180.0); /* in radians */

cairo_set_line_width (cr, 10.0);
cairo_arc (cr, xc, yc, radius, angle1, angle2);
cairo_stroke (cr);

/* draw helping lines */
cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
cairo_set_line_width (cr, 6.0);

cairo_arc (cr, xc, yc, 10.0, 0, 2*M_PI);
cairo_fill (cr);

cairo_arc (cr, xc, yc, radius, angle1, angle1);
cairo_line_to (cr, xc, yc);
cairo_arc (cr, xc, yc, radius, angle2, angle2);
cairo_line_to (cr, xc, yc);
cairo_stroke (cr);

Let's do some scrolling text animated on top of the desktop:

http://www.handlewithlinux.com/downloads/code/simpleAosdScrollText

Have a better idea?

That's it for today, feel free to post comments or questions, it can take a while before they get published due to the time difference.

This is the sixth article in a ongoing series about learning perl GUI programming. You may be interested in the other articles too. You can find the other articles here:
1. starting perl GUI programming
2. Installing Eclipse, the Epic Perl plugin and my first Perl GUI program
3. Open Source rocks! Learning from code by debugging
4. Quick and dirty linux GUI programming
5. resources for learning Perl Graphical Programming
6. Drawing and animating directly to the Desktop with Perl
7. Dynamically-creating-gui-objects-on-demand-in-Perl


Perl and Qt

Anonymous 39 weeks 5 days 9 hours 46 min ago

Thanx for a great article!

Continue diving for these nice perls. What I would love to see you trying out Perl and Qt. The old Qt3 bindigs for perl are pretty ancient by now. Are there functional Qt4 bindings for Perl yet? I recall there being sort of half done attempts floating around. Is it possible write a simple app with those?