1 # General purpose code for being a tray applet
3 proc manyset {list args} {
4 foreach val $list var $args {
12 package require tktray
14 #----- general machinery -----
18 # tk::tktray widget is called .i
20 # Inner window subprocess:
22 # Caller that needs access to inner window should define
23 # proc innerwindow {} { ... }
27 # .i.i.b frame to contain container
28 # .i.i.b.c actual container
32 # Caller may bind .i.i <ButtonPress-$b>
34 # Alternatively caller may call applet::setup-button-menu $b
35 # which will generate a menu .m$b which the user can configure
36 # and which will automatically be posted and unposted etc.
40 tktray::icon .i -class example
41 .i configure -docked 1
44 namespace eval applet {
48 proc setup-button-menu {b} {
49 bind .i.i <ButtonPress> { applet::menubuttonpressed %b %X %Y }
53 proc menubuttonpressed {b x y} {
57 puts "unpost $posted toggle"
60 } elseif {[winfo exists .m$b]} {
63 puts "unpost $posted other"
78 proc innerwindow-resetup-required {why} {
79 variable innerwindow_after
81 if {[info exists innerwindow_after]} return
82 set innerwindow_after [after idle innerwindow-resetup]
85 proc innerwindow-resetup {} {
86 variable innerwindow_after
87 unset innerwindow_after
91 innerwindow-destroying
93 catch { destroy .i.i.c }
94 if {![winfo exists .i.i]} return
95 destroy [frame .i.i.make-exist]
96 catch { destroy .i.i.b.c }
97 catch { destroy .i.i.b }
99 pack .i.i.b -fill both -side left -expand 1
100 frame .i.i.b.c -container 1 -background orange
101 pack .i.i.b.c -fill both -side left -expand 1
103 global inner_lastw inner_lasth
104 #set w [winfo width .i.i]
105 # set w [winfo width .i.i]
106 # set h [winfo height .i.i]
108 # if {$w != $inner_lastw || $h != $inner_lasth} {
111 # innerwindow-ph-dummy configure -width $w -height 2
116 proc setupinnerwindow {w} {
117 global inner_lastw inner_lasth
121 image create photo innerwindow-ph-dummy -width $w -height 2
122 .i configure -image innerwindow-ph-dummy
124 destroy [frame .i.make-exist]
125 destroy [frame .i.i.make-exist]
126 bind .i <<IconConfigure>> { innerwindow-resetup-required IconConfigure }
129 namespace eval applet {
131 proc tooltip-starttimer {state x y} {
132 variable tooltip_after
134 variable tooltip_inwindow
135 if {$state || $posted || !$tooltip_inwindow} { tooltip-cancel; return }
136 catch { after cancel $tooltip_after }
137 set tooltip_after [after 500 applet::tooltip-show $x $y]
140 proc tooltip-cancel {} {
141 variable tooltip_after
142 catch { after cancel $tooltip_after }
143 catch { unset $tooltip_after }
147 set tooltip_inwindow 0
149 proc tooltip-enter {state x y} {
150 variable tooltip_inwindow
151 set tooltip_inwindow 1
152 tooltip-starttimer $state $x $y
155 proc tooltip-leave {} {
156 variable tooltip_inwindow
157 set tooltip_inwindow 0
161 proc setup-tooltip {} {
162 bind .i <Enter> { applet::tooltip-enter %s %X %Y }
163 bind .i <Leave> { applet::tooltip-leave }
164 bind .i <ButtonRelease> {
165 applet::tooltip-cancel
166 applet::tooltip-starttimer %s %X %Y
168 bind .i <Motion> { applet::tooltip-starttimer %s %X %Y }
169 toplevel .tt -background black
171 wm overrideredirect .tt 1
172 label .tt.t -justify left -background {#EEE1B3}
173 pack .tt.t -padx 1 -pady 1
177 proc tooltip-set {s} {
178 .tt.t configure -text $s
181 proc tooltip-show {x y} {
184 wm geometry .tt +$x+$y
190 proc setimage {image} {
191 .i configure -image $image
194 proc fork-then {ondeath inchild} {
195 global children errorCode errorInfo
196 foreach f {stdout stderr} {
197 if {[catch { flush $f } emsg]} {
198 catch { bgerror $emsg }
206 puts stderr "CHILD ERROR $emsg\n$errorCode\n$errorInfo\n"
208 kill KILL [id process]
210 set children($pid) $ondeath
214 proc chld-handler {} {
217 if {[catch { set got [wait -nohang] }]} break
218 if {![llength $got]} break
219 manyset $got pid how how2
220 if {[info exists children($pid)]} {
221 set l $children($pid)
224 uplevel #0 [concat [list $l] $how $how2]
226 catch { bgerror $emsg }
232 signal -restart trap CHLD { after idle chld-handler }