cvsimport
[fvwm.git] / perllib / FVWM / EventNames.pm
blobba33c2da0141aff7ba9aed4a00c3cc737d13eac2
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::EventNames;
19 use strict;
20 use FVWM::Constants;
22 use constant number => 0;
23 use constant bool => 1;
24 use constant window => 2;
25 use constant pixel => 3;
26 use constant string => 4;
27 use constant wflags => 5;
28 use constant looped => 6;
30 use vars qw($EVENTS_INFO);
32 # ----------------------------------------------------------------------------
33 # start of the would-be-generated part
35 $EVENTS_INFO = {
37 &M_NEW_PAGE => {
38 format => "l!3L!4",
39 fields => [
40 vp_x => number,
41 vp_y => number,
42 desk_n => number,
43 vp_width => number,
44 vp_height => number,
45 desk_pages_x => number,
46 desk_pages_y => number,
48 aliases => {
49 desk => 'desk_n',
53 &M_NEW_DESK => {
54 format => "l!",
55 fields => [
56 desk_n => number,
58 aliases => {
59 desk => 'desk_n',
63 # &M_OLD_ADD_WINDOW => {
64 # },
66 &M_RAISE_WINDOW => {
67 format => "L!3",
68 fields => [
69 win_id => window,
70 frame_id => window,
71 ptr => number,
75 &M_LOWER_WINDOW => {
76 format => "L!3",
77 fields => [
78 win_id => window,
79 frame_id => window,
80 ptr => number,
84 # &M_OLD_CONFIGURE_WINDOW => {
85 # },
87 &M_FOCUS_CHANGE => {
88 format => "L!5",
89 fields => [
90 win_id => window,
91 frame_id => window,
92 flip => bool,
93 focus_fg => pixel,
94 focus_bg => pixel,
98 &M_DESTROY_WINDOW => {
99 format => "L!3",
100 fields => [
101 win_id => window,
102 frame_id => window,
103 ptr => number,
107 &M_ICONIFY => {
108 format => "L!3l!8",
109 fields => [
110 win_id => window,
111 frame_id => window,
112 ptr => number,
113 icon_x => number,
114 icon_y => number,
115 icon_width => number,
116 icon_height => number,
117 frame_x => number,
118 frame_y => number,
119 frame_width => number,
120 frame_height => number,
124 &M_DEICONIFY => {
125 format => "L!3l!8",
126 fields => [
127 win_id => window,
128 frame_id => window,
129 ptr => number,
130 icon_x => number,
131 icon_y => number,
132 icon_width => number,
133 icon_height => number,
134 frame_x => number,
135 frame_y => number,
136 frame_width => number,
137 frame_height => number,
141 &M_WINDOW_NAME => {
142 format => "L!3a*",
143 fields => [
144 win_id => window,
145 frame_id => window,
146 ptr => number,
147 name => string,
151 &M_ICON_NAME => {
152 format => "L!3a*",
153 fields => [
154 win_id => window,
155 frame_id => window,
156 ptr => number,
157 name => string,
161 &M_RES_CLASS => {
162 format => "L!3a*",
163 fields => [
164 win_id => window,
165 frame_id => window,
166 ptr => number,
167 name => string,
171 &M_RES_NAME => {
172 format => "L!3a*",
173 fields => [
174 win_id => window,
175 frame_id => window,
176 ptr => number,
177 name => string,
181 &M_END_WINDOWLIST => {
182 format => "",
183 fields => [
187 &M_ICON_LOCATION => {
188 format => "L!3l!4",
189 fields => [
190 win_id => window,
191 frame_id => window,
192 ptr => number,
193 x => number,
194 y => number,
195 width => number,
196 height => number,
200 &M_MAP => {
201 format => "L!3",
202 fields => [
203 win_id => window,
204 frame_id => window,
205 ptr => number,
209 &M_ERROR => {
210 format => "L!3a*",
211 fields => [
212 win_id => window,
213 frame_id => window,
214 ptr => number,
215 text => string,
219 &M_CONFIG_INFO => {
220 format => "L!3a*",
221 fields => [
222 win_id => window,
223 frame_id => window,
224 ptr => number,
225 text => string,
229 &M_END_CONFIG_INFO => {
230 format => "",
231 fields => [
235 &M_ICON_FILE => {
236 format => "L!3a*",
237 fields => [
238 win_id => window,
239 frame_id => window,
240 ptr => number,
241 name => string,
245 &M_DEFAULTICON => {
246 format => "L!3a*",
247 fields => [
248 win_id => window,
249 frame_id => window,
250 ptr => number,
251 name => string,
255 &M_STRING => {
256 format => "L!3a*",
257 fields => [
258 win_id => window,
259 frame_id => window,
260 ptr => number,
261 text => string,
265 &M_MINI_ICON => {
266 format => "L!9a*",
267 fields => [
268 win_id => window,
269 frame_id => window,
270 ptr => number,
271 width => number,
272 height => number,
273 depth => number,
274 icon_id => window,
275 mask => number,
276 alpha => number,
277 name => string,
281 &M_WINDOWSHADE => {
282 format => "L!3",
283 fields => [
284 win_id => window,
285 frame_id => window,
286 ptr => number,
290 &M_DEWINDOWSHADE => {
291 format => "L!3",
292 fields => [
293 win_id => window,
294 frame_id => window,
295 ptr => number,
299 &M_VISIBLE_NAME => {
300 format => "L!3a*",
301 fields => [
302 win_id => window,
303 frame_id => window,
304 ptr => number,
305 name => string,
309 # &M_SENDCONFIG => {
310 # },
312 &M_RESTACK => {
313 format => "L!3a*",
314 fields => [
315 win_id => window,
316 frame_id => window,
317 ptr => number,
318 low_windows => looped,
320 loop_format => "L!3a*",
321 loop_fields => [
322 win_id => window,
323 frame_id => window,
324 ptr => number,
328 &M_ADD_WINDOW => {
329 format => "L!3l!6l!8L!2l!L!2l!3S4a*",
330 fields => [
331 win_id => window,
332 frame_id => window,
333 ptr => number,
334 frame_x => number,
335 frame_y => number,
336 frame_width => number,
337 frame_height => number,
338 desk => number,
339 layer => number,
340 win_width => number,
341 win_height => number,
342 resize_width_inc => number,
343 resize_height_inc => number,
344 minimum_width => number,
345 minimum_height => number,
346 maximum_width => number,
347 maximum_height => number,
348 icon_title_id => window,
349 icon_image_id => window,
350 gravity => number,
351 fore_color => pixel,
352 back_color => pixel,
353 ewmh_layer => number,
354 ewmh_desktop => number,
355 ewmh_window_type => number,
356 title_height => number,
357 border_width => number,
358 dummy_zero_1 => number,
359 dummy_zero_2 => number,
360 window_flags => wflags,
364 &M_CONFIGURE_WINDOW => {
365 format => "L!3l!6l!8L!2l!L!2l!3S4a*",
366 fields => [
367 win_id => window,
368 frame_id => window,
369 ptr => number,
370 frame_x => number,
371 frame_y => number,
372 frame_width => number,
373 frame_height => number,
374 desk => number,
375 layer => number,
376 win_width => number,
377 win_height => number,
378 resize_width_inc => number,
379 resize_height_inc => number,
380 minimum_width => number,
381 minimum_height => number,
382 maximum_width => number,
383 maximum_height => number,
384 icon_title_id => window,
385 icon_image_id => window,
386 gravity => number,
387 fore_color => pixel,
388 back_color => pixel,
389 ewmh_layer => number,
390 ewmh_desktop => number,
391 ewmh_window_type => number,
392 title_height => number,
393 border_width => number,
394 dummy_zero_1 => number,
395 dummy_zero_2 => number,
396 window_flags => wflags,
400 # &M_EXTENDED_MSG => {
401 # },
403 &MX_VISIBLE_ICON_NAME => {
404 format => "L!3a*",
405 fields => [
406 win_id => window,
407 frame_id => window,
408 ptr => number,
409 name => string,
413 &MX_ENTER_WINDOW => {
414 format => "L!3",
415 fields => [
416 win_id => window,
417 frame_id => window,
418 ptr => number,
422 &MX_LEAVE_WINDOW => {
423 format => "L!3",
424 fields => [
425 win_id => window,
426 frame_id => window,
427 ptr => number,
431 &MX_PROPERTY_CHANGE => {
432 format => "L!3a*",
433 fields => [
434 type => number,
435 value => number,
436 win_id => window,
437 text => string,
439 info => {
440 type_names => [ qw(NONE BACKGROUND SWALLOW) ],
444 &MX_REPLY => {
445 format => "L!3a*",
446 fields => [
447 win_id => window,
448 frame_id => window,
449 ptr => number,
450 text => string,
454 "faked" => {
455 format => "",
456 fields => [
462 # end of the would-be-generated part
463 # ----------------------------------------------------------------------------
465 use Exporter;
466 use vars qw(@EXPORT @ISA $EVENT_TYPES $EVENT_NAMES $EVENT_TYPE_NAMES);
467 @EXPORT = (
468 @FVWM::Constants::EXPORT,
469 qw(event_name event_arg_names event_arg_types event_arg_values event_args),
470 qw(event_loop_arg_names event_loop_arg_types),
471 qw(event_arg_aliases all_event_names all_event_types)
473 @ISA = qw(Exporter);
475 sub all_event_type_names () {
476 if (!defined $EVENT_TYPE_NAMES) {
477 $EVENT_TYPES = [];
478 $EVENT_NAMES = [];
479 $EVENT_TYPE_NAMES = {};
480 my ($type, $name);
481 foreach $name (@FVWM::Constants::EXPORT) {
482 next unless $name =~ /^MX?_/;
483 next if $name eq 'M_EXTENDED_MSG';
484 no strict 'refs';
485 $type = &$name();
486 next if $name =~ /^MX_/ && !($type & M_EXTENDED_MSG);
487 push @$EVENT_TYPES, $type;
488 push @$EVENT_NAMES, $name;
489 $EVENT_TYPE_NAMES->{$type} = $name;
492 return $EVENT_TYPE_NAMES;
495 sub all_event_names () {
496 all_event_type_names();
497 return wantarray? @$EVENT_NAMES: $EVENT_NAMES;
500 sub all_event_types () {
501 all_event_type_names();
502 return wantarray? @$EVENT_TYPES: $EVENT_TYPES;
505 sub event_name ($) {
506 my $type = shift;
507 return all_event_type_names()->{$type};
510 sub event_type_to_binary ($) {
511 my $type = shift || "no-event-type";
513 return $type unless $type =~ /^\d+$/;
514 return sprintf("%b", $type);
517 sub event_info ($) {
518 my $type = shift;
519 unless (defined $EVENTS_INFO->{$type}) {
520 die "FVWM::EventNames: Unknown event type (" .
521 event_type_to_binary($type) . ")\n";
523 return $EVENTS_INFO->{$type};
526 sub calculate_internals ($) {
527 my $type = shift;
529 my $event_info = event_info($type);
530 $event_info->{names} = [];
531 $event_info->{types} = [];
533 my $i = 0;
534 foreach (@{$event_info->{fields}}) {
535 push @{$event_info->{names}}, $_ if ($i % 2) == 0;
536 push @{$event_info->{types}}, $_ if ($i % 2) == 1;
537 $i++;
540 # handle loop args if any
541 return unless exists $event_info->{loop_fields};
542 $event_info->{loop_names} = [];
543 $event_info->{loop_types} = [];
545 $i = 0;
546 foreach (@{$event_info->{loop_fields}}) {
547 push @{$event_info->{loop_names}}, $_ if ($i % 2) == 0;
548 push @{$event_info->{loop_types}}, $_ if ($i % 2) == 1;
549 $i++;
553 sub event_arg_names ($$) {
554 my $type = shift;
555 my $arg_values = shift;
557 my $event_info = event_info($type);
558 my $arg_names = $event_info->{names};
559 return $arg_names if defined $arg_names;
560 calculate_internals($type);
561 return $event_info->{names};
564 sub event_arg_types ($$) {
565 my $type = shift;
566 my $arg_values = shift;
568 my $event_info = event_info($type);
569 my $arg_types = $event_info->{types};
570 return $arg_types if defined $arg_types;
571 calculate_internals($type);
572 return $event_info->{types};
575 sub event_arg_values ($$) {
576 my $type = shift;
577 my $packed_str = shift;
579 my $event_info = event_info($type);
580 my @arg_values = unpack($event_info->{format}, $packed_str);
581 my $arg_fields = $event_info->{fields};
582 push @arg_values, (undef) x ((@$arg_fields / 2) - @arg_values);
584 # process looped args
585 if (@$arg_fields && $arg_fields->[@$arg_fields - 1] == looped) {
586 my @loop_arg_values = ();
588 my $rest_str = pop @arg_values;
589 while ($rest_str ne "") {
590 my @new_arg_values = unpack($event_info->{loop_format}, $rest_str);
591 die "Internal error, no loop args unpacked ($type)\n" unless @new_arg_values > 1;
592 $rest_str = pop @new_arg_values;
593 push @loop_arg_values, @new_arg_values;
596 push @arg_values, \@loop_arg_values;
599 # strip everything past the first null (or newline) if needed
600 if (@$arg_fields && $arg_fields->[-1] == string) {
601 $arg_values[-1] =~ s/\n*\0.*//s;
604 return \@arg_values;
607 sub event_loop_arg_names ($$) {
608 my $type = shift;
609 my $arg_values = shift;
611 my $event_info = event_info($type);
612 my $arg_names = $event_info->{loop_names};
613 return $arg_names if defined $arg_names;
614 calculate_internals($type);
615 return $event_info->{loop_names};
618 sub event_loop_arg_types ($$) {
619 my $type = shift;
620 my $arg_values = shift;
622 my $event_info = event_info($type);
623 my $arg_types = $event_info->{loop_types};
624 return $arg_types if defined $arg_types;
625 calculate_internals($type);
626 return $event_info->{loop_types};
629 sub event_args ($$) {
630 my $type = shift;
631 my $arg_values = shift;
633 my $arg_names = event_arg_names($type, $arg_values);
635 die sprintf "Internal error, event type %s (%d names, %d values)\n",
636 event_type_to_binary($type), scalar @$arg_names, scalar @$arg_values
637 if @$arg_names != @$arg_values;
639 my $loop_arg_names = event_loop_arg_names($type, $arg_values);
641 die sprintf "Internal error, event type %s (%d loop names, non array)\n",
642 event_type_to_binary($type), scalar @$loop_arg_names
643 if $loop_arg_names && ref($loop_arg_names) ne 'ARRAY'
644 && !@$loop_arg_names && ref($arg_values->[-1]) ne 'ARRAY';
646 my $i = 0;
647 my %args = map {
648 my $value = $_;
649 $arg_names->[$i++], ref($value) ne 'ARRAY'? $value: do {
650 my $loop_value = [];
651 my $j = 0;
652 while ($j < @$value) {
653 my %loop_hash = map { $_, $value->[$j++] } @$loop_arg_names;
654 push @$loop_value, \%loop_hash;
656 $loop_value
658 } @$arg_values;
659 return \%args;
662 sub event_arg_aliases ($) {
663 my $type = shift;
665 return event_info($type)->{aliases} || {};
668 # ----------------------------------------------------------------------------
670 =head1 NAME
672 FVWM::EventNames - names and types of all fvwm event arguments
674 =head1 SYNOPSIS
676 use FVWM::EventNames;
678 print "All event names: ", join(", ", @{all_event_names()}), "\n";
679 print "All event types: ", join(", ", @{all_event_types()}), "\n";
681 my $name = event_name (M_ICON_LOCATION);
682 my $arg_values = event_arg_values(M_ICON_LOCATION, $packed_str);
683 my $arg_names = event_arg_names (M_ICON_LOCATION, $arg_values);
684 my $arg_types = event_arg_types (M_ICON_LOCATION, $arg_values);
685 my $args = event_args (M_ICON_LOCATION, $arg_values);
687 =head1 DESCRIPTION
689 Every event send by I<fvwm> consist of arguments. The argument names and
690 types vary from one event type to another. For example, event of the
691 type B<M_NEW_DESK> consists of only one argument I<desk> of type I<number>.
692 B<M_NEW_PAGE> consists of 5 numeric arguments, B<M_MINI_ICON> consists of 10
693 arguments of different types.
695 This class provides information about all fvwm events. It provides such
696 services as listing all supported event types and their names,
697 converting event type to event name, listing the event argument names/types,
698 constructing event argument values from the plain packet data.
700 Usually you do not need to work with this class directly, but, instead, with
701 B<FVWM::Event> objects. Hovewer, you may need this class source as a
702 reference for the names of the event arguments and their types.
704 =head1 PUBLIC FUNCTIONS
706 =over 4
708 =item B<event_name> I<type>
710 Returns the string representation of the numeric event I<type> constant,
711 like I<M_RAISE_WINDOW> or I<MX_ENTER_WINDOW>.
713 =item B<event_arg_values> I<type> I<packed_str>
715 Constructs array ref of argument values for the event I<type>
716 from the I<packed_str> (as received from I<fvwm>).
718 If the last argument type of the event is string, for convenience,
719 everything past the first null (or newline) is automatically stripped
720 from the last argument value.
722 =item B<event_arg_names> I<type> I<arg_values>
724 Returns array ref of argument names of the event type.
726 I<arg_values> is either the real array ref of values (as returned by
727 B<event_arg_values>) or a number of actual values.
728 The returned array has the same number of elements.
730 =item B<event_arg_types> I<type> I<arg_values>
732 Returns array ref of argument types of the event type.
734 I<arg_values> is either the real array ref of values (as returned by
735 B<event_arg_values>) or a number of actual values.
736 The returned array has the same number of elements.
738 =item B<event_loop_arg_names> I<type> I<arg_values>
740 Returns array ref of looped argument names of the event type (or undef).
742 =item B<event_loop_arg_types> I<type> I<arg_values>
744 Returns array ref of looped argument types of the event type (or undef).
746 =item B<event_args> I<type> I<arg_values>
748 Constructs hash ref of the named arguments for the event I<type>
749 from the I<arg_values> array ref (as returned by B<event_arg_values>).
751 =item B<event_arg_aliases> I<type>
753 This method is provided for backward compatibility when argument names
754 are changed. For example, in the past the argument name of I<M_NEW_DESK>
755 was B<desk>, but now it is B<desk_n>. Using this method it is possible
756 to make both names supported. Returns hash ref (old-name => new-name).
758 =item B<all_event_names>
760 Returns array ref of all known event names (strings).
761 In the list context returns list of these names.
763 =item B<all_event_types>
765 Returns array ref of all known event types (numbers).
766 In the list context returns list of these types.
768 =item B<all_event_type_names>
770 Returns hash ref of all known event names and types (type => name).
772 =back
774 =head1 SEE ALSO
776 L<FVWM::Event>.
778 =cut