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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


< prev index next >