# which should examine b and do something appropriate.
#
+proc manyset {list args} {
+ foreach val $list var $args {
+ upvar 1 $var my
+ set my $val
+ }
+}
+package require Tclx
package require tktray
-#load /home/ian/things/Systray/tktray-1.3.8/libtktray1.3.8.so
-
wm withdraw .
set posted 0
}
-proc innerwindow-event {why} {
+proc innerwindow-resetup-required {why} {
global innerwindow_after
puts "IW-EVENT $why"
if {[info exists innerwindow_after]} return
puts RESETUP
+ innerwindow-destroying
+
catch { destroy .i.i.c }
if {![winfo exists .i.i]} return
destroy [frame .i.i.make-exist]
# set inner_lastw $w
# set inner_lasth $h
# innerwindow-ph-dummy configure -width $w -height 2
- innerwindow [winfo id .i.i.b.c]
+ innerwindow-ready
# }
}
destroy [frame .i.make-exist]
destroy [frame .i.i.make-exist]
- bind .i <<IconConfigure>> { innerwindow-event "%w" }
+ bind .i <<IconConfigure>> { innerwindow-resetup-required IconConfigure }
}
bind .i <ButtonPress> { pressed %b %X %Y }
proc setimage {image} {
.i configure -image $image
}
+
+proc fork-then {ondeath inchild} {
+ global children errorCode errorInfo
+ foreach f {stdout stderr} {
+ if {[catch { flush $f } emsg]} {
+ catch { bgerror $emsg }
+ }
+ }
+ set pid [fork]
+ if {!$pid} {
+ if {[catch {
+ uplevel 1 $inchild
+ } emsg]} {
+ puts stderr "CHILD ERROR $emsg\n$errorCode\n$errorInfo\n"
+ }
+ kill KILL [id process]
+ }
+ set children($pid) $ondeath
+ return $pid
+}
+
+proc chld-handler {} {
+ global children
+ while 1 {
+ if {[catch { set got [wait -nohang] }]} break
+ if {![llength $got]} break
+ manyset $got pid how how2
+ if {[info exists children($pid)]} {
+ set l $children($pid)
+ unset children($pid)
+ if {[catch {
+ uplevel #0 [concat [list $l] $how $how2]
+ } emsg]} {
+ catch { bgerror $emsg }
+ }
+ }
+ }
+}
+
+signal -restart trap CHLD { after idle chld-handler }
setuptooltip
settooltip "line\nanother"
-proc innerwindow {id} {
- puts IICONFIG
- puts "IC $id"
+fconfigure stdout -buffering line
- .i.i.b configure -background darkblue -bd 1
-exec /home/ian/things/Chiark-utils/chiark-utils.git/cprogs/xacpi-simple \
- -into $id &
+set status none
+
+proc innerwindow-destroying {} {
+ global status
+ puts "DESTROYING $status"
+ switch -exact $status {
+ none { }
+ old { }
+ default { kill $status; set status old }
+ }
+}
+
+proc innerwindow-ready {} {
+ global status
+ puts "READY $status"
+ switch -exact $status {
+ none {
+ run-child
+ }
+ old {
+ # wait for it to die
+ }
+ default {
+ error "unexpected state $status"
+ }
+ }
+ puts "READY-done $status"
+}
+
+set ratelimit 0
+
+proc run-child {} {
+ global status ratelimit
+
+ puts "RUN-CHILD $status"
+ set now [clock seconds]
+ lappend ratelimit $now
+ while {[lindex $ratelimit 0] < {$now - 10}} {
+ set ratelimit [lrange $ratelimit 1 end]
+ }
+ if {[llength $ratelimit] > 10} {
+ puts stderr "crashing repeatedly, quitting $ratelimit"
+ exit 127
+ }
+
+ set status none
+ set status [fork-then child-died {
+ execl xacpi-simple [list -into [winfo id .i.i.b.c]]
+ }]
+ puts "FORKED $status"
+}
+
+proc child-died {how how2} {
+ puts "DIED $how $how2"
+ global status
+ switch -exact $status {
+ old {
+ set status none
+ run-child
+ }
+ default {
+ set status none
+ innerwindow-resetup-required "child died"
+ }
+ }
}
setupinnerwindow 40