# This file is a Tcl script to test out Tk's interactions with # the window manager, including the "wm" command. It is organized # in the standard fashion for Tcl tests. # # Copyright (c) 1992-1994 The Regents of the University of California. # Copyright (c) 1994-1997 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # # RCS: @(#) $Id: wm.test,v 1.15 2002/07/13 20:28:36 dgp Exp $ # This file tests window manager interactions that work across # platforms. Window manager tests that only work on a specific # platform should be placed in unixWm.test or winWm.test. package require tcltest 2.1 namespace import -force tcltest::configure namespace import -force tcltest::testsDirectory configure -testdir [file join [pwd] [file dirname [info script]]] configure -loadfile [file join [testsDirectory] constraints.tcl] tcltest::loadTestedCommands wm deiconify . if {![winfo ismapped .]} { tkwait visibility . } test wm-stackorder-1.1 {usage} { list [catch {wm stackorder} err] $err } {1 {wrong # args: should be "wm option window ?arg ...?"}} test wm-stackorder-1.2 {usage} { list [catch {wm stackorder . _} err] $err } {1 {wrong # arguments: must be "wm stackorder window ?isabove|isbelow window?"}} test wm-stackorder-1.3 {usage} { list [catch {wm stackorder . _ _ _} err] $err } {1 {wrong # arguments: must be "wm stackorder window ?isabove|isbelow window?"}} test wm-stackorder-1.4 {usage} { list [catch {wm stackorder . is .} err] $err } {1 {bad argument "is": must be isabove or isbelow}} test wm-stackorder-1.5 {usage} { list [catch {wm stackorder _} err] $err } {1 {bad window path name "_"}} test wm-stackorder-1.6 {usage} { list [catch {wm stackorder . isabove _} err] $err } {1 {bad window path name "_"}} test wm-stackorder-1.7 {usage} { catch {destroy .t} toplevel .t button .t.b list [catch {wm stackorder .t.b} err] $err } {1 {window ".t.b" isn't a top-level window}} test wm-stackorder-1.8 {usage} { catch {destroy .t} toplevel .t button .t.b pack .t.b update list [catch {wm stackorder . isabove .t.b} err] $err } {1 {window ".t.b" isn't a top-level window}} test wm-stackorder-1.9 {usage} { catch {destroy .t} toplevel .t button .t.b pack .t.b update list [catch {wm stackorder . isbelow .t.b} err] $err } {1 {window ".t.b" isn't a top-level window}} test wm-stackorder-1.10 {usage, isabove|isbelow toplevels must be mapped} { catch {destroy .t} toplevel .t ; update wm withdraw .t list [catch {wm stackorder .t isabove .} err] $err } {1 {window ".t" isn't mapped}} test wm-stackorder-1.11 {usage, isabove|isbelow toplevels must be mapped} { catch {destroy .t} toplevel .t ; update wm withdraw .t list [catch {wm stackorder . isbelow .t} err] $err } {1 {window ".t" isn't mapped}} deleteWindows test wm-stackorder-2.1 {} { catch {destroy .t} toplevel .t ; update wm stackorder . } {. .t} test wm-stackorder-2.2 {} { catch {destroy .t} toplevel .t ; update raise . wm stackorder . } {.t .} test wm-stackorder-2.3 {} { catch {destroy .t} toplevel .t ; update catch {destroy .t2} toplevel .t2 ; update raise . raise .t2 wm stackorder . } {.t . .t2} test wm-stackorder-2.4 {} { catch {destroy .t} toplevel .t ; update catch {destroy .t2} toplevel .t2 ; update raise . lower .t2 wm stackorder . } {.t2 .t .} test wm-stackorder-2.5 {} { catch {destroy .parent} toplevel .parent ; update catch {destroy .parent.child1} toplevel .parent.child1 ; update catch {destroy .parent.child2} toplevel .parent.child2 ; update catch {destroy .extra} toplevel .extra ; update raise .parent lower .parent.child2 wm stackorder .parent } {.parent.child2 .parent.child1 .parent} deleteWindows test wm-stackorder-2.6 {non-toplevel widgets ignored} { catch {destroy .t1} toplevel .t1 button .t1.b pack .t1.b update wm stackorder . } {. .t1} deleteWindows test wm-stackorder-2.7 {no children returns self} { wm stackorder . } {.} deleteWindows test wm-stackorder-3.1 {unmapped toplevel} { catch {destroy .t1} toplevel .t1 ; update catch {destroy .t2} toplevel .t2 ; update wm iconify .t1 wm stackorder . } {. .t2} test wm-stackorder-3.2 {unmapped toplevel} { catch {destroy .t1} toplevel .t1 ; update catch {destroy .t2} toplevel .t2 ; update wm withdraw .t2 wm stackorder . } {. .t1} test wm-stackorder-3.3 {unmapped toplevel} { catch {destroy .t1} toplevel .t1 ; update catch {destroy .t2} toplevel .t2 ; update wm withdraw .t2 wm stackorder .t2 } {} test wm-stackorder-3.4 {unmapped toplevel} { catch {destroy .t1} toplevel .t1 ; update toplevel .t1.t2 ; update wm withdraw .t1.t2 wm stackorder .t1 } {.t1} test wm-stackorder-3.5 {unmapped toplevel} { catch {destroy .t1} toplevel .t1 ; update toplevel .t1.t2 ; update wm withdraw .t1 wm stackorder .t1 } {.t1.t2} test wm-stackorder-3.6 {unmapped toplevel} { catch {destroy .t1} toplevel .t1 ; update toplevel .t1.t2 ; update toplevel .t1.t2.t3 ; update wm withdraw .t1.t2 wm stackorder .t1 } {.t1 .t1.t2.t3} test wm-stackorder-3.7 {unmapped toplevel, mapped children returned} { catch {destroy .t1} toplevel .t1 ; update toplevel .t1.t2 ; update wm withdraw .t1 wm stackorder .t1 } {.t1.t2} test wm-stackorder-3.8 {toplevel mapped in idle callback } { catch {destroy .t1} toplevel .t1 wm stackorder . } {.} deleteWindows test wm-stackorder-4.1 {wm stackorder isabove|isbelow} { catch {destroy .t} toplevel .t ; update raise .t wm stackorder . isabove .t } {0} test wm-stackorder-4.2 {wm stackorder isabove|isbelow} { catch {destroy .t} toplevel .t ; update raise .t wm stackorder . isbelow .t } {1} test wm-stackorder-4.3 {wm stackorder isabove|isbelow} { catch {destroy .t} toplevel .t ; update raise . wm stackorder .t isa . } {0} test wm-stackorder-4.4 {wm stackorder isabove|isbelow} { catch {destroy .t} toplevel .t ; update raise . wm stackorder .t isb . } {1} deleteWindows test wm-stackorder-5.1 {a menu is not a toplevel} { catch {destroy .t} toplevel .t menu .t.m -type menubar .t.m add cascade -label "File" .t configure -menu .t.m update raise . wm stackorder . } {.t .} test wm-stackorder-5.2 {A normal toplevel can't be raised above an overrideredirect toplevel } { catch {destroy .t} toplevel .t wm overrideredirect .t 1 raise . update wm stackorder . isabove .t } 0 test wm-stackorder-5.3 {An overrideredirect window can be explicitly lowered } { catch {destroy .t} toplevel .t wm overrideredirect .t 1 lower .t update wm stackorder .t isbelow . } 1 test wm-stackorder-6.1 {An embedded toplevel does not appear in the stacking order} { deleteWindows toplevel .real -container 1 toplevel .embd -bg blue -use [winfo id .real] update wm stackorder . } {. .real} test wm-transient-1.1 {usage} { catch {destroy .t} ; toplevel .t list [catch {wm transient .t 1 2} msg] $msg } {1 {wrong # arguments: must be "wm transient window ?master?"}} test wm-transient-1.2 {usage} { catch {destroy .t} ; toplevel .t list [catch {wm transient .t foo} msg] $msg } {1 {bad window path name "foo"}} test wm-transient-1.3 {usage} { catch {destroy .t} ; toplevel .t list [catch {wm transient foo .t} msg] $msg } {1 {bad window path name "foo"}} test wm-transient-1.4 {usage} { deleteWindows toplevel .master toplevel .subject wm transient .subject .master list [catch {wm iconify .subject} msg] $msg } {1 {can't iconify ".subject": it is a transient}} test wm-transient-1.5 {usage} { deleteWindows toplevel .icon -bg blue toplevel .top wm iconwindow .top .icon toplevel .dummy list [catch {wm transient .icon .dummy} msg] $msg } {1 {can't make ".icon" a transient: it is an icon for .top}} test wm-transient-1.6 {usage} { deleteWindows toplevel .icon -bg blue toplevel .top wm iconwindow .top .icon toplevel .dummy list [catch {wm transient .dummy .icon} msg] $msg } {1 {can't make ".icon" a master: it is an icon for .top}} test wm-transient-1.7 {usage} { deleteWindows toplevel .master list [catch {wm transient .master .master} err] $err } {1 {can't make ".master" its own master}} test wm-transient-1.8 {usage} { deleteWindows toplevel .master frame .master.f list [catch {wm transient .master .master.f} err] $err } {1 {can't make ".master" its own master}} test wm-transient-2.1 { basic get/set of master } { deleteWindows set results [list] toplevel .master toplevel .subject lappend results [wm transient .subject] wm transient .subject .master lappend results [wm transient .subject] wm transient .subject {} lappend results [wm transient .subject] set results } {{} .master {}} test wm-transient-2.2 { first toplevel parent of non-toplevel master is used } { deleteWindows toplevel .master frame .master.f toplevel .subject wm transient .subject .master.f wm transient .subject } {.master} test wm-transient-3.1 { transient toplevel is withdrawn when mapped if master is withdrawn } { deleteWindows toplevel .master wm withdraw .master update toplevel .subject wm transient .subject .master update list [wm state .subject] [winfo ismapped .subject] } {withdrawn 0} test wm-transient-3.2 { already mapped transient toplevel takes on withdrawn state of master } { deleteWindows toplevel .master wm withdraw .master update toplevel .subject update wm transient .subject .master update list [wm state .subject] [winfo ismapped .subject] } {withdrawn 0} test wm-transient-3.3 { withdraw/deiconify on the master also does a withdraw/deiconify on the transient } { deleteWindows set results [list] toplevel .master toplevel .subject update wm transient .subject .master wm withdraw .master update lappend results [wm state .subject] \ [winfo ismapped .subject] wm deiconify .master update lappend results [wm state .subject] \ [winfo ismapped .subject] set results } {withdrawn 0 normal 1} test wm-transient-4.1 { transient toplevel is withdrawn when mapped if master is iconic } { deleteWindows toplevel .master wm iconify .master update toplevel .subject wm transient .subject .master update list [wm state .subject] [winfo ismapped .subject] } {withdrawn 0} test wm-transient-4.2 { already mapped transient toplevel is withdrawn if master is iconic } { deleteWindows toplevel .master wm iconify .master update toplevel .subject update wm transient .subject .master update list [wm state .subject] [winfo ismapped .subject] } {withdrawn 0} test wm-transient-4.3 { iconify/deiconify on the master does a withdraw/deiconify on the transient } { deleteWindows set results [list] toplevel .master toplevel .subject update wm transient .subject .master wm iconify .master update lappend results [wm state .subject] \ [winfo ismapped .subject] wm deiconify .master update lappend results [wm state .subject] \ [winfo ismapped .subject] set results } {withdrawn 0 normal 1} test wm-transient-5.1 { an error during transient command should not cause the map/unmap binding to be deleted } { deleteWindows set results [list] toplevel .master toplevel .subject update wm transient .subject .master # Expect a bad window path error here lappend results [catch {wm transient .subject .bad}] wm withdraw .master update lappend results [wm state .subject] wm deiconify .master update lappend results [wm state .subject] set results } {1 withdrawn normal} test wm-transient-5.2 { remove transient property when master is destroyed } { deleteWindows toplevel .master toplevel .subject wm transient .subject .master update destroy .master update wm transient .subject } {} test wm-transient-5.3 { remove transient property from window that had never been mapped when master is destroyed } { deleteWindows toplevel .master toplevel .subject wm transient .subject .master destroy .master wm transient .subject } {} test wm-transient-6.1 { a withdrawn transient does not track state changes in the master } { deleteWindows toplevel .master toplevel .subject update wm transient .subject .master wm withdraw .subject wm withdraw .master wm deiconify .master # idle handler should not map the transient update wm state .subject } {withdrawn} test wm-transient-6.2 { a withdrawn transient does not track state changes in the master } { set results [list] deleteWindows toplevel .master toplevel .subject update wm transient .subject .master wm withdraw .subject wm withdraw .master wm deiconify .master # idle handler should not map the transient update lappend results [wm state .subject] wm deiconify .subject lappend results [wm state .subject] wm withdraw .master lappend results [wm state .subject] wm deiconify .master # idle handler should map transient update lappend results [wm state .subject] } {withdrawn normal withdrawn normal} test wm-state-1.1 {usage} { list [catch {wm state} err] $err } {1 {wrong # args: should be "wm option window ?arg ...?"}} test wm-state-1.2 {usage} { list [catch {wm state . _ _} err] $err } {1 {wrong # arguments: must be "wm state window ?state?"}} test wm-state-2.1 {initial state} { deleteWindows toplevel .t wm state .t } {normal} test wm-state-2.2 {state change before map} { deleteWindows toplevel .t wm state .t withdrawn wm state .t } {withdrawn} test wm-state-2.3 {state change before map} { deleteWindows toplevel .t wm withdraw .t wm state .t } {withdrawn} test wm-state-2.4 {state change after map} { deleteWindows toplevel .t update wm state .t withdrawn wm state .t } {withdrawn} test wm-state-2.5 {state change after map} { deleteWindows toplevel .t update wm withdraw .t wm state .t } {withdrawn} test wm-state-2.6 {state change before map} { deleteWindows toplevel .t wm state .t iconic wm state .t } {iconic} test wm-state-2.7 {state change before map} { deleteWindows toplevel .t wm iconify .t wm state .t } {iconic} test wm-state-2.8 {state change after map} { deleteWindows toplevel .t update wm state .t iconic wm state .t } {iconic} test wm-state-2.9 {state change after map} { deleteWindows toplevel .t update wm iconify .t wm state .t } {iconic} test wm-state-2.10 {state change before map} { deleteWindows toplevel .t wm withdraw .t wm state .t normal wm state .t } {normal} test wm-state-2.11 {state change before map} { deleteWindows toplevel .t wm withdraw .t wm deiconify .t wm state .t } {normal} test wm-state-2.12 {state change after map} { deleteWindows toplevel .t update wm withdraw .t wm state .t normal wm state .t } {normal} test wm-state-2.13 {state change after map} { deleteWindows toplevel .t update wm withdraw .t wm deiconify .t wm state .t } {normal} test wm-state-2.14 {state change before map} { deleteWindows toplevel .t wm iconify .t wm state .t normal wm state .t } {normal} test wm-state-2.15 {state change before map} { deleteWindows toplevel .t wm iconify .t wm deiconify .t wm state .t } {normal} test wm-state-2.16 {state change after map} { deleteWindows toplevel .t update wm iconify .t wm state .t normal wm state .t } {normal} test wm-state-2.17 {state change after map} { deleteWindows toplevel .t update wm iconify .t wm deiconify .t wm state .t } {normal} test wm-maxsize-1.1 {usage} { list [catch {wm maxsize} msg] $msg } {1 {wrong # args: should be "wm option window ?arg ...?"}} test wm-maxsize-1.2 {usage} { list [catch {wm maxsize . a} msg] $msg } {1 {wrong # arguments: must be "wm maxsize window ?width height?"}} test wm-maxsize-1.3 {usage} { list [catch {wm maxsize . a b c} msg] $msg } {1 {wrong # arguments: must be "wm maxsize window ?width height?"}} test wm-maxsize-1.4 {usage} { list [catch {wm maxsize . x 100} msg] $msg } {1 {expected integer but got "x"}} test wm-maxsize-1.5 {usage} { list [catch {wm maxsize . 100 bogus} msg] $msg } {1 {expected integer but got "bogus"}} test wm-maxsize-1.6 {usage} { wm maxsize .t 200 150 wm maxsize .t } {200 150} test wm-minsize-1.1 {usage} { list [catch {wm minsize} msg] $msg } {1 {wrong # args: should be "wm option window ?arg ...?"}} test wm-minsize-1.2 {usage} { list [catch {wm minsize . a} msg] $msg } {1 {wrong # arguments: must be "wm minsize window ?width height?"}} test wm-minsize-1.3 {usage} { list [catch {wm minsize . a b c} msg] $msg } {1 {wrong # arguments: must be "wm minsize window ?width height?"}} test wm-minsize-1.4 {usage} { list [catch {wm minsize . x 100} msg] $msg } {1 {expected integer but got "x"}} test wm-minsize-1.5 {usage} { list [catch {wm minsize . 100 bogus} msg] $msg } {1 {expected integer but got "bogus"}} test wm-minsize-1.6 {usage} { wm minsize .t 200 150 wm minsize .t } {200 150} test wm-deiconify-1.1 {usage} { list [catch {wm deiconify} err] $err } {1 {wrong # args: should be "wm option window ?arg ...?"}} test wm-deiconify-1.2 {usage} { list [catch {wm deiconify . _} err] $err } {1 {wrong # arguments: must be "wm deiconify window"}} test wm-deiconify-1.3 {usage} { list [catch {wm deiconify _} err] $err } {1 {bad window path name "_"}} test wm-deiconify-2.1 {a window that has never been mapped should not be mapped by a call to deiconify} { deleteWindows toplevel .t wm deiconify .t winfo ismapped .t } 0 test wm-deiconify-2.2 {a window that has already been mapped should be mapped by deiconify} { deleteWindows toplevel .t update idletasks wm withdraw .t wm deiconify .t winfo ismapped .t } 1 test wm-deiconify-2.3 {geometry for an unmapped window should not be calculated by a call to deiconify, it should be done at idle time} { deleteWindows set results {} toplevel .t -width 200 -height 200 lappend results [wm geometry .t] wm deiconify .t lappend results [wm geometry .t] update idletasks lappend results [lindex [split \ [wm geometry .t] +] 0] } {1x1+0+0 1x1+0+0 200x200} test wm-deiconify-2.4 {invoking destroy after a deiconify should not result in a crash because of a callback set on the toplevel} { deleteWindows toplevel .t wm withdraw .t wm deiconify .t destroy .t update } {} # FIXME: # Test delivery of virtual events to the WM. We could check to see # if the window was raised after a button click for example. # This sort of testing may not be possible. deleteWindows tcltest::cleanupTests return