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

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 geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
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:        }
ww_w__.___jav___a___2__s.__c_o_m | Contact Us
Copyright 2003 - 08 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.