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