/* Window.java --
   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005  Free Software Foundation

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.ComponentEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;
import java.awt.image.BufferStrategy;
import java.awt.peer.WindowPeer;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.EventListener;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Vector;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;

/**
 * This class represents a top-level window with no decorations.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Warren Levy  (warrenl@cygnus.com)
 */
public class Window extends Container implements Accessible
{
  private static final long serialVersionUID = 4497834738069338734L;

  // Serialized fields, from Sun's serialization spec.
  private String warningString = null;
  private int windowSerializedDataVersion = 0; // FIXME
  /** @since 1.2 */
  // private FocusManager focusMgr;  // FIXME: what is this?  
  /** @since 1.2 */
  private int state = 0;
  /** @since 1.4 */
  private boolean focusableWindowState = true;
  /** @since 1.5 */
  private boolean alwaysOnTop = false;

  // A list of other top-level windows owned by this window.
  private transient Vector ownedWindows = new Vector();

  private transient WindowListener windowListener;
  private transient WindowFocusListener windowFocusListener;
  private transient WindowStateListener windowStateListener;

  private transient boolean shown;

  // This is package-private to avoid an accessor method.
  transient Component windowFocusOwner;
  
  /*
   * The number used to generate the name returned by getName.
   */
  private static transient long next_window_number;

  protected class AccessibleAWTWindow extends AccessibleAWTContainer
  {
    private static final long serialVersionUID = 4215068635060671780L;

    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.WINDOW;
    }
    
