The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl -w

# Copyright 2008, 2009, 2010 Kevin Ryde

# This file is part of Gtk2-Ex-MenuView.
#
# Gtk2-Ex-MenuView is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3, or (at your option) any later
# version.
#
# Gtk2-Ex-MenuView is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with Gtk2-Ex-MenuView.  If not, see <http://www.gnu.org/licenses/>.


# Usage: perl screenshot.pl [outputfile.png]
#
# Popup a MenuView and write it to the given output file in PNG format.
# The default output file is /tmp/screenshot.png
#
# Must manually wave the mouse over the submenu to make it display.  Then
# there's some weirdness needing $submenu->popup before its $submenu->window
# is set to get its root position ...

use 5.010;
use strict;
use warnings;
use File::Basename;
use FindBin;
use POSIX;
use Gtk2 1.220 '-init';
use Gtk2::Ex::MenuView;
use Gtk2::Ex::WidgetBits;


# PNG spec 11.3.4.2 suggests RFC822 (or rather RFC1123) for CreationTime
use constant STRFTIME_FORMAT_RFC822 => '%a, %d %b %Y %H:%M:%S %z';

my $progname = $FindBin::Script; # basename part
print "progname '$progname'\n";
my $output_filename = (@ARGV >= 1 ? $ARGV[0] : '/tmp/screenshot.png');

my $treestore = Gtk2::TreeStore->new ('Glib::String');
foreach my $str ('Row Zero',
                 'Row One',
                 'Row Two',
                 'Row Three',
                 'Row Four') {
  $treestore->set ($treestore->append(undef), 0 => $str);
}
{
  my $iter = $treestore->iter_nth_child (undef, 2);
  $treestore->insert_with_values ($iter, 9999, 0 => 'Sub-Row One');
  $treestore->insert_with_values ($iter, 9999, 0 => 'Sub-Row Two');
}

my $toplevel = Gtk2::Window->new('toplevel');
$toplevel->modify_bg ('normal', Gtk2::Gdk::Color->parse('black'));
$toplevel->set_default_size (500, 500);
$toplevel->signal_connect (destroy => sub { Gtk2->main_quit });
$toplevel->show_all;

my $menuview = Gtk2::Ex::MenuView->new (model => $treestore);

$menuview->signal_connect (item_create_or_update => \&do_item_create_or_update);
sub do_item_create_or_update {
  my ($menuview, $item, $treestore, $path, $iter) = @_;
  return Gtk2::MenuItem->new_with_label ($treestore->get_value ($iter, 0));
}

$toplevel->signal_connect
  (map_event => sub {
     $menuview->popup (undef, undef,
                       \&position_in_toplevel, undef,
                       1, 0);
     return Gtk2::EVENT_PROPAGATE;
   });
sub position_in_toplevel {
  my ($x, $y) = Gtk2::Ex::WidgetBits::get_root_position($toplevel);
  $x += 10;
  $y += 10;
  print "popup position $x,$y\n";
  return ($x, $y);
}

$menuview->signal_connect
  (map_event => sub {
     Glib::Timeout->add (3000, \&screenshot);
     return Gtk2::EVENT_PROPAGATE;
   });

