mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			567 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			567 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
/* DefaultKeyboardFocusManager.java --
 | 
						|
   Copyright (C) 2002, 2004  Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
 | 
						|
package java.awt;
 | 
						|
 | 
						|
import java.awt.event.ActionEvent;
 | 
						|
import java.awt.event.FocusEvent;
 | 
						|
import java.awt.event.KeyEvent;
 | 
						|
import java.awt.event.WindowEvent;
 | 
						|
import java.util.Iterator;
 | 
						|
import java.util.LinkedList;
 | 
						|
import java.util.Set;
 | 
						|
import java.util.SortedSet;
 | 
						|
import java.util.TreeSet;
 | 
						|
 | 
						|
// FIXME: finish documentation
 | 
						|
public class DefaultKeyboardFocusManager extends KeyboardFocusManager
 | 
						|
{
 | 
						|
  /**
 | 
						|
   * This class models a request to delay the dispatch of events that
 | 
						|
   * arrive after a certain time, until a certain component becomes
 | 
						|
   * the focus owner.
 | 
						|
   */
 | 
						|
  private class EventDelayRequest implements Comparable
 | 
						|
  {
 | 
						|
    /** A {@link java.util.List} of {@link java.awt.event.KeyEvent}s
 | 
						|
        that are being delayed, pending this request's {@link
 | 
						|
        Component} receiving the keyboard focus. */
 | 
						|
    private LinkedList enqueuedKeyEvents = new LinkedList ();
 | 
						|
 | 
						|
    /** An event timestamp.  All events that arrive after this time
 | 
						|
        should be queued in the {@link #enqueuedKeyEvents} {@link
 | 
						|
        java.util.List}. */
 | 
						|
    public long timestamp;
 | 
						|
    /** When this {@link Component} becomes focused, all events
 | 
						|
        between this EventDelayRequest and the next one in will be
 | 
						|
        dispatched from {@link #enqueuedKeyEvents}. */
 | 
						|
    public Component focusedComp;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Construct a new EventDelayRequest.
 | 
						|
     *
 | 
						|
     * @param timestamp events that arrive after this time will be
 | 
						|
     * delayed
 | 
						|
     * @param focusedComp the Component that needs to receive focus
 | 
						|
     * before events are dispatched
 | 
						|
     */
 | 
						|
    public EventDelayRequest (long timestamp, Component focusedComp)
 | 
						|
    {
 | 
						|
      this.timestamp = timestamp;
 | 
						|
      this.focusedComp = focusedComp;
 | 
						|
    }
 | 
						|
 | 
						|
    public int compareTo (Object o)
 | 
						|
    {
 | 
						|
      if (!(o instanceof EventDelayRequest))
 | 
						|
        throw new ClassCastException ();
 | 
						|
 | 
						|
      EventDelayRequest request = (EventDelayRequest) o;
 | 
						|
 | 
						|
      if (request.timestamp < timestamp)
 | 
						|
        return -1;
 | 
						|
      else if (request.timestamp == timestamp)
 | 
						|
        return 0;
 | 
						|
      else
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean equals (Object o)
 | 
						|
    {
 | 
						|
      if (!(o instanceof EventDelayRequest) || o == null)
 | 
						|
        return false;
 | 
						|
 | 
						|
      EventDelayRequest request = (EventDelayRequest) o;
 | 
						|
 | 
						|
      return (request.timestamp == timestamp
 | 
						|
              && request.focusedComp == focusedComp);
 | 
						|
    }
 | 
						|
 | 
						|
    public void enqueueEvent (KeyEvent e)
 | 
						|
    {
 | 
						|
      KeyEvent last = (KeyEvent) enqueuedKeyEvents.getLast ();
 | 
						|
      if (last != null && e.getWhen () < last.getWhen ())
 | 
						|
        throw new RuntimeException ("KeyEvents enqueued out-of-order");
 | 
						|
 | 
						|
      if (e.getWhen () <= timestamp)
 | 
						|
        throw new RuntimeException ("KeyEvents enqueued before starting timestamp");
 | 
						|
 | 
						|
      enqueuedKeyEvents.add (e);
 | 
						|
    }
 | 
						|
 | 
						|
    public void dispatchEvents ()
 | 
						|
    {
 | 
						|
      int size = enqueuedKeyEvents.size ();
 | 
						|
      for (int i = 0; i < size; i++)
 | 
						|
        {
 | 
						|
          KeyEvent e = (KeyEvent) enqueuedKeyEvents.remove (0);
 | 
						|
          dispatchKeyEvent (e);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public void discardEvents ()
 | 
						|
    {
 | 
						|
      enqueuedKeyEvents.clear ();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * This flag indicates for which focus traversal key release event we
 | 
						|
   * possibly wait, before letting any more KEY_TYPED events through.
 | 
						|
   */
 | 
						|
  private AWTKeyStroke waitForKeyStroke = null;
 | 
						|
 | 
						|
  /** The {@link java.util.SortedSet} of current
 | 
						|
   * {@link EventDelayRequest}s. */
 | 
						|
  private SortedSet delayRequests = new TreeSet ();
 | 
						|
 | 
						|
  public DefaultKeyboardFocusManager ()
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean dispatchEvent (AWTEvent e)
 | 
						|
  {
 | 
						|
    if (e instanceof WindowEvent)
 | 
						|
      {
 | 
						|
        Window target = (Window) e.getSource ();
 | 
						|
 | 
						|
        if (e.id == WindowEvent.WINDOW_ACTIVATED)
 | 
						|
          setGlobalActiveWindow (target);
 | 
						|
        else if (e.id == WindowEvent.WINDOW_GAINED_FOCUS)
 | 
						|
          {
 | 
						|
            setGlobalFocusedWindow (target);
 | 
						|
            FocusTraversalPolicy p = target.getFocusTraversalPolicy();
 | 
						|
            Component toFocus = p.getInitialComponent(target);
 | 
						|
            if (toFocus != null)
 | 
						|
              toFocus.requestFocusInWindow();
 | 
						|
          }
 | 
						|
        else if (e.id != WindowEvent.WINDOW_LOST_FOCUS
 | 
						|
                 && e.id != WindowEvent.WINDOW_DEACTIVATED)
 | 
						|
          return false;
 | 
						|
 | 
						|
        redispatchEvent(target, e);
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    else if (e instanceof FocusEvent)
 | 
						|
      {
 | 
						|
        FocusEvent fe = (FocusEvent) e;
 | 
						|
        Component target = fe.getComponent ();
 | 
						|
 | 
						|
        boolean retval = false;
 | 
						|
        if (e.id == FocusEvent.FOCUS_GAINED)
 | 
						|
          {
 | 
						|
            retval = handleFocusGained(fe);
 | 
						|
          }
 | 
						|
        else if (e.id == FocusEvent.FOCUS_LOST)
 | 
						|
          {
 | 
						|
            retval = handleFocusLost(fe);
 | 
						|
          }
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    else if (e instanceof KeyEvent)
 | 
						|
      {
 | 
						|
        // Loop through all registered KeyEventDispatchers, giving
 | 
						|
        // each a chance to handle this event.
 | 
						|
        Iterator i = getKeyEventDispatchers().iterator();
 | 
						|
 | 
						|
        while (i.hasNext ())
 | 
						|
          {
 | 
						|
            KeyEventDispatcher dispatcher = (KeyEventDispatcher) i.next ();
 | 
						|
            if (dispatcher.dispatchKeyEvent ((KeyEvent) e))
 | 
						|
              return true;
 | 
						|
          }
 | 
						|
 | 
						|
        // processKeyEvent checks if this event represents a focus
 | 
						|
        // traversal key stroke.
 | 
						|
        Component focusOwner = getGlobalPermanentFocusOwner ();
 | 
						|
 | 
						|
        if (focusOwner != null)
 | 
						|
          processKeyEvent (focusOwner, (KeyEvent) e);
 | 
						|
 | 
						|
        if (e.isConsumed ())
 | 
						|
          return true;
 | 
						|
 | 
						|
        if (enqueueKeyEvent ((KeyEvent) e))
 | 
						|
          // This event was enqueued for dispatch at a later time.
 | 
						|
          return true;
 | 
						|
        else
 | 
						|
          // This event wasn't handled by any of the registered
 | 
						|
          // KeyEventDispatchers, and wasn't enqueued for dispatch
 | 
						|
          // later, so send it to the default dispatcher.
 | 
						|
          return dispatchKeyEvent ((KeyEvent) e);
 | 
						|
      }
 | 
						|
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Handles FOCUS_GAINED events in {@link #dispatchEvent(AWTEvent)}.
 | 
						|
   *
 | 
						|
   * @param fe the focus event
 | 
						|
   */
 | 
						|
  private boolean handleFocusGained(FocusEvent fe)
 | 
						|
  {
 | 
						|
    Component target = fe.getComponent ();
 | 
						|
 | 
						|
    // If old focus owner != new focus owner, notify old focus
 | 
						|
    // owner that it has lost focus.
 | 
						|
    Component oldFocusOwner = getGlobalFocusOwner();
 | 
						|
    if (oldFocusOwner != null && oldFocusOwner != target)
 | 
						|
      {
 | 
						|
        FocusEvent lost = new FocusEvent(oldFocusOwner,
 | 
						|
                                         FocusEvent.FOCUS_LOST,
 | 
						|
                                         fe.isTemporary(), target);
 | 
						|
        oldFocusOwner.dispatchEvent(lost);
 | 
						|
      }
 | 
						|
 | 
						|
     setGlobalFocusOwner (target);
 | 
						|
     if (target != getGlobalFocusOwner())
 | 
						|
       {
 | 
						|
         // Focus transfer was rejected, like when the target is not
 | 
						|
         // focusable.
 | 
						|
         dequeueKeyEvents(-1, target);
 | 
						|
         // FIXME: Restore focus somehow.
 | 
						|
       }
 | 
						|
     else
 | 
						|
       {
 | 
						|
         if (! fe.isTemporary())
 | 
						|
           {
 | 
						|
             setGlobalPermanentFocusOwner (target);
 | 
						|
             if (target != getGlobalPermanentFocusOwner())
 | 
						|
               {
 | 
						|
                 // Focus transfer was rejected, like when the target is not
 | 
						|
                 // focusable.
 | 
						|
                 dequeueKeyEvents(-1, target);
 | 
						|
                 // FIXME: Restore focus somehow.
 | 
						|
               }
 | 
						|
             else
 | 
						|
               {
 | 
						|
                 redispatchEvent(target, fe);
 | 
						|
               }
 | 
						|
           }
 | 
						|
       }
 | 
						|
 | 
						|
     return true;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Handles FOCUS_LOST events for {@link #dispatchEvent(AWTEvent)}.
 | 
						|
   *
 | 
						|
   * @param fe the focus event
 | 
						|
   *
 | 
						|
   * @return if the event has been handled
 | 
						|
   */
 | 
						|
  private boolean handleFocusLost(FocusEvent fe)
 | 
						|
  {
 | 
						|
    Component currentFocus = getGlobalFocusOwner();
 | 
						|
    if (currentFocus != fe.getOppositeComponent())
 | 
						|
      {
 | 
						|
        setGlobalFocusOwner(null);
 | 
						|
        if (getGlobalFocusOwner() != null)
 | 
						|
          {
 | 
						|
            // TODO: Is this possible? If so, then we should try to restore
 | 
						|
            // the focus.
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            if (! fe.isTemporary())
 | 
						|
              {
 | 
						|
                setGlobalPermanentFocusOwner(null);
 | 
						|
                if (getGlobalPermanentFocusOwner() != null)
 | 
						|
                  {
 | 
						|
                    // TODO: Is this possible? If so, then we should try to
 | 
						|
                    // restore the focus.
 | 
						|
                  }
 | 
						|
                else
 | 
						|
                  {
 | 
						|
                    fe.setSource(currentFocus);
 | 
						|
                    redispatchEvent(currentFocus, fe);
 | 
						|
                  }
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  private boolean enqueueKeyEvent (KeyEvent e)
 | 
						|
  {
 | 
						|
    Iterator i = delayRequests.iterator ();
 | 
						|
    boolean oneEnqueued = false;
 | 
						|
    while (i.hasNext ())
 | 
						|
      {
 | 
						|
        EventDelayRequest request = (EventDelayRequest) i.next ();
 | 
						|
        if (e.getWhen () > request.timestamp)
 | 
						|
          {
 | 
						|
            request.enqueueEvent (e);
 | 
						|
            oneEnqueued = true;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return oneEnqueued;
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean dispatchKeyEvent (KeyEvent e)
 | 
						|
  {
 | 
						|
    Component focusOwner = getFocusOwner();
 | 
						|
    if (focusOwner == null)
 | 
						|
      focusOwner = getFocusedWindow();
 | 
						|
 | 
						|
    if (focusOwner != null)
 | 
						|
      redispatchEvent(focusOwner, e);
 | 
						|
 | 
						|
    // Loop through all registered KeyEventPostProcessors, giving
 | 
						|
    // each a chance to process this event.
 | 
						|
    Iterator i = getKeyEventPostProcessors().iterator();
 | 
						|
 | 
						|
    while (i.hasNext ())
 | 
						|
      {
 | 
						|
        KeyEventPostProcessor processor = (KeyEventPostProcessor) i.next ();
 | 
						|
        if (processor.postProcessKeyEvent (e))
 | 
						|
          return true;
 | 
						|
      }
 | 
						|
 | 
						|
    // The event hasn't been consumed yet.  Check if it is an
 | 
						|
    // MenuShortcut.
 | 
						|
    if (postProcessKeyEvent (e))
 | 
						|
      return true;
 | 
						|
 | 
						|
    // Always return true.
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean postProcessKeyEvent (KeyEvent e)
 | 
						|
  {
 | 
						|
    // Check if this event represents a menu shortcut.
 | 
						|
 | 
						|
    // MenuShortcuts are activated by Ctrl- KeyEvents, only on KEY_PRESSED.
 | 
						|
    int modifiers = e.getModifiersEx ();
 | 
						|
    if (e.getID() == KeyEvent.KEY_PRESSED
 | 
						|
        && (modifiers & KeyEvent.CTRL_DOWN_MASK) != 0)
 | 
						|
      {
 | 
						|
        Window focusedWindow = getGlobalFocusedWindow ();
 | 
						|
        if (focusedWindow instanceof Frame)
 | 
						|
          {
 | 
						|
            MenuBar menubar = ((Frame) focusedWindow).getMenuBar ();
 | 
						|
 | 
						|
            if (menubar != null)
 | 
						|
              {
 | 
						|
                // If there's a menubar, loop through all menu items,
 | 
						|
                // checking whether each one has a shortcut, and if
 | 
						|
                // so, whether this key event should activate it.
 | 
						|
                int numMenus = menubar.getMenuCount ();
 | 
						|
 | 
						|
                for (int i = 0; i < numMenus; i++)
 | 
						|
                  {
 | 
						|
                    Menu menu = menubar.getMenu (i);
 | 
						|
                    int numItems = menu.getItemCount ();
 | 
						|
 | 
						|
                    for (int j = 0; j < numItems; j++)
 | 
						|
                      {
 | 
						|
                        MenuItem item = menu.getItem (j);
 | 
						|
                        MenuShortcut shortcut = item.getShortcut ();
 | 
						|
 | 
						|
                        if (item.isEnabled() && shortcut != null)
 | 
						|
                          {
 | 
						|
                            // Dispatch a new ActionEvent if:
 | 
						|
                            //
 | 
						|
                            //     a) this is a Shift- KeyEvent, and the
 | 
						|
                            //        shortcut requires the Shift modifier
 | 
						|
                            //
 | 
						|
                            // or, b) this is not a Shift- KeyEvent, and the
 | 
						|
                            //        shortcut does not require the Shift
 | 
						|
                            //        modifier.
 | 
						|
                            if (shortcut.getKey () == e.getKeyCode ()
 | 
						|
                                && ((shortcut.usesShiftModifier ()
 | 
						|
                                     && (modifiers & KeyEvent.SHIFT_DOWN_MASK) != 0)
 | 
						|
                                    || (! shortcut.usesShiftModifier ()
 | 
						|
                                        && (modifiers & KeyEvent.SHIFT_DOWN_MASK) == 0)))
 | 
						|
                              {
 | 
						|
                                item.dispatchEvent (new ActionEvent (item,
 | 
						|
                                                                     ActionEvent.ACTION_PERFORMED,
 | 
						|
                                                                     item.getActionCommand (),
 | 
						|
                                                                     modifiers));
 | 
						|
                                // The event was dispatched.
 | 
						|
                                return true;
 | 
						|
                              }
 | 
						|
                          }
 | 
						|
                      }
 | 
						|
                  }
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  public void processKeyEvent (Component comp, KeyEvent e)
 | 
						|
  {
 | 
						|
    AWTKeyStroke eventKeystroke = AWTKeyStroke.getAWTKeyStrokeForEvent (e);
 | 
						|
    // For every focus traversal keystroke, we need to also consume
 | 
						|
    // the other two key event types for the same key (e.g. if
 | 
						|
    // KEY_PRESSED TAB is a focus traversal keystroke, we also need to
 | 
						|
    // consume KEY_RELEASED and KEY_TYPED TAB key events).
 | 
						|
    // consuming KEY_RELEASED is easy, because their keyCodes matches
 | 
						|
    // the KEY_PRESSED event. Consuming the intermediate KEY_TYPED is
 | 
						|
    // very difficult because their is no clean way that we can know
 | 
						|
    // which KEY_TYPED belongs to a focusTraversalKey and which not.
 | 
						|
    // To address this problem we swallow every KEY_TYPE between the
 | 
						|
    // KEY_PRESSED event that matches a focusTraversalKey and the
 | 
						|
    // corresponding KEY_RELEASED.
 | 
						|
    AWTKeyStroke oppositeKeystroke = AWTKeyStroke.getAWTKeyStroke (e.getKeyCode (),
 | 
						|
                                                                   e.getModifiersEx (),
 | 
						|
                                                                   !(e.id == KeyEvent.KEY_RELEASED));
 | 
						|
 | 
						|
    // Here we check if we are currently waiting for a KEY_RELEASED and
 | 
						|
    // swallow all KeyEvents that are to be delivered in between. This
 | 
						|
    // should only be the KEY_TYPED events that correspond to the
 | 
						|
    // focusTraversalKey's KEY_PRESSED event
 | 
						|
    if (waitForKeyStroke != null)
 | 
						|
      {
 | 
						|
        if (eventKeystroke.equals(waitForKeyStroke))
 | 
						|
          // release this lock
 | 
						|
          waitForKeyStroke = null;
 | 
						|
 | 
						|
        // as long as we are waiting for the KEY_RELEASED, we swallow every
 | 
						|
        // KeyEvent, including the KEY_RELEASED
 | 
						|
        e.consume();
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
    Set forwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
 | 
						|
    Set backwardKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
 | 
						|
    Set upKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
 | 
						|
    Set downKeystrokes = null;
 | 
						|
    if (comp instanceof Container)
 | 
						|
      downKeystrokes = comp.getFocusTraversalKeys (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
 | 
						|
 | 
						|
    if (forwardKeystrokes.contains (eventKeystroke))
 | 
						|
      {
 | 
						|
        waitForKeyStroke = oppositeKeystroke;
 | 
						|
        focusNextComponent (comp);
 | 
						|
        e.consume ();
 | 
						|
      }
 | 
						|
    else if (backwardKeystrokes.contains (eventKeystroke))
 | 
						|
      {
 | 
						|
        waitForKeyStroke = oppositeKeystroke;
 | 
						|
        focusPreviousComponent (comp);
 | 
						|
        e.consume ();
 | 
						|
      }
 | 
						|
    else if (upKeystrokes.contains (eventKeystroke))
 | 
						|
      {
 | 
						|
        waitForKeyStroke = oppositeKeystroke;
 | 
						|
        upFocusCycle (comp);
 | 
						|
        e.consume ();
 | 
						|
      }
 | 
						|
    else if (comp instanceof Container
 | 
						|
             && downKeystrokes.contains (eventKeystroke))
 | 
						|
      {
 | 
						|
        waitForKeyStroke = oppositeKeystroke;
 | 
						|
        downFocusCycle ((Container) comp);
 | 
						|
        e.consume ();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  protected void enqueueKeyEvents (long after, Component untilFocused)
 | 
						|
  {
 | 
						|
    delayRequests.add (new EventDelayRequest (after, untilFocused));
 | 
						|
  }
 | 
						|
 | 
						|
  protected void dequeueKeyEvents (long after, Component untilFocused)
 | 
						|
  {
 | 
						|
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
 | 
						|
 | 
						|
    // Remove the KeyEvent with the oldest timestamp, which should be
 | 
						|
    // the first element in the SortedSet.
 | 
						|
    if (after < 0)
 | 
						|
      {
 | 
						|
        int size = delayRequests.size ();
 | 
						|
        if (size > 0)
 | 
						|
          delayRequests.remove (delayRequests.first ());
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        EventDelayRequest template = new EventDelayRequest (after, untilFocused);
 | 
						|
        if (delayRequests.contains (template))
 | 
						|
          {
 | 
						|
            EventDelayRequest actual = (EventDelayRequest) delayRequests.tailSet (template).first ();
 | 
						|
            delayRequests.remove (actual);
 | 
						|
            actual.dispatchEvents ();
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  protected void discardKeyEvents (Component comp)
 | 
						|
  {
 | 
						|
    // FIXME: need synchronization on delayRequests and enqueuedKeyEvents.
 | 
						|
 | 
						|
    Iterator i = delayRequests.iterator ();
 | 
						|
 | 
						|
    while (i.hasNext ())
 | 
						|
      {
 | 
						|
        EventDelayRequest request = (EventDelayRequest) i.next ();
 | 
						|
 | 
						|
        if (request.focusedComp == comp
 | 
						|
            || (comp instanceof Container
 | 
						|
                && ((Container) comp).isAncestorOf (request.focusedComp)))
 | 
						|
          request.discardEvents ();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void focusPreviousComponent (Component comp)
 | 
						|
  {
 | 
						|
    if (comp != null)
 | 
						|
      comp.transferFocusBackward();
 | 
						|
  }
 | 
						|
 | 
						|
  public void focusNextComponent (Component comp)
 | 
						|
  {
 | 
						|
    if (comp != null)
 | 
						|
      comp.transferFocus();
 | 
						|
  }
 | 
						|
 | 
						|
  public void upFocusCycle (Component comp)
 | 
						|
  {
 | 
						|
    if (comp != null)
 | 
						|
      comp.transferFocusUpCycle();
 | 
						|
  }
 | 
						|
 | 
						|
  public void downFocusCycle (Container cont)
 | 
						|
  {
 | 
						|
    if (cont != null)
 | 
						|
      cont.transferFocusDownCycle();
 | 
						|
  }
 | 
						|
} // class DefaultKeyboardFocusManager
 |