Hi Mikhael, Find attached patch for the WindowList tracker.
I wonder if you would be adverse to renaming this tracker "FVWM::Tracker::Window(s)"? This tracker tracks windows, not window lists. What do you think? Your fix to FVWM::Tracker::deleteHandlers works great! Thanks, SCoTT. :)
Index: WindowList.pm =================================================================== RCS file: /home/cvs/fvwm/fvwm/perllib/FVWM/Tracker/WindowList.pm,v retrieving revision 1.4 diff -u -r1.4 WindowList.pm --- WindowList.pm 25 Oct 2003 03:00:01 -0000 1.4 +++ WindowList.pm 25 Apr 2004 08:18:49 -0000 @@ -20,11 +20,21 @@ use FVWM::Tracker qw(base); +my $windowEvents = M_ADD_WINDOW | M_CONFIGURE_WINDOW | M_DESTROY_WINDOW; +my $nameEvents = M_RES_NAME | M_RES_CLASS | M_WINDOW_NAME | M_VISIBLE_NAME | M_ICON_NAME; +my $stackEvents = M_RESTACK | M_RAISE_WINDOW | M_LOWER_WINDOW; +my $iconEvents = M_ICON_LOCATION | M_ICON_FILE | M_DEFAULTICON | M_MINI_ICON; + sub observables ($) { return [ "window added", "window deleted", "window properties updated", + "window moved", + "window resized", + "window name updated", + "window stack updated", + "window icon updated", ]; } @@ -36,41 +46,36 @@ my $self = $class->FVWM::Tracker::new($module); $self->{options} = [ @options ]; - return $self; } -sub addRequestedInfoHandlers ($$$$) { +sub addRequestedInfoHandlers ($$) { my $self = shift; - my $handlerC = shift; - my $handlerD = shift; - my $handlerP = shift; + my $handler = shift; my $useWInfo = 1; my $useNames = 1; my $useStack = 0; my $useIcons = 0; - foreach my $option (@{$self->{options}}) { + foreach (@{$self->{options}}) { /^(\!?)winfo$/ and $useWInfo = $1 ne '!'; /^(\!?)names$/ and $useNames = $1 ne '!'; /^(\!?)stack$/ and $useStack = $1 ne '!'; /^(\!?)icons$/ and $useIcons = $1 ne '!'; } - my $mask1 = 0; - my $mask2 = 0; - my $xmask2 = 0; - $mask1 |= M_ADD_WINDOW | M_CONFIGURE_WINDOW if $useWInfo; - $mask2 |= M_RES_NAME | M_RES_CLASS | M_WINDOW_NAME | M_VISIBLE_NAME | M_ICON_NAME - if $useNames; - $mask2 |= M_RESTACK | M_RAISE_WINDOW | M_LOWER_WINDOW if $useStack; - $mask2 |= M_ICON_LOCATION | M_ICON_FILE | M_DEFAULTICON | M_MINI_ICON - if $useIcons; - $xmask2 |= MX_VISIBLE_ICON_NAME if $useNames; - - $self->addHandler($mask1, $handlerC) if $mask1; - $self->addHandler(M_DESTROY_WINDOW, $handlerD); - $self->addHandler($mask2, $handlerP) if $mask2; - $self->addHandler($xmask2, $handlerP) if $xmask2; + my $mask = 0; + $mask |= $windowEvents if $useWInfo; + $mask |= $nameEvents if $useNames; + $mask |= $stackEvents if $useStack; + $mask |= $iconEvents if $useIcons; + + # Adding MX_VISIBLE_ICON_NAME to $nameEvents does not work. + my $xmask = 0; + $xmask |= MX_VISIBLE_ICON_NAME if $useNames; + + $self->addHandler($mask, $handler) if $mask; + $self->addHandler($xmask, $handler) if $xmask; + $self->addHandler(M_NEW_PAGE, sub { $self->handlerNewPage($_[1]); }); } sub start ($) { @@ -78,37 +83,62 @@ $self->{data} = {}; - ### TODO $self->addRequestedInfoHandlers(sub { my $event = $_[1]; - $self->calculateInternals($event->args); - }, sub { - my $event = $_[1]; - $self->calculateInternals($event->args); - }, sub { - my $event = $_[1]; - $self->calculateInternals($event->args); + $self->calculateInternals($event); }); $self->requestWindowListEvents; - - ### temporary - $self->deleteHandlers; - my $result = $self->SUPER::start; - $self->deleteHandlers; - ### TODO $self->addRequestedInfoHandlers(sub { my $event = $_[1]; - $self->calculateInternals($event->args); - }, sub { - my $event = $_[1]; - $self->calculateInternals($event->args); - }, sub { - my $event = $_[1]; - $self->calculateInternals($event->args); + my ($winId, $oldHash) = $self->calculateInternals($event); + return unless defined $winId; + my $type = $event->type(); + if ($type & M_ADD_WINDOW) + { + $self->notify("window added", $winId); + } + elsif ($type & M_CONFIGURE_WINDOW) + { + $self->notify("window properties updated", $winId, $oldHash); + # The "window properties updated" observable is very broad & + # occurs as a result of many different operations - here we + # try & determine if some common operations occur & invoke more + # specific observables. This may reduce the amount of parsing + # external modules have to do. + my $p = $self->{data}->{$winId}; + if ($p->{frame_width} != $oldHash->{frame_width} || + $p->{frame_height} != $oldHash->{frame_height}) + { + $self->notify("window resized", $winId, $oldHash); + } + elsif ($p->{desk} != $oldHash->{desk} || + $p->{x} != $oldHash->{x} || + $p->{y} != $oldHash->{y}) + { + $self->notify("window moved", $winId, $oldHash); + } + # We can easily add other specific observables here as required. + } + elsif ($type & M_DESTROY_WINDOW) + { + $self->notify("window deleted", $winId, $oldHash); + } + elsif ($type & $nameEvents || $type & MX_VISIBLE_ICON_NAME) + { + $self->notify("window name updated", $winId, $oldHash); + } + elsif ($type & $stackEvents) + { + $self->notify("window stack updated", $winId, $oldHash); + } + elsif ($type & $iconEvents) + { + $self->notify("window icon updated", $winId, $oldHash); + } }); return $result; @@ -116,10 +146,41 @@ sub calculateInternals ($$) { my $self = shift; - my $args = shift; + my $event = shift; + my $args = $event->args; my $data = $self->{data}; - ### TODO + my $winId = $args->{win_id}; + my $oldHash = undef; + if (defined $data->{$winId}) + { + # make a copy of the hash cos we are about to modify it. + my %tmp = %{$data->{$winId}}; + $oldHash = \%tmp; + } + @{$data->{$winId}}{keys %{$args}} = values %{$args}; + + if (defined $args->{frame_x}) + { + # frame_x & frame_y are _relative_ coords of the window to the + # current page - calculate the _absolute_ coords - x & y. + my $p = $self->{pageInfo}; + $data->{$winId}->{x} = $p->{currentPageX} + $args->{frame_x}; + $data->{$winId}->{y} = $p->{currentPageY} + $args->{frame_y}; + } + + return wantarray ? ($winId, $oldHash) : $winId; +} + +sub handlerNewPage ($$) { + my $self = shift; + my $event = shift; + my $args = $event->args; + + $self->{pageInfo}->{currentPageX} = $args->{vp_x}; + $self->{pageInfo}->{currentPageY} = $args->{vp_y}; + $self->{pageInfo}->{pageWidth} = $args->{vp_width}; + $self->{pageInfo}->{pageHeight} = $args->{vp_height}; } sub data ($;$) { @@ -161,22 +222,27 @@ "window added", "window deleted", "window properties updated", - -NOT USABLE YET. + "window moved", + "window resized", + "window name updated", + "window stack updated", + "window icon updated", =head1 SYNOPSYS Using B<FVWM::Module> $module object (preferably): - my $windowsTracker = $module->track("ModuleConfig"); + my $windowsTracker = $module->track("WindowList", $options); my $windows = $windowsTracker->data; my $windowSizeX = $windows->{$winId}->{'x'}; or: - my $windowsTracker = $module->track("WindowList"); + my $windowsTracker = $module->track("WindowList", $options); my $windowSizeX = $windowsTracker->data($winId)->{'x'}; +Default $options string is: "!stack !icons names winfo" + =head1 OVERRIDDEN METHODS =over 4 @@ -200,7 +266,7 @@ =head1 AUTHOR -Mikhael Goikhman <[EMAIL PROTECTED]>. +Mikhael Goikhman <[EMAIL PROTECTED]>, Scott Smedley. =head1 SEE ALSO