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

I'm in a situation where I would like to do a Tk::exit(0) if any key is pressed or if any mouse movement occurs. I glanced through Mastering Perl/Tk but this situation is not typical so is not really covered. Is there a way to bind to all keys? Is there a way to bind to mouse movement even if the cursor is not over the MainWindow (or any widgets)? Is there a way to key off of any user input event?

As you may guess, this is screensaver related. For thin client users we disconenct sessions when the screensaver is supposed to kick off. What I'd like to do is give users an easy and convenient way to keep the session active. Think of working on your PC and noticing a warning popping up on your Sun Ray out of the corner of your eye. It would be really nice if you could tap any key or do a quick tap to the mouse to keep it alive, right?

Note: I have something that works off of the ENTER key or if they click a button. I'm just looking for guidance for binding to any user input. And in case it matters I'm using a grid layout.

Man, I'm losing my touch. I need to go back to BOFH training!! Caring about the users!! Oh the SHAME!!! ;-)
  • Comment on Perl/Tk: Is there a way to key off of any user input event?

Replies are listed 'Best First'.
Re: Perl/Tk: Is there a way to key off of any user input event?
by rcseege (Pilgrim) on Oct 14, 2006 at 07:09 UTC

    Do you mean something like this? I'm not sure I completely understand what you want to achieve.

    use Tk; my $mw = MainWindow->new; $mw->bind('<KeyPress>', \&keyPress); $mw->withdraw; my ($lastX, $lastY); $mw->repeat(400, [\&checkMouse, \$lastX, \$lastY]); $mw->focusForce; MainLoop; sub quit { print "User triggered event -- exiting!\n"; exit; } sub checkMouse { my ($lastX, $lastY) = @_; my $x = $mw->pointerx; my $y = $mw->pointery; $$lastX = $x unless defined $$lastX; $$lastY = $y unless defined $$lastY; quit() if $x != $$lastX; quit() if $y != $$lastY; } sub keyPress { quit(); }

    Other ideas... if you're using X-Windows, you might have a look at X11-IdleTime, you could call that from the repeat sub. You might also tie something in to your screensaver hook, so that it pops open a window, displays it and acts as a kind of an alert asking the user if he wants to keep the user session.

    You'll probably want to build some sort of timer in case the user does nothing, and allow the session to die. I'm generally pretty leery about hacks designed to keep user sessions open. of thing. Having sessions expire is a good thing, although if that session time is too short, then it can be irritating. Too long, and it can effectively be a memory leak.

    Rob
      If you're looking for any mouse movement, you could also just bind to the "<Motion>" event.  That would simplify your code even more:
      use Tk; use strict; use warnings; my $mw = MainWindow->new; $mw->bind('<KeyPress>', \&keyPress); $mw->bind('<Motion>', \&mouseMotion); MainLoop; sub quit { print "User triggered event -- exiting!\n"; exit; } sub keyPress { print "Debug: keypress occurred\n"; quit(); } sub mouseMotion { print "Debug: mouse motion occurred\n"; quit(); }

      s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

        Yep - I didn't think to try it out. For some reason, I was thinking it would only trigger events if it was over the widgets that had the binding.

        Thanks,

        Rob
      I'm not sure I completely understand what you want to achieve.

      My bad, throwing too much thin client jargon around. I have a wrapper script for the screensaver. I check if someone is using a thin client and if they are I disconnect the session instead of running the actual screensaver. Disconnected sessions remain running on the server until the user reconnects from a thin client (could be the same one or could be a different one). Think Citrix or Windows Terminal Services (I list Citrix first because guess who Microsoft got the technology from.... ;-)

      Management wants idle sessions locked or disconnected after 30 minutes. The problem is several users are looking at informantion on the thin client but not actually using them so the idle timeout kicks in and the session gets disconencted. Reconencting is annoying -- it's several seconds slower than just unlocking a screen saver. Thus, this script to warn them before it happens.

      Thanks for the help!!

Re: Perl/Tk: Is there a way to key off of any user input event?
by zentara (Cardinal) on Oct 14, 2006 at 15:53 UTC
    Since you are using this as a screensaver type app, and you want it to have focus when it's out of the mainwindow, you may want a grab_global call. Try this. I've included an 'Escape' key to quit, but you could use a password. You could also make it full screen and put a graphic on it.
    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new; #my $width = $mw->screenwidth; #my $height = $mw->screenheight; #$mw->geometry($width . 'x' . $height .'+0+0'); $mw->bind('<Motion>', [\&activity ,'mouse']); $mw->bind('<Key>', [ \&activity, Ev('K')]); $mw->after(500,sub {$mw->grabGlobal}); #window must be visible $mw->focusForce; #for grab MainLoop; sub activity { if( $_[1] eq 'Escape'){ exit } print chr(07); #beep }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
      Thanks zentara, the grabGlobal was the last thing I needed!! And thanks to everyone for the help!! My users will love you!! :-)