13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.event.FocusEvent; 28 import java.awt.event.KeyEvent; 29 import java.awt.event.WindowEvent; 30 import java.awt.peer.ComponentPeer; 31 import java.awt.peer.LightweightPeer; 32 import java.lang.ref.WeakReference; 33 import java.util.LinkedList; 34 import java.util.Iterator; 35 import java.util.ListIterator; 36 import java.util.Set; 37 38 import sun.util.logging.PlatformLogger; 39 40 import sun.awt.AppContext; 41 import sun.awt.SunToolkit; 42 import sun.awt.AWTAccessor; 43 import sun.awt.TimedWindowEvent; 44 45 /** 46 * The default KeyboardFocusManager for AWT applications. Focus traversal is 47 * done in response to a Component's focus traversal keys, and using a 48 * Container's FocusTraversalPolicy. 49 * <p> 50 * Please see 51 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 52 * How to Use the Focus Subsystem</a>, 60 * @see Component#setFocusTraversalKeys 61 * @see Component#getFocusTraversalKeys 62 * @since 1.4 63 */ 64 public class DefaultKeyboardFocusManager extends KeyboardFocusManager { 65 private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.DefaultKeyboardFocusManager"); 66 67 // null weak references to not create too many objects 68 private static final WeakReference<Window> NULL_WINDOW_WR = 69 new WeakReference<Window>(null); 70 private static final WeakReference<Component> NULL_COMPONENT_WR = 71 new WeakReference<Component>(null); 72 private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR; 73 private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR; 74 private int inSendMessage; 75 private LinkedList<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>(); 76 private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>(); 77 private boolean consumeNextKeyTyped; 78 private Component restoreFocusTo; 79 80 static { 81 AWTAccessor.setDefaultKeyboardFocusManagerAccessor( 82 new AWTAccessor.DefaultKeyboardFocusManagerAccessor() { 83 public void consumeNextKeyTyped(DefaultKeyboardFocusManager dkfm, KeyEvent e) { 84 dkfm.consumeNextKeyTyped(e); 85 } 86 }); 87 } 88 89 private static class TypeAheadMarker { 90 long after; 91 Component untilFocused; 92 93 TypeAheadMarker(long after, Component untilFocused) { 94 this.after = after; 95 this.untilFocused = untilFocused; 96 } 97 /** 98 * Returns string representation of the marker 99 */ 100 public String toString() { 101 return ">>> Marker after " + after + " on " + untilFocused; 102 } 103 } 104 105 private Window getOwningFrameDialog(Window window) { 106 while (window != null && !(window instanceof Frame || 247 * posted to the other AppContext's EventQueue, and this method blocks 248 * until the event is handled or target AppContext is disposed. 249 * Returns true if successfully dispatched event, false if failed 250 * to dispatch. 251 */ 252 static boolean sendMessage(Component target, AWTEvent e) { 253 e.isPosted = true; 254 AppContext myAppContext = AppContext.getAppContext(); 255 final AppContext targetAppContext = target.appContext; 256 final SentEvent se = 257 new DefaultKeyboardFocusManagerSentEvent(e, myAppContext); 258 259 if (myAppContext == targetAppContext) { 260 se.dispatch(); 261 } else { 262 if (targetAppContext.isDisposed()) { 263 return false; 264 } 265 SunToolkit.postEvent(targetAppContext, se); 266 if (EventQueue.isDispatchThread()) { 267 EventDispatchThread edt = (EventDispatchThread) 268 Thread.currentThread(); 269 edt.pumpEvents(SentEvent.ID, new Conditional() { 270 public boolean evaluate() { 271 return !se.dispatched && !targetAppContext.isDisposed(); 272 } 273 }); 274 } else { 275 synchronized (se) { 276 while (!se.dispatched && !targetAppContext.isDisposed()) { 277 try { 278 se.wait(1000); 279 } catch (InterruptedException ie) { 280 break; 281 } 282 } 283 } 284 } 285 } 286 return se.dispatched; 287 } 288 289 /* 290 * Checks if the focus window event follows key events waiting in the type-ahead 291 * queue (if any). This may happen when a user types ahead in the window, the client 292 * listeners hang EDT for a while, and the user switches b/w toplevels. In that 293 * case the focus window events may be dispatched before the type-ahead events | 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.event.FocusEvent; 28 import java.awt.event.KeyEvent; 29 import java.awt.event.WindowEvent; 30 import java.awt.peer.ComponentPeer; 31 import java.awt.peer.LightweightPeer; 32 import java.lang.ref.WeakReference; 33 import java.security.AccessController; 34 import java.security.PrivilegedAction; 35 import java.util.LinkedList; 36 import java.util.Iterator; 37 import java.util.ListIterator; 38 import java.util.Set; 39 40 import sun.util.logging.PlatformLogger; 41 42 import sun.awt.AppContext; 43 import sun.awt.SunToolkit; 44 import sun.awt.AWTAccessor; 45 import sun.awt.TimedWindowEvent; 46 47 /** 48 * The default KeyboardFocusManager for AWT applications. Focus traversal is 49 * done in response to a Component's focus traversal keys, and using a 50 * Container's FocusTraversalPolicy. 51 * <p> 52 * Please see 53 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 54 * How to Use the Focus Subsystem</a>, 62 * @see Component#setFocusTraversalKeys 63 * @see Component#getFocusTraversalKeys 64 * @since 1.4 65 */ 66 public class DefaultKeyboardFocusManager extends KeyboardFocusManager { 67 private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.DefaultKeyboardFocusManager"); 68 69 // null weak references to not create too many objects 70 private static final WeakReference<Window> NULL_WINDOW_WR = 71 new WeakReference<Window>(null); 72 private static final WeakReference<Component> NULL_COMPONENT_WR = 73 new WeakReference<Component>(null); 74 private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR; 75 private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR; 76 private int inSendMessage; 77 private LinkedList<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>(); 78 private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>(); 79 private boolean consumeNextKeyTyped; 80 private Component restoreFocusTo; 81 82 private static boolean fxAppThreadIsDispatchThread; 83 84 static { 85 AWTAccessor.setDefaultKeyboardFocusManagerAccessor( 86 new AWTAccessor.DefaultKeyboardFocusManagerAccessor() { 87 public void consumeNextKeyTyped(DefaultKeyboardFocusManager dkfm, KeyEvent e) { 88 dkfm.consumeNextKeyTyped(e); 89 } 90 }); 91 AccessController.doPrivileged(new PrivilegedAction<Object>() { 92 public Object run() { 93 fxAppThreadIsDispatchThread = 94 "true".equals(System.getProperty("javafx.embed.singleThread")); 95 return null; 96 } 97 }); 98 } 99 100 private static class TypeAheadMarker { 101 long after; 102 Component untilFocused; 103 104 TypeAheadMarker(long after, Component untilFocused) { 105 this.after = after; 106 this.untilFocused = untilFocused; 107 } 108 /** 109 * Returns string representation of the marker 110 */ 111 public String toString() { 112 return ">>> Marker after " + after + " on " + untilFocused; 113 } 114 } 115 116 private Window getOwningFrameDialog(Window window) { 117 while (window != null && !(window instanceof Frame || 258 * posted to the other AppContext's EventQueue, and this method blocks 259 * until the event is handled or target AppContext is disposed. 260 * Returns true if successfully dispatched event, false if failed 261 * to dispatch. 262 */ 263 static boolean sendMessage(Component target, AWTEvent e) { 264 e.isPosted = true; 265 AppContext myAppContext = AppContext.getAppContext(); 266 final AppContext targetAppContext = target.appContext; 267 final SentEvent se = 268 new DefaultKeyboardFocusManagerSentEvent(e, myAppContext); 269 270 if (myAppContext == targetAppContext) { 271 se.dispatch(); 272 } else { 273 if (targetAppContext.isDisposed()) { 274 return false; 275 } 276 SunToolkit.postEvent(targetAppContext, se); 277 if (EventQueue.isDispatchThread()) { 278 if (Thread.currentThread() instanceof EventDispatchThread) { 279 EventDispatchThread edt = (EventDispatchThread) 280 Thread.currentThread(); 281 edt.pumpEvents(SentEvent.ID, new Conditional() { 282 public boolean evaluate() { 283 return !se.dispatched && !targetAppContext.isDisposed(); 284 } 285 }); 286 } else { 287 if (fxAppThreadIsDispatchThread) { 288 Thread fxCheckDispatchThread = new Thread() { 289 @Override 290 public void run() { 291 while (!se.dispatched && !targetAppContext.isDisposed()) { 292 try { 293 Thread.sleep(100); 294 } catch (InterruptedException e) { 295 break; 296 } 297 } 298 } 299 }; 300 fxCheckDispatchThread.start(); 301 try { 302 // check if event is dispatched or disposed 303 // but since this user app thread is same as 304 // dispatch thread in fx when run with 305 // javafx.embed.singleThread=true 306 // we do not wait infinitely to avoid deadlock 307 // as dispatch will ultimately be done by this thread 308 fxCheckDispatchThread.join(500); 309 } catch (InterruptedException ex) { 310 } 311 } 312 } 313 } else { 314 synchronized (se) { 315 while (!se.dispatched && !targetAppContext.isDisposed()) { 316 try { 317 se.wait(1000); 318 } catch (InterruptedException ie) { 319 break; 320 } 321 } 322 } 323 } 324 } 325 return se.dispatched; 326 } 327 328 /* 329 * Checks if the focus window event follows key events waiting in the type-ahead 330 * queue (if any). This may happen when a user types ahead in the window, the client 331 * listeners hang EDT for a while, and the user switches b/w toplevels. In that 332 * case the focus window events may be dispatched before the type-ahead events |