[Keith Vetter] 2008-05-06 : One feature I've been wanting for a while is way to execute some background code when the user is really and truly idle, say 2 seconds after the last user event. [after idle] doesn't quite work because it can fire when the user is not really idle, such as when scrolling through a document. What I really want is something like ''after idle 2000 myCmd'' In tcl 8.5, Tip 245 ''Discover User Inactivity Time'' [http://www.tcl.tk/cgi-bin/tct/tip/245.html] provides a way of doing this. '''WhenIdle''' below is a function which after the user has been idle for '''$delay''' ms executes the command '''$cmd'''. It works by scheduling an after script for the desired delay, and checking when that event fires, just how long the user has been idle. If long enough then it executes the specified commmand, otherwise it reschedules another after script. There's some demo code that shows the code in action. Fiddle with the delay amount and then press ''Start''; click randomly to see how it compensates for your activity. After the specified amount of user idle time, the screen will flash red. ---- ====== ##+########################################################################## # # whenidle.tcl -- Fires after a certain amount of user idle time has passed # by Keith Vetter, May 2008 # package require Tk ##+########################################################################## # # WhenIdle -- after $delay amount of user idle time, execute $cmd # proc WhenIdle {delay cmd} { set t [tk inactive] set diff [expr {$delay - $t}] if {$diff <= 0} { if {$::demo} {set ::S(msg) "idle long enough"} eval $cmd } else { if {$::demo} { if {$t == 0} { set ::S(msg) "idling for $delay ms" } else { set ::S(msg) "need more idling ($diff ms)" } } after $diff [list WhenIdle $delay $cmd] } } proc DoDisplay {} { label .l1 -text Status: label .msg -textvariable ::S(msg) -bd 2 -relief sunken -width 20 label .l2 -text "Idle Time:" scale .s -from 10 -to 3000 -orient h -variable ::S(delay) button .start -text Start -command [list WhenIdle $::S(delay) {myCmd red}] .start config -command Start ;# Use this for demo grid .l1 .msg -sticky ew grid .l2 .s grid .start - -pady 1m grid columnconfigure . 1 -weight 1 update idletasks wm geom . [wm geom .] } proc Start {} { foreach aid [after info] { after cancel $aid } WhenIdle $::S(delay) {myCmd red} } proc myCmd {bg} { set bg2 [lindex [. config -bg] 3] foreach clr [list $bg $bg2 $bg $bg2 $bg] { . config -bg $clr update idletasks after 100 } . config -bg $bg2 } set demo 1 set S(delay) 2000 set S(msg) "press Start to begin" DoDisplay return ====== ---- !!!!!! %| enter categories here |% !!!!!!