--- deliantra/Deliantra-Client/DC/UI.pm 2006/05/27 21:15:57 1.245 +++ deliantra/Deliantra-Client/DC/UI.pm 2006/05/29 02:01:56 1.255 @@ -42,6 +42,8 @@ if (length $widget->{tooltip}) { if ($TOOLTIP->{owner} != $widget) { + $TOOLTIP->hide; + $TOOLTIP->{owner} = $widget; my $tip = $widget->{tooltip}; @@ -50,15 +52,6 @@ $TOOLTIP->set_tooltip_from ($widget); $TOOLTIP->show; - - my ($x, $y) = $widget->coord2global ($widget->{w}, 0); - - ($x, $y) = $widget->coord2global (-$TOOLTIP->{w}, 0) - if $x + $TOOLTIP->{w} > $::WIDTH; - - $TOOLTIP->move ($x, $y); - $TOOLTIP->check_size; - $TOOLTIP->update; } return; @@ -177,11 +170,9 @@ $widget->{x} = int 0.5 + $widget->{x} * $sx if exists $widget->{x}; $widget->{w} = int 0.5 + $widget->{w} * $sx if exists $widget->{w}; $widget->{req_w} = int 0.5 + $widget->{req_w} * $sx if exists $widget->{req_w}; - $widget->{user_w} = int 0.5 + $widget->{user_w} * $sx if exists $widget->{user_w}; $widget->{y} = int 0.5 + $widget->{y} * $sy if exists $widget->{y}; $widget->{h} = int 0.5 + $widget->{h} * $sy if exists $widget->{h}; $widget->{req_h} = int 0.5 + $widget->{req_h} * $sy if exists $widget->{req_h}; - $widget->{user_h} = int 0.5 + $widget->{user_h} * $sy if exists $widget->{user_h}; } } @@ -216,25 +207,15 @@ Scalar::Util::weaken ($CFClient::UI::WIDGET{$self+0} = $self); if (my $layout = $CFClient::UI::LAYOUT->{$self->{name}}) { - $self->{user_x} = $layout->{x} * $::WIDTH; - $self->{user_y} = $layout->{y} * $::HEIGHT; - $self->{user_w} = ($layout->{w} != 0 ? $layout->{w} : 1) * $::WIDTH; - $self->{user_h} = ($layout->{h} != 0 ? $layout->{h} : 1) * $::HEIGHT; + $self->{req_x} = $layout->{x} * $::WIDTH; + $self->{req_y} = $layout->{y} * $::HEIGHT; + $self->{def_w} = ($layout->{w} != 0 ? $layout->{w} : 1) * $::WIDTH; + $self->{def_h} = ($layout->{h} != 0 ? $layout->{h} : 1) * $::HEIGHT; } $self } -sub toggle_visibility { - my ($self) = @_; - - if ($self->{visible}) { - $self->hide; - } else { - $self->show; - } -} - sub destroy { my ($self) = @_; @@ -244,22 +225,37 @@ sub show { my ($self) = @_; + return if $self->{parent}; $CFClient::UI::ROOT->add ($self); } -sub show_centered { +sub center { my ($self) = @_; - return if $self->{parent}; - - $self->show; $CFClient::UI::ROOT->on_post_alloc ( - "centered $self" => sub { - $self->move (($::WIDTH - $self->{w}) * 0.5, ($::HEIGHT - $self->{h}) * 0.5); + "center_$self" => sub { + $self->move (($self->{parent}{w} - $self->{w}) * 0.5, ($self->{parent}{h} - $self->{h}) * 0.5); }, ); + + $self->update; +} + +sub set_visible { + my ($self) = @_; + + return if $self->{visible}; + + $self->{root} = $self->{parent}{root}; + $self->{visible} = $self->{parent}{visible} + 1; + + $self->emit (visibility_change => 1); + + $self->realloc if !exists $self->{req_w}; + + $_->set_visible for $self->children; } sub set_invisible { @@ -267,7 +263,7 @@ return unless $self->{visible}; - # broken show/hide model + $_->set_invisible for $self->children; delete $self->{root}; delete $self->{visible}; @@ -276,13 +272,30 @@ undef $HOVER if $HOVER == $self; CFClient::UI::check_tooltip - if $CFClient::UI::TOOLTIP->{owner} == $self; + if $TOOLTIP->{owner} == $self; $self->focus_out; $self->emit (visibility_change => 0); } +sub set_visibility { + my ($self, $visible) = @_; + + return if $self->{visible} == $visible; + + $visible ? $self->hide + : $self->show; +} + +sub toggle_visibility { + my ($self) = @_; + + $self->{visible} + ? $self->hide + : $self->show; +} + sub hide { my ($self) = @_; @@ -305,10 +318,10 @@ sub set_size { my ($self, $w, $h) = @_; - $self->{user_w} = $w; - $self->{user_h} = $h; + $self->{def_w} = $w; + $self->{def_h} = $h; - $self->check_size; + $self->realloc; } sub size_request { @@ -338,7 +351,9 @@ } if ($self->{w} != $w || $self->{h} != $h) { - $CFClient::UI::ROOT->{size_alloc}{$self} = [$self, $w, $h]; + return unless $self->{visible}; + + $self->{root}->{size_alloc}{$self+0} = [$self, $w, $h]; } } @@ -346,13 +361,6 @@ # nothing to be done } -sub reconfigure { - my ($self) = @_; - - $self->check_size (1); - $self->update; -} - sub children { } @@ -439,6 +447,69 @@ sub y { $_[0]{y} = $_[1] if @_ > 1; $_[0]{y} } sub z { $_[0]{z} = $_[1] if @_ > 1; $_[0]{z} } +sub find_widget { + my ($self, $x, $y) = @_; + + return () unless $self->{can_events}; + + return $self + if $x >= $self->{x} && $x < $self->{x} + $self->{w} + && $y >= $self->{y} && $y < $self->{y} + $self->{h}; + + () +} + +sub set_parent { + my ($self, $parent) = @_; + + Scalar::Util::weaken ($self->{parent} = $parent); + + $self->set_visible if $parent->{visible}; +} + +sub connect { + my ($self, $signal, $cb) = @_; + + push @{ $self->{signal_cb}{$signal} }, $cb; +} + +sub _emit { + my ($self, $signal, @args) = @_; + + List::Util::sum map $_->($self, @args), @{$self->{signal_cb}{$signal} || []} +} + +sub emit { + my ($self, $signal, @args) = @_; + + $self->_emit ($signal, @args) + || $self->$signal (@args); +} + +sub visibility_change { + #my ($self, $visible) = @_; +} + +sub realloc { + my ($self) = @_; + + if ($self->{visible}) { + return if $self->{root}{realloc}{$self}; + + $self->{root}{realloc}{$self} = $self; + $self->{root}->update; + } else { + delete $self->{req_w}; + } +} + +sub update { + my ($self) = @_; + + $self->{parent}->update + if $self->{parent}; +} + sub draw { my ($self) = @_; @@ -485,75 +556,6 @@ warn "no draw defined for $self\n"; } -sub find_widget { - my ($self, $x, $y) = @_; - - return () unless $self->{can_events}; - - return $self - if $x >= $self->{x} && $x < $self->{x} + $self->{w} - && $y >= $self->{y} && $y < $self->{y} + $self->{h}; - - () -} - -sub set_parent { - my ($self, $parent) = @_; - - Scalar::Util::weaken ($self->{parent} = $parent); - - if ($parent->{visible} || 1) { - $self->{root} = $parent->{root}; - $self->{visible} = $parent->{visible} + 1; - - $self->emit (visibility_change => 1) - unless $self->{parent}{visible}; - } - - # TODO: req_w _does_change after ->reconfigure - $self->check_size - unless exists $self->{req_w}; - - $self->show; -} - -sub check_size { - my ($self, $forced) = @_; - - $self->{force_alloc} = 1 if $forced; - $CFClient::UI::ROOT->{check_size}{$self} = $self; -} - -sub update { - my ($self) = @_; - - $self->{parent}->update - if $self->{parent}; -} - -sub connect { - my ($self, $signal, $cb) = @_; - - push @{ $self->{signal_cb}{$signal} }, $cb; -} - -sub _emit { - my ($self, $signal, @args) = @_; - - List::Util::sum map $_->($self, @args), @{$self->{signal_cb}{$signal} || []} -} - -sub emit { - my ($self, $signal, @args) = @_; - - $self->_emit ($signal, @args) - || $self->$signal (@args); -} - -sub visibility_change { - #my ($self, $visible) = @_; -} - sub DESTROY { my ($self) = @_; @@ -658,8 +660,7 @@ @{$self->{children}}, @widgets ]; - $self->check_size (1); - $self->update; + $self->realloc; } sub children { @@ -674,8 +675,7 @@ $self->{children} = [ grep $_ != $child, @{ $self->{children} } ]; - $self->check_size (1); - $self->update; + $self->realloc; } sub clear { @@ -689,8 +689,7 @@ $_->hide; } - $self->check_size; - $self->update; + $self->realloc; } sub find_widget { @@ -753,7 +752,7 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; $self->{children}[0]->configure (0, 0, $w, $h); } @@ -780,10 +779,11 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; - $self->SUPER::size_allocate ($w, $h); - $self->update; + $self->SUPER::size_allocate ($w, $h, $changed); + $self->update + if $changed; } sub _render { @@ -837,13 +837,16 @@ sub size_request { my ($self) = @_; - @$self{qw(child_w child_h)} = @{$self->child}{qw(req_w req_h)}; + my ($w, $h) = @$self{qw(child_w child_h)} = @{$self->child}{qw(req_w req_h)}; - @$self{qw(child_w child_h)} + $w = 10 if $self->{scroll_x}; + $h = 10 if $self->{scroll_y}; + + ($w, $h) } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; $w = $self->{child_w} if $self->{scroll_x} && $self->{child_w}; $h = $self->{child_h} if $self->{scroll_y} && $self->{child_h}; @@ -940,9 +943,9 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; - $self->SUPER::size_allocate ($w, $h); + $self->SUPER::size_allocate ($w, $h, $changed); my $child = $self->{vp}->child; $self->{slider}->set_range ([$self->{slider}{range}[0], 0, $child->{h}, $self->{vp}{h}, 1]); @@ -999,15 +1002,17 @@ use CFClient::OpenGL; -my @tex = +my $bg = + new_from_file CFClient::Texture CFClient::find_rcfile "d1_bg.png", + mipmap => 1, wrap => 1; + +my @border = map { new_from_file CFClient::Texture CFClient::find_rcfile $_, mipmap => 1 } - qw(d1_bg.png d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png); + qw(d1_border_top.png d1_border_right.png d1_border_left.png d1_border_bottom.png); sub new { my $class = shift; - # TODO: user_x, user_y, overwrite moveto? - my $self = $class->SUPER::new ( bg => [1, 1, 1, 1], border_bg => [1, 1, 1, 1], @@ -1042,7 +1047,9 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; + + return unless $changed; $h -= List::Util::max 0, $self->border * 2; $w -= List::Util::max 0, $self->border * 2; @@ -1078,10 +1085,10 @@ $self->{user_x} = $wx + $dx * $mx; $self->{user_y} = $wy + $dy * $my; - $self->{user_w} = $bw + $dx * ($mx ? -1 : 1); - $self->{user_h} = $bh + $dy * ($my ? -1 : 1); + $self->{def_w} = $bw + $dx * ($mx ? -1 : 1); + $self->{def_h} = $bh + $dy * ($my ? -1 : 1); $self->move ($self->{user_x}, $self->{user_y}); - $self->check_size; + $self->realloc; }; } elsif ($lr ^ $td) { @@ -1095,8 +1102,9 @@ $self->{user_x} = $bx + $x - $ox; $self->{user_y} = $by + $y - $oy; + $self->move ($self->{user_x}, $self->{user_y}); - $self->update; + $self->realloc; }; } } @@ -1125,23 +1133,18 @@ my $border = $self->border; glColor @{ $self->{border_bg} }; - $tex[1]->draw_quad_alpha (0, 0, $w, $border); - $tex[3]->draw_quad_alpha (0, $border, $border, $ch); - $tex[2]->draw_quad_alpha ($w - $border, $border, $border, $ch); - $tex[4]->draw_quad_alpha (0, $h - $border, $w, $border); + $border[0]->draw_quad_alpha (0, 0, $w, $border); + $border[1]->draw_quad_alpha (0, $border, $border, $ch); + $border[2]->draw_quad_alpha ($w - $border, $border, $border, $ch); + $border[3]->draw_quad_alpha (0, $h - $border, $w, $border); if (@{$self->{bg}} < 4 || $self->{bg}[3]) { - my $bg = $tex[0]; - - # TODO: repeat texture not scale - my $rep_x = $cw / $bg->{w}; - my $rep_y = $ch / $bg->{h}; - glColor @{ $self->{bg} }; - $bg->{s} = $rep_x; - $bg->{t} = $rep_y; - $bg->{wrap_mode} = 1; + # TODO: repeat texture not scale + # solve this better(?) + $bg->{s} = $cw / $bg->{w}; + $bg->{t} = $ch / $bg->{h}; $bg->draw_quad_alpha ($border, $border, $cw, $ch); } @@ -1181,7 +1184,7 @@ $child->set_parent ($self); $self->{children}[$y][$x] = $child; - $self->check_size (1); + $self->realloc; } # TODO: move to container class maybe? send children a signal on removal? @@ -1196,8 +1199,7 @@ $_->hide; } - $self->check_size (1); - $self->update; + $self->realloc; } sub get_wh { @@ -1234,7 +1236,7 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; my ($ws, $hs) = $self->get_wh; @@ -1303,59 +1305,59 @@ ############################################################################# -package CFClient::UI::HBox; - -# TODO: wrap into common Box base class +package CFClient::UI::Box; our @ISA = CFClient::UI::Container::; sub size_request { my ($self) = @_; - my @alloc = map [$_->size_request], @{$self->{children}}; - - ( - (List::Util::sum map $_->[0], @alloc), - (List::Util::max map $_->[1], @alloc), - ) + $self->{vertical} + ? ( + (List::Util::max map $_->{req_w}, @{$self->{children}}), + (List::Util::sum map $_->{req_h}, @{$self->{children}}), + ) + : ( + (List::Util::sum map $_->{req_w}, @{$self->{children}}), + (List::Util::max map $_->{req_h}, @{$self->{children}}), + ) } sub size_allocate { - my ($self, $w, $h) = @_; - - ($h, $w) = ($w, $h); + my ($self, $w, $h, $changed) = @_; + my $space = $self->{vertical} ? $h : $w; my $children = $self->{children}; - my @h = map $_->{req_w}, @$children; + my @req; - my $req_h = List::Util::sum @h; - - if ($req_h > $h) { - # ah well, not enough space - $_ *= $h / $req_h for @h; + if ($self->{homogeneous}) { + @req = ($space / (@$children || 1)) x @$children; } else { - my $exp = List::Util::sum map $_->{expand}, @$children; - $exp ||= 1; - - for (0 .. $#$children) { - my $child = $children->[$_]; + @req = map $_->{$self->{vertical} ? "req_h" : "req_w"}, @$children; + my $req = List::Util::sum @req; + + if ($req > $space) { + # ah well, not enough space + $_ *= $space / $req for @req; + } else { + my $expand = (List::Util::sum map $_->{expand}, @$children) || 1; + + $space = ($space - $req) / $expand; # remaining space to give away - my $alloc_h = $h[$_]; - $alloc_h += ($h - $req_h) * $child->{expand} / $exp; - $h[$_] = $alloc_h; + $req[$_] += $space * $children->[$_]{expand} + for 0 .. $#$children; } } - CFClient::UI::harmonize \@h; + CFClient::UI::harmonize \@req; - my $y = 0; + my $pos = 0; for (0 .. $#$children) { - my $child = $children->[$_]; - my $h = $h[$_]; - $child->configure ($y, 0, $h, $w); + my $alloc = $req[$_]; + $children->[$_]->configure ($self->{vertical} ? (0, $pos, $w, $alloc) : ($pos, 0, $alloc, $h)); - $y += $h; + $pos += $alloc; } 1 @@ -1363,60 +1365,32 @@ ############################################################################# -package CFClient::UI::VBox; - -# TODO: wrap into common Box base class - -our @ISA = CFClient::UI::Container::; +package CFClient::UI::HBox; -sub size_request { - my ($self) = @_; +our @ISA = CFClient::UI::Box::; - my @alloc = map [$_->size_request], @{$self->{children}}; +sub new { + my $class = shift; - ( - (List::Util::max map $_->[0], @alloc), - (List::Util::sum map $_->[1], @alloc), + $class->SUPER::new ( + vertical => 0, + @_, ) } -sub size_allocate { - my ($self, $w, $h) = @_; - - Carp::confess "negative size" if $w < 0 || $h < 0;#d# - - my $children = $self->{children}; - - my @h = map $_->{req_h}, @$children; - - my $req_h = List::Util::sum @h; - - if ($req_h > $h) { - # ah well, not enough space - $_ *= $h / $req_h for @h; - } else { - my $exp = List::Util::sum map $_->{expand}, @$children; - $exp ||= 1; - - for (0 .. $#$children) { - my $child = $children->[$_]; - - $h[$_] += ($h - $req_h) * $child->{expand} / $exp; - } - } +############################################################################# - CFClient::UI::harmonize \@h; +package CFClient::UI::VBox; - my $y = 0; - for (0 .. $#$children) { - my $child = $children->[$_]; - my $h = $h[$_]; - $child->configure (0, $y, $w, $h); +our @ISA = CFClient::UI::Box::; - $y += $h; - } +sub new { + my $class = shift; - 1 + $class->SUPER::new ( + vertical => 1, + @_, + ) } ############################################################################# @@ -1489,8 +1463,8 @@ $self->{layout} = new CFClient::Layout if $self->{layout}->is_rgba; $self->{layout}->set_text ($text); + $self->realloc; $self->update; - $self->check_size; } sub set_markup { @@ -1504,8 +1478,8 @@ $self->{layout} = new CFClient::Layout $rgba if $self->{layout}->is_rgba != $rgba; $self->{layout}->set_markup ($markup); + $self->realloc; $self->update; - $self->check_size; } sub size_request { @@ -1536,9 +1510,10 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; - delete $self->{texture}; + delete $self->{texture} + if $changed; } sub set_fontsize { @@ -1547,8 +1522,7 @@ $self->{fontsize} = $fontsize; delete $self->{texture}; - $self->update; - $self->check_size; + $self->realloc; } sub _draw { @@ -1638,8 +1612,8 @@ $self->{cursor} = length $text; $self->_set_text ($text); - $self->update; - $self->check_size; + + $self->realloc; } sub get_text { @@ -1682,8 +1656,8 @@ } $self->_set_text ($text); - $self->update; - $self->check_size; + + $self->realloc; } sub focus_in { @@ -2200,6 +2174,8 @@ $self } +sub changed { } + sub set_range { my ($self, $range) = @_; @@ -2398,9 +2374,11 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; + + $self->SUPER::size_allocate ($w, $h, $changed); - $self->SUPER::size_allocate ($w, $h); + return unless $changed; $self->{layout}->set_font ($self->{font}) if $self->{font}; $self->{layout}->set_height ($self->{fontsize} * $::FONTSIZE); @@ -2652,9 +2630,29 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; + + return unless $changed; - $self->SUPER::size_allocate ($w - 4, $h - 4); + $self->SUPER::size_allocate ($w - 4, $h - 4, $changed); +} + +sub visibility_change { + my ($self, $visible) = @_; + + return unless $visible; + + $self->{root}->on_post_alloc ("move_$self" => sub { + my $widget = $self->{owner} + or return; + + my ($x, $y) = $widget->coord2global ($widget->{w}, 0); + + ($x, $y) = $widget->coord2global (-$self->{w}, 0) + if $x + $self->{w} > $::WIDTH; + + $self->move ($x, $y); + }); } sub _draw { @@ -2681,6 +2679,7 @@ glEnd; glTranslate 2 - 0.375, 2 - 0.375; + $self->SUPER::_draw; } @@ -2806,11 +2805,6 @@ } } -sub size_request { - my ($self) = @_; - ($self->{req_w}, $self->{req_h}); -} - ############################################################################# package CFClient::UI::Menu; @@ -3004,10 +2998,14 @@ sub new { my $class = shift; - $class->SUPER::new ( + my $self = $class->SUPER::new ( visible => 1, @_, - ) + ); + + Scalar::Util::weaken ($self->{root} = $self); + + $self } sub configure { @@ -3017,10 +3015,12 @@ $self->{h} = $h; } -sub check_size { +sub reconfigure { my ($self) = @_; - $self->size_allocate ($self->{w}, $self->{h}) + $self->SUPER::reconfigure; + + $self->size_allocate ($self->{w}, $self->{h}, 1) if $self->{w}; } @@ -3031,7 +3031,7 @@ } sub size_allocate { - my ($self, $w, $h) = @_; + my ($self, $w, $h, $changed) = @_; for my $child ($self->children) { my ($X, $Y, $W, $H) = @$child{qw(x y req_w req_h)}; @@ -3042,8 +3042,7 @@ $Y = $child->{req_y} > 0 ? $child->{req_y} : $h - $H - $child->{req_y} + 1 if exists $child->{req_y}; - $X = $self->{user_x} if exists $self->{user_x}; - $Y = $self->{user_y} if exists $self->{user_y}; + #delete @$child{qw(req_x req_y)};#d# def_x, def_y $X = List::Util::max 0, List::Util::min $w - $W, int $X + 0.5; $Y = List::Util::max 0, List::Util::min $h - $H, int $Y + 0.5; @@ -3067,19 +3066,12 @@ sub update { my ($self) = @_; - $self->check_size; $::WANT_REFRESH++; } sub add { my ($self, @children) = @_; - for (my @widgets = @children; my $w = pop @widgets; ) { - push @widgets, $w->children; - $w->{root} = $self; - $w->{visible} = $self->{visible} + 1; - } - for my $child (@children) { $child->{is_toplevel} = 1; @@ -3123,50 +3115,53 @@ for values %{delete $self->{refresh_hook}}; } - if ($self->{check_size}) { + if ($self->{realloc}) { my @queue; - for (;;) { - if ($self->{check_size}) { + while () { + if ($self->{realloc}) { #TODO use array-of-depth approach @queue = sort { $a->{visible} <=> $b->{visible} } - @queue, values %{delete $self->{check_size}}; + @queue, values %{delete $self->{realloc}}; } my $widget = pop @queue || last; - defined $widget->{visible} or last; # do not resize invisible widgets + $widget->{visible} or last; # do not resize invisible widgets - my ($w, $h) = $widget->{user_w} && $widget->{user_h} - ? @$widget{qw(user_w user_h)} + my ($w, $h) = $widget->{def_w} && $widget->{def_h} + ? @$widget{qw(def_w def_h)} : $widget->size_request; - if (delete $widget->{force_alloc} - or $w != $widget->{req_w} or $h != $widget->{req_h}) { - Carp::confess "$widget: size_request is negative" if $w < 0 || $h < 0;#d# + Carp::confess "$widget: size_request is negative" if $w < 0 || $h < 0;#d# - $widget->{req_w} = $w; - $widget->{req_h} = $h; + $widget->{req_w} = $w; + $widget->{req_h} = $h; - $self->{size_alloc}{$widget} = [$widget, $widget->{w} || $w, $widget->{h} || $h]; + $self->{size_alloc}{$widget} = [$widget, $widget->{w} || $w, $widget->{h} || $h]; - $widget->{parent}->check_size - if $widget->{parent}; - } + push @queue, $widget->{parent} + if $widget->{parent}; } } - while ($self->{size_alloc}) { - for (values %{delete $self->{size_alloc}}) { - my ($widget, $w, $h) = @$_; + while (my $size_alloc = delete $self->{size_alloc}) { + my @queue = sort $b->[0]{visible} <=> $a->[0]{visible}, + values %$size_alloc; + + while () { + my ($widget, $w, $h) = @{ pop @queue or last }; $w = 0 if $w < 0; $h = 0 if $h < 0; + my $changed = $widget->{w} != $w || $widget->{h} != $h; + $widget->{w} = $w; $widget->{h} = $h; - $widget->emit (size_allocate => $w, $h); + + $widget->emit (size_allocate => $w, $h, $changed); } }