Restructure how we look for Read files slightly.
[fvwm.git] / perllib / FVWM / Module.pm.in
blobeffd5aed02c7301cdc984237f82e5f54872e8ebf
1 # Copyright (c) 2003-2009 Mikhael Goikhman
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 package FVWM::Module;
19 use 5.004;
20 use strict;
21 use IO::File;
23 BEGIN {
24 use vars qw($prefix $datarootdir $datadir);
25 $prefix = "@prefix@";
26 $datarootdir = "@datarootdir@";
27 $datadir = "@datadir@";
30 use lib "@FVWM_PERLLIBDIR@";
31 use vars qw($VERSION @ISA @EXPORT $AUTOLOAD);
33 use FVWM::Constants;
34 use FVWM::Event;
36 use Exporter;
37 @EXPORT = @FVWM::Constants::EXPORT;
38 @ISA = qw(Exporter);
40 # The major version part indicates major API changes
41 $VERSION = '2.0';
43 # Set the fvwm search directories (used for non fully qualified file names)
44 $General::FileSystem::SAVE_FILE_DIR = $General::FileSystem::SAVE_FILE_DIR ||
45 __PACKAGE__->user_data_dir();
46 $General::FileSystem::LOAD_FILE_DIRS = $General::FileSystem::LOAD_FILE_DIRS ||
47 [ __PACKAGE__->search_dirs() ];
49 sub internal_die ($$) {
50 my $self = shift;
51 my $msg = shift;
52 $msg =~ s/([^\.!?])$/$1./;
53 die $self->name . ": $msg Exiting.\n";
56 sub show_error ($$) {
57 my $self = shift;
58 my $msg = shift;
59 print STDERR $self->name . ": $msg\n";
62 sub show_message ($$) {
63 my $self = shift;
64 my $msg = shift;
65 print STDERR "[" . $self->name . "]: $msg\n";
68 sub show_debug ($$) {
69 my $self = shift;
70 my $msg = shift;
71 print STDERR "[" . $self->name . "]: $msg\n";
74 sub debug ($$;$) {
75 my $self = shift;
76 my $msg = shift;
77 my $level = shift;
78 $level = 1 unless defined $level;
79 my $debug_level = $self->{debug};
80 $debug_level = $ENV{FVWM_MODULE_DEBUG} if exists $ENV{FVWM_MODULE_DEBUG};
81 return if $debug_level < $level;
82 $msg =~ s/\n$//s;
83 $self->show_debug($msg);
86 sub is_event_extended ($$) {
87 my $self = shift;
88 my $type = shift;
89 return $type & M_EXTENDED_MSG ? 1 : 0;
92 sub new ($@) {
93 my $class = shift;
94 my %params = @_;
95 my $self = {};
97 my $name = $0; $name =~ s|.*/||;
98 $name = $params{'Name'} || $name;
99 my $mask = $params{'Mask'};
100 my $xmask = $params{'XMask'};
101 my $sync_mask = $params{'SyncMask'};
102 my $sync_xmask = $params{'SyncXMask'};
104 # initialize module from argv
105 my ($out_fd, $in_fd, $rc_file, $win_id, $context);
106 if (@ARGV >= 5 && $ARGV[0] =~ /^\d+$/ && $ARGV[1] =~ /^\d+$/) {
107 $self->{is_dummy} = 0;
108 ($out_fd, $in_fd, $rc_file, $win_id, $context) = splice(@ARGV, 0, 5);
109 } else {
110 warn "$name should be spawned by fvwm normally.\n";
111 warn "Activating a dummy command line mode for 30 minutes (no events).\n";
112 warn "----------------------------------------------------------------\n";
113 open(DUMMYOUT, '| cat >/dev/null');
114 open(DUMMYIN, 'sleep 1800 |');
115 $self->{is_dummy} = 1;
116 ($out_fd, $in_fd) = (fileno(DUMMYOUT), fileno(DUMMYIN));
117 ($rc_file, $win_id, $context) = ("none", 0, 0);
120 if (@ARGV && $params{'EnableAlias'} && $ARGV[0] =~ /^\w[\w\d\.\/-]*/) {
121 $name = shift @ARGV;
123 if (@ARGV && ref($params{'EnableOptions'}) eq 'HASH') {
124 # save time by lazy loading Getopt::Long only if needed
125 eval "use Getopt::Long;"; die "$name: $@" if $@;
126 GetOptions(%{$params{'EnableOptions'}})
127 or die "$name: Incorrect options given.\n";
129 my @argv = @ARGV;
131 $self->{rc_file} = $rc_file;
132 $self->{win_id} = hex $win_id;
133 $self->{context} = $context;
134 $self->{argv} = [@argv];
136 # a module may need this
137 autoflush STDOUT;
138 autoflush STDERR;
140 $self->{ostream} = new IO::File ">&$out_fd"
141 or die "$name: Can't write to file descriptor (&$out_fd)\n";
142 $self->{istream} = new IO::File "<&$in_fd"
143 or die "$name: Can't read from file descriptor (&$in_fd)\n";
144 $self->{ostream}->autoflush(1);
145 $self->{istream}->autoflush(1);
147 $self->{disconnected} = 0;
148 $self->{debug} = $params{'Debug'} || 0;
149 $self->{debug} = ${$self->{debug}} if ref($self->{debug}) eq 'SCALAR';
150 $self->{last_packet} = [];
151 $self->{handlers} = {};
152 $self->{should_send_unlock} = 0;
153 $self->{should_send_ready} = 1;
154 $self->{add_mask} = 0;
155 $self->{add_xmask} = 0;
156 $self->{mask_was_set} = defined $mask;
157 $self->{xmask_was_set} = defined $xmask;
159 $self->{held_command_args} = [];
160 $self->{synthetic_events} = [];
161 $self->{used_tracker_classes} = {};
162 $self->{trackers} = {};
164 # bless here, so die above does not run DESTROY
165 bless $self, $class;
166 $self->name($name);
167 $self->mask($mask || 0, $self->{mask_was_set});
168 $self->xmask($xmask, $self->{xmask_was_set}) if $xmask;
169 $self->sync_mask($sync_mask || 0);
170 $self->sync_xmask($sync_xmask) if $sync_xmask;
171 $self->reset_handlers;
172 return $self;
175 sub disconnect ($) {
176 my $self = shift;
178 # do nonrecoverable things, but do them only once
179 return if $self->{disconnected};
181 $self->{disconnected} = 1;
182 $self->invoke_handler(new FVWM::Event(ON_EXIT));
184 if (defined $self->{ostream} && $self->{ostream}->opened) {
185 # TODO: should wait until fvwm actually gets it
186 $self->send("Nop", 0, 0);
187 close $self->{ostream};
189 if (defined $self->{istream} && $self->{istream}->opened) {
190 close $self->{istream};
194 sub DESTROY ($) {
195 my $self = shift;
196 $self->disconnect;
199 sub is_dummy ($) {
200 my $self = shift;
201 return $self->{is_dummy};
204 sub name ($;$) {
205 my $self = shift;
206 my $name = shift;
207 $self->{name} = $name if defined $name;
208 return $self->{name};
211 sub mask ($;$$) {
212 my $self = shift;
213 my $mask = shift;
214 my $explicit = shift;
215 $explicit = 1 unless defined $explicit;
217 if (defined $mask) {
218 $self->internal_die("mask() can't get extended mask, use xmask()")
219 if $self->is_event_extended($mask);
220 my $old_mask = $self->{mask};
221 $self->send_mask($mask, $self->{add_mask})
222 unless defined $old_mask && $old_mask == $mask;
223 $self->{mask} = $mask;
224 $self->{mask_was_set} = $explicit;
225 return $old_mask;
227 return $self->{mask} || 0;
230 sub xmask ($;$$) {
231 my $self = shift;
232 my $mask = shift;
233 my $explicit = shift;
234 $explicit = 1 unless defined $explicit;
236 if (defined $mask) {
237 $mask &= ~M_EXTENDED_MSG;
238 my $old_mask = $self->{xmask};
239 $self->send_mask($mask | M_EXTENDED_MSG, $self->{add_xmask})
240 unless defined $old_mask && $old_mask == $mask;
241 $self->{xmask} = $mask;
242 $self->{xmask_was_set} = $explicit;
243 return $old_mask;
245 return $self->{xmask} || 0;
248 sub is_in_mask ($$) {
249 my $self = shift;
250 my $type = shift;
251 my $mask = ($type & M_EXTENDED_MSG) ? $self->{xmask} : $self->{mask};
252 return $type & ($mask || 0);
255 sub sync_mask ($;$) {
256 my $self = shift;
257 my $mask = shift;
258 if (defined $mask) {
259 $self->internal_die("sync_mask() can't get extended mask, use sync_xmask()")
260 if $self->is_event_extended($mask);
261 my $old_mask = $self->{sync_mask};
262 $self->send("SET_SYNC_MASK $mask")
263 unless defined $old_mask && $old_mask == $mask;
264 $self->{sync_mask} = $mask;
265 return $old_mask;
267 return $self->{sync_mask} || 0;
270 sub sync_xmask ($;$) {
271 my $self = shift;
272 my $mask = shift;
273 if (defined $mask) {
274 $mask &= ~M_EXTENDED_MSG;
275 my $old_mask = $self->{sync_xmask};
276 $self->send("SET_SYNC_MASK " . ($mask | M_EXTENDED_MSG))
277 unless defined $old_mask && $old_mask == $mask;
278 $self->{sync_xmask} = $mask;
279 return $old_mask;
281 return $self->{sync_xmask} || 0;
284 sub is_in_sync_mask ($$) {
285 my $self = shift;
286 my $type = shift;
287 my $mask = ($type & M_EXTENDED_MSG) ? $self->{sync_xmask} : $self->{sync_mask};
288 return $type & ($mask || 0);
291 # by default the version of a module is the fvwm version
292 sub version ($) {
293 my $self = shift;
294 return "@VERSION@";
297 sub version_info ($) {
298 my $self = shift;
299 return "@VERSIONINFO@";
302 sub argv ($) {
303 my $self = shift;
304 return @{$self->{argv}};
307 sub reset_handlers ($) {
308 my $self = shift;
310 $self->{handlers}->{regular} = {};
311 $self->{handlers}->{extended} = {};
312 $self->{handlers}->{special} = {};
315 sub get_handler_category ($$) {
316 my $self = shift;
317 my $type = shift;
318 return "special" if $type =~ /e/i;
319 return "extended" if $self->is_event_extended($type);
320 return "regular";
323 sub postpone_send ($@) {
324 my $self = shift;
325 push @{$self->{held_command_args}}, [ @_ ];
328 # params: text, [win_id], [continue=0/1]
329 sub send ($$;$$) {
330 my $self = shift;
331 my $text = shift;
332 my $win_id = shift || 0;
333 my $continue = shift;
334 $continue = 1 unless defined $continue;
336 $self->internal_die("send requires at least text param")
337 unless defined $text;
339 my @lines = split(/\n/s, $text);
341 my $last_line = "";
342 for my $line (@lines) {
343 # support continuation lines
344 $line = "$last_line$line" if $last_line ne "";
345 if ($line =~ /^(.*)\\$/) {
346 $last_line = $1;
347 next;
348 } else {
349 $last_line = "";
351 next if $line =~ /^\s*$/;
353 unless ($self->{ostream}->opened) {
354 $self->debug("Closed send [$line]\n", 1);
355 next;
357 $self->debug("sent [$line]" . (!$continue && " FINISH"), 2);
358 my $len = length $line;
359 local $SIG{PIPE} = sub {
360 $self->debug("Failed send [$line]\n", 1);
362 $self->{ostream}->print(
363 pack("l!l!a${len}l!", $win_id, $len, $line, $continue)
366 return $self;
369 sub send_ready ($) {
370 my $self = shift;
371 $self->send(RESPONSE_READY) if $self->{should_send_ready};
372 $self->{should_send_ready} = 0;
373 return $self;
376 sub send_unlock ($) {
377 my $self = shift;
378 $self->send(RESPONSE_UNLOCK) if $self->{should_send_unlock};
379 $self->{should_send_unlock} = 0;
380 return $self;
383 sub send_mask ($$;$) {
384 my $self = shift;
385 my $mask = shift;
386 my $add_mask = shift || 0;
388 $self->send("SET_MASK " . ($mask | $add_mask));
391 sub request_reply ($$) {
392 my $self = shift;
393 my $text = shift;
394 my $win_id = shift;
396 $self->send("Send_Reply $text", $win_id);
399 sub terminate ($;$) {
400 my $self = shift;
401 my $continue = shift || 0;
402 die "!quit" if !$continue;
403 die "!next";
406 sub wait_packet ($) {
409 sub read_packet ($) {
410 my $self = shift;
412 goto RETURN_PACKET if @{$self->{synthetic_events}};
414 $self->{last_packet} = [];
416 my $header = "";
417 my $packet = "";
419 $self->wait_packet;
421 # read a packet's header first, sizeof(int) * HEADER_SIZE bytes long
422 my $got;
423 # With perl-5.8.0+, $SIG{ALRM} causes sysread to exit with "Illegal seek",
424 # so loop around sysread. I am not sure this is safe.
425 do {
426 $got = sysread($self->{istream}, $header, INTSIZE * HEADER_SIZE);
427 } until (defined $got);
429 if ($got != (INTSIZE * HEADER_SIZE)) {
430 # module killed or other read error
431 $self->debug($got ? "read packet error" : "connection closed", 3);
432 return undef;
435 my ($magic, $type, $len, $timestamp) =
436 unpack(sprintf("L!%d", HEADER_SIZE), $header);
437 $self->internal_die("Bad magic number $magic in packet")
438 unless $magic == START_FLAG;
440 # $type should not be anything other than a 32-bit number
441 # however, extended messages are padded with set bits on 64-bit systems
442 $type &= 0xffffffff;
444 # $len is number of words in packet, including header;
445 # we need this as number of bytes.
446 $len -= HEADER_SIZE;
447 $len *= INTSIZE;
449 if ($len > 0) {
450 my $off = 0;
451 while ($off < $len) {
452 $got = sysread($self->{istream}, $packet, $len, $off);
453 if (!defined $got) {
454 $self->internal_die("sysread error: $!");
456 $off += $got;
458 $self->internal_die("Got packet len $off while expecting $len")
459 if $off != $len;
462 RETURN_PACKET:
463 ($type, $packet) = @{shift @{$self->{synthetic_events}}}
464 if @{$self->{synthetic_events}};
465 $self->{last_packet} = [$type, $packet];
466 return ($type, $packet);
469 sub invoke_handler ($$) {
470 my $self = shift;
471 my $event = shift;
472 my $type = $event->type;
474 my $category = $self->get_handler_category($type);
475 my @masks = sort { $a <=> $b } keys %{$self->{handlers}->{$category}};
476 foreach my $mask (@masks) {
477 if ($type eq $mask || $type & $mask) {
478 foreach my $handler (@{$self->{handlers}->{$category}->{$mask}}) {
479 last unless $event->propagation_allowed;
480 next unless defined $handler; # skip deleted ones
482 eval { &$handler($self, $event); };
484 if ($@) {
485 return 0 if $@ =~ /^!quit/i;
486 return 1 if $@ =~ /^!next/i;
487 die $@;
492 return 1;
495 sub process_packet ($;$$) {
496 my $self = shift;
497 my ($type, $packet) = @_;
499 ($type, $packet) = @{$self->{last_packet}} unless defined $packet;
500 return undef unless defined $packet;
502 my $event = eval { new FVWM::Event($type, $packet); };
503 $self->internal_die($@ || "Internal error") unless defined $event;
505 if ($self->{debug}) {
506 my $msg = "got " . $event->name;
507 $msg .= " [" . $event->arg_values->[-1] . "]"
508 if @{$event->arg_types} && $event->arg_types->[-1] == FVWM::EventNames::string();
509 $self->debug($msg, 2);
512 $self->{should_send_unlock} = 1 if $self->is_in_sync_mask($type);
514 my $continue = $self->invoke_handler($event);
516 $self->send_unlock if $self->{should_send_unlock};
517 return $continue;
520 sub emulate_event ($$$) {
521 my $self = shift;
522 my ($type, $packet) = @_;
524 if ($self->{is_in_event_loop}) {
525 $self->invoke_handler(new FVWM::Event($type, $packet));
526 return;
529 push @{$self->{synthetic_events}}, [$type, $packet];
532 sub event_loop_prepared ($@) {
533 my $self = shift;
534 my $tracking = shift() ? 1 : 0;
536 if (!$self->{is_in_event_loop}) {
537 $self->send_ready unless $tracking;
538 $self->debug("entered event loop", 3 + $tracking);
539 $self->{is_in_event_loop} = 1;
542 # update module masks to handle trackers if needed
543 my $add_mask = 0;
544 my $add_xmask = 0;
545 foreach (values %{$self->{trackers}}) {
546 my ($mask, $xmask) = $_->masks;
547 $add_mask |= $mask;
548 $add_xmask |= $xmask;
550 $self->send_mask($self->mask, $self->{add_mask} = $add_mask)
551 if $add_mask != $self->{add_mask};
552 $self->send_mask($self->xmask | M_EXTENDED_MSG, $self->{add_xmask} = $add_xmask)
553 if $add_xmask != $self->{add_xmask};
555 # execute postponed commands if any
556 $self->send(@{shift @{$self->{held_command_args}}})
557 while @{$self->{held_command_args}};
559 # fire emulated events if any
560 $self->process_packet(@{shift @{$self->{synthetic_events}}})
561 while !$tracking && @{$self->{synthetic_events}};
564 sub event_loop_finished ($@) {
565 my $self = shift;
566 my $tracking = shift() ? 1 : 0;
568 $self->debug("exited event loop", 3 + $tracking);
570 unless ($tracking) {
571 foreach my $tracker (values %{$self->{trackers}}) {
572 $tracker->to_be_disconnected;
574 $self->disconnect;
577 $self->{is_in_event_loop} = 0;
580 sub event_loop ($@) {
581 my $self = shift;
583 while (1) {
584 $self->event_loop_prepared(@_);
586 # catch exceptions during read, for example from alarm() handler,
587 # but don't catch errors (or die) in event handlers
588 $self->process_packet(eval { $self->read_packet }) || last;
590 $self->event_loop_finished(@_);
593 sub track ($$;$@) {
594 my $self = shift;
595 my $params = ref($_[0]) eq 'HASH' ? shift() : {};
596 my $tracker_type = shift;
598 my $tracker_class = $tracker_type =~ /::/
599 ? $tracker_type : "FVWM::Tracker::$tracker_type";
600 # load a tracker class if not yet
601 unless (defined $self->{used_tracker_classes}->{$tracker_class}) {
602 eval "use $tracker_class;"; die $@ if $@;
603 $self->{used_tracker_classes}->{$tracker_class} = 1;
606 my $tracker = !$params->{NoReuse} && $self->{trackers}->{$tracker_type}
607 || $tracker_class->new($self, @_);
608 if ($params->{NoReuse}) {
609 $tracker_type .= "+" while exists $self->{trackers}->{$tracker_type};
611 $self->{trackers}->{$tracker_type} = $tracker;
612 $tracker->start unless $params->{NoStart};
613 return $tracker;
616 sub add_handler ($$$;$) {
617 my $self = shift;
618 my $type = shift;
619 my $handler = shift;
620 my $is_tracking = shift || 0;
622 $self->internal_die("add_handler: no handler type") unless defined $type;
623 $self->internal_die("add_handler: no handler code") unless ref($handler) eq 'CODE';
625 my $category = $self->get_handler_category($type);
626 $self->{handlers}->{$category}->{$type} = []
627 unless exists $self->{handlers}->{$category}->{$type};
628 push @{$self->{handlers}->{$category}->{$type}}, $handler;
629 my $index = @{$self->{handlers}->{$category}->{$type}} - 1;
631 unless ($is_tracking) {
632 $self->mask($self->mask | $type, 0)
633 if !$self->{mask_was_set} && $category eq "regular";
634 $self->xmask($self->xmask | $type, 0)
635 if !$self->{xmask_was_set} && $category eq "extended";
638 return [$type, $index];
641 sub delete_handler ($$) {
642 my $self = shift;
643 my $id = shift;
645 return 0 unless ref($id) eq 'ARRAY' && @$id == 2;
646 my ($type, $index) = @$id;
647 my $category = $self->get_handler_category($type);
648 return 0 unless defined $self->{handlers}->{$category}->{$type}->[$index];
650 $self->{handlers}->{$category}->{$type}->[$index] = undef;
651 return 1;
654 sub add_default_error_handler ($) {
655 my $self = shift;
657 $self->add_handler(M_ERROR, sub {
658 my ($self, $type, @args) = @_;
659 my $error = $args[3];
660 print STDERR "[", $self->name, "]: got fvwm error: $error\n";
661 #$self->terminate;
665 sub user_data_dir ($) {
666 return $ENV{FVWM_USERDIR} || (($ENV{HOME} || "") . "/.fvwm");
669 sub site_data_dir ($) {
670 return "@FVWM_DATADIR@";
673 sub search_dirs ($) {
674 my $this = shift;
675 return ($this->user_data_dir, $this->site_data_dir);
678 # support old API, like addHandler, dispatch to add_handler
679 sub AUTOLOAD ($;@) {
680 my $self = shift;
681 my @params = @_;
683 my $autoload_method = $AUTOLOAD;
684 my $method = $autoload_method;
686 # remove the package name
687 $method =~ s/.*://g;
689 $method =~ s/XMask/Xmask/;
690 $method =~ s/([a-z])([A-Z])/${1}_\L$2/g;
692 die "No method $method in $self as guessed from $autoload_method"
693 unless $self->can($method);
695 $self->$method(@params);
700 __END__
702 =head1 NAME
704 FVWM::Module - the base class representing fvwm module
706 =head1 SYNOPSIS
708 use lib `fvwm-perllib dir`;
709 use FVWM::Module;
711 my $module = new FVWM::Module;
713 $module->send("Beep");
715 # auto-raise all windows
716 sub auto_raise { $_[0]->send("Raise", $_[1]->_win_id) };
717 $module->add_handler(M_FOCUS_CHANGE, \&auto_raise);
719 # terminate itself after 5 minutes
720 my $scheduler = $module->track('Scheduler');
721 $scheduler->schedule(5 * 60, sub { $module->terminate; });
723 # print the current desk number ($page_tracker is auto updated)
724 my $page_tracker = $module->track("PageInfo");
725 $module->show_message("Desk: " . $page_tracker->data->{desk_n});
727 $module->event_loop;
729 =head1 DESCRIPTION
731 An fvwm module is a separate program that communicates with the main I<fvwm>
732 process, receives a module configuration and events and sends commands back.
733 This class B<FVWM::Module> makes it easy to create fvwm modules in Perl.
735 If you are interested in all module protocol details that this class tries
736 to make invisible, visit the web page
737 I<http://fvwm.org/documentation/dev_modules.php>.
738 You will need an information about packet arguments anyway to be able to
739 write complex modules. This is however not obligatory for simple modules
740 that only send commands back when something happens.
742 A typical fvwm module has an initialization part including setting event
743 handlers using B<add_handler> methods and entering an event loop using
744 B<event_loop> method. Most of the work is done in the event handlers although
745 a module may define other execution ways, for example using C<$SIG{ALRM}>.
747 An fvwm module receives 3 values from I<fvwm>: I<rc_file> - the file this
748 module was called from or "none" if the module is called as a command from
749 another module or from a binding/function (this value is not really useful),
750 I<win_id> - the window context of this module if it is called from window
751 decoration bindings or window menu (the value is integer, 0 if there is no
752 window context), and finally I<context> that indicates the place this module
753 was called from, like menu or window title (see the fvwm documentation).
754 All these values may be accessed as properties of the module object,
755 like C<$module-E<gt>{win_id}>.
757 =head1 METHODS
759 The following methods are available:
761 B<new>,
762 B<version>,
763 B<version_info>,
764 B<argv>,
765 B<send>,
766 B<track>,
767 B<event_loop>,
768 B<send_ready>,
769 B<send_unlock>,
770 B<request_reply>,
771 B<postpone_send>,
772 B<terminate>,
773 B<reset_handlers>,
774 B<add_handler>,
775 B<delete_handler>,
776 B<add_default_error_handler>,
777 B<debug>,
778 B<show_error>,
779 B<show_message>,
780 B<show_debug>,
781 B<is_dummy>.
783 The following methods are called from other methods above, but may be useful
784 in other situations as well:
786 B<internal_die>,
787 B<name>,
788 B<mask>,
789 B<xmask>,
790 B<is_in_mask>,
791 B<sync_mask>,
792 B<sync_xmask>,
793 B<is_in_sync_mask>,
794 B<disconnect>,
795 B<get_handler_category>,
796 B<read_packet>,
797 B<invoke_handler>,
798 B<process_packet>,
799 B<emulate_event>.
801 These methods deal with a received packet (event):
803 B<is_event_extended>
805 These methods deal with configuration directories:
807 B<user_data_dir>,
808 B<site_data_dir>,
809 B<search_dirs>
811 =over 4
813 =item B<new> I<param-hash>
815 Creates a module object. Only one module instance may be created in the
816 program, since this object gets exclusive rights on communication with I<fvwm>.
818 The following parameters may be given in the constractor:
820 Name - used in module configuration and debugging
821 Mask - events a module is interested to receive
822 XMask - the same for extended events
823 SyncMask - events to lock on
824 SyncXMask - the same for extended events
825 EnableAlias - whether a module accepts an alias in command line
826 EnableOptions - options that a module accepts in command line
827 Debug - 0 means no debug, 1 - user debug, 2,3,4 - perllib
829 Example:
831 my $module = new FVWM::Module(
832 Name => "FvwmPerlBasedWindowRearranger",
833 Mask => M_CONFIGURE_WINDOW | M_END_WINDOWLIST,
834 EnableOptions => { "animate" => \$a, "cascade" => \$c },
835 Debug => 2,
838 Event types needed for the 4 mask parameters are defined in B<FVWM::Constants>.
840 Set I<Debug> to 2 to nicely dump all communication with fvwm (sent commands
841 and received events). Setting it to 3 makes it even more verbose.
843 Some options cause an automatically parsing of the module command line args.
844 See L<Getopt::Long> for the format of the hash ref accepted by
845 I<EnableOptions> parameter. If boolean I<EnableAlias> parameter is given,
846 then the alias argument may be specified anywhere on the command line, for
847 example before or after long/short options or even in between, as long as
848 there are no conflicts with some non-mandatory option arguments. In which
849 case "--" may be used to indicate the end of the options. All non-parsed
850 command line arguments are available to the program using B<argv> method.
852 =item B<version>
854 Returns fvwm version string I<x.y.z>.
856 =item B<version_info>
858 Returns fvwm version info string, like " (from cvs)" or " (snap-YYYYMMDD)".
859 This string is usually empty for the final version.
861 =item B<argv>
863 Returns remaining module arguments (array ref) passed in the command line.
864 Arguments that are used for I<fvwm>-to-module communication are not included.
865 Arguments that are automatically parsed using I<EnableAlias> and/or
866 I<EnableOptions> specified in the constructor are not included.
868 =item B<send> I<command> [I<window-id>] [I<continue-flag>]
870 Sends I<command> back for execution. If the I<window-id> is specified this
871 command will be executed in this window context. I<continue-flag> of 0
872 signals that this is the last sent command from the module, the default
873 for this flag is 1.
875 =item B<track> [I<mode-hash>] [I<name>] [I<param-hash>]
877 Creates a module tracker object (see L<FVWM::Tracker>) specified
878 by a I<name>.
880 I<mode-hash> may include parameters:
882 NoStart - true value means the created tracker is not auto-started
883 NoReuse - true value means not to reuse any existing named tracker
885 I<param-hash> is specific to the tracker named I<name>. Every tracker class
886 (a subclass of B<FVWM::Tracker>) has its own manual page, contact it for
887 the tracker details and usage.
889 =item B<event_loop>
891 The main event loop. A module should define some event handlers using
892 B<add_handler> before entering the event loop. When the event happens all
893 event handlers registered on this event are called, then a module returns
894 to the event loop awaiting for new events forever.
896 This method may be finished when one of the following happens. 1) Explicit
897 B<terminate> is called in one of the event handlers. 2) Signal handler
898 (system signals are independent from this event loop) decides to I<die>.
899 This is usually catched and a proper shutdown is done. 3) An event handler
900 I<die>d, in this case the module aborts, this is done on purpose to
901 encourage programmers to fix bugs. 4) Communication with I<fvwm> closed, for
902 example B<KillModule> called or the main I<fvwm> process exited.
904 In all these cases (except for the third one) I<ON_EXIT> event handlers are
905 called if defined and then B<disconnect> is called. So no communication is
906 available after this method is finished. If you need a communication before
907 the module exits, define an I<ON_EXIT> event handler.
909 =item B<send_ready>
911 This is automatically called (if needed) when a module enters B<event_loop>,
912 but sometimes you may want to tell I<fvwm> that the module is fully ready
913 earlier. This only makes sence if the module was run using
914 B<ModuleSynchronous> command, in this case I<fvwm> gets locked until the module
915 sends the "ready" notification.
917 =item B<send_unlock>
919 When an event was configured to be sent to a module synchronously using
920 I<SyncMask> and I<SyncXMask>, I<fvwm> gets locked until the module sends
921 the "unlock" notification. This is automatically sent (if needed) when a
922 handler is finished, but sometimes a handler should release I<fvwm> earlier.
924 =item B<request_reply> I<text> [I<win_id>]
926 A module may request I<fvwm> to send the same text (but possibly
927 interpolated) back to it using MX_REPLY event. This method sends special
928 command I<Send_Reply>.
930 =item B<postpone_send> I<command> [I<window-id>] [I<continue-flag>]
932 The same like B<send>, but the actual command sending is postponed
933 until before the module enters the reading-from-fvwm phase in B<event_loop>.
935 =item B<terminate> [I<continue>]
937 This method is used for 2 purposed, usually in event handlers. To terminate
938 the entire event loop and to terminate only an execution of the current
939 handler if I<continue> is set.
941 =item B<reset_handlers>
943 This deletes all event handlers without exception.
945 =item B<add_handler> I<mask code>
947 Defines a handler (that is a I<code> subroutine) for the given I<mask> event
948 (or several events). Usually the event type is one of the fvwm I<M_*> or
949 I<MX_*> constants (see B<FVWM::Constants>), but it may also be I<ON_EXIT>,
950 this special event is called just before the event loop is terminated.
952 The I<mask> may include several events in the same category (the event types
953 are or-ed). In this case the handler will be called for every matching event.
954 Currently there are 3 categories: regular events (M_*), extended events (MX_*)
955 and special events (ON_EXIT). These 3 categories of events can't be mixed,
956 primary because of technical reasons.
958 The handler subroutine is called with these parameters:
960 ($self, $event)
962 where C<$self> is a module object, C<$event> is B<FVWM::Event> object.
964 If the I<mask> includes more than one event type, use C<$event-E<gt>type>
965 to dispatch event types if needed.
967 The handler may call C<$self-E<gt>terminate> to terminate the event loop
968 completely or C<$self-E<gt>terminate("continue")> to terminate the current
969 event handler only. The second form is useful when the handler subroutine
970 calls other subroutines that need to terminate the primary one.
972 If several event handlers are added for the same event type, they are
973 executed in the added order. To forbid the further propagation of the
974 same event, an event handler may call C<$event-E<gt>propagation_allowed(0)>.
976 The return value from B<add_handler> is an identifier the only purpose of
977 which is to be passed to B<delete_handler> in case the newly defined handler
978 should be deleted at some point.
980 =item B<delete_handler> I<id>
982 Removes the handler specified by I<id>. The return value is 1 if the handler
983 is found and deleted, 0 otherwise.
985 =item B<add_default_error_handler>
987 This adds the default handler for I<M_ERROR> event. This class simply prints
988 an error message to the standard error stream, but subclasses may define
989 another default handler by overwriting this method.
991 =item B<debug> I<msg> [I<level>]
993 Prints I<msg> to the standard error stream if I<level> is greater or equal to
994 the module debug level defined using I<Debug> in the constructor. The default
995 I<level> for this method is 1 that makes it possible to add user debugging
996 output without specifying a level. The default module level is 0, so no
997 debugging output of positive levels is shown.
999 This module uses B<debug> internally (with I<level> 2) to dump all
1000 incoming and outgoing communication data in B<send> and B<process_packet>.
1001 Apparently this output is only seen if I<Debug> is set to 2 or greater.
1003 =item B<show_error> I<msg>
1005 Writes I<msg> to the error stream (stderr). It is supposed that the argument
1006 has no traling end of line. May be used to signal non fatal error.
1008 Subclasses may overwrite this method and, for example, show all error
1009 messages in separate windows or in the common error window.
1011 =item B<show_message> I<msg>
1013 Writes I<msg> to the message stream (stderr). It is supposed that the argument
1014 has no traling end of line. May be used to show a named output.
1016 Subclasses may overwrite this method and, for example, show all
1017 messages in separate windows or in the common message window.
1019 =item B<show_debug> I<msg>
1021 Unconditionally writes I<msg> to the debug stream (stderr). It is supposed
1022 that the argument has no traling end of line. Used in B<debug> to actually
1023 show the message when the level is matched.
1025 Subclasses may overwrite this method and, for example, show all debugging
1026 messages in separate windows or in the common debug window.
1028 =item B<is_dummy>
1030 Usually a module should be executed by I<fvwm> only. But to help creating
1031 GUI applications, the dummy mode is supported when the module is started
1032 from the command line. No events are received in this case, but with some
1033 effort they may be emulated:
1035 $module->emulate_event(M_NEW_DESK, [ 2 ]) if $module->is_dummy;
1037 =item B<internal_die> I<msg>
1039 This may be used to end the module with the corresponding I<msg>.
1040 For a clean module exit use B<show_error> and B<terminate> instead.
1042 =item B<name> [I<name>]
1044 Sets or returns the module name. Called automatically from the constructor.
1046 =item B<mask> [I<mask>] [I<explicit-flag>]
1047 =item B<xmask> [I<mask>] [I<explicit-flag>]
1049 Sets or returns the module mask. Called automatically from the constructor.
1051 Regular and extended event types should never be mixed, this is why there
1052 are 2 variants of this method, the first is for regular and the second is
1053 for extended event types. Without a parameter, the module mask is returned,
1054 the integer parameter indicates a mask to set and the old mask is returned.
1056 The module only receives the packets matching these 2 module masks (regular
1057 and extended).
1059 This class is smart to update the minimal module masks automatically if you
1060 never set them explicitly (either in constructor or using these methods).
1061 The I<explicit-flag> parameter should not be usually used, it defaults to 1.
1062 If you set it to 0 then the module is informed to continue to automatically
1063 update masks on the following B<add_handlers> calls even after the current
1064 mask setting.
1066 =item B<is_in_mask> I<type>
1068 Returns true if the module mask matches the given I<type>.
1069 Good for both regular and extended event types as long as they are queried
1070 separately.
1072 =item B<sync_mask> [I<mask>]
1073 =item B<sync_xmask> [I<mask>]
1075 The same as B<mask> and B<xmask>, but sets/returns the synchronization
1076 mask of the module.
1078 The module is synchronized with I<fvwm> on all packets matching these 2
1079 module synchronization masks (regular and extended).
1081 =item B<is_in_sync_mask> I<type>
1083 Returns true if the module synchronization mask matches the given I<type>.
1084 Good for both regular and extended event types as long as they are queried
1085 separately.
1087 =item B<disconnect>
1089 This method invokes I<ON_EXIT> handlers if any and closes communication.
1090 It is called automatically from B<event_loop> before finishing.
1091 It is safe to call this method more than once.
1093 This method may be called from signal handlers before I<exit>ing for the
1094 proper shutdown.
1096 =item B<get_handler_category> I<type>
1098 Returns one of 3 string ids depending on the event handler I<type> that has
1099 the same meaning as the corresponding packet type ("regular" or "extended")
1100 with an addition of "special" category for I<ON_EXIT> handlers.
1102 =item B<read_packet>
1104 This is a blocking method that waits until there is a packet on the
1105 communication end from I<fvwm>. Then it returns a list of 2 values,
1106 packet type and packet data (unpacked array of arguments).
1108 =item B<invoke_handler> I<event>
1110 Dispatches the apropos event handlers with the event data.
1111 This method is called automatically, so you usually should not worry about it.
1113 =item B<process_packet> [I<type data>]
1115 This method constructs the event object from the packet data and calls
1116 B<invoke_handler> with it. Prints debug info if requested. Finally calls
1117 B<send_unlock> if needed.
1119 You should not really worry about this method, it is called automatically
1120 from the event loop.
1122 =item B<emulate_event> I<type data>
1124 This method emulates the event as returned by B<read_packet>. The given event
1125 is processed immediately if in the event loop, or just before the real
1126 B<read_packet> otherwise.
1128 The parameters are the same as in B<process_packet> and the same as in
1129 L<FVWM::Event> constructor.
1131 =item B<event_loop_prepared>
1133 Called from B<event_loop> every time before reading the packet for new data.
1134 Subclasses should pass this method the same arguments that B<event_loop>
1135 received for a possible future use.
1137 =item B<event_loop_finished>
1139 Called from B<event_loop> just before the return.
1140 Subclasses should pass this method the same arguments that B<event_loop>
1141 received for a possible future use.
1143 =item B<is_event_extended> I<type>
1145 For technical reasons there are 2 categories of fvwm events, regular and
1146 extended. This is done to enable more events. With introdution of the
1147 extended event types (with the highest bit set) it is now possible to have
1148 31+31=62 different event types rather than 32. This is a good point, the bad
1149 point is that only event types of the same category may be masked (or-ed)
1150 together. This method returns 1 or 0 depending on whether the event I<type>
1151 is extended or not.
1153 =item B<user_data_dir>
1155 Returns the user data directory, usually ~/.fvwm or set by $FVWM_USERDIR.
1157 =item B<site_data_dir>
1159 Returns the system-wide data directory, the one configured when fvwm is
1160 installed. It is also returned by `fvwm-config --fvwm-datadir`.
1162 =item B<search_dirs>
1164 It is a good practice for a module to search for the given configuration
1165 in one of 2 data directories, the user one and the system-wide. This method
1166 returns a list of both directories in that order.
1168 =back
1170 =head1 BUGS
1172 Awaiting for your reporting.
1174 =head1 CAVEATS
1176 In keeping with the UNIX philosophy, B<FVWM::Module> does not keep you from
1177 doing stupid things, as that would also keep you from doing clever things.
1178 What this means is that there are several areas with which you can hang your
1179 module or even royally confuse your running I<fvwm> process. This is due to
1180 flexibility, not bugs.
1182 =head1 AUTHOR
1184 Mikhael Goikhman <migo@homemail.com>.
1186 =head1 THANKS TO
1188 Randy J. Ray <randy@byz.org>.
1190 =head1 SEE ALSO
1192 For more information, see L<fvwm>, L<FVWM::Module::Gtk> and L<FVWM::Module::Tk>,
1193 L<FVWM::Tracker>.
1195 =cut