Source Code Cross Referenced for KeyboardFocusManager.java in  » 6.0-JDK-Core » AWT » java » awt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025        package java.awt;
0026
0027        import java.awt.event.FocusEvent;
0028        import java.awt.event.InputEvent;
0029        import java.awt.event.KeyEvent;
0030        import java.awt.event.WindowEvent;
0031
0032        import java.awt.peer.KeyboardFocusManagerPeer;
0033        import java.awt.peer.LightweightPeer;
0034
0035        import java.beans.PropertyChangeListener;
0036        import java.beans.PropertyChangeSupport;
0037        import java.beans.PropertyVetoException;
0038        import java.beans.VetoableChangeListener;
0039        import java.beans.VetoableChangeSupport;
0040
0041        import java.lang.ref.WeakReference;
0042
0043        import java.lang.reflect.Field;
0044
0045        import java.security.AccessController;
0046        import java.security.PrivilegedAction;
0047
0048        import java.util.Collections;
0049        import java.util.HashSet;
0050        import java.util.Iterator;
0051        import java.util.LinkedList;
0052        import java.util.Set;
0053        import java.util.StringTokenizer;
0054        import java.util.WeakHashMap;
0055
0056        import java.util.logging.Level;
0057        import java.util.logging.Logger;
0058
0059        import sun.awt.AppContext;
0060        import sun.awt.DebugHelper;
0061        import sun.awt.HeadlessToolkit;
0062        import sun.awt.SunToolkit;
0063        import sun.awt.CausedFocusEvent;
0064
0065        /**
0066         * The KeyboardFocusManager is responsible for managing the active and focused
0067         * Windows, and the current focus owner. The focus owner is defined as the
0068         * Component in an application that will typically receive all KeyEvents
0069         * generated by the user. The focused Window is the Window that is, or
0070         * contains, the focus owner. Only a Frame or a Dialog can be the active
0071         * Window. The native windowing system may denote the active Window or its
0072         * children with special decorations, such as a highlighted title bar. The
0073         * active Window is always either the focused Window, or the first Frame or
0074         * Dialog that is an owner of the focused Window.
0075         * <p>
0076         * The KeyboardFocusManager is both a centralized location for client code to
0077         * query for the focus owner and initiate focus changes, and an event
0078         * dispatcher for all FocusEvents, WindowEvents related to focus, and
0079         * KeyEvents.
0080         * <p>
0081         * Some browsers partition applets in different code bases into separate
0082         * contexts, and establish walls between these contexts. In such a scenario,
0083         * there will be one KeyboardFocusManager per context. Other browsers place all
0084         * applets into the same context, implying that there will be only a single,
0085         * global KeyboardFocusManager for all applets. This behavior is
0086         * implementation-dependent. Consult your browser's documentation for more
0087         * information. No matter how many contexts there may be, however, there can
0088         * never be more than one focus owner, focused Window, or active Window, per
0089         * ClassLoader.
0090         * <p>
0091         * Please see
0092         * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
0093         * How to Use the Focus Subsystem</a>,
0094         * a section in <em>The Java Tutorial</em>, and the
0095         * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
0096         * for more information.
0097         *
0098         * @author David Mendenhall
0099         * @version 1.83, 06/25/07 
0100         *
0101         * @see Window
0102         * @see Frame
0103         * @see Dialog
0104         * @see java.awt.event.FocusEvent
0105         * @see java.awt.event.WindowEvent
0106         * @see java.awt.event.KeyEvent
0107         * @since 1.4
0108         */
0109        public abstract class KeyboardFocusManager implements 
0110                KeyEventDispatcher, KeyEventPostProcessor {
0111
0112            // Shared focus engine logger
0113            private static final Logger focusLog = Logger
0114                    .getLogger("java.awt.focus.KeyboardFocusManager");
0115
0116            static {
0117                /* ensure that the necessary native libraries are loaded */
0118                Toolkit.loadLibraries();
0119                if (!GraphicsEnvironment.isHeadless()) {
0120                    initIDs();
0121                }
0122            }
0123
0124            transient KeyboardFocusManagerPeer peer;
0125
0126            /**
0127             * Initialize JNI field and method IDs
0128             */
0129            private static native void initIDs();
0130
0131            private static final DebugHelper dbg = DebugHelper
0132                    .create(KeyboardFocusManager.class);
0133
0134            /**
0135             * The identifier for the Forward focus traversal keys.
0136             *
0137             * @see #setDefaultFocusTraversalKeys
0138             * @see #getDefaultFocusTraversalKeys
0139             * @see Component#setFocusTraversalKeys
0140             * @see Component#getFocusTraversalKeys
0141             */
0142            public static final int FORWARD_TRAVERSAL_KEYS = 0;
0143
0144            /**
0145             * The identifier for the Backward focus traversal keys.
0146             *
0147             * @see #setDefaultFocusTraversalKeys
0148             * @see #getDefaultFocusTraversalKeys
0149             * @see Component#setFocusTraversalKeys
0150             * @see Component#getFocusTraversalKeys
0151             */
0152            public static final int BACKWARD_TRAVERSAL_KEYS = 1;
0153
0154            /**
0155             * The identifier for the Up Cycle focus traversal keys.
0156             *
0157             * @see #setDefaultFocusTraversalKeys
0158             * @see #getDefaultFocusTraversalKeys
0159             * @see Component#setFocusTraversalKeys
0160             * @see Component#getFocusTraversalKeys
0161             */
0162            public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
0163
0164            /**
0165             * The identifier for the Down Cycle focus traversal keys.
0166             *
0167             * @see #setDefaultFocusTraversalKeys
0168             * @see #getDefaultFocusTraversalKeys
0169             * @see Component#setFocusTraversalKeys
0170             * @see Component#getFocusTraversalKeys
0171             */
0172            public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
0173
0174            static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
0175
0176            /**
0177             * Returns the current KeyboardFocusManager instance for the calling
0178             * thread's context.
0179             *
0180             * @return this thread's context's KeyboardFocusManager
0181             * @see #setCurrentKeyboardFocusManager
0182             */
0183            public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
0184                return getCurrentKeyboardFocusManager(AppContext
0185                        .getAppContext());
0186            }
0187
0188            synchronized static KeyboardFocusManager getCurrentKeyboardFocusManager(
0189                    AppContext appcontext) {
0190                KeyboardFocusManager manager = (KeyboardFocusManager) appcontext
0191                        .get(KeyboardFocusManager.class);
0192                if (manager == null) {
0193                    manager = new DefaultKeyboardFocusManager();
0194                    appcontext.put(KeyboardFocusManager.class, manager);
0195                }
0196                return manager;
0197            }
0198
0199            /**
0200             * Sets the current KeyboardFocusManager instance for the calling thread's
0201             * context. If null is specified, then the current KeyboardFocusManager
0202             * is replaced with a new instance of DefaultKeyboardFocusManager.
0203             * <p>
0204             * If a SecurityManager is installed, the calling thread must be granted
0205             * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
0206             * the current KeyboardFocusManager. If this permission is not granted,
0207             * this method will throw a SecurityException, and the current
0208             * KeyboardFocusManager will be unchanged.
0209             *
0210             * @param newManager the new KeyboardFocusManager for this thread's context
0211             * @see #getCurrentKeyboardFocusManager
0212             * @see DefaultKeyboardFocusManager
0213             * @throws SecurityException if the calling thread does not have permission
0214             *         to replace the current KeyboardFocusManager
0215             */
0216            public static void setCurrentKeyboardFocusManager(
0217                    KeyboardFocusManager newManager) throws SecurityException {
0218                SecurityManager security = System.getSecurityManager();
0219                if (security != null) {
0220                    if (replaceKeyboardFocusManagerPermission == null) {
0221                        replaceKeyboardFocusManagerPermission = new AWTPermission(
0222                                "replaceKeyboardFocusManager");
0223                    }
0224                    security
0225                            .checkPermission(replaceKeyboardFocusManagerPermission);
0226                }
0227
0228                KeyboardFocusManager oldManager = null;
0229
0230                synchronized (KeyboardFocusManager.class) {
0231                    AppContext appcontext = AppContext.getAppContext();
0232
0233                    if (newManager != null) {
0234                        oldManager = getCurrentKeyboardFocusManager(appcontext);
0235
0236                        appcontext.put(KeyboardFocusManager.class, newManager);
0237                    } else {
0238                        oldManager = getCurrentKeyboardFocusManager(appcontext);
0239                        appcontext.remove(KeyboardFocusManager.class);
0240                    }
0241                }
0242
0243                if (oldManager != null) {
0244                    oldManager.firePropertyChange("managingFocus",
0245                            Boolean.TRUE, Boolean.FALSE);
0246                }
0247                if (newManager != null) {
0248                    newManager.firePropertyChange("managingFocus",
0249                            Boolean.FALSE, Boolean.TRUE);
0250                }
0251            }
0252
0253            /**
0254             * The Component in an application that will typically receive all
0255             * KeyEvents generated by the user.
0256             */
0257            private static Component focusOwner;
0258
0259            /**
0260             * The Component in an application that will regain focus when an
0261             * outstanding temporary focus transfer has completed, or the focus owner,
0262             * if no outstanding temporary transfer exists.
0263             */
0264            private static Component permanentFocusOwner;
0265
0266            /**
0267             * The Window which is, or contains, the focus owner.
0268             */
0269            private static Window focusedWindow;
0270
0271            /**
0272             * Only a Frame or a Dialog can be the active Window. The native windowing
0273             * system may denote the active Window with a special decoration, such as a
0274             * highlighted title bar. The active Window is always either the focused
0275             * Window, or the first Frame or Dialog which is an owner of the focused
0276             * Window.
0277             */
0278            private static Window activeWindow;
0279
0280            /**
0281             * The default FocusTraversalPolicy for all Windows that have no policy of
0282             * their own set. If those Windows have focus-cycle-root children that have
0283             * no keyboard-traversal policy of their own, then those children will also
0284             * inherit this policy (as will, recursively, their focus-cycle-root
0285             * children).
0286             */
0287            private FocusTraversalPolicy defaultPolicy = new DefaultFocusTraversalPolicy();
0288
0289            /**
0290             * The bound property names of each focus traversal key.
0291             */
0292            private static final String[] defaultFocusTraversalKeyPropertyNames = {
0293                    "forwardDefaultFocusTraversalKeys",
0294                    "backwardDefaultFocusTraversalKeys",
0295                    "upCycleDefaultFocusTraversalKeys",
0296                    "downCycleDefaultFocusTraversalKeys" };
0297
0298            /**
0299             * The default strokes for initializing the default focus traversal keys.
0300             */
0301            private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
0302                    {
0303                            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0,
0304                                    false),
0305                            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
0306                                    InputEvent.CTRL_DOWN_MASK
0307                                            | InputEvent.CTRL_MASK, false), },
0308                    {
0309                            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
0310                                    InputEvent.SHIFT_DOWN_MASK
0311                                            | InputEvent.SHIFT_MASK, false),
0312                            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
0313                                    InputEvent.SHIFT_DOWN_MASK
0314                                            | InputEvent.SHIFT_MASK
0315                                            | InputEvent.CTRL_DOWN_MASK
0316                                            | InputEvent.CTRL_MASK, false), },
0317                    {}, {}, };
0318            /**
0319             * The default focus traversal keys. Each array of traversal keys will be
0320             * in effect on all Windows that have no such array of their own explicitly
0321             * set. Each array will also be inherited, recursively, by any child
0322             * Component of those Windows that has no such array of its own explicitly
0323             * set.
0324             */
0325            private Set[] defaultFocusTraversalKeys = new Set[4];
0326
0327            /**
0328             * The current focus cycle root. If the focus owner is itself a focus cycle
0329             * root, then it may be ambiguous as to which Components represent the next
0330             * and previous Components to focus during normal focus traversal. In that
0331             * case, the current focus cycle root is used to differentiate among the
0332             * possibilities.
0333             */
0334            private static Container currentFocusCycleRoot;
0335
0336            /**
0337             * A description of any VetoableChangeListeners which have been registered.
0338             */
0339            private VetoableChangeSupport vetoableSupport;
0340
0341            /**
0342             * A description of any PropertyChangeListeners which have been registered.
0343             */
0344            private PropertyChangeSupport changeSupport;
0345
0346            /**
0347             * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
0348             * include this KeyboardFocusManager unless it was explicitly re-registered
0349             * via a call to <code>addKeyEventDispatcher</code>. If no other
0350             * KeyEventDispatchers are registered, this field may be null or refer to
0351             * a List of length 0.
0352             */
0353            private java.util.LinkedList keyEventDispatchers;
0354
0355            /**
0356             * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does 
0357             * not include this KeyboardFocusManager unless it was explicitly 
0358             * re-registered via a call to <code>addKeyEventPostProcessor</code>. 
0359             * If no other KeyEventPostProcessors are registered, this field may be 
0360             * null or refer to a List of length 0.
0361             */
0362            private java.util.LinkedList keyEventPostProcessors;
0363
0364            /**
0365             * Maps Windows to those Windows' most recent focus owners.
0366             */
0367            private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
0368
0369            /**
0370             * Error String for initializing SecurityExceptions.
0371             */
0372            private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
0373
0374            /**
0375             * We cache the permission used to verify that the calling thread is
0376             * permitted to access the global focus state.
0377             */
0378            private static AWTPermission replaceKeyboardFocusManagerPermission;
0379
0380            /*
0381             * SequencedEvent which is currently dispatched in AppContext.
0382             */
0383            transient SequencedEvent currentSequencedEvent = null;
0384
0385            final void setCurrentSequencedEvent(SequencedEvent current) {
0386                synchronized (SequencedEvent.class) {
0387                    assert (current == null || currentSequencedEvent == null);
0388                    currentSequencedEvent = current;
0389                }
0390            }
0391
0392            final SequencedEvent getCurrentSequencedEvent() {
0393                synchronized (SequencedEvent.class) {
0394                    return currentSequencedEvent;
0395                }
0396            }
0397
0398            static Set initFocusTraversalKeysSet(String value, Set targetSet) {
0399                StringTokenizer tokens = new StringTokenizer(value, ",");
0400                while (tokens.hasMoreTokens()) {
0401                    targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens
0402                            .nextToken()));
0403                }
0404                return (targetSet.isEmpty()) ? Collections.EMPTY_SET
0405                        : Collections.unmodifiableSet(targetSet);
0406            }
0407
0408            /**
0409             * Initializes a KeyboardFocusManager.
0410             */
0411            public KeyboardFocusManager() {
0412                for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
0413                    Set work_set = new HashSet();
0414                    for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
0415                        work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
0416                    }
0417                    defaultFocusTraversalKeys[i] = (work_set.isEmpty()) ? Collections.EMPTY_SET
0418                            : Collections.unmodifiableSet(work_set);
0419                }
0420                initPeer();
0421            }
0422
0423            private void initPeer() {
0424                if (Toolkit.getDefaultToolkit() instanceof  HeadlessToolkit) {
0425                    peer = ((HeadlessToolkit) Toolkit.getDefaultToolkit())
0426                            .createKeyboardFocusManagerPeer(this );
0427                }
0428                if (Toolkit.getDefaultToolkit() instanceof  SunToolkit) {
0429                    peer = ((SunToolkit) Toolkit.getDefaultToolkit())
0430                            .createKeyboardFocusManagerPeer(this );
0431                }
0432            }
0433
0434            /**
0435             * Returns the focus owner, if the focus owner is in the same context as
0436             * the calling thread. The focus owner is defined as the Component in an
0437             * application that will typically receive all KeyEvents generated by the
0438             * user. KeyEvents which map to the focus owner's focus traversal keys will
0439             * not be delivered if focus traversal keys are enabled for the focus
0440             * owner. In addition, KeyEventDispatchers may retarget or consume
0441             * KeyEvents before they reach the focus owner.
0442             *
0443             * @return the focus owner, or null if the focus owner is not a member of
0444             *         the calling thread's context
0445             * @see #getGlobalFocusOwner
0446             * @see #setGlobalFocusOwner
0447             */
0448            public Component getFocusOwner() {
0449                synchronized (KeyboardFocusManager.class) {
0450                    if (focusOwner == null) {
0451                        return null;
0452                    }
0453
0454                    return (focusOwner.appContext == AppContext.getAppContext()) ? focusOwner
0455                            : null;
0456                }
0457            }
0458
0459            /**
0460             * Returns the focus owner, even if the calling thread is in a different
0461             * context than the focus owner. The focus owner is defined as the
0462             * Component in an application that will typically receive all KeyEvents
0463             * generated by the user. KeyEvents which map to the focus owner's focus
0464             * traversal keys will not be delivered if focus traversal keys are enabled
0465             * for the focus owner. In addition, KeyEventDispatchers may retarget or
0466             * consume KeyEvents before they reach the focus owner.
0467             * <p>
0468             * This method will throw a SecurityException if this KeyboardFocusManager
0469             * is not the current KeyboardFocusManager for the calling thread's
0470             * context.
0471             *
0472             * @return the focus owner
0473             * @see #getFocusOwner
0474             * @see #setGlobalFocusOwner
0475             * @throws SecurityException if this KeyboardFocusManager is not the
0476             *         current KeyboardFocusManager for the calling thread's context
0477             */
0478            protected Component getGlobalFocusOwner() throws SecurityException {
0479                synchronized (KeyboardFocusManager.class) {
0480                    if (this  == getCurrentKeyboardFocusManager()) {
0481                        return focusOwner;
0482                    } else {
0483                        if (focusLog.isLoggable(Level.FINE))
0484                            focusLog.fine("This manager is " + this 
0485                                    + ", current is "
0486                                    + getCurrentKeyboardFocusManager());
0487                        throw new SecurityException(notPrivileged);
0488                    }
0489                }
0490            }
0491
0492            /**
0493             * Sets the focus owner. The operation will be cancelled if the Component
0494             * is not focusable. The focus owner is defined as the Component in an
0495             * application that will typically receive all KeyEvents generated by the
0496             * user. KeyEvents which map to the focus owner's focus traversal keys will
0497             * not be delivered if focus traversal keys are enabled for the focus
0498             * owner. In addition, KeyEventDispatchers may retarget or consume
0499             * KeyEvents before they reach the focus owner. 
0500             * <p>
0501             * This method does not actually set the focus to the specified Component.
0502             * It merely stores the value to be subsequently returned by
0503             * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
0504             * or <code>Component.requestFocusInWindow()</code> to change the focus
0505             * owner, subject to platform limitations.
0506             *
0507             * @param focusOwner the focus owner
0508             * @see #getFocusOwner
0509             * @see #getGlobalFocusOwner
0510             * @see Component#requestFocus()
0511             * @see Component#requestFocusInWindow()
0512             * @see Component#isFocusable
0513             * @beaninfo
0514             *       bound: true
0515             */
0516            protected void setGlobalFocusOwner(Component focusOwner) {
0517                Component oldFocusOwner = null;
0518                boolean shouldFire = false;
0519
0520                if (focusOwner == null || focusOwner.isFocusable()) {
0521                    synchronized (KeyboardFocusManager.class) {
0522                        oldFocusOwner = getFocusOwner();
0523
0524                        try {
0525                            fireVetoableChange("focusOwner", oldFocusOwner,
0526                                    focusOwner);
0527                        } catch (PropertyVetoException e) {
0528                            // rejected
0529                            return;
0530                        }
0531
0532                        KeyboardFocusManager.focusOwner = focusOwner;
0533
0534                        if (focusOwner != null
0535                                && (getCurrentFocusCycleRoot() == null || !focusOwner
0536                                        .isFocusCycleRoot(getCurrentFocusCycleRoot()))) {
0537                            Container rootAncestor = focusOwner
0538                                    .getFocusCycleRootAncestor();
0539                            if (rootAncestor == null
0540                                    && (focusOwner instanceof  Window)) {
0541                                rootAncestor = (Container) focusOwner;
0542                            }
0543                            if (rootAncestor != null) {
0544                                setGlobalCurrentFocusCycleRoot(rootAncestor);
0545                            }
0546                        }
0547
0548                        shouldFire = true;
0549                    }
0550                }
0551
0552                if (shouldFire) {
0553                    firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
0554                }
0555            }
0556
0557            /**
0558             * Clears the global focus owner at both the Java and native levels. If
0559             * there exists a focus owner, that Component will receive a permanent
0560             * FOCUS_LOST event. After this operation completes, the native windowing
0561             * system will discard all user-generated KeyEvents until the user selects
0562             * a new Component to receive focus, or a Component is given focus
0563             * explicitly via a call to <code>requestFocus()</code>. This operation
0564             * does not change the focused or active Windows.
0565             *
0566             * @see Component#requestFocus()
0567             * @see java.awt.event.FocusEvent#FOCUS_LOST
0568             */
0569            public void clearGlobalFocusOwner() {
0570                if (!GraphicsEnvironment.isHeadless()) {
0571                    // Toolkit must be fully initialized, otherwise
0572                    // _clearGlobalFocusOwner will crash or throw an exception
0573                    Toolkit.getDefaultToolkit();
0574
0575                    _clearGlobalFocusOwner();
0576                }
0577            }
0578
0579            private void _clearGlobalFocusOwner() {
0580                Window activeWindow = markClearGlobalFocusOwner();
0581                peer.clearGlobalFocusOwner(activeWindow);
0582            }
0583
0584            Component getNativeFocusOwner() {
0585                return peer.getCurrentFocusOwner();
0586            }
0587
0588            void setNativeFocusOwner(Component comp) {
0589                focusLog.log(Level.FINEST,
0590                        "Calling peer {0} setCurrentFocusOwner for {1}",
0591                        new Object[] { peer, comp });
0592                peer.setCurrentFocusOwner(comp);
0593            }
0594
0595            Window getNativeFocusedWindow() {
0596                return peer.getCurrentFocusedWindow();
0597            }
0598
0599            /**
0600             * Returns the permanent focus owner, if the permanent focus owner is in
0601             * the same context as the calling thread. The permanent focus owner is
0602             * defined as the last Component in an application to receive a permanent
0603             * FOCUS_GAINED event. The focus owner and permanent focus owner are
0604             * equivalent unless a temporary focus change is currently in effect. In
0605             * such a situation, the permanent focus owner will again be the focus
0606             * owner when the temporary focus change ends.
0607             *
0608             * @return the permanent focus owner, or null if the permanent focus owner
0609             *         is not a member of the calling thread's context
0610             * @see #getGlobalPermanentFocusOwner
0611             * @see #setGlobalPermanentFocusOwner
0612             */
0613            public Component getPermanentFocusOwner() {
0614                synchronized (KeyboardFocusManager.class) {
0615                    if (permanentFocusOwner == null) {
0616                        return null;
0617                    }
0618
0619                    return (permanentFocusOwner.appContext == AppContext
0620                            .getAppContext()) ? permanentFocusOwner : null;
0621                }
0622            }
0623
0624            /**
0625             * Returns the permanent focus owner, even if the calling thread is in a
0626             * different context than the permanent focus owner. The permanent focus
0627             * owner is defined as the last Component in an application to receive a
0628             * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
0629             * are equivalent unless a temporary focus change is currently in effect.
0630             * In such a situation, the permanent focus owner will again be the focus
0631             * owner when the temporary focus change ends.
0632             * <p>
0633             * This method will throw a SecurityException if this KeyboardFocusManager
0634             * is not the current KeyboardFocusManager for the calling thread's
0635             * context.
0636             *
0637             * @return the permanent focus owner
0638             * @see #getPermanentFocusOwner
0639             * @see #setGlobalPermanentFocusOwner
0640             * @throws SecurityException if this KeyboardFocusManager is not the
0641             *         current KeyboardFocusManager for the calling thread's context
0642             */
0643            protected Component getGlobalPermanentFocusOwner()
0644                    throws SecurityException {
0645                synchronized (KeyboardFocusManager.class) {
0646                    if (this  == getCurrentKeyboardFocusManager()) {
0647                        return permanentFocusOwner;
0648                    } else {
0649                        if (focusLog.isLoggable(Level.FINE))
0650                            focusLog.fine("This manager is " + this 
0651                                    + ", current is "
0652                                    + getCurrentKeyboardFocusManager());
0653                        throw new SecurityException(notPrivileged);
0654                    }
0655                }
0656            }
0657
0658            /**
0659             * Sets the permanent focus owner. The operation will be cancelled if the
0660             * Component is not focusable. The permanent focus owner is defined as the
0661             * last Component in an application to receive a permanent FOCUS_GAINED
0662             * event. The focus owner and permanent focus owner are equivalent unless
0663             * a temporary focus change is currently in effect. In such a situation,
0664             * the permanent focus owner will again be the focus owner when the
0665             * temporary focus change ends.
0666             * <p>
0667             * This method does not actually set the focus to the specified Component.
0668             * It merely stores the value to be subsequently returned by
0669             * <code>getPermanentFocusOwner()</code>. Use
0670             * <code>Component.requestFocus()</code> or
0671             * <code>Component.requestFocusInWindow()</code> to change the focus owner,
0672             * subject to platform limitations.
0673             *
0674             * @param permanentFocusOwner the permanent focus owner
0675             * @see #getPermanentFocusOwner
0676             * @see #getGlobalPermanentFocusOwner
0677             * @see Component#requestFocus()
0678             * @see Component#requestFocusInWindow()
0679             * @see Component#isFocusable
0680             * @beaninfo
0681             *       bound: true
0682             */
0683            protected void setGlobalPermanentFocusOwner(
0684                    Component permanentFocusOwner) {
0685                Component oldPermanentFocusOwner = null;
0686                boolean shouldFire = false;
0687
0688                if (permanentFocusOwner == null
0689                        || permanentFocusOwner.isFocusable()) {
0690                    synchronized (KeyboardFocusManager.class) {
0691                        oldPermanentFocusOwner = getPermanentFocusOwner();
0692
0693                        try {
0694                            fireVetoableChange("permanentFocusOwner",
0695                                    oldPermanentFocusOwner, permanentFocusOwner);
0696                        } catch (PropertyVetoException e) {
0697                            // rejected
0698                            return;
0699                        }
0700
0701                        KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
0702
0703                        KeyboardFocusManager
0704                                .setMostRecentFocusOwner(permanentFocusOwner);
0705
0706                        shouldFire = true;
0707                    }
0708                }
0709
0710                if (shouldFire) {
0711                    firePropertyChange("permanentFocusOwner",
0712                            oldPermanentFocusOwner, permanentFocusOwner);
0713                }
0714            }
0715
0716            /**
0717             * Returns the focused Window, if the focused Window is in the same context
0718             * as the calling thread. The focused Window is the Window that is or
0719             * contains the focus owner.
0720             *
0721             * @return the focused Window, or null if the focused Window is not a
0722             *         member of the calling thread's context
0723             * @see #getGlobalFocusedWindow
0724             * @see #setGlobalFocusedWindow
0725             */
0726            public Window getFocusedWindow() {
0727                synchronized (KeyboardFocusManager.class) {
0728                    if (focusedWindow == null) {
0729                        return null;
0730                    }
0731
0732                    return (focusedWindow.appContext == AppContext
0733                            .getAppContext()) ? focusedWindow : null;
0734                }
0735            }
0736
0737            /**
0738             * Returns the focused Window, even if the calling thread is in a different
0739             * context than the focused Window. The focused Window is the Window that
0740             * is or contains the focus owner.
0741             * <p>
0742             * This method will throw a SecurityException if this KeyboardFocusManager
0743             * is not the current KeyboardFocusManager for the calling thread's
0744             * context.
0745             *
0746             * @return the focused Window
0747             * @see #getFocusedWindow
0748             * @see #setGlobalFocusedWindow
0749             * @throws SecurityException if this KeyboardFocusManager is not the
0750             *         current KeyboardFocusManager for the calling thread's context
0751             */
0752            protected Window getGlobalFocusedWindow() throws SecurityException {
0753                synchronized (KeyboardFocusManager.class) {
0754                    if (this  == getCurrentKeyboardFocusManager()) {
0755                        return focusedWindow;
0756                    } else {
0757                        if (focusLog.isLoggable(Level.FINE))
0758                            focusLog.fine("This manager is " + this 
0759                                    + ", current is "
0760                                    + getCurrentKeyboardFocusManager());
0761                        throw new SecurityException(notPrivileged);
0762                    }
0763                }
0764            }
0765
0766            /**
0767             * Sets the focused Window. The focused Window is the Window that is or
0768             * contains the focus owner. The operation will be cancelled if the
0769             * specified Window to focus is not a focusable Window.
0770             * <p>
0771             * This method does not actually change the focused Window as far as the
0772             * native windowing system is concerned. It merely stores the value to be
0773             * subsequently returned by <code>getFocusedWindow()</code>. Use
0774             * <code>Component.requestFocus()</code> or
0775             * <code>Component.requestFocusInWindow()</code> to change the focused
0776             * Window, subject to platform limitations.
0777             *
0778             * @param focusedWindow the focused Window
0779             * @see #getFocusedWindow
0780             * @see #getGlobalFocusedWindow
0781             * @see Component#requestFocus()
0782             * @see Component#requestFocusInWindow()
0783             * @see Window#isFocusableWindow
0784             * @beaninfo
0785             *       bound: true
0786             */
0787            protected void setGlobalFocusedWindow(Window focusedWindow) {
0788                Window oldFocusedWindow = null;
0789                boolean shouldFire = false;
0790
0791                if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
0792                    synchronized (KeyboardFocusManager.class) {
0793                        oldFocusedWindow = getFocusedWindow();
0794
0795                        try {
0796                            fireVetoableChange("focusedWindow",
0797                                    oldFocusedWindow, focusedWindow);
0798                        } catch (PropertyVetoException e) {
0799                            // rejected
0800                            return;
0801                        }
0802
0803                        KeyboardFocusManager.focusedWindow = focusedWindow;
0804                        shouldFire = true;
0805                    }
0806                }
0807
0808                if (shouldFire) {
0809                    firePropertyChange("focusedWindow", oldFocusedWindow,
0810                            focusedWindow);
0811                }
0812            }
0813
0814            /**
0815             * Returns the active Window, if the active Window is in the same context
0816             * as the calling thread. Only a Frame or a Dialog can be the active
0817             * Window. The native windowing system may denote the active Window or its
0818             * children with special decorations, such as a highlighted title bar.
0819             * The active Window is always either the focused Window, or the first
0820             * Frame or Dialog that is an owner of the focused Window.
0821             *
0822             * @return the active Window, or null if the active Window is not a member
0823             *         of the calling thread's context
0824             * @see #getGlobalActiveWindow
0825             * @see #setGlobalActiveWindow
0826             */
0827            public Window getActiveWindow() {
0828                synchronized (KeyboardFocusManager.class) {
0829                    if (activeWindow == null) {
0830                        return null;
0831                    }
0832
0833                    return (activeWindow.appContext == AppContext
0834                            .getAppContext()) ? activeWindow : null;
0835                }
0836            }
0837
0838            /**
0839             * Returns the active Window, even if the calling thread is in a different
0840             * context than the active Window. Only a Frame or a Dialog can be the
0841             * active Window. The native windowing system may denote the active Window
0842             * or its children with special decorations, such as a highlighted title
0843             * bar. The active Window is always either the focused Window, or the first
0844             * Frame or Dialog that is an owner of the focused Window.
0845             * <p>
0846             * This method will throw a SecurityException if this KeyboardFocusManager
0847             * is not the current KeyboardFocusManager for the calling thread's
0848             * context.
0849             *
0850             * @return the active Window
0851             * @see #getActiveWindow
0852             * @see #setGlobalActiveWindow
0853             * @throws SecurityException if this KeyboardFocusManager is not the
0854             *         current KeyboardFocusManager for the calling thread's context
0855             */
0856            protected Window getGlobalActiveWindow() throws SecurityException {
0857                synchronized (KeyboardFocusManager.class) {
0858                    if (this  == getCurrentKeyboardFocusManager()) {
0859                        return activeWindow;
0860                    } else {
0861                        if (focusLog.isLoggable(Level.FINE))
0862                            focusLog.fine("This manager is " + this 
0863                                    + ", current is "
0864                                    + getCurrentKeyboardFocusManager());
0865                        throw new SecurityException(notPrivileged);
0866                    }
0867                }
0868            }
0869
0870            /**
0871             * Sets the active Window. Only a Frame or a Dialog can be the active
0872             * Window. The native windowing system may denote the active Window or its
0873             * children with special decorations, such as a highlighted title bar. The
0874             * active Window is always either the focused Window, or the first Frame or
0875             * Dialog that is an owner of the focused Window.
0876             * <p>
0877             * This method does not actually change the active Window as far as the
0878             * native windowing system is concerned. It merely stores the value to be
0879             * subsequently returned by <code>getActiveWindow()</code>. Use
0880             * <code>Component.requestFocus()</code> or
0881             * <code>Component.requestFocusInWindow()</code>to change the active
0882             * Window, subject to platform limitations.
0883             *
0884             * @param activeWindow the active Window
0885             * @see #getActiveWindow
0886             * @see #getGlobalActiveWindow
0887             * @see Component#requestFocus()
0888             * @see Component#requestFocusInWindow()
0889             * @beaninfo
0890             *       bound: true
0891             */
0892            protected void setGlobalActiveWindow(Window activeWindow) {
0893                Window oldActiveWindow;
0894                synchronized (KeyboardFocusManager.class) {
0895                    oldActiveWindow = getActiveWindow();
0896                    if (focusLog.isLoggable(Level.FINER)) {
0897                        focusLog.finer("Setting global active window to "
0898                                + activeWindow + ", old active "
0899                                + oldActiveWindow);
0900                    }
0901
0902                    try {
0903                        fireVetoableChange("activeWindow", oldActiveWindow,
0904                                activeWindow);
0905                    } catch (PropertyVetoException e) {
0906                        // rejected
0907                        return;
0908                    }
0909
0910                    KeyboardFocusManager.activeWindow = activeWindow;
0911                }
0912
0913                firePropertyChange("activeWindow", oldActiveWindow,
0914                        activeWindow);
0915            }
0916
0917            /**
0918             * Returns the default FocusTraversalPolicy. Top-level components 
0919             * use this value on their creation to initialize their own focus traversal
0920             * policy by explicit call to Container.setFocusTraversalPolicy.
0921             *
0922             * @return the default FocusTraversalPolicy. null will never be returned.
0923             * @see #setDefaultFocusTraversalPolicy
0924             * @see Container#setFocusTraversalPolicy
0925             * @see Container#getFocusTraversalPolicy
0926             */
0927            public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
0928                return defaultPolicy;
0929            }
0930
0931            /**
0932             * Sets the default FocusTraversalPolicy. Top-level components 
0933             * use this value on their creation to initialize their own focus traversal
0934             * policy by explicit call to Container.setFocusTraversalPolicy.
0935             * Note: this call doesn't affect already created components as they have 
0936             * their policy initialized. Only new components will use this policy as
0937             * their default policy.
0938             *
0939             * @param defaultPolicy the new, default FocusTraversalPolicy
0940             * @see #getDefaultFocusTraversalPolicy
0941             * @see Container#setFocusTraversalPolicy
0942             * @see Container#getFocusTraversalPolicy
0943             * @throws IllegalArgumentException if defaultPolicy is null
0944             * @beaninfo
0945             *       bound: true
0946             */
0947            public void setDefaultFocusTraversalPolicy(
0948                    FocusTraversalPolicy defaultPolicy) {
0949                if (defaultPolicy == null) {
0950                    throw new IllegalArgumentException(
0951                            "default focus traversal policy cannot be null");
0952                }
0953
0954                FocusTraversalPolicy oldPolicy;
0955
0956                synchronized (this ) {
0957                    oldPolicy = this .defaultPolicy;
0958                    this .defaultPolicy = defaultPolicy;
0959                }
0960
0961                firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
0962                        defaultPolicy);
0963            }
0964
0965            /**
0966             * Sets the default focus traversal keys for a given traversal operation.
0967             * This traversal key <code>Set</code> will be in effect on all
0968             * <code>Window</code>s that have no such <code>Set</code> of
0969             * their own explicitly defined. This <code>Set</code> will also be
0970             * inherited, recursively, by any child <code>Component</code> of
0971             * those <code>Windows</code> that has
0972             * no such <code>Set</code> of its own explicitly defined.
0973             * <p>
0974             * The default values for the default focus traversal keys are
0975             * implementation-dependent. Sun recommends that all implementations for a
0976             * particular native platform use the same default values. The
0977             * recommendations for Windows and Unix are listed below. These
0978             * recommendations are used in the Sun AWT implementations.
0979             *
0980             * <table border=1 summary="Recommended default values for focus traversal keys">
0981             * <tr>
0982             *    <th>Identifier</th>
0983             *    <th>Meaning</th>
0984             *    <th>Default</th>
0985             * </tr>
0986             * <tr>
0987             *    <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
0988             *    <td>Normal forward keyboard traversal</td>
0989             *    <td><code>TAB</code> on <code>KEY_PRESSED</code>,
0990             *        <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
0991             * </tr>
0992             * <tr>
0993             *    <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
0994             *    <td>Normal reverse keyboard traversal</td>
0995             *    <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
0996             *        <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
0997             * </tr>
0998             * <tr>
0999             *    <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
1000             *    <td>Go up one focus traversal cycle</td>
1001             *    <td>none</td>
1002             * </tr>
1003             * <tr>
1004             *    <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
1005             *    <td>Go down one focus traversal cycle</td>
1006             *    <td>none</td>
1007             * </tr>
1008             * </table>
1009             *
1010             * To disable a traversal key, use an empty <code>Set</code>;
1011             * <code>Collections.EMPTY_SET</code> is recommended.
1012             * <p>
1013             * Using the <code>AWTKeyStroke</code> API, client code can
1014             * specify on which of two
1015             * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
1016             * <code>KEY_RELEASED</code>, the focus traversal operation will
1017             * occur. Regardless of which <code>KeyEvent</code> is specified,
1018             * however, all <code>KeyEvent</code>s related to the focus
1019             * traversal key, including the associated <code>KEY_TYPED</code>
1020             * event, will be consumed, and will not be dispatched
1021             * to any <code>Component</code>. It is a runtime error to
1022             * specify a <code>KEY_TYPED</code> event as
1023             * mapping to a focus traversal operation, or to map the same event to
1024             * multiple default focus traversal operations.
1025             *
1026             * @param id one of
1027             *        <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1028             *        <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1029             *        <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1030             *        <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
1031             * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
1032             *        specified operation
1033             * @see #getDefaultFocusTraversalKeys
1034             * @see Component#setFocusTraversalKeys
1035             * @see Component#getFocusTraversalKeys
1036             * @throws IllegalArgumentException if id is not one of
1037             *         <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1038             *         <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1039             *         <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1040             *         <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
1041             *         or if keystrokes is <code>null</code>,
1042             *         or if keystrokes contains <code>null</code>,
1043             *         or if any <code>Object</code> in
1044             *         keystrokes is not an <code>AWTKeyStroke</code>,
1045             *         or if any keystroke
1046             *         represents a <code>KEY_TYPED</code> event,
1047             *         or if any keystroke already maps
1048             *         to another default focus traversal operation
1049             * @beaninfo
1050             *       bound: true
1051             */
1052            public void setDefaultFocusTraversalKeys(int id,
1053                    Set<? extends AWTKeyStroke> keystrokes) {
1054                if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1055                    throw new IllegalArgumentException(
1056                            "invalid focus traversal key identifier");
1057                }
1058                if (keystrokes == null) {
1059                    throw new IllegalArgumentException(
1060                            "cannot set null Set of default focus traversal keys");
1061                }
1062
1063                Set oldKeys;
1064
1065                synchronized (this ) {
1066                    for (Iterator iter = keystrokes.iterator(); iter.hasNext();) {
1067                        Object obj = iter.next();
1068
1069                        if (obj == null) {
1070                            throw new IllegalArgumentException(
1071                                    "cannot set null focus traversal key");
1072                        }
1073
1074                        // Fix for 6195831:
1075                        //According to javadoc this method should throw IAE instead of ClassCastException
1076                        if (!(obj instanceof  AWTKeyStroke)) {
1077                            throw new IllegalArgumentException(
1078                                    "object is expected to be AWTKeyStroke");
1079                        }
1080                        AWTKeyStroke keystroke = (AWTKeyStroke) obj;
1081
1082                        if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1083                            throw new IllegalArgumentException(
1084                                    "focus traversal keys cannot map to KEY_TYPED events");
1085                        }
1086
1087                        // Check to see if key already maps to another traversal
1088                        // operation
1089                        for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
1090                            if (i == id) {
1091                                continue;
1092                            }
1093
1094                            if (defaultFocusTraversalKeys[i]
1095                                    .contains(keystroke)) {
1096                                throw new IllegalArgumentException(
1097                                        "focus traversal keys must be unique for a Component");
1098                            }
1099                        }
1100                    }
1101
1102                    oldKeys = defaultFocusTraversalKeys[id];
1103                    defaultFocusTraversalKeys[id] = Collections
1104                            .unmodifiableSet(new HashSet(keystrokes));
1105                }
1106
1107                firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
1108                        oldKeys, keystrokes);
1109            }
1110
1111            /**
1112             * Returns a Set of default focus traversal keys for a given traversal
1113             * operation. This traversal key Set will be in effect on all Windows that
1114             * have no such Set of their own explicitly defined. This Set will also be
1115             * inherited, recursively, by any child Component of those Windows that has
1116             * no such Set of its own explicitly defined. (See
1117             * <code>setDefaultFocusTraversalKeys</code> for a full description of each
1118             * operation.)
1119             *
1120             * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1121             *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1122             *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1123             *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1124             * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
1125             *         for the specified operation; the <code>Set</code>
1126             *         will be unmodifiable, and may be empty; <code>null</code>
1127             *         will never be returned
1128             * @see #setDefaultFocusTraversalKeys
1129             * @see Component#setFocusTraversalKeys
1130             * @see Component#getFocusTraversalKeys
1131             * @throws IllegalArgumentException if id is not one of
1132             *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1133             *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1134             *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1135             *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1136             */
1137            public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
1138                if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1139                    throw new IllegalArgumentException(
1140                            "invalid focus traversal key identifier");
1141                }
1142
1143                // Okay to return Set directly because it is an unmodifiable view
1144                return defaultFocusTraversalKeys[id];
1145            }
1146
1147            /**
1148             * Returns the current focus cycle root, if the current focus cycle root is
1149             * in the same context as the calling thread. If the focus owner is itself
1150             * a focus cycle root, then it may be ambiguous as to which Components
1151             * represent the next and previous Components to focus during normal focus
1152             * traversal. In that case, the current focus cycle root is used to
1153             * differentiate among the possibilities.
1154             * <p>
1155             * This method is intended to be used only by KeyboardFocusManagers and
1156             * focus implementations. It is not for general client use.
1157             *
1158             * @return the current focus cycle root, or null if the current focus cycle
1159             *         root is not a member of the calling thread's context
1160             * @see #getGlobalCurrentFocusCycleRoot
1161             * @see #setGlobalCurrentFocusCycleRoot
1162             */
1163            public Container getCurrentFocusCycleRoot() {
1164                synchronized (KeyboardFocusManager.class) {
1165                    if (currentFocusCycleRoot == null) {
1166                        return null;
1167                    }
1168
1169                    return (currentFocusCycleRoot.appContext == AppContext
1170                            .getAppContext()) ? currentFocusCycleRoot : null;
1171                }
1172            }
1173
1174            /**
1175             * Returns the current focus cycle root, even if the calling thread is in a
1176             * different context than the current focus cycle root. If the focus owner
1177             * is itself a focus cycle root, then it may be ambiguous as to which
1178             * Components represent the next and previous Components to focus during
1179             * normal focus traversal. In that case, the current focus cycle root is
1180             * used to differentiate among the possibilities.
1181             * <p>
1182             * This method will throw a SecurityException if this KeyboardFocusManager
1183             * is not the current KeyboardFocusManager for the calling thread's
1184             * context.
1185             *
1186             * @return the current focus cycle root, or null if the current focus cycle
1187             *         root is not a member of the calling thread's context
1188             * @see #getCurrentFocusCycleRoot
1189             * @see #setGlobalCurrentFocusCycleRoot
1190             * @throws SecurityException if this KeyboardFocusManager is not the
1191             *         current KeyboardFocusManager for the calling thread's context
1192             */
1193            protected Container getGlobalCurrentFocusCycleRoot()
1194                    throws SecurityException {
1195                synchronized (KeyboardFocusManager.class) {
1196                    if (this  == getCurrentKeyboardFocusManager()) {
1197                        return currentFocusCycleRoot;
1198                    } else {
1199                        if (focusLog.isLoggable(Level.FINE))
1200                            focusLog.fine("This manager is " + this 
1201                                    + ", current is "
1202                                    + getCurrentKeyboardFocusManager());
1203                        throw new SecurityException(notPrivileged);
1204                    }
1205                }
1206            }
1207
1208            /**
1209             * Sets the current focus cycle root. If the focus owner is itself a focus
1210             * cycle root, then it may be ambiguous as to which Components represent
1211             * the next and previous Components to focus during normal focus traversal.
1212             * In that case, the current focus cycle root is used to differentiate
1213             * among the possibilities.
1214             * <p>
1215             * This method is intended to be used only by KeyboardFocusManagers and
1216             * focus implementations. It is not for general client use.
1217             *
1218             * @param newFocusCycleRoot the new focus cycle root
1219             * @see #getCurrentFocusCycleRoot
1220             * @see #getGlobalCurrentFocusCycleRoot
1221             * @beaninfo
1222             *       bound: true
1223             */
1224            public void setGlobalCurrentFocusCycleRoot(
1225                    Container newFocusCycleRoot) {
1226                Container oldFocusCycleRoot;
1227
1228                synchronized (KeyboardFocusManager.class) {
1229                    oldFocusCycleRoot = getCurrentFocusCycleRoot();
1230                    currentFocusCycleRoot = newFocusCycleRoot;
1231                }
1232
1233                firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
1234                        newFocusCycleRoot);
1235            }
1236
1237            /**
1238             * Adds a PropertyChangeListener to the listener list. The listener is
1239             * registered for all bound properties of this class, including the
1240             * following:
1241             * <ul>
1242             *    <li>whether the KeyboardFocusManager is currently managing focus 
1243             *        for this application or applet's browser context 
1244             *        ("managingFocus")</li> 
1245             *    <li>the focus owner ("focusOwner")</li>
1246             *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1247             *    <li>the focused Window ("focusedWindow")</li>
1248             *    <li>the active Window ("activeWindow")</li>
1249             *    <li>the default focus traversal policy
1250             *        ("defaultFocusTraversalPolicy")</li>
1251             *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
1252             *        ("forwardDefaultFocusTraversalKeys")</li>
1253             *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1254             *        ("backwardDefaultFocusTraversalKeys")</li>
1255             *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1256             *        ("upCycleDefaultFocusTraversalKeys")</li>
1257             *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1258             *        ("downCycleDefaultFocusTraversalKeys")</li>
1259             *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1260             * </ul>
1261             * If listener is null, no exception is thrown and no action is performed.
1262             *
1263             * @param listener the PropertyChangeListener to be added
1264             * @see #removePropertyChangeListener
1265             * @see #getPropertyChangeListeners
1266             * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1267             */
1268            public void addPropertyChangeListener(
1269                    PropertyChangeListener listener) {
1270                if (listener != null) {
1271                    synchronized (this ) {
1272                        if (changeSupport == null) {
1273                            changeSupport = new PropertyChangeSupport(this );
1274                        }
1275                        changeSupport.addPropertyChangeListener(listener);
1276                    }
1277                }
1278            }
1279
1280            /**
1281             * Removes a PropertyChangeListener from the listener list. This method
1282             * should be used to remove the PropertyChangeListeners that were
1283             * registered for all bound properties of this class.
1284             * <p>
1285             * If listener is null, no exception is thrown and no action is performed.
1286             *
1287             * @param listener the PropertyChangeListener to be removed
1288             * @see #addPropertyChangeListener
1289             * @see #getPropertyChangeListeners
1290             * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1291             */
1292            public void removePropertyChangeListener(
1293                    PropertyChangeListener listener) {
1294                if (listener != null) {
1295                    synchronized (this ) {
1296                        if (changeSupport != null) {
1297                            changeSupport
1298                                    .removePropertyChangeListener(listener);
1299                        }
1300                    }
1301                }
1302            }
1303
1304            /**
1305             * Returns an array of all the property change listeners
1306             * registered on this keyboard focus manager.
1307             *
1308             * @return all of this keyboard focus manager's
1309             *         <code>PropertyChangeListener</code>s
1310             *         or an empty array if no property change 
1311             *         listeners are currently registered
1312             *
1313             * @see #addPropertyChangeListener
1314             * @see #removePropertyChangeListener
1315             * @see #getPropertyChangeListeners(java.lang.String)
1316             * @since 1.4
1317             */
1318            public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
1319                if (changeSupport == null) {
1320                    changeSupport = new PropertyChangeSupport(this );
1321                }
1322                return changeSupport.getPropertyChangeListeners();
1323            }
1324
1325            /**
1326             * Adds a PropertyChangeListener to the listener list for a specific
1327             * property. The specified property may be user-defined, or one of the
1328             * following:
1329             * <ul>
1330             *    <li>whether the KeyboardFocusManager is currently managing focus 
1331             *        for this application or applet's browser context 
1332             *        ("managingFocus")</li> 
1333             *    <li>the focus owner ("focusOwner")</li>
1334             *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1335             *    <li>the focused Window ("focusedWindow")</li>
1336             *    <li>the active Window ("activeWindow")</li>
1337             *    <li>the default focus traversal policy
1338             *        ("defaultFocusTraversalPolicy")</li>
1339             *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
1340             *        ("forwardDefaultFocusTraversalKeys")</li>
1341             *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1342             *        ("backwardDefaultFocusTraversalKeys")</li>
1343             *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1344             *        ("upCycleDefaultFocusTraversalKeys")</li>
1345             *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1346             *        ("downCycleDefaultFocusTraversalKeys")</li>
1347             *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1348             * </ul>
1349             * If listener is null, no exception is thrown and no action is performed.
1350             *
1351             * @param propertyName one of the property names listed above
1352             * @param listener the PropertyChangeListener to be added
1353             * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
1354             * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1355             * @see #getPropertyChangeListeners(java.lang.String)
1356             */
1357            public void addPropertyChangeListener(String propertyName,
1358                    PropertyChangeListener listener) {
1359                if (listener != null) {
1360                    synchronized (this ) {
1361                        if (changeSupport == null) {
1362                            changeSupport = new PropertyChangeSupport(this );
1363                        }
1364                        changeSupport.addPropertyChangeListener(propertyName,
1365                                listener);
1366                    }
1367                }
1368            }
1369
1370            /**
1371             * Removes a PropertyChangeListener from the listener list for a specific
1372             * property. This method should be used to remove PropertyChangeListeners
1373             * that were registered for a specific bound property.
1374             * <p>
1375             * If listener is null, no exception is thrown and no action is performed.
1376             *
1377             * @param propertyName a valid property name
1378             * @param listener the PropertyChangeListener to be removed
1379             * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1380             * @see #getPropertyChangeListeners(java.lang.String)
1381             * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
1382             */
1383            public void removePropertyChangeListener(String propertyName,
1384                    PropertyChangeListener listener) {
1385                if (listener != null) {
1386                    synchronized (this ) {
1387                        if (changeSupport != null) {
1388                            changeSupport.removePropertyChangeListener(
1389                                    propertyName, listener);
1390                        }
1391                    }
1392                }
1393            }
1394
1395            /**
1396             * Returns an array of all the <code>PropertyChangeListener</code>s
1397             * associated with the named property.
1398             *
1399             * @return all of the <code>PropertyChangeListener</code>s associated with
1400             *         the named property or an empty array if no such listeners have
1401             *         been added.
1402             *         
1403             * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1404             * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1405             * @since 1.4
1406             */
1407            public synchronized PropertyChangeListener[] getPropertyChangeListeners(
1408                    String propertyName) {
1409                if (changeSupport == null) {
1410                    changeSupport = new PropertyChangeSupport(this );
1411                }
1412                return changeSupport.getPropertyChangeListeners(propertyName);
1413            }
1414
1415            /**
1416             * Fires a PropertyChangeEvent in response to a change in a bound property.
1417             * The event will be delivered to all registered PropertyChangeListeners.
1418             * No event will be delivered if oldValue and newValue are the same.
1419             *
1420             * @param propertyName the name of the property that has changed
1421             * @param oldValue the property's previous value
1422             * @param newValue the property's new value
1423             */
1424            protected void firePropertyChange(String propertyName,
1425                    Object oldValue, Object newValue) {
1426                if (oldValue == newValue) {
1427                    return;
1428                }
1429                PropertyChangeSupport changeSupport = this .changeSupport;
1430                if (changeSupport != null) {
1431                    changeSupport.firePropertyChange(propertyName, oldValue,
1432                            newValue);
1433                }
1434            }
1435
1436            /**
1437             * Adds a VetoableChangeListener to the listener list. The listener is
1438             * registered for all vetoable properties of this class, including the
1439             * following:
1440             * <ul>
1441             *    <li>the focus owner ("focusOwner")</li>
1442             *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1443             *    <li>the focused Window ("focusedWindow")</li>
1444             *    <li>the active Window ("activeWindow")</li>
1445             * </ul>
1446             * If listener is null, no exception is thrown and no action is performed.
1447             *
1448             * @param listener the VetoableChangeListener to be added
1449             * @see #removeVetoableChangeListener
1450             * @see #getVetoableChangeListeners
1451             * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1452             */
1453            public void addVetoableChangeListener(
1454                    VetoableChangeListener listener) {
1455                if (listener != null) {
1456                    synchronized (this ) {
1457                        if (vetoableSupport == null) {
1458                            vetoableSupport = new VetoableChangeSupport(this );
1459                        }
1460                        vetoableSupport.addVetoableChangeListener(listener);
1461                    }
1462                }
1463            }
1464
1465            /**
1466             * Removes a VetoableChangeListener from the listener list. This method
1467             * should be used to remove the VetoableChangeListeners that were
1468             * registered for all vetoable properties of this class.
1469             * <p>
1470             * If listener is null, no exception is thrown and no action is performed.
1471             *
1472             * @param listener the VetoableChangeListener to be removed
1473             * @see #addVetoableChangeListener
1474             * @see #getVetoableChangeListeners
1475             * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1476             */
1477            public void removeVetoableChangeListener(
1478                    VetoableChangeListener listener) {
1479                if (listener != null) {
1480                    synchronized (this ) {
1481                        if (vetoableSupport != null) {
1482                            vetoableSupport
1483                                    .removeVetoableChangeListener(listener);
1484                        }
1485                    }
1486                }
1487            }
1488
1489            /**
1490             * Returns an array of all the vetoable change listeners
1491             * registered on this keyboard focus manager.
1492             *
1493             * @return all of this keyboard focus manager's
1494             *         <code>VetoableChangeListener</code>s
1495             *         or an empty array if no vetoable change 
1496             *         listeners are currently registered
1497             *
1498             * @see #addVetoableChangeListener
1499             * @see #removeVetoableChangeListener
1500             * @see #getVetoableChangeListeners(java.lang.String)
1501             * @since 1.4
1502             */
1503            public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
1504                if (vetoableSupport == null) {
1505                    vetoableSupport = new VetoableChangeSupport(this );
1506                }
1507                return vetoableSupport.getVetoableChangeListeners();
1508            }
1509
1510            /**
1511             * Adds a VetoableChangeListener to the listener list for a specific
1512             * property. The specified property may be user-defined, or one of the
1513             * following:
1514             * <ul>
1515             *    <li>the focus owner ("focusOwner")</li>
1516             *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1517             *    <li>the focused Window ("focusedWindow")</li>
1518             *    <li>the active Window ("activeWindow")</li>
1519             * </ul>
1520             * If listener is null, no exception is thrown and no action is performed.
1521             *
1522             * @param propertyName one of the property names listed above
1523             * @param listener the VetoableChangeListener to be added
1524             * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
1525             * @see #removeVetoableChangeListener
1526             * @see #getVetoableChangeListeners
1527             */
1528            public void addVetoableChangeListener(String propertyName,
1529                    VetoableChangeListener listener) {
1530                if (listener != null) {
1531                    synchronized (this ) {
1532                        if (vetoableSupport == null) {
1533                            vetoableSupport = new VetoableChangeSupport(this );
1534                        }
1535                        vetoableSupport.addVetoableChangeListener(propertyName,
1536                                listener);
1537                    }
1538                }
1539            }
1540
1541            /**
1542             * Removes a VetoableChangeListener from the listener list for a specific
1543             * property. This method should be used to remove VetoableChangeListeners
1544             * that were registered for a specific bound property.
1545             * <p>
1546             * If listener is null, no exception is thrown and no action is performed.
1547             *
1548             * @param propertyName a valid property name
1549             * @param listener the VetoableChangeListener to be removed
1550             * @see #addVetoableChangeListener
1551             * @see #getVetoableChangeListeners
1552             * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
1553             */
1554            public void removeVetoableChangeListener(String propertyName,
1555                    VetoableChangeListener listener) {
1556                if (listener != null) {
1557                    synchronized (this ) {
1558                        if (vetoableSupport != null) {
1559                            vetoableSupport.removeVetoableChangeListener(
1560                                    propertyName, listener);
1561                        }
1562                    }
1563                }
1564            }
1565
1566            /**
1567             * Returns an array of all the <code>VetoableChangeListener</code>s
1568             * associated with the named property.
1569             *
1570             * @return all of the <code>VetoableChangeListener</code>s associated with
1571             *         the named property or an empty array if no such listeners have
1572             *         been added.
1573             *
1574             * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1575             * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1576             * @see #getVetoableChangeListeners
1577             * @since 1.4
1578             */
1579            public synchronized VetoableChangeListener[] getVetoableChangeListeners(
1580                    String propertyName) {
1581                if (vetoableSupport == null) {
1582                    vetoableSupport = new VetoableChangeSupport(this );
1583                }
1584                return vetoableSupport.getVetoableChangeListeners(propertyName);
1585            }
1586
1587            /**
1588             * Fires a PropertyChangeEvent in response to a change in a vetoable
1589             * property. The event will be delivered to all registered
1590             * VetoableChangeListeners. If a VetoableChangeListener throws a
1591             * PropertyVetoException, a new event is fired reverting all
1592             * VetoableChangeListeners to the old value and the exception is then
1593             * rethrown. No event will be delivered if oldValue and newValue are the
1594             * same.
1595             *
1596             * @param propertyName the name of the property that has changed
1597             * @param oldValue the property's previous value
1598             * @param newValue the property's new value
1599             * @throws java.beans.PropertyVetoException if a
1600             *         <code>VetoableChangeListener</code> threw
1601             *         <code>PropertyVetoException</code>
1602             */
1603            protected void fireVetoableChange(String propertyName,
1604                    Object oldValue, Object newValue)
1605                    throws PropertyVetoException {
1606                if (oldValue == newValue) {
1607                    return;
1608                }
1609                VetoableChangeSupport vetoableSupport = this .vetoableSupport;
1610                if (vetoableSupport != null) {
1611                    vetoableSupport.fireVetoableChange(propertyName, oldValue,
1612                            newValue);
1613                }
1614            }
1615
1616            /**
1617             * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
1618             * chain. This KeyboardFocusManager will request that each
1619             * KeyEventDispatcher dispatch KeyEvents generated by the user before
1620             * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
1621             * notified in the order in which they were added. Notifications will halt
1622             * as soon as one KeyEventDispatcher returns <code>true</code> from its
1623             * <code>dispatchKeyEvent</code> method. There is no limit to the total
1624             * number of KeyEventDispatchers which can be added, nor to the number of
1625             * times which a particular KeyEventDispatcher instance can be added.
1626             * <p>
1627             * If a null dispatcher is specified, no action is taken and no exception
1628             * is thrown.
1629             * <p>
1630             * In a multithreaded application, {@link KeyEventDispatcher} behaves
1631             * the same as other AWT listeners.  See
1632             * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1633             * >AWT Threading Issues</a> for more details.
1634             *
1635             * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
1636             * @see #removeKeyEventDispatcher
1637             */
1638            public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1639                if (dispatcher != null) {
1640                    synchronized (this ) {
1641                        if (keyEventDispatchers == null) {
1642                            keyEventDispatchers = new java.util.LinkedList();
1643                        }
1644                        keyEventDispatchers.add(dispatcher);
1645                    }
1646                }
1647            }
1648
1649            /**
1650             * Removes a KeyEventDispatcher which was previously added to this
1651             * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
1652             * cannot itself be removed, unless it was explicitly re-registered via a
1653             * call to <code>addKeyEventDispatcher</code>.
1654             * <p>
1655             * If a null dispatcher is specified, if the specified dispatcher is not
1656             * in the dispatcher chain, or if this KeyboardFocusManager is specified
1657             * without having been explicitly re-registered, no action is taken and no
1658             * exception is thrown.
1659             * <p>
1660             * In a multithreaded application, {@link KeyEventDispatcher} behaves
1661             * the same as other AWT listeners.  See
1662             * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1663             * >AWT Threading Issues</a> for more details.
1664             *
1665             * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
1666             *        chain
1667             * @see #addKeyEventDispatcher
1668             */
1669            public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1670                if (dispatcher != null) {
1671                    synchronized (this ) {
1672                        if (keyEventDispatchers != null) {
1673                            keyEventDispatchers.remove(dispatcher);
1674                        }
1675                    }
1676                }
1677            }
1678
1679            /**
1680             * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
1681             * The List will not include this KeyboardFocusManager unless it was
1682             * explicitly re-registered via a call to
1683             * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
1684             * registered, implementations are free to return null or a List of length
1685             * 0. Client code should not assume one behavior over another, nor should
1686             * it assume that the behavior, once established, will not change.
1687             *
1688             * @return a possibly null or empty List of KeyEventDispatchers
1689             * @see #addKeyEventDispatcher
1690             * @see #removeKeyEventDispatcher
1691             */
1692            protected synchronized java.util.List<KeyEventDispatcher> getKeyEventDispatchers() {
1693                return (keyEventDispatchers != null) ? (java.util.List) keyEventDispatchers
1694                        .clone()
1695                        : null;
1696            }
1697
1698            /**
1699             * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
1700             * processor chain. After a KeyEvent has been dispatched to and handled by
1701             * its target, KeyboardFocusManager will request that each
1702             * KeyEventPostProcessor perform any necessary post-processing as part
1703             * of the KeyEvent's final resolution. KeyEventPostProcessors
1704             * will be notified in the order in which they were added; the current
1705             * KeyboardFocusManager will be notified last. Notifications will halt
1706             * as soon as one KeyEventPostProcessor returns <code>true</code> from its
1707             * <code>postProcessKeyEvent</code> method. There is no limit to the the
1708             * total number of KeyEventPostProcessors that can be added, nor to the
1709             * number of times that a particular KeyEventPostProcessor instance can be
1710             * added.
1711             * <p>
1712             * If a null post-processor is specified, no action is taken and no
1713             * exception is thrown.
1714             * <p>
1715             * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1716             * the same as other AWT listeners.  See
1717             * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1718             * >AWT Threading Issues</a> for more details.
1719             *
1720             * @param processor the KeyEventPostProcessor to add to the post-processor
1721             *        chain
1722             * @see #removeKeyEventPostProcessor
1723             */
1724            public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
1725                if (processor != null) {
1726                    synchronized (this ) {
1727                        if (keyEventPostProcessors == null) {
1728                            keyEventPostProcessors = new java.util.LinkedList();
1729                        }
1730                        keyEventPostProcessors.add(processor);
1731                    }
1732                }
1733            }
1734
1735            /**
1736             * Removes a previously added KeyEventPostProcessor from this
1737             * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
1738             * cannot itself be entirely removed from the chain. Only additional
1739             * references added via <code>addKeyEventPostProcessor</code> can be
1740             * removed.
1741             * <p>
1742             * If a null post-processor is specified, if the specified post-processor
1743             * is not in the post-processor chain, or if this KeyboardFocusManager is
1744             * specified without having been explicitly added, no action is taken and
1745             * no exception is thrown.
1746             * <p>
1747             * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1748             * the same as other AWT listeners.  See
1749             * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1750             * >AWT Threading Issues</a> for more details.
1751             *
1752             * @param processor the KeyEventPostProcessor to remove from the post-
1753             *        processor chain
1754             * @see #addKeyEventPostProcessor
1755             */
1756            public void removeKeyEventPostProcessor(
1757                    KeyEventPostProcessor processor) {
1758                if (processor != null) {
1759                    synchronized (this ) {
1760                        if (keyEventPostProcessors != null) {
1761                            keyEventPostProcessors.remove(processor);
1762                        }
1763                    }
1764                }
1765            }
1766
1767            /**
1768             * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
1769             * List. The List will not include this KeyboardFocusManager unless it was
1770             * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
1771             * no KeyEventPostProcessors are registered, implementations are free to
1772             * return null or a List of length 0. Client code should not assume one
1773             * behavior over another, nor should it assume that the behavior, once
1774             * established, will not change.
1775             *
1776             * @return a possibly null or empty List of KeyEventPostProcessors
1777             * @see #addKeyEventPostProcessor
1778             * @see #removeKeyEventPostProcessor
1779             */
1780            protected java.util.List<KeyEventPostProcessor> getKeyEventPostProcessors() {
1781                return (keyEventPostProcessors != null) ? (java.util.List) keyEventPostProcessors
1782                        .clone()
1783                        : null;
1784            }
1785
1786            static void setMostRecentFocusOwner(Component component) {
1787                Component window = component;
1788                while (window != null && !(window instanceof  Window)) {
1789                    window = window.parent;
1790                }
1791                if (window != null) {
1792                    setMostRecentFocusOwner((Window) window, component);
1793                }
1794            }
1795
1796            static synchronized void setMostRecentFocusOwner(Window window,
1797                    Component component) {
1798                // ATTN: component has a strong reference to window via chain
1799                // of Component.parent fields.  Since WeakHasMap refers to its
1800                // values strongly, we need to break the strong link from the
1801                // value (component) back to its key (window).
1802                WeakReference weakValue = null;
1803                if (component != null) {
1804                    weakValue = new WeakReference(component);
1805                }
1806                mostRecentFocusOwners.put(window, weakValue);
1807            }
1808
1809            static void clearMostRecentFocusOwner(Component comp) {
1810                Container window;
1811
1812                if (comp == null) {
1813                    return;
1814                }
1815
1816                synchronized (comp.getTreeLock()) {
1817                    window = comp.getParent();
1818                    while (window != null && !(window instanceof  Window)) {
1819                        window = window.getParent();
1820                    }
1821                }
1822
1823                synchronized (KeyboardFocusManager.class) {
1824                    if ((window != null)
1825                            && (getMostRecentFocusOwner((Window) window) == comp)) {
1826                        setMostRecentFocusOwner((Window) window, null);
1827                    }
1828                    // Also clear temporary lost component stored in Window
1829                    if (window != null) {
1830                        Window realWindow = (Window) window;
1831                        if (realWindow.getTemporaryLostComponent() == comp) {
1832                            realWindow.setTemporaryLostComponent(null);
1833                        }
1834                    }
1835                }
1836            }
1837
1838            /*
1839             * Please be careful changing this method! It is called from
1840             * javax.swing.JComponent.runInputVerifier() using reflection.
1841             */
1842            static synchronized Component getMostRecentFocusOwner(Window window) {
1843                WeakReference weakValue = (WeakReference) mostRecentFocusOwners
1844                        .get(window);
1845                return weakValue == null ? null : (Component) weakValue.get();
1846            }
1847
1848            /**
1849             * This method is called by the AWT event dispatcher requesting that the
1850             * current KeyboardFocusManager dispatch the specified event on its behalf.
1851             * It is expected that all KeyboardFocusManagers will dispatch all
1852             * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
1853             * These events should be dispatched based on the KeyboardFocusManager's
1854             * notion of the focus owner and the focused and active Windows, sometimes
1855             * overriding the source of the specified AWTEvent. Dispatching must be
1856             * done using <code>redispatchEvent</code> to prevent the AWT event
1857             * dispatcher from recursively requesting that the KeyboardFocusManager
1858             * dispatch the event again. If this method returns <code>false</code>,
1859             * then the AWT event dispatcher will attempt to dispatch the event itself.
1860             *
1861             * @param e the AWTEvent to be dispatched
1862             * @return <code>true</code> if this method dispatched the event;
1863             *         <code>false</code> otherwise
1864             * @see #redispatchEvent
1865             * @see #dispatchKeyEvent
1866             */
1867            public abstract boolean dispatchEvent(AWTEvent e);
1868
1869            /**
1870             * Redispatches an AWTEvent in such a way that the AWT event dispatcher
1871             * will not recursively request that the KeyboardFocusManager, or any
1872             * installed KeyEventDispatchers, dispatch the event again. Client
1873             * implementations of <code>dispatchEvent</code> and client-defined
1874             * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
1875             * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
1876             * <p>
1877             * This method is intended to be used only by KeyboardFocusManagers and
1878             * KeyEventDispatchers. It is not for general client use.
1879             *
1880             * @param target the Component to which the event should be dispatched
1881             * @param e the event to dispatch
1882             * @see #dispatchEvent
1883             * @see KeyEventDispatcher
1884             */
1885            public final void redispatchEvent(Component target, AWTEvent e) {
1886                e.focusManagerIsDispatching = true;
1887                target.dispatchEvent(e);
1888                e.focusManagerIsDispatching = false;
1889            }
1890
1891            /**
1892             * Typically this method will be called by <code>dispatchEvent</code> if no
1893             * other KeyEventDispatcher in the dispatcher chain dispatched the
1894             * KeyEvent, or if no other KeyEventDispatchers are registered. If an
1895             * implementation of this method returns <code>false</code>,
1896             * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
1897             * may simply return <code>false</code>. If <code>true</code> is returned,
1898             * <code>dispatchEvent</code> should return <code>true</code> as well.
1899             *
1900             * @param e the KeyEvent which the current KeyboardFocusManager has
1901             *        requested that this KeyEventDispatcher dispatch
1902             * @return <code>true</code> if the KeyEvent was dispatched;
1903             *         <code>false</code> otherwise
1904             * @see #dispatchEvent
1905             */
1906            public abstract boolean dispatchKeyEvent(KeyEvent e);
1907
1908            /**
1909             * This method will be called by <code>dispatchKeyEvent</code>.
1910             * By default, this method will handle any unconsumed KeyEvents that
1911             * map to an AWT <code>MenuShortcut</code> by consuming the event
1912             * and activating the shortcut.
1913             *
1914             * @param e the KeyEvent to post-process
1915             * @return <code>true</code> to indicate that no other
1916             *         KeyEventPostProcessor will be notified of the KeyEvent.
1917             * @see #dispatchKeyEvent
1918             * @see MenuShortcut
1919             */
1920            public abstract boolean postProcessKeyEvent(KeyEvent e);
1921
1922            /**
1923             * This method initiates a focus traversal operation if and only if the
1924             * KeyEvent represents a focus traversal key for the specified
1925             * focusedComponent. It is expected that focusedComponent is the current
1926             * focus owner, although this need not be the case. If it is not,
1927             * focus traversal will nevertheless proceed as if focusedComponent
1928             * were the current focus owner.
1929             *
1930             * @param focusedComponent the Component that will be the basis for a focus
1931             *        traversal operation if the specified event represents a focus
1932             *        traversal key for the Component
1933             * @param e the event that may represent a focus traversal key
1934             */
1935            public abstract void processKeyEvent(Component focusedComponent,
1936                    KeyEvent e);
1937
1938            /**
1939             * Called by the AWT to notify the KeyboardFocusManager that it should
1940             * delay dispatching of KeyEvents until the specified Component becomes
1941             * the focus owner. If client code requests a focus change, and the AWT
1942             * determines that this request might be granted by the native windowing
1943             * system, then the AWT will call this method. It is the responsibility of
1944             * the KeyboardFocusManager to delay dispatching of KeyEvents with
1945             * timestamps later than the specified time stamp until the specified
1946             * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
1947             * request by invoking <code>dequeueKeyEvents</code> or
1948             * <code>discardKeyEvents</code>.
1949             *
1950             * @param after timestamp of current event, or the current, system time if
1951             *        the current event has no timestamp, or the AWT cannot determine
1952             *        which event is currently being handled
1953             * @param untilFocused Component which should receive a FOCUS_GAINED event
1954             *        before any pending KeyEvents
1955             * @see #dequeueKeyEvents
1956             * @see #discardKeyEvents
1957             */
1958            protected abstract void enqueueKeyEvents(long after,
1959                    Component untilFocused);
1960
1961            /**
1962             * Called by the AWT to notify the KeyboardFocusManager that it should
1963             * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1964             * enqueued because of a call to <code>enqueueKeyEvents</code> with the
1965             * same timestamp and Component should be released for normal dispatching
1966             * to the current focus owner. If the given timestamp is less than zero,
1967             * the outstanding enqueue request for the given Component with the <b>
1968             * oldest</b> timestamp (if any) should be cancelled.
1969             *
1970             * @param after the timestamp specified in the call to
1971             *        <code>enqueueKeyEvents</code>, or any value < 0
1972             * @param untilFocused the Component specified in the call to
1973             *        <code>enqueueKeyEvents</code>
1974             * @see #enqueueKeyEvents
1975             * @see #discardKeyEvents
1976             */
1977            protected abstract void dequeueKeyEvents(long after,
1978                    Component untilFocused);
1979
1980            /**
1981             * Called by the AWT to notify the KeyboardFocusManager that it should
1982             * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1983             * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
1984             * with the same Component should be discarded.
1985             *
1986             * @param comp the Component specified in one or more calls to
1987             *        <code>enqueueKeyEvents</code>
1988             * @see #enqueueKeyEvents
1989             * @see #dequeueKeyEvents
1990             */
1991            protected abstract void discardKeyEvents(Component comp);
1992
1993            /**
1994             * Focuses the Component after aComponent, typically based on a
1995             * FocusTraversalPolicy.
1996             *
1997             * @param aComponent the Component that is the basis for the focus
1998             *        traversal operation
1999             * @see FocusTraversalPolicy
2000             */
2001            public abstract void focusNextComponent(Component aComponent);
2002
2003            /**
2004             * Focuses the Component before aComponent, typically based on a
2005             * FocusTraversalPolicy.
2006             *
2007             * @param aComponent the Component that is the basis for the focus
2008             *        traversal operation
2009             * @see FocusTraversalPolicy
2010             */
2011            public abstract void focusPreviousComponent(Component aComponent);
2012
2013            /**
2014             * Moves the focus up one focus traversal cycle. Typically, the focus owner
2015             * is set to aComponent's focus cycle root, and the current focus cycle
2016             * root is set to the new focus owner's focus cycle root. If, however,
2017             * aComponent's focus cycle root is a Window, then typically the focus
2018             * owner is set to the Window's default Component to focus, and the current
2019             * focus cycle root is unchanged.
2020             *
2021             * @param aComponent the Component that is the basis for the focus
2022             *        traversal operation
2023             */
2024            public abstract void upFocusCycle(Component aComponent);
2025
2026            /**
2027             * Moves the focus down one focus traversal cycle. Typically, if
2028             * aContainer is a focus cycle root, then the focus owner is set to
2029             * aContainer's default Component to focus, and the current focus cycle
2030             * root is set to aContainer. If aContainer is not a focus cycle root, then
2031             * no focus traversal operation occurs.
2032             *
2033             * @param aContainer the Container that is the basis for the focus
2034             *        traversal operation
2035             */
2036            public abstract void downFocusCycle(Container aContainer);
2037
2038            /**
2039             * Focuses the Component after the current focus owner.
2040             */
2041            public final void focusNextComponent() {
2042                Component focusOwner = getFocusOwner();
2043                if (focusOwner != null) {
2044                    focusNextComponent(focusOwner);
2045                }
2046            }
2047
2048            /**
2049             * Focuses the Component before the current focus owner.
2050             */
2051            public final void focusPreviousComponent() {
2052                Component focusOwner = getFocusOwner();
2053                if (focusOwner != null) {
2054                    focusPreviousComponent(focusOwner);
2055                }
2056            }
2057
2058            /**
2059             * Moves the focus up one focus traversal cycle from the current focus
2060             * owner. Typically, the new focus owner is set to the current focus
2061             * owner's focus cycle root, and the current focus cycle root is set to the
2062             * new focus owner's focus cycle root. If, however, the current focus
2063             * owner's focus cycle root is a Window, then typically the focus owner is
2064             * set to the focus cycle root's default Component to focus, and the
2065             * current focus cycle root is unchanged.
2066             */
2067            public final void upFocusCycle() {
2068                Component focusOwner = getFocusOwner();
2069                if (focusOwner != null) {
2070                    upFocusCycle(focusOwner);
2071                }
2072            }
2073
2074            /**
2075             * Moves the focus down one focus traversal cycle from the current focus
2076             * owner, if and only if the current focus owner is a Container that is a
2077             * focus cycle root. Typically, the focus owner is set to the current focus
2078             * owner's default Component to focus, and the current focus cycle root is
2079             * set to the current focus owner. If the current focus owner is not a
2080             * Container that is a focus cycle root, then no focus traversal operation
2081             * occurs.
2082             */
2083            public final void downFocusCycle() {
2084                Component focusOwner = getFocusOwner();
2085                if (focusOwner instanceof  Container) {
2086                    downFocusCycle((Container) focusOwner);
2087                }
2088            }
2089
2090            /**
2091             * Dumps the list of focus requests to stderr
2092             */
2093            void dumpRequests() {
2094                System.err.println(">>> Requests dump, time: "
2095                        + System.currentTimeMillis());
2096                synchronized (heavyweightRequests) {
2097                    for (HeavyweightFocusRequest req : heavyweightRequests) {
2098                        System.err.println(">>> Req: " + req);
2099                    }
2100                }
2101                System.err.println("");
2102            }
2103
2104            private static final class LightweightFocusRequest {
2105                final Component component;
2106                final boolean temporary;
2107                final CausedFocusEvent.Cause cause;
2108
2109                LightweightFocusRequest(Component component, boolean temporary,
2110                        CausedFocusEvent.Cause cause) {
2111                    this .component = component;
2112                    this .temporary = temporary;
2113                    this .cause = cause;
2114                }
2115
2116                public String toString() {
2117                    return "LightweightFocusRequest[component=" + component
2118                            + ",temporary=" + temporary + ", cause=" + cause
2119                            + "]";
2120                }
2121            }
2122
2123            private static final class HeavyweightFocusRequest {
2124                final Component heavyweight;
2125                final LinkedList<LightweightFocusRequest> lightweightRequests;
2126
2127                static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER = new HeavyweightFocusRequest();
2128
2129                private HeavyweightFocusRequest() {
2130                    heavyweight = null;
2131                    lightweightRequests = null;
2132                }
2133
2134                HeavyweightFocusRequest(Component heavyweight,
2135                        Component descendant, boolean temporary,
2136                        CausedFocusEvent.Cause cause) {
2137                    if (dbg.on) {
2138                        dbg.assertion(heavyweight != null);
2139                    }
2140
2141                    this .heavyweight = heavyweight;
2142                    this .lightweightRequests = new LinkedList<LightweightFocusRequest>();
2143                    addLightweightRequest(descendant, temporary, cause);
2144                }
2145
2146                boolean addLightweightRequest(Component descendant,
2147                        boolean temporary, CausedFocusEvent.Cause cause) {
2148                    if (dbg.on) {
2149                        dbg
2150                                .assertion(this  != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2151                        dbg.assertion(descendant != null);
2152                    }
2153
2154                    Component lastDescendant = ((lightweightRequests.size() > 0) ? lightweightRequests
2155                            .getLast().component
2156                            : null);
2157
2158                    if (descendant != lastDescendant) {
2159                        // Not a duplicate request
2160                        lightweightRequests.add(new LightweightFocusRequest(
2161                                descendant, temporary, cause));
2162                        return true;
2163                    } else {
2164                        return false;
2165                    }
2166                }
2167
2168                LightweightFocusRequest getFirstLightweightRequest() {
2169                    if (this  == CLEAR_GLOBAL_FOCUS_OWNER) {
2170                        return null;
2171                    }
2172                    return lightweightRequests.getFirst();
2173                }
2174
2175                public String toString() {
2176                    boolean first = true;
2177                    String str = "HeavyweightFocusRequest[heavweight="
2178                            + heavyweight + ",lightweightRequests=";
2179                    if (lightweightRequests == null) {
2180                        str += null;
2181                    } else {
2182                        str += "[";
2183
2184                        for (LightweightFocusRequest lwRequest : lightweightRequests) {
2185                            if (first) {
2186                                first = false;
2187                            } else {
2188                                str += ",";
2189                            }
2190                            str += lwRequest;
2191                        }
2192                        str += "]";
2193                    }
2194                    str += "]";
2195                    return str;
2196                }
2197            }
2198
2199            /*
2200             * heavyweightRequests is used as a monitor for synchronized changes of 
2201             * currentLightweightRequests, clearingCurrentLightweightRequests and 
2202             * newFocusOwner.
2203             */
2204            private static LinkedList<HeavyweightFocusRequest> heavyweightRequests = new LinkedList<HeavyweightFocusRequest>();
2205            private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
2206            private static boolean clearingCurrentLightweightRequests;
2207            private static boolean allowSyncFocusRequests = true;
2208            private static Component newFocusOwner = null;
2209            private static volatile boolean disableRestoreFocus;
2210
2211            static final int SNFH_FAILURE = 0;
2212            static final int SNFH_SUCCESS_HANDLED = 1;
2213            static final int SNFH_SUCCESS_PROCEED = 2;
2214
2215            static boolean processSynchronousLightweightTransfer(
2216                    Component heavyweight, Component descendant,
2217                    boolean temporary, boolean focusedWindowChangeAllowed,
2218                    long time) {
2219                Window parentWindow = Component
2220                        .getContainingWindow(heavyweight);
2221                if (parentWindow == null || !parentWindow.syncLWRequests) {
2222                    return false;
2223                }
2224                if (descendant == null) {
2225                    // Focus transfers from a lightweight child back to the
2226                    // heavyweight Container should be treated like lightweight
2227                    // focus transfers.
2228                    descendant = heavyweight;
2229                }
2230
2231                KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit
2232                        .targetToAppContext(descendant));
2233
2234                FocusEvent currentFocusOwnerEvent = null;
2235                FocusEvent newFocusOwnerEvent = null;
2236                Component currentFocusOwner = manager.getGlobalFocusOwner();
2237
2238                synchronized (heavyweightRequests) {
2239                    HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2240                    if (hwFocusRequest == null
2241                            && heavyweight == manager.getNativeFocusOwner()
2242                            && allowSyncFocusRequests) {
2243
2244                        if (descendant == currentFocusOwner) {
2245                            // Redundant request.
2246                            return true;
2247                        }
2248
2249                        // 'heavyweight' owns the native focus and there are no pending
2250                        // requests. 'heavyweight' must be a Container and
2251                        // 'descendant' must not be the focus owner. Otherwise,
2252                        // we would never have gotten this far.
2253                        manager.enqueueKeyEvents(time, descendant);
2254
2255                        hwFocusRequest = new HeavyweightFocusRequest(
2256                                heavyweight, descendant, temporary,
2257                                CausedFocusEvent.Cause.UNKNOWN);
2258                        heavyweightRequests.add(hwFocusRequest);
2259
2260                        if (currentFocusOwner != null) {
2261                            currentFocusOwnerEvent = new FocusEvent(
2262                                    currentFocusOwner, FocusEvent.FOCUS_LOST,
2263                                    temporary, descendant);
2264                        }
2265                        newFocusOwnerEvent = new FocusEvent(descendant,
2266                                FocusEvent.FOCUS_GAINED, temporary,
2267                                currentFocusOwner);
2268                    }
2269                }
2270                boolean result = false;
2271                final boolean clearing = clearingCurrentLightweightRequests;
2272
2273                Throwable caughtEx = null;
2274                try {
2275                    clearingCurrentLightweightRequests = false;
2276                    synchronized (Component.LOCK) {
2277
2278                        if (currentFocusOwnerEvent != null
2279                                && currentFocusOwner != null) {
2280                            ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2281                            caughtEx = dispatchAndCatchException(caughtEx,
2282                                    currentFocusOwner, currentFocusOwnerEvent);
2283                            result = true;
2284                        }
2285
2286                        if (newFocusOwnerEvent != null && descendant != null) {
2287                            ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2288                            caughtEx = dispatchAndCatchException(caughtEx,
2289                                    descendant, newFocusOwnerEvent);
2290                            result = true;
2291                        }
2292                    }
2293                } finally {
2294                    clearingCurrentLightweightRequests = clearing;
2295                }
2296                if (caughtEx instanceof  RuntimeException) {
2297                    throw (RuntimeException) caughtEx;
2298                } else if (caughtEx instanceof  Error) {
2299                    throw (Error) caughtEx;
2300                }
2301                return result;
2302            }
2303
2304            /**
2305             * Indicates whether the native implementation should proceed with a
2306             * pending, native focus request. Before changing the focus at the native
2307             * level, the AWT implementation should always call this function for
2308             * permission. This function will reject the request if a duplicate request
2309             * preceded it, or if the specified heavyweight Component already owns the
2310             * focus and no native focus changes are pending. Otherwise, the request
2311             * will be approved and the focus request list will be updated so that,
2312             * if necessary, the proper descendant will be focused when the
2313             * corresponding FOCUS_GAINED event on the heavyweight is received.
2314             * 
2315             * An implementation must ensure that calls to this method and native
2316             * focus changes are atomic. If this is not guaranteed, then the ordering
2317             * of the focus request list may be incorrect, leading to errors in the
2318             * type-ahead mechanism. Typically this is accomplished by only calling
2319             * this function from the native event pumping thread, or by holding a
2320             * global, native lock during invocation.
2321             */
2322            static int shouldNativelyFocusHeavyweight(Component heavyweight,
2323                    Component descendant, boolean temporary,
2324                    boolean focusedWindowChangeAllowed, long time,
2325                    CausedFocusEvent.Cause cause) {
2326                if (dbg.on) {
2327                    dbg.assertion(heavyweight != null);
2328                    dbg.assertion(time != 0);
2329                }
2330
2331                if (descendant == null) {
2332                    // Focus transfers from a lightweight child back to the
2333                    // heavyweight Container should be treated like lightweight
2334                    // focus transfers.
2335                    descendant = heavyweight;
2336                }
2337
2338                KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit
2339                        .targetToAppContext(descendant));
2340                KeyboardFocusManager this Manager = getCurrentKeyboardFocusManager();
2341                Component currentFocusOwner = this Manager.getGlobalFocusOwner();
2342                Component nativeFocusOwner = this Manager.getNativeFocusOwner();
2343                Window nativeFocusedWindow = this Manager
2344                        .getNativeFocusedWindow();
2345                if (focusLog.isLoggable(Level.FINER)) {
2346                    focusLog.log(Level.FINER, "SNFH for {0} in {1}",
2347                            new Object[] { descendant, heavyweight });
2348                }
2349                if (focusLog.isLoggable(Level.FINEST)) {
2350                    focusLog.log(Level.FINEST, "0. Current focus owner {0}",
2351                            currentFocusOwner);
2352                    focusLog.log(Level.FINEST, "0. Native focus owner {0}",
2353                            nativeFocusOwner);
2354                    focusLog.log(Level.FINEST, "0. Native focused window {0}",
2355                            nativeFocusedWindow);
2356                }
2357                synchronized (heavyweightRequests) {
2358                    HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2359                    if (focusLog.isLoggable(Level.FINEST)) {
2360                        focusLog.log(Level.FINEST, "Request {0}",
2361                                hwFocusRequest);
2362                    }
2363                    if (hwFocusRequest == null
2364                            && heavyweight == nativeFocusOwner) {
2365                        if (descendant == currentFocusOwner) {
2366                            // Redundant request.
2367                            if (focusLog.isLoggable(Level.FINEST))
2368                                focusLog.log(Level.FINEST,
2369                                        "1. SNFH_FAILURE for {0}", descendant);
2370                            return SNFH_FAILURE;
2371                        }
2372
2373                        // 'heavyweight' owns the native focus and there are no pending
2374                        // requests. 'heavyweight' must be a Container and
2375                        // 'descendant' must not be the focus owner. Otherwise,
2376                        // we would never have gotten this far.
2377                        manager.enqueueKeyEvents(time, descendant);
2378
2379                        hwFocusRequest = new HeavyweightFocusRequest(
2380                                heavyweight, descendant, temporary, cause);
2381                        heavyweightRequests.add(hwFocusRequest);
2382
2383                        if (currentFocusOwner != null) {
2384                            FocusEvent currentFocusOwnerEvent = new CausedFocusEvent(
2385                                    currentFocusOwner, FocusEvent.FOCUS_LOST,
2386                                    temporary, descendant, cause);
2387                            // Fix 5028014. Rolled out.
2388                            // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2389                            SunToolkit.postEvent(currentFocusOwner.appContext,
2390                                    currentFocusOwnerEvent);
2391                        }
2392                        FocusEvent newFocusOwnerEvent = new CausedFocusEvent(
2393                                descendant, FocusEvent.FOCUS_GAINED, temporary,
2394                                currentFocusOwner, cause);
2395                        // Fix 5028014. Rolled out.
2396                        // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2397                        SunToolkit.postEvent(descendant.appContext,
2398                                newFocusOwnerEvent);
2399
2400                        if (focusLog.isLoggable(Level.FINEST))
2401                            focusLog.log(Level.FINEST,
2402                                    "2. SNFH_HANDLED for {0}", descendant);
2403                        return SNFH_SUCCESS_HANDLED;
2404                    } else if (hwFocusRequest != null
2405                            && hwFocusRequest.heavyweight == heavyweight) {
2406                        // 'heavyweight' doesn't have the native focus right now, but
2407                        // if all pending requests were completed, it would. Add
2408                        // descendant to the heavyweight's list of pending
2409                        // lightweight focus transfers.
2410                        if (hwFocusRequest.addLightweightRequest(descendant,
2411                                temporary, cause)) {
2412                            manager.enqueueKeyEvents(time, descendant);
2413                        }
2414
2415                        if (focusLog.isLoggable(Level.FINEST))
2416                            focusLog.finest("3. SNFH_HANDLED for lightweight"
2417                                    + descendant + " in " + heavyweight);
2418                        return SNFH_SUCCESS_HANDLED;
2419                    } else {
2420                        if (!focusedWindowChangeAllowed) {
2421                            // For purposes of computing oldFocusedWindow, we should look at
2422                            // the second to last HeavyweightFocusRequest on the queue iff the
2423                            // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
2424                            // there is no second to last HeavyweightFocusRequest, null is an
2425                            // acceptable value.
2426                            if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2427                                int size = heavyweightRequests.size();
2428                                hwFocusRequest = (HeavyweightFocusRequest) ((size >= 2) ? heavyweightRequests
2429                                        .get(size - 2)
2430                                        : null);
2431                            }
2432                            if (focusedWindowChanged(
2433                                    heavyweight,
2434                                    (hwFocusRequest != null) ? hwFocusRequest.heavyweight
2435                                            : nativeFocusedWindow)) {
2436                                if (focusLog.isLoggable(Level.FINEST))
2437                                    focusLog.finest("4. SNFH_FAILURE for "
2438                                            + descendant);
2439                                return SNFH_FAILURE;
2440                            }
2441                        }
2442
2443                        manager.enqueueKeyEvents(time, descendant);
2444                        heavyweightRequests.add(new HeavyweightFocusRequest(
2445                                heavyweight, descendant, temporary, cause));
2446                        if (focusLog.isLoggable(Level.FINEST))
2447                            focusLog
2448                                    .finest("5. SNFH_PROCEED for " + descendant);
2449                        return SNFH_SUCCESS_PROCEED;
2450                    }
2451                }
2452            }
2453
2454            static void heavyweightButtonDown(Component heavyweight, long time) {
2455                heavyweightButtonDown(heavyweight, time, false);
2456            }
2457
2458            static void heavyweightButtonDown(Component heavyweight, long time,
2459                    boolean acceptDuplicates) {
2460                if (dbg.on) {
2461                    dbg.assertion(heavyweight != null);
2462                    dbg.assertion(time != 0);
2463                }
2464                KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit
2465                        .targetToAppContext(heavyweight));
2466
2467                synchronized (heavyweightRequests) {
2468                    HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2469                    Component currentNativeFocusOwner = (hwFocusRequest == null) ? manager
2470                            .getNativeFocusOwner()
2471                            : hwFocusRequest.heavyweight;
2472
2473                    // Behavior for all use cases:
2474                    // 1. Heavyweight leaf Components (e.g., Button, Checkbox, Choice,
2475                    //    List, TextComponent, Canvas) that respond to button down.
2476                    //
2477                    //    Native platform will generate a FOCUS_GAINED if and only if
2478                    //    the Component is not the focus owner (or, will not be the
2479                    //    focus owner when all outstanding focus requests are
2480                    //    processed).
2481                    //
2482                    // 2. Panel with no descendants.
2483                    //
2484                    //    Same as (1).
2485                    //
2486                    // 3. Panel with at least one heavyweight descendant.
2487                    //
2488                    //    This function should NOT be called for this case!
2489                    //
2490                    // 4. Panel with only lightweight descendants.
2491                    //
2492                    //    Native platform will generate a FOCUS_GAINED if and only if
2493                    //    neither the Panel, nor any of its recursive, lightweight
2494                    //    descendants, is the focus owner. However, we want a
2495                    //    requestFocus() for any lightweight descendant to win out over
2496                    //    the focus request for the Panel. To accomplish this, we
2497                    //    differ from the algorithm for shouldNativelyFocusHeavyweight
2498                    //    as follows:
2499                    //      a. If the requestFocus() for a lightweight descendant has
2500                    //         been fully handled by the time this function is invoked,
2501                    //         then 'hwFocusRequest' will be null and 'heavyweight'
2502                    //         will be the native focus owner. Do *not* synthesize a
2503                    //         focus transfer to the Panel.
2504                    //      b. If the requestFocus() for a lightweight descendant has
2505                    //         been recorded, but not handled, then 'hwFocusRequest'
2506                    //         will be non-null and 'hwFocusRequest.heavyweight' will
2507                    //         equal 'heavyweight'. Do *not* append 'heavyweight' to
2508                    //         hwFocusRequest.lightweightRequests.
2509                    //      c. If the requestFocus() for a lightweight descendant is
2510                    //         yet to be made, then post a new HeavyweightFocusRequest.
2511                    //         If no lightweight descendant ever requests focus, then
2512                    //         the Panel will get focus. If some descendant does, then
2513                    //         the descendant will get focus by either a synthetic
2514                    //         focus transfer, or a lightweightRequests focus transfer.
2515
2516                    if (acceptDuplicates
2517                            || heavyweight != currentNativeFocusOwner) {
2518                        getCurrentKeyboardFocusManager(
2519                                SunToolkit.targetToAppContext(heavyweight))
2520                                .enqueueKeyEvents(time, heavyweight);
2521                        heavyweightRequests.add(new HeavyweightFocusRequest(
2522                                heavyweight, heavyweight, false,
2523                                CausedFocusEvent.Cause.MOUSE_EVENT));
2524                    }
2525                }
2526            }
2527
2528            /**
2529             * Returns the Window which will be active after processing this request,
2530             * or null if this is a duplicate request. The active Window is useful
2531             * because some native platforms do not support setting the native focus
2532             * owner to null. On these platforms, the obvious choice is to set the
2533             * focus owner to the focus proxy of the active Window.
2534             */
2535            static Window markClearGlobalFocusOwner() {
2536                // need to call this out of synchronized block to avoid possible deadlock
2537                // see 6454631.
2538                final Component nativeFocusedWindow = getCurrentKeyboardFocusManager()
2539                        .getNativeFocusedWindow();
2540
2541                synchronized (heavyweightRequests) {
2542                    HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2543                    if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2544                        // duplicate request
2545                        return null;
2546                    }
2547
2548                    heavyweightRequests
2549                            .add(HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2550
2551                    Component activeWindow = ((hwFocusRequest != null) ? Component
2552                            .getContainingWindow(hwFocusRequest.heavyweight)
2553                            : nativeFocusedWindow);
2554                    while (activeWindow != null
2555                            && !((activeWindow instanceof  Frame) || (activeWindow instanceof  Dialog))) {
2556                        activeWindow = activeWindow.getParent_NoClientCode();
2557                    }
2558
2559                    return (Window) activeWindow;
2560                }
2561            }
2562
2563            Component getCurrentWaitingRequest(Component parent) {
2564                synchronized (heavyweightRequests) {
2565                    HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2566                    if (hwFocusRequest != null) {
2567                        if (hwFocusRequest.heavyweight == parent) {
2568                            LightweightFocusRequest lwFocusRequest = hwFocusRequest.lightweightRequests
2569                                    .getFirst();
2570                            if (lwFocusRequest != null) {
2571                                return lwFocusRequest.component;
2572                            }
2573                        }
2574                    }
2575                }
2576                return null;
2577            }
2578
2579            static boolean isAutoFocusTransferEnabled() {
2580                synchronized (heavyweightRequests) {
2581                    return (heavyweightRequests.size() == 0)
2582                            && !disableRestoreFocus
2583                            && (null == currentLightweightRequests);
2584                }
2585            }
2586
2587            /*
2588             * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
2589             * @param ex previously caught exception that may be processed right here, or null
2590             * @param comp the component to dispatch the event to
2591             * @param event the event to dispatch to the component
2592             */
2593            static private Throwable dispatchAndCatchException(Throwable ex,
2594                    Component comp, FocusEvent event) {
2595                Throwable retEx = null;
2596                try {
2597                    comp.dispatchEvent(event);
2598                } catch (RuntimeException re) {
2599                    retEx = re;
2600                } catch (Error er) {
2601                    retEx = er;
2602                }
2603                if (retEx != null) {
2604                    if (ex != null) {
2605                        handleException(ex);
2606                    }
2607                    return retEx;
2608                }
2609                return ex;
2610            }
2611
2612            static private void handleException(Throwable ex) {
2613                ex.printStackTrace();
2614            }
2615
2616            static void processCurrentLightweightRequests() {
2617                KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2618                LinkedList<LightweightFocusRequest> localLightweightRequests = null;
2619
2620                Component globalFocusOwner = manager.getGlobalFocusOwner();
2621                if ((globalFocusOwner != null)
2622                        && (globalFocusOwner.appContext != AppContext
2623                                .getAppContext())) {
2624                    // The current app context differs from the app context of a focus
2625                    // owner (and all pending lightweight requests), so we do nothing
2626                    // now and wait for a next event.
2627                    return;
2628                }
2629
2630                synchronized (heavyweightRequests) {
2631                    if (currentLightweightRequests != null) {
2632                        clearingCurrentLightweightRequests = true;
2633                        disableRestoreFocus = true;
2634                        localLightweightRequests = currentLightweightRequests;
2635                        allowSyncFocusRequests = (localLightweightRequests
2636                                .size() < 2);
2637                        currentLightweightRequests = null;
2638                    } else {
2639                        // do nothing
2640                        return;
2641                    }
2642                }
2643
2644                Throwable caughtEx = null;
2645                try {
2646                    if (localLightweightRequests != null) {
2647                        Component lastFocusOwner = null;
2648                        Component currentFocusOwner = null;
2649
2650                        for (Iterator iter = localLightweightRequests
2651                                .iterator(); iter.hasNext();) {
2652
2653                            currentFocusOwner = manager.getGlobalFocusOwner();
2654                            LightweightFocusRequest lwFocusRequest = (LightweightFocusRequest) iter
2655                                    .next();
2656
2657                            /*
2658                             * WARNING: This is based on DKFM's logic solely!
2659                             *
2660                             * We allow to trigger restoreFocus() in the dispatching process
2661                             * only if we have the last request to dispatch. If the last request
2662                             * fails, focus will be restored to either the component of the last
2663                             * previously succedded request, or to to the focus owner that was
2664                             * before this clearing proccess.
2665                             */
2666                            if (!iter.hasNext()) {
2667                                disableRestoreFocus = false;
2668                            }
2669
2670                            FocusEvent currentFocusOwnerEvent = null;
2671                            /*
2672                             * We're not dispatching FOCUS_LOST while the current focus owner is null.
2673                             * But regardless of whether it's null or not, we're clearing ALL the local
2674                             * lw requests.
2675                             */
2676                            if (currentFocusOwner != null) {
2677                                currentFocusOwnerEvent = new CausedFocusEvent(
2678                                        currentFocusOwner,
2679                                        FocusEvent.FOCUS_LOST,
2680                                        lwFocusRequest.temporary,
2681                                        lwFocusRequest.component,
2682                                        lwFocusRequest.cause);
2683                            }
2684                            FocusEvent newFocusOwnerEvent = new CausedFocusEvent(
2685                                    lwFocusRequest.component,
2686                                    FocusEvent.FOCUS_GAINED,
2687                                    lwFocusRequest.temporary,
2688                                    currentFocusOwner == null ? lastFocusOwner
2689                                            : currentFocusOwner,
2690                                    lwFocusRequest.cause);
2691
2692                            if (currentFocusOwner != null) {
2693                                ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2694                                caughtEx = dispatchAndCatchException(caughtEx,
2695                                        currentFocusOwner,
2696                                        currentFocusOwnerEvent);
2697                            }
2698
2699                            ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2700                            caughtEx = dispatchAndCatchException(caughtEx,
2701                                    lwFocusRequest.component,
2702                                    newFocusOwnerEvent);
2703
2704                            if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2705                                lastFocusOwner = lwFocusRequest.component;
2706                            }
2707                        }
2708                    }
2709                } finally {
2710                    clearingCurrentLightweightRequests = false;
2711                    disableRestoreFocus = false;
2712                    localLightweightRequests = null;
2713                    allowSyncFocusRequests = true;
2714                }
2715                if (caughtEx instanceof  RuntimeException) {
2716                    throw (RuntimeException) caughtEx;
2717                } else if (caughtEx instanceof  Error) {
2718                    throw (Error) caughtEx;
2719                }
2720            }
2721
2722            static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2723                synchronized (heavyweightRequests) {
2724                    // Any other case represents a failure condition which we did
2725                    // not expect. We need to clearFocusRequestList() and patch up
2726                    // the event as best as possible.
2727
2728                    if (removeFirstRequest()) {
2729                        return (FocusEvent) retargetFocusEvent(fe);
2730                    }
2731
2732                    Component source = fe.getComponent();
2733                    Component opposite = fe.getOppositeComponent();
2734                    boolean temporary = false;
2735                    if (fe.getID() == FocusEvent.FOCUS_LOST
2736                            && (opposite == null || isTemporary(opposite,
2737                                    source))) {
2738                        temporary = true;
2739                    }
2740                    return new CausedFocusEvent(source, fe.getID(), temporary,
2741                            opposite, CausedFocusEvent.Cause.NATIVE_SYSTEM);
2742                }
2743            }
2744
2745            static FocusEvent retargetFocusGained(FocusEvent fe) {
2746                assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2747
2748                Component currentFocusOwner = getCurrentKeyboardFocusManager()
2749                        .getGlobalFocusOwner();
2750                Component source = fe.getComponent();
2751                Component opposite = fe.getOppositeComponent();
2752                Component nativeSource = getHeavyweight(source);
2753
2754                synchronized (heavyweightRequests) {
2755                    HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2756
2757                    if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2758                        return retargetUnexpectedFocusEvent(fe);
2759                    }
2760
2761                    if (source != null && nativeSource == null
2762                            && hwFocusRequest != null) {
2763                        // if source w/o peer and 
2764                        // if source is equal to first lightweight
2765                        // then we should correct source and nativeSource
2766                        if (source == hwFocusRequest
2767                                .getFirstLightweightRequest().component) {
2768                            source = hwFocusRequest.heavyweight;
2769                            nativeSource = source; // source is heavuweight itself
2770                        }
2771                    }
2772                    if (hwFocusRequest != null
2773                            && nativeSource == hwFocusRequest.heavyweight) {
2774                        // Focus change as a result of a known call to requestFocus(),
2775                        // or known click on a peer focusable heavyweight Component.
2776
2777                        heavyweightRequests.removeFirst();
2778
2779                        LightweightFocusRequest lwFocusRequest = hwFocusRequest.lightweightRequests
2780                                .removeFirst();
2781
2782                        Component newSource = lwFocusRequest.component;
2783                        if (currentFocusOwner != null) {
2784                            /*
2785                             * Since we receive FOCUS_GAINED when current focus 
2786                             * owner is not null, correcponding FOCUS_LOST is supposed
2787                             * to be lost.  And so,  we keep new focus owner 
2788                             * to determine synthetic FOCUS_LOST event which will be 
2789                             * generated by KeyboardFocusManager for this FOCUS_GAINED.
2790                             *
2791                             * This code based on knowledge of 
2792                             * DefaultKeyboardFocusManager's implementation and might 
2793                             * be not applicable for another KeyboardFocusManager.
2794                             */
2795                            newFocusOwner = newSource;
2796                        }
2797
2798                        boolean temporary = (opposite == null || isTemporary(
2799                                newSource, opposite)) ? false
2800                                : lwFocusRequest.temporary;
2801
2802                        if (hwFocusRequest.lightweightRequests.size() > 0) {
2803                            currentLightweightRequests = hwFocusRequest.lightweightRequests;
2804                            EventQueue.invokeLater(new Runnable() {
2805                                public void run() {
2806                                    processCurrentLightweightRequests();
2807                                }
2808                            });
2809                        }
2810
2811                        // 'opposite' will be fixed by
2812                        // DefaultKeyboardFocusManager.realOppositeComponent
2813                        return new CausedFocusEvent(newSource,
2814                                FocusEvent.FOCUS_GAINED, temporary, opposite,
2815                                lwFocusRequest.cause);
2816                    }
2817
2818                    if (currentFocusOwner != null
2819                            && currentFocusOwner.getContainingWindow() == source
2820                            && (hwFocusRequest == null || source != hwFocusRequest.heavyweight)) {
2821                        // Special case for FOCUS_GAINED in top-levels
2822                        // If it arrives as the result of activation we should skip it
2823                        // This event will not have appropriate request record and
2824                        // on arrival there will be already some focus owner set.
2825                        return new CausedFocusEvent(currentFocusOwner,
2826                                FocusEvent.FOCUS_GAINED, false, null,
2827                                CausedFocusEvent.Cause.ACTIVATION);
2828                    }
2829
2830                    return retargetUnexpectedFocusEvent(fe);
2831                } // end synchronized(heavyweightRequests)
2832            }
2833
2834            static FocusEvent retargetFocusLost(FocusEvent fe) {
2835                assert (fe.getID() == FocusEvent.FOCUS_LOST);
2836
2837                Component currentFocusOwner = getCurrentKeyboardFocusManager()
2838                        .getGlobalFocusOwner();
2839                Component opposite = fe.getOppositeComponent();
2840                Component nativeOpposite = getHeavyweight(opposite);
2841
2842                synchronized (heavyweightRequests) {
2843                    HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2844
2845                    if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2846                        if (currentFocusOwner != null) {
2847                            // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2848                            heavyweightRequests.removeFirst();
2849                            return new CausedFocusEvent(
2850                                    currentFocusOwner,
2851                                    FocusEvent.FOCUS_LOST,
2852                                    false,
2853                                    null,
2854                                    CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2855                        }
2856
2857                        // Otherwise, fall through to failure case below
2858
2859                    } else if (opposite == null) {
2860                        // Focus leaving application
2861                        if (currentFocusOwner != null) {
2862                            return new CausedFocusEvent(currentFocusOwner,
2863                                    FocusEvent.FOCUS_LOST, true, null,
2864                                    CausedFocusEvent.Cause.ACTIVATION);
2865                        } else {
2866                            return fe;
2867                        }
2868                    } else if (hwFocusRequest != null
2869                            && (nativeOpposite == hwFocusRequest.heavyweight || nativeOpposite == null
2870                                    && opposite == hwFocusRequest
2871                                            .getFirstLightweightRequest().component)) {
2872                        if (currentFocusOwner == null) {
2873                            return fe;
2874                        }
2875                        // Focus change as a result of a known call to requestFocus(),
2876                        // or click on a peer focusable heavyweight Component.
2877                        // If a focus transfer is made across top-levels, then the
2878                        // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2879                        // event is always permanent. Otherwise, the stored temporary
2880                        // value is honored.
2881
2882                        LightweightFocusRequest lwFocusRequest = hwFocusRequest.lightweightRequests
2883                                .getFirst();
2884
2885                        boolean temporary = isTemporary(opposite,
2886                                currentFocusOwner) ? true
2887                                : lwFocusRequest.temporary;
2888
2889                        return new CausedFocusEvent(currentFocusOwner,
2890                                FocusEvent.FOCUS_LOST, temporary,
2891                                lwFocusRequest.component, lwFocusRequest.cause);
2892                    } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2893                        // If top-level changed there might be no focus request in a list
2894                        // But we know the opposite, we now it is temporary - dispatch the event.
2895                        if (!fe.isTemporary() && currentFocusOwner != null) {
2896                            // Create copy of the event with only difference in temporary parameter.
2897                            fe = new CausedFocusEvent(currentFocusOwner,
2898                                    FocusEvent.FOCUS_LOST, true, opposite,
2899                                    CausedFocusEvent.Cause.ACTIVATION);
2900                        }
2901                        return fe;
2902                    }
2903
2904                    return retargetUnexpectedFocusEvent(fe);
2905                } // end synchronized(heavyweightRequests)
2906            }
2907
2908            static AWTEvent retargetFocusEvent(AWTEvent event) {
2909                if (clearingCurrentLightweightRequests) {
2910                    return event;
2911                }
2912
2913                KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2914                if (focusLog.isLoggable(Level.FINE)) {
2915                    if (event instanceof  FocusEvent
2916                            || event instanceof  WindowEvent) {
2917                        focusLog.log(Level.FINE, ">>> {0}",
2918                                new Object[] { event });
2919                    }
2920                    if (focusLog.isLoggable(Level.FINER)
2921                            && event instanceof  KeyEvent) {
2922                        focusLog.log(Level.FINER, "    focus owner is {0}",
2923                                new Object[] { manager.getGlobalFocusOwner() });
2924                        focusLog.log(Level.FINER, ">>> {0}",
2925                                new Object[] { event });
2926                    }
2927                }
2928
2929                synchronized (heavyweightRequests) {
2930                    /*
2931                     * This code handles FOCUS_LOST event which is generated by 
2932                     * DefaultKeyboardFocusManager for FOCUS_GAINED.
2933                     *
2934                     * This code based on knowledge of DefaultKeyboardFocusManager's
2935                     * implementation and might be not applicable for another 
2936                     * KeyboardFocusManager.
2937                     * 
2938                     * Fix for 4472032
2939                     */
2940                    if (newFocusOwner != null
2941                            && event.getID() == FocusEvent.FOCUS_LOST) {
2942                        FocusEvent fe = (FocusEvent) event;
2943
2944                        if (manager.getGlobalFocusOwner() == fe.getComponent()
2945                                && fe.getOppositeComponent() == newFocusOwner) {
2946                            newFocusOwner = null;
2947                            return event;
2948                        }
2949                    }
2950                }
2951
2952                processCurrentLightweightRequests();
2953
2954                switch (event.getID()) {
2955                case FocusEvent.FOCUS_GAINED: {
2956                    event = retargetFocusGained((FocusEvent) event);
2957                    break;
2958                }
2959                case FocusEvent.FOCUS_LOST: {
2960                    event = retargetFocusLost((FocusEvent) event);
2961                    break;
2962                }
2963                default:
2964                    /* do nothing */
2965                }
2966                return event;
2967            }
2968
2969            /**
2970             * Clears markers queue
2971             * This method is not intended to be overridden by KFM's. 
2972             * Only DefaultKeyboardFocusManager can implement it.
2973             * @since 1.5
2974             */
2975            void clearMarkers() {
2976            }
2977
2978            static boolean removeFirstRequest() {
2979                KeyboardFocusManager manager = KeyboardFocusManager
2980                        .getCurrentKeyboardFocusManager();
2981
2982                synchronized (heavyweightRequests) {
2983                    HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2984
2985                    if (hwFocusRequest != null) {
2986                        heavyweightRequests.removeFirst();
2987                        if (hwFocusRequest.lightweightRequests != null) {
2988                            for (Iterator lwIter = hwFocusRequest.lightweightRequests
2989                                    .iterator(); lwIter.hasNext();) {
2990                                manager.dequeueKeyEvents(-1,
2991                                        ((LightweightFocusRequest) lwIter
2992                                                .next()).component);
2993                            }
2994                        }
2995                    }
2996                    // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2997                    // We do it here because this method is called only when problems happen 
2998                    if (heavyweightRequests.size() == 0) {
2999                        manager.clearMarkers();
3000                    }
3001                    return (heavyweightRequests.size() > 0);
3002                }
3003            }
3004
3005            static void removeLastFocusRequest(Component heavyweight) {
3006                if (dbg.on) {
3007                    dbg.assertion(heavyweight != null);
3008                }
3009
3010                KeyboardFocusManager manager = KeyboardFocusManager
3011                        .getCurrentKeyboardFocusManager();
3012                synchronized (heavyweightRequests) {
3013                    HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
3014                    if (hwFocusRequest != null
3015                            && hwFocusRequest.heavyweight == heavyweight) {
3016                        heavyweightRequests.removeLast();
3017                    }
3018                    // Fix for 4799136 - clear type-ahead markers if requests queue is empty
3019                    // We do it here because this method is called only when problems happen 
3020                    if (heavyweightRequests.size() == 0) {
3021                        manager.clearMarkers();
3022                    }
3023                }
3024            }
3025
3026            private static boolean focusedWindowChanged(Component to,
3027                    Component from) {
3028                Window wto = Component.getContainingWindow(to);
3029                Window wfrom = Component.getContainingWindow(from);
3030                if (wto == null && wfrom == null) {
3031                    return true;
3032                }
3033                if (wto == null) {
3034                    return true;
3035                }
3036                if (wfrom == null) {
3037                    return true;
3038                }
3039                return (wto != wfrom);
3040            }
3041
3042            private static boolean isTemporary(Component to, Component from) {
3043                Window wto = Component.getContainingWindow(to);
3044                Window wfrom = Component.getContainingWindow(from);
3045                if (wto == null && wfrom == null) {
3046                    return false;
3047                }
3048                if (wto == null) {
3049                    return true;
3050                }
3051                if (wfrom == null) {
3052                    return false;
3053                }
3054                return (wto != wfrom);
3055            }
3056
3057            static Component getHeavyweight(Component comp) {
3058                if (comp == null || comp.getPeer() == null) {
3059                    return null;
3060                } else if (comp.getPeer() instanceof  LightweightPeer) {
3061                    return comp.getNativeContainer();
3062                } else {
3063                    return comp;
3064                }
3065            }
3066
3067            static Field proxyActive;
3068
3069            // Accessor to private field isProxyActive of KeyEvent 
3070            private static boolean isProxyActiveImpl(KeyEvent e) {
3071                if (proxyActive == null) {
3072                    proxyActive = (Field) AccessController
3073                            .doPrivileged(new PrivilegedAction() {
3074                                public Object run() {
3075                                    Field field = null;
3076                                    try {
3077                                        field = KeyEvent.class
3078                                                .getDeclaredField("isProxyActive");
3079                                        if (field != null) {
3080                                            field.setAccessible(true);
3081                                        }
3082                                    } catch (NoSuchFieldException nsf) {
3083                                        assert (false);
3084                                    }
3085                                    return field;
3086                                }
3087                            });
3088                }
3089
3090                try {
3091                    return proxyActive.getBoolean(e);
3092                } catch (IllegalAccessException iae) {
3093                    assert (false);
3094                }
3095                return false;
3096            }
3097
3098            // Returns the value of this KeyEvent's field isProxyActive
3099            static boolean isProxyActive(KeyEvent e) {
3100                if (!GraphicsEnvironment.isHeadless()) {
3101                    return isProxyActiveImpl(e);
3102                } else {
3103                    return false;
3104                }
3105            }
3106
3107            private static HeavyweightFocusRequest getLastHWRequest() {
3108                synchronized (heavyweightRequests) {
3109                    return (heavyweightRequests.size() > 0) ? heavyweightRequests
3110                            .getLast()
3111                            : null;
3112                }
3113            }
3114
3115            private static HeavyweightFocusRequest getFirstHWRequest() {
3116                synchronized (heavyweightRequests) {
3117                    return (heavyweightRequests.size() > 0) ? heavyweightRequests
3118                            .getFirst()
3119                            : null;
3120                }
3121            }
3122        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.