OK. I’ve updated the tarball, so this might be a good time to talk about how to actually use this sucker.
What it does is combine an arbitary number of buttons into one single button that cycles through all its icons. You can set mouse actions for individual icons, and you can have variant icons based on system states such as battery power, disk usage and email status.
FvwmMonitor uses the standard fvwm module configuration method, so you can control the module operation from your fvwm config. It works by defining conditions to monitor, and states that condition may occupy. One possible condition would be NewMail which has two conditions: true and false. Another might be battery charge, with conditions 00, 10, 20, and so in through to 90 and 100. You can also define tests to determine the current state of any condition, and mouse actions to be executed when an icon is clicked
Let’s have an example. Let’s start with a simple terminal launcher. Since our launcher is always going to look the same and always do the same thing, we don’t need to define any states, just the condition.
*FvwmMonitor: Condition Terminal, Icon l33t_LOG_tux.png
*FvwmMonitor: Condition Terminal, Mouse(1) "Exec xterm -bg black -fg purple"
*FvwmMonitor: Condition Terminal, Mouse(3) "module FvwmConsole"
That gives us a a button with a tux icon [1,2] which launches a term on a left click and a console on a right click. The Mouse actions are sent to fvwm directly. That means if you have invocation funcs to manage all the args for your terms you can call them directly by writing something like this:
*FvwmMonitor: Condition Terminal, Mouse(1) InvokeAterm
*FvwmMonitor: Condition Terminal, Mouse(3) InvokeConsole
To display the icon you can launch it like any other module. However, it’s designed to be swallowed by FvwmButtons
*FvwmButtons: (Swallow "FvwmMonitor" FvwmMonitor FvwmMonitor-Main)
Right. So now we have a picture of a penguin that launches xterms. Unfortunately, that’s nothing we couldn’t have done easier with FvwmButtons. To get the full benefit of this module we need more than one condition.
Let’s add a local mail checker. We’ll create a condition called “LocalMail” with two states: “Full” and “Empty”:
*FvwmMonitor: Condition LocalMail, State(Full) "Icon l33t_MAI_envelope.png"
*FvwmMonitor: Condition LocalMail, State(Empty), "Flag trivial"
Notice that I’ve not given the Empty state an icon. That’s because I’m not interested in being told when my mailbox is empty. Instead, I’ve flagged the state as “trivial”.
There are three levels of importance: trivial, normal and critical. Normal events are not displayed if one or more conditions are in a critical state, while trivial events are not displayed at all. This means that you don’t have to watch five minutes of irrelevancies scroll past before the monitor informs you that your CPU is busy catching fire.
Having defined out two scripts, we need a way to tell the module which state applies at any given time. We do this with Test and PipeTest directives. Let’s assume you’ve got a checker script called “checkmail” and that when run it prints either “Full” or "Empty: We can then write:
*FvwmMonitor: Condition LocalMail, PipeTest "checkmail"
This tells FvwmMonitor to run checkmail as a shell command every so often (10 seconds by default) and select a state based upon the output of the command. If you speak Perl, you can use “Test” instead of “PipeTest” and code the test directly in that language. This has the advantage, like torsmo or gkrellm, of executing in the same process and avoidig the overhead of starting and stopping a monitor script.
We also need to tell the module which output goes with which state, We do that with the Value keyword.
*FvwmMonitor: Condition LocalMail, State(Full) "Value Full"
*FvwmMonitor: Condition LocalMail, State(Empty) "Value Empty"
(Having the values default to the state names is a useful default I’ve just this minute thought of - expect it in the next release)
Of course, if the script returns something else the module won’t know what to display. We can add a default icon to the module to take care of this:
*FvwmMonitor: Icon l33t_DES_skull.png
Which displays a skull and crossbones if something goes wrong.
Finally, let’s add a mouse action to the Full state:
*FvwmMonitor: Condition LocalMail, State(Full) "Mouse(1) 'exec sylpheed'"
Right. If all goes well you should have a penguin icon that launches terms and consoles, unless you have mail in which case it splits its time between the penguin launcher and an email icon which launches a mail reader. Read your mail and it’s a full time terminal launcher again.
Let’s do a couple more. I get my mail over a POP3 connection from my ISP. I like to fetch it manually so I can delete the *$#% spam on the server. So I wrote a button to tell me if there was POP3 mail awaiting:
*FvwmMonitor: Condition Demon, SleepTime 300,
*FvwmMonitor: Condition Demon, Flag trivial
*FvwmMonitor: Condition Demon, State(Empty) "Value 0"
*FvwmMonitor: Condition Demon, State(Full) "Flag Normal, Value 1"
*FvwmMonitor: Condition Demon, State(Full) "Icon l33t_LOG_bsddevil.png"
*FvwmMonitor: Condition Demon, Mouse(1) "exec myat green mailer thead -m"
*FvwmMonitor: Condition Demon, Mouse(3) "*Test"
I’ve set the time to sleep between checks to 300 seconds so my ISP don’t think I’m DOSing them; I’ve used the BSD devil for a mail icon because I couldn’t find a demon internet one that’d fit inside a bubble and still look good, and I’m calling “thead”, my home grown spam filter, and telling it to launch a mail reader when its done - if there’s anything left to read.
One problem with a five minute sleep time is that, after you’ve read your email, it takes forever for the “mail waiting” icon go away. Hence the Mouse 3 action. Actions prefixed by a “*” are interpretted by the module rather than by FVWM. *Test means “perform the test for this action immediately”. So after I read my mail, if it still thinks there’s mail waiting I can right click on it and get it to update itself. This really needs a better solution, but this’ll do for the time being.
For the test, I thought I’d inline the perl code to show how that works. You don’t need perl, remember. If you can code it in bash, it should work using PipeTest. For those who can use perl however…
*FvwmMonitor: Condition Demon, Test " \
use Net::POP3; \
my $pop = Net::POP3->new('pop3.demon.co.uk'); \
my $rc = $pop->login( \
$ENV{ POP3_USER }, \
$ENV{ POP3_PASS } \
); \
return ($rc == 0 ? 0 : 1);"
The final condition I have on my desktop is a battery level monitor. All the conditions defined so far have been binary ones. For battery level I want 10% chunks from 100% to 00%. I knocked up some icons for the states:
…
You get the idea.
Now I need to define a condition:
*FvwmMonitor: Condition Battery, Flag normal
*FvwmMonitor: Condition Battery, SleepTime 30
And some states for that condition:
*FvwmMonitor: Condition Battery, State(00) "Value 0, Icon battery_00.png, Flag critical"
*FvwmMonitor: Condition Battery, State(10) "Value 1, Icon battery_10.png, Flag critical"
*FvwmMonitor: Condition Battery, State(20) "Value 2, Icon battery_20.png, Flag critical"
*FvwmMonitor: Condition Battery, State(30) "Value 3, Icon battery_30.png"
*FvwmMonitor: Condition Battery, State(40) "Value 4, Icon battery_40.png"
*FvwmMonitor: Condition Battery, State(50) "Value 5, Icon battery_50.png"
*FvwmMonitor: Condition Battery, State(60) "Value 6, Icon battery_60.png"
*FvwmMonitor: Condition Battery, State(70) "Value 7, Icon battery_70.png"
*FvwmMonitor: Condition Battery, State(80) "Value 8, Icon battery_80.png, Flag trivial"
*FvwmMonitor: Condition Battery, State(90) "Value 9, Icon battery_90.png, Flag trivial"
*FvwmMonitor: Condition Battery, State(100) "Value 10, Icon battery_100.png, Flag trivial"
So I’m not interested in seeing the power level if it’s 80% or higher, while if it’s less than 30% I don’t want to see anything else.
The test, at least in my config, is another swatch of perl returning a value in the range 0 to 10. I could just as easily done it using a bash script. If anyone’s interested in the perl, it’s in the example on the man page.
I also have another monitor icon in my config. This one defines a bunch of conditions, but no states. As such it cycles through a number of launchers, and duplicates the functionality of the MultiButton script I used in config-from-scratch. Except that this one doesn’t need an external script to drive it, and you get to configure which apps and icons it uses from inside your config file which is how things ought to be.
However, since I’ve rabbited on enough for one session, I’ll leave configuring that as an exercise for the interested student
[1] Except as noted, all icons are taken from the gentoo icon set.
[2] It used to be a terminal icon, but I got bored with it.