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

$top->Button( -activebackground => 'green', -text => "GO!", -command => sub { my @selected = $lb->curselection; foreach (@selected){ chomp$_; push @systemNames, "$systems[$_]";} my $goto = join(" ",@systemNames); my $proc2 = $mw => Proc::Background->new("cssh -G -T 'OOPC +SSH' $goto"); @systemNames = (); } )->pack( -before => $lb, -side => 'bottom', -fill => 'both'); MainLoop;

The problem I am having is, the call to CSSH is a system call, I then lose the ability to control the window placement of the 10-100 or so windows that open. (Trying to do this without Compiz window placement) Is there any cssh/ssh TK module or ability that allows me to just say place open window 1 to x,y - window 2 x,y - window 3 x,y - etc. or pipe the system call to a widget that can be controlled via grid or frame?

Replies are listed 'Best First'.
Re: Perl/Tk + CSSH
by zentara (Cardinal) on Feb 07, 2012 at 11:41 UTC
    s there any cssh/ssh TK module or ability that allows me to just say place open window 1 to x,y - window 2 x,y - window 3 x,y - etc. or pipe the system call to a widget that can be controlled via grid or frame?

    Yes to all those questions. :-)

    Considering you are using Proc::Background to run your c based ssh connections, your best bet for this style of code may be to make individual mainwindows for each connection, otherwise you would make one mainwindow, and the rest would be dependent toplevels. If you go the toplevel route, you may still run into the blocking of the eventloop. The best solution would be to run each ssh instance in it's own thread, and display all the input/output in a set of Text widgets.

    But lets just get back to just opening multiple mainwidows( independent eventloops) and controlling their placements. It's quite simple. The general way to do it is:

    $widget -> geometry("wxh+x+y") width (w), height (h), yposition (x), and yposition (y) can be set as +string using above syntax. Position and size can be set independently, e.g. "+x+y" or "100x200". Without a parameter the actual size and position is returned in the ab +ove syntax. Attention: Values are "0" before the widget has manifested itself on t +he screen; use update() or waitVisibility() if unsure. Note: All values are in pixels. The screensize can be requested using $top -> screenwidth() and $top -> screenheight() Thus (e.g.): $h = $top->screenheight() - 40; $w = $top->screenwidth() - 40; $top -> geometry("${w}x$h+20+20") # if you specify -0-0 for position, you anchor in the lower right corn +er
    Here is a rudimentary example, almost a Window Bomb. :-)
    #!/usr/bin/perl use warnings; use strict; use Tk; my ($x,$y,$count) = (0,0,0); for(1..15) { $count++; if (fork == 0) { #$widget->geometry("wxh+x+y") my $top = new MainWindow; $top->geometry('100x100'.'+'.$x.'+'.$y); $top->Button(-command => sub { warn "top$_" })->pack; MainLoop; CORE::exit(); } if( $count % 3 == 0) {$y += 150; $x = 0 } $x += 150; } MainLoop; #If you need start a new process from one of the child processes, then #you have to establish some kind of IPC (e.g. pipes) between the child #and parent. #I the launched task running another Perl/Tk module or function or a #complete new program? In the latter case, you should just use fork an +d #exit/system and do not forget to use CORE::exit instead of exit in th +e #child process (according to the FAQ). Perl/Tk forks are somewhat more #difficult. You have to make sure that you fork off the process which #does not have a created a MainWindow itself. This will work fine:

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

      Oh Wise one, Your response is greatly appreciated. I am currently combing through your explanation/examples. I think this is what I am looking for, but will need to see how its implemented into my code. Your example worked like a charm and will post back with my success/failure! Thanks again for quick turn around!

      Ok, So I had the chance to review and here is what I have come up with. I took your example and mashed a chunk of my code that has my CSSH call, to see if I could manage the windows via example code.

      #!/usr/bin/perl -w use warnings; use strict; use Tk; my ($x,$y,$count) = (0,0,0); my @systems = qw(system1 system2 system3 system4 system5 system7); foreach(@systems) { $count++; if (fork == 0) { #$widget->geometry("wxh+x+y") my $top = new MainWindow; $top->geometry('100x100'.'+'.$x.'+'.$y); $top => "cssh -G -T 'OOPCSSH' -l username $_"; ##MY PROBLEM LIES H +ERE. If I simply `the command/call` it runs but still no placement co +ntrol. $top->Button(-command => sub { warn "top$_" })->pack; MainLoop; CORE::exit(); } if( $count % 3 == 0) {$y += 150; $x = 0 } $x += 150; } MainLoop;

      Since I am calling cssh, what it is actually doing is opening up a seperate XTERM window for each connection in which I can control each window with one control window. Essentially calling a seperate program all together, your example actually cleared up a previous issue I had but not quite this one, as I still cannot control the placement of the "outside" program/call. I would like to be able to place the XTERM windows that CSSH opens or use a CSSH module to do the work inside the program. Checking CPAN I didn't see what I was looking for.

        as I still cannot control the placement of the "outside" program/call. I would like to be able to place the XTERM windows that CSSH opens

        That can be done with the xterm options.

        See "xterm -h" for all the options. To execute cssh in that xterm, use the -e option, like " xterm -fn 10x20 -geometry '16x19+0+20' -e CSSH @CSSHOPTIONS "

        #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = tkinit; $mw->Button(-text=>"Xterm",-command=> [\&go])->pack; $mw->Button(-text=>"Xterm with attributes ", -command=>[\&go, q(-fn 10x20 -geometry '16x19+0+20')])->pac +k; MainLoop; sub go { print "@_\n"; my $xoptions = shift || ''; local $SIG{CHLD} = 'IGNORE'; # don't wait for child # exit status. avoids # zombies. die "fork failed: $!" unless defined(my $pid = fork); return if $pid; exec("xterm $xoptions"); warn "exec failed: $!"; CORE::exit(1); }

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh
Re: Perl/Tk + CSSH
by zentara (Cardinal) on Feb 08, 2012 at 11:34 UTC
    It dawned on me, that there is another option which you may be looking for.... the xid option. Some programs, will have the " into an xwindow id " option. It allows you to open a frame in Tk or Gtk2, then get its X window id, then specify that as an option to xterm. See embedding xterm into a Tk app for example.

    Here is the simplest example possible. When doing this sort of thing, you may experience glitches in keyboard or mouse focus, but you likely will be lucky.

    #!/usr/bin/perl use strict; use Tk; my $mw = MainWindow->new( -bg => 'white' ); $mw->geometry('400x400' . '+100+100'); my $frame1 = $mw->Frame( -height => 30, -bg => 'lightblue', )->pack( -fill => 'x', -side => 'top' ); my $frame; my $button = $frame1->Button( -text => 'Open window', -command => sub { open_w($frame) }, )->pack; $frame = $mw->Frame( -container => 1, -bg => 'white', -relief => 'sunken', -bd => 2, )->pack( -fill => 'y', -side => 'left' ); MainLoop(); sub open_w { my ($f) = @_; my $id = sprintf hex $f->id; my $t = $mw->Toplevel( -use => $id ); system("xterm -into $id &"); }

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

      You truly are a Monk among Monks.. :p Packing the geometry in the command was brilliant! I like the sound of the xid option, gonna play with both and will let you know what road I traveled! Thanks again for the knowledge BOMB!

        I resolved this by using a little perl foo..

        Instead of controlling the windows via Perl/TK - I opted to look into the window manager itself and what I found was..

        'wmctrl' is a window manager for Unix, once installed I was able to run wmctrl -l for a window listing - I then was able to manipulate where the windows were placed via wmctrl.

        (eg. `wmctrl -i -r '$e' -e 0,$x,$y,-1,-1`;)

        $e = window ID - $x,$y = X and Y window positioning found with xwininfo

        does use a system call, but much easier than trying to control a call outside of the app.