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

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


0001        /*
0002         * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025        package java.awt;
0026
0027        import java.awt.event.FocusEvent;
0028        import java.awt.event.KeyEvent;
0029        import java.awt.event.WindowEvent;
0030        import java.awt.peer.ComponentPeer;
0031        import java.awt.peer.LightweightPeer;
0032        import java.lang.ref.WeakReference;
0033        import java.util.LinkedList;
0034        import java.util.Iterator;
0035        import java.util.ListIterator;
0036        import java.util.Set;
0037
0038        import java.util.logging.Level;
0039        import java.util.logging.Logger;
0040
0041        import sun.awt.AppContext;
0042        import sun.awt.SunToolkit;
0043        import sun.awt.CausedFocusEvent;
0044
0045        /**
0046         * The default KeyboardFocusManager for AWT applications. Focus traversal is
0047         * done in response to a Component's focus traversal keys, and using a
0048         * Container's FocusTraversalPolicy.
0049         * <p>
0050         * Please see
0051         * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
0052         * How to Use the Focus Subsystem</a>,
0053         * a section in <em>The Java Tutorial</em>, and the
0054         * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
0055         * for more information.
0056         *
0057         * @author David Mendenhall
0058         * @version 1.51, 06/25/07
0059         *
0060         * @see FocusTraversalPolicy
0061         * @see Component#setFocusTraversalKeys
0062         * @see Component#getFocusTraversalKeys
0063         * @since 1.4
0064         */
0065        public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
0066            private static final Logger focusLog = Logger
0067                    .getLogger("java.awt.focus.DefaultKeyboardFocusManager");
0068
0069            // null weak references to not create too many objects
0070            private static final WeakReference<Window> NULL_WINDOW_WR = new WeakReference<Window>(
0071                    null);
0072            private static final WeakReference<Component> NULL_COMPONENT_WR = new WeakReference<Component>(
0073                    null);
0074            private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR;
0075            private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR;
0076            private int inSendMessage;
0077            private LinkedList enqueuedKeyEvents = new LinkedList(),
0078                    typeAheadMarkers = new LinkedList();
0079            private boolean consumeNextKeyTyped;
0080
0081            private static class TypeAheadMarker {
0082                long after;
0083                Component untilFocused;
0084
0085                TypeAheadMarker(long after, Component untilFocused) {
0086                    this .after = after;
0087                    this .untilFocused = untilFocused;
0088                }
0089
0090                /**
0091                 * Returns string representation of the marker
0092                 */
0093                public String toString() {
0094                    return ">>> Marker after " + after + " on " + untilFocused;
0095                }
0096            }
0097
0098            private Window getOwningFrameDialog(Window window) {
0099                while (window != null
0100                        && !(window instanceof  Frame || window instanceof  Dialog)) {
0101                    window = (Window) window.getParent();
0102                }
0103                return window;
0104            }
0105
0106            /*
0107             * This series of restoreFocus methods is used for recovering from a
0108             * rejected focus or activation change. Rejections typically occur when
0109             * the user attempts to focus a non-focusable Component or Window.
0110             */
0111            private void restoreFocus(FocusEvent fe, Window newFocusedWindow) {
0112                Component realOppositeComponent = this .realOppositeComponentWR
0113                        .get();
0114                Component vetoedComponent = fe.getComponent();
0115
0116                if (newFocusedWindow != null
0117                        && restoreFocus(newFocusedWindow, vetoedComponent,
0118                                false)) {
0119                } else if (realOppositeComponent != null
0120                        && doRestoreFocus(realOppositeComponent,
0121                                vetoedComponent, false)) {
0122                } else if (fe.getOppositeComponent() != null
0123                        && doRestoreFocus(fe.getOppositeComponent(),
0124                                vetoedComponent, false)) {
0125                } else {
0126                    clearGlobalFocusOwner();
0127                }
0128            }
0129
0130            private void restoreFocus(WindowEvent we) {
0131                Window realOppositeWindow = this .realOppositeWindowWR.get();
0132                if (realOppositeWindow != null
0133                        && restoreFocus(realOppositeWindow, null, false)) {
0134                    // do nothing, everything is done in restoreFocus()
0135                } else if (we.getOppositeWindow() != null
0136                        && restoreFocus(we.getOppositeWindow(), null, false)) {
0137                    // do nothing, everything is done in restoreFocus()
0138                } else {
0139                    clearGlobalFocusOwner();
0140                }
0141            }
0142
0143            private boolean restoreFocus(Window aWindow,
0144                    Component vetoedComponent, boolean clearOnFailure) {
0145                Component toFocus = KeyboardFocusManager
0146                        .getMostRecentFocusOwner(aWindow);
0147
0148                if (toFocus != null && toFocus != vetoedComponent
0149                        && doRestoreFocus(toFocus, vetoedComponent, false)) {
0150                    return true;
0151                } else if (clearOnFailure) {
0152                    clearGlobalFocusOwner();
0153                    return true;
0154                } else {
0155                    return false;
0156                }
0157            }
0158
0159            private boolean restoreFocus(Component toFocus,
0160                    boolean clearOnFailure) {
0161                return doRestoreFocus(toFocus, null, clearOnFailure);
0162            }
0163
0164            private boolean doRestoreFocus(Component toFocus,
0165                    Component vetoedComponent, boolean clearOnFailure) {
0166                if (toFocus.isShowing()
0167                        && toFocus.isFocusable()
0168                        && toFocus.requestFocus(false,
0169                                CausedFocusEvent.Cause.ROLLBACK)) {
0170                    return true;
0171                } else {
0172                    Component nextFocus = toFocus.preNextFocusHelper();
0173                    if (nextFocus != vetoedComponent
0174                            && Component.postNextFocusHelper(nextFocus,
0175                                    CausedFocusEvent.Cause.ROLLBACK)) {
0176                        return true;
0177                    } else if (clearOnFailure) {
0178                        clearGlobalFocusOwner();
0179                        return true;
0180                    } else {
0181                        return false;
0182                    }
0183                }
0184            }
0185
0186            /**
0187             * A special type of SentEvent which updates a counter in the target
0188             * KeyboardFocusManager if it is an instance of
0189             * DefaultKeyboardFocusManager.
0190             */
0191            private static class DefaultKeyboardFocusManagerSentEvent extends
0192                    SentEvent {
0193                /*
0194                 * serialVersionUID
0195                 */
0196                private static final long serialVersionUID = -2924743257508701758L;
0197
0198                public DefaultKeyboardFocusManagerSentEvent(AWTEvent nested,
0199                        AppContext toNotify) {
0200                    super (nested, toNotify);
0201                }
0202
0203                public final void dispatch() {
0204                    KeyboardFocusManager manager = KeyboardFocusManager
0205                            .getCurrentKeyboardFocusManager();
0206                    DefaultKeyboardFocusManager defaultManager = (manager instanceof  DefaultKeyboardFocusManager) ? (DefaultKeyboardFocusManager) manager
0207                            : null;
0208
0209                    if (defaultManager != null) {
0210                        synchronized (defaultManager) {
0211                            defaultManager.inSendMessage++;
0212                        }
0213                    }
0214
0215                    super .dispatch();
0216
0217                    if (defaultManager != null) {
0218                        synchronized (defaultManager) {
0219                            defaultManager.inSendMessage--;
0220                        }
0221                    }
0222                }
0223            }
0224
0225            /**
0226             * Sends a synthetic AWTEvent to a Component. If the Component is in
0227             * the current AppContext, then the event is immediately dispatched.
0228             * If the Component is in a different AppContext, then the event is
0229             * posted to the other AppContext's EventQueue, and this method blocks
0230             * until the event is handled or target AppContext is disposed.
0231             * Returns true if successfuly dispatched event, false if failed 
0232             * to dispatch.
0233             */
0234            static boolean sendMessage(Component target, AWTEvent e) {
0235                e.isPosted = true;
0236                AppContext myAppContext = AppContext.getAppContext();
0237                final AppContext targetAppContext = target.appContext;
0238                final SentEvent se = new DefaultKeyboardFocusManagerSentEvent(
0239                        e, myAppContext);
0240
0241                if (myAppContext == targetAppContext) {
0242                    se.dispatch();
0243                } else {
0244                    if (targetAppContext.isDisposed()) {
0245                        return false;
0246                    }
0247                    SunToolkit.postEvent(targetAppContext, se);
0248                    if (EventQueue.isDispatchThread()) {
0249                        EventDispatchThread edt = (EventDispatchThread) Thread
0250                                .currentThread();
0251                        edt.pumpEvents(SentEvent.ID, new Conditional() {
0252                            public boolean evaluate() {
0253                                return !se.dispatched
0254                                        && !targetAppContext.isDisposed();
0255                            }
0256                        });
0257                    } else {
0258                        synchronized (se) {
0259                            while (!se.dispatched
0260                                    && !targetAppContext.isDisposed()) {
0261                                try {
0262                                    se.wait(1000);
0263                                } catch (InterruptedException ie) {
0264                                    break;
0265                                }
0266                            }
0267                        }
0268                    }
0269                }
0270                return se.dispatched;
0271            }
0272
0273            /**
0274             * This method is called by the AWT event dispatcher requesting that the
0275             * current KeyboardFocusManager dispatch the specified event on its behalf.
0276             * DefaultKeyboardFocusManagers dispatch all FocusEvents, all WindowEvents
0277             * related to focus, and all KeyEvents. These events are dispatched based
0278             * on the KeyboardFocusManager's notion of the focus owner and the focused
0279             * and active Windows, sometimes overriding the source of the specified
0280             * AWTEvent. If this method returns <code>false</code>, then the AWT event
0281             * dispatcher will attempt to dispatch the event itself.
0282             *
0283             * @param e the AWTEvent to be dispatched
0284             * @return <code>true</code> if this method dispatched the event;
0285             *         <code>false</code> otherwise
0286             */
0287            public boolean dispatchEvent(AWTEvent e) {
0288                if (focusLog.isLoggable(Level.FINE)
0289                        && (e instanceof  WindowEvent || e instanceof  FocusEvent))
0290                    focusLog.fine("" + e);
0291                switch (e.getID()) {
0292                case WindowEvent.WINDOW_GAINED_FOCUS: {
0293                    WindowEvent we = (WindowEvent) e;
0294                    Window oldFocusedWindow = getGlobalFocusedWindow();
0295                    Window newFocusedWindow = we.getWindow();
0296                    if (newFocusedWindow == oldFocusedWindow) {
0297                        break;
0298                    }
0299
0300                    if (!(newFocusedWindow.isFocusableWindow()
0301                            && newFocusedWindow.isVisible() && newFocusedWindow
0302                            .isDisplayable())) {
0303                        // we can not accept focus on such window, so reject it.
0304                        restoreFocus(we);
0305                        break;
0306                    }
0307                    // If there exists a current focused window, then notify it
0308                    // that it has lost focus.
0309                    if (oldFocusedWindow != null) {
0310                        boolean isEventDispatched = sendMessage(
0311                                oldFocusedWindow, new WindowEvent(
0312                                        oldFocusedWindow,
0313                                        WindowEvent.WINDOW_LOST_FOCUS,
0314                                        newFocusedWindow));
0315                        // Failed to dispatch, clear by ourselfves
0316                        if (!isEventDispatched) {
0317                            setGlobalFocusOwner(null);
0318                            setGlobalFocusedWindow(null);
0319                        }
0320                    }
0321
0322                    // Because the native libraries do not post WINDOW_ACTIVATED
0323                    // events, we need to synthesize one if the active Window
0324                    // changed.
0325                    Window newActiveWindow = getOwningFrameDialog(newFocusedWindow);
0326                    Window currentActiveWindow = getGlobalActiveWindow();
0327                    if (newActiveWindow != currentActiveWindow) {
0328                        sendMessage(newActiveWindow, new WindowEvent(
0329                                newActiveWindow, WindowEvent.WINDOW_ACTIVATED,
0330                                currentActiveWindow));
0331                        if (newActiveWindow != getGlobalActiveWindow()) {
0332                            // Activation change was rejected. Unlikely, but
0333                            // possible.
0334                            restoreFocus(we);
0335                            break;
0336                        }
0337                    }
0338
0339                    setGlobalFocusedWindow(newFocusedWindow);
0340
0341                    if (newFocusedWindow != getGlobalFocusedWindow()) {
0342                        // Focus change was rejected. Will happen if
0343                        // newFocusedWindow is not a focusable Window.
0344                        restoreFocus(we);
0345                        break;
0346                    }
0347
0348                    // Restore focus to the Component which last held it. We do
0349                    // this here so that client code can override our choice in
0350                    // a WINDOW_GAINED_FOCUS handler.
0351                    //
0352                    // Make sure that the focus change request doesn't change the
0353                    // focused Window in case we are no longer the focused Window
0354                    // when the request is handled.
0355                    if (inSendMessage == 0) {
0356                        // Identify which Component should initially gain focus 
0357                        // in the Window.
0358                        //
0359                        // * If we're in SendMessage, then this is a synthetic
0360                        //   WINDOW_GAINED_FOCUS message which was generated by a
0361                        //   the FOCUS_GAINED handler. Allow the Component to 
0362                        //   which the FOCUS_GAINED message was targeted to 
0363                        //   receive the focus.
0364                        // * Otherwise, look up the correct Component here. 
0365                        //   We don't use Window.getMostRecentFocusOwner because
0366                        //   window is focused now and 'null' will be returned
0367
0368                        // Calculating of most recent focus owner and focus 
0369                        // request should be synchronized on KeyboardFocusManager.class
0370                        // to prevent from thread race when user will request
0371                        // focus between calculation and our request.
0372                        // But if focus transfer is synchronous, this synchronization
0373                        // may cause deadlock, thus we don't synchronize this block.
0374                        Component toFocus = KeyboardFocusManager
0375                                .getMostRecentFocusOwner(newFocusedWindow);
0376                        if ((toFocus == null)
0377                                && newFocusedWindow.isFocusableWindow()) {
0378                            toFocus = newFocusedWindow
0379                                    .getFocusTraversalPolicy()
0380                                    .getInitialComponent(newFocusedWindow);
0381                        }
0382                        Component tempLost = null;
0383                        synchronized (KeyboardFocusManager.class) {
0384                            tempLost = newFocusedWindow
0385                                    .setTemporaryLostComponent(null);
0386                        }
0387
0388                        // The component which last has the focus when this window was focused
0389                        // should receive focus first
0390                        if (focusLog.isLoggable(Level.FINER)) {
0391                            focusLog.log(Level.FINER,
0392                                    "tempLost {0}, toFocus {1}", new Object[] {
0393                                            tempLost, toFocus });
0394                        }
0395                        if (tempLost != null) {
0396                            tempLost
0397                                    .requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
0398                        }
0399
0400                        if (toFocus != null && toFocus != tempLost) {
0401                            // If there is a component which requested focus when this window
0402                            // was inactive it expects to receive focus after activation.
0403                            toFocus
0404                                    .requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
0405                        }
0406                    }
0407
0408                    Window realOppositeWindow = this .realOppositeWindowWR.get();
0409                    if (realOppositeWindow != we.getOppositeWindow()) {
0410                        we = new WindowEvent(newFocusedWindow,
0411                                WindowEvent.WINDOW_GAINED_FOCUS,
0412                                realOppositeWindow);
0413                    }
0414                    return typeAheadAssertions(newFocusedWindow, we);
0415                }
0416
0417                case WindowEvent.WINDOW_ACTIVATED: {
0418                    WindowEvent we = (WindowEvent) e;
0419                    Window oldActiveWindow = getGlobalActiveWindow();
0420                    Window newActiveWindow = we.getWindow();
0421                    if (oldActiveWindow == newActiveWindow) {
0422                        break;
0423                    }
0424
0425                    // If there exists a current active window, then notify it that
0426                    // it has lost activation.
0427                    if (oldActiveWindow != null) {
0428                        boolean isEventDispatched = sendMessage(
0429                                oldActiveWindow, new WindowEvent(
0430                                        oldActiveWindow,
0431                                        WindowEvent.WINDOW_DEACTIVATED,
0432                                        newActiveWindow));
0433                        // Failed to dispatch, clear by ourselfves
0434                        if (!isEventDispatched) {
0435                            setGlobalActiveWindow(null);
0436                        }
0437                        if (getGlobalActiveWindow() != null) {
0438                            // Activation change was rejected. Unlikely, but
0439                            // possible.
0440                            break;
0441                        }
0442                    }
0443
0444                    setGlobalActiveWindow(newActiveWindow);
0445
0446                    if (newActiveWindow != getGlobalActiveWindow()) {
0447                        // Activation change was rejected. Unlikely, but
0448                        // possible.
0449                        break;
0450                    }
0451
0452                    return typeAheadAssertions(newActiveWindow, we);
0453                }
0454
0455                case FocusEvent.FOCUS_GAINED: {
0456                    FocusEvent fe = (FocusEvent) e;
0457                    CausedFocusEvent.Cause cause = (fe instanceof  CausedFocusEvent) ? ((CausedFocusEvent) fe)
0458                            .getCause()
0459                            : CausedFocusEvent.Cause.UNKNOWN;
0460                    Component oldFocusOwner = getGlobalFocusOwner();
0461                    Component newFocusOwner = fe.getComponent();
0462                    if (oldFocusOwner == newFocusOwner) {
0463                        if (focusLog.isLoggable(Level.FINE)) {
0464                            focusLog
0465                                    .log(
0466                                            Level.FINE,
0467                                            "Skipping {0} because focus owner is the same",
0468                                            new Object[] { e });
0469                        }
0470                        // We can't just drop the event - there could be
0471                        // type-ahead markers associated with it.
0472                        dequeueKeyEvents(-1, newFocusOwner);
0473                        break;
0474                    }
0475
0476                    // If there exists a current focus owner, then notify it that
0477                    // it has lost focus.
0478                    if (oldFocusOwner != null) {
0479                        boolean isEventDispatched = sendMessage(oldFocusOwner,
0480                                new CausedFocusEvent(oldFocusOwner,
0481                                        FocusEvent.FOCUS_LOST,
0482                                        fe.isTemporary(), newFocusOwner, cause));
0483                        // Failed to dispatch, clear by ourselfves
0484                        if (!isEventDispatched) {
0485                            setGlobalFocusOwner(null);
0486                            if (!fe.isTemporary()) {
0487                                setGlobalPermanentFocusOwner(null);
0488                            }
0489                        }
0490                    }
0491
0492                    // Because the native windowing system has a different notion
0493                    // of the current focus and activation states, it is possible
0494                    // that a Component outside of the focused Window receives a
0495                    // FOCUS_GAINED event. We synthesize a WINDOW_GAINED_FOCUS
0496                    // event in that case.
0497                    final Window newFocusedWindow = Component
0498                            .getContainingWindow(newFocusOwner);
0499                    final Window currentFocusedWindow = getGlobalFocusedWindow();
0500                    if (newFocusedWindow != null
0501                            && newFocusedWindow != currentFocusedWindow) {
0502                        sendMessage(newFocusedWindow, new WindowEvent(
0503                                newFocusedWindow,
0504                                WindowEvent.WINDOW_GAINED_FOCUS,
0505                                currentFocusedWindow));
0506                        if (newFocusedWindow != getGlobalFocusedWindow()) {
0507                            // Focus change was rejected. Will happen if
0508                            // newFocusedWindow is not a focusable Window.
0509
0510                            // Need to recover type-ahead, but don't bother
0511                            // restoring focus. That was done by the
0512                            // WINDOW_GAINED_FOCUS handler
0513                            dequeueKeyEvents(-1, newFocusOwner);
0514                            break;
0515                        }
0516                    }
0517
0518                    if (!(newFocusOwner.isFocusable()
0519                            && newFocusOwner.isEnabled() && newFocusOwner
0520                            .isShowing())) {
0521                        // we should not accept focus on such component, so reject it.
0522                        dequeueKeyEvents(-1, newFocusOwner);
0523                        if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
0524                            restoreFocus(fe, newFocusedWindow);
0525                        }
0526                        break;
0527                    }
0528
0529                    setGlobalFocusOwner(newFocusOwner);
0530
0531                    if (newFocusOwner != getGlobalFocusOwner()) {
0532                        // Focus change was rejected. Will happen if
0533                        // newFocusOwner is not focus traversable.
0534                        dequeueKeyEvents(-1, newFocusOwner);
0535                        if (KeyboardFocusManager.isAutoFocusTransferEnabled()) {
0536                            restoreFocus(fe, (Window) newFocusedWindow);
0537                        }
0538                        break;
0539                    }
0540
0541                    if (!fe.isTemporary()) {
0542                        setGlobalPermanentFocusOwner(newFocusOwner);
0543
0544                        if (newFocusOwner != getGlobalPermanentFocusOwner()) {
0545                            // Focus change was rejected. Unlikely, but possible.
0546                            dequeueKeyEvents(-1, newFocusOwner);
0547                            if (KeyboardFocusManager
0548                                    .isAutoFocusTransferEnabled()) {
0549                                restoreFocus(fe, (Window) newFocusedWindow);
0550                            }
0551                            break;
0552                        }
0553                    }
0554
0555                    setNativeFocusOwner(getHeavyweight(newFocusOwner));
0556
0557                    Component realOppositeComponent = this .realOppositeComponentWR
0558                            .get();
0559                    if (realOppositeComponent != null
0560                            && realOppositeComponent != fe
0561                                    .getOppositeComponent()) {
0562                        fe = new CausedFocusEvent(newFocusOwner,
0563                                FocusEvent.FOCUS_GAINED, fe.isTemporary(),
0564                                realOppositeComponent, cause);
0565                        ((AWTEvent) fe).isPosted = true;
0566                    }
0567                    return typeAheadAssertions(newFocusOwner, fe);
0568                }
0569
0570                case FocusEvent.FOCUS_LOST: {
0571                    FocusEvent fe = (FocusEvent) e;
0572                    Component currentFocusOwner = getGlobalFocusOwner();
0573                    if (currentFocusOwner == null) {
0574                        if (focusLog.isLoggable(Level.FINE))
0575                            focusLog.log(Level.FINE,
0576                                    "Skipping {0} because focus owner is null",
0577                                    new Object[] { e });
0578                        break;
0579                    }
0580                    // Ignore cases where a Component loses focus to itself.
0581                    // If we make a mistake because of retargeting, then the
0582                    // FOCUS_GAINED handler will correct it.
0583                    if (currentFocusOwner == fe.getOppositeComponent()) {
0584                        if (focusLog.isLoggable(Level.FINE))
0585                            focusLog
0586                                    .log(
0587                                            Level.FINE,
0588                                            "Skipping {0} because current focus owner is equal to opposite",
0589                                            new Object[] { e });
0590                        break;
0591                    }
0592
0593                    setGlobalFocusOwner(null);
0594
0595                    if (getGlobalFocusOwner() != null) {
0596                        // Focus change was rejected. Unlikely, but possible.
0597                        restoreFocus(currentFocusOwner, true);
0598                        break;
0599                    }
0600
0601                    if (!fe.isTemporary()) {
0602                        setGlobalPermanentFocusOwner(null);
0603
0604                        if (getGlobalPermanentFocusOwner() != null) {
0605                            // Focus change was rejected. Unlikely, but possible.
0606                            restoreFocus(currentFocusOwner, true);
0607                            break;
0608                        }
0609                    } else {
0610                        Window owningWindow = currentFocusOwner
0611                                .getContainingWindow();
0612                        if (owningWindow != null) {
0613                            owningWindow
0614                                    .setTemporaryLostComponent(currentFocusOwner);
0615                        }
0616                    }
0617
0618                    setNativeFocusOwner(null);
0619
0620                    fe.setSource(currentFocusOwner);
0621
0622                    realOppositeComponentWR = (fe.getOppositeComponent() != null) ? new WeakReference<Component>(
0623                            currentFocusOwner)
0624                            : NULL_COMPONENT_WR;
0625
0626                    return typeAheadAssertions(currentFocusOwner, fe);
0627                }
0628
0629                case WindowEvent.WINDOW_DEACTIVATED: {
0630                    WindowEvent we = (WindowEvent) e;
0631                    Window currentActiveWindow = getGlobalActiveWindow();
0632                    if (currentActiveWindow == null) {
0633                        break;
0634                    }
0635
0636                    if (currentActiveWindow != e.getSource()) {
0637                        // The event is lost in time.
0638                        // Allow listeners to precess the event but do not 
0639                        // change any global states
0640                        break;
0641                    }
0642
0643                    setGlobalActiveWindow(null);
0644                    if (getGlobalActiveWindow() != null) {
0645                        // Activation change was rejected. Unlikely, but possible.
0646                        break;
0647                    }
0648
0649                    we.setSource(currentActiveWindow);
0650                    return typeAheadAssertions(currentActiveWindow, we);
0651                }
0652
0653                case WindowEvent.WINDOW_LOST_FOCUS: {
0654                    WindowEvent we = (WindowEvent) e;
0655                    Window currentFocusedWindow = getGlobalFocusedWindow();
0656                    Window losingFocusWindow = we.getWindow();
0657                    Window activeWindow = getGlobalActiveWindow();
0658                    Window oppositeWindow = we.getOppositeWindow();
0659                    if (focusLog.isLoggable(Level.FINE))
0660                        focusLog
0661                                .log(
0662                                        Level.FINE,
0663                                        "Active {0}, Current focused {1}, losing focus {2} opposite {3}",
0664                                        new Object[] { activeWindow,
0665                                                currentFocusedWindow,
0666                                                losingFocusWindow,
0667                                                oppositeWindow });
0668                    if (currentFocusedWindow == null) {
0669                        break;
0670                    }
0671
0672                    // Special case -- if the native windowing system posts an
0673                    // event claiming that the active Window has lost focus to the
0674                    // focused Window, then discard the event. This is an artifact
0675                    // of the native windowing system not knowing which Window is
0676                    // really focused.
0677                    if (inSendMessage == 0 && losingFocusWindow == activeWindow
0678                            && oppositeWindow == currentFocusedWindow) {
0679                        break;
0680                    }
0681
0682                    Component currentFocusOwner = getGlobalFocusOwner();
0683                    if (currentFocusOwner != null) {
0684                        // The focus owner should always receive a FOCUS_LOST event
0685                        // before the Window is defocused.
0686                        Component oppositeComp = null;
0687                        if (oppositeWindow != null) {
0688                            oppositeComp = oppositeWindow
0689                                    .getTemporaryLostComponent();
0690                            if (oppositeComp == null) {
0691                                oppositeComp = oppositeWindow
0692                                        .getMostRecentFocusOwner();
0693                            }
0694                        }
0695                        if (oppositeComp == null) {
0696                            oppositeComp = oppositeWindow;
0697                        }
0698                        sendMessage(currentFocusOwner,
0699                                new CausedFocusEvent(currentFocusOwner,
0700                                        FocusEvent.FOCUS_LOST, true,
0701                                        oppositeComp,
0702                                        CausedFocusEvent.Cause.ACTIVATION));
0703                    }
0704
0705                    setGlobalFocusedWindow(null);
0706                    if (getGlobalFocusedWindow() != null) {
0707                        // Focus change was rejected. Unlikely, but possible.
0708                        restoreFocus(currentFocusedWindow, null, true);
0709                        break;
0710                    }
0711
0712                    we.setSource(currentFocusedWindow);
0713                    realOppositeWindowWR = (oppositeWindow != null) ? new WeakReference<Window>(
0714                            currentFocusedWindow)
0715                            : NULL_WINDOW_WR;
0716                    typeAheadAssertions(currentFocusedWindow, we);
0717
0718                    if (oppositeWindow == null) {
0719                        // Then we need to deactive the active Window as well.
0720                        // No need to synthesize in other cases, because
0721                        // WINDOW_ACTIVATED will handle it if necessary.
0722                        sendMessage(activeWindow, new WindowEvent(activeWindow,
0723                                WindowEvent.WINDOW_DEACTIVATED, null));
0724                        if (getGlobalActiveWindow() != null) {
0725                            // Activation change was rejected. Unlikely,
0726                            // but possible.
0727                            restoreFocus(currentFocusedWindow, null, true);
0728                        }
0729                    }
0730                    break;
0731                }
0732
0733                case KeyEvent.KEY_TYPED:
0734                case KeyEvent.KEY_PRESSED:
0735                case KeyEvent.KEY_RELEASED:
0736                    return typeAheadAssertions(null, e);
0737
0738                default:
0739                    return false;
0740                }
0741
0742                return true;
0743            }
0744
0745            /**
0746             * Called by <code>dispatchEvent</code> if no other
0747             * KeyEventDispatcher in the dispatcher chain dispatched the KeyEvent, or
0748             * if no other KeyEventDispatchers are registered. If the event has not
0749             * been consumed, its target is enabled, and the focus owner is not null,
0750             * this method dispatches the event to its target. This method will also
0751             * subsequently dispatch the event to all registered
0752             * KeyEventPostProcessors. After all this operations are finished, 
0753             * the event is passed to peers for processing.
0754             * <p>
0755             * In all cases, this method returns <code>true</code>, since
0756             * DefaultKeyboardFocusManager is designed so that neither
0757             * <code>dispatchEvent</code>, nor the AWT event dispatcher, should take
0758             * further action on the event in any situation.
0759             *
0760             * @param e the KeyEvent to be dispatched
0761             * @return <code>true</code>
0762             * @see Component#dispatchEvent
0763             */
0764            public boolean dispatchKeyEvent(KeyEvent e) {
0765                Component focusOwner = (((AWTEvent) e).isPosted) ? getFocusOwner()
0766                        : e.getComponent();
0767
0768                if (focusOwner != null && focusOwner.isShowing()
0769                        && focusOwner.isFocusable() && focusOwner.isEnabled()) {
0770                    if (!e.isConsumed()) {
0771                        Component comp = e.getComponent();
0772                        if (comp != null && comp.isEnabled()) {
0773                            redispatchEvent(comp, e);
0774                        }
0775                    }
0776                }
0777                boolean stopPostProcessing = false;
0778                java.util.List processors = getKeyEventPostProcessors();
0779                if (processors != null) {
0780                    for (java.util.Iterator iter = processors.iterator(); !stopPostProcessing
0781                            && iter.hasNext();) {
0782                        stopPostProcessing = (((KeyEventPostProcessor) (iter
0783                                .next())).postProcessKeyEvent(e));
0784                    }
0785                }
0786                if (!stopPostProcessing) {
0787                    postProcessKeyEvent(e);
0788                }
0789
0790                // Allow the peer to process KeyEvent
0791                Component source = e.getComponent();
0792                ComponentPeer peer = source.getPeer();
0793
0794                if (peer == null || peer instanceof  LightweightPeer) {
0795                    // if focus owner is lightweight then its native container 
0796                    // processes event
0797                    Container target = source.getNativeContainer();
0798                    if (target != null) {
0799                        peer = target.getPeer();
0800                    }
0801                }
0802                if (peer != null) {
0803                    peer.handleEvent(e);
0804                }
0805
0806                return true;
0807            }
0808
0809            /**
0810             * This method will be called by <code>dispatchKeyEvent</code>. It will
0811             * handle any unconsumed KeyEvents that map to an AWT
0812             * <code>MenuShortcut</code> by consuming the event and activating the
0813             * shortcut.
0814             *
0815             * @param e the KeyEvent to post-process
0816             * @return <code>true</code>
0817             * @see #dispatchKeyEvent
0818             * @see MenuShortcut
0819             */
0820            public boolean postProcessKeyEvent(KeyEvent e) {
0821                if (!e.isConsumed()) {
0822                    Component target = e.getComponent();
0823                    Container p = (Container) (target instanceof  Container ? target
0824                            : target.getParent());
0825                    if (p != null) {
0826                        p.postProcessKeyEvent(e);
0827                    }
0828                }
0829                return true;
0830            }
0831
0832            private void pumpApprovedKeyEvents() {
0833                KeyEvent ke;
0834                do {
0835                    ke = null;
0836                    synchronized (this ) {
0837                        if (enqueuedKeyEvents.size() != 0) {
0838                            ke = (KeyEvent) enqueuedKeyEvents.getFirst();
0839                            if (typeAheadMarkers.size() != 0) {
0840                                TypeAheadMarker marker = (TypeAheadMarker) typeAheadMarkers
0841                                        .getFirst();
0842                                // Fixed 5064013: may appears that the events have the same time
0843                                // if (ke.getWhen() >= marker.after) {
0844                                // The fix is rolled out.
0845
0846                                if (ke.getWhen() > marker.after) {
0847                                    ke = null;
0848                                }
0849                            }
0850                            if (ke != null) {
0851                                focusLog.log(Level.FINER,
0852                                        "Pumping approved event {0}",
0853                                        new Object[] { ke });
0854                                enqueuedKeyEvents.removeFirst();
0855                            }
0856                        }
0857                    }
0858                    if (ke != null) {
0859                        preDispatchKeyEvent(ke);
0860                    }
0861                } while (ke != null);
0862            }
0863
0864            /**
0865             * Dumps the list of type-ahead queue markers to stderr
0866             */
0867            void dumpMarkers() {
0868                if (focusLog.isLoggable(Level.FINEST)) {
0869                    focusLog.log(Level.FINEST, ">>> Markers dump, time: {0}",
0870                            System.currentTimeMillis());
0871                    synchronized (this ) {
0872                        if (typeAheadMarkers.size() != 0) {
0873                            Iterator iter = typeAheadMarkers.iterator();
0874                            while (iter.hasNext()) {
0875                                TypeAheadMarker marker = (TypeAheadMarker) iter
0876                                        .next();
0877                                focusLog.log(Level.FINEST, "    {0}", marker);
0878                            }
0879                        }
0880                    }
0881                }
0882            }
0883
0884            private boolean typeAheadAssertions(Component target, AWTEvent e) {
0885
0886                // Clear any pending events here as well as in the FOCUS_GAINED
0887                // handler. We need this call here in case a marker was removed in
0888                // response to a call to dequeueKeyEvents.
0889                pumpApprovedKeyEvents();
0890
0891                switch (e.getID()) {
0892                case KeyEvent.KEY_TYPED:
0893                case KeyEvent.KEY_PRESSED:
0894                case KeyEvent.KEY_RELEASED: {
0895                    KeyEvent ke = (KeyEvent) e;
0896                    synchronized (this ) {
0897                        if (e.isPosted && typeAheadMarkers.size() != 0) {
0898                            TypeAheadMarker marker = (TypeAheadMarker) typeAheadMarkers
0899                                    .getFirst();
0900                            // Fixed 5064013: may appears that the events have the same time
0901                            // if (ke.getWhen() >= marker.after) {
0902                            // The fix is rolled out.
0903
0904                            if (ke.getWhen() > marker.after) {
0905                                focusLog
0906                                        .log(
0907                                                Level.FINER,
0908                                                "Storing event {0} because of marker {1}",
0909                                                new Object[] { ke, marker });
0910                                enqueuedKeyEvents.addLast(ke);
0911                                return true;
0912                            }
0913                        }
0914                    }
0915
0916                    // KeyEvent was posted before focus change request
0917                    return preDispatchKeyEvent(ke);
0918                }
0919
0920                case FocusEvent.FOCUS_GAINED:
0921                    focusLog.log(Level.FINEST,
0922                            "Markers before FOCUS_GAINED on {0}",
0923                            new Object[] { target });
0924                    dumpMarkers();
0925                    // Search the marker list for the first marker tied to
0926                    // the Component which just gained focus. Then remove
0927                    // that marker, any markers which immediately follow
0928                    // and are tied to the same component, and all markers
0929                    // that preceed it. This handles the case where
0930                    // multiple focus requests were made for the same
0931                    // Component in a row and when we lost some of the
0932                    // earlier requests. Since FOCUS_GAINED events will
0933                    // not be generated for these additional requests, we
0934                    // need to clear those markers too.
0935                    synchronized (this ) {
0936                        boolean found = false;
0937                        if (hasMarker(target)) {
0938                            for (Iterator iter = typeAheadMarkers.iterator(); iter
0939                                    .hasNext();) {
0940                                if (((TypeAheadMarker) iter.next()).untilFocused == target) {
0941                                    found = true;
0942                                } else if (found) {
0943                                    break;
0944                                }
0945                                iter.remove();
0946                            }
0947                        } else {
0948                            // Exception condition - event without marker
0949                            focusLog.log(Level.FINER,
0950                                    "Event without marker {0}", e);
0951                        }
0952                    }
0953                    focusLog.log(Level.FINEST, "Markers after FOCUS_GAINED");
0954                    dumpMarkers();
0955
0956                    redispatchEvent(target, e);
0957
0958                    // Now, dispatch any pending KeyEvents which have been
0959                    // released because of the FOCUS_GAINED event so that we don't
0960                    // have to wait for another event to be posted to the queue.
0961                    pumpApprovedKeyEvents();
0962                    return true;
0963
0964                default:
0965                    redispatchEvent(target, e);
0966                    return true;
0967                }
0968            }
0969
0970            /**
0971             * Returns true if there are some marker associated with component <code>comp</code> 
0972             * in a markers' queue
0973             * @since 1.5
0974             */
0975            private boolean hasMarker(Component comp) {
0976                for (Iterator iter = typeAheadMarkers.iterator(); iter
0977                        .hasNext();) {
0978                    if (((TypeAheadMarker) iter.next()).untilFocused == comp) {
0979                        return true;
0980                    }
0981                }
0982                return false;
0983            }
0984
0985            /**
0986             * Clears markers queue
0987             * @since 1.5
0988             */
0989            void clearMarkers() {
0990                synchronized (this ) {
0991                    typeAheadMarkers.clear();
0992                }
0993            }
0994
0995            private boolean preDispatchKeyEvent(KeyEvent ke) {
0996                if (((AWTEvent) ke).isPosted) {
0997                    Component focusOwner = getFocusOwner();
0998                    ke.setSource(((focusOwner != null) ? focusOwner
0999                            : getFocusedWindow()));
1000                }
1001                if (ke.getSource() == null) {
1002                    return true;
1003                }
1004
1005                // Explicitly set the current event and most recent timestamp here in
1006                // addition to the call in Component.dispatchEventImpl. Because
1007                // KeyEvents can be delivered in response to a FOCUS_GAINED event, the
1008                // current timestamp may be incorrect. We need to set it here so that
1009                // KeyEventDispatchers will use the correct time.
1010                EventQueue.setCurrentEventAndMostRecentTime(ke);
1011
1012                /**
1013                 * Fix for 4495473.
1014                 * This fix allows to correctly dispatch events when native
1015                 * event proxying mechanism is active.
1016                 * If it is active we should redispatch key events after
1017                 * we detected its correct target.
1018                 */
1019                if (KeyboardFocusManager.isProxyActive(ke)) {
1020                    Component source = (Component) ke.getSource();
1021                    Container target = source.getNativeContainer();
1022                    if (target != null) {
1023                        ComponentPeer peer = target.getPeer();
1024                        if (peer != null) {
1025                            peer.handleEvent(ke);
1026                            /**
1027                             * Fix for 4478780 - consume event after it was dispatched by peer.
1028                             */
1029                            ke.consume();
1030                        }
1031                    }
1032                    return true;
1033                }
1034
1035                java.util.List dispatchers = getKeyEventDispatchers();
1036                if (dispatchers != null) {
1037                    for (java.util.Iterator iter = dispatchers.iterator(); iter
1038                            .hasNext();) {
1039                        if (((KeyEventDispatcher) (iter.next()))
1040                                .dispatchKeyEvent(ke)) {
1041                            return true;
1042                        }
1043                    }
1044                }
1045                return dispatchKeyEvent(ke);
1046            }
1047
1048            /* 
1049             * @param e is a KEY_PRESSED event that can be used
1050             *          to track the next KEY_TYPED related.
1051             */
1052            private void consumeNextKeyTyped(KeyEvent e) {
1053                consumeNextKeyTyped = true;
1054            }
1055
1056            private void consumeTraversalKey(KeyEvent e) {
1057                e.consume();
1058                consumeNextKeyTyped = (e.getID() == KeyEvent.KEY_PRESSED)
1059                        && !e.isActionKey();
1060            }
1061
1062            /*
1063             * return true if event was consumed
1064             */
1065            private boolean consumeProcessedKeyEvent(KeyEvent e) {
1066                if ((e.getID() == KeyEvent.KEY_TYPED) && consumeNextKeyTyped) {
1067                    e.consume();
1068                    consumeNextKeyTyped = false;
1069                    return true;
1070                }
1071                return false;
1072            }
1073
1074            /**
1075             * This method initiates a focus traversal operation if and only if the
1076             * KeyEvent represents a focus traversal key for the specified
1077             * focusedComponent. It is expected that focusedComponent is the current
1078             * focus owner, although this need not be the case. If it is not,
1079             * focus traversal will nevertheless proceed as if focusedComponent
1080             * were the focus owner.
1081             *
1082             * @param focusedComponent the Component that is the basis for a focus
1083             *        traversal operation if the specified event represents a focus
1084             *        traversal key for the Component
1085             * @param e the event that may represent a focus traversal key
1086             */
1087            public void processKeyEvent(Component focusedComponent, KeyEvent e) {
1088                // consume processed event if needed
1089                if (consumeProcessedKeyEvent(e)) {
1090                    return;
1091                }
1092
1093                // KEY_TYPED events cannot be focus traversal keys
1094                if (e.getID() == KeyEvent.KEY_TYPED) {
1095                    return;
1096                }
1097
1098                if (focusedComponent.getFocusTraversalKeysEnabled()
1099                        && !e.isConsumed()) {
1100                    AWTKeyStroke stroke = AWTKeyStroke
1101                            .getAWTKeyStrokeForEvent(e), oppStroke = AWTKeyStroke
1102                            .getAWTKeyStroke(stroke.getKeyCode(), stroke
1103                                    .getModifiers(), !stroke.isOnKeyRelease());
1104                    Set toTest;
1105                    boolean contains, containsOpp;
1106
1107                    toTest = focusedComponent
1108                            .getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1109                    contains = toTest.contains(stroke);
1110                    containsOpp = toTest.contains(oppStroke);
1111
1112                    if (contains || containsOpp) {
1113                        consumeTraversalKey(e);
1114                        if (contains) {
1115                            focusNextComponent(focusedComponent);
1116                        }
1117                        return;
1118                    }
1119
1120                    toTest = focusedComponent
1121                            .getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1122                    contains = toTest.contains(stroke);
1123                    containsOpp = toTest.contains(oppStroke);
1124
1125                    if (contains || containsOpp) {
1126                        consumeTraversalKey(e);
1127                        if (contains) {
1128                            focusPreviousComponent(focusedComponent);
1129                        }
1130                        return;
1131                    }
1132
1133                    toTest = focusedComponent
1134                            .getFocusTraversalKeys(KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1135                    contains = toTest.contains(stroke);
1136                    containsOpp = toTest.contains(oppStroke);
1137
1138                    if (contains || containsOpp) {
1139                        consumeTraversalKey(e);
1140                        if (contains) {
1141                            upFocusCycle(focusedComponent);
1142                        }
1143                        return;
1144                    }
1145
1146                    if (!((focusedComponent instanceof  Container) && ((Container) focusedComponent)
1147                            .isFocusCycleRoot())) {
1148                        return;
1149                    }
1150
1151                    toTest = focusedComponent
1152                            .getFocusTraversalKeys(KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1153                    contains = toTest.contains(stroke);
1154                    containsOpp = toTest.contains(oppStroke);
1155
1156                    if (contains || containsOpp) {
1157                        consumeTraversalKey(e);
1158                        if (contains) {
1159                            downFocusCycle((Container) focusedComponent);
1160                        }
1161                    }
1162                }
1163            }
1164
1165            /**
1166             * Delays dispatching of KeyEvents until the specified Component becomes
1167             * the focus owner. KeyEvents with timestamps later than the specified
1168             * timestamp will be enqueued until the specified Component receives a
1169             * FOCUS_GAINED event, or the AWT cancels the delay request by invoking
1170             * <code>dequeueKeyEvents</code> or <code>discardKeyEvents</code>.
1171             *
1172             * @param after timestamp of current event, or the current, system time if
1173             *        the current event has no timestamp, or the AWT cannot determine
1174             *        which event is currently being handled
1175             * @param untilFocused Component which will receive a FOCUS_GAINED event
1176             *        before any pending KeyEvents
1177             * @see #dequeueKeyEvents
1178             * @see #discardKeyEvents
1179             */
1180            protected synchronized void enqueueKeyEvents(long after,
1181                    Component untilFocused) {
1182                if (untilFocused == null) {
1183                    return;
1184                }
1185
1186                focusLog.log(Level.FINER, "Enqueue at {0} for {1}",
1187                        new Object[] { after, untilFocused });
1188
1189                int insertionIndex = 0, i = typeAheadMarkers.size();
1190                ListIterator iter = typeAheadMarkers.listIterator(i);
1191
1192                for (; i > 0; i--) {
1193                    TypeAheadMarker marker = (TypeAheadMarker) iter.previous();
1194                    if (marker.after <= after) {
1195                        insertionIndex = i;
1196                        break;
1197                    }
1198                }
1199
1200                typeAheadMarkers.add(insertionIndex, new TypeAheadMarker(after,
1201                        untilFocused));
1202            }
1203
1204            /**
1205             * Releases for normal dispatching to the current focus owner all
1206             * KeyEvents which were enqueued because of a call to
1207             * <code>enqueueKeyEvents</code> with the same timestamp and Component.
1208             * If the given timestamp is less than zero, the outstanding enqueue
1209             * request for the given Component with the <b>oldest</b> timestamp (if
1210             * any) should be cancelled.
1211             *
1212             * @param after the timestamp specified in the call to
1213             *        <code>enqueueKeyEvents</code>, or any value < 0
1214             * @param untilFocused the Component specified in the call to
1215             *        <code>enqueueKeyEvents</code>
1216             * @see #enqueueKeyEvents
1217             * @see #discardKeyEvents
1218             */
1219            protected synchronized void dequeueKeyEvents(long after,
1220                    Component untilFocused) {
1221                if (untilFocused == null) {
1222                    return;
1223                }
1224
1225                focusLog.log(Level.FINER, "Dequeue at {0} for {1}",
1226                        new Object[] { after, untilFocused });
1227
1228                TypeAheadMarker marker;
1229                ListIterator iter = typeAheadMarkers
1230                        .listIterator((after >= 0) ? typeAheadMarkers.size()
1231                                : 0);
1232
1233                if (after < 0) {
1234                    while (iter.hasNext()) {
1235                        marker = (TypeAheadMarker) iter.next();
1236                        if (marker.untilFocused == untilFocused) {
1237                            iter.remove();
1238                            return;
1239                        }
1240                    }
1241                } else {
1242                    while (iter.hasPrevious()) {
1243                        marker = (TypeAheadMarker) iter.previous();
1244                        if (marker.untilFocused == untilFocused
1245                                && marker.after == after) {
1246                            iter.remove();
1247                            return;
1248                        }
1249                    }
1250                }
1251            }
1252
1253            /**
1254             * Discards all KeyEvents which were enqueued because of one or more calls
1255             * to <code>enqueueKeyEvents</code> with the specified Component, or one of
1256             * its descendants.
1257             *
1258             * @param comp the Component specified in one or more calls to
1259             *        <code>enqueueKeyEvents</code>, or a parent of such a Component
1260             * @see #enqueueKeyEvents
1261             * @see #dequeueKeyEvents
1262             */
1263            protected synchronized void discardKeyEvents(Component comp) {
1264                if (comp == null) {
1265                    return;
1266                }
1267
1268                long start = -1;
1269
1270                for (Iterator iter = typeAheadMarkers.iterator(); iter
1271                        .hasNext();) {
1272                    TypeAheadMarker marker = (TypeAheadMarker) iter.next();
1273                    Component toTest = marker.untilFocused;
1274                    boolean match = (toTest == comp);
1275                    while (!match && toTest != null
1276                            && !(toTest instanceof  Window)) {
1277                        toTest = toTest.getParent();
1278                        match = (toTest == comp);
1279                    }
1280                    if (match) {
1281                        if (start < 0) {
1282                            start = marker.after;
1283                        }
1284                        iter.remove();
1285                    } else if (start >= 0) {
1286                        purgeStampedEvents(start, marker.after);
1287                        start = -1;
1288                    }
1289                }
1290
1291                purgeStampedEvents(start, -1);
1292            }
1293
1294            // Notes:
1295            //   * must be called inside a synchronized block
1296            //   * if 'start' is < 0, then this function does nothing
1297            //   * if 'end' is < 0, then all KeyEvents from 'start' to the end of the
1298            //     queue will be removed
1299            private void purgeStampedEvents(long start, long end) {
1300                if (start < 0) {
1301                    return;
1302                }
1303
1304                for (Iterator iter = enqueuedKeyEvents.iterator(); iter
1305                        .hasNext();) {
1306                    KeyEvent ke = (KeyEvent) iter.next();
1307                    long time = ke.getWhen();
1308
1309                    if (start < time && (end < 0 || time <= end)) {
1310                        iter.remove();
1311                    }
1312
1313                    if (end >= 0 && time > end) {
1314                        break;
1315                    }
1316                }
1317            }
1318
1319            /**
1320             * Focuses the Component before aComponent, typically based on a
1321             * FocusTraversalPolicy.
1322             *
1323             * @param aComponent the Component that is the basis for the focus
1324             *        traversal operation
1325             * @see FocusTraversalPolicy
1326             * @see Component#transferFocusBackward
1327             */
1328            public void focusPreviousComponent(Component aComponent) {
1329                if (aComponent != null) {
1330                    aComponent.transferFocusBackward();
1331                }
1332            }
1333
1334            /**
1335             * Focuses the Component after aComponent, typically based on a
1336             * FocusTraversalPolicy.
1337             *
1338             * @param aComponent the Component that is the basis for the focus
1339             *        traversal operation
1340             * @see FocusTraversalPolicy
1341             * @see Component#transferFocus
1342             */
1343            public void focusNextComponent(Component aComponent) {
1344                if (aComponent != null) {
1345                    aComponent.transferFocus();
1346                }
1347            }
1348
1349            /**
1350             * Moves the focus up one focus traversal cycle. Typically, the focus owner
1351             * is set to aComponent's focus cycle root, and the current focus cycle
1352             * root is set to the new focus owner's focus cycle root. If, however,
1353             * aComponent's focus cycle root is a Window, then the focus owner is set
1354             * to the focus cycle root's default Component to focus, and the current
1355             * focus cycle root is unchanged.
1356             *
1357             * @param aComponent the Component that is the basis for the focus
1358             *        traversal operation
1359             * @see Component#transferFocusUpCycle
1360             */
1361            public void upFocusCycle(Component aComponent) {
1362                if (aComponent != null) {
1363                    aComponent.transferFocusUpCycle();
1364                }
1365            }
1366
1367            /**
1368             * Moves the focus down one focus traversal cycle. If aContainer is a focus
1369             * cycle root, then the focus owner is set to aContainer's default
1370             * Component to focus, and the current focus cycle root is set to
1371             * aContainer. If aContainer is not a focus cycle root, then no focus
1372             * traversal operation occurs.
1373             *
1374             * @param aContainer the Container that is the basis for the focus
1375             *        traversal operation
1376             * @see Container#transferFocusDownCycle
1377             */
1378            public void downFocusCycle(Container aContainer) {
1379                if (aContainer != null && aContainer.isFocusCycleRoot()) {
1380                    aContainer.transferFocusDownCycle();
1381                }
1382            }
1383        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.