sub screenshot {
  # system "xwd -id ".$toplevel->window->XID." >/tmp/screenshot.xwd";
  #      system "xwd -root >/tmp/screenshot.xwd";
  #      system "convert /tmp/screenshot.xwd /tmp/screenshot.png";
  # system "convert -crop 27,65,115,116 /tmp/screenshot.xwd /tmp/screenshot.png";
  my ($x, $y) = Gtk2::Ex::WidgetBits::get_root_position ($toplevel);

  my ($mx, $my) = Gtk2::Ex::WidgetBits::get_root_position ($menuview);
  print "menuview at $mx,$my\n";
  my ($mw, $mh) = $menuview->window->get_size;
  my $rx = $mx + $mw;
  my $ry = $my + $mh;

  my $submenu = $menuview->item_at_indices(2)->get_submenu;
  $submenu->popup (undef,undef,undef,undef,1,0);
  my $window = $submenu->window;
  { my ($sx, $sy) = Gtk2::Ex::WidgetBits::get_root_position ($submenu);
    print "submenu at ",($sx//'undef'),",",($sy//'undef'),
      " ",($window//'nowin'),"\n"; }
  my $req = $submenu->size_request;
  $rx += $req->width;

  $rx += 8;
  $ry += 10;
  my $width = $rx - $x;
  my $height = $ry - $y;

  my $screen = $toplevel->get_screen;
  my $rootwin = $screen->get_root_window;
  my $pixbuf = Gtk2::Gdk::Pixbuf->get_from_drawable ($rootwin,
                                                     undef, # colormap
                                                     $x,$y, 0,0,
                                                     $width, $height);
  $pixbuf->save
    ($output_filename, 'png',
     'tEXt::Title'         => 'MenuView Screenshot',
     'tEXt::Author'        => 'Kevin Ryde',
     'tEXt::Copyright'     => 'Copyright 2010 Kevin Ryde',
     'tEXt::Creation Time' => POSIX::strftime (STRFTIME_FORMAT_RFC822,
                                               localtime(time)),
     'tEXt::Description'   => 'A sample screenshot of a Gtk2::Ex::MenuView display',
     'tEXt::Software'      => "Generated by $progname",
     'tEXt::Homepage'      => 'http://user42.tuxfamily.org/gtk2-ex-menuview/index.html',
     # must be last or gtk 2.18 botches the text keys
     compression           => 9,
    );
  print "wrote $output_filename\n";

  Gtk2->main_quit;
  return 0; # Glib::SOURCE_REMOVE
}

$toplevel->show_all;
Gtk2->main;
exit 0



__END__

Glib::Timeout->add
  (1000,
   sub {
     my $submenu = $menuview->item_at_indices(2,0)->get_parent;
     $submenu->show_all;
   });


#        if (my $window = $submenu->window) {
#          ($mx, $my) = Gtk2::Ex::WidgetBits::get_root_position ($submenu);
#          ($mw, $mh) = $window->get_size;
#          $rx = max ($rx, $mx + $mw);
#          $ry = max ($ry, $mx + $mw);
#        }
#      }
     #      my $mpixbuf = Gtk2::Gdk::Pixbuf->get_from_drawable
     #        ($menuview->window,
     #         undef, # colormap
     #         0,0, 0,0,
     #         $menuview->window->get_size);
     #
     #      {
     #        my ($mx, $my) = Gtk2::Ex::WidgetBits::get_root_position($menuview);
     #        my $rx = $mx - $x;
     #        my $ry = $my - $y;
     #        print "at $rx,$ry\n";
     #        $mpixbuf->composite ($pixbuf,
     #                             $rx,$ry,$mpixbuf->get_width,$mpixbuf->get_height,
     #                             $rx,$ry,1,1,
     #                             'nearest',
     #                             255);
     #      }
     #          my $spixbuf = Gtk2::Gdk::Pixbuf->get_from_drawable
     #            ($window,
     #             undef, # colormap
     #             0,0, 0,0,
     #             $window->get_size);
     #
     #          {
     #            my ($mx, $my) = Gtk2::Ex::WidgetBits::get_root_position($submenu);
     #            my $rx = $mx-$x;
     #            my $ry = $my-$y;
     #            print "submenu at $rx,$ry\n";
     #            $spixbuf->composite ($pixbuf,
     #                                 $rx,$ry,$mpixbuf->get_width,$mpixbuf->get_height,
     #                                 $rx,$ry,1,1,
     #                                 'nearest',
     #                                 255);
     #          }
     #        }
     #      }

     #      my ($width, undef) = Gtk2::Ex::WidgetBits::get_root_position($submenu);
     #      $width -= $x;
     #      $width += $submenu->allocation->width + 10;
     #
     #      my (undef, $height) = Gtk2::Ex::WidgetBits::get_root_position($menuview);
     #      $height -= $y;
     #      $height += $menuview->allocation->height + 10;
     #
     #      print "$x,$y ${width}x$height\n";

# Glib::Timeout->add
#   (1000,
#    sub {
#      my $item = $menuview->item_at_indices(2);
#      print "item 2: $item ",$item->get_child->get_text, "\n";
#      # $item->get_submenu->popup ($menuview, $item, undef, undef, 0, 0);
#      # $item->activate;
#
#      Gtk2::Ex::WidgetBits::warp_pointer ($item->get_child, 200, 200);
#
#      #      my ($x, $y) = Gtk2::Ex::WidgetBits::get_root_position($menuview);
#      #      print "menu position $x,$y\n";
#      #      ($x, $y) = Gtk2::Ex::WidgetBits::get_root_position($item);
#      #      print "item position $x,$y\n";
#      #      print "item alloc ",$item->get_child->allocation->x,",",$item->get_child->allocation->y,"\n";
#      #      $x += 40;
#      #      $y += 45;
#      #      my $screen = $item->get_screen;
#      #      my $display = $screen->get_display;
#      #      $display->warp_pointer ($screen, $x, $y);
#    });
# Glib::Timeout->add
#   (3500,
#    sub {
#      my $item = $menuview->item_at_indices(2);
#      Gtk2::Ex::WidgetBits::warp_pointer ($item->get_child, 40,45);
#    });