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
23 # applet::setup-tooltip ON-VISIBLE ON-INVISIBLE
24 # to make applet have a tooltip.
26 # ON-VISIBLE and ON-INVISIBLE will be globally eval'd
27 # when the tooltip becomes visible and invisible.
30 # applet::tooltip-set TEXT-MAYBE-MULTILINE
33 # Inner window subprocess:
35 # Caller that needs access to inner window should define
36 # proc innerwindow {} { ... }
40 # .i.i.b frame to contain container
41 # .i.i.b.c actual container
45 # Caller may bind .i.i <ButtonPress-$b>
47 # Alternatively caller may call applet::setup-button-menu $b
48 # which will generate a menu .m$b which the user can configure
49 # and which will automatically be posted and unposted etc.
53 tktray::icon .i -class example
54 .i configure -docked 1
57 namespace eval applet {
60 # used by both menus and tooltips
65 proc setup-button-menu {b} {
66 bind .i.i <ButtonPress> { applet::menubuttonpressed %b %X %Y }
70 proc menubuttonpressed {b x y} {
74 puts "unpost $posted toggle"
77 } elseif {[winfo exists .m$b]} {
80 puts "unpost $posted other"
95 variable tooltip_on_vis {}
96 variable tooltip_on_invis {}
98 proc tooltip-starttimer {state x y} {
99 variable tooltip_after
101 variable tooltip_inwindow
102 if {$state || $posted || !$tooltip_inwindow} { tooltip-cancel; return }
103 catch { after cancel $tooltip_after }
104 set tooltip_after [after 500 applet::tooltip-show $x $y]
107 proc tooltip-cancel {} {
108 variable tooltip_after
109 variable tooltip_on_invis
110 catch { after cancel $tooltip_after }
111 catch { unset $tooltip_after }
113 uplevel #0 $tooltip_on_invis
116 set tooltip_inwindow 0
118 proc tooltip-enter {state x y} {
119 variable tooltip_inwindow
120 set tooltip_inwindow 1
121 tooltip-starttimer $state $x $y
124 proc tooltip-leave {} {
125 variable tooltip_inwindow
126 set tooltip_inwindow 0
130 proc setup-tooltip {on_vis on_invis} {
131 foreach v {vis invis} {
132 variable tooltip_on_$v [set on_$v]
134 bind .i <Enter> { applet::tooltip-enter %s %X %Y }
135 bind .i <Leave> { applet::tooltip-leave }
136 bind .i <ButtonRelease> {
137 applet::tooltip-cancel
138 applet::tooltip-starttimer %s %X %Y
140 bind .i <Motion> { applet::tooltip-starttimer %s %X %Y }
141 toplevel .tt -background black
143 wm overrideredirect .tt 1
144 label .tt.t -justify left -background {#EEE1B3}
145 pack .tt.t -padx 1 -pady 1
149 proc tooltip-set {s} {
150 .tt.t configure -text $s
153 proc tooltip-show {x y} {
154 variable tooltip_on_vis
157 wm geometry .tt +$x+$y
159 uplevel #0 $tooltip_on_vis
165 proc innerwindow-resetup-required {why} {
166 variable innerwindow_after
168 if {[info exists innerwindow_after]} return
169 set innerwindow_after [after idle innerwindow-resetup]
172 proc innerwindow-resetup {} {
173 variable innerwindow_after
174 unset innerwindow_after
178 innerwindow-destroying
180 catch { destroy .i.i.c }
181 if {![winfo exists .i.i]} return
182 destroy [frame .i.i.make-exist]
183 catch { destroy .i.i.b.c }
184 catch { destroy .i.i.b }
186 pack .i.i.b -fill both -side left -expand 1
187 frame .i.i.b.c -container 1 -background orange
188 pack .i.i.b.c -fill both -side left -expand 1
190 global inner_lastw inner_lasth
191 #set w [winfo width .i.i]
192 # set w [winfo width .i.i]
193 # set h [winfo height .i.i]
195 # if {$w != $inner_lastw || $h != $inner_lasth} {
198 # innerwindow-ph-dummy configure -width $w -height 2
203 proc setupinnerwindow {w} {
204 global inner_lastw inner_lasth
208 image create photo innerwindow-ph-dummy -width $w -height 2
209 .i configure -image innerwindow-ph-dummy
211 destroy [frame .i.make-exist]
212 destroy [frame .i.i.make-exist]
213 bind .i <<IconConfigure>> { innerwindow-resetup-required IconConfigure }
218 proc setimage {image} {
219 .i configure -image $image
222 proc fork-then {ondeath inchild} {
223 global children errorCode errorInfo
224 foreach f {stdout stderr} {
225 if {[catch { flush $f } emsg]} {
226 catch { bgerror $emsg }
234 puts stderr "CHILD ERROR $emsg\n$errorCode\n$errorInfo\n"
236 kill KILL [id process]
238 set children($pid) $ondeath
242 proc chld-handler {} {
245 if {[catch { set got [wait -nohang] }]} break
246 if {![llength $got]} break
247 manyset $got pid how how2
248 if {[info exists children($pid)]} {
249 set l $children($pid)
252 uplevel #0 [concat [list $l] $how $how2]
254 catch { bgerror $emsg }
260 signal -restart trap CHLD { after idle chld-handler }