3 # This file defines several procedures for managing the input
6 # Copyright (c) 1994-1995 Sun Microsystems, Inc.
8 # See the file "license.terms" for information on usage and redistribution
9 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 set ckPriv(restrictWindow) {}
15 # This procedure returns the name of the next window after "w" in
16 # "focus order" (the window that should receive the focus next if
17 # Tab is typed in w). "Next" is defined by a pre-order search
18 # of the current window and its descendants, with the stacking
19 # order determining the order of siblings. The "-takefocus" options
20 # on windows determine whether or not they should be skipped.
23 # w - Name of a window.
30 # Descend to just before the first child of the current widget.
33 set children [winfo children $cur]
36 # Look for the next sibling that isn't a top-level.
40 if {$i < [llength $children]} {
41 set cur [lindex $children $i]
42 if {[winfo toplevel $cur] == $cur} {
49 # No more siblings, so go to the current widget's parent.
50 # If it's a top-level, break out of the loop, otherwise
51 # look for its next sibling.
54 if {$parent == $ckPriv(restrictWindow)} break
55 if {[winfo toplevel $cur] == $cur} {
58 set parent [winfo parent $parent]
59 set children [winfo children $parent]
60 set i [lsearch -exact $children $cur]
62 if {($cur == $w) || [ckFocusOK $cur]} {
69 # This procedure returns the name of the previous window before "w" in
70 # "focus order" (the window that should receive the focus next if
71 # Shift-Tab is typed in w). "Next" is defined by a pre-order search
72 # of the current and its descendants, with the stacking
73 # order determining the order of siblings. The "-takefocus" options
74 # on windows determine whether or not they should be skipped.
77 # w - Name of a window.
84 # Collect information about the current window's position
87 # Collect information about the current window's position
88 # among its siblings. Also, if the window is a top-level,
89 # then reposition to just after the last child of the window.
91 if {[winfo toplevel $cur] == $cur || \
92 $cur == $ckPriv(restrictWindow)} {
94 set children [winfo children $cur]
95 set i [llength $children]
97 set parent [winfo parent $cur]
98 set children [winfo children $parent]
99 set i [lsearch -exact $children $cur]
102 # Go to the previous sibling, then descend to its last descendant
103 # (highest in stacking order. While doing this, ignore top-levels
104 # and their descendants. When we run out of descendants, go up
105 # one level to the parent.
109 set cur [lindex $children $i]
110 if {[winfo toplevel $cur] == $cur} {
114 set children [winfo children $parent]
115 set i [llength $children]
118 if {($cur == $w) || [ckFocusOK $cur]} {
126 # This procedure is invoked to decide whether or not to focus on
127 # a given window. It returns 1 if it's OK to focus on the window,
128 # 0 if it's not OK. The code first checks whether the window is
129 # viewable. If not, then it never focuses on the window. Then it
130 # checks the -takefocus option for the window and uses it if it's
131 # set. If there's no -takefocus option, the procedure checks to
132 # see if (a) the widget isn't disabled, and (b) it has some key
133 # bindings. If all of these are true, then 1 is returned.
136 # w - Name of a window.
140 if {![winfo ismapped $w]} {return 0}
141 if {$ckPriv(restrictWindow) != ""} {
142 if {[winfo toplevel $w] == [winfo toplevel $ckPriv(restrictWindow)]} {
143 if {[string first $ckPriv(restrictWindow) $w] != 0} {return 0}
146 set code [catch {$w cget -takefocus} value]
147 if {($code == 0) && ($value != "")} {
150 } elseif {$value == 1} {
151 # For listboxes: don't take focus if nothing selectable
152 if {[winfo class $w] == "Listbox" && [$w size] == 0} {
157 set value [uplevel #0 $value $w]
163 set code [catch {$w cget -state} value]
164 if {($code == 0) && ($value == "disabled")} {
167 regexp Key|Focus "[bind $w] [bind [winfo class $w]]"
170 # ck_RestrictFocus --
172 # This procedure implements restriction of keyboard focus on a
173 # subtree of the widget hierarchy not including toplevels within
178 # w - Name of a window on which the restriction is placed.
179 # current - Returns the current restrict window or an empty
180 # string, if there's no restriction active.
181 # release w - If w is the current restrict window, the restriction is
184 proc ck_RestrictFocus args {
186 set len [llength $args]
187 set opt [lindex $args 0]
188 switch -glob -- $opt {
191 error "bad # arguments: must be \"ck_RestrictFocus window\""
193 if {![winfo exists $opt]} {
194 error "bad window pathname \"$opt\""
196 if {![winfo ismapped $opt]} {
197 error "window \"$opt\" not viewable"
199 set ckPriv(restrictWindow) $opt
200 bind $opt <Destroy> {ck_Unrestrict %W}
201 bind $opt <Unmap> {ck_Unrestrict %W}
205 error "bad # arguments: must be \"ck_RestrictFocus current\""
207 return $ckPriv(restrictWindow)
212 "bad # arguments: must be \"ck_RestrictFocus release window\""
214 set w [lindex $args 1]
218 error "bad option \"$opt\": must be current or release"
225 # This procedure is invoked on Destroy or Unmap events in order
226 # to release a restriction on a window.
229 # w - Name of a window.
231 proc ck_Unrestrict w {
233 if {$w == $ckPriv(restrictWindow)} {
234 set ckPriv(restrictWindow) {}
236 bind $w <Destroy> {# nothing}
237 bind $w <Unmap> {# nothing}