Home
Authors History
Donations Cats
News
News FVWM Logo
Logo Competition
Features
Features
Download
Download
Icons and Sounds
Screenshots
Desktop Screenshots Menu Screenshots
Window Decor Screenshots Vectorbuttons
Documentation
Documentation Man pages
FAQ Developer Info
Mailing Lists
Mailing Lists
Links
Links
Customize
 
 Official FVWM Home Page plain theme

FVWM - Perl library - tutorial


Perl Library Tutorial

Section: FVWM Perl library (3)
Updated: 2005-08-27
This page contents - Return to main index
 

NAME

tutorial - common techniques for writting FVWM modules  

TUTORIAL

 

What is a window manager

A window manager is a program that runs on top of the X Window System and manages windows, menus, key and mouse bindings, virtual desktops and pages, draws window decorations using defined colors or images, title-bar buttons and fonts. It may also manage such things as root background, mouse cursors, sounds, run applications and do other nice things.  

What is a module

In the unix traditions, different functionality may be implemented by separate programs to reduce a bloat. A module is an optional program that is intended to extend the window manager using a defined module protocol.

FVWM modules are spawned by the main fvwm executable. They usually listen to the window manager events, do some useful work and send back commands for execution. There are transient modules that exit immediately or shortly, and persistent modules that exit together with a window manager or when a user requests. Some modules may control windows or other modules. Some modules may supply a GUI, others may be non interactive.  

Creating a simple module

Let's create a module that shows a flash window for one second when you change pages. We will use xmessage with nifty options for our flash purposes, but you may use your fantasy to do this better.

First, we should understand when our module works. Usually a module does nothing (sleeps) and is awaken when something interesting happens. This is achieved using events. A module defines events that it is interesting to receive and set-ups event handlers (perl functions) to be called when the event happens. Then a module enters the event loop where it sleeps all the time until one or another event happens. Most of the module work is done in the event handlers. When an event is processed, the module enters the event loop again.

In our case, we should listen to an FVWM event M_NEW_PAGE. The list of all events may be found in FVWM::Constants. When we receive the event we want to get new page coordinates and display them using our special xmessage window.

Now, from theory to practice. The header of all modules written in Perl is pretty standard:

    #!/usr/bin/perl -w

    use lib `fvwm-perllib dir`;
    use FVWM::Module;

Then create the actual module object:

    my $module = new FVWM::Module(
        Mask => M_NEW_PAGE | M_NEW_DESK,
        Debug => 1,
    );

The Debug option tells to print the event names that a module receives to help writing a module, it also echoes all sent commands. The Mask option tells which events a module wants to receive, in our case these are events generated on the page and desk changes.

To handle events, event handlers that are perl functions, should be defined. It is ok not to define any event handler for M_NEW_DESK and to define two event handlers for M_NEW_PAGE. But for our purposes one M_NEW_PAGE would be more than enough:

    $module->addHandler(M_NEW_PAGE, \&gotNewPage);

It is a time to implement our "gotNewPage" function that will be called every time the desktop page is changed.

    sub gotNewPage {
        my ($module, $event) = @_;

        my $width  = $event->_vp_width;
        my $height = $event->_vp_height;

        if (!$width || !$height) {
            # this may happen when doing DeskTopSize 1x1 on page 2 2
            return;
        }
        my $page_nx = int($event->_vp_x / $width);
        my $page_ny = int($event->_vp_y / $height);

        # actually show the flash
        $module->send("Exec xmessage -name FlashWindow \
            -bg cyan -fg white -center -timeout 1 -button '' \
            -xrm '*cursorName: none' -xrm '*borderWidth: 2' \
            -xrm '*borderColor: yellow' -xrm '*Margin: 12' \
            '($page_nx, $page_ny)'");
    }

All event handlers are called with 2 parameters, a module and an event objects. The arguments of the event are described in FVWM::EventNames. Each event type has its own arguments. Our M_NEW_PAGE has 5 arguments: vp_x vp_y desk vp_width vp_height. We should do some calculations to get the page numbers from viewport coordinates.

The send method passes the command to fvwm for execution. It would be better to set-up the FlashWindow specially:

    $module->send("Style FlashWindow StaysOnTop, NoTitle, NoHandles, \
        BorderWidth 10, WindowListSkip, NeverFocus, UsePPosition");

Finally, all persistent modules should enter the event loop:

    $module->eventLoop;

The full module source that we just wrote is available at ftp://ftp.fvwm.org/pub/fvwm/devel/sources/tests/perl/module-flash . To run it execute this fvwm command:

    Module /path/to/module-flash

To kill the module, execute:

    KillModule /path/to/module-flash
 

Creating a more functional module

Let's extend our new-page-flash example above and add a way to stop our module and to define another string format. This would be possible using the following fvwm commands:

    SendToModule /path/to/module-flash stop
    SendToModule /path/to/module-flash format '[%d %d]'

To handle such commands, we should define M_STRING event handler.

    use General::Parse;
    my $format = "(%d, %d)";  # the default format

    $module->mask($module->mask | M_STRING);
    $module->addHandler(M_STRING, sub {
        my ($module, $event) = @_;
        my $line = $event->_text;
        my ($action, @args) = getTokens($line);

        if ($action eq "stop") {
            $module->terminate;
        } elsif ($action eq "format") {
            $format = $args[0];
        }
    });

Now, let convert our module to be GTK+ based and not to be dependent on xmessage.

    use lib `fvwm-perllib dir`;
    use FVWM::Module::Gtk;
    use Gtk;
    init Gtk;

    my $format = "(%d, %d)";
    my $module = new FVWM::Module::Gtk(Mask => M_NEW_PAGE);

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

        my $width  = $event->_vp_width;
        my $height = $event->_vp_height;

        if (!$width || !$height) {
            return;
        }
        my $page_nx = int($event->_vp_x / $width);
        my $page_ny = int($event->_vp_y / $height);

        # actually show the flash
        my ($w, $h) = (80, 50);
        my $string = sprintf($format, $page_nx, $page_ny);

        my $window = new Gtk::Window('toplevel');
        $window->set_title("FlashWindow");
        $window->set_border_width(5);
        $window->set_usize($w, $h);
        $window->set_uposition(($width - $w) / 2, ($height - $h) / 2);

        my $frame = new Gtk::Frame();
        $window->add($frame);
        $frame->set_shadow_type('etched_out');

        my $label = new Gtk::Label($string);
        $frame->add($label);
        $window->show_all;

        $SIG{ALRM} = sub { $window->destroy(); };
        alarm(1);
    });

    $module->eventLoop;

The full module source that we just wrote is available at ftp://ftp.fvwm.org/pub/fvwm/devel/sources/tests/perl/module-gtkflash .  

EXAMPLES

Currently see ftp://ftp.fvwm.org/pub/fvwm/devel/sources/tests/perl/ for examples.

Learning the sources of FvwmPerl, FvwmDebug, FvwmGtkDebug modules may help too.  

SEE ALSO

See FVWM::Module and FVWM::Module::Gtk for the module API.  

AUTHOR

Mikhael Goikhman <migo@homemail.com>.


 

Index

NAME
TUTORIAL
What is a window manager
What is a module
Creating a simple module
Creating a more functional module
EXAMPLES
SEE ALSO
AUTHOR

This document was created by man2html, using the manual pages.
Time: 00:51:23 GMT, August 27, 2005

Last modified on April 26, 2010