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}",
|