3909N/A Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 0N/A DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A This code is free software; you can redistribute it and/or modify it 0N/A under the terms of the GNU General Public License version 2 only, as 2362N/A published by the Free Software Foundation. Oracle designates this 0N/A particular file as subject to the "Classpath" exception as provided 2362N/A by Oracle in the LICENSE file that accompanied this code. 0N/A This code is distributed in the hope that it will be useful, but WITHOUT 0N/A ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A version 2 for more details (a copy is included in the LICENSE file that 0N/A accompanied this code). 0N/A You should have received a copy of the GNU General Public License version 0N/A 2 along with this work; if not, write to the Free Software Foundation, 0N/A Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
0N/A <
title align=center>The AWT Focus Subsystem</
title>
0N/A <
body bgcolor="white">
0N/A <
h1 align=center>The AWT Focus Subsystem</
h1>
0N/A Prior to Java 2 Standard Edition, JDK 1.4, the AWT focus subsystem
0N/A was inadequate. It suffered from major design and API problems,
0N/A as well as over a hundred open bugs. Many of these bugs were caused by
0N/A platform inconsistencies, or incompatibilities between the native
0N/A focus system for heavyweights and the Java focus system for
0N/A The single worst problem with the AWT focus implementation was the
0N/A inability to query for the currently focused Component. Not only was
0N/A there no API for such a query, but also, because of an insufficient
0N/A architecture, such information was not even maintained by the code.
0N/A Almost as bad was the inability of lightweight children of a Window
0N/A (not a Frame or a Dialog) to receive keyboard input. This problem
0N/A existed because Windows never received <
code>WINDOW_ACTIVATED</
code>
0N/A events and thus could never be activated, and only active Windows
0N/A could contain focused Components.
0N/A In addition, many developers noted that the APIs for FocusEvent and
0N/A WindowEvent were insufficient because they did not provide a way for
0N/A determining the "opposite" Component involved in the focus or
0N/A activation change. For example, when a Component received a FOCUS_LOST
0N/A event, it had no way of knowing which Component was gaining
0N/A focus. Since Microsoft Windows provides this functionality for free,
0N/A developers migrating from Microsoft Windows C/C++ or Visual Basic to
0N/A Java had been frustrated by the omission.
0N/A To address these and other deficiencies, we have designed a new focus
0N/A model for the AWT in JDK 1.4. The primary design changes were the
0N/A construction of a new centralized KeyboardFocusManager class, and a
0N/A lightweight focus architecture. The amount of focus-related,
0N/A platform-dependent code has been minimized and replaced by fully
0N/A pluggable and extensible public APIs in the AWT. While we have
0N/A attempted to remain backward compatible with the existing
0N/A implementation, we were forced to make minor incompatible changes in
0N/A order to reach an elegant and workable conclusion. We anticipate that
0N/A these incompatibilities will have only a trivial impact on existing
0N/A This document is a formal specification both of the new APIs and of
0N/A existing APIs which remain relevant in the new model. Combined with
0N/A the javadoc for focus-related classes and methods, this document
0N/A should enable developers to create substantial AWT and Swing
0N/A applications with a focus behavior that is customized yet consistent
0N/A across platforms. This document has the following sections:
0N/A <
li><
a href=#
Overview>Overview of KeyboardFocusManager</
a>
0N/A <
li><
a href=#
BrowserContexts>KeyboardFocusManager and Browser Contexts</
a>
0N/A <
li><
a href=#
KeyEventDispatcher>KeyEventDispatcher</
a>
0N/A <
li><
a href=#
FocusEventAndWindowEvent>FocusEvent and WindowEvent</
a>
0N/A <
li><
a href=#
EventDelivery>Event Delivery</
a>
0N/A <
li><
a href=#
OppositeComponents>Opposite Components and Windows</
a>
0N/A <
li><
a href=#
TemporaryFocusEvents>Temporary FocusEvents</
a>
0N/A <
li><
a href=#
FocusTraversal>Focus Traversal</
a>
0N/A <
li><
a href=#
FocusTraversalPolicy>Focus Traversal Policy</
a>
0N/A <
li><
a href=#
FocusTraversalPolicyProviders>Focus Traversal Policy Providers</
a>
0N/A <
li><
a href=#
ProgrammaticTraversal>Programmatic Traversal</
a>
0N/A <
li><
a href=#
Focusability>Focusability</
a>
0N/A <
li><
a href=#
FocusableWindows>Focusable Windows</
a>
0N/A <
li><
a href=#
RequestingFocus>Requesting Focus</
a>
0N/A <
li><
a href=#
FocusAndPropertyChangeListener>Focus and PropertyChangeListener</
a>
0N/A <
li><
a href=#
FocusAndVetoableChangeListener>Focus and VetoableChangeListener</
a>
0N/A <
li><
a href=#
ZOrder>Z-Order</
a>
0N/A <
li><
a href=#
ReplacingDefaultKeyboardFocusManager>Replacing DefaultKeyboardFocusManager</
a>
0N/A <
li><
a href=#
Incompatibilities>Incompatibilities with Previous Releases</
a>
0N/A <
a name="Overview"></
a>
0N/A <
h3>Overview of KeyboardFocusManager</
h3>
0N/A The focus model is centralized around a single class,
0N/A KeyboardFocusManager, that provides a set of APIs for client code to
0N/A inquire about the current focus state, initiate focus changes, and
0N/A replace default focus event dispatching with a custom dispatcher.
0N/A Clients can inquire about the focus state directly, or can register a
0N/A PropertyChangeListener that will receive PropertyChangeEvents when a
0N/A change to the focus state occurs.
0N/A KeyboardFocusManager introduces the following main concepts and their
0N/A <
li>The "focus owner" -- the Component which typically receives
0N/A <
li>The "permanent focus owner" -- the last Component to receive
0N/A focus permanently. The "focus owner" and the "permanent focus
0N/A owner" are equivalent unless a temporary focus change is
0N/A currently in effect. In such a situation, the "permanent focus
0N/A owner" will again be the "focus owner" when the temporary focus
0N/A <
li>The "focused Window" -- the Window which contains the "focus
0N/A <
li>The "active Window" -- the Frame or Dialog that is either the
0N/A "focused Window", or the first Frame or Dialog that is an owner
0N/A of the "focused Window".
0N/A <
li>"Focus traversal" -- the user's ability to change the "focus
0N/A owner" without moving the cursor. Typically, this is done using
0N/A the keyboard (for example, by using the TAB key), or an
0N/A equivalent device in an accessible environment. Client code can
0N/A also initiate traversal programmatically. Normal focus traversal
0N/A can be either "forward" to the "next" Component, or "backward" to
0N/A the "previous" Component.
0N/A <
li>"Focus traversal cycle" -- a portion of the Component hierarchy,
0N/A such that normal focus traversal "forward" (or "backward") will
0N/A traverse through all of the Components in the focus cycle, but no
0N/A other Components. This cycle provides a mapping from an arbitrary
0N/A Component in the cycle to its "next" (forward traversal) and
0N/A "previous" (backward traversal) Components.
0N/A <
li>"Traversable Component" -- Component that is in the focus traversal
0N/A <
li>"Non-traversable Component" -- Component that is not in the focus
0N/A traversal cycle. Note that a non-traversable Component can nevertheless
0N/A be focused in other way (
e.g. by direct focus request).
0N/A <
li>"Focus cycle root" -- Container that is the root of the Component
0N/A hierarchy for a particular "focus traversal cycle". When the
0N/A "focus owner" is a Component inside a particular cycle, normal
0N/A forward and backward focus traversal cannot move the "focus
0N/A owner" above the focus cycle root in the Component hierarchy.
0N/A Instead, two additional traversal operations, "up cycle" and
0N/A "down cycle", are defined to allow keyboard and programmatic
0N/A navigation up and down the focus traversal cycle hierarchy. </
li>
0N/A <
li>"Focus traversal policy provider" - Container which has
0N/A "FocusTraversalPolicyProvider" property as true. This Container will
0N/A be used to acquire focus traversal policy. This container doesn't
0N/A define new focus cycle but only modifies the order by which its
0N/A children are traversed "forward" and "backward". Focus traversal
0N/A policy provider can be set using
0N/A <
code>setFocusTraversalPolicyProvider</
code> on the Container.
0N/A Every Window and JInternalFrame is, by default, a "focus cycle
0N/A root". If it's the only focus cycle root, then all of its
0N/A focusable descendants should be in its focus cycle, and its focus
0N/A traversal policy should enforce that they are by making sure that
0N/A all will be reached during normal forward (or backward)
0N/A traversal. If, on the other hand, the Window or JInternalFrame
0N/A has descendants that are also focus cycle roots, then each such
0N/A descendant is a member of two focus cycles: the one that it is
0N/A the root of, and the one of its nearest focus-cycle-root
0N/A ancestor. In order to traverse the focusable components belonging
0N/A to the focus cycle of such a "descendant" focus cycle root, one
0N/A first traverses (forward or backward) to reach the descendant,
0N/A and then uses the "down cycle" operation to reach, in turn, its
0N/A alt="Three groups as described below: ABCF BDE and DGH. "><
br>
0N/A <
p>Assume the following:
0N/A <
li><
b>A</
b> is a <
code>Window</
code>, which means that it
0N/A must be a focus cycle root.
0N/A <
li><
b>B</
b> and <
b>D</
b> are <
code>Container</
code>s that
0N/A are focus cycle roots.
0N/A <
li><
b>C</
b> is a <
code>Container</
code> that is not a focus cycle root.
0N/A <
li><
b>G</
b>, <
b>H</
b>, <
b>E</
b>, and <
b>F</
b> are all
0N/A <
code>Component</
code>s.
0N/A There are a total of three focus cycle roots in this example:
0N/A <
li><
b>A</
b> is a root, and <
b>A</
b>, <
b>B</
b>, <
b>C</
b>,
0N/A and <
b>F</
b> are members of <
b>A</
b>'s cycle.
0N/A <
li><
b>B</
b> is a root, and <
b>B</
b>, <
b>D</
b>, and
0N/A <
b>E</
b> are members of <
b>B</
b>'s cycle.
0N/A <
li><
b>D</
b> is a root, and <
b>D</
b>, <
b>G</
b>,
0N/A and <
b>H</
b> are members of <
b>D</
b>'s cycle.
0N/A Windows are the only Containers which, by default, are focus cycle
0N/A<
code>KeyboardFocusManager</
code> is an abstract class. AWT provides a default
0N/Aimplementation in the <
code>DefaultKeyboardFocusManager</
code> class.
0N/A<
a name="BrowserContexts"></
a>
0N/A<
h3>KeyboardFocusManager and Browser Contexts</
h3>
0N/ASome browsers partition applets in different code bases into separate
0N/Acontexts, and establish walls between these contexts. Each thread and
0N/Aeach Component is associated with a particular context and cannot
0N/Ainterfere with threads or access Components in other contexts. In such
0N/Aa scenario, there will be one KeyboardFocusManager per context. Other
0N/Abrowsers place all applets into the same context, implying that there
0N/Awill be only a single, global KeyboardFocusManager for all
0N/Aapplets. This behavior is implementation-dependent. Consult your
0N/Abrowser's documentation for more information. No matter how many
0N/Acontexts there may be, however, there can never be more than one focus
0N/Aowner, focused Window, or active Window, per ClassLoader.
0N/A<
a name="KeyEventDispatcher"></
a>
0N/A<
h3>KeyEventDispatcher and KeyEventPostProcessor</
h3>
0N/AWhile the user's KeyEvents should generally be delivered to the focus
0N/Aowner, there are rare cases where this is not desirable. An input
0N/Amethod is an example of a specialized Component that should receive
0N/AKeyEvents even though its associated text Component is and should
0N/Aremain the focus owner.
0N/AA KeyEventDispatcher is a lightweight interface that allows client
0N/Acode to pre-listen to all KeyEvents in a particular context. Instances
0N/Aof classes that implement the interface and are registered with the
0N/Acurrent KeyboardFocusManager will receive KeyEvents before they are
0N/Adispatched to the focus owner, allowing the KeyEventDispatcher to
0N/Aretarget the event, consume it, dispatch it itself, or make other
0N/AFor consistency, KeyboardFocusManager itself is a
0N/AKeyEventDispatcher. By default, the current KeyboardFocusManager will
0N/Abe the sink for all KeyEvents not dispatched by the registered
0N/AKeyEventDispatchers. The current KeyboardFocusManager cannot be
0N/Acompletely deregistered as a KeyEventDispatcher. However, if a
0N/AKeyEventDispatcher reports that it dispatched the KeyEvent, regardless
0N/Aof whether it actually did so, the KeyboardFocusManager will take no
0N/Afurther action with regard to the KeyEvent. (While it is possible for
0N/Aclient code to register the current KeyboardFocusManager as a
0N/AKeyEventDispatcher one or more times, there is no obvious reason why
0N/Athis would be necessary, and therefore it is not recommended.)
0N/AClient-code may also post-listen to KeyEvents in a particular context
0N/Ausing the KeyEventPostProcessor interface. KeyEventPostProcessors
0N/Aregistered with the current KeyboardFocusManager will receive
0N/AKeyEvents after the KeyEvents have been dispatched to and handled by
0N/Athe focus owner. The KeyEventPostProcessors will also receive
0N/AKeyEvents that would have been otherwise discarded because no
0N/AComponent in the application currently owns the focus. This will allow
0N/Aapplications to implement features that require global KeyEvent post-
0N/Ahandling, such as menu shortcuts.
0N/ALike KeyEventDispatcher, KeyboardFocusManager also implements
0N/AKeyEventPostProcessor, and similar restrictions apply to its use in
0N/A<
a name="FocusEventAndWindowEvent"></
a>
0N/A<
h3>FocusEvent and WindowEvent</
h3>
0N/AThe AWT defines the following six event types central to the focus
0N/A dispatched to a Frame or Dialog (but never a Window which
0N/A is not a Frame or Dialog) when it becomes the active Window.
0N/A dispatched to a Window when it becomes the focused Window.
0N/A Only focusable Windows can receive this event.
0N/A to a Component when it becomes the focus owner. Only focusable
0N/A Components can receive this event.
0N/A to a Component when it is no longer the focus owner.
0N/A dispatched to a Window when it is no longer the focused Window.
0N/A dispatched to a Frame or Dialog (but never a Window which is
0N/A not a Frame or Dialog) when it is no longer the active Window.
0N/A<
a name="EventDelivery"></
a>
0N/A<
h3>Event Delivery</
h3>
0N/AIf the focus is not in java application and the user clicks on a focusable
0N/Achild Component<
b>a</
b> of an inactive Frame <
b>b</
b>, the following events
0N/Awill be dispatched and handled in order:
0N/A <
li><
b>b</
b> will receive a <
code>WINDOW_ACTIVATED</
code> event.
0N/A <
li>Next, <
b>b</
b> will receive a <
code>WINDOW_GAINED_FOCUS</
code> event.
0N/A <
li>Finally, <
b>a</
b> will receive a <
code>FOCUS_GAINED</
code> event.
0N/AIf the user later clicks on a focusable child Component <
b>c</
b> of another
0N/AFrame <
b>d</
b>, the following events will be dispatched and handled in
0N/A <
li><
b>a</
b> will receive a <
code>FOCUS_LOST</
code> event.
0N/A <
li><
b>b</
b> will receive a <
code>WINDOW_LOST_FOCUS</
code> event.
0N/A <
li><
b>b</
b> will receive a <
code>WINDOW_DEACTIVATED</
code> event.
0N/A <
li><
b>d</
b> will receive a <
code>WINDOW_ACTIVATED</
code> event.
0N/A <
li><
b>d</
b> will receive a <
code>WINDOW_GAINED_FOCUS</
code> event.
0N/A <
li><
b>c</
b> will receive a <
code>FOCUS_GAINED</
code> event.
0N/ANote that each event will be fully handled before the next event is
0N/Adispatched. This restriction will be enforced even if the Components
0N/Aare in different contexts and are handled on different event
0N/AIn addition, each event type will be dispatched in 1-to-1
0N/Acorrespondence with its opposite event type. For example, if a
0N/AComponent receives a <
code>FOCUS_GAINED</
code> event, under no
0N/Acircumstances can it ever receive another <
code>FOCUS_GAINED</
code>
0N/Aevent without an intervening <
code>FOCUS_LOST</
code> event.
0N/AFinally, it is important to note that these events are delivered for
0N/Ainformational purposes only. It is impossible, for example, to prevent
0N/Athe delivery of a pending <
code>FOCUS_GAINED</
code> event by requesting
0N/Afocus back to the Component losing focus while handling the preceding
0N/A<
code>FOCUS_LOST</
code> event. While client code may make such a request,
0N/Athe pending <
code>FOCUS_GAINED</
code> will still be delivered,
0N/Afollowed later by the events transferring focus back to the original
0N/AIf it is absolutely necessary to suppress the <
code>FOCUS_GAINED</
code> event,
0N/Aclient code can install a <
code>VetoableChangeListener</
code> which
0N/Arejects the focus change. See <
a href="#FocusAndVetoableChangeListener">Focus
0N/Aand VetoableChangeListener</
a>.
0N/A<
a name="OppositeComponents"></
a>
0N/A<
h3>Opposite Components and Windows</
h3>
0N/AEach event includes information about the "opposite" Component or
0N/AWindow involved in the focus or activation change. For example, for a
0N/A<
code>FOCUS_GAINED</
code> event, the opposite Component is the Component
0N/Athat lost focus. If the focus or activation change occurs with a native
0N/Aapplication, with a Java application in a different VM or context, or
0N/Awith no other Component, then the opposite Component or Window is
0N/Anull. This information is accessible using
0N/AOn some platforms, it is not possible to discern the opposite
0N/AComponent or Window when the focus or activation change occurs between
0N/Atwo different heavyweight Components. In these cases, the opposite
0N/AComponent or Window may be set to null on some platforms, and to a
0N/Avalid non-null value on other platforms. However, for a focus change
0N/Abetween two lightweight Components which share the same heavyweight
0N/AContainer, the opposite Component will always be set correctly. Thus,
0N/Aa pure Swing application can ignore this platform restriction when
0N/Ausing the opposite Component of a focus change that occurred within a
0N/A<
a name="TemporaryFocusEvents"></
a>
0N/A<
h3>Temporary FocusEvents</
h3>
0N/A<
code>FOCUS_GAINED</
code> and <
code>FOCUS_LOST</
code> events are
0N/Amarked as either temporary or permanent.
0N/ATemporary <
code>FOCUS_LOST</
code> events are sent when a Component is
0N/Alosing the focus, but will regain the focus shortly. These events
0N/Acan be useful when focus changes are used as triggers for validation
0N/Aof data. For instance, a text Component may want to commit its
0N/Acontents when the user begins interacting with another Component,
0N/Aand can accomplish this by responding to <
code>FOCUS_LOST</
code> events.
0N/AHowever, if the <
code>FocusEvent</
code> received is temporary,
0N/Athe commit should not be done, since the text field will be receiving
0N/Athe focus again shortly.
0N/AA permanent focus transfer typically occurs as the result of a user
0N/Aclicking on a selectable, heavyweight Component, focus traversal with
0N/Athe keyboard or an equivalent input device, or from a call to
0N/A<
code>requestFocus()</
code> or <
code>requestFocusInWindow()</
code>.
0N/AA temporary focus transfer typically occurs as the result of showing a
0N/AMenu or PopupMenu, clicking or dragging a Scrollbar, moving a Window
0N/Aby dragging the title bar, or making another Window the focused
0N/AWindow. Note that on some platforms, these actions may not generate
0N/Aany FocusEvents at all. On others, temporary focus transfers will
0N/AWhen a Component receives a temporary <
code>FOCUS_LOST</
code> event,
0N/Athe event's opposite Component (if any) may receive a temporary
0N/A<
code>FOCUS_GAINED</
code> event, but could also receive a permanent
0N/A<
code>FOCUS_GAINED</
code> event. Showing a Menu or PopupMenu, or
0N/Aclicking or dragging a Scrollbar, should generate a temporary
0N/A<
code>FOCUS_GAINED</
code> event. Changing the focused Window,
0N/Ahowever, will yield a permanent <
code>FOCUS_GAINED</
code> event
0N/Afor the new focus owner.
0N/AThe Component class includes variants of <
code>requestFocus</
code> and
0N/A<
code>requestFocusInWindow</
code> which take a desired temporary state as a
0N/Aparameter. However, because specifying an arbitrary temporary state
0N/Amay not be implementable on all native windowing systems, correct
0N/Abehavior for this method can be guaranteed only for lightweight
0N/AComponents. This method is not intended for general use, but exists
0N/Ainstead as a hook for lightweight Component libraries, such as Swing.
0N/A<
a name="FocusTraversal"></
a>
0N/A<
h3>Focus Traversal</
h3>
0N/AEach Component defines its own Set of focus traversal keys for a given
0N/Afocus traversal operation. Components support separate Sets of keys
0N/Afor forward and backward traversal, and also for traversal up one
0N/Afocus traversal cycle. Containers which are focus cycle roots also
0N/Asupport a Set of keys for traversal down one focus traversal cycle. If
0N/Aa Set is not explicitly defined for a Component, that Component
0N/Arecursively inherits a Set from its parent, and ultimately from a
0N/Acontext-wide default set on the current <
code>KeyboardFocusManager</
code>.
0N/AUsing the <
code>AWTKeyStroke</
code> API, client code can specify
0N/Aon which of two specific KeyEvents, <
code>KEY_PRESSED</
code> or
0N/A<
code>KEY_RELEASED</
code>, the focus traversal operation will occur.
0N/ARegardless of which KeyEvent is specified, however, all KeyEvents
0N/Arelated to the focus traversal key, including the associated
0N/A<
code>KEY_TYPED</
code> event, will be consumed, and will not be
0N/Adispatched to any Component. It is a runtime error to specify a
0N/A<
code>KEY_TYPED</
code> event as mapping to a focus traversal operation,
0N/Aor to map the same event to multiple focus traversal operations for any
0N/Aparticular Component or for a <
code>KeyboardFocusManager</
code>'s defaults.
0N/AThe default focus traversal keys are implementation-dependent. Sun
0N/Arecommends that the all implementations for a particular native
0N/Aplatform use the same keys. For Windows and Unix, the recommendations
0N/A <
li>traverse forward to the next Component:
0N/A <
br><
i>TextAreas</
i>: <
code>CTRL-TAB</
code> on <
code>KEY_PRESSED</
code>
0N/A <
br><
i>All others</
i>: <
code>TAB</
code> on <
code>KEY_PRESSED</
code> and
0N/A <
code>CTRL-TAB</
code> on <
code>KEY_PRESSED</
code>
0N/A <
li>traverse backward to the previous Component:
0N/A <
br><
i>TextAreas</
i>: <
code>CTRL-SHIFT-TAB</
code> on
0N/A <
code>KEY_PRESSED</
code>
0N/A <
br><
i>All others</
i>: <
code>SHIFT-TAB</
code> on <
code>KEY_PRESSED</
code>
0N/A and <
code>CTRL-SHIFT-TAB</
code> on
0N/A <
code>KEY_PRESSED</
code>
0N/A <
li>traverse up one focus traversal cycle : <none>
0N/A <
li>traverse down one focus traversal cycle : <none>
0N/AComponents can enable and disable all of their focus traversal keys en
0N/Atraversal keys are disabled, the Component receives all KeyEvents for
0N/Athose keys. When focus traversal keys are enabled, the Component never
0N/Areceives KeyEvents for traversal keys; instead, the KeyEvents are
0N/Aautomatically mapped to focus traversal operations.
0N/AFor normal forward and backward traversal, the AWT focus
0N/Aimplementation determines which Component to focus next based on the
0N/A<
a href=#
FocusTraversalPolicy><
code>FocusTraversalPolicy</
code></
a> of
0N/Athe focus owner's focus cycle root or focus traversal policy provider. If the
0N/Afocus owner is a focus cycle root, then it may be ambiguous as to which
0N/AComponents represent the next and previous Components to focus during
0N/Anormal focus traversal. Thus, the current
0N/A<
code>KeyboardFocusManager</
code> maintains a reference to the
0N/A"current" focus cycle root, which is global across all contexts. The
0N/Acurrent focus cycle root is used to resolve the ambiguity.
0N/AFor up-cycle traversal, the focus owner is set to the current focus
0N/Aowner's focus cycle root, and the current focus cycle root is set to
0N/Athe new focus owner's focus cycle root. If, however, the current focus
0N/Aowner's focus cycle root is a top-level window, then the focus owner
0N/Ais set to the focus cycle root's default component to focus, and the
0N/Acurrent focus cycle root is unchanged.
0N/AFor down-cycle traversal, if the current focus owner is a focus cycle
0N/Aroot, then the focus owner is set to the current focus owner's default
0N/Acomponent to focus, and the current focus cycle root is set to the
0N/Acurrent focus owner. If the current focus owner is not a focus cycle
0N/Aroot, then no focus traversal operation occurs.
0N/A<
a name="FocusTraversalPolicy"></
a>
0N/A<
h3>FocusTraversalPolicy</
h3>
0N/AA <
code>FocusTraversalPolicy</
code> defines the order in which Components within
0N/Aa particular focus cycle root or focus traversal policy provider are
0N/Atraversed. Instances of <
code>FocusTraversalPolicy</
code> can be shared across
0N/AContainers, allowing those Containers to implement the same traversal policy.
0N/AFocusTraversalPolicies do not need to be reinitialized when the
0N/Afocus-traversal-cycle hierarchy changes.
0N/AEach <
code>FocusTraversalPolicy</
code> must define the following
0N/A <
li>Given a focus cycle root and a Component <
b>a</
b> in that cycle, the
0N/A next Component after <
b>a</
b>.
0N/A <
li>Given a focus cycle root and a Component <
b>a</
b> in that cycle, the
0N/A previous Component before <
b>a</
b>.
0N/A <
li>Given a focus cycle root, the "first" Component in that cycle.
0N/A The "first" Component is the Component to focus when traversal
0N/A wraps in the forward direction.
0N/A <
li>Given a focus cycle root, the "last" Component in that cycle.
0N/A The "last" Component is the Component to focus when traversal
0N/A wraps in the reverse direction.
0N/A <
li>Given a focus cycle root, the "default" Component in that cycle.
0N/A The "default" Component will be the first to receive focus when
0N/A traversing down into a new focus traversal cycle. This may be the
0N/A same as the "first" Component, but need not be.
0N/AA <
code>FocusTraversalPolicy</
code> may optionally provide an
0N/Aalgorithm for the following:
0N/A Given a Window, the "initial" Component in that Window. The initial
0N/A Component will be the first to receive focus when the Window is
0N/A first made visible. By default, this is the same as the "default"
0N/AIn addition, Swing provides a subclass of <
code>FocusTraversalPolicy</
code>,
0N/A<
code>InternalFrameFocusTraversalPolicy</
code>, which allows developers
0N/Ato provide an algorithm for the following:
0N/A Given a <
code>JInternalFrame</
code>, the "initial" Component in that
0N/A <
code>JInternalFrame</
code>. The initial Component is the first to
0N/A receive focus when the <
code>JInternalFrame</
code> is first selected.
0N/A By default, this is the same as the <
code>JInternalFrame</
code>'s
0N/A default Component to focus.
0N/AA <
code>FocusTraversalPolicy</
code> is installed on a Container using
0N/AContainer.<
code>setFocusTraversalPolicy</
code>. If a policy is not explicitly
0N/Aset, then a Container inherits its policy from its nearest focus-cycle-root
0N/Aancestor. Top-levels initialize their focus traversal policies using the context
0N/Adefault policy. The context default policy is established by using
0N/AKeyboardFocusManager. <
code>setDefaultFocusTraversalPolicy</
code>.
0N/AAWT provides two standard <
code>FocusTraversalPolicy</
code>
0N/Aimplementations for use by client code.
0N/A <
li><
code>ContainerOrderFocusTraversalPolicy</
code>: Iterates across the
0N/A Components in a focus traversal cycle in the order they were added
0N/A to their Containers. Each Component is tested for fitness using the
0N/A accept(Component) method. By default, a Component is fit only if it
0N/A is visible, displayable, enabled, and focusable.
0N/A <
li>By default, ContainerOrderFocusTraversalPolicy implicitly transfers
0N/A focus down-cycle. That is, during normal forward focus traversal,
0N/A the Component traversed after a focus cycle root will be the
0N/A focus-cycle-root's default Component to focus, regardless of whether
0N/A the focus cycle root is a traversable or non-traversable Container
0N/A (see the pic.1,2 below). Such behavior provides backward compatibility
0N/A with applications designed without the concepts of up- and down-cycle
0N/A <
li><
code>DefaultFocusTraversalPolicy</
code>: A subclass of
0N/A <
code>ContainerOrderFocusTraversalPolicy</
code> which redefines
0N/A the fitness test. If client code has explicitly set the
0N/A focusability of a Component by either overriding
0N/A <
code>DefaultFocusTraversalPolicy</
code> behaves exactly
0N/A like a <
code>ContainerOrderFocusTraversalPolicy</
code>. If,
0N/A however, the Component is relying on default focusability, then a
0N/A <
code>DefaultFocusTraversalPolicy</
code> will reject all
0N/A Components with non-focusable peers.
0N/A The focusability of a peer is implementation-dependent. Sun
0N/A recommends that all implementations for a particular native platform
0N/A construct peers with the same focusability. The recommendations for
0N/A Windows and Unix are that Canvases, Labels, Panels, Scrollbars,
0N/A ScrollPanes, Windows, and lightweight Components have non-focusable
0N/A peers, and all other Components have focusable peers. These
0N/A recommendations are used in the Sun AWT implementations. Note that
0N/A the focusability of a Component's peer is different from, and does
0N/A not impact, the focusability of the Component itself.
0N/ASwing provides two additional, standard FocusTraversalPolicy
0N/Aimplementations for use by client code. Each implementation is an
0N/AInternalFrameFocusTraversalPolicy.
0N/A <
li>SortingFocusTraversalPolicy: Determines traversal order by
0N/A sorting the Components of a focus traversal cycle based on a given
0N/A Comparator. Each Component is tested for fitness using the
0N/A accept(Component) method. By default, a Component is fit only if it
0N/A is visible, displayable, enabled, and focusable.
0N/A <
li>By default, SortingFocusTraversalPolicy implicitly transfers focus
0N/A down-cycle. That is, during normal forward focus traversal, the
0N/A Component traversed after a focus cycle root will be the
0N/A focus-cycle-root's default Component to focus, regardless of
0N/A whether the focus cycle root is a traversable or non-traversable
0N/A Container (see the pic.1,2 below). Such behavior provides backward
0N/A compatibility with applications designed without the concepts of
0N/A up- and down-cycle traversal.
0N/A <
li>LayoutFocusTraversalPolicy: A subclass of
0N/A SortingFocusTraversalPolicy which sorts Components based on their
0N/A size, position, and orientation. Based on their size and position,
0N/A Components are roughly categorized into rows and columns. For a
0N/A Container with horizontal orientation, columns run left-to-right or
0N/A right-to-left, and rows run top-to-bottom. For a Container with
0N/A vertical orientation, columns run top-to-bottom and rows run
0N/A left-to-right or right-to-left. All columns in a row are fully
0N/A traversed before proceeding to the next row.
0N/A In addition, the fitness test is extended to exclude JComponents
0N/A that have or inherit empty InputMaps.
0N/AThe figure below shows an implicit focus transfer:
0N/AAssume the following:
0N/A <
li><
b>A</
b>, <
b>B</
b> and <
b>C</
b> are components in some window (a container)
0N/A <
li><
b>R</
b> is a container in the window and it is a parent of <
b>B</
b> and <
b>C</
b>.
0N/A Besides, <
b>R</
b> is a focus cycle root.
0N/A <
li><
b>B</
b> is the default component in the focul traversal cycle of <
b>R</
b>
0N/A <
li><
b>R</
b> is a traversable Container in the pic.1, and it is a non-traversable
0N/A Container in the pic.2.
0N/A <
li>In such a case a forward traversal will look as follows:
0N/A <
li> pic.1 : <
b>A</
b> -> <
b>R</
b> -> <
b>B</
b> -> <
b>C</
b>
0N/A <
li> pic.2 : <
b>A</
b> -> <
b>B</
b> -> <
b>C</
b>
0N/ASwing applications, or mixed
Swing/
AWT applications, that use one of
0N/Athe standard look and feels, or any other look and feel derived from
0N/ABasicLookAndFeel, will use LayoutFocusTraversalPolicy for all
0N/AContainers by default.
0N/AAll other applications, including pure AWT applications, will use
0N/A<
code>DefaultFocusTraversalPolicy</
code> by default.
0N/A<
a name="FocusTraversalPolicyProviders"></
a>
0N/A<
h3>Focus Traversal Policy Providers</
h3>
0N/A A Container that isn't a focus cycle root has an option to provide a
0N/A FocusTraversalPolicy of its own. To do so, one needs to set Container's focus
0N/A traversal policy provider property to <
code>true</
code> with the call to
0N/A To determine whether a Container is a focus traversal policy provider, the
0N/A following method should be used:
0N/A If focus traversal policy provider property is set on a focus cycle root, it
0N/A isn't considered a focus traversal policy provider and behaves just like any
0N/A other focus cycle root.
0N/A The main difference between focus cycle roots and focus traversal policy
0N/A providers is that the latter allow focus to enter and leave them just as all other
0N/A Containers. However, children inside focus traversal policy provider are
0N/A traversed in the order determined by provider's FocusTraversalPolicy. In order
0N/A to enable focus traversal policy providers to behave this way,
0N/A FocusTraversalPolicies treat them in the following manner:
0N/A <
li> Focus traversal policy providers can be passed to FocusTraversalPolicy
0N/A methods instead of focus cycle roots.
0N/A <
li> When calculating next or previous Component in
0N/A <
li>if a Component is a child of a focus traversal policy provider,
0N/A the next and previous for this Component are determined using this
0N/A focus traversal policy provider's FocusTraversalPolicy. However,
0N/A in order for focus to leave the provider, the following rules are
0N/A <
li> if at some point the <
code>next</
code> found Component is
0N/A the <
code>first</
code> Component of focus traversal policy
0N/A provider, the Component after the focus traversal policy
0N/A provider is returned
0N/A <
li> if at some point the <
code>previous</
code> found Component is
0N/A the <
code>last</
code> Component of focus traversal policy
0N/A provider, the Component before the focus traversal policy
0N/A provider is returned
0N/A <
li> When calculating the next Component in
0N/A <
li> if an obtained Component is a non-traversable Container and
0N/A it is a focus traversal policy provider, then the default Component
0N/A of that provider is returned
0N/A method is a traversable Container and it is a focus
0N/A traversal policy provider, then the default Component of this provider
0N/A <
li> When calculating the previous Component in
0N/A <
li> if an obtained Component is a Container (traversable or
0N/A non-traversable) and it is a focus traversal policy provider, then
0N/A the last Component of that provider is returned
0N/A <
li> if an obtained Component is a non-traversable Container and it is a focus
0N/A traversal policy provider, then the default Component of that provider is
0N/A <
li> if an obtained Component is a traversable Container and it is a focus traversal
0N/A policy provider, then that Container itself is returned
0N/A <
li> if an obtained Component is a Container (traversable or non-traversable)
0N/A and it is a focus traversal policy provider, then the last Component of
0N/A that provider is returned
0N/A<
a name="ProgrammaticTraversal"></
a>
0N/A<
h3>Programmatic Traversal</
h3>
0N/AIn addition to user-initiated focus traversal, client code can
0N/Ainitiate a focus traversal operation programmatically. To client code,
0N/Aprogrammatic traversals are indistinguishable from user-initiated
0N/Atraversals. The preferred way to initiate a programmatic traversal is
0N/Ato use one of the following methods on <
code>KeyboardFocusManager</
code>:
0N/AEach of these methods initiates the traversal operation with the
0N/Acurrent focus owner. If there is currently no focus owner, then no
0N/Atraversal operation occurs. In addition, if the focus owner is not a
0N/Afocus cycle root, then downFocusCycle() performs no traversal
0N/A<
code>KeyboardFocusManager</
code> also supports the following variants
0N/AEach of these methods initiates the traversal operation with the
0N/Aspecified Component rather than the focus owner. That is, the
0N/Atraversal occurs as though the specified Component is the focus owner,
0N/Athough it need not be.
0N/AAlternate, but equivalent, APIs are defined on the Component and
0N/AContainer classes themselves:
0N/AAs with the <
code>KeyboardFocusManager</
code> variants, each of these methods
0N/Ainitiates the traversal operation as though the Component is the focus
0N/Aowner, though it need not be.
0N/AAlso note that hiding or disabling the focus owner, directly or
0N/Aindirectly via an ancestor, or making the focus owner non-displayable
0N/Aor non-focusable, initiates an automatic, forward focus traversal.
0N/AWhile hiding any ancestor, lightweight or heavyweight, will always
0N/Aindirectly hide its children, only disabling a heavyweight ancestor
0N/Awill disable its children. Thus, disabling a lightweight ancestor of
0N/Athe focus owner does not automatically initiate a focus traversal.
0N/AIf client code initiates a focus traversal, and there is no other
0N/AComponent to focus, then the focus owner remains unchanged. If client
0N/Acode initiates an automatic focus traversal by hiding the focus owner,
0N/Adirectly or indirectly, or by making the focus owner non-displayable or
0N/Anon-focusable, and there is no other Component to focus, then the
0N/Aglobal focus owner is cleared. If client code initiates an automatic
0N/Afocus traversal by disabling the focus owner, directly or indirectly,
0N/Aand there is no other Component to focus, then the focus owner remains
0N/A<
a name="Focusability"></
a>
0N/A<
h3>Focusability</
h3>
0N/AA focusable Component can become the focus owner ("focusability") and
0N/Aparticipates in keyboard focus traversal ("focus traversability") with
0N/Aa FocusTraversalPolicy. There is no separation of these two concepts;
0N/Aa Component must either be both focusable and focus traversable, or
0N/AA Component expresses this state via the isFocusable() method. By
0N/Adefault, all Components return true from this method. Client code can
0N/A<
a name="FocusableWindows"></
a>
0N/A<
h3>Focusable Windows</
h3>
0N/ATo support palette windows and input methods, client code can prevent
0N/Aa Window from becoming the focused Window. By transitivity, this
0N/Aprevents the Window or any of its descendants from becoming the focus
0N/Aowner. Non-focusable Windows may still own Windows that are
0N/Afocusable. By default, every Frame and Dialog is focusable. Every
0N/AWindow which is not a Frame or Dialog, but whose nearest owning Frame
0N/Aor Dialog is showing on the screen, and which has at least one
0N/AComponent in its focus traversal cycle, is also focusable by
0N/Adefault. To make a Window non-focusable, use
0N/AIf a Window is non-focusable, this restriction is enforced when the
0N/A<
code>KeyboardFocusManager</
code> sees a <
code>WINDOW_GAINED_FOCUS</
code>
0N/Aevent for the Window. At this point, the focus change is rejected and
0N/Afocus is reset to a different Window. The rejection recovery scheme
0N/Ais the same as if a <
code>VetoableChangeListener</
code> rejected the
0N/Afocus change. See <
a href="#FocusAndVetoableChangeListener">Focus
0N/Aand VetoableChangeListener</
a>.
0N/ABecause the new focus implementation requires that KeyEvents intended
0N/Afor a Window or its descendants be proxied through a child of the
0N/AWindow's owner, and because this proxy must be mapped on X11 in order
0N/Ato receive events, a Window whose nearest owning Frame or Dialog is
0N/Anot showing could never receive KeyEvents on X11. To support this
0N/Arestriction, we have made a distinction between a Window's "window
0N/Afocusability" and its "window focusability state". A Window's
0N/Afocusability state is combined with the showing state of the Window's
0N/Anearest owning Frame or Dialog to determine the Window's focusability.
0N/ABy default, all Windows have a focusability state of true. Setting a
0N/AWindow's focusability state to false ensures that it will not become
0N/Athe focused Window regardless of the showing state of its nearest
0N/Aowning Frame or Dialog.
0N/ASwing allows applications to create JWindows with null owners. Swing
0N/Aconstructs all such JWindows so that they are owned by a private,
0N/Ahidden Frame. Because the showing state of this Frame will always be
0N/Afalse, a JWindow constructed will a null owner can never be the
0N/Afocused Window, even if it has a Window focusability state of true.
0N/AIf the focused Window is made non-focusable, then the AWT will attempt
0N/Ato focus the most recently focused Component of the Window's
0N/Aowner. The Window's owner will thus become the new focused Window. If
0N/Athe Window's owner is also a non-focusable Window, then the focus
0N/Achange request will proceed up the ownership hierarchy recursively.
0N/ASince not all platforms support cross-Window focus changes (see
0N/A<
a href=#
RequestingFocus>Requesting Focus</
a>), it is possible that
0N/Aall such focus change requests will fail. In this case, the global
0N/Afocus owner will be cleared and the focused Window will remain unchanged.
0N/A<
a name="RequestingFocus"></
a>
0N/A<
h3>Requesting Focus</
h3>
0N/AA Component can request that it become the focus owner by calling
0N/Afocus transfer to the Component only if the Component is displayable,
0N/Afocusable, visible and all of its ancestors (with the exception of the
0N/Atop-level Window) are visible. The request will be immediately denied if
0N/Aany of these conditions is not met. A disabled Component may be
0N/Athe focus owner; however, in this case, all KeyEvents will be discarded.
0N/AThe request will also be denied if the Component's top-level Window is
0N/Anot the focused Window and the platform does not support requesting
0N/Afocus across Windows. If the request is denied for this reason, the
0N/Arequest is remembered and will be granted when the Window is later
0N/Afocused by the user. Otherwise, the focus change request changes the
0N/AThere is no way to determine synchronously whether a focus change
0N/Arequest has been granted. Instead, client code must install a
0N/AFocusListener on the Component and watch for the delivery of a
0N/A<
code>FOCUS_GAINED</
code> event. Client code must not assume that
0N/Athe Component is the focus owner until it receives this event.
0N/AThe event may or may not be delivered before <
code>requestFocus()</
code>
0N/Areturns. Developers must not assume one behavior or the other.
0N/AThe AWT supports type-ahead if all focus change requests are made on
0N/Athe EventDispatchThread. If client code requests a focus change, and
0N/Athe AWT determines that this request might be granted by the native
0N/Awindowing system, then the AWT will notify the current
0N/AKeyboardFocusManager that is should enqueue all KeyEvents with a
0N/Atimestamp later than the that of the event currently being handled.
0N/AThese KeyEvents will not be dispatched until the new Component becomes
0N/Athe focus owner. The AWT will cancel the delayed dispatching request
0N/Aif the focus change does not succeed at the native level, if the
0N/AComponent's peer is disposed, or if the focus change is vetoed by a
0N/AVetoableChangeListener. KeyboardFocusManagers are not required to
0N/Asupport type-ahead if a focus change request is made from a thread
0N/Aother than the EventDispatchThread.
0N/Aconsistently across platforms, developers are encouraged to use
0N/Adenies cross-Window focus transfers on all platforms automatically.
0N/ABy eliminating the only platform-specific element of the focus transfer,
0N/Athis method achieves consistent cross-platform behavior.
0N/AIn addition, <
code>requestFocusInWindow()</
code> returns a boolean value.
0N/AIf 'false' is returned, the request is guaranteed to fail. If 'true' is
0N/Areturned, the request will succeed unless it is vetoed, or an
0N/Aextraordinary event, such as disposal of the Component's peer, occurs
0N/Abefore the request can be granted by the native windowing
0N/Asystem. Again, while a return value of 'true' indicates that the
0N/Arequest is likely to succeed, developers must never assume that this
0N/AComponent is the focus owner until this Component receives a
0N/A<
code>FOCUS_GAINED</
code> event.
0N/AIf client code wants no Component in the application to be the focus
0N/Aowner, it can call the method <
code>KeyboardFocusManager</
code>.
0N/A<
code>clearGlobalFocusOwner()</
code> on the current
0N/A<
code>KeyboardFocusManager</
code>. If there exists a focus owner
0N/Awhen this method is called, the focus owner will receive a permanent
0N/A<
code>FOCUS_LOST</
code> event. After this point, the AWT
0N/Afocus implementation will discard all KeyEvents until the user or
0N/Aclient code explicitly sets focus to a Component.
0N/AThe Component class also supports variants of <
code>requestFocus</
code> and
0N/A<
code>requestFocusInWindow</
code> that allow client code to specify
0N/ASee <
a href="#TemporaryFocusEvents">Temporary FocusEvents</
a>
0N/A<
a name="FocusAndPropertyChangeListener"></
a>
0N/A<
h3>Focus and PropertyChangeListener</
h3>
0N/AClient code can listen to changes in context-wide focus state, or to
0N/Achanges in focus-related state in Components, via
0N/APropertyChangeListeners.
0N/AThe <
code>KeyboardFocusManager</
code> supports the following properties:
0N/A <
li><
code>focusOwner</
code>: the focus owner
0N/A <
li><
code>focusedWindow</
code>: the focused Window
0N/A <
li><
code>activeWindow</
code>: the active Window
0N/A <
li><
code>defaultFocusTraversalPolicy</
code>: the default focus
0N/A <
li><
code>forwardDefaultFocusTraversalKeys</
code>: the Set of default
0N/A <
code>FORWARD_TRAVERSAL_KEYS</
code>
0N/A <
li><
code>backwardDefaultFocusTraversalKeys</
code>: the Set of default
0N/A <
code>BACKWARD_TRAVERSAL_KEYS</
code>
0N/A <
li><
code>upCycleDefaultFocusTraversalKeys</
code>: the Set of default
0N/A <
code>UP_CYCLE_TRAVERSAL_KEYS</
code>
0N/A <
li><
code>downCycleDefaultFocusTraversalKeys</
code>: the Set of default
0N/A <
code>DOWN_CYCLE_TRAVERSAL_KEYS</
code>
0N/A <
li><
code>currentFocusCycleRoot</
code>: the current focus cycle root
0N/AA <
code>PropertyChangeListener</
code> installed on the current
0N/A<
code>KeyboardFocusManager</
code> will only see these changes within
0N/Athe <
code>KeyboardFocusManager</
code>'s context, even though the
0N/Afocus owner, focused Window, active Window, and current focus cycle
0N/Aroot comprise the global focus state shared by all contexts.
0N/AWe believe this is less intrusive than requiring client code to pass
0N/Aa security check before installing a <
code>PropertyChangeListener</
code>.
0N/AComponent supports the following focus-related properties:
0N/A <
li><
code>focusable</
code>: the Component's focusability
0N/A <
li><
code>focusTraversalKeysEnabled</
code>: the Component's
0N/A focus traversal keys enabled state
0N/A <
li><
code>forwardFocusTraversalKeys</
code>: the Component's Set of
0N/A <
code>FORWARD_TRAVERSAL_KEYS</
code>
0N/A <
li><
code>backwardFocusTraversalKeys</
code>: the Component's Set of
0N/A <
code>BACKWARD_TRAVERSAL_KEYS</
code>
0N/A <
li><
code>upCycleFocusTraversalKeys</
code>: the Component's Set of
0N/A <
code>UP_CYCLE_TRAVERSAL_KEYS</
code>
0N/AIn addition to the Component properties, Container supports the
0N/Afollowing focus-related properties:
0N/A <
li><
code>downCycleFocusTraversalKeys</
code>: the Container's Set of
0N/A <
code>DOWN_CYCLE_TRAVERSAL_KEYS</
code>
0N/A <
li><
code>focusTraversalPolicy</
code>: the Container's focus
0N/A <
li><
code>focusCycleRoot</
code>: the Container's focus-cycle-root state
0N/AIn addition to the Container properties, Window supports the following
0N/Afocus-related property:
0N/A <
li><
code>focusableWindow</
code>: the Window's focusable Window state
0N/AAlso note that a <
code>PropertyChangeListener</
code> installed on a
0N/AWindow will never see a <
code>PropertyChangeEvent</
code> for the
0N/A<
code>focusCycleRoot</
code> property.
0N/AA Window is always a focus cycle root; this property cannot change.
0N/A<
a name="FocusAndVetoableChangeListener"></
a>
0N/A<
h3>Focus and VetoableChangeListener</
h3>
0N/AThe <
code>KeyboardFocusManager</
code> also supports
0N/A<
code>VetoableChangeListener</
code>s for the following properties:
0N/A <
li>"focusOwner": the focus owner
0N/A <
li>"focusedWindow": the focused Window
0N/A <
li>"activeWindow": the active Window
0N/AIf a VetoableChangeListener vetoes a focus or activation change by
0N/Athrowing a PropertyVetoException, the change is aborted. Any
0N/AVetoableChangeListeners which had already approved the change will
0N/Aasynchronously receive PropertyChangeEvents indicating a reversion of
0N/Astate to the previous value.
0N/AVetoableChangeListeners are notified of the state change before the
0N/Achange is reflected in the KeyboardFocusManager. Conversely,
0N/APropertyChangeListeners are notified after the change is reflected.
0N/AIt follows that all VetoableChangeListeners will be notified before
0N/Aany PropertyChangeListener.
0N/AVetoableChangeListeners must be idempotent, and must veto both loss
0N/Aand gain events for a particular focus change (
e.g., both
0N/A<
code>FOCUS_LOST</
code> and <
code>FOCUS_GAINED</
code>). For example,
0N/Aif a <
code>VetoableChangeListener</
code> vetoes a <
code>FOCUS_LOST</
code>
0N/Aevent, a <
code>KeyboardFocusManager</
code> is not required to search the
0N/A<
code>EventQueue</
code> and remove the associated pending
0N/A<
code>FOCUS_GAINED</
code> event. Instead, the
0N/A<
code>KeyboardFocusManager</
code> is free to attempt to
0N/Adispatch this event and it is the responsibility of the
0N/A<
code>VetoableChangeListener</
code> to veto it as well. In addition,
0N/Aduring processing of the <
code>FOCUS_GAINED</
code> event, the
0N/A<
code>KeyboardFocusManager</
code> may attempt to resync the global
0N/Afocus state by synthesizing another <
code>FOCUS_LOST</
code> event.
0N/AThis event must be vetoed just as the first <
code>FOCUS_LOST</
code> event was.
0N/AA <
code>KeyboardFocusManager</
code> may not hold any locks while
0N/Anotifying <
code>PropertyChangeListener</
code>s of a state change.
0N/AThis requirement is relaxed for <
code>VetoableChangeListeners</
code>,
0N/Ahowever. Therefore, client-definied <
code>VetoableChangeListener</
code>s
0N/Ashould avoid acquiring additional locks inside
0N/A<
code>vetoableChange(PropertyChangeEvent)</
code> as this may lead to deadlock.
0N/AIf a focus or activation change is rejected, the KeyboardFocusManager
0N/Awill initiate rejection recovery as follows:
0N/A <
li>If a focused or active Window change was rejected, then the
0N/A focused or active Window will be reset to the Window which was
0N/A previously the focused or active Window. If there is no such
0N/A Window, then the <
code>KeyboardFocusManager</
code> will clear
0N/A the global focus owner.
0N/A <
li>If a focus owner change was rejected, then the focus owner will be
0N/A reset to the Component which was previously the focus owner. If
0N/A that is not possible, then it will be reset to the next Component
0N/A in the focus traversal cycle after the previous focus owner. If
0N/A that is also not possible, then the <
code>KeyboardFocusManager</
code>
0N/A will clear the global focus owner.
0N/A<
code>VetoableChangeListener</
code>s must be careful to avoid vetoing focus
0N/Achanges initiated as a result of veto rejection recovery. Failure
0N/Ato anticipate this situation could lead to an infinite cycle of
0N/Avetoed focus changes and recovery attempts.
0N/A<
a name="ZOrder"></
a>
0N/AOn some native windowing systems, the Z-order of a Window can affect
0N/Aits focused or active (if applicable) state. On Microsoft Windows, the
0N/Atop-most Window is naturally the focused Window as well. However, on
0N/ASolaris, many window managers use a point-to-focus model that ignores
0N/AZ-order in determining the focused Window.
0N/AWhen focusing or activating Windows, the AWT adheres to the UI
0N/Arequirements of the native platform. Therefore, the focus behavior of
0N/AZ-order-related methods such as:
0N/Ais platform-dependent. In JDK 1.4, the behavior of these methods on
0N/AMicrosoft Windows and Solaris is as follows:
0N/A <
b>Microsoft Windows</
b>: The Window is moved to front, if possible.
0N/A While we will always be able to move this Window in front of other
0N/A Windows in the same VM, Windows 98 and Windows 2000 do not allow an
0N/A application to bring any of its windows to the front unless one
0N/A of that application's windows is already in the foreground. In
0N/A this case, Windows will instead flash the Window's icon in the
0N/A taskbar. If the Window is moved to the front, it will be made
0N/A the focused and (if applicable) active Window.
0N/A <
b>Solaris</
b>: The Window is moved to front. In a point-to-focus
0N/A window manager, the Window will become the focused Window if it
0N/A is the top-most Window underneath the cursor. In a click-to-focus
0N/A window manager, the focused Window will remain unchanged.
0N/A <
b>Microsoft Windows</
b>: The Window is moved to back. Note however
0N/A that Microsoft Windows insists that an owned Window always be in
0N/A front of all of its recursive owners. Thus, after the completion of
0N/A this operation, the Window may not be the lowest Java Window in the
0N/A Z-order. If the Window, or any of its owners, was the focused Window,
0N/A then the focused Window is reset to the top-most Window in the VM.
0N/A <
b>Solaris</
b>: The Window is moved to back. Like Microsoft Windows,
0N/A some window managers insist than an owned Window always be in front
0N/A of all of its recursive owners. Thus, after the completion of this
0N/A operation, the Window may not be the lowest Java Window in the
0N/A Z-order. If the Window was the focused Window, it will lose
0N/A focus in a point-to-focus window manager if it is no longer the
0N/A top-most Window under the cursor. In a click-to-focus window
0N/A manager, the focused Window will remain unchanged.
0N/A <
b>Microsoft Windows</
b>: The Window is moved to front and becomes the focused
0N/A </
b>Solaris</
b>: The Window is moved to front. In a point-to-focus focus
0N/A window manager, the Window will be focused if it is now the
0N/A top-most Window under the cursor. In a click-to-focus window
0N/A manager, the Window will become the focused Window.
0N/A <
b>Microsoft Windows</
b>: If the Window was the focused Window, the focused
0N/A Window is reset to a window chosen by the OS, or to no window. The
0N/A window may be in a native application, or a Java application in
0N/A <
b>Solaris</
b>: If the Window was the focused Window, in a point-to-
0N/A focus window manager, the top-most Window under the cursor will
0N/A become the focused Window. In a click-to-focus window manager,
0N/A the focused Window is reset to a window chosen by the window
0N/A manager. The window may be in a native application, or a Java
0N/A application in another VM.
0N/A<
a name="ReplacingDefaultKeyboardFocusManager"></
a>
0N/A<
h3>Replacing DefaultKeyboardFocusManager</
h3>
0N/A<
code>KeyboardFocusManager</
code>s are pluggable at the browser context
0N/Alevel. Client code can subclass <
code>KeyboardFocusManager</
code> or
0N/A<
code>DefaultKeyboardFocusManager</
code> to modify the way that WindowEvents
0N/Arelated to focus, FocusEvents, and KeyEvents are handled and
0N/Adispatched, and to examine and modify the global focus state. A custom
0N/A<
code>KeyboardFocusManager</
code> can also reject focus changes at a more
0N/Afundamental level then a FocusListener or WindowListener ever could.
0N/AWhile giving a developer ultimate control over the focus model,
0N/Areplacing the entire <
code>KeyboardFocusManager</
code> is a difficult process
0N/Arequiring a thorough understanding of the peer focus layer.
0N/AFortunately, most applications do not need this much control.
0N/ADevelopers are encouraged to use KeyEventDispatchers,
0N/AKeyEventPostProcessors, FocusTraversalPolicies,
0N/AVetoableChangeListeners, and other concepts discussed in this document
0N/Abefore resorting to a full replacement of the <
code>KeyboardFocusManager</
code>.
0N/AFirst note that, because unhindered access to Components in other
0N/Acontexts represents a security hole, the SecurityManager must grant a
0N/Anew permission, "replaceKeyboardFocusManager", before client code is
0N/Apermitted to replace the <
code>KeyboardFocusManager</
code> with an arbitrary
0N/Asubclass instance. Because of the security check, replacing the
0N/A<
code>KeyboardFocusManager</
code> is not an option for applications that will be
0N/Adeployed in environments with a SecurityManager, such as applets in a
0N/AOnce installed, a <
code>KeyboardFocusManager</
code> instance has
0N/Aaccess to the global focus state via a set of protected functions.
0N/AThe <
code>KeyboardFocusManager</
code> can only call these functions
0N/Aif it is installed in the calling thread's context. This ensures
0N/Athat malicious code cannot circumvent the security check in
0N/AA <
code>KeyboardFocusManager</
code> should always work with
0N/Athe global focus state instead of the context focus state.
0N/AFailure to do this will lead to incorrect behavior of the
0N/A<
code>KeyboardFocusManager</
code>.
0N/AThe primary responsibility of a <
code>KeyboardFocusManager</
code>
0N/Ais the dispatch of the following events:
0N/A <
li>all <
code>KeyEvent</
code>s
0N/A <
li>all <
code>FocusEvent</
code>s
0N/AThe peer layer will provide the <
code>KeyboardFocusManager</
code>
0N/Awith all of the above events except <
code>WINDOW_ACTIVATED</
code>
0N/Aand <
code>WINDOW_DEACTIVATED</
code>. The <
code>KeyboardFocusManager</
code>
0N/Amust synthesize <
code>WINDOW_ACTIVATED</
code> and
0N/A<
code>WINDOW_DEACTIVATED</
code> events when appropriate and target them
0N/AThe <
code>KeyboardFocusManager</
code> may need to retarget the events
0N/Aprovided by the peer layer to its own notion of the focus owner or
0N/A <
li>A KeyEvent must be retargeted to the focus owner. Because the peer
0N/A layer is unaware of any lightweight Components, KeyEvents will
0N/A arrive from the peer layer targeted to the focus owner's
0N/A heavyweight Container, not the focus owner.
0N/A <
li>A <
code>FOCUS_LOST</
code> event must be retargeted to the focus
0N/A owner. Again, this is necessary because the peer layer is
0N/A unaware of lightweight Components.
0N/A <
li>A <
code>WINDOW_LOST_FOCUS</
code> event must be retargeted to
0N/A the focused Window. The implementation of the Window class
0N/A may cause the native focused Window to differ from the Java
0N/AA <
code>KeyboardFocusManager</
code> must ensure proper event ordering,
0N/Aand a 1-to-1 correspondence between an event and its opposite event type.
0N/AThe peer layer does not make any of these guarantees. For example, it is
0N/Apossible for the peer layer to send a <
code>FOCUS_GAINED</
code>
0N/Aevent before a <
code>WINDOW_GAINED_FOCUS</
code> event.
0N/AThe <
code>KeyboardFocusManager</
code> is responsible for
0N/Aensuring that the <
code>WINDOW_GAINED_FOCUS</
code> event is dispatched
0N/Abefore the <
code>FOCUS_GAINED</
code> event.
0N/ABefore redispatching an event via <
code>KeyboardFocusManager</
code>.
0N/A<
code>redispatchEvent</
code>, a <
code>KeyboardFocusManager</
code>
0N/Amust attempt to update the global focus state. Typically, this
0N/Amethods; however, an implementation is free to implement its own methods.
0N/AAfter attempting an update, the <
code>KeyboardFocusManager</
code>
0N/Amust verify that the global focus state change
0N/Awas not rejected. A rejection is detected when a call to the
0N/Acorresponding <
code>getGlobal*</
code> method returns a value different than the
0N/Avalue just set. Rejections occur in three standard cases:
0N/A <
li>If the <
code>KeyboardFocusManager</
code> attempts
0N/A to set the global focus owner to a non-focusable Component.
0N/A <
li>If the <
code>KeyboardFocusManager</
code> attempts
0N/A to set the global focused Window to a non-focusable Window.
0N/A <
li>If the change is rejected by an installed
0N/A <
code>VetoableChangeListener</
code>.
0N/AClient-defined implementations of <
code>KeyboardFocusManager</
code>
0N/Acan adjust the set of focus transfers which are rejected by overriding the
0N/Aaccessor and mutator methods for the global focus state.
0N/AIf a request to change the global focus state is rejected, the
0N/A<
code>KeyboardFocusManager</
code> must discard the event which prompted
0N/Athe focus change request. The Component to which the event was targeted
0N/Amust not receive the event.
0N/AThe <
code>KeyboardFocusManager</
code> is also expected to initiate rejection
0N/Arecovery as outlined in <
a href="#FocusAndVetoableChangeListener">Focus
0N/Aand VetoableChangeListener</
a>.
0N/A Finally, a KeyboardFocusManager must handle the following set of
0N/A <
li>When handling a <
code>WINDOW_GAINED_FOCUS</
code> event, the
0N/A <
code>KeyboardFocusManager</
code> must set focus to the
0N/A appropriate child Component of the Window. If a child
0N/A Component of the Window previously requested focus,
0N/A but the focus change was rejected because the platform
0N/A does not support cross-Window focus change requests,
0N/A then focus should be set to that child Component.
0N/A Otherwise, if the Window has never been focused, focus should be
0N/A set to the Window's initial Component to focus. If the Window was
0N/A previously focused, focus should be set to the Window's most
0N/A <
li>The <
code>KeyboardFocusManager</
code> must ensure that the
0N/A opposite Component or Window are as accurate as the native
0N/A windowing platform permits. For example, the
0N/A <
code>KeyboardFocusManager</
code> may need to
0N/A retarget the opposite Component to a lightweight child of the
0N/A heavyweight initially specified by the peer layer.
0N/A If the peer layer states that the opposite Component or Window is
0N/A <
code>null</
code>, it is acceptable for the
0N/A <
code>KeyboardFocusManager</
code> to propagate
0N/A this value. <
code>null</
code> indicates that it is highly
0N/A probably that no other Component or Window was involved
0N/A in the focus or activation change. Because of platform
0N/A limitations, this computation may be
0N/A subject to a heuristic and could be incorrect. Nevertheless, this
0N/A heuristic will be the best possible guess which the peer layer
0N/A <
li>Focus and activation changes in which a Component or Window loses
0N/A focus or activation to itself must be discarded.
0N/A <
li>Events posted by the peer layer claiming that the active Window
0N/A has lost focus to the focused Window must be discarded. The peer
0N/A implementation of the Window class may generate these spurious
0N/A<
a name="Incompatibilities"></
a>
0N/A<
h3>Incompatibilities with Previous Releases</
h3>
0N/A <
p><
b>Cross-platform changes:</
b>
0N/A <
li>The default focus traversability for all Components is now
0N/A 'true'. Previously, some Components (in particular, all
0N/A lightweights), had a default focus traversability of 'false'. Note
0N/A that despite this change, however, the
0N/A <
code>DefaultFocusTraversalPolicy</
code> for all AWT Containers
0N/A will preserve the traversal order of previous releases.
0N/A <
li>A request to focus a non-focus traversable (
i.e., non-focusable)
0N/A Component will be denied. Previously, such requests were granted.
0N/A now perform no operation if the Window is not visible.
0N/A Previously, the behavior was platform-dependent.
0N/A <
li>KeyListeners installed on <
code>Component</
code>s
0N/A will no longer see <
code>KeyEvent</
code>s that map to focus
0N/A traversal operations, and
0N/A for such events. Previously, AWT Components saw these events
0N/A and had an opportunity to consume them before AWT
0N/A initiated focus traversal. Code that requires this
0N/A functionality should instead disable focus traversal keys on
0N/A its <
code>Component</
code>s and handle focus traversal
0N/A itself. Alternately, the code can use an
0N/A <
code>AWTEventListener</
code> or
0N/A <
code>KeyEventDispatcher</
code> to pre-listen to all
0N/A <
code>KeyEvent</
code>s.
0N/A <
p><
b>Changes specific to Microsoft Windows:</
b>
0N/A the top-most Window after the Z-order change.
0N/A <
li><
code>requestFocus()</
code> now allows cross-Window focus
0N/A change requests in all cases. Previously, requests were granted
0N/A for heavyweights, but denied for lightweights.