< prev index next >

src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java

Print this page




  40 
  41 import java.lang.ref.WeakReference;
  42 
  43 import java.lang.reflect.Field;
  44 
  45 import java.security.AccessController;
  46 import java.security.PrivilegedAction;
  47 
  48 import java.util.Collections;
  49 import java.util.HashSet;
  50 import java.util.Iterator;
  51 import java.util.LinkedList;
  52 import java.util.Set;
  53 import java.util.StringTokenizer;
  54 import java.util.WeakHashMap;
  55 
  56 import sun.util.logging.PlatformLogger;
  57 
  58 import sun.awt.AppContext;
  59 import sun.awt.SunToolkit;
  60 import sun.awt.CausedFocusEvent;
  61 import sun.awt.KeyboardFocusManagerPeerProvider;
  62 import sun.awt.AWTAccessor;
  63 
  64 /**
  65  * The KeyboardFocusManager is responsible for managing the active and focused
  66  * Windows, and the current focus owner. The focus owner is defined as the
  67  * Component in an application that will typically receive all KeyEvents
  68  * generated by the user. The focused Window is the Window that is, or
  69  * contains, the focus owner. Only a Frame or a Dialog can be the active
  70  * Window. The native windowing system may denote the active Window or its
  71  * children with special decorations, such as a highlighted title bar. The
  72  * active Window is always either the focused Window, or the first Frame or
  73  * Dialog that is an owner of the focused Window.
  74  * <p>
  75  * The KeyboardFocusManager is both a centralized location for client code to
  76  * query for the focus owner and initiate focus changes, and an event
  77  * dispatcher for all FocusEvents, WindowEvents related to focus, and
  78  * KeyEvents.
  79  * <p>
  80  * Some browsers partition applets in different code bases into separate


 107 public abstract class KeyboardFocusManager
 108     implements KeyEventDispatcher, KeyEventPostProcessor
 109 {
 110 
 111     // Shared focus engine logger
 112     private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
 113 
 114     static {
 115         /* ensure that the necessary native libraries are loaded */
 116         Toolkit.loadLibraries();
 117         if (!GraphicsEnvironment.isHeadless()) {
 118             initIDs();
 119         }
 120         AWTAccessor.setKeyboardFocusManagerAccessor(
 121             new AWTAccessor.KeyboardFocusManagerAccessor() {
 122                 public int shouldNativelyFocusHeavyweight(Component heavyweight,
 123                                                    Component descendant,
 124                                                    boolean temporary,
 125                                                    boolean focusedWindowChangeAllowed,
 126                                                    long time,
 127                                                    CausedFocusEvent.Cause cause)
 128                 {
 129                     return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
 130                         heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
 131                 }
 132                 public boolean processSynchronousLightweightTransfer(Component heavyweight,
 133                                                               Component descendant,
 134                                                               boolean temporary,
 135                                                               boolean focusedWindowChangeAllowed,
 136                                                               long time)
 137                 {
 138                     return KeyboardFocusManager.processSynchronousLightweightTransfer(
 139                         heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
 140                 }
 141                 public void removeLastFocusRequest(Component heavyweight) {
 142                     KeyboardFocusManager.removeLastFocusRequest(heavyweight);
 143                 }
 144                 public void setMostRecentFocusOwner(Window window, Component component) {
 145                     KeyboardFocusManager.setMostRecentFocusOwner(window, component);
 146                 }
 147                 public KeyboardFocusManager getCurrentKeyboardFocusManager(AppContext ctx) {


2157             downFocusCycle((Container)focusOwner);
2158         }
2159     }
2160 
2161     /**
2162      * Dumps the list of focus requests to stderr
2163      */
2164     void dumpRequests() {
2165         System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2166         synchronized (heavyweightRequests) {
2167             for (HeavyweightFocusRequest req : heavyweightRequests) {
2168                 System.err.println(">>> Req: " + req);
2169             }
2170         }
2171         System.err.println("");
2172     }
2173 
2174     private static final class LightweightFocusRequest {
2175         final Component component;
2176         final boolean temporary;
2177         final CausedFocusEvent.Cause cause;
2178 
2179         LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
2180             this.component = component;
2181             this.temporary = temporary;
2182             this.cause = cause;
2183         }
2184         public String toString() {
2185             return "LightweightFocusRequest[component=" + component +
2186                 ",temporary=" + temporary + ", cause=" + cause + "]";
2187         }
2188     }
2189 
2190     private static final class HeavyweightFocusRequest {
2191         final Component heavyweight;
2192         final LinkedList<LightweightFocusRequest> lightweightRequests;
2193 
2194         static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2195             new HeavyweightFocusRequest();
2196 
2197         private HeavyweightFocusRequest() {
2198             heavyweight = null;
2199             lightweightRequests = null;
2200         }
2201 
2202         HeavyweightFocusRequest(Component heavyweight, Component descendant,
2203                                 boolean temporary, CausedFocusEvent.Cause cause) {
2204             if (log.isLoggable(PlatformLogger.Level.FINE)) {
2205                 if (heavyweight == null) {
2206                     log.fine("Assertion (heavyweight != null) failed");
2207                 }
2208             }
2209 
2210             this.heavyweight = heavyweight;
2211             this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2212             addLightweightRequest(descendant, temporary, cause);
2213         }
2214         boolean addLightweightRequest(Component descendant,
2215                                       boolean temporary, CausedFocusEvent.Cause cause) {
2216             if (log.isLoggable(PlatformLogger.Level.FINE)) {
2217                 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2218                     log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2219                 }
2220                 if (descendant == null) {
2221                     log.fine("Assertion (descendant != null) failed");
2222                 }
2223             }
2224 
2225             Component lastDescendant = ((lightweightRequests.size() > 0)
2226                 ? lightweightRequests.getLast().component
2227                 : null);
2228 
2229             if (descendant != lastDescendant) {
2230                 // Not a duplicate request
2231                 lightweightRequests.add
2232                     (new LightweightFocusRequest(descendant, temporary, cause));
2233                 return true;
2234             } else {
2235                 return false;


2307         synchronized (heavyweightRequests) {
2308             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2309             if (hwFocusRequest == null &&
2310                 heavyweight == manager.getNativeFocusOwner() &&
2311                 allowSyncFocusRequests)
2312             {
2313 
2314                 if (descendant == currentFocusOwner) {
2315                     // Redundant request.
2316                     return true;
2317                 }
2318 
2319                 // 'heavyweight' owns the native focus and there are no pending
2320                 // requests. 'heavyweight' must be a Container and
2321                 // 'descendant' must not be the focus owner. Otherwise,
2322                 // we would never have gotten this far.
2323                 manager.enqueueKeyEvents(time, descendant);
2324 
2325                 hwFocusRequest =
2326                     new HeavyweightFocusRequest(heavyweight, descendant,
2327                                                 temporary, CausedFocusEvent.Cause.UNKNOWN);
2328                 heavyweightRequests.add(hwFocusRequest);
2329 
2330                 if (currentFocusOwner != null) {
2331                     currentFocusOwnerEvent =
2332                         new FocusEvent(currentFocusOwner,
2333                                        FocusEvent.FOCUS_LOST,
2334                                        temporary, descendant);
2335                 }
2336                 newFocusOwnerEvent =
2337                     new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2338                                    temporary, currentFocusOwner);
2339             }
2340         }
2341         boolean result = false;
2342         final boolean clearing = clearingCurrentLightweightRequests;
2343 
2344         Throwable caughtEx = null;
2345         try {
2346             clearingCurrentLightweightRequests = false;
2347             synchronized(Component.LOCK) {


2372     /**
2373      * Indicates whether the native implementation should proceed with a
2374      * pending, native focus request. Before changing the focus at the native
2375      * level, the AWT implementation should always call this function for
2376      * permission. This function will reject the request if a duplicate request
2377      * preceded it, or if the specified heavyweight Component already owns the
2378      * focus and no native focus changes are pending. Otherwise, the request
2379      * will be approved and the focus request list will be updated so that,
2380      * if necessary, the proper descendant will be focused when the
2381      * corresponding FOCUS_GAINED event on the heavyweight is received.
2382      *
2383      * An implementation must ensure that calls to this method and native
2384      * focus changes are atomic. If this is not guaranteed, then the ordering
2385      * of the focus request list may be incorrect, leading to errors in the
2386      * type-ahead mechanism. Typically this is accomplished by only calling
2387      * this function from the native event pumping thread, or by holding a
2388      * global, native lock during invocation.
2389      */
2390     static int shouldNativelyFocusHeavyweight
2391         (Component heavyweight, Component descendant, boolean temporary,
2392          boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
2393     {
2394         if (log.isLoggable(PlatformLogger.Level.FINE)) {
2395             if (heavyweight == null) {
2396                 log.fine("Assertion (heavyweight != null) failed");
2397             }
2398             if (time == 0) {
2399                 log.fine("Assertion (time != 0) failed");
2400             }
2401         }
2402 
2403         if (descendant == null) {
2404             // Focus transfers from a lightweight child back to the
2405             // heavyweight Container should be treated like lightweight
2406             // focus transfers.
2407             descendant = heavyweight;
2408         }
2409 
2410         KeyboardFocusManager manager =
2411             getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2412         KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();


2438                     // Redundant request.
2439                     if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2440                         focusLog.finest("1. SNFH_FAILURE for {0}",
2441                                         String.valueOf(descendant));
2442                     return SNFH_FAILURE;
2443                 }
2444 
2445                 // 'heavyweight' owns the native focus and there are no pending
2446                 // requests. 'heavyweight' must be a Container and
2447                 // 'descendant' must not be the focus owner. Otherwise,
2448                 // we would never have gotten this far.
2449                 manager.enqueueKeyEvents(time, descendant);
2450 
2451                 hwFocusRequest =
2452                     new HeavyweightFocusRequest(heavyweight, descendant,
2453                                                 temporary, cause);
2454                 heavyweightRequests.add(hwFocusRequest);
2455 
2456                 if (currentFocusOwner != null) {
2457                     FocusEvent currentFocusOwnerEvent =
2458                         new CausedFocusEvent(currentFocusOwner,
2459                                        FocusEvent.FOCUS_LOST,
2460                                        temporary, descendant, cause);
2461                     // Fix 5028014. Rolled out.
2462                     // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2463                     SunToolkit.postEvent(currentFocusOwner.appContext,
2464                                          currentFocusOwnerEvent);
2465                 }
2466                 FocusEvent newFocusOwnerEvent =
2467                     new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2468                                    temporary, currentFocusOwner, cause);
2469                 // Fix 5028014. Rolled out.
2470                 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2471                 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
2472 
2473                 if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2474                     focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
2475                 return SNFH_SUCCESS_HANDLED;
2476             } else if (hwFocusRequest != null &&
2477                        hwFocusRequest.heavyweight == heavyweight) {
2478                 // 'heavyweight' doesn't have the native focus right now, but
2479                 // if all pending requests were completed, it would. Add
2480                 // descendant to the heavyweight's list of pending
2481                 // lightweight focus transfers.
2482                 if (hwFocusRequest.addLightweightRequest(descendant,
2483                                                          temporary, cause)) {
2484                     manager.enqueueKeyEvents(time, descendant);
2485                 }
2486 
2487                 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {


2663                     /*
2664                      * WARNING: This is based on DKFM's logic solely!
2665                      *
2666                      * We allow to trigger restoreFocus() in the dispatching process
2667                      * only if we have the last request to dispatch. If the last request
2668                      * fails, focus will be restored to either the component of the last
2669                      * previously succeeded request, or to the focus owner that was
2670                      * before this clearing process.
2671                      */
2672                     if (!iter.hasNext()) {
2673                         disableRestoreFocus = false;
2674                     }
2675 
2676                     FocusEvent currentFocusOwnerEvent = null;
2677                     /*
2678                      * We're not dispatching FOCUS_LOST while the current focus owner is null.
2679                      * But regardless of whether it's null or not, we're clearing ALL the local
2680                      * lw requests.
2681                      */
2682                     if (currentFocusOwner != null) {
2683                         currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
2684                                        FocusEvent.FOCUS_LOST,
2685                                        lwFocusRequest.temporary,
2686                                        lwFocusRequest.component, lwFocusRequest.cause);
2687                     }
2688                     FocusEvent newFocusOwnerEvent =
2689                         new CausedFocusEvent(lwFocusRequest.component,
2690                                        FocusEvent.FOCUS_GAINED,
2691                                        lwFocusRequest.temporary,
2692                                        currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
2693                                        lwFocusRequest.cause);
2694 
2695                     if (currentFocusOwner != null) {
2696                         ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2697                         caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2698                     }
2699 
2700                     ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2701                     caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2702 
2703                     if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2704                         lastFocusOwner = lwFocusRequest.component;
2705                     }
2706                 }
2707             }
2708         } finally {
2709             clearingCurrentLightweightRequests = false;


2719     }
2720 
2721     static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2722         synchronized (heavyweightRequests) {
2723             // Any other case represents a failure condition which we did
2724             // not expect. We need to clearFocusRequestList() and patch up
2725             // the event as best as possible.
2726 
2727             if (removeFirstRequest()) {
2728                 return (FocusEvent)retargetFocusEvent(fe);
2729             }
2730 
2731             Component source = fe.getComponent();
2732             Component opposite = fe.getOppositeComponent();
2733             boolean temporary = false;
2734             if (fe.getID() == FocusEvent.FOCUS_LOST &&
2735                 (opposite == null || isTemporary(opposite, source)))
2736             {
2737                 temporary = true;
2738             }
2739             return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
2740                                         CausedFocusEvent.Cause.NATIVE_SYSTEM);
2741         }
2742     }
2743 
2744     static FocusEvent retargetFocusGained(FocusEvent fe) {
2745         assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2746 
2747         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2748             getGlobalFocusOwner();
2749         Component source = fe.getComponent();
2750         Component opposite = fe.getOppositeComponent();
2751         Component nativeSource = getHeavyweight(source);
2752 
2753         synchronized (heavyweightRequests) {
2754             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2755 
2756             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2757             {
2758                 return retargetUnexpectedFocusEvent(fe);
2759             }
2760 


2795                     newFocusOwner = newSource;
2796                 }
2797 
2798                 boolean temporary = (opposite == null ||
2799                                      isTemporary(newSource, opposite))
2800                         ? false
2801                         : lwFocusRequest.temporary;
2802 
2803                 if (hwFocusRequest.lightweightRequests.size() > 0) {
2804                     currentLightweightRequests =
2805                         hwFocusRequest.lightweightRequests;
2806                     EventQueue.invokeLater(new Runnable() {
2807                             public void run() {
2808                                 processCurrentLightweightRequests();
2809                             }
2810                         });
2811                 }
2812 
2813                 // 'opposite' will be fixed by
2814                 // DefaultKeyboardFocusManager.realOppositeComponent
2815                 return new CausedFocusEvent(newSource,
2816                                       FocusEvent.FOCUS_GAINED, temporary,
2817                                       opposite, lwFocusRequest.cause);
2818             }
2819 
2820             if (currentFocusOwner != null
2821                 && currentFocusOwner.getContainingWindow() == source
2822                 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2823             {
2824                 // Special case for FOCUS_GAINED in top-levels
2825                 // If it arrives as the result of activation we should skip it
2826                 // This event will not have appropriate request record and
2827                 // on arrival there will be already some focus owner set.
2828                 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
2829                                             null, CausedFocusEvent.Cause.ACTIVATION);
2830             }
2831 
2832             return retargetUnexpectedFocusEvent(fe);
2833         } // end synchronized(heavyweightRequests)
2834     }
2835 
2836     static FocusEvent retargetFocusLost(FocusEvent fe) {
2837         assert (fe.getID() == FocusEvent.FOCUS_LOST);
2838 
2839         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2840             getGlobalFocusOwner();
2841         Component opposite = fe.getOppositeComponent();
2842         Component nativeOpposite = getHeavyweight(opposite);
2843 
2844         synchronized (heavyweightRequests) {
2845             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2846 
2847             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2848             {
2849                 if (currentFocusOwner != null) {
2850                     // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2851                     heavyweightRequests.removeFirst();
2852                     return new CausedFocusEvent(currentFocusOwner,
2853                                                 FocusEvent.FOCUS_LOST, false, 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             {
2861                 // Focus leaving application
2862                 if (currentFocusOwner != null) {
2863                     return new CausedFocusEvent(currentFocusOwner,
2864                                                 FocusEvent.FOCUS_LOST,
2865                                                 true, null, CausedFocusEvent.Cause.ACTIVATION);
2866                 } else {
2867                     return fe;
2868                 }
2869             } else if (hwFocusRequest != null &&
2870                        (nativeOpposite == hwFocusRequest.heavyweight ||
2871                         nativeOpposite == null &&
2872                         opposite == hwFocusRequest.getFirstLightweightRequest().component))
2873             {
2874                 if (currentFocusOwner == null) {
2875                     return fe;
2876                 }
2877                 // Focus change as a result of a known call to requestFocus(),
2878                 // or click on a peer focusable heavyweight Component.
2879                 // If a focus transfer is made across top-levels, then the
2880                 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2881                 // event is always permanent. Otherwise, the stored temporary
2882                 // value is honored.
2883 
2884                 LightweightFocusRequest lwFocusRequest =
2885                     hwFocusRequest.lightweightRequests.getFirst();
2886 
2887                 boolean temporary = isTemporary(opposite, currentFocusOwner)
2888                     ? true
2889                     : lwFocusRequest.temporary;
2890 
2891                 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2892                                             temporary, lwFocusRequest.component, lwFocusRequest.cause);
2893             } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2894                 // If top-level changed there might be no focus request in a list
2895                 // But we know the opposite, we now it is temporary - dispatch the event.
2896                 if (!fe.isTemporary() && currentFocusOwner != null) {
2897                     // Create copy of the event with only difference in temporary parameter.
2898                     fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2899                                               true, opposite, 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(PlatformLogger.Level.FINER)) {
2915             if (event instanceof FocusEvent || event instanceof WindowEvent) {
2916                 focusLog.finer(">>> {0}", String.valueOf(event));
2917             }
2918             if (focusLog.isLoggable(PlatformLogger.Level.FINER) && event instanceof KeyEvent) {
2919                 focusLog.finer("    focus owner is {0}",




  40 
  41 import java.lang.ref.WeakReference;
  42 
  43 import java.lang.reflect.Field;
  44 
  45 import java.security.AccessController;
  46 import java.security.PrivilegedAction;
  47 
  48 import java.util.Collections;
  49 import java.util.HashSet;
  50 import java.util.Iterator;
  51 import java.util.LinkedList;
  52 import java.util.Set;
  53 import java.util.StringTokenizer;
  54 import java.util.WeakHashMap;
  55 
  56 import sun.util.logging.PlatformLogger;
  57 
  58 import sun.awt.AppContext;
  59 import sun.awt.SunToolkit;

  60 import sun.awt.KeyboardFocusManagerPeerProvider;
  61 import sun.awt.AWTAccessor;
  62 
  63 /**
  64  * The KeyboardFocusManager is responsible for managing the active and focused
  65  * Windows, and the current focus owner. The focus owner is defined as the
  66  * Component in an application that will typically receive all KeyEvents
  67  * generated by the user. The focused Window is the Window that is, or
  68  * contains, the focus owner. Only a Frame or a Dialog can be the active
  69  * Window. The native windowing system may denote the active Window or its
  70  * children with special decorations, such as a highlighted title bar. The
  71  * active Window is always either the focused Window, or the first Frame or
  72  * Dialog that is an owner of the focused Window.
  73  * <p>
  74  * The KeyboardFocusManager is both a centralized location for client code to
  75  * query for the focus owner and initiate focus changes, and an event
  76  * dispatcher for all FocusEvents, WindowEvents related to focus, and
  77  * KeyEvents.
  78  * <p>
  79  * Some browsers partition applets in different code bases into separate


 106 public abstract class KeyboardFocusManager
 107     implements KeyEventDispatcher, KeyEventPostProcessor
 108 {
 109 
 110     // Shared focus engine logger
 111     private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
 112 
 113     static {
 114         /* ensure that the necessary native libraries are loaded */
 115         Toolkit.loadLibraries();
 116         if (!GraphicsEnvironment.isHeadless()) {
 117             initIDs();
 118         }
 119         AWTAccessor.setKeyboardFocusManagerAccessor(
 120             new AWTAccessor.KeyboardFocusManagerAccessor() {
 121                 public int shouldNativelyFocusHeavyweight(Component heavyweight,
 122                                                    Component descendant,
 123                                                    boolean temporary,
 124                                                    boolean focusedWindowChangeAllowed,
 125                                                    long time,
 126                                                    FocusEvent.Cause cause)
 127                 {
 128                     return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
 129                         heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
 130                 }
 131                 public boolean processSynchronousLightweightTransfer(Component heavyweight,
 132                                                               Component descendant,
 133                                                               boolean temporary,
 134                                                               boolean focusedWindowChangeAllowed,
 135                                                               long time)
 136                 {
 137                     return KeyboardFocusManager.processSynchronousLightweightTransfer(
 138                         heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
 139                 }
 140                 public void removeLastFocusRequest(Component heavyweight) {
 141                     KeyboardFocusManager.removeLastFocusRequest(heavyweight);
 142                 }
 143                 public void setMostRecentFocusOwner(Window window, Component component) {
 144                     KeyboardFocusManager.setMostRecentFocusOwner(window, component);
 145                 }
 146                 public KeyboardFocusManager getCurrentKeyboardFocusManager(AppContext ctx) {


2156             downFocusCycle((Container)focusOwner);
2157         }
2158     }
2159 
2160     /**
2161      * Dumps the list of focus requests to stderr
2162      */
2163     void dumpRequests() {
2164         System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2165         synchronized (heavyweightRequests) {
2166             for (HeavyweightFocusRequest req : heavyweightRequests) {
2167                 System.err.println(">>> Req: " + req);
2168             }
2169         }
2170         System.err.println("");
2171     }
2172 
2173     private static final class LightweightFocusRequest {
2174         final Component component;
2175         final boolean temporary;
2176         final FocusEvent.Cause cause;
2177 
2178         LightweightFocusRequest(Component component, boolean temporary, FocusEvent.Cause cause) {
2179             this.component = component;
2180             this.temporary = temporary;
2181             this.cause = cause;
2182         }
2183         public String toString() {
2184             return "LightweightFocusRequest[component=" + component +
2185                 ",temporary=" + temporary + ", cause=" + cause + "]";
2186         }
2187     }
2188 
2189     private static final class HeavyweightFocusRequest {
2190         final Component heavyweight;
2191         final LinkedList<LightweightFocusRequest> lightweightRequests;
2192 
2193         static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2194             new HeavyweightFocusRequest();
2195 
2196         private HeavyweightFocusRequest() {
2197             heavyweight = null;
2198             lightweightRequests = null;
2199         }
2200 
2201         HeavyweightFocusRequest(Component heavyweight, Component descendant,
2202                                 boolean temporary, FocusEvent.Cause cause) {
2203             if (log.isLoggable(PlatformLogger.Level.FINE)) {
2204                 if (heavyweight == null) {
2205                     log.fine("Assertion (heavyweight != null) failed");
2206                 }
2207             }
2208 
2209             this.heavyweight = heavyweight;
2210             this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2211             addLightweightRequest(descendant, temporary, cause);
2212         }
2213         boolean addLightweightRequest(Component descendant,
2214                                       boolean temporary, FocusEvent.Cause cause) {
2215             if (log.isLoggable(PlatformLogger.Level.FINE)) {
2216                 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2217                     log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2218                 }
2219                 if (descendant == null) {
2220                     log.fine("Assertion (descendant != null) failed");
2221                 }
2222             }
2223 
2224             Component lastDescendant = ((lightweightRequests.size() > 0)
2225                 ? lightweightRequests.getLast().component
2226                 : null);
2227 
2228             if (descendant != lastDescendant) {
2229                 // Not a duplicate request
2230                 lightweightRequests.add
2231                     (new LightweightFocusRequest(descendant, temporary, cause));
2232                 return true;
2233             } else {
2234                 return false;


2306         synchronized (heavyweightRequests) {
2307             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2308             if (hwFocusRequest == null &&
2309                 heavyweight == manager.getNativeFocusOwner() &&
2310                 allowSyncFocusRequests)
2311             {
2312 
2313                 if (descendant == currentFocusOwner) {
2314                     // Redundant request.
2315                     return true;
2316                 }
2317 
2318                 // 'heavyweight' owns the native focus and there are no pending
2319                 // requests. 'heavyweight' must be a Container and
2320                 // 'descendant' must not be the focus owner. Otherwise,
2321                 // we would never have gotten this far.
2322                 manager.enqueueKeyEvents(time, descendant);
2323 
2324                 hwFocusRequest =
2325                     new HeavyweightFocusRequest(heavyweight, descendant,
2326                                                 temporary, FocusEvent.Cause.UNKNOWN);
2327                 heavyweightRequests.add(hwFocusRequest);
2328 
2329                 if (currentFocusOwner != null) {
2330                     currentFocusOwnerEvent =
2331                         new FocusEvent(currentFocusOwner,
2332                                        FocusEvent.FOCUS_LOST,
2333                                        temporary, descendant);
2334                 }
2335                 newFocusOwnerEvent =
2336                     new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2337                                    temporary, currentFocusOwner);
2338             }
2339         }
2340         boolean result = false;
2341         final boolean clearing = clearingCurrentLightweightRequests;
2342 
2343         Throwable caughtEx = null;
2344         try {
2345             clearingCurrentLightweightRequests = false;
2346             synchronized(Component.LOCK) {


2371     /**
2372      * Indicates whether the native implementation should proceed with a
2373      * pending, native focus request. Before changing the focus at the native
2374      * level, the AWT implementation should always call this function for
2375      * permission. This function will reject the request if a duplicate request
2376      * preceded it, or if the specified heavyweight Component already owns the
2377      * focus and no native focus changes are pending. Otherwise, the request
2378      * will be approved and the focus request list will be updated so that,
2379      * if necessary, the proper descendant will be focused when the
2380      * corresponding FOCUS_GAINED event on the heavyweight is received.
2381      *
2382      * An implementation must ensure that calls to this method and native
2383      * focus changes are atomic. If this is not guaranteed, then the ordering
2384      * of the focus request list may be incorrect, leading to errors in the
2385      * type-ahead mechanism. Typically this is accomplished by only calling
2386      * this function from the native event pumping thread, or by holding a
2387      * global, native lock during invocation.
2388      */
2389     static int shouldNativelyFocusHeavyweight
2390         (Component heavyweight, Component descendant, boolean temporary,
2391          boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)
2392     {
2393         if (log.isLoggable(PlatformLogger.Level.FINE)) {
2394             if (heavyweight == null) {
2395                 log.fine("Assertion (heavyweight != null) failed");
2396             }
2397             if (time == 0) {
2398                 log.fine("Assertion (time != 0) failed");
2399             }
2400         }
2401 
2402         if (descendant == null) {
2403             // Focus transfers from a lightweight child back to the
2404             // heavyweight Container should be treated like lightweight
2405             // focus transfers.
2406             descendant = heavyweight;
2407         }
2408 
2409         KeyboardFocusManager manager =
2410             getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2411         KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();


2437                     // Redundant request.
2438                     if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2439                         focusLog.finest("1. SNFH_FAILURE for {0}",
2440                                         String.valueOf(descendant));
2441                     return SNFH_FAILURE;
2442                 }
2443 
2444                 // 'heavyweight' owns the native focus and there are no pending
2445                 // requests. 'heavyweight' must be a Container and
2446                 // 'descendant' must not be the focus owner. Otherwise,
2447                 // we would never have gotten this far.
2448                 manager.enqueueKeyEvents(time, descendant);
2449 
2450                 hwFocusRequest =
2451                     new HeavyweightFocusRequest(heavyweight, descendant,
2452                                                 temporary, cause);
2453                 heavyweightRequests.add(hwFocusRequest);
2454 
2455                 if (currentFocusOwner != null) {
2456                     FocusEvent currentFocusOwnerEvent =
2457                         new FocusEvent(currentFocusOwner,
2458                                        FocusEvent.FOCUS_LOST,
2459                                        temporary, descendant, cause);
2460                     // Fix 5028014. Rolled out.
2461                     // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2462                     SunToolkit.postEvent(currentFocusOwner.appContext,
2463                                          currentFocusOwnerEvent);
2464                 }
2465                 FocusEvent newFocusOwnerEvent =
2466                     new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2467                                    temporary, currentFocusOwner, cause);
2468                 // Fix 5028014. Rolled out.
2469                 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2470                 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
2471 
2472                 if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2473                     focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
2474                 return SNFH_SUCCESS_HANDLED;
2475             } else if (hwFocusRequest != null &&
2476                        hwFocusRequest.heavyweight == heavyweight) {
2477                 // 'heavyweight' doesn't have the native focus right now, but
2478                 // if all pending requests were completed, it would. Add
2479                 // descendant to the heavyweight's list of pending
2480                 // lightweight focus transfers.
2481                 if (hwFocusRequest.addLightweightRequest(descendant,
2482                                                          temporary, cause)) {
2483                     manager.enqueueKeyEvents(time, descendant);
2484                 }
2485 
2486                 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {


2662                     /*
2663                      * WARNING: This is based on DKFM's logic solely!
2664                      *
2665                      * We allow to trigger restoreFocus() in the dispatching process
2666                      * only if we have the last request to dispatch. If the last request
2667                      * fails, focus will be restored to either the component of the last
2668                      * previously succeeded request, or to the focus owner that was
2669                      * before this clearing process.
2670                      */
2671                     if (!iter.hasNext()) {
2672                         disableRestoreFocus = false;
2673                     }
2674 
2675                     FocusEvent currentFocusOwnerEvent = null;
2676                     /*
2677                      * We're not dispatching FOCUS_LOST while the current focus owner is null.
2678                      * But regardless of whether it's null or not, we're clearing ALL the local
2679                      * lw requests.
2680                      */
2681                     if (currentFocusOwner != null) {
2682                         currentFocusOwnerEvent = new FocusEvent(currentFocusOwner,
2683                                        FocusEvent.FOCUS_LOST,
2684                                        lwFocusRequest.temporary,
2685                                        lwFocusRequest.component, lwFocusRequest.cause);
2686                     }
2687                     FocusEvent newFocusOwnerEvent =
2688                         new FocusEvent(lwFocusRequest.component,
2689                                        FocusEvent.FOCUS_GAINED,
2690                                        lwFocusRequest.temporary,
2691                                        currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
2692                                        lwFocusRequest.cause);
2693 
2694                     if (currentFocusOwner != null) {
2695                         ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2696                         caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2697                     }
2698 
2699                     ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2700                     caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2701 
2702                     if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2703                         lastFocusOwner = lwFocusRequest.component;
2704                     }
2705                 }
2706             }
2707         } finally {
2708             clearingCurrentLightweightRequests = false;


2718     }
2719 
2720     static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2721         synchronized (heavyweightRequests) {
2722             // Any other case represents a failure condition which we did
2723             // not expect. We need to clearFocusRequestList() and patch up
2724             // the event as best as possible.
2725 
2726             if (removeFirstRequest()) {
2727                 return (FocusEvent)retargetFocusEvent(fe);
2728             }
2729 
2730             Component source = fe.getComponent();
2731             Component opposite = fe.getOppositeComponent();
2732             boolean temporary = false;
2733             if (fe.getID() == FocusEvent.FOCUS_LOST &&
2734                 (opposite == null || isTemporary(opposite, source)))
2735             {
2736                 temporary = true;
2737             }
2738             return new FocusEvent(source, fe.getID(), temporary, opposite,
2739                                         FocusEvent.Cause.UNEXPECTED);
2740         }
2741     }
2742 
2743     static FocusEvent retargetFocusGained(FocusEvent fe) {
2744         assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2745 
2746         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2747             getGlobalFocusOwner();
2748         Component source = fe.getComponent();
2749         Component opposite = fe.getOppositeComponent();
2750         Component nativeSource = getHeavyweight(source);
2751 
2752         synchronized (heavyweightRequests) {
2753             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2754 
2755             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2756             {
2757                 return retargetUnexpectedFocusEvent(fe);
2758             }
2759 


2794                     newFocusOwner = newSource;
2795                 }
2796 
2797                 boolean temporary = (opposite == null ||
2798                                      isTemporary(newSource, opposite))
2799                         ? false
2800                         : lwFocusRequest.temporary;
2801 
2802                 if (hwFocusRequest.lightweightRequests.size() > 0) {
2803                     currentLightweightRequests =
2804                         hwFocusRequest.lightweightRequests;
2805                     EventQueue.invokeLater(new Runnable() {
2806                             public void run() {
2807                                 processCurrentLightweightRequests();
2808                             }
2809                         });
2810                 }
2811 
2812                 // 'opposite' will be fixed by
2813                 // DefaultKeyboardFocusManager.realOppositeComponent
2814                 return new FocusEvent(newSource,
2815                                       FocusEvent.FOCUS_GAINED, temporary,
2816                                       opposite, lwFocusRequest.cause);
2817             }
2818 
2819             if (currentFocusOwner != null
2820                 && currentFocusOwner.getContainingWindow() == source
2821                 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2822             {
2823                 // Special case for FOCUS_GAINED in top-levels
2824                 // If it arrives as the result of activation we should skip it
2825                 // This event will not have appropriate request record and
2826                 // on arrival there will be already some focus owner set.
2827                 return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
2828                                             null, FocusEvent.Cause.ACTIVATION);
2829             }
2830 
2831             return retargetUnexpectedFocusEvent(fe);
2832         } // end synchronized(heavyweightRequests)
2833     }
2834 
2835     static FocusEvent retargetFocusLost(FocusEvent fe) {
2836         assert (fe.getID() == FocusEvent.FOCUS_LOST);
2837 
2838         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2839             getGlobalFocusOwner();
2840         Component opposite = fe.getOppositeComponent();
2841         Component nativeOpposite = getHeavyweight(opposite);
2842 
2843         synchronized (heavyweightRequests) {
2844             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2845 
2846             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2847             {
2848                 if (currentFocusOwner != null) {
2849                     // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2850                     heavyweightRequests.removeFirst();
2851                     return new FocusEvent(currentFocusOwner,
2852                                                 FocusEvent.FOCUS_LOST, false, null,
2853                                                 FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2854                 }
2855 
2856                 // Otherwise, fall through to failure case below
2857 
2858             } else if (opposite == null)
2859             {
2860                 // Focus leaving application
2861                 if (currentFocusOwner != null) {
2862                     return new FocusEvent(currentFocusOwner,
2863                                                 FocusEvent.FOCUS_LOST,
2864                                                 true, null, FocusEvent.Cause.ACTIVATION);
2865                 } else {
2866                     return fe;
2867                 }
2868             } else if (hwFocusRequest != null &&
2869                        (nativeOpposite == hwFocusRequest.heavyweight ||
2870                         nativeOpposite == null &&
2871                         opposite == hwFocusRequest.getFirstLightweightRequest().component))
2872             {
2873                 if (currentFocusOwner == null) {
2874                     return fe;
2875                 }
2876                 // Focus change as a result of a known call to requestFocus(),
2877                 // or click on a peer focusable heavyweight Component.
2878                 // If a focus transfer is made across top-levels, then the
2879                 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2880                 // event is always permanent. Otherwise, the stored temporary
2881                 // value is honored.
2882 
2883                 LightweightFocusRequest lwFocusRequest =
2884                     hwFocusRequest.lightweightRequests.getFirst();
2885 
2886                 boolean temporary = isTemporary(opposite, currentFocusOwner)
2887                     ? true
2888                     : lwFocusRequest.temporary;
2889 
2890                 return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2891                                             temporary, 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 FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2898                                               true, opposite, FocusEvent.Cause.ACTIVATION);
2899                 }
2900                 return fe;
2901             }
2902 
2903             return retargetUnexpectedFocusEvent(fe);
2904         }  // end synchronized(heavyweightRequests)
2905     }
2906 
2907     static AWTEvent retargetFocusEvent(AWTEvent event) {
2908         if (clearingCurrentLightweightRequests) {
2909             return event;
2910         }
2911 
2912         KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2913         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
2914             if (event instanceof FocusEvent || event instanceof WindowEvent) {
2915                 focusLog.finer(">>> {0}", String.valueOf(event));
2916             }
2917             if (focusLog.isLoggable(PlatformLogger.Level.FINER) && event instanceof KeyEvent) {
2918                 focusLog.finer("    focus owner is {0}",


< prev index next >