# 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.10 2002/06/13 21:35:09 mdejong 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.

if {[lsearch [namespace children] ::tcltest] == -1} {
    source [file join [pwd] [file dirname [info script]] defs.tcl]
}

proc deleteWindows {} {
    foreach i [winfo children .] {
    	destroy $i
    }
}


deleteWindows

wm deicon .

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-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} {
    wm minsize .t
} {1 1}

test wm-minsize-1.5 {usage} {
    list [catch {wm minsize . x 100} msg]  $msg
} {1 {expected integer but got "x"}}

test wm-minsize-1.6 {usage} {
    list [catch {wm minsize . 100 bogus} msg]  $msg
} {1 {expected integer but got "bogus"}}

test wm-minsize-1.7 {usage} {
    wm minsize .t 200 150
    wm minsize .t
} {200 150}


# 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

return