< 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) {


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


2293         synchronized (heavyweightRequests) {
2294             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2295             if (hwFocusRequest == null &&
2296                 heavyweight == manager.getNativeFocusOwner() &&
2297                 allowSyncFocusRequests)
2298             {
2299 
2300                 if (descendant == currentFocusOwner) {
2301                     // Redundant request.
2302                     return true;
2303                 }
2304 
2305                 // 'heavyweight' owns the native focus and there are no pending
2306                 // requests. 'heavyweight' must be a Container and
2307                 // 'descendant' must not be the focus owner. Otherwise,
2308                 // we would never have gotten this far.
2309                 manager.enqueueKeyEvents(time, descendant);
2310 
2311                 hwFocusRequest =
2312                     new HeavyweightFocusRequest(heavyweight, descendant,
2313                                                 temporary, CausedFocusEvent.Cause.UNKNOWN);
2314                 heavyweightRequests.add(hwFocusRequest);
2315 
2316                 if (currentFocusOwner != null) {
2317                     currentFocusOwnerEvent =
2318                         new FocusEvent(currentFocusOwner,
2319                                        FocusEvent.FOCUS_LOST,
2320                                        temporary, descendant);
2321                 }
2322                 newFocusOwnerEvent =
2323                     new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2324                                    temporary, currentFocusOwner);
2325             }
2326         }
2327         boolean result = false;
2328         final boolean clearing = clearingCurrentLightweightRequests;
2329 
2330         Throwable caughtEx = null;
2331         try {
2332             clearingCurrentLightweightRequests = false;
2333             synchronized(Component.LOCK) {


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


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


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


2705     }
2706 
2707     static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2708         synchronized (heavyweightRequests) {
2709             // Any other case represents a failure condition which we did
2710             // not expect. We need to clearFocusRequestList() and patch up
2711             // the event as best as possible.
2712 
2713             if (removeFirstRequest()) {
2714                 return (FocusEvent)retargetFocusEvent(fe);
2715             }
2716 
2717             Component source = fe.getComponent();
2718             Component opposite = fe.getOppositeComponent();
2719             boolean temporary = false;
2720             if (fe.getID() == FocusEvent.FOCUS_LOST &&
2721                 (opposite == null || isTemporary(opposite, source)))
2722             {
2723                 temporary = true;
2724             }
2725             return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
2726                                         CausedFocusEvent.Cause.NATIVE_SYSTEM);
2727         }
2728     }
2729 
2730     static FocusEvent retargetFocusGained(FocusEvent fe) {
2731         assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2732 
2733         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2734             getGlobalFocusOwner();
2735         Component source = fe.getComponent();
2736         Component opposite = fe.getOppositeComponent();
2737         Component nativeSource = getHeavyweight(source);
2738 
2739         synchronized (heavyweightRequests) {
2740             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2741 
2742             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2743             {
2744                 return retargetUnexpectedFocusEvent(fe);
2745             }
2746 


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


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


2292         synchronized (heavyweightRequests) {
2293             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2294             if (hwFocusRequest == null &&
2295                 heavyweight == manager.getNativeFocusOwner() &&
2296                 allowSyncFocusRequests)
2297             {
2298 
2299                 if (descendant == currentFocusOwner) {
2300                     // Redundant request.
2301                     return true;
2302                 }
2303 
2304                 // 'heavyweight' owns the native focus and there are no pending
2305                 // requests. 'heavyweight' must be a Container and
2306                 // 'descendant' must not be the focus owner. Otherwise,
2307                 // we would never have gotten this far.
2308                 manager.enqueueKeyEvents(time, descendant);
2309 
2310                 hwFocusRequest =
2311                     new HeavyweightFocusRequest(heavyweight, descendant,
2312                                                 temporary, FocusEvent.Cause.UNKNOWN);
2313                 heavyweightRequests.add(hwFocusRequest);
2314 
2315                 if (currentFocusOwner != null) {
2316                     currentFocusOwnerEvent =
2317                         new FocusEvent(currentFocusOwner,
2318                                        FocusEvent.FOCUS_LOST,
2319                                        temporary, descendant);
2320                 }
2321                 newFocusOwnerEvent =
2322                     new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2323                                    temporary, currentFocusOwner);
2324             }
2325         }
2326         boolean result = false;
2327         final boolean clearing = clearingCurrentLightweightRequests;
2328 
2329         Throwable caughtEx = null;
2330         try {
2331             clearingCurrentLightweightRequests = false;
2332             synchronized(Component.LOCK) {


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


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


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


2704     }
2705 
2706     static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2707         synchronized (heavyweightRequests) {
2708             // Any other case represents a failure condition which we did
2709             // not expect. We need to clearFocusRequestList() and patch up
2710             // the event as best as possible.
2711 
2712             if (removeFirstRequest()) {
2713                 return (FocusEvent)retargetFocusEvent(fe);
2714             }
2715 
2716             Component source = fe.getComponent();
2717             Component opposite = fe.getOppositeComponent();
2718             boolean temporary = false;
2719             if (fe.getID() == FocusEvent.FOCUS_LOST &&
2720                 (opposite == null || isTemporary(opposite, source)))
2721             {
2722                 temporary = true;
2723             }
2724             return new FocusEvent(source, fe.getID(), temporary, opposite,
2725                                         FocusEvent.Cause.UNEXPECTED);
2726         }
2727     }
2728 
2729     static FocusEvent retargetFocusGained(FocusEvent fe) {
2730         assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2731 
2732         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2733             getGlobalFocusOwner();
2734         Component source = fe.getComponent();
2735         Component opposite = fe.getOppositeComponent();
2736         Component nativeSource = getHeavyweight(source);
2737 
2738         synchronized (heavyweightRequests) {
2739             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2740 
2741             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2742             {
2743                 return retargetUnexpectedFocusEvent(fe);
2744             }
2745 


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


< prev index next >