Random colorsets for window decorations...

Recently I decided to see how I would fare with assigning random colours to my windows – I use a really simple MWM-decor with a single colour so this worked well for me [1].

In order for this to work I wrote a very simple perl module using perllib which ships with FVWM, and here it is; note that in order to use this you will need to grab Graphics::RGBManipulate from CPAN first:

#!/usr/bin/perl

# Graphics::RGBManipulate comes from CPAN.
use Graphics::RGBManipulate;
use lib `fvwm-perllib dir`;
use FVWM::Module;
use strict;

our( @baseColours, @colourMaps, %colorPairs );

sub _randomPair
{
    my $randomKey = (keys %colorPairs)[rand keys %colorPairs];
    return ($randomKey, $colorPairs{ $randomKey } );
}


my $module = new FVWM::Module(
    Mask  => M_ADD_WINDOW,
    Debug => 0,
);

$module->addHandler(M_ADD_WINDOW, sub {
        my( $self, $event ) = @_;

        my $colorsetRef = $colourMaps[ rand @colourMaps ];
        my $hilightCS = (split( /\s+/, $colorsetRef->[1]))[1];
        my $colorset  = (split( /\s+/, $colorsetRef->[0]))[1];

        $self->send( "WindowStyle HilightColorset $hilightCS, Colorset $colorset", $event->_win_id );
});

# We start here -- send all colorsets to FVWM.
foreach( @colourMaps )
{
    foreach my $colorset ( @$_ )
    {
        $module->send($colorset);
    }
}

$module->eventLoop();
$module->showMessage( "Done..." );

BEGIN {
    @baseColours = (
        "#aaccee",
        "#eebbaa",
        "#aa99ee",
        "#bb99aa",
        "#bbdd99",
        "#edcd88",
        "#ee8844",
        "#ee9988",
        "#aaeebb",
        "#888888",
    );

    # key == unfocused.  value == focused.
    %colorPairs = map {
        $_ => lc Graphics::RGBManipulate::tweak( hex => $_, saturation => 0.9 ) 
    } @baseColours;

    my $c = 0;
    for( 0.. $#baseColours )
    {
        my ($focused, $unfocused) = &_randomPair();
        my $d = $c++;
        push( @colourMaps, [qq|Colorset $d fg black, bg $focused|, 
                            qq|Colorset $c fg black, bg $unfocused|
                           ]
        );
        $c++;
    }
};

It’s simple – we tell the module to listen out for add_window events and send the windowstyle for that window based on a random sampling of the colours available. You’ll note that I already have a base set of colours to work from – this is deliberate since I wanted to pair colours together. I didn’t want any colours which clashed with one another. Basically, the darker colour is for focus, the lighter is for non-focus; you need to see it for yourselves to get the idea.

If you want to give this a go, I suggest creating a “modules” directory under $FVWM_USERDIR:

mkdir -p ~/.fvwm/modules

Save the above module to whatever name you wish. I called mine FvwmChangeColour.

And then changing your ~/.fvwm/config file such that you do two things:

  1. You actually tell FVWM about a new module path (preserving the bulitin one with “+” which means append to [2].
ModulePath +:$[FVWM_USERDIR]/modules
  1. Tell FVWM to load the module.
AddToFunc StartFunction I Module FvwmChangeColour

Here’s a screenshot of course:

edulinux.homeunix.org/~n6tadam/f … olours.png

– Thomas Adam

[1] Contrary to popular belief I do not really use the multicolour-borders patch I wrote some time ago.
[2] This is the only time you should ever need to do anything with ModulePath, incidentally.

This actually required a patch to FVWM itself to work – and one of the requisites I neglected to mention was that IndexedWindowName had to be in use for it to work effectively.

But now I’ve implemented this in the form of $[w.visiblename] and had that accepted in FVWM CVS, it’s a non-issue. The change to the perl module is:

$self->send( "Style $[w.visiblename] HilightColorset $hilightCS, Colorset $colorset", $event->_win_id );

Not using WindowStyle is a conscious decision here, since there could be other things setting WindowStyle on a window which aren’t cumulative. When one WindowStyle is destroyed, alas, they all are.

– Thomas Adam