1 # ui-activesourcemgr.tcl --
2 #
3 # ActiveSourceManager is used to dispatch and manage ActiveSource
4 # objects.
5 #
6 # Copyright (c) 1998-2002 The Regents of the University of California.
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are met:
11 #
12 # A. Redistributions of source code must retain the above copyright notice,
13 # this list of conditions and the following disclaimer.
14 # B. Redistributions in binary form must reproduce the above copyright notice,
15 # this list of conditions and the following disclaimer in the documentation
16 # and/or other materials provided with the distribution.
17 # C. Neither the names of the copyright holders nor the names of its
18 # contributors may be used to endorse or promote products derived from this
19 # software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
22 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
25 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #
32 # @(#) $Header: /usr/mash/src/repository/mash/mash-1/tcl/vic/ui-activesourcemgr.tcl,v 1.20 2002/08/12 06:21:19 agu Exp $
33
34
35 import Observer ActiveSource UserWindow Configuration
36
37 #
38 # ActiveSourceManager is used to dispatch and manage ActiveSource
39 # objects. It is an Observer of VideoAgent.
40 #
41 Class ActiveSourceManager -superclass {Observer} -configuration {
42 tile 1
43 }
44
45 #
46 # Tile out in a grid the video of the ActiveSources followed by the
47 # provided <i>videoAgent</i>. If <i>list_direction</i> is "horizontal",
48 # the <i>tile</i> resource option indicates the initial number of rows
49 # for the grid. If <i>list_direction</i> is "vertical", the <i>tile</i>
50 # resource option indicates the initial number of columns for the grid.
51 #
52 ActiveSourceManager public init {ui w videoAgent list_direction localChannel {autoplace 0}} {
53 $self next
54
55 $self instvar ui_ videoAgent_ localChannel_ autoplace_
56 set ui_ $ui
57 set videoAgent_ $videoAgent
58 set localChannel_ $localChannel
59 set autoplace_ $autoplace
60
61 $self instvar curcol_ currow_ ncol_ nrow_ list_direction_
62 set curcol_ 0
63 set currow_ 0
64 set list_direction_ $list_direction
65 set ncol_ [$self get_option tile]
66 set nrow_ [$self get_option tile]
67
68 # let this ActiveSourceManager be an observer of the VideoAgent so it can catch "trigger_format" and "activate" and "deactivate"
69 $videoAgent_ attach $self
70 }
71
72 #
73 ActiveSourceManager public init_grid {w} {
74 $self instvar grid_ label_
75
76 frame $w
77 set grid_ $w.grid
78 frame $grid_
79 set label_ $w.label
80 label $label_ -text "Waiting for video..."
81
82 pack $label_ -anchor c -expand 1 -side left -fill both
83 }
84
85 #
86 # The provided ActiveSource, <i>as</i>, is added to the active_() instvar (an array of active senders indexed by <i>src</i>).
87 # If the array was previously empty, the $label_ is removed and the $grid_ is packed in its place.
88 #
89 ActiveSourceManager public add_active { as src } {
90 $self instvar active_ grid_ label_
91 set active_($src) $as
92 if { [array size active_] == 1 } {
93 pack forget $label_
94 pack $grid_ -expand 1 -fill x -anchor n
95 }
96 }
97
98 #
99 # The specified <i>src</i> is removed from the active_() instvar (an array of active senders indexed by src).
100 # If this was the last element of the array, the $grid_ is removed and the $label_ is packed in its place.
101 #
102 ActiveSourceManager public rm_active src {
103 $self instvar active_ grid_ label_
104 unset active_($src)
105 if { [array size active_] == 0 } {
106 pack forget $grid_
107 pack $label_ -anchor c -expand 1 -side left
108 }
109 }
110
111 #
112 # Return a list of the active sources.
113 #
114 ActiveSourceManager public active-sources {} {
115 $self instvar active_
116 return [array names active_]
117 }
118
119 #
120 # Update the row and column variables to indicate an addition to the
121 # grid of thumbnails of ActiveSources. If the <i>list_direction_</i> is
122 # "vertical", additions to the grid are placed at the end of the first
123 # non-full column. When a column becomes full, a new column is begun,
124 # filled from top to bottom. If the <i>list_direction_</i> is
125 # "horizontal", additions to the grid are placed at the end of the first
126 # non-full row. When a row becomes full, a new row is begun, filled
127 # from left to right.
128 #
129 ActiveSourceManager public bump { } {
130 $self instvar curcol_ currow_ list_direction_
131
132 if { $list_direction_ == "vertical" } {
133 $self instvar ncol_
134 incr curcol_
135 if { $curcol_ == $ncol_ } {
136 set curcol_ 0
137 incr currow_
138 }
139 } else {
140 $self instvar nrow_
141 incr currow_
142 if { $currow_ == $nrow_ } {
143 set currow_ 0
144 incr curcol_
145 }
146 }
147 }
148
149 #
150 # If the <i>list_direction_</i> is "vertical", reformat the grid of
151 # video thumbnails into <i>n</i> columns. If the <i>list_direction_</i>
152 # is "horizontal", reformat the grid of video thumbnails into <i>n</i>
153 # rows.
154 #
155 ActiveSourceManager public redecorate { {n 0} } {
156 $self instvar curcol_ currow_ list_direction_ active_
157 set curcol_ 0
158 set currow_ 0
159 if { $n != 0 } {
160 if { $list_direction_ == "vertical" } {
161 $self instvar ncol_
162 set ncol_ $n
163 } else {
164 $self instvar nrow_
165 set nrow_ $n
166 }
167 }
168
169 $self instvar grid_
170 if ![info exists grid_] {
171 return
172 }
173 foreach src [$self active-sources] {
174 if [$active_($src) set hidden_] {
175 grid forget $grid_.$src
176 } else {
177 grid $grid_.$src -row $currow_ -column $curcol_ -sticky we
178 if { $list_direction_ == "vertical" } {
179 grid columnconfigure $grid_ $curcol_ -weight 1
180 } else {
181 grid rowconfigure $grid_ $currow_ -weight 1
182 }
183 $self bump
184 }
185 }
186 }
187
188
189 #
190 # Add a <i>src</i> to the active senders list. E.g., make a postage
191 # stamp window appear, stats, etc. so that the user can select
192 # the video stream.
193 #
194 ActiveSourceManager public activate src {
195 #
196 # give the VideoAgent a chance to create and install
197 # a decoder and for that decoder to see a packet so it can
198 # determine the output geometry and color decimation.
199 # we shouldn't have to do this (e.g., resize will
200 # take care of a geometry change), but currently
201 # decoders can't trigger a renderer realloation
202 # when the decimation changes.FIXME fix this
203 # Note that trigger_format allocates the decoder object
204 # is called before the event loop goes idle
205 #
206 after idle "$self really_activate $src"
207 }
208
209 #
210 # Create an ActiveSource, $as, within the widget, $grid_.$src, out of the provided <i>src</i>.
211 # (This entails dropping a postage-stamp-sized VideoWidget decoding the $src into the $grid_.$src widget.)
212 # The widget, $grid.$src, is subsequently positioned within $grid_ by the grid manager in
213 # the row specified by instvar $currow_ and the column specified by instvar $curcol_.
214 # The column and row variables are updated by the bump method to reflect this addition to the grid.
215 # Add this ActiveSource, $as, to the instvar array active_() (the array of active senders).
216 # Update the decoder for the specified <i>src</i>.
217 #
218 ActiveSourceManager public really_activate src {
219 $self instvar grid_ curcol_ currow_ ui_ list_direction_ localChannel_ autoplace_
220
221 set as [new ActiveSource $self $ui_ $grid_.$src $src $localChannel_]
222
223 # If autoplace is active, get the x,y coordinates and scale factor
224 # for the new ActiveSource. After creating the UserWindow, register
225 # it so its movements, etc. can be tracked.
226 if { $autoplace_ } {
227 set coords_scale [$self autoplace add $as]
228 $as place [lindex $coords_scale 0] \
229 [lindex $coords_scale 1] \
230 [lindex $coords_scale 2]
231 }
232
233 grid $grid_.$src -row $currow_ -column $curcol_ -sticky we
234
235 if { $list_direction_ == "vertical" } {
236 grid columnconfigure $grid_ $curcol_ -weight 1
237 } else {
238 grid rowconfigure $grid_ $currow_ -weight 1
239 }
240
241 $ui_ update_decoder $src
242 $self bump
243
244 #
245 # Someone became activated, so we have to change
246 # the switchable menu to include this participant
247 #
248 Switcher rebuild_switch_list_menu
249
250 # FIXME this is a temporary hack while cindy works on the VideoBox class...
251 if {[$ui_ info class] == "MuiUI"} {
252 $ui_ maybe_switch_in $src
253 }
254 }
255
256 #
257 # Remove a <i>src</i> from the active senders list.
258 #
259 ActiveSourceManager public deactivate {src} {
260 $self instvar active_
261 if [info exists active_($src)] {
262 set as $active_($src)
263 set L [$as user-windows]
264 foreach uw $L {
265 #FIXME should check if we're voice-switched
266 # and if so, bump window
267 delete $uw
268 }
269 # detach any we missed by deleting user-windows
270 $as detach-windows
271 $as delete-decoder-window
272 $as destroy
273 }
274
275 $self instvar grid_
276 set w $grid_.$src
277 if [winfo exists $w] {
278 grid forget $w
279 destroy $w
280 }
281 $self rm_active $src
282 $self redecorate
283 $src handler ""
284
285 #
286 # Someone became de-activated, so we have to change
287 # the switchable menu to un-include this participant
288 #
289 Switcher rebuild_switch_list_menu
290
291 #FIXME
292 global ftext btext ltext fpshat bpshat lhat shat
293 unset ftext($src)
294 unset btext($src)
295 unset ltext($src)
296 unset fpshat($src)
297 unset bpshat($src)
298 unset lhat($src)
299 unset shat($src)
300 }
301
302 #
303 # Dispatch focus method on switcher windows.
304 #
305 ActiveSourceManager public focus_speaker { infoname msg } {
306 foreach s [$self active-sources] {
307 if { [$s sdes cname] == $msg } {
308 Switcher focus $s
309 }
310 }
311 }
312
313 #
314 # Update the name of the <i>src</i> for the UserWindows in which it appears.
315 #
316 ActiveSourceManager public change_name {src} {
317 set name [$src sdes name]
318 # update viewing window names to reflect new name
319 $self instvar active_
320 if [info exists active_($src)] {
321 set as $active_($src)
322 foreach uw [$as user-windows] {
323 if { [$uw attached-source] == "$as" } {
324 $uw set-name $name
325 }
326 }
327 }
328
329 # Someone's name has been altered , so we have to change
330 # the switchable menu to include this participant
331 #
332 Switcher rebuild_switch_list_menu
333 }
334
335 #
336 ActiveSourceManager public trigger_format {src} {
337 $self instvar active_ videoAgent_ ui_
338
339 if ![info exists active_($src)] {
340 #
341 # if we get a change format before really_activate
342 # was called (i.e., so we don't even have a thumbnail yet),
343 # don't do anything
344 #
345 return
346 }
347
348 set as $active_($src)
349
350 set L [$as user-windows]
351 $as detach-windows
352 #FIXME
353 set extoutList [extout_detach_src $src]
354
355 set d [$videoAgent_ reactivate $src]
356
357 $ui_ update_decoder $src
358 global colorbutton
359 $d color $colorbutton($src)
360
361 foreach uw $L {
362 $as attach-window $uw
363 [$uw video-widget] redraw
364 }
365 $as attach-thumbnail
366 #FIXME
367 extout_attach_src $src $extoutList
368 }
369
370 #
371 # Called when the video stream state changes in a way that would
372 # affect the choice of renderer. For example, when a jpeg stream
373 # changes from type-0 to type-1 we might have to revert from
374 # hardware to software decoding, or we might have to reallocate
375 # a 422 renderer as a 420 renderer. This never needs to happen
376 # for most stream types (i.e., because the decimation factor is fixed).
377 #
378 ActiveSourceManager public decoder_changed {src} {
379 $self instvar active_
380 if ![info exists active_($src)] {
381 return
382 }
383 #FIXME redundant with trigger_format
384 set as $active_($src)
385
386 set L [$as user-windows]
387 $as detach-windows
388 #FIXME
389 set extoutList [extout_detach_src $src]
390 foreach uw $L {
391 $as attach-window $uw
392 [$uw video-widget] redraw
393 }
394 #FIXME
395 extout_attach_src $src $extoutList
396 return
397 }
398
399
400 ActiveSourceManager public trigger_format_all { } {
401 foreach s [$self active-sources] {
402 $self trigger_format $s
403 }
404 }
405
406
407 ActiveSourceManager public get_activesource src {
408 $self instvar active_
409 if [info exists active_($src)] {
410 return $active_($src)
411 } else {
412 return ""
413 }
414 }
415
416 #
417 # switches the VideoAgent object.
418 # This method should be called always from VicUI::switch-agent
419 #
420 ActiveSourceManager instproc switch-agent {new_agent} {
421 $self instvar videoAgent_
422
423 # the attachement is already done by VicUI::switch-agent
424 #$new_agent attach $self
425
426 # set the new videoAgent
427 set videoAgent_ $new_agent
428 }
429
430 #
431 # Outside hook via tkvar autoplaceNewSources to turn on/off use of the
432 # autoplace function.
433 #
434 ActiveSourceManager instproc set_autoplace {} {
435 $self tkvar autoplaceNewSources
436 if { $autoplaceNewSources } {
437 $self autoplace_on
438 } else {
439 $self autoplace_off
440 }
441 }
442
443 #
444 # Toggle the autoplace function on and off.
445 #
446 ActiveSourceManager instproc toggle_autoplace {} {
447 $self instvar autoplace_
448 if { $autoplace_ } {
449 $self autoplace_off
450 } else {
451 $self autoplace_on
452 }
453 }
454
455 #
456 # Turn off autoplace.
457 #
458 ActiveSourceManager instproc autoplace_off {} {
459 $self instvar autoplace_
460 set autoplace_ false
461 }
462
463 #
464 # Turn on autoplace. Close all windows and replace them.
465 #
466 ActiveSourceManager instproc autoplace_on {} {
467 $self instvar autoplace_ active_
468
469 # Don't do anything if autoplace is already on.
470 if {$autoplace_} return
471
472 # Close all windows. We can't just call detach-windows because that
473 # also detaches the thumbnail.
474 foreach src [$self active-sources] {
475 set as $active_($src)
476 foreach uw [$as user-windows] {
477 # We have to check that the user windows this ActiveSource
478 # knows about are actually still attached to this ActiveSource
479 # because voice-switched or browse-mode windows change their
480 # ActiveSources.
481 if {[$uw attached-source] == "$as"} {
482 $uw destroy
483 }
484 }
485 }
486
487 # Replace all windows.
488 foreach src [$self active-sources] {
489 set as $active_($src)
490 set coords_scale [$self autoplace add $as]
491 $as place [lindex $coords_scale 0] \
492 [lindex $coords_scale 1] \
493 [lindex $coords_scale 2]
494 }
495
496 # Set new autoplace_ value.
497 set autoplace_ true
498 }
499
500 #
501 # Default autoplace function.
502 #
503 # {add $as} is called when a new ActiveSource is to be placed. It
504 # should return virtual screen coordinates and image size
505 # formatted as "x y scale". If scale is 0, the ActiveSource
506 # will not be placed.
507 # {remove $as} is called when an ActiveSource's display window is
508 # destroyed (e.g. user closes the window).
509 # {register $as $uw} is called when the ActiveSource's display window
510 # has been created to associate a specific
511 # UserWindow with the ActiveSource.
512 ActiveSourceManager instproc autoplace {cmd as {uw false}} {
513 global mutebutton
514 $self instvar asources_ windows_ mon_ xbase_ ybase_ nextx_ nexty_ maxy_ xoffset_ yoffset_ xincr_ yincr_ mon_list_ screen_width_ screen_height_ minx_ miny_ maxx_ maxy_ framesize_ titlebarsize_
515
516 # Should we place windows across monitors or only within monitors?
517 set cross_monitors 0
518
519 # Handle add commands.
520 if {$cmd == "add"} {
521 # Get the monitor coordinates.
522 if {![info exists mon_list_]} {
523 # get_monitorinfo returns a list of lists. Each element of the
524 # list is a list formatted as "minx miny maxx maxy". The first
525 # element contains the total virtual screen resolution. All
526 # subsequent elements contain the physical screen resolutions
527 # in the virtual screen coordinate space. e.g. the second
528 # monitor might return "1024 0 1824 600" if its resolution is
529 # 800x600.
530 set mon_list_ [get_monitorinfo]
531 if { $mon_list_ == "" } {
532 set mon_list_ [list [list 0 0 [winfo screenwidth .] [winfo screenheight .]] [list 0 0 [winfo screenwidth .] [winfo screenheight .]]]
533 }
534
535 # Grab the virtual screen coordinates.
536 set v_coords [lindex $mon_list_ 0]
537 set minx_ [lindex $v_coords 0]
538 set miny_ [lindex $v_coords 1]
539 set maxx_ [lindex $v_coords 2]
540 set maxy_ [lindex $v_coords 3]
541
542 # Remove the virtual screen coordinates from the monitor list,
543 # and sort left-most, then top-most.
544 set mon_list_ [lsort [lrange $mon_list_ 1 end]]
545
546 # Compute the virtual screen width and height.
547 set screen_width_ [expr $maxx_ - $minx_ + 1]
548 set screen_height_ [expr $maxy_ - $miny_ + 1]
549
550 # Compute the window frame and titlebar sizes.
551 set wm_geom [split [wm geometry .] {+}]
552 set winfo_geom [split [winfo geometry .] {+}]
553 if {[lindex $wm_geom 1] != [lindex $winfo_geom 1] && \
554 [lindex $wm_geom 2] != [lindex $winfo_geom 2]} \
555 {
556 set framesize_ [expr [lindex $winfo_geom 1] - [lindex $wm_geom 1]]
557 set titlebarsize_ [expr [lindex $winfo_geom 2] - [lindex $wm_geom 2]]
558 } else {
559 set framesize_ [expr [winfo rootx .] - [winfo x .]]
560 set titlebarsize_ [expr [winfo rooty .] - [winfo y .]]
561 }
562 }
563
564 # If there are no ActiveSources placed, initialize values.
565 #
566 # mon_ the list index of the current monitor being populated.
567 # xbase_ the left-most pixel value of the last window placed.
568 # nextx_ the right-most pixel value of the last window placed.
569 # nexty_ the bottom-most pixel value of the last completed row.
570 # maxy_ the bottom-most pixel value of the current row.
571 # xincr_ the pixel amount to increase the xbase by each time.
572 # yincr_ the pixel amount to increase the ybase by each time.
573 # xoffset_ the horizontal pixel spacing between windows.
574 # yoffset_ the vertical pixel spacing between windows.
575 if {![array size asources_]} {
576 set mon_ 0
577 set xbase_ [expr $minx_ - $framesize_]
578 set ybase_ [expr $miny_ - $titlebarsize_]
579 set nextx_ $xbase_
580 set nexty_ $ybase_
581 set maxy_ $nexty_
582 set xincr_ 10
583 set yincr_ 20
584 set xoffset_ $framesize_
585 set yoffset_ $titlebarsize_
586 }
587
588 # Initialize the return values.
589 set retx [expr $nextx_ + $xoffset_]
590 set rety [expr $nexty_ + $yoffset_]
591 set scale 1
592
593 # If the ActiveSource is muted, just return 0 for the scale.
594 if {$mutebutton([$as source])} {
595 return "$retx $rety 0"
596 }
597
598 # If the ActiveSource was already placed, just return the previously
599 # calculated coordinates.
600 if {[info exists asources_($as)]} {
601 return $asources_($as)
602 }
603
604 # Get the video stream dimensions.
605 set src [$as source]
606 set decoder [$src handler]
607 set width [expr int([$decoder width] * $scale)]
608 set height [expr int([$decoder height] * $scale)]
609
610 # If we're crossing monitors or there is only one monitor, use
611 # a simple left-right, top-down placement. If we run out of room
612 # on the bottom of the virtual screen, jump back to the top.
613 if {$cross_monitors || [llength $mon_list_] == 1} {
614 # If there is no room in the current row, try the next row.
615 if {[expr $retx + $width] >= $screen_width_} {
616 set retx [expr $xbase_ + $xoffset_]
617 set rety [expr $maxy_ + $yoffset_]
618
619 # Update nexty_.
620 set nexty_ $maxy_
621 }
622
623 # If there is no room for the bottom of the window in this
624 # row, go back to the top-left corner. Increase the base
625 # coordinates so we don't cover up the previous windows.
626 if {[expr $rety + $height] >= $screen_height_} {
627 set xbase_ [expr $xbase_ + $xincr_]
628 set ybase_ [expr $ybase_ + $yincr_]
629 set retx [expr $xbase_ + $xoffset_]
630 set rety [expr $ybase_ + $yoffset_]
631
632 # Update nexty_ and maxy_.
633 set nexty_ $ybase_
634 set maxy_ $ybase_
635 }
636 } else {
637 # If we're not crossing monitors, place on one monitor after
638 # another, looping back to the first monitor if all monitors
639 # have been fully covered. If we're starting on the first
640 # monitor, then there is no need to loop later (set looped to
641 # true).
642 set placed 0
643 set looped [expr $mon_ == 0]
644 while {!$placed} {
645 # If the current monitor index is less than zero or larger
646 # than the number of monitors, reset it to zero.
647 if {$mon_ < 0 || $mon_ >= [llength $mon_list_]} {
648 set mon_ 0
649 }
650
651 # Get the virtual space coordinates for the current
652 # monitor.
653 set v_coords [lindex $mon_list_ $mon_]
654 set minx [lindex $v_coords 0]
655 set miny [lindex $v_coords 1]
656 set maxx [lindex $v_coords 2]
657 set maxy [lindex $v_coords 3]
658
659 # Assume that we've placed the window. If it doesn't fit
660 # on this monitor, then we know it can't be placed.
661 set placed 1
662
663 # If we're on the last monitor and we've looped here, then
664 # just use these coordinates.
665 if {[expr $mon_ + 1] == [llength $mon_list_] && $looped} {
666 break;
667 }
668
669 # If there is no room in the current row, try the next row.
670 if {[expr $retx + $width] >= $maxx} {
671 set retx [expr $minx + $xbase_ + $xoffset_]
672 set rety [expr $maxy_ + $yoffset_]
673
674 # Update nexty_.
675 set nexty_ $maxy_
676
677 # Try the new coordinates.
678 set placed 0
679 }
680
681 # If there is no room for the bottom of the window in this
682 # row, go to the top-left corner of the next monitor.
683 if {[expr $rety + $height] >= $maxy} {
684 # If the next monitor would be the first monitor
685 # (looping around) and we have not already looped
686 # around, increase the base coordinates so we don't
687 # cover up the previous windows.
688 incr mon_
689 if {$mon_ == [llength $mon_list_]} {
690 set mon_ 0
691 set xbase_ [expr $xbase_ + $xincr_]
692 set ybase_ [expr $ybase_ + $yincr_]
693 set looped 1
694 }
695
696 # Set the window coordinates to the top-left corner
697 # of the next monitor.
698 set v_coords [lindex $mon_list_ $mon_]
699 set minx [lindex $v_coords 0]
700 set miny [lindex $v_coords 1]
701 set retx [expr $minx + $xbase_ + $xoffset_]
702 set rety [expr $miny + $ybase_ + $yoffset_]
703
704 # Update nexty_ and maxy_.
705 set nexty_ [expr $miny + $ybase_]
706 set maxy_ [expr $miny + $ybase_]
707
708 # Try the new coordinates.
709 set placed 0
710 }
711 }
712 }
713
714 # Update nextx_ and maxy_.
715 set nextx_ [expr $retx + $width]
716 if {[expr $rety + $height] > $maxy_} {
717 set maxy_ [expr $rety + $height]
718 }
719
720 # Store and return this window's coordinates.
721 set asources_($as) "$retx $rety $scale"
722 return $asources_($as)
723 }
724
725 # Handle remove commands.
726 if {$cmd == "remove"} {
727 array unset asources_ $as
728 array unset windows_ $as
729 }
730
731 # Handle register commands.
732 if {$cmd == "register" && $uw != "false"} {
733 set windows_($as) $uw
734 }
735 }
736
737
738
739
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.