--- /dev/null
+package Display::Notifications;
+
+use Clutter;
+use Set::Object;
+
+my $delay = 15;
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+
+ my $self = {};
+
+ $self->{'blocks'} = Set::Object->new();
+
+ bless ($self, $class);
+ return $self;
+}
+
+sub add {
+ my ($self, $notification) = @_;
+
+ my $block = Clutter::Group->new();
+
+ my $bg = Clutter::Rectangle->new(Clutter::Color->parse('Black'));
+ $bg->set_width($self->{'stage'}->get_width() - 40);
+ $bg->set_opacity(100);
+
+ $block->add($bg);
+ $block->add($notification);
+
+ $bg->set_height($notification->get_height() + 10);
+ $bg->set_anchor_point(1, $bg->get_height());
+ $bg->set_position(10, $self->{'stage'}->get_height() - 10);
+
+ $notification->set_anchor_point(1, $notification->get_height());
+ $notification->set_position(20, $self->{'stage'}->get_height() - 20);
+
+ my $expire = time() + $delay;
+
+ $self->{'blocks'}->add( {
+ 'expire' => $expire,
+ 'block' => $block
+ });
+
+ $self->{'stage'}->add($block);
+ my $effect = Clutter::EffectTemplate->new_for_duration(1000, 'main::smoothstep_inc');
+ my $timeline = Clutter::Effect->fade($effect, $block, 255);
+ $timeline->start();
+
+ $self->{'stage'}->delay_add(notification_expire, $expire, $self);
+}
+
+sub expire {
+ my $self = shift;
+
+ for my $block ($self->{'blocks'}->members()) {
+ if ($block->expire <= time()) {
+ $self->{'stage'}->remove($block->{'block'});
+ $self->{'blocks'}->remove($block);
+ }
+ }
+}
+
+1;