+ my $pid;
+ # http://docstore.mik.ua/orelly/perl/cookbook/ch10_17.htm
+ local *run_process = sub {
+ $pid = fork ();
+ die "fork: $!" unless defined $pid;
+ unless ($pid) {
+ # Child.
+ POSIX::setsid ();
+ $ENV{PATH} = ".:$ENV{PATH}";
+ exec ($slide->{name});
+ die "failed to execute command: ", $slide->{name}, ": $!";
+ }
+ # Parent returns.
+ };
+ local *kill_process = sub {
+ print STDERR "sending TERM signal to process group $pid\n"
+ if $verbose;
+ kill "TERM", -$pid;
+ };
+ run_process ();
+
+ my $r = "NEXT";
+
+ my $w = Gtk2::Window->new ();
+
+ my $s = $w->get_screen;
+ $w->set_default_size ($s->get_width, -1);
+ $w->move (0, 0);
+ $w->set_decorated (0);
+
+ my $bbox = Gtk2::HButtonBox->new ();
+ $bbox->set_layout ('start');
+
+ my $bnext = Gtk2::Button->new ("Next slide");
+ $bnext->signal_connect (clicked => sub { $r = "NEXT"; $w->destroy });
+ $bnext->set_sensitive (!(exists $slide->{last}));
+ $bbox->add ($bnext);
+
+ my $bback = Gtk2::Button->new ("Back");
+ $bback->signal_connect (clicked => sub { $r = "PREV"; $w->destroy });
+ $bback->set_sensitive (!(exists $slide->{first}));
+ $bbox->add ($bback);
+
+ my $brestart = Gtk2::Button->new ("Kill & restart");
+ $brestart->signal_connect (clicked => sub {
+ kill_process ();
+ run_process ();
+ });
+ $bbox->add ($brestart);
+
+ my $bquit = Gtk2::Button->new ("Quit");
+ $bquit->signal_connect (clicked => sub { $r = "QUIT"; $w->destroy });
+ $bbox->add ($bquit);
+ $bbox->set_child_secondary ($bquit, 1);
+
+ $w->add ($bbox);
+
+ $w->signal_connect (destroy => sub {
+ Gtk2->main_quit;
+ return FALSE;
+ });
+ $w->show_all ();
+
+ Gtk2->main;
+
+ kill_process ();
+ print STDERR "returning r=$r\n" if $verbose;
+ return $r;