Updated 2006-10-14 19:34:26

This is another window manager for weeApps. The code below sets up a main window with four MDI-like app windows, one anchored to each corner.

There's a starkit at [1] which adds a wrapper around this with Keith Vetter's Rush Hour game in window #1 and Steve Redler's weeCalc in window #3.

Here is "goowee.tcl", a (densely coded) GooWee wanna-be-a-desktop-manager. It presents a demo desktop when launched as is:
  # GooWee - A little desktop for little windows
  # jcw, 2004-10-07

  package require Tk

  bind . <F5> { destroy . } ;# ramdebugger convenience

  namespace eval gw {
    variable version 0.1

    proc layoutScreen {} {
      variable version
      wm title . "GooWee $version"
      set bg #fffff0
      . configure -bg $bg
      pack [frame .desk -bg $bg -height 500 -width 750] -expand 1 -fill both
      pack [frame .ctl -height 50] -fill x -padx 3 -pady 3
      text .ctl.t -bg $bg -height 2 -bd 0 -highlightcolor #c0c0c0
      pack .ctl.t -fill both
      .ctl.t insert end "Press F1..F4 to switch or F5 to quit. "
                # fgcolor bgcolor -----arrow-bitmask----- hside vtitle
      createTop 1 #ffcccc #fff0f0 80/C0/E0/F0/F8/FC/FE/FF right bottom
      createTop 2 #ccffcc #f0fff0 01/03/07/0F/1F/3F/7F/FF left  bottom
      createTop 3 #ccccff #f0f0ff FF/7F/3F/1F/0F/07/03/01 left  top
      createTop 4 #dddddd #f0f0f0 FF/FE/FC/F8/F0/E0/C0/80 right top
      focusOn 1
    proc createTop {n fgcolor bgcolor bits hside vtitle} {
      variable arrows
      if {![info exists arrows($n)]} {
        set arrows($n) [makeArrow $bits]
      set w .desk.f$n
      frame $w -bg white -highlightthickness 1 \
        -highlightbackground $fgcolor -highlightcolor $fgcolor
      frame $w.bar
      label $w.bar.t -bg $bgcolor -text F$n -anchor w
      label $w.bar.a -bg $bgcolor -image $arrows($n) -width 15
      frame $w.top -bg white -bd 0
      pack $w.bar -fill x -side $vtitle
      pack $w.bar.a -fill y -side $hside
      pack $w.bar.t -expand 1 -fill x -side $hside
      pack $w.top -expand 1 -fill both -side $vtitle
      setSize $n 350 200
      bind . <F$n> "::gw::focusOn $n"
      bind $w <FocusIn> "::gw::setColor $n $fgcolor; raise $w"
      bind $w <FocusOut> "::gw::setColor $n $bgcolor"
      bind $w.bar.t <1> "::gw::focusOn $n"
      bind $w.bar.a <1> "::gw::focusOn $n %x %y"
      bind $w.bar.a <B1-Motion> "::gw::trackSize $n %x %y"
    proc makeArrow {b} {
      set d [string map [list #m 0x[string map {/ ,0x} $b]] {
        #define _width 8
        #define _height 8
        static char _bits[] = { #m };
      return [image create bitmap -data $d]
    proc focusOn {n {x ""} {y ""}} {
      variable rx $x ry $y
      focus .desk.f$n.top
    proc trackSize {n x y} {
      variable rx
      variable ry
      set w .desk.f$n
      set ax [string map {1 + 2 - 3 - 4 +} $n]
      set ay [string map {1 + 2 + 3 - 4 -} $n]
      set nx [expr [winfo width $w] $ax ($x-$rx)]
      set ny [expr [winfo height $w] $ay ($y-$ry)]
      setSize $n $nx $ny
    proc setSize {n nx ny} {
      #XXX cannot use winfo before geometry has been determined
      #XXX but winfo will be required to deal with desk resizing
      set sx [.desk cget -width] ;#set sx [winfo width .desk]
      set sy [.desk cget -height] ;#set sy [winfo height .desk]
      incr sx -3
      if {$nx > $sx-25} { set nx [expr {$sx-25}] }
      if {$ny > $sy-30} { set ny [expr {$sy-30}] }
      if {$nx < 45} { set nx 45 }
      if {$ny < 25} { set ny 25 }
      switch $n 1 - 4 { set x 3 } default { set x [expr {$sx-$nx}] }
      switch $n 1 - 2 { set y 3 } default { set y [expr {$sy-$ny}] }
      place .desk.f$n -width $nx -height $ny -x $x -y $y
    proc setColor {n color} {
      set w .desk.f$n
      $w.bar.t configure -bg $color
      $w.bar.a configure -bg $color


(Obsolete info about making multiple toplevels work omitted, now that it all works with slave interps)

NEM Regarding the hack to get each app to see a different toplevel widget, I seem to remember that child interps can load Tk with a particular container widget acting as the root for that interp. [2] has details - it's part of the Safe Base package.

jcw - Aha! Thanks, I now also found Embedded Toplevels. Right now, the GooWee "toplevels" are frames. Given that I don't want the usual windows manager borders/decorations, I assume that the way to do it is: 1) create new frameless toplevel, 2) embed it in frame via the -use & -container options, 3) pass the resulting toplevel to scripts (trapping wm title), or 4) use the ::save::loadTk approach with a slave interpreter, as you suggest. Interesting - I never knew such things were possible. Will need to explore the x-platform combinations. Inter-process is less important for me.

Brian Theado - I dug into the ::safe::loadTk a bit and here is a way of doing it using a plain slave interpreter instead of a safe slave interpreter. I guess "package require Tk" looks at the contents of argv for options such as -use [3].
 package require Tk
 pack [frame .f -container 1]
 interp create s
 s eval [list set argv [list -use [winfo id .f]]]
 s eval {
    package require Tk
    pack [text .t]

To illustrate that the slave's text widget is embedded, try:
 pack forget .f

and see the text widget disappear.

jcw - W(h)ee! Thanks Brian, for such a clean solution. Now goowee.kit runs unmodified scripts with a . top-level in a non-safe slave interpreter (only tested on Linux so far) - yes! I only had to wrap "wm deiconify" in a catch in SR's weeCalc, to make it run like a main app. Lost the ability to set the title, will be fixed later.

Whoops, I seem to have lost the ability to switch on F1..F4. No doubt because the window has no way to activate another one.

Brian Theado - I haven't seen that behavior, but I do notice on Windows XP, a text widget (like one created in the above code snippet) can't get the focus whatever I try (clicking, explicitly calling focus in the slave). Button clicks (i.e. clicking tags) work fine. A post on c.l.t [4] suggests this problem exists for entry widgets as well.

20dec04 Brian Theado - The focus problem for embedded text and entry widgets has been resolved in CVS head for win32. See discussion of tk bug 842945 [5] for details. I suppose this will be part of Tk 8.5 and maybe part of 8.4 if there continue to be releases beyond Tk 8.4.9.

08oct04 jcw - GooWee 0.3 adds the GRIDPLUS package, and uses it to present a little welcome screen and basic documentation (this only just scratches the surface of what GRIDPLUS can do). There's still a problem with F1..F4 and button click focus, but the context is very transparent to each weeApp. Resizing the entire desktop now works. Exit is redefined in each slave to only tear down the corresponding app & window. Apps can be launched and replaced using "::gw::launch <n> appname".

14oct04 jsi - Very impressing! I played a little with the Goowee.kit + tclkit on WIN NT4SP6 and on WIN XP Home SP1. Switching focus via F1..F4 works fine. Using F5 to end Goowee works fine too. I noticed that ending Goowee with ALT-F4 (the usual hotkey on windows) or the X-Button in the title-bar crashes Tclkit - as long as one of the four Goowee-windows contains weeCalc.

Category Application - Category GUI