    public AccessibleStateSet getAccessibleStateSet()
    {
      AccessibleStateSet states = super.getAccessibleStateSet();
      if (isActive())
        states.add(AccessibleState.ACTIVE);
      return states;
    }
  }

  /** 
   * This (package access) constructor is used by subclasses that want
   * to build windows that do not have parents.  Eg. toplevel
   * application frames.  Subclasses cannot call super(null), since
   * null is an illegal argument.
   */
  Window()
  {
    visible = false;
    // Windows are the only Containers that default to being focus
    // cycle roots.
    focusCycleRoot = true;
    setLayout(new BorderLayout());
    
    GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
    graphicsConfig = g.getDefaultScreenDevice().getDefaultConfiguration();
  }

  Window(GraphicsConfiguration gc)
  {
    this();
    graphicsConfig = gc;
  }

  /**
   * Initializes a new instance of <code>Window</code> with the specified
   * parent.  The window will initially be invisible.
   *
   * @param owner The owning <code>Frame</code> of this window.
   *
   * @exception IllegalArgumentException If the owner's GraphicsConfiguration
   * is not from a screen device, or if owner is null; this exception is always
   * thrown when GraphicsEnvironment.isHeadless returns true.
   */
  public Window(Frame owner)
  {
    this (owner, owner.getGraphicsConfiguration ());
  }

  /**
   * Initializes a new instance of <code>Window</code> with the specified
   * parent.  The window will initially be invisible.   
   *
   * @exception IllegalArgumentException If the owner's GraphicsConfiguration
   * is not from a screen device, or if owner is null; this exception is always
   * thrown when GraphicsEnvironment.isHeadless returns true.
   *
   * @since 1.2
   */
  public Window(Window owner)
  {
    this (owner, owner.getGraphicsConfiguration ());
  }
  
  /**
   * Initializes a new instance of <code>Window</code> with the specified
   * parent.  The window will initially be invisible.   
   *
   * @exception IllegalArgumentException If owner is null or if gc is not from a
   * screen device; this exception is always thrown when
   * GraphicsEnvironment.isHeadless returns true.
   *
   * @since 1.3
   */
  public Window(Window owner, GraphicsConfiguration gc)
  {
    this ();

    synchronized (getTreeLock())
      {
	if (owner == null)
	  throw new IllegalArgumentException ("owner must not be null");

	parent = owner;
        owner.ownedWindows.add(new WeakReference(this));
      }

    // FIXME: make this text visible in the window.
    SecurityManager s = System.getSecurityManager();
    if (s != null && ! s.checkTopLevelWindow(this))
      warningString = System.getProperty("awt.appletWarning");

    if (gc != null
        && gc.getDevice().getType() != GraphicsDevice.TYPE_RASTER_SCREEN)
      throw new IllegalArgumentException ("gc must be from a screen device");

    if (gc == null)
      graphicsConfig = GraphicsEnvironment.getLocalGraphicsEnvironment()
                                          .getDefaultScreenDevice()
                                          .getDefaultConfiguration();
    else
      graphicsConfig = gc;
  }

  /**
   * Creates the native peer for this window.
   */
  public void addNotify()
  {
    if (peer == null)
      peer = getToolkit().createWindow(this);
    super.addNotify();
  }

  /**
   * Relays out this window's child components at their preferred size.
   *
   * @specnote pack() doesn't appear to be called internally by show(), so
   *             we duplicate some of the functionality.
   */
  public void pack()
  {
    if (parent != null && !parent.isDisplayable())
      parent.addNotify();
    if (peer == null)
      addNotify();

    setSize(getPreferredSize());

    validate();
  }

  /**
   * Shows on-screen this window and any of its owned windows for whom
   * isVisible returns true.
   * @specnote: Deprecated starting in 1.5.
   */
  @Deprecated
  public void show()
  {
    synchronized (getTreeLock())
      {
        if (peer == null)
          addNotify();

        validate();
        if (visible)
          toFront();
        else
          {
            super.show();
            // Show visible owned windows.
            Iterator e = ownedWindows.iterator();
            while (e.hasNext())
              {
                Window w = (Window) (((Reference) e.next()).get());
                if (w != null)
                  {
                    if (w.isVisible())
                      w.getPeer().setVisible(true);
                  }
                else
                  // Remove null weak reference from ownedWindows.
                  // Unfortunately this can't be done in the Window's
                  // finalize method because there is no way to guarantee
                  // synchronous access to ownedWindows there.
                  e.remove();
              }
          }
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.setGlobalFocusedWindow(this);

        if (! shown)
          {
            FocusTraversalPolicy policy = getFocusTraversalPolicy();
            Component initialFocusOwner = null;

            if (policy != null)
              initialFocusOwner = policy.getInitialComponent(this);

            if (initialFocusOwner != null)
              initialFocusOwner.requestFocusInWindow();

            // Post WINDOW_OPENED from here.
            if (windowListener != null
                || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
              {
                WindowEvent ev = new WindowEvent(this,
                                                 WindowEvent.WINDOW_OPENED);
                Toolkit tk = Toolkit.getDefaultToolkit();
                tk.getSystemEventQueue().postEvent(ev);
              }
            shown = true;
          }
      }
  }

  /**
   * @specnote: Deprecated starting in 1.5.
   */
  @Deprecated
  public void hide()
  {
    // Hide visible owned windows.
    synchronized (getTreeLock ())
      {
	Iterator e = ownedWindows.iterator();
	while(e.hasNext())
	  {
	    Window w = (Window)(((Reference) e.next()).get());
	    if (w != null)
	      {
		if (w.isVisible() && w.getPeer() != null)
		  w.getPeer().setVisible(false);
	      }
     	    else
	      e.remove();
	  }
      }
    super.hide();
  }

  /**
   * Destroys any resources associated with this window.  This includes
   * all components in the window and all owned top-level windows.
   */
  public void dispose()
  {
    hide();

    synchronized (getTreeLock ())
      {
	Iterator e = ownedWindows.iterator();
	while(e.hasNext())
	  {
	    Window w = (Window)(((Reference) e.next()).get());
	    if (w != null)
	      w.dispose();
	    else
	      // Remove null weak reference from ownedWindows.
	      e.remove();
	  }

	for (int i = 0; i < ncomponents; ++i)
	  component[i].removeNotify();
	this.removeNotify();

	// Post WINDOW_CLOSED from here.
	if (windowListener != null
	    || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
	  {
	    WindowEvent ev = new WindowEvent(this,
	                                     WindowEvent.WINDOW_CLOSED);
	    Toolkit tk = Toolkit.getDefaultToolkit();
	    tk.getSystemEventQueue().postEvent(ev);
	  }
      }
  }

  /**
   * Sends this window to the back so that all other windows display in
   * front of it.
   *
   * If the window is set to be always-on-top, this will remove its
   * always-on-top status.
   */
  public void toBack()
  {
    if (peer != null)
      {
	if( alwaysOnTop )
	  setAlwaysOnTop( false );
	( (WindowPeer) peer ).toBack();
      }
  }

  /**
   * Brings this window to the front so that it displays in front of
   * any other windows.
   */
  public void toFront()
  {
    if (peer != null)
      ( (WindowPeer) peer ).toFront();
  }

  /**
   * Returns the toolkit used to create this window.
   *
   * @return The toolkit used to create this window.
   *
   * @specnote Unlike Component.getToolkit, this implementation always 
   *           returns the value of Toolkit.getDefaultToolkit().
   */
  public Toolkit getToolkit()
  {
    return Toolkit.getDefaultToolkit();    
  }

  /**
   * Returns the warning string that will be displayed if this window is
   * popped up by an unsecure applet or application.
   *
   * @return The unsecure window warning message.
   */
  public final String getWarningString()
  {
    return warningString;
  }

  /**
   * Returns the locale that this window is configured for.
   *
   * @return The locale this window is configured for.
   */
  public Locale getLocale()
  {
    return locale == null ? Locale.getDefault() : locale;
  }

  /*
  /** @since 1.2
  public InputContext getInputContext()
  {
    // FIXME
  }
  */

  /**
   * Sets the cursor for this window to the specifiec cursor.
   *
   * @param cursor The new cursor for this window.
   */
  public void setCursor(Cursor cursor)
  {
    super.setCursor(cursor);
  }

  public Window getOwner()
  {
    return (Window) parent;
  }

  /** @since 1.2 */
  public Window[] getOwnedWindows()
  {
    Window [] trimmedList;
    synchronized (getTreeLock ())
      {
	// Windows with non-null weak references in ownedWindows.
	Window [] validList = new Window [ownedWindows.size()];

	Iterator e = ownedWindows.iterator();
	int numValid = 0;
	while (e.hasNext())
	  {
	    Window w = (Window)(((Reference) e.next()).get());
	    if (w != null)
	      validList[numValid++] = w;
	    else
	      // Remove null weak reference from ownedWindows.
	      e.remove();
	  }

	if (numValid != validList.length)
	  {
	    trimmedList = new Window [numValid];
	    System.arraycopy (validList, 0, trimmedList, 0, numValid);
	  }
	else
	  trimmedList = validList;
      }
    return trimmedList;
  }

  /**
   * Adds the specified listener to the list of <code>WindowListeners</code>
   * that will receive events for this window.
   *
   * @param listener The <code>WindowListener</code> to add.
   */
  public synchronized void addWindowListener(WindowListener listener)
  {
    if (listener != null)
      {
        newEventsOnly = true;
        windowListener = AWTEventMulticaster.add(windowListener, listener);
      }
  }

  /**
   * Removes the specified listener from the list of
   * <code>WindowListeners</code> that will receive events for this window.
   *
   * @param listener The <code>WindowListener</code> to remove.
   */
  public synchronized void removeWindowListener(WindowListener listener)
  {
    windowListener = AWTEventMulticaster.remove(windowListener, listener);
  }

  /**
   * Returns an array of all the window listeners registered on this window.
   *
   * @since 1.4
   */
  public synchronized WindowListener[] getWindowListeners()
  {
    return (WindowListener[])
      AWTEventMulticaster.getListeners(windowListener,
                                       WindowListener.class);
  }

  /**
   * Returns an array of all the window focus listeners registered on this
   * window.
   *
   * @since 1.4
   */
  public synchronized WindowFocusListener[] getWindowFocusListeners()
  {
    return (WindowFocusListener[])
      AWTEventMulticaster.getListeners(windowFocusListener,
                                       WindowFocusListener.class);
  }
  
  /**
   * Returns an array of all the window state listeners registered on this
   * window.
   *
   * @since 1.4
   */
  public synchronized WindowStateListener[] getWindowStateListeners()
  {
    return (WindowStateListener[])
      AWTEventMulticaster.getListeners(windowStateListener,
                                       WindowStateListener.class);
  }

  /**
   * Adds the specified listener to this window.
   */
  public void addWindowFocusListener (WindowFocusListener wfl)
  {
    if (wfl != null)
      {
        newEventsOnly = true;
        windowFocusListener = AWTEventMulticaster.add (windowFocusListener,
                                                       wfl);
      }
  }
  
  /**
   * Adds the specified listener to this window.
   *
   * @since 1.4
   */
  public void addWindowStateListener (WindowStateListener wsl)
  {
    if (wsl != null)
      {
        newEventsOnly = true;
        windowStateListener = AWTEventMulticaster.add (windowStateListener,
                                                       wsl);  
      }
  }
  
  /**
   * Removes the specified listener from this window.
   */
  public void removeWindowFocusListener (WindowFocusListener wfl)
  {
    windowFocusListener = AWTEventMulticaster.remove (windowFocusListener, wfl);
  }
  
  /**
   * Removes the specified listener from this window.
   *
   * @since 1.4
   */
  public void removeWindowStateListener (WindowStateListener wsl)
  {
    windowStateListener = AWTEventMulticaster.remove (windowStateListener, wsl);
  }

  /**
   * Returns an array of all the objects currently registered as FooListeners
   * upon this Window. FooListeners are registered using the addFooListener
   * method.
   *
   * @exception ClassCastException If listenerType doesn't specify a class or
   * interface that implements java.util.EventListener.
   *
   * @since 1.3
   */
  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
  {
    if (listenerType == WindowListener.class)
      return (T[]) getWindowListeners();
    return super.getListeners(listenerType);
  }

  void dispatchEventImpl(AWTEvent e)
  {
    if (e.getID() == ComponentEvent.COMPONENT_RESIZED)
      {
        invalidate();
        validate();
      }
    super.dispatchEventImpl(e);
  }

  /**
   * Processes the specified event for this window.  If the event is an
   * instance of <code>WindowEvent</code>, then
   * <code>processWindowEvent()</code> is called to process the event,
   * otherwise the superclass version of this method is invoked.
   *
   * @param evt The event to process.
   */
  protected void processEvent(AWTEvent evt)
  {
    if (evt instanceof WindowEvent)
      {
        WindowEvent we = (WindowEvent) evt;
        switch (evt.getID())
          {
          case WindowEvent.WINDOW_OPENED:
          case WindowEvent.WINDOW_CLOSED:
          case WindowEvent.WINDOW_CLOSING:
          case WindowEvent.WINDOW_ICONIFIED:
          case WindowEvent.WINDOW_DEICONIFIED:
          case WindowEvent.WINDOW_ACTIVATED:
          case WindowEvent.WINDOW_DEACTIVATED:
            processWindowEvent(we);
            break;
          case WindowEvent.WINDOW_GAINED_FOCUS:
          case WindowEvent.WINDOW_LOST_FOCUS:
            processWindowFocusEvent(we);
            break;
          case WindowEvent.WINDOW_STATE_CHANGED:
            processWindowStateEvent(we);
            break;
          }
      }
    else
      super.processEvent(evt);
  }

  /**
   * Dispatches this event to any listeners that are listening for
   * <code>WindowEvents</code> on this window.  This method only gets
   * invoked if it is enabled via <code>enableEvents()</code> or if
   * a listener has been added.
   *
   * @param evt The event to process.
   */
  protected void processWindowEvent(WindowEvent evt)
  {
    if (windowListener != null)
      {
        switch (evt.getID())
          {
          case WindowEvent.WINDOW_ACTIVATED:
            windowListener.windowActivated(evt);
            break;
          case WindowEvent.WINDOW_CLOSED:
            windowListener.windowClosed(evt);
            break;
          case WindowEvent.WINDOW_CLOSING:
            windowListener.windowClosing(evt);
            break;
          case WindowEvent.WINDOW_DEACTIVATED:
            windowListener.windowDeactivated(evt);
            break;
          case WindowEvent.WINDOW_DEICONIFIED:
            windowListener.windowDeiconified(evt);
            break;
          case WindowEvent.WINDOW_ICONIFIED:
            windowListener.windowIconified(evt);
            break;
          case WindowEvent.WINDOW_OPENED:
            windowListener.windowOpened(evt);
            break;
          }
      }
  }

  /**
   * Identifies if this window is active.  The active window is a Frame or
   * Dialog that has focus or owns the active window.
   *  
   * @return true if active, else false.
   * @since 1.4
   */
  public boolean isActive()
  {
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
    return manager.getActiveWindow() == this;
  }

  /**
   * Identifies if this window is focused.  A window is focused if it is the
   * focus owner or it contains the focus owner.
   * 
   * @return true if focused, else false.
   * @since 1.4
   */
  public boolean isFocused()
  {
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
    return manager.getFocusedWindow() == this;
  }
  
  /**
   * Returns the child window that has focus if this window is active.
   * This method returns <code>null</code> if this window is not active
   * or no children have focus.
   *
   * @return The component that has focus, or <code>null</code> if no
   * component has focus.
   */
  public Component getFocusOwner ()
  {
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();

    Window activeWindow = manager.getActiveWindow ();

    // The currently-focused Component belongs to the active Window.
    if (activeWindow == this)
      return manager.getFocusOwner ();
    else
      return null;
  }

  /**
   * Returns the child component of this window that would receive
   * focus if this window were to become focused.  If the window
   * already has the top-level focus, then this method returns the
   * same component as getFocusOwner.  If no child component has
   * requested focus within the window, then the initial focus owner
   * is returned.  If this is a non-focusable window, this method
   * returns null.
   *
   * @return the child component of this window that most recently had
   * the focus, or <code>null</code>
   * @since 1.4
   */
  public Component getMostRecentFocusOwner ()
  {
    return windowFocusOwner;
  }

  /**
   * Set the focus owner for this window.  This method is used to
   * remember which component was focused when this window lost
   * top-level focus, so that when it regains top-level focus the same
   * child component can be refocused.
   *
   * @param windowFocusOwner the component in this window that owns
   * the focus.
   */
  void setFocusOwner (Component windowFocusOwner)
  {
    this.windowFocusOwner = windowFocusOwner;
  }

  /**
   * Post a Java 1.0 event to the event queue.
   *
   * @param e The event to post.
   *
   * @deprecated
   */
  public boolean postEvent(Event e)
  {
    return handleEvent (e);
  }

  /**
   * Tests whether or not this window is visible on the screen.
   *
   * In contrast to the normal behaviour of Container, which is that
   * a container is showing if its parent is visible and showing, a Window
   * is even showing, if its parent (i.e. an invisible Frame) is not showing.
   *
   * @return <code>true</code> if this window is visible, <code>false</code>
   * otherwise.
   */
  public boolean isShowing()
  {
    return isVisible();
  }

  public void setLocationRelativeTo(Component c)
  {
    int x = 0;
    int y = 0;
    
    if (c == null || !c.isShowing())
      {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        Point center = ge.getCenterPoint();
        x = center.x - (width / 2);
        y = center.y - (height / 2);
      }
    else
      {
        int cWidth = c.getWidth();
        int cHeight = c.getHeight();
        Dimension screenSize = getToolkit().getScreenSize();

        x = c.getLocationOnScreen().x;
        y = c.getLocationOnScreen().y;
        
        // If bottom of component is cut off, window placed
        // on the left or the right side of component
        if ((y + cHeight) > screenSize.height)
          {
            // If the right side of the component is closer to the center
            if ((screenSize.width / 2 - x) <= 0)
              {
                if ((x - width) >= 0)
                  x -= width;
                else
                  x = 0;
              }
            else
              {
                if ((x + cWidth + width) <= screenSize.width)
                  x += cWidth;
                else
                  x = screenSize.width - width;
              }

            y = screenSize.height - height;
          }
        else if (cWidth > width || cHeight > height)
          {
            // If right side of component is cut off
            if ((x + width) > screenSize.width)
              x = screenSize.width - width;
            // If left side of component is cut off
            else if (x < 0)
              x = 0;
            else
              x += (cWidth - width) / 2;
            
            y += (cHeight - height) / 2;
          }
        else
          {
            // If right side of component is cut off
            if ((x + width) > screenSize.width)
              x = screenSize.width - width;
            // If left side of component is cut off
            else if (x < 0 || (x - (width - cWidth) / 2) < 0)
              x = 0;
            else
              x -= (width - cWidth) / 2;

            if ((y - (height - cHeight) / 2) > 0)
              y -= (height - cHeight) / 2;
            else
              y = 0;
          }
      }

    setLocation(x, y);
  }

  /**
   * A BltBufferStrategy for windows.
   */
  private class WindowBltBufferStrategy extends BltBufferStrategy
  {
    /**
     * Creates a block transfer strategy for this window.
     *
     * @param numBuffers the number of buffers in this strategy
     * @param accelerated true if the buffer should be accelerated,
     * false otherwise
     */
    WindowBltBufferStrategy(int numBuffers, boolean accelerated)
    {
      super(numBuffers,
	    new BufferCapabilities(new ImageCapabilities(accelerated),
				   new ImageCapabilities(accelerated),
				   BufferCapabilities.FlipContents.COPIED));
    }
  }

  /**
   * A FlipBufferStrategy for windows.
   */
  private class WindowFlipBufferStrategy extends FlipBufferStrategy
  {
    /**
     * Creates a flip buffer strategy for this window.
     *
     * @param numBuffers the number of buffers in this strategy
     *
     * @throws AWTException if the requested number of buffers is not
     * supported
     */
    WindowFlipBufferStrategy(int numBuffers)
      throws AWTException
    {
      super(numBuffers,
	    new BufferCapabilities(new ImageCapabilities(true),
				   new ImageCapabilities(true),
				   BufferCapabilities.FlipContents.COPIED));
    }
  }

  /**
   * Creates a buffering strategy that manages how this window is
   * repainted.  This method attempts to create the optimum strategy
   * based on the desired number of buffers.  Hardware or software
   * acceleration may be used.
   *
   * createBufferStrategy attempts different levels of optimization,
   * but guarantees that some strategy with the requested number of
   * buffers will be created even if it is not optimal.  First it
   * attempts to create a page flipping strategy, then an accelerated
   * blitting strategy, then an unaccelerated blitting strategy.
   *
   * Calling this method causes any existing buffer strategy to be
   * destroyed.
   *
   * @param numBuffers the number of buffers in this strategy
   *
   * @throws IllegalArgumentException if requested number of buffers
   * is less than one
   * @throws IllegalStateException if this window is not displayable
   *
   * @since 1.4
   */
  public void createBufferStrategy(int numBuffers)
  {
    if (numBuffers < 1)
      throw new IllegalArgumentException("Window.createBufferStrategy: number"
					 + " of buffers is less than one");

    if (!isDisplayable())
      throw new IllegalStateException("Window.createBufferStrategy: window is"
				      + " not displayable");

    BufferStrategy newStrategy = null;

    // try a flipping strategy
    try
      {
	newStrategy = new WindowFlipBufferStrategy(numBuffers);
      }
    catch (AWTException e)
      {
      }

    // fall back to an accelerated blitting strategy
    if (newStrategy == null)
      newStrategy = new WindowBltBufferStrategy(numBuffers, true);

    bufferStrategy = newStrategy;
  }

  /**
   * Creates a buffering strategy that manages how this window is
   * repainted.  This method attempts to create a strategy based on
   * the specified capabilities and throws an exception if the
   * requested strategy is not supported.
   *
   * Calling this method causes any existing buffer strategy to be
   * destroyed.
   *
   * @param numBuffers the number of buffers in this strategy
   * @param caps the requested buffering capabilities
   *
   * @throws AWTException if the requested capabilities are not
   * supported
   * @throws IllegalArgumentException if requested number of buffers
   * is less than one or if caps is null
   *
   * @since 1.4
   */
  public void createBufferStrategy(int numBuffers, BufferCapabilities caps)
    throws AWTException
  {
    if (numBuffers < 1)
      throw new IllegalArgumentException("Window.createBufferStrategy: number"
					 + " of buffers is less than one");

    if (caps == null)
      throw new IllegalArgumentException("Window.createBufferStrategy:"
					 + " capabilities object is null");

    // a flipping strategy was requested
    if (caps.isPageFlipping())
      bufferStrategy = new WindowFlipBufferStrategy(numBuffers);
    else
      bufferStrategy = new WindowBltBufferStrategy(numBuffers, true);
  }

  /**
   * Returns the buffer strategy used by the window.
   *
   * @return the buffer strategy.
   * @since 1.4
   */
  public BufferStrategy getBufferStrategy()
  {
    return bufferStrategy;
  }

  /**
   * @since 1.2
   *
   * @deprecated replaced by Component.applyComponentOrientation.
   */
  public void applyResourceBundle(ResourceBundle rb)
  {
    applyComponentOrientation(ComponentOrientation.getOrientation(rb));
  }

  /**
   * @since 1.2
   *
   * @deprecated
   */
  public void applyResourceBundle(String rbName)
  {
    ResourceBundle rb = ResourceBundle.getBundle(rbName, Locale.getDefault(),
      ClassLoader.getSystemClassLoader());
    if (rb != null)
      applyResourceBundle(rb);    
  }

  /**
   * Gets the AccessibleContext associated with this <code>Window</code>.
   * The context is created, if necessary.
   *
   * @return the associated context
   */
  public AccessibleContext getAccessibleContext()
  {
    /* Create the context if this is the first request */
    if (accessibleContext == null)
      accessibleContext = new AccessibleAWTWindow();
    return accessibleContext;
  }

  /** 
   * Get graphics configuration.  The implementation for Window will
   * not ask any parent containers, since Window is a toplevel
   * window and not actually embedded in the parent component.
   */
  public GraphicsConfiguration getGraphicsConfiguration()
  {
    GraphicsConfiguration conf = graphicsConfig;
    if (conf == null)
      {
        conf = GraphicsEnvironment.getLocalGraphicsEnvironment()
        .getDefaultScreenDevice().getDefaultConfiguration();
        graphicsConfig = conf;
      }
    return conf;
  }

  protected void processWindowFocusEvent(WindowEvent event)
  {
    if (windowFocusListener != null)
      {
        switch (event.getID ())
          {
          case WindowEvent.WINDOW_GAINED_FOCUS:
            windowFocusListener.windowGainedFocus (event);
            break;
            
          case WindowEvent.WINDOW_LOST_FOCUS:
            windowFocusListener.windowLostFocus (event);
            break;
            
          default:
            break;
          }
      }
  }
  
  /**
   * @since 1.4
   */
  protected void processWindowStateEvent(WindowEvent event)
  {
    if (windowStateListener != null
        && event.getID () == WindowEvent.WINDOW_STATE_CHANGED)
      windowStateListener.windowStateChanged (event);
  }

  /**
   * Returns whether this <code>Window</code> can get the focus or not.
   *
   * @since 1.4
   */
  public final boolean isFocusableWindow ()
  {
    if (getFocusableWindowState () == false)
      return false;

    if (this instanceof Dialog
        || this instanceof Frame)
      return true;

    // FIXME: Implement more possible cases for returning true.

    return false;
  }
  
  /**
   * Returns the value of the focusableWindowState property.
   * 
   * @since 1.4
   */
  public boolean getFocusableWindowState ()
  {
    return focusableWindowState;
  }

  /**
   * Sets the value of the focusableWindowState property.
   * 
   * @since 1.4
   */
  public void setFocusableWindowState (boolean focusableWindowState)
  {
    this.focusableWindowState = focusableWindowState;
  }
  
  /**
   * Check whether this Container is a focus cycle root.
   * Returns always <code>true</code> as Windows are the 
   * root of the focus cycle.
   *
   * @return Always <code>true</code>.
   *
   * @since 1.4
   */
  public final boolean isFocusCycleRoot()
  {
    return true;
  }

  /**
   * Set whether or not this Container is the root of a focus
   * traversal cycle. Windows are the root of the focus cycle
   * and therefore this method does nothing.
   * 
   * @param focusCycleRoot ignored.
   *
   * @since 1.4
   */
  public final void setFocusCycleRoot(boolean focusCycleRoot)
  {
    // calls to the method are ignored
  }

  /**
   * Returns the root container that owns the focus cycle where this
   * component resides. Windows have no ancestors and this method
   * returns always <code>null</code>.
   *
   * @return Always <code>null</code>.
   * @since 1.4
   */
  public final Container getFocusCycleRootAncestor()
  {
    return null;
  }

  /**
   * Returns whether the Windows is an always-on-top window,
   * meaning whether the window can be obscured by other windows or not.
   *
   * @return <code>true</code> if the windows is always-on-top,
   * <code>false</code> otherwise.
   * @since 1.5
   */
  public final boolean isAlwaysOnTop()
  {
    return alwaysOnTop;
  }

  /**
   * Sets the always-on-top state of this window (if supported).
   *
   * Setting a window to always-on-top means it will not be obscured
   * by any other windows (with the exception of other always-on-top 
   * windows). Not all platforms may support this.
   *
   * If an window's always-on-top status is changed to false, the window
   * will remain at the front but not be anchored there.
   *
   * Calling toBack() on an always-on-top window will change its
   * always-on-top status to false.
   *
   * @since 1.5
   */
  public final void setAlwaysOnTop(boolean alwaysOnTop)
  {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkPermission( new AWTPermission("setWindowAlwaysOnTop") );

    if( this.alwaysOnTop == alwaysOnTop )
      return;
    
    if( alwaysOnTop )
      toFront();

    firePropertyChange("alwaysOnTop", this.alwaysOnTop, alwaysOnTop );
    this.alwaysOnTop = alwaysOnTop;

    if (peer != null) 
      ( (WindowPeer) peer).updateAlwaysOnTop();
    else
      System.out.println("Null peer?!");
  }

  /**
   * Generate a unique name for this window.
   *
   * @return A unique name for this window.
   */
  String generateName()
  {
    return "win" + getUniqueLong();
  }

  /**
   * Overridden to handle WindowEvents.
   *
   * @return <code>true</code> when the specified event type is enabled,
   *         <code>false</code> otherwise
   */
  boolean eventTypeEnabled(int type)
  {
    boolean enabled = false;
    switch (type)
      {
        case WindowEvent.WINDOW_OPENED:
        case WindowEvent.WINDOW_CLOSED:
        case WindowEvent.WINDOW_CLOSING:
        case WindowEvent.WINDOW_ICONIFIED:
        case WindowEvent.WINDOW_DEICONIFIED:
        case WindowEvent.WINDOW_ACTIVATED:
        case WindowEvent.WINDOW_DEACTIVATED:
          enabled = ((eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
                    || windowListener != null;
          break;
        case WindowEvent.WINDOW_GAINED_FOCUS:
        case WindowEvent.WINDOW_LOST_FOCUS:
          enabled = ((eventMask & AWTEvent.WINDOW_FOCUS_EVENT_MASK) != 0)
                    || windowFocusListener != null;
          break;
        case WindowEvent.WINDOW_STATE_CHANGED:
          enabled = ((eventMask & AWTEvent.WINDOW_STATE_EVENT_MASK) != 0)
                    || windowStateListener != null;
          break;
        default:
          enabled = super.eventTypeEnabled(type);
      }
    return enabled;
  }

  private static synchronized long getUniqueLong()
  {
    return next_window_number++;
  }
}
