… | |
… | |
16 | our $TOOLTIP; |
16 | our $TOOLTIP; |
17 | our $BUTTON_STATE; |
17 | our $BUTTON_STATE; |
18 | |
18 | |
19 | our %WIDGET; # all widgets, weak-referenced |
19 | our %WIDGET; # all widgets, weak-referenced |
20 | |
20 | |
21 | our $TOOLTIP_WATCHER = EV::timer_ns 0, 1/60, sub { |
21 | our $TOOLTIP_WATCHER = EV::timer_ns 0, 0.03, sub { |
22 | $_[0]->stop; |
22 | $_[0]->stop; |
23 | |
23 | |
24 | if (!$GRAB) { |
24 | if (!$GRAB) { |
25 | for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { |
25 | for (my $widget = $HOVER; $widget; $widget = $widget->{parent}) { |
26 | if (length $widget->{tooltip}) { |
26 | if (length $widget->{tooltip}) { |
… | |
… | |
139 | my $grab = $GRAB; undef $GRAB; |
139 | my $grab = $GRAB; undef $GRAB; |
140 | $grab->update if $grab; |
140 | $grab->update if $grab; |
141 | $GRAB->update if $GRAB; |
141 | $GRAB->update if $GRAB; |
142 | |
142 | |
143 | check_hover $widget; |
143 | check_hover $widget; |
144 | $TOOLTIP_WATCHER->trigger; |
144 | $TOOLTIP_WATCHER->invoke; |
145 | } |
145 | } |
146 | } |
146 | } |
147 | |
147 | |
148 | sub feed_sdl_motion_event { |
148 | sub feed_sdl_motion_event { |
149 | my ($ev) = @_; |
149 | my ($ev) = @_; |
… | |
… | |
309 | delete $self->{root}; |
309 | delete $self->{root}; |
310 | |
310 | |
311 | undef $GRAB if $GRAB == $self; |
311 | undef $GRAB if $GRAB == $self; |
312 | undef $HOVER if $HOVER == $self; |
312 | undef $HOVER if $HOVER == $self; |
313 | |
313 | |
314 | $CFPlus::UI::TOOLTIP_WATCHER->trigger |
314 | $CFPlus::UI::TOOLTIP_WATCHER->invoke |
315 | if $TOOLTIP->{owner} == $self; |
315 | if $TOOLTIP->{owner} == $self; |
316 | |
316 | |
317 | $self->emit ("focus_out"); |
317 | $self->emit ("focus_out"); |
318 | $self->emit (visibility_change => 0); |
318 | $self->emit (visibility_change => 0); |
319 | } |
319 | } |
… | |
… | |
338 | sub hide { |
338 | sub hide { |
339 | my ($self) = @_; |
339 | my ($self) = @_; |
340 | |
340 | |
341 | $self->set_invisible; |
341 | $self->set_invisible; |
342 | |
342 | |
|
|
343 | # extra $parent copy for 5.8.8+ bug workaround |
|
|
344 | # (otherwise $_[0] in remove gets freed |
|
|
345 | if (my $parent = $self->{parent}) { |
343 | $self->{parent}->remove ($self) |
346 | $parent->remove ($self); |
344 | if $self->{parent}; |
347 | } |
345 | } |
348 | } |
346 | |
349 | |
347 | sub move_abs { |
350 | sub move_abs { |
348 | my ($self, $x, $y, $z) = @_; |
351 | my ($self, $x, $y, $z) = @_; |
349 | |
352 | |
… | |
… | |
440 | |
443 | |
441 | $self->{tooltip} = $tooltip; |
444 | $self->{tooltip} = $tooltip; |
442 | |
445 | |
443 | if ($CFPlus::UI::TOOLTIP->{owner} == $self) { |
446 | if ($CFPlus::UI::TOOLTIP->{owner} == $self) { |
444 | delete $CFPlus::UI::TOOLTIP->{owner}; |
447 | delete $CFPlus::UI::TOOLTIP->{owner}; |
445 | $CFPlus::UI::TOOLTIP_WATCHER->trigger; |
448 | $CFPlus::UI::TOOLTIP_WATCHER->invoke; |
446 | } |
449 | } |
447 | } |
450 | } |
448 | |
451 | |
449 | # translate global coordinates to local coordinate system |
452 | # translate global coordinates to local coordinate system |
450 | sub coord2local { |
453 | sub coord2local { |
451 | my ($self, $x, $y) = @_; |
454 | my ($self, $x, $y) = @_; |
452 | |
455 | |
453 | Carp::confess unless $self->{parent};#d# |
456 | return (undef, undef) unless $self->{parent}; |
454 | |
457 | |
455 | $self->{parent}->coord2local ($x - $self->{x}, $y - $self->{y}) |
458 | $self->{parent}->coord2local ($x - $self->{x}, $y - $self->{y}) |
456 | } |
459 | } |
457 | |
460 | |
458 | # translate local coordinates to global coordinate system |
461 | # translate local coordinates to global coordinate system |
459 | sub coord2global { |
462 | sub coord2global { |
460 | my ($self, $x, $y) = @_; |
463 | my ($self, $x, $y) = @_; |
461 | |
464 | |
462 | Carp::confess unless $self->{parent};#d# |
465 | return (undef, undef) unless $self->{parent}; |
463 | |
466 | |
464 | $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y}) |
467 | $self->{parent}->coord2global ($x + $self->{x}, $y + $self->{y}) |
465 | } |
468 | } |
466 | |
469 | |
467 | sub invoke_focus_in { |
470 | sub invoke_focus_in { |
… | |
… | |
3673 | ); |
3676 | ); |
3674 | |
3677 | |
3675 | if ($self->{anim} && $self->{animspeed}) { |
3678 | if ($self->{anim} && $self->{animspeed}) { |
3676 | CFPlus::weaken (my $widget = $self); |
3679 | CFPlus::weaken (my $widget = $self); |
3677 | |
3680 | |
3678 | $widget->{animspeed} = List::Util::max 0.05, $widget->{animspeed}; |
3681 | $self->{animspeed} = List::Util::max 0.05, $self->{animspeed}; |
3679 | $widget->{anim_start} = $self->{animspeed} * int EV::now / $self->{animspeed}; |
3682 | $self->{timer} = EV::periodic_ns 0, $self->{animspeed}, undef, sub { |
3680 | $self->{timer} = EV::timer_ns 0, 0, sub { |
|
|
3681 | return unless $::CONN; |
3683 | return unless $::CONN; |
3682 | |
3684 | |
3683 | my $w = $widget |
3685 | my $w = $widget |
3684 | or return; |
3686 | or return; |
3685 | |
3687 | |
… | |
… | |
3702 | my ($self) = @_; |
3704 | my ($self) = @_; |
3703 | |
3705 | |
3704 | return unless $self->{timer}; |
3706 | return unless $self->{timer}; |
3705 | |
3707 | |
3706 | if ($self->{visible}) { |
3708 | if ($self->{visible}) { |
3707 | $self->{timer}->set ( |
|
|
3708 | $self->{anim_start} |
|
|
3709 | + $self->{animspeed} |
|
|
3710 | * int 1.5 + (EV::now - $self->{anim_start}) / $self->{animspeed} |
|
|
3711 | ); |
|
|
3712 | $self->{timer}->start; |
3709 | $self->{timer}->start; |
3713 | } else { |
3710 | } else { |
3714 | $self->{timer}->stop; |
3711 | $self->{timer}->stop; |
3715 | } |
3712 | } |
3716 | } |
3713 | } |
… | |
… | |
4369 | } |
4366 | } |
4370 | |
4367 | |
4371 | sub update { |
4368 | sub update { |
4372 | my ($self) = @_; |
4369 | my ($self) = @_; |
4373 | |
4370 | |
4374 | $::WANT_REFRESH->start; |
4371 | $::WANT_REFRESH = 1; |
4375 | } |
4372 | } |
4376 | |
4373 | |
4377 | sub add { |
4374 | sub add { |
4378 | my ($self, @children) = @_; |
4375 | my ($self, @children) = @_; |
4379 | |
4376 | |