40
41 import java.lang.ref.WeakReference;
42
43 import java.lang.reflect.Field;
44
45 import java.security.AccessController;
46 import java.security.PrivilegedAction;
47
48 import java.util.Collections;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.LinkedList;
52 import java.util.Set;
53 import java.util.StringTokenizer;
54 import java.util.WeakHashMap;
55
56 import sun.util.logging.PlatformLogger;
57
58 import sun.awt.AppContext;
59 import sun.awt.SunToolkit;
60 import sun.awt.CausedFocusEvent;
61 import sun.awt.KeyboardFocusManagerPeerProvider;
62 import sun.awt.AWTAccessor;
63
64 /**
65 * The KeyboardFocusManager is responsible for managing the active and focused
66 * Windows, and the current focus owner. The focus owner is defined as the
67 * Component in an application that will typically receive all KeyEvents
68 * generated by the user. The focused Window is the Window that is, or
69 * contains, the focus owner. Only a Frame or a Dialog can be the active
70 * Window. The native windowing system may denote the active Window or its
71 * children with special decorations, such as a highlighted title bar. The
72 * active Window is always either the focused Window, or the first Frame or
73 * Dialog that is an owner of the focused Window.
74 * <p>
75 * The KeyboardFocusManager is both a centralized location for client code to
76 * query for the focus owner and initiate focus changes, and an event
77 * dispatcher for all FocusEvents, WindowEvents related to focus, and
78 * KeyEvents.
79 * <p>
80 * Some browsers partition applets in different code bases into separate
107 public abstract class KeyboardFocusManager
108 implements KeyEventDispatcher, KeyEventPostProcessor
109 {
110
111 // Shared focus engine logger
112 private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
113
114 static {
115 /* ensure that the necessary native libraries are loaded */
116 Toolkit.loadLibraries();
117 if (!GraphicsEnvironment.isHeadless()) {
118 initIDs();
119 }
120 AWTAccessor.setKeyboardFocusManagerAccessor(
121 new AWTAccessor.KeyboardFocusManagerAccessor() {
122 public int shouldNativelyFocusHeavyweight(Component heavyweight,
123 Component descendant,
124 boolean temporary,
125 boolean focusedWindowChangeAllowed,
126 long time,
127 CausedFocusEvent.Cause cause)
128 {
129 return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
130 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
131 }
132 public boolean processSynchronousLightweightTransfer(Component heavyweight,
133 Component descendant,
134 boolean temporary,
135 boolean focusedWindowChangeAllowed,
136 long time)
137 {
138 return KeyboardFocusManager.processSynchronousLightweightTransfer(
139 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
140 }
141 public void removeLastFocusRequest(Component heavyweight) {
142 KeyboardFocusManager.removeLastFocusRequest(heavyweight);
143 }
144 public void setMostRecentFocusOwner(Window window, Component component) {
145 KeyboardFocusManager.setMostRecentFocusOwner(window, component);
146 }
147 public KeyboardFocusManager getCurrentKeyboardFocusManager(AppContext ctx) {
2157 downFocusCycle((Container)focusOwner);
2158 }
2159 }
2160
2161 /**
2162 * Dumps the list of focus requests to stderr
2163 */
2164 void dumpRequests() {
2165 System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2166 synchronized (heavyweightRequests) {
2167 for (HeavyweightFocusRequest req : heavyweightRequests) {
2168 System.err.println(">>> Req: " + req);
2169 }
2170 }
2171 System.err.println("");
2172 }
2173
2174 private static final class LightweightFocusRequest {
2175 final Component component;
2176 final boolean temporary;
2177 final CausedFocusEvent.Cause cause;
2178
2179 LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
2180 this.component = component;
2181 this.temporary = temporary;
2182 this.cause = cause;
2183 }
2184 public String toString() {
2185 return "LightweightFocusRequest[component=" + component +
2186 ",temporary=" + temporary + ", cause=" + cause + "]";
2187 }
2188 }
2189
2190 private static final class HeavyweightFocusRequest {
2191 final Component heavyweight;
2192 final LinkedList<LightweightFocusRequest> lightweightRequests;
2193
2194 static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2195 new HeavyweightFocusRequest();
2196
2197 private HeavyweightFocusRequest() {
2198 heavyweight = null;
2199 lightweightRequests = null;
2200 }
2201
2202 HeavyweightFocusRequest(Component heavyweight, Component descendant,
2203 boolean temporary, CausedFocusEvent.Cause cause) {
2204 if (log.isLoggable(PlatformLogger.Level.FINE)) {
2205 if (heavyweight == null) {
2206 log.fine("Assertion (heavyweight != null) failed");
2207 }
2208 }
2209
2210 this.heavyweight = heavyweight;
2211 this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2212 addLightweightRequest(descendant, temporary, cause);
2213 }
2214 boolean addLightweightRequest(Component descendant,
2215 boolean temporary, CausedFocusEvent.Cause cause) {
2216 if (log.isLoggable(PlatformLogger.Level.FINE)) {
2217 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2218 log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2219 }
2220 if (descendant == null) {
2221 log.fine("Assertion (descendant != null) failed");
2222 }
2223 }
2224
2225 Component lastDescendant = ((lightweightRequests.size() > 0)
2226 ? lightweightRequests.getLast().component
2227 : null);
2228
2229 if (descendant != lastDescendant) {
2230 // Not a duplicate request
2231 lightweightRequests.add
2232 (new LightweightFocusRequest(descendant, temporary, cause));
2233 return true;
2234 } else {
2235 return false;
2307 synchronized (heavyweightRequests) {
2308 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2309 if (hwFocusRequest == null &&
2310 heavyweight == manager.getNativeFocusOwner() &&
2311 allowSyncFocusRequests)
2312 {
2313
2314 if (descendant == currentFocusOwner) {
2315 // Redundant request.
2316 return true;
2317 }
2318
2319 // 'heavyweight' owns the native focus and there are no pending
2320 // requests. 'heavyweight' must be a Container and
2321 // 'descendant' must not be the focus owner. Otherwise,
2322 // we would never have gotten this far.
2323 manager.enqueueKeyEvents(time, descendant);
2324
2325 hwFocusRequest =
2326 new HeavyweightFocusRequest(heavyweight, descendant,
2327 temporary, CausedFocusEvent.Cause.UNKNOWN);
2328 heavyweightRequests.add(hwFocusRequest);
2329
2330 if (currentFocusOwner != null) {
2331 currentFocusOwnerEvent =
2332 new FocusEvent(currentFocusOwner,
2333 FocusEvent.FOCUS_LOST,
2334 temporary, descendant);
2335 }
2336 newFocusOwnerEvent =
2337 new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2338 temporary, currentFocusOwner);
2339 }
2340 }
2341 boolean result = false;
2342 final boolean clearing = clearingCurrentLightweightRequests;
2343
2344 Throwable caughtEx = null;
2345 try {
2346 clearingCurrentLightweightRequests = false;
2347 synchronized(Component.LOCK) {
2372 /**
2373 * Indicates whether the native implementation should proceed with a
2374 * pending, native focus request. Before changing the focus at the native
2375 * level, the AWT implementation should always call this function for
2376 * permission. This function will reject the request if a duplicate request
2377 * preceded it, or if the specified heavyweight Component already owns the
2378 * focus and no native focus changes are pending. Otherwise, the request
2379 * will be approved and the focus request list will be updated so that,
2380 * if necessary, the proper descendant will be focused when the
2381 * corresponding FOCUS_GAINED event on the heavyweight is received.
2382 *
2383 * An implementation must ensure that calls to this method and native
2384 * focus changes are atomic. If this is not guaranteed, then the ordering
2385 * of the focus request list may be incorrect, leading to errors in the
2386 * type-ahead mechanism. Typically this is accomplished by only calling
2387 * this function from the native event pumping thread, or by holding a
2388 * global, native lock during invocation.
2389 */
2390 static int shouldNativelyFocusHeavyweight
2391 (Component heavyweight, Component descendant, boolean temporary,
2392 boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
2393 {
2394 if (log.isLoggable(PlatformLogger.Level.FINE)) {
2395 if (heavyweight == null) {
2396 log.fine("Assertion (heavyweight != null) failed");
2397 }
2398 if (time == 0) {
2399 log.fine("Assertion (time != 0) failed");
2400 }
2401 }
2402
2403 if (descendant == null) {
2404 // Focus transfers from a lightweight child back to the
2405 // heavyweight Container should be treated like lightweight
2406 // focus transfers.
2407 descendant = heavyweight;
2408 }
2409
2410 KeyboardFocusManager manager =
2411 getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2412 KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
2438 // Redundant request.
2439 if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2440 focusLog.finest("1. SNFH_FAILURE for {0}",
2441 String.valueOf(descendant));
2442 return SNFH_FAILURE;
2443 }
2444
2445 // 'heavyweight' owns the native focus and there are no pending
2446 // requests. 'heavyweight' must be a Container and
2447 // 'descendant' must not be the focus owner. Otherwise,
2448 // we would never have gotten this far.
2449 manager.enqueueKeyEvents(time, descendant);
2450
2451 hwFocusRequest =
2452 new HeavyweightFocusRequest(heavyweight, descendant,
2453 temporary, cause);
2454 heavyweightRequests.add(hwFocusRequest);
2455
2456 if (currentFocusOwner != null) {
2457 FocusEvent currentFocusOwnerEvent =
2458 new CausedFocusEvent(currentFocusOwner,
2459 FocusEvent.FOCUS_LOST,
2460 temporary, descendant, cause);
2461 // Fix 5028014. Rolled out.
2462 // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2463 SunToolkit.postEvent(currentFocusOwner.appContext,
2464 currentFocusOwnerEvent);
2465 }
2466 FocusEvent newFocusOwnerEvent =
2467 new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2468 temporary, currentFocusOwner, cause);
2469 // Fix 5028014. Rolled out.
2470 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2471 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
2472
2473 if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2474 focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
2475 return SNFH_SUCCESS_HANDLED;
2476 } else if (hwFocusRequest != null &&
2477 hwFocusRequest.heavyweight == heavyweight) {
2478 // 'heavyweight' doesn't have the native focus right now, but
2479 // if all pending requests were completed, it would. Add
2480 // descendant to the heavyweight's list of pending
2481 // lightweight focus transfers.
2482 if (hwFocusRequest.addLightweightRequest(descendant,
2483 temporary, cause)) {
2484 manager.enqueueKeyEvents(time, descendant);
2485 }
2486
2487 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
2663 /*
2664 * WARNING: This is based on DKFM's logic solely!
2665 *
2666 * We allow to trigger restoreFocus() in the dispatching process
2667 * only if we have the last request to dispatch. If the last request
2668 * fails, focus will be restored to either the component of the last
2669 * previously succeeded request, or to the focus owner that was
2670 * before this clearing process.
2671 */
2672 if (!iter.hasNext()) {
2673 disableRestoreFocus = false;
2674 }
2675
2676 FocusEvent currentFocusOwnerEvent = null;
2677 /*
2678 * We're not dispatching FOCUS_LOST while the current focus owner is null.
2679 * But regardless of whether it's null or not, we're clearing ALL the local
2680 * lw requests.
2681 */
2682 if (currentFocusOwner != null) {
2683 currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
2684 FocusEvent.FOCUS_LOST,
2685 lwFocusRequest.temporary,
2686 lwFocusRequest.component, lwFocusRequest.cause);
2687 }
2688 FocusEvent newFocusOwnerEvent =
2689 new CausedFocusEvent(lwFocusRequest.component,
2690 FocusEvent.FOCUS_GAINED,
2691 lwFocusRequest.temporary,
2692 currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
2693 lwFocusRequest.cause);
2694
2695 if (currentFocusOwner != null) {
2696 ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2697 caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2698 }
2699
2700 ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2701 caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2702
2703 if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2704 lastFocusOwner = lwFocusRequest.component;
2705 }
2706 }
2707 }
2708 } finally {
2709 clearingCurrentLightweightRequests = false;
2719 }
2720
2721 static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2722 synchronized (heavyweightRequests) {
2723 // Any other case represents a failure condition which we did
2724 // not expect. We need to clearFocusRequestList() and patch up
2725 // the event as best as possible.
2726
2727 if (removeFirstRequest()) {
2728 return (FocusEvent)retargetFocusEvent(fe);
2729 }
2730
2731 Component source = fe.getComponent();
2732 Component opposite = fe.getOppositeComponent();
2733 boolean temporary = false;
2734 if (fe.getID() == FocusEvent.FOCUS_LOST &&
2735 (opposite == null || isTemporary(opposite, source)))
2736 {
2737 temporary = true;
2738 }
2739 return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
2740 CausedFocusEvent.Cause.NATIVE_SYSTEM);
2741 }
2742 }
2743
2744 static FocusEvent retargetFocusGained(FocusEvent fe) {
2745 assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2746
2747 Component currentFocusOwner = getCurrentKeyboardFocusManager().
2748 getGlobalFocusOwner();
2749 Component source = fe.getComponent();
2750 Component opposite = fe.getOppositeComponent();
2751 Component nativeSource = getHeavyweight(source);
2752
2753 synchronized (heavyweightRequests) {
2754 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2755
2756 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2757 {
2758 return retargetUnexpectedFocusEvent(fe);
2759 }
2760
2795 newFocusOwner = newSource;
2796 }
2797
2798 boolean temporary = (opposite == null ||
2799 isTemporary(newSource, opposite))
2800 ? false
2801 : lwFocusRequest.temporary;
2802
2803 if (hwFocusRequest.lightweightRequests.size() > 0) {
2804 currentLightweightRequests =
2805 hwFocusRequest.lightweightRequests;
2806 EventQueue.invokeLater(new Runnable() {
2807 public void run() {
2808 processCurrentLightweightRequests();
2809 }
2810 });
2811 }
2812
2813 // 'opposite' will be fixed by
2814 // DefaultKeyboardFocusManager.realOppositeComponent
2815 return new CausedFocusEvent(newSource,
2816 FocusEvent.FOCUS_GAINED, temporary,
2817 opposite, lwFocusRequest.cause);
2818 }
2819
2820 if (currentFocusOwner != null
2821 && currentFocusOwner.getContainingWindow() == source
2822 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2823 {
2824 // Special case for FOCUS_GAINED in top-levels
2825 // If it arrives as the result of activation we should skip it
2826 // This event will not have appropriate request record and
2827 // on arrival there will be already some focus owner set.
2828 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
2829 null, CausedFocusEvent.Cause.ACTIVATION);
2830 }
2831
2832 return retargetUnexpectedFocusEvent(fe);
2833 } // end synchronized(heavyweightRequests)
2834 }
2835
2836 static FocusEvent retargetFocusLost(FocusEvent fe) {
2837 assert (fe.getID() == FocusEvent.FOCUS_LOST);
2838
2839 Component currentFocusOwner = getCurrentKeyboardFocusManager().
2840 getGlobalFocusOwner();
2841 Component opposite = fe.getOppositeComponent();
2842 Component nativeOpposite = getHeavyweight(opposite);
2843
2844 synchronized (heavyweightRequests) {
2845 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2846
2847 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2848 {
2849 if (currentFocusOwner != null) {
2850 // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2851 heavyweightRequests.removeFirst();
2852 return new CausedFocusEvent(currentFocusOwner,
2853 FocusEvent.FOCUS_LOST, false, null,
2854 CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2855 }
2856
2857 // Otherwise, fall through to failure case below
2858
2859 } else if (opposite == null)
2860 {
2861 // Focus leaving application
2862 if (currentFocusOwner != null) {
2863 return new CausedFocusEvent(currentFocusOwner,
2864 FocusEvent.FOCUS_LOST,
2865 true, null, CausedFocusEvent.Cause.ACTIVATION);
2866 } else {
2867 return fe;
2868 }
2869 } else if (hwFocusRequest != null &&
2870 (nativeOpposite == hwFocusRequest.heavyweight ||
2871 nativeOpposite == null &&
2872 opposite == hwFocusRequest.getFirstLightweightRequest().component))
2873 {
2874 if (currentFocusOwner == null) {
2875 return fe;
2876 }
2877 // Focus change as a result of a known call to requestFocus(),
2878 // or click on a peer focusable heavyweight Component.
2879 // If a focus transfer is made across top-levels, then the
2880 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2881 // event is always permanent. Otherwise, the stored temporary
2882 // value is honored.
2883
2884 LightweightFocusRequest lwFocusRequest =
2885 hwFocusRequest.lightweightRequests.getFirst();
2886
2887 boolean temporary = isTemporary(opposite, currentFocusOwner)
2888 ? true
2889 : lwFocusRequest.temporary;
2890
2891 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2892 temporary, lwFocusRequest.component, lwFocusRequest.cause);
2893 } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2894 // If top-level changed there might be no focus request in a list
2895 // But we know the opposite, we now it is temporary - dispatch the event.
2896 if (!fe.isTemporary() && currentFocusOwner != null) {
2897 // Create copy of the event with only difference in temporary parameter.
2898 fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2899 true, opposite, CausedFocusEvent.Cause.ACTIVATION);
2900 }
2901 return fe;
2902 }
2903
2904 return retargetUnexpectedFocusEvent(fe);
2905 } // end synchronized(heavyweightRequests)
2906 }
2907
2908 static AWTEvent retargetFocusEvent(AWTEvent event) {
2909 if (clearingCurrentLightweightRequests) {
2910 return event;
2911 }
2912
2913 KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2914 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
2915 if (event instanceof FocusEvent || event instanceof WindowEvent) {
2916 focusLog.finer(">>> {0}", String.valueOf(event));
2917 }
2918 if (focusLog.isLoggable(PlatformLogger.Level.FINER) && event instanceof KeyEvent) {
2919 focusLog.finer(" focus owner is {0}",
|
40
41 import java.lang.ref.WeakReference;
42
43 import java.lang.reflect.Field;
44
45 import java.security.AccessController;
46 import java.security.PrivilegedAction;
47
48 import java.util.Collections;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.LinkedList;
52 import java.util.Set;
53 import java.util.StringTokenizer;
54 import java.util.WeakHashMap;
55
56 import sun.util.logging.PlatformLogger;
57
58 import sun.awt.AppContext;
59 import sun.awt.SunToolkit;
60 import sun.awt.KeyboardFocusManagerPeerProvider;
61 import sun.awt.AWTAccessor;
62
63 /**
64 * The KeyboardFocusManager is responsible for managing the active and focused
65 * Windows, and the current focus owner. The focus owner is defined as the
66 * Component in an application that will typically receive all KeyEvents
67 * generated by the user. The focused Window is the Window that is, or
68 * contains, the focus owner. Only a Frame or a Dialog can be the active
69 * Window. The native windowing system may denote the active Window or its
70 * children with special decorations, such as a highlighted title bar. The
71 * active Window is always either the focused Window, or the first Frame or
72 * Dialog that is an owner of the focused Window.
73 * <p>
74 * The KeyboardFocusManager is both a centralized location for client code to
75 * query for the focus owner and initiate focus changes, and an event
76 * dispatcher for all FocusEvents, WindowEvents related to focus, and
77 * KeyEvents.
78 * <p>
79 * Some browsers partition applets in different code bases into separate
106 public abstract class KeyboardFocusManager
107 implements KeyEventDispatcher, KeyEventPostProcessor
108 {
109
110 // Shared focus engine logger
111 private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
112
113 static {
114 /* ensure that the necessary native libraries are loaded */
115 Toolkit.loadLibraries();
116 if (!GraphicsEnvironment.isHeadless()) {
117 initIDs();
118 }
119 AWTAccessor.setKeyboardFocusManagerAccessor(
120 new AWTAccessor.KeyboardFocusManagerAccessor() {
121 public int shouldNativelyFocusHeavyweight(Component heavyweight,
122 Component descendant,
123 boolean temporary,
124 boolean focusedWindowChangeAllowed,
125 long time,
126 FocusEvent.Cause cause)
127 {
128 return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
129 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
130 }
131 public boolean processSynchronousLightweightTransfer(Component heavyweight,
132 Component descendant,
133 boolean temporary,
134 boolean focusedWindowChangeAllowed,
135 long time)
136 {
137 return KeyboardFocusManager.processSynchronousLightweightTransfer(
138 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
139 }
140 public void removeLastFocusRequest(Component heavyweight) {
141 KeyboardFocusManager.removeLastFocusRequest(heavyweight);
142 }
143 public void setMostRecentFocusOwner(Window window, Component component) {
144 KeyboardFocusManager.setMostRecentFocusOwner(window, component);
145 }
146 public KeyboardFocusManager getCurrentKeyboardFocusManager(AppContext ctx) {
2156 downFocusCycle((Container)focusOwner);
2157 }
2158 }
2159
2160 /**
2161 * Dumps the list of focus requests to stderr
2162 */
2163 void dumpRequests() {
2164 System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2165 synchronized (heavyweightRequests) {
2166 for (HeavyweightFocusRequest req : heavyweightRequests) {
2167 System.err.println(">>> Req: " + req);
2168 }
2169 }
2170 System.err.println("");
2171 }
2172
2173 private static final class LightweightFocusRequest {
2174 final Component component;
2175 final boolean temporary;
2176 final FocusEvent.Cause cause;
2177
2178 LightweightFocusRequest(Component component, boolean temporary, FocusEvent.Cause cause) {
2179 this.component = component;
2180 this.temporary = temporary;
2181 this.cause = cause;
2182 }
2183 public String toString() {
2184 return "LightweightFocusRequest[component=" + component +
2185 ",temporary=" + temporary + ", cause=" + cause + "]";
2186 }
2187 }
2188
2189 private static final class HeavyweightFocusRequest {
2190 final Component heavyweight;
2191 final LinkedList<LightweightFocusRequest> lightweightRequests;
2192
2193 static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2194 new HeavyweightFocusRequest();
2195
2196 private HeavyweightFocusRequest() {
2197 heavyweight = null;
2198 lightweightRequests = null;
2199 }
2200
2201 HeavyweightFocusRequest(Component heavyweight, Component descendant,
2202 boolean temporary, FocusEvent.Cause cause) {
2203 if (log.isLoggable(PlatformLogger.Level.FINE)) {
2204 if (heavyweight == null) {
2205 log.fine("Assertion (heavyweight != null) failed");
2206 }
2207 }
2208
2209 this.heavyweight = heavyweight;
2210 this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2211 addLightweightRequest(descendant, temporary, cause);
2212 }
2213 boolean addLightweightRequest(Component descendant,
2214 boolean temporary, FocusEvent.Cause cause) {
2215 if (log.isLoggable(PlatformLogger.Level.FINE)) {
2216 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2217 log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2218 }
2219 if (descendant == null) {
2220 log.fine("Assertion (descendant != null) failed");
2221 }
2222 }
2223
2224 Component lastDescendant = ((lightweightRequests.size() > 0)
2225 ? lightweightRequests.getLast().component
2226 : null);
2227
2228 if (descendant != lastDescendant) {
2229 // Not a duplicate request
2230 lightweightRequests.add
2231 (new LightweightFocusRequest(descendant, temporary, cause));
2232 return true;
2233 } else {
2234 return false;
2306 synchronized (heavyweightRequests) {
2307 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2308 if (hwFocusRequest == null &&
2309 heavyweight == manager.getNativeFocusOwner() &&
2310 allowSyncFocusRequests)
2311 {
2312
2313 if (descendant == currentFocusOwner) {
2314 // Redundant request.
2315 return true;
2316 }
2317
2318 // 'heavyweight' owns the native focus and there are no pending
2319 // requests. 'heavyweight' must be a Container and
2320 // 'descendant' must not be the focus owner. Otherwise,
2321 // we would never have gotten this far.
2322 manager.enqueueKeyEvents(time, descendant);
2323
2324 hwFocusRequest =
2325 new HeavyweightFocusRequest(heavyweight, descendant,
2326 temporary, FocusEvent.Cause.UNKNOWN);
2327 heavyweightRequests.add(hwFocusRequest);
2328
2329 if (currentFocusOwner != null) {
2330 currentFocusOwnerEvent =
2331 new FocusEvent(currentFocusOwner,
2332 FocusEvent.FOCUS_LOST,
2333 temporary, descendant);
2334 }
2335 newFocusOwnerEvent =
2336 new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2337 temporary, currentFocusOwner);
2338 }
2339 }
2340 boolean result = false;
2341 final boolean clearing = clearingCurrentLightweightRequests;
2342
2343 Throwable caughtEx = null;
2344 try {
2345 clearingCurrentLightweightRequests = false;
2346 synchronized(Component.LOCK) {
2371 /**
2372 * Indicates whether the native implementation should proceed with a
2373 * pending, native focus request. Before changing the focus at the native
2374 * level, the AWT implementation should always call this function for
2375 * permission. This function will reject the request if a duplicate request
2376 * preceded it, or if the specified heavyweight Component already owns the
2377 * focus and no native focus changes are pending. Otherwise, the request
2378 * will be approved and the focus request list will be updated so that,
2379 * if necessary, the proper descendant will be focused when the
2380 * corresponding FOCUS_GAINED event on the heavyweight is received.
2381 *
2382 * An implementation must ensure that calls to this method and native
2383 * focus changes are atomic. If this is not guaranteed, then the ordering
2384 * of the focus request list may be incorrect, leading to errors in the
2385 * type-ahead mechanism. Typically this is accomplished by only calling
2386 * this function from the native event pumping thread, or by holding a
2387 * global, native lock during invocation.
2388 */
2389 static int shouldNativelyFocusHeavyweight
2390 (Component heavyweight, Component descendant, boolean temporary,
2391 boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)
2392 {
2393 if (log.isLoggable(PlatformLogger.Level.FINE)) {
2394 if (heavyweight == null) {
2395 log.fine("Assertion (heavyweight != null) failed");
2396 }
2397 if (time == 0) {
2398 log.fine("Assertion (time != 0) failed");
2399 }
2400 }
2401
2402 if (descendant == null) {
2403 // Focus transfers from a lightweight child back to the
2404 // heavyweight Container should be treated like lightweight
2405 // focus transfers.
2406 descendant = heavyweight;
2407 }
2408
2409 KeyboardFocusManager manager =
2410 getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2411 KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
2437 // Redundant request.
2438 if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2439 focusLog.finest("1. SNFH_FAILURE for {0}",
2440 String.valueOf(descendant));
2441 return SNFH_FAILURE;
2442 }
2443
2444 // 'heavyweight' owns the native focus and there are no pending
2445 // requests. 'heavyweight' must be a Container and
2446 // 'descendant' must not be the focus owner. Otherwise,
2447 // we would never have gotten this far.
2448 manager.enqueueKeyEvents(time, descendant);
2449
2450 hwFocusRequest =
2451 new HeavyweightFocusRequest(heavyweight, descendant,
2452 temporary, cause);
2453 heavyweightRequests.add(hwFocusRequest);
2454
2455 if (currentFocusOwner != null) {
2456 FocusEvent currentFocusOwnerEvent =
2457 new FocusEvent(currentFocusOwner,
2458 FocusEvent.FOCUS_LOST,
2459 temporary, descendant, cause);
2460 // Fix 5028014. Rolled out.
2461 // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2462 SunToolkit.postEvent(currentFocusOwner.appContext,
2463 currentFocusOwnerEvent);
2464 }
2465 FocusEvent newFocusOwnerEvent =
2466 new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2467 temporary, currentFocusOwner, cause);
2468 // Fix 5028014. Rolled out.
2469 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2470 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
2471
2472 if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2473 focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
2474 return SNFH_SUCCESS_HANDLED;
2475 } else if (hwFocusRequest != null &&
2476 hwFocusRequest.heavyweight == heavyweight) {
2477 // 'heavyweight' doesn't have the native focus right now, but
2478 // if all pending requests were completed, it would. Add
2479 // descendant to the heavyweight's list of pending
2480 // lightweight focus transfers.
2481 if (hwFocusRequest.addLightweightRequest(descendant,
2482 temporary, cause)) {
2483 manager.enqueueKeyEvents(time, descendant);
2484 }
2485
2486 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
2662 /*
2663 * WARNING: This is based on DKFM's logic solely!
2664 *
2665 * We allow to trigger restoreFocus() in the dispatching process
2666 * only if we have the last request to dispatch. If the last request
2667 * fails, focus will be restored to either the component of the last
2668 * previously succeeded request, or to the focus owner that was
2669 * before this clearing process.
2670 */
2671 if (!iter.hasNext()) {
2672 disableRestoreFocus = false;
2673 }
2674
2675 FocusEvent currentFocusOwnerEvent = null;
2676 /*
2677 * We're not dispatching FOCUS_LOST while the current focus owner is null.
2678 * But regardless of whether it's null or not, we're clearing ALL the local
2679 * lw requests.
2680 */
2681 if (currentFocusOwner != null) {
2682 currentFocusOwnerEvent = new FocusEvent(currentFocusOwner,
2683 FocusEvent.FOCUS_LOST,
2684 lwFocusRequest.temporary,
2685 lwFocusRequest.component, lwFocusRequest.cause);
2686 }
2687 FocusEvent newFocusOwnerEvent =
2688 new FocusEvent(lwFocusRequest.component,
2689 FocusEvent.FOCUS_GAINED,
2690 lwFocusRequest.temporary,
2691 currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
2692 lwFocusRequest.cause);
2693
2694 if (currentFocusOwner != null) {
2695 ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2696 caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2697 }
2698
2699 ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2700 caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2701
2702 if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2703 lastFocusOwner = lwFocusRequest.component;
2704 }
2705 }
2706 }
2707 } finally {
2708 clearingCurrentLightweightRequests = false;
2718 }
2719
2720 static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2721 synchronized (heavyweightRequests) {
2722 // Any other case represents a failure condition which we did
2723 // not expect. We need to clearFocusRequestList() and patch up
2724 // the event as best as possible.
2725
2726 if (removeFirstRequest()) {
2727 return (FocusEvent)retargetFocusEvent(fe);
2728 }
2729
2730 Component source = fe.getComponent();
2731 Component opposite = fe.getOppositeComponent();
2732 boolean temporary = false;
2733 if (fe.getID() == FocusEvent.FOCUS_LOST &&
2734 (opposite == null || isTemporary(opposite, source)))
2735 {
2736 temporary = true;
2737 }
2738 return new FocusEvent(source, fe.getID(), temporary, opposite,
2739 FocusEvent.Cause.UNEXPECTED);
2740 }
2741 }
2742
2743 static FocusEvent retargetFocusGained(FocusEvent fe) {
2744 assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2745
2746 Component currentFocusOwner = getCurrentKeyboardFocusManager().
2747 getGlobalFocusOwner();
2748 Component source = fe.getComponent();
2749 Component opposite = fe.getOppositeComponent();
2750 Component nativeSource = getHeavyweight(source);
2751
2752 synchronized (heavyweightRequests) {
2753 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2754
2755 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2756 {
2757 return retargetUnexpectedFocusEvent(fe);
2758 }
2759
2794 newFocusOwner = newSource;
2795 }
2796
2797 boolean temporary = (opposite == null ||
2798 isTemporary(newSource, opposite))
2799 ? false
2800 : lwFocusRequest.temporary;
2801
2802 if (hwFocusRequest.lightweightRequests.size() > 0) {
2803 currentLightweightRequests =
2804 hwFocusRequest.lightweightRequests;
2805 EventQueue.invokeLater(new Runnable() {
2806 public void run() {
2807 processCurrentLightweightRequests();
2808 }
2809 });
2810 }
2811
2812 // 'opposite' will be fixed by
2813 // DefaultKeyboardFocusManager.realOppositeComponent
2814 return new FocusEvent(newSource,
2815 FocusEvent.FOCUS_GAINED, temporary,
2816 opposite, lwFocusRequest.cause);
2817 }
2818
2819 if (currentFocusOwner != null
2820 && currentFocusOwner.getContainingWindow() == source
2821 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2822 {
2823 // Special case for FOCUS_GAINED in top-levels
2824 // If it arrives as the result of activation we should skip it
2825 // This event will not have appropriate request record and
2826 // on arrival there will be already some focus owner set.
2827 return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
2828 null, FocusEvent.Cause.ACTIVATION);
2829 }
2830
2831 return retargetUnexpectedFocusEvent(fe);
2832 } // end synchronized(heavyweightRequests)
2833 }
2834
2835 static FocusEvent retargetFocusLost(FocusEvent fe) {
2836 assert (fe.getID() == FocusEvent.FOCUS_LOST);
2837
2838 Component currentFocusOwner = getCurrentKeyboardFocusManager().
2839 getGlobalFocusOwner();
2840 Component opposite = fe.getOppositeComponent();
2841 Component nativeOpposite = getHeavyweight(opposite);
2842
2843 synchronized (heavyweightRequests) {
2844 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2845
2846 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2847 {
2848 if (currentFocusOwner != null) {
2849 // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2850 heavyweightRequests.removeFirst();
2851 return new FocusEvent(currentFocusOwner,
2852 FocusEvent.FOCUS_LOST, false, null,
2853 FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2854 }
2855
2856 // Otherwise, fall through to failure case below
2857
2858 } else if (opposite == null)
2859 {
2860 // Focus leaving application
2861 if (currentFocusOwner != null) {
2862 return new FocusEvent(currentFocusOwner,
2863 FocusEvent.FOCUS_LOST,
2864 true, null, FocusEvent.Cause.ACTIVATION);
2865 } else {
2866 return fe;
2867 }
2868 } else if (hwFocusRequest != null &&
2869 (nativeOpposite == hwFocusRequest.heavyweight ||
2870 nativeOpposite == null &&
2871 opposite == hwFocusRequest.getFirstLightweightRequest().component))
2872 {
2873 if (currentFocusOwner == null) {
2874 return fe;
2875 }
2876 // Focus change as a result of a known call to requestFocus(),
2877 // or click on a peer focusable heavyweight Component.
2878 // If a focus transfer is made across top-levels, then the
2879 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2880 // event is always permanent. Otherwise, the stored temporary
2881 // value is honored.
2882
2883 LightweightFocusRequest lwFocusRequest =
2884 hwFocusRequest.lightweightRequests.getFirst();
2885
2886 boolean temporary = isTemporary(opposite, currentFocusOwner)
2887 ? true
2888 : lwFocusRequest.temporary;
2889
2890 return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2891 temporary, lwFocusRequest.component, lwFocusRequest.cause);
2892 } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2893 // If top-level changed there might be no focus request in a list
2894 // But we know the opposite, we now it is temporary - dispatch the event.
2895 if (!fe.isTemporary() && currentFocusOwner != null) {
2896 // Create copy of the event with only difference in temporary parameter.
2897 fe = new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2898 true, opposite, FocusEvent.Cause.ACTIVATION);
2899 }
2900 return fe;
2901 }
2902
2903 return retargetUnexpectedFocusEvent(fe);
2904 } // end synchronized(heavyweightRequests)
2905 }
2906
2907 static AWTEvent retargetFocusEvent(AWTEvent event) {
2908 if (clearingCurrentLightweightRequests) {
2909 return event;
2910 }
2911
2912 KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2913 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
2914 if (event instanceof FocusEvent || event instanceof WindowEvent) {
2915 focusLog.finer(">>> {0}", String.valueOf(event));
2916 }
2917 if (focusLog.isLoggable(PlatformLogger.Level.FINER) && event instanceof KeyEvent) {
2918 focusLog.finer(" focus owner is {0}",
|