< prev index next >

src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java

Print this page




  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


< prev index next >