DentArthurDent has asked for the wisdom of the Perl Monks concerning the following question:

Howdy fellow monks:

I'm making a little tray app in perl Gtk2 that puts up a menu of different hosts that I might want a shell window to. The only problem I have with it is that the submenu arrows show up on the right instead of the left like you would expect from a tray app.

I know this is probably a setting on the menu, but I can't find an example anywhere of how to set it. Can anybody help?

If it helps, the following is my current code:
#!/usr/bin/perl -w use Glib qw/TRUE FALSE/; use Gtk2; # load the Gtk-Perl module use Gtk2::TrayIcon; use strict; # a good idea for all non-trivial Perl scripts use Data::Dumper; # # To Do: perhaps submenus for hosts within clusters? DONE!! # set_locale Gtk2; # internationalize init Gtk2; # initialize Gtk-Perl # convenience variables for true and false my $false = 0; my $true = 1; # widget creation my $top_menu = new Gtk2::Menu(); my $menu_item; my $new_submenu; my $button; my %hosts; my %proggies; my $cur_host; my $img_dir="/opt/gnome/share/icons/hicolor/16x16/stock/net/"; my $menu_x; my $menu_y; my @menu_stack; # start a new submenu sub new_submenu { # get the highest menu in the stack my $name = shift; my $cur_submenu = $menu_stack[$#menu_stack]; $new_submenu = new Gtk2::Menu(); $menu_item = Gtk2::MenuItem->new_with_label($name); $menu_item->set_submenu($new_submenu); $menu_item->show; $cur_submenu->append($menu_item); push(@menu_stack,$new_submenu); } # stop adding stuff to the most nested menu sub end_submenu { pop(@menu_stack); } sub add_new_menu_entry { my $name = shift; my $cur_menu = $menu_stack[$#menu_stack]; $menu_item = Gtk2::MenuItem->new_with_label($name); $menu_item->signal_connect(activate => \&new_shell_cb, $name); $menu_item->show; # push this item on the current menu $cur_menu->append($menu_item); } sub new_shell_cb { my $button_clicked = shift; #my $cur_item = $menu->get_active; my $host; my $label; $label = $button_clicked->get_child; if ($label->isa('Gtk2::Label')) { $cur_host = $label->get_label; } if (exists($hosts{$cur_host})) { $host = $hosts{$cur_host}; } else { $host = $cur_host; } # start the shell unless (fork) { if (defined($proggies{$cur_host})) { exec("$ENV{HOME}/shell.csh","\#0000ff",$host,"root", $proggies{$cur_host}); } else { exec("$ENV{HOME}/shell.csh","\#0000ff",$host,"root"); } } } my $tray_img = Gtk2::Image->new_from_file($img_dir."stock_internet.png +"); my $tray = Gtk2::TrayIcon->new("shells"); my $eventbox = Gtk2::EventBox->new; $eventbox->add($tray_img); $tray->add($eventbox); $tray->show_all; $eventbox->signal_connect("button-press-event", \&handle_tray_press); open(SHELLS,"<$ENV{HOME}/.shells"); my $host_info; my $name; my $ip; my $first = 1; my $proggie; my $cur_menu; push(@menu_stack,$top_menu); $cur_menu = $menu_stack[$#menu_stack]; $menu_item = Gtk2::MenuItem->new_with_label("Exit"); $menu_item->signal_connect(activate => sub { exit(0); }, "Exit"); $menu_item->show; $cur_menu->append($menu_item); while ($host_info = <SHELLS>) { chomp($host_info); # ignore leading spaces to make config file prettier $host_info =~ s/^\s+//g; ($name, $proggie, $ip) = split(/\s+/,$host_info); # never pop the top menu if ($name eq "end" && scalar(@menu_stack) > 1) { end_submenu(); next; } if ($name eq "submenu") { new_submenu($proggie); next; } if ($first == 1) { $cur_host = $name; $first = 0; } if (defined($ip)) { $hosts{$name} = $ip; } if (defined($proggie)) { $proggies{$name} = $proggie; } add_new_menu_entry($name); } close(SHELLS); # Gtk event loop Gtk2->main; # Should never get here exit( 0 ); sub handle_tray_press { my $widget = shift; my $event = shift; $menu_x = $event->x_root - $event->x; $menu_y = $event->y_root - $event->y; $top_menu->popup(undef, undef, \&position_menu, 0, $event->button, $event->time); } sub position_menu { # Shamlessly stolen from Muine :-) my $x = $menu_x; my $y = $menu_y; my $monitor = $top_menu->get_screen->get_monitor_at_point($x,$y); my $rect = $top_menu->get_screen->get_monitor_geometry($monitor); my $space_above = $y - $rect->y; my $space_below = $rect->y + $rect->height - $y; my $requisition = $top_menu->size_request(); if ($requisition->height <= $space_above || $requisition->height <= $space_below) { if ($requisition->height <= $space_below) { $y = $y + $eventbox->allocation->height; } else { $y = $y - $requisition->height; } } elsif ($requisition->height > $space_below and $requisition->height > $space_above) { if ($space_below >= $space_above) { $y = $rect->y + $rect->height - $requisition->height; } else { $y = $rect->y; } } else { $y = $rect->y; } return ($x,$y,1); }
Thanks in advance!
My mission: To boldy split infinitives that have never been split before!

Replies are listed 'Best First'.
Re: Gtk2::Menu submenu placement
by Melly (Hermit) on Mar 23, 2006 at 16:20 UTC

    Just a suggestion - are you sure that the placement of the arrows isn't dependant on how far to the right/left the system-tray icon is?

    i.e. if it's bang up against the right, the arrows may be on the left, otherwise the submenu would risk being off-screen.

    Tom Melly,
      The menu is always flush against the right edge of the screen. What you describe was kind of the behavior I expected, but didn't get.
      My mission: To boldy split infinitives that have never been split before!

        My mistake - I misread your original post.

        I shall seek redemption but I actually trying out your code.. ;)

        Update - well, maybe not. Any chance of posting a simplest-case?

        Tom Melly,
Re: Gtk2::Menu submenu placement
by zentara (Archbishop) on Mar 23, 2006 at 22:24 UTC
    I got your code to run on my system, after a bunch of changes, and I'm not sure what your problem is. If you get a "submenu" entry, the expander arrow is on the right, which is the normal for most every menu I see. Maybe I'm not setting the data up right. I'm with Melly.....can you post a self contained example, with the information in DATA or something?

    Are you looking to make the arrow on the left, or the popup to appear on the left, or what?

    I'm not really a human, but I play one on earth. flash japh